summaryrefslogtreecommitdiffstats
path: root/base/server
diff options
context:
space:
mode:
authorEndi S. Dewata <edewata@redhat.com>2013-10-07 11:48:54 -0400
committerEndi S. Dewata <edewata@redhat.com>2013-10-25 17:17:39 -0400
commit2119f1b218e9d68b13496e7042785d9c68753966 (patch)
treeb8c7cf5692723340d8d56e5d8c401acdee059ca5 /base/server
parent7ca5adf1bd5bc4f9a7c5f2035426b9158007bb28 (diff)
downloadpki-2119f1b218e9d68b13496e7042785d9c68753966.tar.gz
pki-2119f1b218e9d68b13496e7042785d9c68753966.tar.xz
pki-2119f1b218e9d68b13496e7042785d9c68753966.zip
Reorganized server packages.
The tomcat, cms, and cmscore packages have been moved from base/common into separate folders in base/server so that they can be built separately.
Diffstat (limited to 'base/server')
-rw-r--r--base/server/CMakeLists.txt4
-rw-r--r--base/server/cms/CMakeLists.txt3
-rw-r--r--base/server/cms/src/CMakeLists.txt168
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/AVAPattern.java557
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/AgentCertAuthentication.java327
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java1109
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/Crypt.java438
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/DNPattern.java216
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/DirBasedAuthentication.java675
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/FlatFileAuth.java686
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/HashAuthData.java118
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/HashAuthentication.java283
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/PortalEnroll.java468
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/RDNPattern.java232
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/SSLclientCertAuthentication.java352
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/SharedSecret.java38
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/TokenAuthentication.java327
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/UdnPwdDirAuthentication.java189
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/UidPwdDirAuthentication.java269
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/UidPwdPinDirAuthentication.java461
-rw-r--r--base/server/cms/src/com/netscape/cms/authorization/AAclAuthz.java858
-rw-r--r--base/server/cms/src/com/netscape/cms/authorization/ACLInterceptor.java159
-rw-r--r--base/server/cms/src/com/netscape/cms/authorization/AuthMethodInterceptor.java168
-rw-r--r--base/server/cms/src/com/netscape/cms/authorization/BasicAclAuthz.java213
-rw-r--r--base/server/cms/src/com/netscape/cms/authorization/DirAclAuthz.java365
-rw-r--r--base/server/cms/src/com/netscape/cms/crl/CMSAuthInfoAccessExtension.java259
-rw-r--r--base/server/cms/src/com/netscape/cms/crl/CMSAuthorityKeyIdentifierExtension.java165
-rw-r--r--base/server/cms/src/com/netscape/cms/crl/CMSCRLNumberExtension.java107
-rw-r--r--base/server/cms/src/com/netscape/cms/crl/CMSCRLReasonExtension.java96
-rw-r--r--base/server/cms/src/com/netscape/cms/crl/CMSCertificateIssuerExtension.java224
-rw-r--r--base/server/cms/src/com/netscape/cms/crl/CMSDeltaCRLIndicatorExtension.java108
-rw-r--r--base/server/cms/src/com/netscape/cms/crl/CMSFreshestCRLExtension.java232
-rw-r--r--base/server/cms/src/com/netscape/cms/crl/CMSHoldInstructionExtension.java153
-rw-r--r--base/server/cms/src/com/netscape/cms/crl/CMSInvalidityDateExtension.java99
-rw-r--r--base/server/cms/src/com/netscape/cms/crl/CMSIssuerAlternativeNameExtension.java284
-rw-r--r--base/server/cms/src/com/netscape/cms/crl/CMSIssuingDistributionPointExtension.java332
-rw-r--r--base/server/cms/src/com/netscape/cms/evaluators/GroupAccessEvaluator.java183
-rw-r--r--base/server/cms/src/com/netscape/cms/evaluators/IPAddressAccessEvaluator.java128
-rw-r--r--base/server/cms/src/com/netscape/cms/evaluators/UserAccessEvaluator.java153
-rw-r--r--base/server/cms/src/com/netscape/cms/evaluators/UserOrigReqAccessEvaluator.java163
-rw-r--r--base/server/cms/src/com/netscape/cms/jobs/AJobBase.java301
-rw-r--r--base/server/cms/src/com/netscape/cms/jobs/PublishCertsJob.java392
-rw-r--r--base/server/cms/src/com/netscape/cms/jobs/RenewalNotificationJob.java705
-rw-r--r--base/server/cms/src/com/netscape/cms/jobs/RequestInQueueJob.java217
-rw-r--r--base/server/cms/src/com/netscape/cms/jobs/UnpublishExpiredJob.java384
-rw-r--r--base/server/cms/src/com/netscape/cms/listeners/CertificateIssuedListener.java449
-rw-r--r--base/server/cms/src/com/netscape/cms/listeners/CertificateRevokedListener.java368
-rw-r--r--base/server/cms/src/com/netscape/cms/listeners/PinRemovalListener.java171
-rw-r--r--base/server/cms/src/com/netscape/cms/listeners/RequestInQListener.java277
-rw-r--r--base/server/cms/src/com/netscape/cms/logging/LogEntry.java134
-rw-r--r--base/server/cms/src/com/netscape/cms/logging/LogFile.java1546
-rw-r--r--base/server/cms/src/com/netscape/cms/logging/RollingLogFile.java650
-rw-r--r--base/server/cms/src/com/netscape/cms/notification/MailNotification.java197
-rw-r--r--base/server/cms/src/com/netscape/cms/ocsp/DefStore.java958
-rw-r--r--base/server/cms/src/com/netscape/cms/ocsp/LDAPStore.java749
-rw-r--r--base/server/cms/src/com/netscape/cms/password/PasswordChecker.java103
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/APolicyRule.java363
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/AgentPolicy.java161
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/AttributePresentConstraints.java399
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/DSAKeyConstraints.java252
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/DefaultRevocation.java104
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/IssuerConstraints.java215
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/KeyAlgorithmConstraints.java225
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/ManualAuthentication.java101
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/RSAKeyConstraints.java280
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/RenewalConstraints.java242
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/RenewalValidityConstraints.java351
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/RevocationConstraints.java215
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/SigningAlgorithmConstraints.java449
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/SubCANameConstraints.java195
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/UniqueSubjectName.java33
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/UniqueSubjectNameConstraints.java313
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/constraints/ValidityConstraints.java317
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/AuthInfoAccessExt.java394
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/AuthorityKeyIdentifierExt.java425
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/BasicConstraintsExt.java508
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/CRLDistributionPointsExt.java484
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/CertificatePoliciesExt.java534
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/CertificateRenewalWindowExt.java254
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/CertificateScopeOfUseExt.java326
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/ExtendedKeyUsageExt.java285
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/GenericASN1Ext.java509
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/IssuerAltNameExt.java249
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/KeyUsageExt.java362
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/NSCCommentExt.java293
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/NSCertTypeExt.java535
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/NameConstraintsExt.java475
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/OCSPNoCheckExt.java190
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/PolicyConstraintsExt.java287
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/PolicyMappingsExt.java426
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/PresenceExt.java158
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/PrivateKeyUsagePeriodExt.java252
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/RemoveBasicConstraintsExt.java143
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/SubjAltNameExt.java356
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/SubjectAltNameExt.java331
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/SubjectDirectoryAttributesExt.java428
-rw-r--r--base/server/cms/src/com/netscape/cms/policy/extensions/SubjectKeyIdentifierExt.java377
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/common/BasicProfile.java1213
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/common/CACertCAEnrollProfile.java107
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java243
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java1506
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/common/EnrollProfileContext.java31
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/common/ProfileContext.java39
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/common/ProfilePolicy.java53
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/common/RAEnrollProfile.java128
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/common/ServerCertCAEnrollProfile.java100
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/common/UserCertCAEnrollProfile.java100
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/BasicConstraintsExtConstraint.java224
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/CAEnrollConstraint.java48
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/CAValidityConstraint.java139
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/EnrollConstraint.java214
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/ExtendedKeyUsageExtConstraint.java156
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/ExtensionConstraint.java146
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/KeyConstraint.java328
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/KeyUsageExtConstraint.java291
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/NSCertTypeExtConstraint.java243
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/NoConstraint.java101
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/RenewGracePeriodConstraint.java165
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/SigningAlgConstraint.java160
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/SubjectNameConstraint.java244
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/UniqueKeyConstraint.java294
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/UniqueSubjectNameConstraint.java251
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/UserSubjectNameConstraint.java93
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/constraint/ValidityConstraint.java218
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/AuthInfoAccessExtDefault.java454
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/AuthTokenSubjectNameDefault.java152
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java190
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/AutoAssignDefault.java96
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/BasicConstraintsExtDefault.java297
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/CAEnrollDefault.java106
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/CAValidityDefault.java348
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/CRLDistributionPointsExtDefault.java696
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/CertificatePoliciesExtDefault.java793
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/CertificateVersionDefault.java193
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/EnrollDefault.java774
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/EnrollExtDefault.java28
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/ExtendedKeyUsageExtDefault.java250
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/FreshestCRLExtDefault.java584
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/GenericExtDefault.java253
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/ImageDefault.java105
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/InhibitAnyPolicyExtDefault.java270
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/IssuerAltNameExtDefault.java317
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/KeyUsageExtDefault.java511
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/NSCCommentExtDefault.java246
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/NSCertTypeExtDefault.java420
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/NameConstraintsExtDefault.java670
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/NoDefault.java111
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/OCSPNoCheckExtDefault.java185
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/PolicyConstraintsExtDefault.java287
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/PolicyMappingsExtDefault.java419
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/PrivateKeyUsagePeriodExtDefault.java316
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/RandomizedValidityDefault.java354
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/SigningAlgDefault.java182
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/SubjectAltNameExtDefault.java544
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/SubjectDirAttributesExtDefault.java527
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/SubjectInfoAccessExtDefault.java448
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/SubjectKeyIdentifierExtDefault.java217
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/SubjectNameDefault.java184
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/UserExtensionDefault.java136
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/UserKeyDefault.java241
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/UserSigningAlgDefault.java126
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/UserSubjectNameDefault.java143
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/UserValidityDefault.java149
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/ValidityDefault.java263
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/nsHKeySubjectNameDefault.java215
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/nsNKeySubjectNameDefault.java423
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/nsTokenDeviceKeySubjectNameDefault.java215
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/nsTokenUserKeySubjectNameDefault.java457
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/CMCCertReqInput.java128
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/CertReqInput.java190
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/DualKeyGenInput.java168
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/EncryptionKeyGenInput.java189
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/EnrollInput.java303
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/FileSigningInput.java143
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/GenericInput.java160
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/ImageInput.java89
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/KeyGenInput.java189
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/SerialNumRenewInput.java89
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/SigningKeyGenInput.java189
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/SubjectDNInput.java142
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/SubjectNameInput.java382
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/SubmitterInfoInput.java102
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/nsHKeyCertReqInput.java160
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/input/nsNKeyCertReqInput.java129
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/output/CMMFOutput.java161
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/output/CertOutput.java120
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/output/EnrollOutput.java134
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/output/PKCS7Output.java158
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/output/nsNKeyOutput.java110
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/updater/SubsystemGroupUpdater.java314
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/mappers/AVAPattern.java587
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/mappers/LdapCaSimpleMap.java368
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/mappers/LdapCertCompsMap.java176
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/mappers/LdapCertExactMap.java195
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/mappers/LdapCertSubjMap.java339
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/mappers/LdapCrlIssuerCompsMap.java155
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/mappers/LdapDNCompsMap.java457
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/mappers/LdapEnhancedMap.java635
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/mappers/LdapSimpleMap.java328
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/mappers/MapAVAPattern.java650
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/mappers/MapDNPattern.java201
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/mappers/MapRDNPattern.java217
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/mappers/NoMap.java104
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/publishers/FileBasedPublisher.java476
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/publishers/LdapCaCertPublisher.java420
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/publishers/LdapCertSubjPublisher.java345
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/publishers/LdapCertificatePairPublisher.java318
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/publishers/LdapCrlPublisher.java379
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/publishers/LdapEncryptCertPublisher.java357
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/publishers/LdapUserCertPublisher.java333
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/publishers/OCSPPublisher.java356
-rw-r--r--base/server/cms/src/com/netscape/cms/publish/publishers/PublisherUtils.java136
-rw-r--r--base/server/cms/src/com/netscape/cms/realm/PKIPrincipal.java29
-rw-r--r--base/server/cms/src/com/netscape/cms/realm/PKIRealm.java160
-rw-r--r--base/server/cms/src/com/netscape/cms/request/RequestScheduler.java71
-rw-r--r--base/server/cms/src/com/netscape/cms/selftests/ASelfTest.java193
-rw-r--r--base/server/cms/src/com/netscape/cms/selftests/ca/CAPresence.java262
-rw-r--r--base/server/cms/src/com/netscape/cms/selftests/ca/CAValidity.java262
-rw-r--r--base/server/cms/src/com/netscape/cms/selftests/common/SystemCertsVerification.java213
-rw-r--r--base/server/cms/src/com/netscape/cms/selftests/kra/KRAPresence.java251
-rw-r--r--base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPPresence.java280
-rw-r--r--base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPValidity.java280
-rw-r--r--base/server/cms/src/com/netscape/cms/selftests/ra/RAPresence.java261
-rw-r--r--base/server/cms/src/com/netscape/cms/selftests/tks/TKSKnownSessionKey.java334
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/account/AccountService.java67
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/ACLAdminServlet.java894
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/AdminResources.java42
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java1142
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/AuthAdminServlet.java1716
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/AuthCredentials.java109
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/CAAdminServlet.java1576
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java3424
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/GroupMemberProcessor.java394
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/GroupService.java423
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/JobsAdminServlet.java1006
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/KRAAdminServlet.java233
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/KRAConnectorProcessor.java223
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/KRAConnectorService.java78
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/LogAdminServlet.java2352
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/OCSPAdminServlet.java541
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/PolicyAdminServlet.java1257
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/ProfileAdminServlet.java2666
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/PublisherAdminServlet.java3110
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/RAAdminServlet.java575
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/RegistryAdminServlet.java365
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/SystemCertService.java98
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/UserService.java1101
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/admin/UsrGrpAdminServlet.java2313
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java2264
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/base/CMSStartServlet.java127
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/base/DisplayHtmlServlet.java96
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/base/DynamicVariablesServlet.java332
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/base/GetStats.java185
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/base/IndexServlet.java111
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java153
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/base/PortsServlet.java90
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/base/ProxyServlet.java247
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/base/RESTServlet.java47
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/base/SystemInfoServlet.java287
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/base/UserInfo.java90
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java1074
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/CertEnrollmentRequestFactory.java52
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java350
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/CertRequestDAO.java206
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/CertRequestInfoFactory.java86
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/CertReviewResponseFactory.java177
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/CertService.java618
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/ChallengeRevocationServlet1.java716
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/CloneRedirect.java143
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/DirAuthServlet.java242
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/DisableEnrollResult.java174
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/DisplayBySerial.java488
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/DisplayCRL.java491
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/DisplayHashUserEnroll.java228
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/DoRevoke.java812
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/DoRevokeTPS.java930
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/DoUnrevoke.java499
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/DoUnrevokeTPS.java613
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/EnableEnrollResult.java185
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java1767
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java204
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/FilterBuilder.java332
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/GetBySerial.java295
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/GetCAChain.java406
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/GetCRL.java479
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/GetCertFromRequest.java351
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/GetEnableStatus.java174
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/GetInfo.java374
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/HashEnrollServlet.java1234
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/ImportCertsTemplateFiller.java380
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/ListCerts.java673
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/Monitor.java405
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java298
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/RemoteAuthConfig.java624
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/RenewalProcessor.java344
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/RenewalServlet.java523
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java464
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/RevocationProcessor.java525
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/RevocationServlet.java394
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/RevocationSuccessTemplateFiller.java96
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/SrchCerts.java761
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/UpdateCRL.java529
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/UpdateDir.java747
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/scep/CRSEnrollment.java2133
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/scep/ChallengePassword.java141
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/scep/ExtensionsRequested.java176
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/AuthCredentials.java109
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java1106
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/CMSFile.java102
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/CMSFileLoader.java161
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/CMSGWResources.java44
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/CMSGateway.java370
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/CMSLoadTemplate.java60
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/CMSRequest.java293
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/CMSTemplate.java593
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/CMSTemplateParams.java70
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/ECMSGWException.java74
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/GenErrorTemplateFiller.java102
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java286
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/GenRejectedTemplateFiller.java92
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/GenSuccessTemplateFiller.java63
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/GenSvcPendingTemplateFiller.java79
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/GenUnauthorizedTemplateFiller.java67
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/GenUnexpectedErrorTemplateFiller.java77
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/ICMSTemplateFiller.java49
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/IRawJS.java26
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/IndexTemplateFiller.java111
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/RawJS.java35
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/ServletUtils.java148
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/connector/CloneServlet.java580
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java1115
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java336
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java327
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/AdminPanel.java332
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/AuthDBPanel.java125
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/AuthenticatePanel.java192
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/BackupKeyCertPanel.java215
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/BaseServlet.java121
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/CAInfoPanel.java166
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/Cert.java188
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/CertRequestPanel.java375
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java670
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/CheckIdentity.java116
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java33
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigHSMLoginPanel.java296
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java4085
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/CreateSubsystemPanel.java279
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/DRMInfoPanel.java150
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java532
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/DisplayCertChainPanel.java226
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/DonePanel.java311
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/DownloadPKCS12.java136
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/GetCertChain.java157
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java229
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/GetCookie.java239
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/GetDomainXML.java130
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/GetStatus.java111
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/GetSubsystemCert.java128
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/GetTokenInfo.java150
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/GetTransportCert.java181
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/HierarchyPanel.java194
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/ImportAdminCertPanel.java341
-rwxr-xr-xbase/server/cms/src/com/netscape/cms/servlet/csadmin/ImportCAChainPanel.java145
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/ImportTransportCert.java180
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/LoginServlet.java72
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/MainPageServlet.java157
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/ModulePanel.java338
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/NamePanel.java622
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/RegisterUser.java332
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java235
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/SavePKCS12Panel.java144
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainLogin.java88
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainPanel.java469
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainProcessor.java398
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainService.java74
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/SizePanel.java491
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/SystemCertDataFactory.java48
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/SystemConfigService.java1277
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/TKSInfoPanel.java145
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/TokenAuthenticate.java145
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java191
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java570
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java290
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateOCSPConfig.java180
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/WelcomePanel.java128
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java306
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/filter/AdminRequestFilter.java134
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/filter/AgentRequestFilter.java134
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/filter/EEClientAuthRequestFilter.java133
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/filter/EERequestFilter.java186
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/ConfirmRecoverBySerial.java188
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerial.java195
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerialForRecovery.java214
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/DisplayTransport.java126
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/ExamineRecovery.java240
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/GetApprovalStatus.java236
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/GetAsyncPk12.java265
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/GetPk12.java259
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/GrantAsyncRecovery.java274
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/GrantRecovery.java303
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/KeyRecordParser.java102
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java263
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/KeyService.java372
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/RecoverBySerial.java534
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/SrchKey.java298
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/SrchKeyForRecovery.java318
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/ocsp/AddCAServlet.java311
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/ocsp/AddCRLServlet.java614
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/ocsp/CheckCertServlet.java217
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/ocsp/GetOCSPInfo.java165
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/ocsp/ListCAServlet.java199
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java277
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/ocsp/RemoveCAServlet.java215
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/processors/CMCProcessor.java407
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/processors/CRMFProcessor.java373
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/processors/IPKIProcessor.java33
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/processors/KeyGenProcessor.java120
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/processors/PKCS10Processor.java285
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/processors/PKIProcessor.java355
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/processors/Processor.java1312
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/PolicyConstraintFactory.java47
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/PolicyDefaultFactory.java97
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/ProfileApproveServlet.java532
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/ProfileInputFactory.java44
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/ProfileListServlet.java171
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/ProfileOutputFactory.java49
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java181
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java450
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java410
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/ProfileService.java952
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/ProfileServlet.java578
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java890
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java347
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/SSLClientCertProvider.java39
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/request/CMSRequestDAO.java163
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/request/CertReqParser.java918
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/request/CertRequestService.java368
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/request/CheckRequest.java618
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/request/IReqParser.java42
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/request/KeyReqParser.java81
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/request/KeyRequestService.java297
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java1927
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/request/ProcessReq.java330
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/request/QueryReq.java540
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/request/ReqParser.java79
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/request/SearchReqs.java328
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/tks/TPSConnectorService.java421
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java1353
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/wizard/IWizardPanel.java111
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/wizard/WizardServlet.java489
-rw-r--r--base/server/cms/src/com/netscape/cms/shares/OldJoinShares.java86
-rw-r--r--base/server/cms/src/com/netscape/cms/shares/OldShare.java62
-rw-r--r--base/server/cms/src/pki-cms.mf3
-rw-r--r--base/server/cmscore/CMakeLists.txt3
-rw-r--r--base/server/cmscore/src/CMakeLists.txt166
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java2025
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/apps/CommandQueue.java99
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/apps/PKIServerEvent.java42
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/apps/PKIServerListener.java35
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/apps/Setup.java348
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/apps/Upgrade.java329
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/authentication/AuthSubsystem.java511
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/authentication/CertUserDBAuthentication.java253
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/authentication/ChallengePhraseAuthentication.java406
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/authentication/NullAuthentication.java161
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/authentication/PasswdUserDBAuthentication.java272
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/authentication/SSLClientCertAuthentication.java289
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/authentication/VerifiedCert.java90
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/authentication/VerifiedCerts.java158
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/authorization/AuthzSubsystem.java468
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/base/ArgBlock.java713
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/base/FileConfigStore.java175
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/base/JDialogPasswordCallback.java267
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/base/PropConfigStore.java777
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/base/SimpleProperties.java482
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/base/SourceConfigStore.java59
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/base/SubsystemLoader.java75
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/base/SubsystemRegistry.java43
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/cert/CertDateCompare.java55
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/cert/CertPrettyPrint.java36
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/cert/CertUtils.java1121
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/cert/CertificatePair.java288
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/cert/CrlCachePrettyPrint.java262
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/cert/CrlPrettyPrint.java36
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/cert/CrossCertPairSubsystem.java510
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/cert/ExtPrettyPrint.java36
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/cert/OidLoaderSubsystem.java189
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/cert/PrettyPrintFormat.java164
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/cert/PrettyPrintResources.java293
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/cert/PubKeyPrettyPrint.java35
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/cert/X500NameSubsystem.java285
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnFactory.java299
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java244
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnector.java211
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/connector/HttpPKIMessage.java230
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/connector/HttpRequestEncoder.java76
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/connector/LocalConnector.java213
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/connector/RemoteAuthority.java69
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/connector/RequestTransfer.java115
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/connector/Resender.java260
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/crmf/CRMFParser.java122
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/crmf/PKIArchiveOptionsContainer.java31
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/BigIntegerMapper.java125
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/ByteArrayMapper.java96
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/CRLDBSchema.java47
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/CRLIssuingPointRecord.java334
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/CRLRepository.java370
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/CertDBSchema.java54
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/CertRecord.java283
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/CertRecordList.java113
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/CertRecordMapper.java95
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java2419
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/DBAttribute.java30
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/DBObjectClasses.java30
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/DBRecord.java98
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/DBRegistry.java553
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/DBSSession.java485
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/DBSUtil.java49
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/DBSearchResults.java93
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/DBSubsystem.java986
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/DBVirtualList.java800
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/Database.java77
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/DateArrayMapper.java110
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/DateMapper.java117
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/IntegerMapper.java93
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/KeyDBSchema.java51
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecord.java392
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecordList.java89
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecordMapper.java114
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRepository.java607
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/KeyStateMapper.java86
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/LDAPDatabase.java171
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/LdapFilterConverter.java62
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/LongMapper.java123
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/MetaInfoMapper.java128
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/ObjectStreamMapper.java135
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/PublicKeyMapper.java136
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/ReplicaIDRepository.java83
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java539
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/RepositoryRecord.java121
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/RepositorySchema.java35
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/RevocationInfo.java78
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/RevocationInfoMapper.java175
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/StringMapper.java94
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/StringVectorMapper.java115
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/X500NameMapper.java114
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/X509CertImplMapper.java372
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/extensions/CMSExtensionsMap.java161
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/extensions/KeyUsage.java227
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/jobs/CronItem.java168
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/jobs/CronRange.java84
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/jobs/JobCron.java355
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/jobs/JobsScheduler.java509
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldap/LdapAndExpression.java74
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldap/LdapConnModule.java132
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldap/LdapOrExpression.java80
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldap/LdapPredicateParser.java336
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldap/LdapPublishModule.java782
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldap/LdapRequestListener.java526
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldap/LdapRule.java305
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldap/LdapSimpleExpression.java473
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldap/PublishObject.java84
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldap/PublisherProcessor.java1487
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAnonConnFactory.java475
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAnonConnection.java101
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAuthInfo.java298
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapBoundConnFactory.java536
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapBoundConnection.java204
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapConnInfo.java119
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.java116
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/listeners/ListenerPlugin.java52
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/logging/AuditEventFactory.java99
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/logging/AuditFormat.java116
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/logging/AuditService.java177
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/logging/Auditor.java210
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/logging/LogQueue.java122
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/logging/LogSubsystem.java271
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/logging/Logger.java378
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/logging/SignedAuditEventFactory.java125
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/logging/SignedAuditLogger.java39
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/logging/SystemEventFactory.java99
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/notification/EmailFormProcessor.java249
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/notification/EmailResolverKeys.java93
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/notification/EmailTemplate.java175
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/notification/ReqCertEmailResolver.java155
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/notification/ReqCertSANameEmailResolver.java276
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/policy/AndExpression.java60
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/policy/GeneralNameUtil.java694
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java1532
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java48
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/policy/OrExpression.java67
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/policy/PolicyPredicateParser.java339
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/policy/PolicySet.java299
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/policy/SimpleExpression.java434
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/profile/ProfileSubsystem.java329
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/realm/ACL.java193
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/realm/ACLEntry.java243
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/registry/PluginInfo.java52
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/registry/PluginRegistry.java294
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/request/ARequestQueue.java1581
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/request/ARequestRecord.java42
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/request/CertRequestConstants.java73
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/request/ExtDataHashtable.java64
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/request/RequestAttr.java61
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/request/RequestQueue.java709
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/request/RequestRecord.java905
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/request/RequestRepository.java217
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/request/RequestSubsystem.java186
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/request/Schema.java50
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/security/CASigningCert.java161
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/security/CertificateInfo.java280
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/security/JssSubsystem.java2174
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/security/KRATransportCert.java101
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/security/KeyCertUtil.java1134
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/security/OCSPSigningCert.java139
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/security/PWCBsdr.java257
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/security/PWUtil.java68
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/security/PWsdrCache.java650
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/security/Provider.java57
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/security/RASigningCert.java107
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/security/SSLCert.java119
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/security/SSLSelfSignedCert.java113
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/security/SubsystemCert.java81
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestOrderedInstance.java136
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestService.java148
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestSubsystem.java1884
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/session/LDAPSecurityDomainSessionTable.java303
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/session/SecurityDomainSessionTable.java105
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/session/SessionTimer.java68
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/time/SimpleTimeSource.java29
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/usrgrp/CertDNCertUserLocator.java77
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/usrgrp/ExactMatchCertUserLocator.java83
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/usrgrp/Group.java126
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/usrgrp/UGSubsystem.java1904
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/usrgrp/User.java250
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/util/Assert.java48
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/util/AssertionException.java36
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/util/Debug.java385
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/util/ExceptionFormatter.java91
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/util/FileAsString.java118
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/util/FileDialogFilter.java143
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/util/PFXUtils.java167
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/util/ProfileSubsystem.java308
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/util/StatsSubsystem.java195
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/util/UtilMessage.java181
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/util/UtilResources.java74
-rw-r--r--base/server/cmscore/src/pki-cmscore.mf3
-rw-r--r--base/server/tomcat/CMakeLists.txt3
-rw-r--r--base/server/tomcat/src/CMakeLists.txt158
-rw-r--r--base/server/tomcat/src/com/netscape/cms/tomcat/ProxyRealm.java139
-rw-r--r--base/server/tomcat/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java172
-rw-r--r--base/server/tomcat/src/pki-tomcat.mf3
652 files changed, 221809 insertions, 0 deletions
diff --git a/base/server/CMakeLists.txt b/base/server/CMakeLists.txt
index e8f78c4fc..8f1391a73 100644
--- a/base/server/CMakeLists.txt
+++ b/base/server/CMakeLists.txt
@@ -139,3 +139,7 @@ install(
# install empty directories
install(CODE "file(MAKE_DIRECTORY \$ENV{DESTDIR}${VAR_INSTALL_DIR}/lock/pki)")
install(CODE "file(MAKE_DIRECTORY \$ENV{DESTDIR}${VAR_INSTALL_DIR}/run/pki)")
+
+add_subdirectory(tomcat)
+add_subdirectory(cms)
+add_subdirectory(cmscore)
diff --git a/base/server/cms/CMakeLists.txt b/base/server/cms/CMakeLists.txt
new file mode 100644
index 000000000..735ca31a8
--- /dev/null
+++ b/base/server/cms/CMakeLists.txt
@@ -0,0 +1,3 @@
+project(cms)
+
+add_subdirectory(src)
diff --git a/base/server/cms/src/CMakeLists.txt b/base/server/cms/src/CMakeLists.txt
new file mode 100644
index 000000000..16fa1fe8a
--- /dev/null
+++ b/base/server/cms/src/CMakeLists.txt
@@ -0,0 +1,168 @@
+project(pki-cms)
+
+find_file(JSS_JAR
+ NAMES
+ jss4.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(LDAPJDK_JAR
+ NAMES
+ ldapjdk.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(COMMONS_CODEC_JAR
+ NAMES
+ commons-codec.jar
+ PATHS
+ /usr/share/java
+)
+
+find_file(COMMONS_HTTPCLIENT_JAR
+ NAMES
+ commons-httpclient.jar
+ PATHS
+ /usr/share/java
+)
+
+find_file(APACHE_COMMONS_LANG_JAR
+ NAMES
+ apache-commons-lang.jar
+ PATHS
+ /usr/share/java
+)
+
+find_file(TOMCAT_CATALINA_JAR
+ NAMES
+ catalina.jar
+ PATHS
+ /usr/share/java/tomcat
+)
+
+find_file(TOMCAT_UTIL_JAR
+ NAMES
+ tomcat-util.jar
+ PATHS
+ /usr/share/java/tomcat
+)
+
+find_file(SERVLET_JAR
+ NAMES
+ servlet.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(VELOCITY_JAR
+ NAMES
+ velocity.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(XALAN_JAR
+ NAMES
+ xalan-j2.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(XERCES_JAR
+ NAMES
+ xerces-j2.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+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(HTTPCLIENT_JAR
+ NAMES
+ httpclient.jar
+ PATHS
+ /usr/share/java/httpcomponents
+)
+
+find_file(HTTPCORE_JAR
+ NAMES
+ httpcore.jar
+ PATHS
+ /usr/share/java/httpcomponents
+)
+
+# build pki-cms
+javac(pki-cms-classes
+ SOURCES
+ com/netscape/cms/*.java
+ CLASSPATH
+ ${PKI_NSUTIL_JAR} ${PKI_CMSUTIL_JAR} ${PKI_CERTSRV_JAR} ${PKI_TOMCAT_JAR}
+ ${LDAPJDK_JAR} ${SERVLET_JAR} ${VELOCITY_JAR} ${XALAN_JAR} ${XERCES_JAR}
+ ${JSS_JAR} ${COMMONS_CODEC_JAR} ${COMMONS_HTTPCLIENT_JAR}
+ ${APACHE_COMMONS_LANG_JAR}
+ ${TOMCAT_CATALINA_JAR} ${TOMCAT_UTIL_JAR} ${SYMKEY_JAR}
+ ${JAXRS_API_JAR} ${RESTEASY_JAXRS_JAR} ${RESTEASY_ATOM_PROVIDER_JAR}
+ ${HTTPCLIENT_JAR} ${HTTPCORE_JAR}
+ OUTPUT_DIR
+ ${CMAKE_BINARY_DIR}/classes
+ DEPENDS
+ pki-nsutil-jar pki-cmsutil-jar pki-certsrv-jar pki-tomcat-jar
+)
+
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/pki-cms.mf
+ ${CMAKE_CURRENT_BINARY_DIR}/pki-cms.mf
+)
+
+jar(pki-cms-jar
+ CREATE
+ ${CMAKE_BINARY_DIR}/dist/pki-cms.jar
+ OPTIONS
+ m
+ PARAMS
+ ${CMAKE_CURRENT_BINARY_DIR}/pki-cms.mf
+ INPUT_DIR
+ ${CMAKE_BINARY_DIR}/classes
+ FILES
+ com/netscape/cms/*.class
+ EXCLUDE
+ com/netscape/cms/tomcat/*.class
+ DEPENDS
+ pki-cms-classes
+)
+
+install(
+ FILES
+ ${CMAKE_BINARY_DIR}/dist/pki-cms.jar
+ DESTINATION
+ ${JAVA_JAR_INSTALL_DIR}/pki
+)
+
+set(PKI_CMS_JAR ${CMAKE_BINARY_DIR}/dist/pki-cms.jar CACHE INTERNAL "pki-cms jar file")
diff --git a/base/server/cms/src/com/netscape/cms/authentication/AVAPattern.java b/base/server/cms/src/com/netscape/cms/authentication/AVAPattern.java
new file mode 100644
index 000000000..3e984c0cc
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/AVAPattern.java
@@ -0,0 +1,557 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.StringReader;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPDN;
+import netscape.ldap.LDAPEntry;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AVA;
+import netscape.security.x509.LdapV3DNStrConverter;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.authentication.ECompSyntaxErr;
+
+/**
+ * class for parsing a DN pattern used to construct a certificate
+ * subject name from ldap attributes and dn.
+ * <p>
+ *
+ * dnpattern is a string representing a subject name pattern to formulate from the directory attributes and entry dn. If
+ * empty or not set, the ldap entry DN will be used as the certificate subject name.
+ * <p>
+ *
+ * The syntax is
+ *
+ * <pre>
+ * dnPattern := rdnPattern *[ "," rdnPattern ]
+ * rdnPattern := avaPattern *[ "+" avaPattern ]
+ * avaPattern := name "=" value |
+ * name "=" "$attr" "." attrName [ "." attrNumber ] |
+ * name "=" "$dn" "." attrName [ "." attrNumber ] |
+ * "$dn" "." "$rdn" "." number
+ * </pre>
+ *
+ * <pre>
+ * Example1: <i>E=$attr.mail.1, CN=$attr.cn, OU=$dn.ou.2, O=$dn.o, C=US </i>
+ * Ldap entry: dn: UID=jjames, OU=IS, OU=people, O=acme.org
+ * Ldap attributes: cn: Jesse James
+ * Ldap attributes: mail: jjames@acme.org
+ * <p>
+ * The subject name formulated will be : <br>
+ * E=jjames@acme.org, CN=Jesse James, OU=people, O=acme.org, C=US
+ * <p>
+ * E = the first 'mail' ldap attribute value in user's entry. <br>
+ * CN = the (first) 'cn' ldap attribute value in the user's entry. <br>
+ * OU = the second 'ou' value in the user's entry DN. <br>
+ * O = the (first) 'o' value in the user's entry DN. <br>
+ * C = the string "US"
+ * <p>
+ * Example2: <i>E=$attr.mail.1, CN=$attr.cn, OU=$dn.ou.2, O=$dn.o, C=US</i>
+ * Ldap entry: dn: UID=jjames, OU=IS+OU=people, O=acme.org
+ * Ldap attributes: cn: Jesse James
+ * Ldap attributes: mail: jjames@acme.org
+ * <p>
+ * The subject name formulated will be : <br>
+ * E=jjames@acme.org, CN=Jesse James, OU=people, O=acme.org, C=US
+ * <p>
+ * E = the first 'mail' ldap attribute value in user's entry. <br>
+ * CN = the (first) 'cn' ldap attribute value in the user's entry. <br>
+ * OU = the second 'ou' value in the user's entry DN. note multiple AVAs
+ * in a RDN in this example. <br>
+ * O = the (first) 'o' value in the user's entry DN. <br>
+ * C = the string "US"
+ * <p>
+ * </pre>
+ *
+ * <pre>
+ * Example3: <i>CN=$attr.cn, $rdn.2, O=$dn.o, C=US</i>
+ * Ldap entry: dn: UID=jjames, OU=IS+OU=people, O=acme.org
+ * Ldap attributes: cn: Jesse James
+ * Ldap attributes: mail: jjames@acme.org
+ * <p>
+ * The subject name formulated will be : <br>
+ * CN=Jesse James, OU=IS+OU=people, O=acme.org, C=US
+ * <p>
+ * CN = the (first) 'cn' ldap attribute value in the user's entry. <br>
+ * followed by the second RDN in the user's entry DN. <br>
+ * O = the (first) 'o' value in the user's entry DN. <br>
+ * C = the string "US"
+ * <p>
+ * Example4: <i>CN=$attr.cn, OU=$dn.ou.2+OU=$dn.ou.1, O=$dn.o, C=US</i>
+ * Ldap entry: dn: UID=jjames, OU=IS+OU=people, O=acme.org
+ * Ldap attributes: cn: Jesse James
+ * Ldap attributes: mail: jjames@acme.org
+ * <p>
+ * The subject name formulated will be : <br>
+ * CN=Jesse James, OU=people+OU=IS, O=acme.org, C=US
+ * <p>
+ * CN = the (first) 'cn' ldap attribute value in the user's entry. <br>
+ * OU = the second 'ou' value in the user's entry DN followed by the
+ * first 'ou' value in the user's entry. note multiple AVAs
+ * in a RDN in this example. <br>
+ * O = the (first) 'o' value in the user's entry DN. <br>
+ * C = the string "US"
+ * <p>
+ * </pre>
+ *
+ * If an attribute or subject DN component does not exist the attribute is skipped.
+ *
+ * @version $Revision$, $Date$
+ */
+class AVAPattern {
+
+ /* the value type of the dn component */
+ public static final String TYPE_ATTR = "$attr";
+ public static final String TYPE_DN = "$dn";
+ public static final String TYPE_RDN = "$rdn";
+ public static final String TYPE_CONSTANT = "constant";
+
+ private static final LdapV3DNStrConverter mLdapDNStrConverter =
+ new LdapV3DNStrConverter();
+
+ /* ldap attributes needed by this AVA (to retrieve from ldap) */
+ protected String[] mLdapAttrs = null;
+
+ /* value type */
+ protected String mType = null;
+
+ /* the attribute in the AVA pair */
+ protected String mAttr = null;
+
+ /* value - could be name of an ldap attribute or entry dn attribute. */
+ protected String mValue = null;
+
+ /* nth value of the ldap or dn attribute */
+ protected int mElement = 0;
+
+ protected String mTestDN = null;
+
+ public AVAPattern(String component)
+ throws EAuthException {
+ if (component == null || component.length() == 0)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX", component));
+ parse(new PushbackReader(new StringReader(component)));
+ }
+
+ public AVAPattern(PushbackReader in)
+ throws EAuthException {
+ parse(in);
+ }
+
+ private void parse(PushbackReader in)
+ throws EAuthException {
+ int c;
+
+ // mark ava beginning.
+
+ // skip spaces
+ //System.out.println("============ AVAPattern Begin ===========");
+ //System.out.println("skip spaces");
+
+ try {
+ while ((c = in.read()) == ' ' || c == '\t') {//System.out.println("spaces read "+(char)c);
+ ;
+ }
+ } catch (IOException e) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX", "All blank"));
+ }
+ if (c == -1)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX", "All blank"));
+
+ // $rdn "." number syntax.
+
+ if (c == '$') {
+ //System.out.println("$rdn syntax");
+ mType = TYPE_RDN;
+ try {
+ if (in.read() != 'r' ||
+ in.read() != 'd' ||
+ in.read() != 'n' ||
+ in.read() != '.')
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "Invalid $ syntax, expecting $rdn"));
+ } catch (IOException e) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "Invalid $ syntax, expecting $rdn"));
+ }
+
+ StringBuffer rdnNumberBuf = new StringBuffer();
+
+ try {
+ while ((c = in.read()) != ',' && c != -1 && c != '+') {
+ //System.out.println("rdnNumber read "+(char)c);
+ rdnNumberBuf.append((char) c);
+ }
+ if (c != -1) // either ',' or '+'
+ in.unread(c);
+ } catch (IOException e) {
+ throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR", e.toString()));
+ }
+
+ String rdnNumber = rdnNumberBuf.toString().trim();
+
+ if (rdnNumber.length() == 0)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "$rdn number not set in ava pattern"));
+ try {
+ mElement = Integer.parseInt(rdnNumber) - 1;
+ } catch (NumberFormatException e) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "Invalid $rdn number in ava pattern"));
+ }
+ return;
+ }
+
+ // name "=" ... syntax.
+
+ // read name
+ //System.out.println("reading name");
+
+ StringBuffer attrBuf = new StringBuffer();
+
+ try {
+ while (c != '=' && c != -1 && c != ',' && c != '+') {
+ attrBuf.append((char) c);
+ c = in.read();
+ //System.out.println("name read "+(char)c);
+ }
+ if (c == ',' || c == '+')
+ in.unread(c);
+ } catch (IOException e) {
+ throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR", e.toString()));
+ }
+ if (c != '=')
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "Missing \"=\" in ava pattern"));
+
+ // read value
+ //System.out.println("reading value");
+
+ // skip spaces
+ //System.out.println("skip spaces for value");
+ try {
+ while ((c = in.read()) == ' ' || c == '\t') {//System.out.println("spaces2 read "+(char)c);
+ ;
+ }
+ } catch (IOException e) {
+ throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR", e.toString()));
+ }
+ if (c == -1)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "no value after = in ava pattern"));
+
+ if (c == '$') {
+ // check for $dn or $attr
+ try {
+ c = in.read();
+ //System.out.println("check $dn or $attr read "+(char)c);
+ } catch (IOException e) {
+ throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR", e.toString()));
+ }
+ if (c == -1)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "expecting $dn or $attr in ava pattern"));
+ if (c == 'a') {
+ try {
+ if (in.read() != 't' ||
+ in.read() != 't' ||
+ in.read() != 'r' ||
+ in.read() != '.')
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "expecting $attr in ava pattern"));
+ } catch (IOException e) {
+ throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR", e.toString()));
+ }
+ mType = TYPE_ATTR;
+ //System.out.println("---- mtype $attr");
+ } else if (c == 'd') {
+ try {
+ if (in.read() != 'n' ||
+ in.read() != '.')
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "expecting $dn in ava pattern"));
+ } catch (IOException e) {
+ throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR", e.toString()));
+ }
+ mType = TYPE_DN;
+ //System.out.println("----- mtype $dn");
+ } else {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "unknown keyword. expecting $dn or $attr."));
+ }
+
+ // get attr name of dn pattern from above.
+ String attrName = attrBuf.toString().trim();
+
+ //System.out.println("----- attrName "+attrName);
+ if (attrName.length() == 0)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "attribute name expected"));
+ try {
+ ObjectIdentifier attrOid =
+ mLdapDNStrConverter.parseAVAKeyword(attrName);
+
+ mAttr = mLdapDNStrConverter.encodeOID(attrOid);
+ //System.out.println("----- mAttr "+mAttr);
+ } catch (IOException e) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX", e.getMessage()));
+ }
+
+ // get dn or attribute from ldap search.
+ StringBuffer valueBuf = new StringBuffer();
+
+ try {
+ while ((c = in.read()) != ',' &&
+ c != -1 && c != '.' && c != '+') {
+ //System.out.println("mValue read "+(char)c);
+ valueBuf.append((char) c);
+ }
+ if (c == '+' || c == ',') // either ',' or '+'
+ in.unread(c); // pushback last , or +
+ } catch (IOException e) {
+ throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR", e.toString()));
+ }
+
+ mValue = valueBuf.toString().trim();
+ if (mValue.length() == 0)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "$dn or $attr attribute name expected"));
+ //System.out.println("----- mValue "+mValue);
+
+ // get nth dn or attribute from ldap search.
+ if (c == '.') {
+ StringBuffer attrNumberBuf = new StringBuffer();
+
+ try {
+ while ((c = in.read()) != ',' && c != -1 && c != '+') {
+ //System.out.println("mElement read "+(char)c);
+ attrNumberBuf.append((char) c);
+ }
+ if (c != -1) // either ',' or '+'
+ in.unread(c); // pushback last , or +
+ } catch (IOException e) {
+ throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR", e.toString()));
+ }
+ String attrNumber = attrNumberBuf.toString().trim();
+
+ if (attrNumber.length() == 0)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "nth element $dn or $attr expected"));
+ try {
+ mElement = Integer.parseInt(attrNumber) - 1;
+ } catch (NumberFormatException e) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "Invalid format in nth element $dn or $attr"));
+ }
+ }
+ //System.out.println("----- mElement "+mElement);
+ } else {
+ // value is constant. treat as regular ava.
+ mType = TYPE_CONSTANT;
+ //System.out.println("----- mType constant");
+ // parse ava value.
+ StringBuffer valueBuf = new StringBuffer();
+
+ valueBuf.append((char) c);
+ try {
+ while ((c = in.read()) != ',' &&
+ c != -1) {
+ valueBuf.append((char) c);
+ }
+ if (c == '+' || c == ',') { // either ',' or '+'
+ in.unread(c); // pushback last , or +
+ }
+ } catch (IOException e) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX", e.getMessage()));
+ }
+ try {
+ AVA ava = mLdapDNStrConverter.parseAVA(attrBuf + "=" + valueBuf);
+
+ mValue = ava.toLdapDNString();
+ //System.out.println("----- mValue "+mValue);
+ } catch (IOException e) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX", e.getMessage()));
+ }
+ }
+ }
+
+ public String formAVA(LDAPEntry entry)
+ throws EAuthException {
+ if (mType == TYPE_CONSTANT)
+ return mValue;
+
+ if (mType == TYPE_RDN) {
+ String dn = entry.getDN();
+
+ if (mTestDN != null)
+ dn = mTestDN;
+ //System.out.println("AVAPattern Using dn "+mTestDN);
+ String[] rdns = LDAPDN.explodeDN(dn, false);
+
+ if (mElement >= rdns.length)
+ return null;
+ return rdns[mElement];
+ }
+
+ if (mType == TYPE_DN) {
+ String dn = entry.getDN();
+
+ if (mTestDN != null)
+ dn = mTestDN;
+ //System.out.println("AVAPattern Using dn "+mTestDN);
+ String[] rdns = LDAPDN.explodeDN(dn, false);
+ String value = null;
+ int nFound = -1;
+
+ for (int i = 0; i < rdns.length; i++) {
+ String[] avas = explodeRDN(rdns[i]);
+
+ for (int j = 0; j < avas.length; j++) {
+ String[] exploded = explodeAVA(avas[j]);
+
+ if (exploded[0].equalsIgnoreCase(mValue) &&
+ ++nFound == mElement) {
+ value = exploded[1];
+ break;
+ }
+ }
+ }
+ if (value == null)
+ return null;
+ return mAttr + "=" + value;
+ }
+
+ if (mType == TYPE_ATTR) {
+ LDAPAttribute ldapAttr = entry.getAttribute(mValue);
+
+ if (ldapAttr == null)
+ return null;
+ String value = null;
+ @SuppressWarnings("unchecked")
+ Enumeration<String> ldapValues = ldapAttr.getStringValues();
+
+ for (int i = 0; ldapValues.hasMoreElements(); i++) {
+ String val = ldapValues.nextElement();
+
+ if (i == mElement) {
+ value = val;
+ break;
+ }
+ }
+ if (value == null)
+ return null;
+ String v = escapeLdapString(value);
+
+ return mAttr + "=" + v;
+ }
+
+ return null;
+ }
+
+ private String escapeLdapString(String value) {
+ int len = value.length();
+ char[] c = new char[len];
+ char[] newc = new char[len * 2];
+
+ value.getChars(0, len, c, 0);
+ int j = 0;
+
+ for (int i = 0; i < c.length; i++) {
+ // escape special characters that directory does not.
+ if ((c[i] == ',' || c[i] == '=' || c[i] == '+' || c[i] == '<' ||
+ c[i] == '>' || c[i] == '#' || c[i] == ';')) {
+ if (i == 0 || c[i - 1] != '\\') {
+ newc[j++] = '\\';
+ newc[j++] = c[i];
+ }
+ } // escape "\"
+ else if (c[i] == '\\') {
+ int k = i + 1;
+
+ if (i == len - 1 ||
+ (c[k] == ',' || c[k] == '=' || c[k] == '+' || c[k] == '<' ||
+ c[k] == '>' || c[k] == '#' || c[k] == ';')) {
+ newc[j++] = '\\';
+ newc[j++] = c[i];
+ }
+ } // escape QUOTATION
+ else if (c[i] == '"') {
+ if ((i == 0 && c[len - 1] != '"') ||
+ (i == len - 1 && c[0] != '"') ||
+ (i > 0 && i < len - 1)) {
+ newc[j++] = '\\';
+ newc[j++] = c[i];
+ }
+ } else
+ newc[j++] = c[i];
+ }
+ return new String(newc, 0, j);
+ }
+
+ public String getLdapAttr() {
+ if (mType == TYPE_ATTR)
+ return mValue;
+ else
+ return null;
+ }
+
+ /**
+ * Explode RDN into AVAs.
+ * Does not handle escaped '+'
+ * Java ldap library does not yet support multiple avas per rdn.
+ * If RDN is malformed returns empty array.
+ */
+ public static String[] explodeRDN(String rdn) {
+ int plus = rdn.indexOf('+');
+
+ if (plus == -1)
+ return new String[] { rdn };
+ Vector<String> avas = new Vector<String>();
+ StringTokenizer token = new StringTokenizer(rdn, "+");
+
+ while (token.hasMoreTokens())
+ avas.addElement(token.nextToken());
+ String[] theAvas = new String[avas.size()];
+
+ avas.copyInto(theAvas);
+ return theAvas;
+ }
+
+ /**
+ * Explode AVA into name and value.
+ * Does not handle escaped '='
+ * If AVA is malformed empty array is returned.
+ */
+ public static String[] explodeAVA(String ava) {
+ int equals = ava.indexOf('=');
+
+ if (equals == -1)
+ return null;
+ return new String[] {
+ ava.substring(0, equals).trim(), ava.substring(equals + 1).trim() };
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/AgentCertAuthentication.java b/base/server/cms/src/com/netscape/cms/authentication/AgentCertAuthentication.java
new file mode 100644
index 000000000..c65dd3971
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/AgentCertAuthentication.java
@@ -0,0 +1,327 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authentication.ISSLClientCertProvider;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.usrgrp.Certificates;
+import com.netscape.certsrv.usrgrp.EUsrGrpException;
+import com.netscape.certsrv.usrgrp.ICertUserLocator;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+
+/**
+ * Certificate server agent authentication.
+ * Maps a SSL client authenticate certificate to a user (agent) entry in the
+ * internal database.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class AgentCertAuthentication implements IAuthManager,
+ IProfileAuthenticator {
+
+ /* result auth token attributes */
+ public static final String TOKEN_USERDN = "user";
+ public static final String TOKEN_USER_DN = "userdn";
+ public static final String TOKEN_USERID = "userid";
+ public static final String TOKEN_UID = "uid";
+ public static final String TOKEN_GROUP = "group";
+
+ /* required credentials */
+ public static final String CRED_CERT = IAuthManager.CRED_SSL_CLIENT_CERT;
+ protected String[] mRequiredCreds = { CRED_CERT };
+
+ /* config parameters to pass to console (none) */
+ protected static String[] mConfigParams = null;
+
+ private String mName = null;
+ private String mImplName = null;
+ private IConfigStore mConfig = null;
+
+ private IUGSubsystem mUGSub = null;
+ private ICertUserLocator mCULocator = null;
+
+ public AgentCertAuthentication() {
+ }
+
+ /**
+ * initializes the CertUserDBAuthentication auth manager
+ * <p>
+ * called by AuthSubsystem init() method, when initializing all available authentication managers.
+ *
+ * @param name The name of this authentication manager instance.
+ * @param implName The name of the authentication manager plugin.
+ * @param config The configuration store for this authentication manager.
+ */
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ mName = name;
+ mImplName = implName;
+ mConfig = config;
+
+ mUGSub = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+ mCULocator = mUGSub.getCertUserLocator();
+ }
+
+ /**
+ * Gets the name of this authentication manager.
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Gets the plugin name of authentication manager.
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ public boolean isSSLClientRequired() {
+ return true;
+ }
+
+ /**
+ * authenticates user(agent) by certificate
+ * <p>
+ * called by other subsystems or their servlets to authenticate users (agents)
+ *
+ * @param authCred - authentication credential that contains
+ * an usrgrp.Certificates of the user (agent)
+ * @return the authentication token that contains the following
+ *
+ * @exception EMissingCredential If a required credential for this
+ * authentication manager is missing.
+ * @exception EInvalidCredentials If credentials cannot be authenticated.
+ * @exception EBaseException If an internal error occurred.
+ * @see com.netscape.certsrv.authentication.AuthToken
+ * @see com.netscape.certsrv.usrgrp.Certificates
+ */
+ public IAuthToken authenticate(IAuthCredentials authCred)
+ throws EMissingCredential, EInvalidCredentials, EBaseException {
+
+ CMS.debug("AgentCertAuthentication: start");
+ CMS.debug("authenticator instance name is " + getName());
+
+ // force SSL handshake
+ SessionContext context = SessionContext.getExistingContext();
+ ISSLClientCertProvider provider = (ISSLClientCertProvider)
+ context.get("sslClientCertProvider");
+
+ if (provider == null) {
+ CMS.debug("AgentCertAuthentication: No SSL Client Cert Provider Found");
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ CMS.debug("AgentCertAuthenticator: got provider");
+ CMS.debug("AgentCertAuthenticator: retrieving client certificate");
+ X509Certificate[] allCerts = provider.getClientCertificateChain();
+
+ if (allCerts == null) {
+ CMS.debug("AgentCertAuthentication: No SSL Client Certs Found");
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ CMS.debug("AgentCertAuthenticator: got certificates");
+
+ // retreive certificate from socket
+ AuthToken authToken = new AuthToken(this);
+ X509Certificate[] x509Certs = allCerts;
+
+ // default certificate default has bugs in version
+ // version(3) is returned as 3, which should be 2
+ X509CertImpl ci[] = new X509CertImpl[x509Certs.length];
+
+ try {
+ for (int i = 0; i < x509Certs.length; i++) {
+ ci[i] = new X509CertImpl(x509Certs[i].getEncoded());
+ }
+ } catch (CertificateException e) {
+ CMS.debug(e.toString());
+ }
+
+ // check if certificate(s) is revoked
+ boolean checkRevocation = true;
+ try {
+ checkRevocation = mConfig.getBoolean("checkRevocation", true);
+ } catch (EBaseException e) {
+ // do nothing; default to true
+ }
+ if (checkRevocation) {
+ if (CMS.isRevoked(ci)) {
+ CMS.debug("AgentCertAuthentication: certificate revoked");
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ }
+
+ // map cert to user
+ IUser user = null;
+ Certificates certs = new Certificates(ci);
+
+ try {
+ user = mCULocator.locateUser(certs);
+ } catch (EUsrGrpException e) {
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ } catch (netscape.ldap.LDAPException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ e.toString()));
+ }
+
+ // any unexpected error occurs like internal db down,
+ // UGSubsystem only returns null for user.
+ if (user == null) {
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ // get group name from configuration file
+ IConfigStore sconfig = CMS.getConfigStore();
+ String groupname = "";
+ try {
+ groupname = sconfig.getString("auths.instance." + getName() + ".agentGroup",
+ "");
+ } catch (EBaseException ee) {
+ }
+
+ if (!groupname.equals("")) {
+ CMS.debug("check if " + user.getUserID() + " is in group " + groupname);
+ IUGSubsystem uggroup = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+ if (!uggroup.isMemberOf(user, groupname)) {
+ CMS.debug(user.getUserID() + " is not in this group " + groupname);
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHORIZATION_ERROR"));
+ }
+ }
+ authToken.set(TOKEN_USERDN, user.getUserDN());
+ authToken.set(TOKEN_USER_DN, user.getUserDN());
+ authToken.set(TOKEN_USERID, user.getUserID());
+ authToken.set(TOKEN_UID, user.getUserID());
+ authToken.set(TOKEN_GROUP, groupname);
+ authToken.set(CRED_CERT, certs);
+
+ CMS.debug("AgentCertAuthentication: authenticated " + user.getUserDN());
+
+ return authToken;
+ }
+
+ /**
+ * get the list of authentication credential attribute names
+ * required by this authentication manager. Generally used by
+ * the servlets that handle agent operations to authenticate its
+ * users. It calls this method to know which are the
+ * required credentials from the user (e.g. Javascript form data)
+ *
+ * @return attribute names in Vector
+ */
+ public String[] getRequiredCreds() {
+ return (mRequiredCreds);
+ }
+
+ /**
+ * get the list of configuration parameter names
+ * required by this authentication manager. Generally used by
+ * the Certificate Server Console to display the table for
+ * configuration purposes. CertUserDBAuthentication is currently not
+ * exposed in this case, so this method is not to be used.
+ *
+ * @return configuration parameter names in Hashtable of Vectors
+ * where each hashtable entry's key is the substore name, value is a
+ * Vector of parameter names. If no substore, the parameter name
+ * is the Hashtable key itself, with value same as key.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+
+ /**
+ * prepare this authentication manager for shutdown.
+ */
+ public void shutdown() {
+ }
+
+ /**
+ * gets the configuretion substore used by this authentication
+ * manager
+ *
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ // Profile-related methods
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_AGENT_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_AGENT_TEXT");
+ }
+
+ /**
+ * Retrieves a list of names of the value parameter.
+ */
+ public Enumeration<String> getValueNames() {
+ return null;
+ }
+
+ public boolean isValueWriteable(String name) {
+ return false;
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public void populate(IAuthToken token, IRequest request)
+ throws EProfileException {
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java b/base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java
new file mode 100644
index 000000000..f2bf40241
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java
@@ -0,0 +1,1109 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cms.authentication;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+/* cert server imports */
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.PublicKey;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.pkcs.PKCS10;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.PrivateKey;
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
+import org.mozilla.jss.asn1.OCTET_STRING;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.asn1.SET;
+import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.pkcs10.CertificationRequest;
+import org.mozilla.jss.pkcs11.PK11PubKey;
+import org.mozilla.jss.pkcs11.PK11ECPublicKey;
+import org.mozilla.jss.pkix.cert.Certificate;
+import org.mozilla.jss.pkix.cert.CertificateInfo;
+import org.mozilla.jss.pkix.cmc.PKIData;
+import org.mozilla.jss.pkix.cmc.TaggedAttribute;
+import org.mozilla.jss.pkix.cmc.TaggedCertificationRequest;
+import org.mozilla.jss.pkix.cmc.TaggedRequest;
+import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo;
+import org.mozilla.jss.pkix.cms.IssuerAndSerialNumber;
+import org.mozilla.jss.pkix.cms.SignedData;
+import org.mozilla.jss.pkix.cms.SignerIdentifier;
+import org.mozilla.jss.pkix.crmf.CertReqMsg;
+import org.mozilla.jss.pkix.crmf.CertRequest;
+import org.mozilla.jss.pkix.crmf.CertTemplate;
+import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier;
+import org.mozilla.jss.pkix.primitive.Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cmsutil.util.Utils;
+
+//import com.netscape.cmscore.util.*;
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * UID/CMC authentication plug-in
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMCAuth implements IAuthManager, IExtendedPluginInfo,
+ IProfileAuthenticator {
+
+ ////////////////////////
+ // default parameters //
+ ////////////////////////
+
+ /////////////////////////////
+ // IAuthManager parameters //
+ /////////////////////////////
+
+ /* authentication plug-in configuration store */
+ private IConfigStore mConfig;
+ private static final String HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----";
+ private static final String TRAILER = "-----END NEW CERTIFICATE REQUEST-----";
+ public static final String TOKEN_CERT_SERIAL = "certSerialToRevoke";
+ public static final String REASON_CODE = "reasonCode";
+ /* authentication plug-in name */
+ private String mImplName = null;
+
+ /* authentication plug-in instance name */
+ private String mName = null;
+
+ /* authentication plug-in fields */
+
+ /* Holds authentication plug-in fields accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ protected static String[] mConfigParams =
+ new String[] {};
+
+ /* authentication plug-in values */
+
+ /* authentication plug-in properties */
+
+ /* required credentials to authenticate. UID and CMC are strings. */
+ public static final String CRED_CMC = "cmcRequest";
+
+ protected static String[] mRequiredCreds = {};
+
+ ////////////////////////////////////
+ // IExtendedPluginInfo parameters //
+ ////////////////////////////////////
+
+ /* Vector of extendedPluginInfo strings */
+ protected static Vector<String> mExtendedPluginInfo = null;
+ //public static final String AGENT_AUTHMGR_ID = "agentAuthMgr";
+ //public static final String AGENT_PLUGIN_ID = "agentAuthPlugin";
+
+ /* actual help messages */
+ static {
+ mExtendedPluginInfo = new Vector<String>();
+
+ mExtendedPluginInfo
+ .add(IExtendedPluginInfo.HELP_TEXT +
+ ";Authenticate the CMC request. The signer must be an agent. The \"Authentication Instance ID\" must be named \"CMCAuth\"");
+ mExtendedPluginInfo.add(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-authentication");
+ }
+
+ ///////////////////////
+ // Logger parameters //
+ ///////////////////////
+
+ /* the system's logger */
+ private ILogger mLogger = CMS.getLogger();
+
+ /* signed audit parameters */
+ private ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+ private final static String SIGNED_AUDIT_ENROLLMENT_REQUEST_TYPE =
+ "enrollment";
+ private final static String SIGNED_AUDIT_REVOCATION_REQUEST_TYPE =
+ "revocation";
+ private final static String LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY =
+ "LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY_5";
+
+ /////////////////////
+ // default methods //
+ /////////////////////
+
+ /**
+ * Default constructor, initialization must follow.
+ */
+ public CMCAuth() {
+ }
+
+ //////////////////////////
+ // IAuthManager methods //
+ //////////////////////////
+
+ /**
+ * Initializes the CMCAuth authentication plug-in.
+ * <p>
+ *
+ * @param name The name for this authentication plug-in instance.
+ * @param implName The name of the authentication plug-in.
+ * @param config - The configuration store for this instance.
+ * @exception EBaseException If an error occurs during initialization.
+ */
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ mName = name;
+ mImplName = implName;
+ mConfig = config;
+
+ log(ILogger.LL_INFO, "Initialization complete!");
+ }
+
+ /**
+ * Authenticates user by their CMC;
+ * resulting AuthToken sets a TOKEN_SUBJECT for the subject name.
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY used when CMC (agent-pre-signed) cert
+ * requests or revocation requests are submitted and signature is verified
+ * </ul>
+ *
+ * @param authCred Authentication credentials, CRED_UID and CRED_CMC.
+ * @return an AuthToken
+ * @exception com.netscape.certsrv.authentication.EMissingCredential
+ * If a required authentication credential is missing.
+ * @exception com.netscape.certsrv.authentication.EInvalidCredentials
+ * If credentials failed authentication.
+ * @exception com.netscape.certsrv.base.EBaseException
+ * If an internal error occurred.
+ * @see com.netscape.certsrv.authentication.AuthToken
+ */
+ public IAuthToken authenticate(IAuthCredentials authCred) throws EMissingCredential, EInvalidCredentials,
+ EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditReqType = ILogger.UNIDENTIFIED;
+ String auditCertSubject = ILogger.UNIDENTIFIED;
+ String auditSignerInfo = ILogger.UNIDENTIFIED;
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ // get the CMC.
+
+ Object argblock = authCred.getArgBlock();
+ Object returnVal = null;
+ if (argblock == null) {
+ returnVal = authCred.get("cert_request");
+ if (returnVal == null)
+ returnVal = authCred.get(CRED_CMC);
+ } else {
+ returnVal = authCred.get("cert_request");
+ if (returnVal == null)
+ returnVal = authCred.getArgBlock().get(CRED_CMC);
+ }
+ String cmc = (String) returnVal;
+ if (cmc == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditReqType,
+ auditCertSubject,
+ auditSignerInfo);
+
+ audit(auditMessage);
+
+ throw new EMissingCredential(CMS.getUserMessage(
+ "CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_CMC));
+ }
+
+ if (cmc.equals("")) {
+ log(ILogger.LL_FAILURE,
+ "cmc : attempted login with empty CMC.");
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditReqType,
+ auditCertSubject,
+ auditSignerInfo);
+
+ audit(auditMessage);
+
+ throw new EInvalidCredentials(CMS.getUserMessage(
+ "CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ // authenticate by checking CMC.
+
+ // everything OK.
+ // now formulate the certificate info.
+ // set the subject name at a minimum.
+ // set anything else like version, extensions, etc.
+ // if nothing except subject name is set the rest of
+ // cert info will be filled in by policies and CA defaults.
+
+ AuthToken authToken = new AuthToken(this);
+
+ try {
+ String asciiBASE64Blob;
+
+ int startIndex = cmc.indexOf(HEADER);
+ int endIndex = cmc.indexOf(TRAILER);
+ if (startIndex != -1 && endIndex != -1) {
+ startIndex = startIndex + HEADER.length();
+ asciiBASE64Blob = cmc.substring(startIndex, endIndex);
+ } else
+ asciiBASE64Blob = cmc;
+
+ byte[] cmcBlob = CMS.AtoB(asciiBASE64Blob);
+ ByteArrayInputStream cmcBlobIn = new
+ ByteArrayInputStream(cmcBlob);
+
+ org.mozilla.jss.pkix.cms.ContentInfo cmcReq =
+ (org.mozilla.jss.pkix.cms.ContentInfo)
+ org.mozilla.jss.pkix.cms.ContentInfo.getTemplate().decode(
+ cmcBlobIn);
+
+ if (!cmcReq.getContentType().equals(
+ org.mozilla.jss.pkix.cms.ContentInfo.SIGNED_DATA) ||
+ !cmcReq.hasContent()) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditReqType,
+ auditCertSubject,
+ auditSignerInfo);
+
+ audit(auditMessage);
+
+ // throw new ECMSGWException(CMSGWResources.NO_CMC_CONTENT);
+
+ throw new EBaseException("NO_CMC_CONTENT");
+ }
+
+ SignedData cmcFullReq = (SignedData)
+ cmcReq.getInterpretedContent();
+
+ IConfigStore cmc_config = CMS.getConfigStore();
+ boolean checkSignerInfo =
+ cmc_config.getBoolean("cmc.signerInfo.verify", true);
+ String userid = "defUser";
+ String uid = "defUser";
+ if (checkSignerInfo) {
+ IAuthToken agentToken = verifySignerInfo(authToken, cmcFullReq);
+ if (agentToken == null) {
+ CMS.debug("CMCAuth: authenticate() agentToken null");
+ throw new EBaseException("CMCAuth: agent verifySignerInfo failure");
+ }
+ userid = agentToken.getInString("userid");
+ uid = agentToken.getInString("cn");
+ } else {
+ CMS.debug("CMCAuth: authenticate() signerInfo verification bypassed");
+ }
+ // reset value of auditSignerInfo
+ if (uid != null) {
+ auditSignerInfo = uid.trim();
+ }
+
+ EncapsulatedContentInfo ci = cmcFullReq.getContentInfo();
+
+ OBJECT_IDENTIFIER id = ci.getContentType();
+
+ if (!id.equals(OBJECT_IDENTIFIER.id_cct_PKIData) ||
+ !ci.hasContent()) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditReqType,
+ auditCertSubject,
+ auditSignerInfo);
+
+ audit(auditMessage);
+
+ // throw new ECMSGWException(
+ // CMSGWResources.NO_PKIDATA);
+
+ throw new EBaseException("NO_PKIDATA");
+ }
+
+ OCTET_STRING content = ci.getContent();
+
+ ByteArrayInputStream s = new
+ ByteArrayInputStream(content.toByteArray());
+ PKIData pkiData = (PKIData) (new PKIData.Template()).decode(s);
+
+ SEQUENCE reqSequence = pkiData.getReqSequence();
+
+ int numReqs = reqSequence.size();
+
+ if (numReqs == 0) {
+ // revocation request
+
+ // reset value of auditReqType
+ auditReqType = SIGNED_AUDIT_REVOCATION_REQUEST_TYPE;
+
+ SEQUENCE controlSequence = pkiData.getControlSequence();
+ int controlSize = controlSequence.size();
+
+ if (controlSize > 0) {
+ for (int i = 0; i < controlSize; i++) {
+ TaggedAttribute taggedAttribute =
+ (TaggedAttribute) controlSequence.elementAt(i);
+ OBJECT_IDENTIFIER type = taggedAttribute.getType();
+
+ if (type.equals(
+ OBJECT_IDENTIFIER.id_cmc_revokeRequest)) {
+ // if( i ==1 ) {
+ // taggedAttribute.getType() ==
+ // OBJECT_IDENTIFIER.id_cmc_revokeRequest
+ // }
+
+ SET values = taggedAttribute.getValues();
+ int numVals = values.size();
+ BigInteger[] bigIntArray = null;
+
+ bigIntArray = new BigInteger[numVals];
+ for (int j = 0; j < numVals; j++) {
+ // serialNumber INTEGER
+
+ // SEQUENCE RevRequest = (SEQUENCE)
+ // values.elementAt(j);
+ byte[] encoded = ASN1Util.encode(
+ values.elementAt(j));
+ org.mozilla.jss.asn1.ASN1Template template = new
+ org.mozilla.jss.pkix.cmmf.RevRequest.Template();
+ org.mozilla.jss.pkix.cmmf.RevRequest revRequest =
+ (org.mozilla.jss.pkix.cmmf.RevRequest)
+ ASN1Util.decode(template, encoded);
+
+ // SEQUENCE RevRequest = (SEQUENCE)
+ // ASN1Util.decode(
+ // SEQUENCE.getTemplate(),
+ // ASN1Util.encode(
+ // values.elementAt(j)));
+
+ // SEQUENCE RevRequest =
+ // values.elementAt(j);
+ // int revReqSize = RevRequest.size();
+ // if( revReqSize > 3 ) {
+ // INTEGER serialNumber =
+ // new INTEGER((long)0);
+ // }
+
+ INTEGER temp = revRequest.getSerialNumber();
+
+ bigIntArray[j] = temp;
+ authToken.set(TOKEN_CERT_SERIAL, bigIntArray);
+
+ long reasonCode = revRequest.getReason().getValue();
+ Integer IntObject = Integer.valueOf((int) reasonCode);
+ authToken.set(REASON_CODE, IntObject);
+
+ authToken.set("uid", uid);
+ authToken.set("userid", userid);
+ }
+ }
+ }
+
+ }
+ } else {
+ // enrollment request
+
+ // reset value of auditReqType
+ auditReqType = SIGNED_AUDIT_ENROLLMENT_REQUEST_TYPE;
+
+ X509CertInfo[] certInfoArray = new X509CertInfo[numReqs];
+ String[] reqIdArray = new String[numReqs];
+
+ for (int i = 0; i < numReqs; i++) {
+ // decode message.
+ TaggedRequest taggedRequest =
+ (TaggedRequest) reqSequence.elementAt(i);
+
+ TaggedRequest.Type type = taggedRequest.getType();
+
+ if (type.equals(TaggedRequest.PKCS10)) {
+ CMS.debug("CMCAuth: type is PKCS10");
+ TaggedCertificationRequest tcr =
+ taggedRequest.getTcr();
+ int p10Id = tcr.getBodyPartID().intValue();
+
+ reqIdArray[i] = String.valueOf(p10Id);
+
+ CertificationRequest p10 =
+ tcr.getCertificationRequest();
+
+ // transfer to sun class
+ ByteArrayOutputStream ostream =
+ new ByteArrayOutputStream();
+
+ p10.encode(ostream);
+ boolean sigver = true;
+ boolean tokenSwitched = false;
+ CryptoManager cm = null;
+ CryptoToken signToken = null;
+ CryptoToken savedToken = null;
+ sigver = CMS.getConfigStore().getBoolean("ca.requestVerify.enabled", true);
+ try {
+ cm = CryptoManager.getInstance();
+ if (sigver == true) {
+ String tokenName =
+ CMS.getConfigStore().getString("ca.requestVerify.token", "internal");
+ savedToken = cm.getThreadToken();
+ if (tokenName.equals("internal")) {
+ signToken = cm.getInternalCryptoToken();
+ } else {
+ signToken = cm.getTokenByName(tokenName);
+ }
+ if (!savedToken.getName().equals(signToken.getName())) {
+ cm.setThreadToken(signToken);
+ tokenSwitched = true;
+ }
+ }
+
+ PKCS10 pkcs10 =
+ new PKCS10(ostream.toByteArray(), sigver);
+
+ // xxx do we need to do anything else?
+ X509CertInfo certInfo =
+ CMS.getDefaultX509CertInfo();
+
+ // fillPKCS10(certInfo,pkcs10,authToken,null);
+
+ // authToken.set(
+ // pkcs10.getSubjectPublicKeyInfo());
+
+ X500Name tempName = pkcs10.getSubjectName();
+
+ // reset value of auditCertSubject
+ if (tempName != null) {
+ auditCertSubject =
+ tempName.toString().trim();
+ if (auditCertSubject.equals("")) {
+ auditCertSubject =
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ authToken.set(AuthToken.TOKEN_CERT_SUBJECT,
+ tempName.toString());
+ }
+
+ authToken.set("uid", uid);
+ authToken.set("userid", userid);
+
+ certInfoArray[i] = certInfo;
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditReqType,
+ auditCertSubject,
+ auditSignerInfo);
+
+ audit(auditMessage);
+
+ //throw new ECMSGWException(
+ //CMSGWResources.ERROR_PKCS101, e.toString());
+
+ e.printStackTrace();
+ throw new EBaseException(e.toString());
+ } finally {
+ if ((sigver == true) && (tokenSwitched == true)){
+ cm.setThreadToken(savedToken);
+ }
+ }
+ } else if (type.equals(TaggedRequest.CRMF)) {
+
+ CMS.debug("CMCAuth: type is CRMF");
+ try {
+ CertReqMsg crm =
+ taggedRequest.getCrm();
+ CertRequest certReq = crm.getCertReq();
+ INTEGER reqID = certReq.getCertReqId();
+ reqIdArray[i] = reqID.toString();
+ CertTemplate template = certReq.getCertTemplate();
+ Name name = template.getSubject();
+
+ // xxx do we need to do anything else?
+ X509CertInfo certInfo =
+ CMS.getDefaultX509CertInfo();
+
+ // reset value of auditCertSubject
+ if (name != null) {
+ String ss = name.getRFC1485();
+
+ auditCertSubject = ss;
+ if (auditCertSubject.equals("")) {
+ auditCertSubject =
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ authToken.set(AuthToken.TOKEN_CERT_SUBJECT, ss);
+ authToken.set("uid", uid);
+ authToken.set("userid", userid);
+ }
+ certInfoArray[i] = certInfo;
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditReqType,
+ auditCertSubject,
+ auditSignerInfo);
+
+ audit(auditMessage);
+
+ //throw new ECMSGWException(
+ //CMSGWResources.ERROR_PKCS101, e.toString());
+
+ e.printStackTrace();
+ throw new EBaseException(e.toString());
+ }
+ }
+
+ // authToken.set(AgentAuthentication.CRED_CERT, new
+ // com.netscape.certsrv.usrgrp.Certificates(
+ // x509Certs));
+ }
+ }
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditReqType,
+ auditCertSubject,
+ auditSignerInfo);
+
+ audit(auditMessage);
+
+ //Debug.printStackTrace(e);
+ throw new EInvalidCredentials(CMS.getUserMessage(
+ "CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditReqType,
+ auditCertSubject,
+ auditSignerInfo);
+
+ audit(auditMessage);
+
+ return authToken;
+ } catch (EMissingCredential eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditReqType,
+ auditCertSubject,
+ auditSignerInfo);
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (EInvalidCredentials eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditReqType,
+ auditCertSubject,
+ auditSignerInfo);
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ } catch (EBaseException eAudit3) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditReqType,
+ auditCertSubject,
+ auditSignerInfo);
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit3;
+ }
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ * <p>
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+
+ /**
+ * gets the configuration substore used by this authentication
+ * plug-in
+ * <p>
+ *
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * gets the plug-in name of this authentication plug-in.
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ /**
+ * gets the name of this authentication plug-in instance
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * get the list of required credentials.
+ * <p>
+ *
+ * @return list of required credentials as strings.
+ */
+ public String[] getRequiredCreds() {
+ return (mRequiredCreds);
+ }
+
+ /**
+ * prepares for shutdown.
+ */
+ public void shutdown() {
+ }
+
+ /////////////////////////////////
+ // IExtendedPluginInfo methods //
+ /////////////////////////////////
+
+ /**
+ * Activate the help system.
+ * <p>
+ *
+ * @return help messages
+ */
+ public String[] getExtendedPluginInfo() {
+ CMS.debug("CMCAuth: getExtendedPluginInfo()");
+ String[] s = Utils.getStringArrayFromVector(mExtendedPluginInfo);
+
+ CMS.debug("CMCAuth: s.length = " + s.length);
+ for (int i = 0; i < s.length; i++) {
+ CMS.debug("" + i + " " + s[i]);
+ }
+ return s;
+ }
+
+ ////////////////////
+ // Logger methods //
+ ////////////////////
+
+ /**
+ * Logs a message for this class in the system log file.
+ * <p>
+ *
+ * @param level The log level.
+ * @param msg The message to log.
+ * @see com.netscape.certsrv.logging.ILogger
+ */
+ protected void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHENTICATION,
+ level, "CMC Authentication: " + msg);
+ }
+
+ protected IAuthToken verifySignerInfo(AuthToken authToken, SignedData cmcFullReq) throws EBaseException {
+
+ EncapsulatedContentInfo ci = cmcFullReq.getContentInfo();
+ OBJECT_IDENTIFIER id = ci.getContentType();
+ OCTET_STRING content = ci.getContent();
+
+ boolean tokenSwitched = false;
+ CryptoToken signToken = null;
+ CryptoToken savedToken = null;
+ CryptoManager cm = null;
+ try {
+ cm = CryptoManager.getInstance();
+ ByteArrayInputStream s = new ByteArrayInputStream(content.toByteArray());
+ PKIData pkiData = (PKIData) (new PKIData.Template()).decode(s);
+
+ SET dais = cmcFullReq.getDigestAlgorithmIdentifiers();
+ int numDig = dais.size();
+ Hashtable<String, byte[]> digs = new Hashtable<String, byte[]>();
+
+ //if request key is used for signing, there MUST be only one signerInfo
+ //object in the signedData object.
+ for (int i = 0; i < numDig; i++) {
+ AlgorithmIdentifier dai =
+ (AlgorithmIdentifier) dais.elementAt(i);
+ String name =
+ DigestAlgorithm.fromOID(dai.getOID()).toString();
+
+ MessageDigest md =
+ MessageDigest.getInstance(name);
+
+ byte[] digest = md.digest(content.toByteArray());
+
+ digs.put(name, digest);
+ }
+
+ SET sis = cmcFullReq.getSignerInfos();
+ int numSis = sis.size();
+
+ for (int i = 0; i < numSis; i++) {
+ org.mozilla.jss.pkix.cms.SignerInfo si = (org.mozilla.jss.pkix.cms.SignerInfo) sis.elementAt(i);
+
+ String name = si.getDigestAlgorithm().toString();
+ byte[] digest = digs.get(name);
+
+ if (digest == null) {
+ MessageDigest md = MessageDigest.getInstance(name);
+ ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+
+ pkiData.encode(ostream);
+ digest = md.digest(ostream.toByteArray());
+
+ }
+ // signed by previously certified signature key
+ SignerIdentifier sid = si.getSignerIdentifier();
+
+ if (sid.getType().equals(SignerIdentifier.ISSUER_AND_SERIALNUMBER)) {
+ IssuerAndSerialNumber issuerAndSerialNumber = sid.getIssuerAndSerialNumber();
+ // find from the certs in the signedData
+ java.security.cert.X509Certificate cert = null;
+
+ if (cmcFullReq.hasCertificates()) {
+ SET certs = cmcFullReq.getCertificates();
+ int numCerts = certs.size();
+ java.security.cert.X509Certificate[] x509Certs = new java.security.cert.X509Certificate[1];
+ byte[] certByteArray = new byte[0];
+ for (int j = 0; j < numCerts; j++) {
+ Certificate certJss = (Certificate) certs.elementAt(j);
+ CertificateInfo certI = certJss.getInfo();
+ Name issuer = certI.getIssuer();
+
+ byte[] issuerB = ASN1Util.encode(issuer);
+ INTEGER sn = certI.getSerialNumber();
+ // if this cert is the signer cert, not a cert in the chain
+ if (new String(issuerB).equals(new String(
+ ASN1Util.encode(issuerAndSerialNumber.getIssuer())))
+ && sn.toString().equals(issuerAndSerialNumber.getSerialNumber().toString())) {
+ ByteArrayOutputStream os = new
+ ByteArrayOutputStream();
+
+ certJss.encode(os);
+ certByteArray = os.toByteArray();
+
+ X509CertImpl tempcert = new X509CertImpl(os.toByteArray());
+
+ cert = tempcert;
+ x509Certs[0] = cert;
+ // xxx validate the cert length
+
+ }
+ }
+ CMS.debug("CMCAuth: start checking signature");
+ if (cert == null) {
+ // find from certDB
+ CMS.debug("CMCAuth: verifying signature");
+ si.verify(digest, id);
+ } else {
+ CMS.debug("CMCAuth: found signing cert... verifying");
+ PublicKey signKey = cert.getPublicKey();
+ PrivateKey.Type keyType = null;
+ String alg = signKey.getAlgorithm();
+
+ PK11PubKey pubK = null;
+ if (alg.equals("RSA")) {
+ CMS.debug("CMCAuth: signing key alg=RSA");
+ keyType = PrivateKey.RSA;
+ pubK = PK11PubKey.fromRaw(keyType, ((X509Key) signKey).getKey());
+ } else if (alg.equals("EC")) {
+ CMS.debug("CMCAuth: signing key alg=EC");
+ keyType = PrivateKey.EC;
+ byte publicKeyData[] = ((X509Key) signKey).getEncoded();
+ pubK = (PK11PubKey) PK11ECPublicKey.fromSPKI(/*keyType,*/ publicKeyData);
+ } else if (alg.equals("DSA")) {
+ CMS.debug("CMCAuth: signing key alg=DSA");
+ keyType = PrivateKey.DSA;
+ pubK = PK11PubKey.fromSPKI(/*keyType,*/ ((X509Key) signKey).getKey());
+ }
+
+ String tokenName =
+ CMS.getConfigStore().getString("ca.requestVerify.token", "internal");
+ // by default JSS will use internal crypto token
+ if (!tokenName.equals("internal")) {
+ savedToken = cm.getThreadToken();
+ signToken = cm.getTokenByName(tokenName);
+ if(signToken != null) {
+ cm.setThreadToken(signToken);
+ tokenSwitched = true;
+ CMS.debug("CMCAuth: verifySignerInfo token switched:"+ tokenName);
+ } else {
+ CMS.debug("CMCAuth: verifySignerInfo token not found:"+ tokenName+ ", trying internal");
+ }
+ }
+
+ CMS.debug("CMCAuth: verifying signature with public key");
+ si.verify(digest, id, pubK);
+ }
+ CMS.debug("CMCAuth: finished checking signature");
+ // verify signer's certificate using the revocator
+ if (!cm.isCertValid(certByteArray, true, CryptoManager.CertUsage.SSLClient))
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+
+ // authenticate signer's certificate using the userdb
+ IAuthSubsystem authSS = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+
+ IAuthManager agentAuth = authSS.getAuthManager(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID);//AGENT_AUTHMGR_ID);
+ if (agentAuth == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_AUTHENTICATION_MANAGER_NOT_FOUND", IAuthSubsystem.CERTUSERDB_AUTHMGR_ID));
+ }
+ IAuthCredentials agentCred = new com.netscape.certsrv.authentication.AuthCredentials();
+
+ agentCred.set(IAuthManager.CRED_SSL_CLIENT_CERT, x509Certs);
+
+ IAuthToken tempToken = agentAuth.authenticate(agentCred);
+ netscape.security.x509.X500Name tempPrincipal = (X500Name) x509Certs[0].getSubjectDN();
+ String CN = tempPrincipal.getCommonName(); //tempToken.get("userid");
+
+ BigInteger agentCertSerial = x509Certs[0].getSerialNumber();
+ authToken.set(IAuthManager.CRED_SSL_CLIENT_CERT, agentCertSerial.toString());
+ tempToken.set("cn", CN);
+ return tempToken;
+
+ }
+ // find from internaldb if it's ca. (ra does not have that.)
+ // find from internaldb usrgrp info
+
+ // find from certDB
+ si.verify(digest, id);
+
+ } //
+ }
+ } catch (InvalidBERException e) {
+ CMS.debug("CMCAuth: " + e.toString());
+ } catch (IOException e) {
+ CMS.debug("CMCAuth: " + e.toString());
+ } catch (NotInitializedException e) {
+ CMS.debug("CMCAuth: " + e.toString());
+ } catch (Exception e) {
+ CMS.debug("CMCAuth: " + e.toString());
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ } finally {
+ if ((tokenSwitched == true) && (savedToken != null)){
+ cm.setThreadToken(savedToken);
+ CMS.debug("CMCAuth: verifySignerInfo token restored");
+ }
+ }
+ return null;
+
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ return null;
+ }
+
+ // Profile-related methods
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_CMS_SIGN_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_CMS_SIGN_TEXT");
+ }
+
+ /**
+ * Retrieves a list of names of the value parameter.
+ */
+ public Enumeration<String> getValueNames() {
+ Vector<String> v = new Vector<String>();
+ v.addElement("cert_request");
+ return v.elements();
+ }
+
+ public boolean isValueWriteable(String name) {
+ return false;
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(CRED_CMC)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null, null,
+ "CMC request");
+ }
+ return null;
+ }
+
+ public void populate(IAuthToken token, IRequest request)
+ throws EProfileException {
+ request.setExtData(IProfileAuthenticator.AUTHENTICATED_NAME,
+ token.getInString(AuthToken.TOKEN_CERT_SUBJECT));
+ }
+
+ public boolean isSSLClientRequired() {
+ return false;
+ }
+
+ /**
+ * Signed Audit Log
+ *
+ * This method is called to store messages to the signed audit log.
+ * <P>
+ *
+ * @param msg signed audit log message
+ */
+ private void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+
+ if (mSignedAuditLogger == null) {
+ return;
+ }
+
+ mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+
+ /**
+ * Signed Audit Log Subject ID
+ *
+ * This method is called to obtain the "SubjectID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @return id string containing the signed audit log message SubjectID
+ */
+ private String auditSubjectID() {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String subjectID = null;
+
+ // Initialize subjectID
+ SessionContext auditContext = SessionContext.getExistingContext();
+
+ if (auditContext != null) {
+ subjectID = (String)
+ auditContext.get(SessionContext.USER_ID);
+
+ if (subjectID != null) {
+ subjectID = subjectID.trim();
+ } else {
+ subjectID = ILogger.NONROLEUSER;
+ }
+ } else {
+ subjectID = ILogger.UNIDENTIFIED;
+ }
+
+ return subjectID;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/Crypt.java b/base/server/cms/src/com/netscape/cms/authentication/Crypt.java
new file mode 100644
index 000000000..867181138
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/Crypt.java
@@ -0,0 +1,438 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+public class Crypt {
+ // Static data:
+ static byte[]
+ IP = // Initial permutation
+ {
+ 58, 50, 42, 34, 26, 18, 10, 2,
+ 60, 52, 44, 36, 28, 20, 12, 4,
+ 62, 54, 46, 38, 30, 22, 14, 6,
+ 64, 56, 48, 40, 32, 24, 16, 8,
+ 57, 49, 41, 33, 25, 17, 9, 1,
+ 59, 51, 43, 35, 27, 19, 11, 3,
+ 61, 53, 45, 37, 29, 21, 13, 5,
+ 63, 55, 47, 39, 31, 23, 15, 7
+ },
+ FP = // Final permutation, FP = IP^(-1)
+ {
+ 40, 8, 48, 16, 56, 24, 64, 32,
+ 39, 7, 47, 15, 55, 23, 63, 31,
+ 38, 6, 46, 14, 54, 22, 62, 30,
+ 37, 5, 45, 13, 53, 21, 61, 29,
+ 36, 4, 44, 12, 52, 20, 60, 28,
+ 35, 3, 43, 11, 51, 19, 59, 27,
+ 34, 2, 42, 10, 50, 18, 58, 26,
+ 33, 1, 41, 9, 49, 17, 57, 25
+ },
+ // Permuted-choice 1 from the key bits to yield C and D.
+ // Note that bits 8,16... are left out:
+ // They are intended for a parity check.
+ PC1_C =
+ {
+ 57, 49, 41, 33, 25, 17, 9,
+ 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27,
+ 19, 11, 3, 60, 52, 44, 36
+ },
+ PC1_D =
+ {
+ 63, 55, 47, 39, 31, 23, 15,
+ 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29,
+ 21, 13, 5, 28, 20, 12, 4
+ },
+ shifts = // Sequence of shifts used for the key schedule.
+ {
+ 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
+ },
+ // Permuted-choice 2, to pick out the bits from
+ // the CD array that generate the key schedule.
+ PC2_C =
+ {
+ 14, 17, 11, 24, 1, 5,
+ 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8,
+ 16, 7, 27, 20, 13, 2
+ },
+ PC2_D =
+ {
+ 41, 52, 31, 37, 47, 55,
+ 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53,
+ 46, 42, 50, 36, 29, 32
+ },
+ e2 = // The E-bit selection table. (see E below)
+ {
+ 32, 1, 2, 3, 4, 5,
+ 4, 5, 6, 7, 8, 9,
+ 8, 9, 10, 11, 12, 13,
+ 12, 13, 14, 15, 16, 17,
+ 16, 17, 18, 19, 20, 21,
+ 20, 21, 22, 23, 24, 25,
+ 24, 25, 26, 27, 28, 29,
+ 28, 29, 30, 31, 32, 1
+ },
+ // P is a permutation on the selected combination of
+ // the current L and key.
+ P =
+ {
+ 16, 7, 20, 21,
+ 29, 12, 28, 17,
+ 1, 15, 23, 26,
+ 5, 18, 31, 10,
+ 2, 8, 24, 14,
+ 32, 27, 3, 9,
+ 19, 13, 30, 6,
+ 22, 11, 4, 25
+ };
+ // The 8 selection functions. For some reason, they gave a 0-origin
+ // index, unlike everything else.
+ static byte[][] S =
+ {
+ {
+ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
+ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
+ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
+ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
+ }, {
+ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
+ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
+ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
+ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
+ }, {
+ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
+ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
+ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
+ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
+ }, {
+ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
+ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
+ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
+ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
+ }, {
+ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
+ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
+ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
+ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
+ }, {
+ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
+ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
+ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
+ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
+ }, {
+ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
+ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
+ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
+ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
+ }, {
+ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
+ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
+ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
+ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
+ }
+ };
+
+ // Dynamic data:
+ byte[] C = new byte[28], // The C and D arrays used to
+ D = new byte[28], // calculate the key schedule.
+ E = new byte[48], // The E bit-selection table.
+ L = new byte[32], // The current block,
+ R = new byte[32], // divided into two halves.
+ tempL = new byte[32],
+ f = new byte[32],
+ preS = new byte[48]; // The combination of the key and
+ // the input, before selection.
+ // The key schedule. Generated from the key.
+ byte[][] KS = new byte[16][48];
+
+ // Object fields:
+ String Passwd, Salt, Encrypt;
+
+ // Public methods:
+ /**
+ * Create Crypt object with no passwd or salt set. Must use setPasswd()
+ * and setSalt() before getEncryptedPasswd().
+ */
+ public Crypt() {
+ Passwd = Salt = Encrypt = "";
+ }
+
+ /**
+ * Create a Crypt object with specified salt. Use setPasswd() before
+ * getEncryptedPasswd().
+ *
+ * @param salt the salt string for encryption
+ */
+ public Crypt(String salt) {
+ Passwd = "";
+ Salt = salt;
+ Encrypt = crypt();
+ }
+
+ /**
+ * Create a Crypt object with specified passwd and salt (often the
+ * already encypted passwd). Get the encrypted result with
+ * getEncryptedPasswd().
+ *
+ * @param passwd the passwd to encrypt
+ * @param salt the salt string for encryption
+ */
+ public Crypt(String passwd, String salt) {
+ Passwd = passwd;
+ Salt = salt;
+ Encrypt = crypt();
+ }
+
+ /**
+ * Retrieve the passwd string currently being encrypted.
+ *
+ * @return the current passwd string
+ */
+ public String getPasswd() {
+ return Passwd;
+ }
+
+ /**
+ * Retrieve the salt string currently being used for encryption.
+ *
+ * @return the current salt string
+ */
+ public String getSalt() {
+ return Salt;
+ }
+
+ /**
+ * Retrieve the resulting encrypted string from the current passwd and
+ * salt settings.
+ *
+ * @return the encrypted passwd
+ */
+ public String getEncryptedPasswd() {
+ return Encrypt;
+ }
+
+ /**
+ * Set a new passwd string for encryption. Use getEncryptedPasswd() to
+ * retrieve the new result.
+ *
+ * @param passwd the new passwd string
+ */
+ public void setPasswd(String passwd) {
+ Passwd = passwd;
+ Encrypt = crypt();
+ }
+
+ /**
+ * Set a new salt string for encryption. Use getEncryptedPasswd() to
+ * retrieve the new result.
+ *
+ * @param salt the new salt string
+ */
+ public void setSalt(String salt) {
+ Salt = salt;
+ Encrypt = crypt();
+ }
+
+ // Internal crypt methods:
+ String crypt() {
+ if (Salt.length() == 0)
+ return "";
+ int i, j, pwi;
+ byte c, temp;
+ byte[] block = new byte[66], iobuf = new byte[16], salt = new byte[2], pw = Passwd.getBytes(), //jdk1.1
+ saltbytes = Salt.getBytes(); //jdk1.1
+
+ // pw = new byte[Passwd.length()], //jdk1.0.2
+ // saltbytes = new byte[Salt.length()]; //jdk1.0.2
+ //Passwd.getBytes(0,Passwd.length(),pw,0); //jdk1.0.2
+ //Salt.getBytes(0,Salt.length(),saltbytes,0); //jdk1.0.2
+
+ salt[0] = saltbytes[0];
+ salt[1] = (saltbytes.length > 1) ? saltbytes[1] : 0;
+
+ for (i = 0; i < 66; i++)
+ block[i] = 0;
+
+ for (i = 0, pwi = 0; (pwi < pw.length) && (i < 64); pwi++, i++) {
+ for (j = 0; j < 7; j++, i++) {
+ block[i] = (byte) ((pw[pwi] >> (6 - j)) & 1);
+ }
+ }
+
+ setkey(block);
+
+ for (i = 0; i < 66; i++)
+ block[i] = 0;
+
+ for (i = 0; i < 2; i++) {
+ c = salt[i];
+ iobuf[i] = c;
+ if (c > 'Z')
+ c -= 6;
+ if (c > '9')
+ c -= 7;
+ c -= '.';
+ for (j = 0; j < 6; j++) {
+ if (((c >> j) & 1) != 0) {
+ temp = E[6 * i + j];
+ E[6 * i + j] = E[6 * i + j + 24];
+ E[6 * i + j + 24] = temp;
+ }
+ }
+ }
+
+ for (i = 0; i < 25; i++) {
+ encrypt(block, 0);
+ }
+
+ for (i = 0; i < 11; i++) {
+ c = 0;
+ for (j = 0; j < 6; j++) {
+ c <<= 1;
+ c |= block[6 * i + j];
+ }
+ c += '.';
+ if (c > '9')
+ c += 7;
+ if (c > 'Z')
+ c += 6;
+ iobuf[i + 2] = c;
+ }
+
+ iobuf[i + 2] = 0;
+ if (iobuf[1] == 0)
+ iobuf[1] = iobuf[0];
+
+ return new String(iobuf); //jdk1.1
+ //return new String(iobuf,0); //jdk1.0.2
+ }
+
+ void setkey(byte[] key) // Set up the key schedule from the key.
+ {
+ int i, j, k;
+ byte t;
+
+ // First, generate C and D by permuting the key. The low order bit
+ // of each 8-bit char is not used, so C and D are only 28 bits apiece.
+ for (i = 0; i < 28; i++) {
+ C[i] = key[PC1_C[i] - 1];
+ D[i] = key[PC1_D[i] - 1];
+ }
+
+ // To generate Ki, rotate C and D according to schedule
+ // and pick up a permutation using PC2.
+ for (i = 0; i < 16; i++) {
+ // rotate.
+ for (k = 0; k < shifts[i]; k++) {
+ t = C[0];
+ for (j = 0; j < 27; j++)
+ C[j] = C[j + 1];
+ C[27] = t;
+ t = D[0];
+ for (j = 0; j < 27; j++)
+ D[j] = D[j + 1];
+ D[27] = t;
+ }
+
+ // get Ki. Note C and D are concatenated.
+ for (j = 0; j < 24; j++) {
+ KS[i][j] = C[PC2_C[j] - 1];
+ KS[i][j + 24] = D[PC2_D[j] - 29];
+ }
+ }
+
+ for (i = 0; i < 48; i++) {
+ E[i] = e2[i];
+ }
+ }
+
+ // The payoff: encrypt a block.
+ void encrypt(byte[] block, int edflag) {
+ int i, j, ii, t;
+ byte k;
+
+ // First, permute the bits in the input
+ //for (j = 0; j < 64; j++)
+ //{
+ // L[j] = block[IP[j]-1];
+ //}
+ for (j = 0; j < 32; j++)
+ L[j] = block[IP[j] - 1];
+ for (j = 32; j < 64; j++)
+ R[j - 32] = block[IP[j] - 1];
+
+ // Perform an encryption operation 16 times.
+ for (ii = 0; ii < 16; ii++) {
+ i = ii;
+ // Save the R array, which will be the new L.
+ for (j = 0; j < 32; j++)
+ tempL[j] = R[j];
+ // Expand R to 48 bits using the E selector;
+ // exclusive-or with the current key bits.
+ for (j = 0; j < 48; j++)
+ preS[j] = (byte) (R[E[j] - 1] ^ KS[i][j]);
+
+ // The pre-select bits are now considered in 8 groups of
+ // 6 bits each. The 8 selection functions map these 6-bit
+ // quantities into 4-bit quantities and the results permuted
+ // to make an f(R, K). The indexing into the selection functions
+ // is peculiar; it could be simplified by rewriting the tables.
+ for (j = 0; j < 8; j++) {
+ t = 6 * j;
+ k = S[j][(preS[t] << 5) +
+ (preS[t + 1] << 3) +
+ (preS[t + 2] << 2) +
+ (preS[t + 3] << 1) +
+ (preS[t + 4]) +
+ (preS[t + 5] << 4)];
+ t = 4 * j;
+ f[t] = (byte) ((k >> 3) & 1);
+ f[t + 1] = (byte) ((k >> 2) & 1);
+ f[t + 2] = (byte) ((k >> 1) & 1);
+ f[t + 3] = (byte) ((k) & 1);
+ }
+
+ // The new R is L ^ f(R, K).
+ // The f here has to be permuted first, though.
+ for (j = 0; j < 32; j++) {
+ R[j] = (byte) (L[j] ^ f[P[j] - 1]);
+ }
+
+ // Finally, the new L (the original R) is copied back.
+ for (j = 0; j < 32; j++) {
+ L[j] = tempL[j];
+ }
+ }
+
+ // The output L and R are reversed.
+ for (j = 0; j < 32; j++) {
+ k = L[j];
+ L[j] = R[j];
+ R[j] = k;
+ }
+
+ // The final output gets the inverse permutation of the very original.
+ for (j = 0; j < 64; j++) {
+ //block[j] = L[FP[j]-1];
+ block[j] = (FP[j] > 32) ? R[FP[j] - 33] : L[FP[j] - 1];
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/DNPattern.java b/base/server/cms/src/com/netscape/cms/authentication/DNPattern.java
new file mode 100644
index 000000000..ccee3b512
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/DNPattern.java
@@ -0,0 +1,216 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.StringReader;
+import java.util.Vector;
+
+import netscape.ldap.LDAPEntry;
+
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.base.EBaseException;
+
+/**
+ * class for parsing a DN pattern used to construct a certificate
+ * subject name from ldap attributes and dn.
+ * <p>
+ *
+ * dnpattern is a string representing a subject name pattern to formulate from the directory attributes and entry dn. If
+ * empty or not set, the ldap entry DN will be used as the certificate subject name.
+ * <p>
+ *
+ * The syntax is
+ *
+ * <pre>
+ * dnPattern := rdnPattern *[ "," rdnPattern ]
+ * rdnPattern := avaPattern *[ "+" avaPattern ]
+ * avaPattern := name "=" value |
+ * name "=" "$attr" "." attrName [ "." attrNumber ] |
+ * name "=" "$dn" "." attrName [ "." attrNumber ] |
+ * "$dn" "." "$rdn" "." number
+ * </pre>
+ *
+ * <pre>
+ * Example1: <i>E=$attr.mail.1, CN=$attr.cn, OU=$dn.ou.2, O=$dn.o, C=US </i>
+ * Ldap entry: dn: UID=jjames, OU=IS, OU=people, O=acme.org
+ * Ldap attributes: cn: Jesse James
+ * Ldap attributes: mail: jjames@acme.org
+ * <p>
+ * The subject name formulated will be : <br>
+ * E=jjames@acme.org, CN=Jesse James, OU=people, O=acme.org, C=US
+ * <p>
+ * E = the first 'mail' ldap attribute value in user's entry. <br>
+ * CN = the (first) 'cn' ldap attribute value in the user's entry. <br>
+ * OU = the second 'ou' value in the user's entry DN. <br>
+ * O = the (first) 'o' value in the user's entry DN. <br>
+ * C = the string "US"
+ * <p>
+ * Example2: <i>E=$attr.mail.1, CN=$attr.cn, OU=$dn.ou.2, O=$dn.o, C=US</i>
+ * Ldap entry: dn: UID=jjames, OU=IS+OU=people, O=acme.org
+ * Ldap attributes: cn: Jesse James
+ * Ldap attributes: mail: jjames@acme.org
+ * <p>
+ * The subject name formulated will be : <br>
+ * E=jjames@acme.org, CN=Jesse James, OU=people, O=acme.org, C=US
+ * <p>
+ * E = the first 'mail' ldap attribute value in user's entry. <br>
+ * CN = the (first) 'cn' ldap attribute value in the user's entry. <br>
+ * OU = the second 'ou' value in the user's entry DN. note multiple AVAs
+ * in a RDN in this example. <br>
+ * O = the (first) 'o' value in the user's entry DN. <br>
+ * C = the string "US"
+ * <p>
+ * </pre>
+ *
+ * <pre>
+ * Example3: <i>CN=$attr.cn, $rdn.2, O=$dn.o, C=US</i>
+ * Ldap entry: dn: UID=jjames, OU=IS+OU=people, O=acme.org
+ * Ldap attributes: cn: Jesse James
+ * Ldap attributes: mail: jjames@acme.org
+ * <p>
+ * The subject name formulated will be : <br>
+ * CN=Jesse James, OU=IS+OU=people, O=acme.org, C=US
+ * <p>
+ * CN = the (first) 'cn' ldap attribute value in the user's entry. <br>
+ * followed by the second RDN in the user's entry DN. <br>
+ * O = the (first) 'o' value in the user's entry DN. <br>
+ * C = the string "US"
+ * <p>
+ * Example4: <i>CN=$attr.cn, OU=$dn.ou.2+OU=$dn.ou.1, O=$dn.o, C=US</i>
+ * Ldap entry: dn: UID=jjames, OU=IS+OU=people, O=acme.org
+ * Ldap attributes: cn: Jesse James
+ * Ldap attributes: mail: jjames@acme.org
+ * <p>
+ * The subject name formulated will be : <br>
+ * CN=Jesse James, OU=people+OU=IS, O=acme.org, C=US
+ * <p>
+ * CN = the (first) 'cn' ldap attribute value in the user's entry. <br>
+ * OU = the second 'ou' value in the user's entry DN followed by the
+ * first 'ou' value in the user's entry. note multiple AVAs
+ * in a RDN in this example. <br>
+ * O = the (first) 'o' value in the user's entry DN. <br>
+ * C = the string "US"
+ * <p>
+ * </pre>
+ *
+ * If an attribute or subject DN component does not exist the attribute is skipped.
+ *
+ * @version $Revision$, $Date$
+ */
+public class DNPattern {
+
+ /* ldap attributes to retrieve */
+ private String[] mLdapAttrs = null;
+
+ /* rdn patterns */
+ protected RDNPattern[] mRDNPatterns = null;
+
+ /* original pattern string */
+ protected String mPatternString = null;
+
+ protected String mTestDN = null;
+
+ /**
+ * Construct a DN pattern by parsing a pattern string.
+ *
+ * @param pattern the DN pattern
+ * @exception EBaseException If parsing error occurs.
+ */
+ public DNPattern(String pattern)
+ throws EAuthException {
+ if (pattern == null || pattern.equals("")) {
+ // create an attribute list that is the dn.
+ mLdapAttrs = new String[] { "dn" };
+ } else {
+ mPatternString = pattern;
+ PushbackReader in = new PushbackReader(new StringReader(pattern));
+
+ parse(in);
+ }
+ }
+
+ public DNPattern(PushbackReader in)
+ throws EAuthException {
+ parse(in);
+ }
+
+ private void parse(PushbackReader in)
+ throws EAuthException {
+ Vector<RDNPattern> rdnPatterns = new Vector<RDNPattern>();
+ RDNPattern rdnPattern = null;
+ int lastChar = -1;
+
+ do {
+ rdnPattern = new RDNPattern(in);
+ rdnPatterns.addElement(rdnPattern);
+ try {
+ lastChar = in.read();
+ } catch (IOException e) {
+ throw new EAuthException("CMS_AUTHENTICATION_INTERNAL_ERROR", e.toString());
+ }
+ } while (lastChar == ',');
+
+ mRDNPatterns = new RDNPattern[rdnPatterns.size()];
+ rdnPatterns.copyInto(mRDNPatterns);
+
+ Vector<String> ldapAttrs = new Vector<String>();
+
+ for (int i = 0; i < mRDNPatterns.length; i++) {
+ String[] rdnAttrs = mRDNPatterns[i].getLdapAttrs();
+
+ if (rdnAttrs != null && rdnAttrs.length > 0)
+ for (int j = 0; j < rdnAttrs.length; j++)
+ ldapAttrs.addElement(rdnAttrs[j]);
+ }
+ mLdapAttrs = new String[ldapAttrs.size()];
+ ldapAttrs.copyInto(mLdapAttrs);
+ }
+
+ /**
+ * Form a Ldap v3 DN string from results of a ldap search.
+ *
+ * @param entry LDAPentry from a ldap search
+ * @return Ldap v3 DN string to use for a subject name.
+ */
+ public String formDN(LDAPEntry entry)
+ throws EAuthException {
+ StringBuffer formedDN = new StringBuffer();
+
+ for (int i = 0; i < mRDNPatterns.length; i++) {
+ if (mTestDN != null)
+ mRDNPatterns[i].mTestDN = mTestDN;
+ String rdn = mRDNPatterns[i].formRDN(entry);
+
+ if (rdn != null) {
+ if (rdn != null && rdn.length() != 0) {
+ if (formedDN.length() != 0)
+ formedDN.append(",");
+ formedDN.append(rdn);
+ }
+ }
+ }
+ //System.out.println("formed DN "+formedDN.toString());
+ return formedDN.toString();
+ }
+
+ public String[] getLdapAttrs() {
+ return mLdapAttrs.clone();
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/DirBasedAuthentication.java b/base/server/cms/src/com/netscape/cms/authentication/DirBasedAuthentication.java
new file mode 100644
index 000000000..f2d09df9e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/DirBasedAuthentication.java
@@ -0,0 +1,675 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+// ldap java sdk
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.authentication.EFormSubjectDN;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+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.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Abstract class for directory based authentication managers
+ * Uses a pattern for formulating subject names.
+ * The pattern is read from configuration file.
+ * Syntax of the pattern is described in the init() method.
+ *
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public abstract class DirBasedAuthentication
+ implements IAuthManager, IExtendedPluginInfo {
+
+ protected static final String USER_DN = "userDN";
+
+ /* configuration parameter keys */
+ protected static final String PROP_LDAP = "ldap";
+ protected static final String PROP_BASEDN = "basedn";
+ protected static final String PROP_DNPATTERN = "dnpattern";
+ protected static final String PROP_LDAPSTRINGATTRS = "ldapStringAttributes";
+ protected static final String PROP_LDAPBYTEATTRS = "ldapByteAttributes";
+
+ // members
+
+ /* name of this authentication manager instance */
+ protected String mName = null;
+
+ /* name of the authentication manager plugin */
+ protected String mImplName = null;
+
+ /* configuration store */
+ protected IConfigStore mConfig;
+
+ /* ldap configuration sub-store */
+ protected IConfigStore mLdapConfig;
+
+ /* ldap base dn */
+ protected String mBaseDN = null;
+
+ /* factory of anonymous ldap connections */
+ protected ILdapConnFactory mConnFactory = null;
+
+ /* the system logger */
+ protected ILogger mLogger = CMS.getLogger();
+
+ /* the subject DN pattern */
+ protected DNPattern mPattern = null;
+
+ /* the list of LDAP attributes with string values to retrieve to
+ * save in the auth token including ones from the dn pattern. */
+ protected String[] mLdapStringAttrs = null;
+
+ /* the list of LDAP attributes with byte[] values to retrive to save
+ * in authtoken. */
+ protected String[] mLdapByteAttrs = null;
+
+ /* the combined list of LDAP attriubutes to retrieve*/
+ protected String[] mLdapAttrs = null;
+
+ /* default dn pattern if left blank or not set in the config */
+ protected static String DEFAULT_DNPATTERN =
+ "E=$attr.mail, CN=$attr.cn, O=$dn.o, C=$dn.c";
+
+ /* Vector of extendedPluginInfo strings */
+ protected static Vector<String> mExtendedPluginInfo = null;
+
+ static {
+ mExtendedPluginInfo = new Vector<String>();
+ mExtendedPluginInfo.add(PROP_DNPATTERN + ";string;Template for cert" +
+ " Subject Name. ($dn.xxx - get value from user's LDAP " +
+ "DN. $attr.yyy - get value from LDAP attributes in " +
+ "user's entry.) Default: " + DEFAULT_DNPATTERN);
+ mExtendedPluginInfo.add(PROP_LDAPSTRINGATTRS + ";string;" +
+ "Comma-separated list of LDAP attributes to copy from " +
+ "the user's LDAP entry into the AuthToken. e.g use " +
+ "'mail' to copy user's email address for subjectAltName");
+ mExtendedPluginInfo.add(PROP_LDAPBYTEATTRS + ";string;" +
+ "Comma-separated list of binary LDAP attributes to copy" +
+ " from the user's LDAP entry into the AuthToken");
+ mExtendedPluginInfo.add("ldap.ldapconn.host;string,required;" +
+ "LDAP host to connect to");
+ mExtendedPluginInfo.add("ldap.ldapconn.port;number,required;" +
+ "LDAP port number (use 389, or 636 if SSL)");
+ mExtendedPluginInfo.add("ldap.ldapconn.secureConn;boolean;" +
+ "Use SSL to connect to directory?");
+ mExtendedPluginInfo.add("ldap.ldapconn.version;choice(3,2);" +
+ "LDAP protocol version");
+ mExtendedPluginInfo.add("ldap.basedn;string,required;Base DN to start searching " +
+ "under. If your user's DN is 'uid=jsmith, o=company', you " +
+ "might want to use 'o=company' here");
+ mExtendedPluginInfo.add("ldap.minConns;number;number of connections " +
+ "to keep open to directory server. Default 5.");
+ mExtendedPluginInfo.add("ldap.maxConns;number;when needed, connection " +
+ "pool can grow to this many (multiplexed) connections. Default 1000.");
+ }
+
+ /**
+ * Default constructor, initialization must follow.
+ */
+ public DirBasedAuthentication() {
+ }
+
+ /**
+ * Initializes the UidPwdDirBasedAuthentication auth manager.
+ *
+ * Takes the following configuration parameters: <br>
+ *
+ * <pre>
+ * ldap.basedn - the ldap base dn.
+ * ldap.ldapconn.host - the ldap host.
+ * ldap.ldapconn.port - the ldap port
+ * ldap.ldapconn.secureConn - whether port should be secure
+ * ldap.minConns - minimum connections
+ * ldap.maxConns - max connections
+ * dnpattern - dn pattern.
+ * </pre>
+ * <p>
+ * <i><b>dnpattern</b></i> is a string representing a subject name pattern to formulate from the directory
+ * attributes and entry dn. If empty or not set, the ldap entry DN will be used as the certificate subject name.
+ * <p>
+ * The syntax is
+ *
+ * <pre>
+ * dnpattern = SubjectNameComp *[ "," SubjectNameComp ]
+ *
+ * SubjectNameComponent = DnComp | EntryComp | ConstantComp
+ * DnComp = CertAttr "=" "$dn" "." DnAttr "." Num
+ * EntryComp = CertAttr "=" "$attr" "." EntryAttr "." Num
+ * ConstantComp = CertAttr "=" Constant
+ * DnAttr = an attribute in the Ldap entry dn
+ * EntryAttr = an attribute in the Ldap entry
+ * CertAttr = a Component in the Certificate Subject Name
+ * (multiple AVA in one RDN not supported)
+ * Num = the nth value of tha attribute in the dn or entry.
+ * Constant = Constant String, with any accepted ldap string value.
+ *
+ * </pre>
+ * <p>
+ * <b>Example:</b>
+ *
+ * <pre>
+ * dnpattern:
+ * E=$attr.mail.1, CN=$attr.cn, OU=$attr.ou.2, O=$dn.o, C=US
+ * <br>
+ * Ldap entry dn:
+ * UID=joesmith, OU=people, O=Acme.com
+ * <br>
+ * Ldap attributes:
+ * cn: Joe Smith
+ * sn: Smith
+ * mail: joesmith@acme.com
+ * mail: joesmith@redhat.com
+ * ou: people
+ * ou: IS
+ * <i>etc.</i>
+ * </pre>
+ * <p>
+ * The subject name formulated in the cert will be : <br>
+ *
+ * <pre>
+ * E=joesmith@acme.com, CN=Joe Smith, OU=Human Resources, O=Acme.com, C=US
+ *
+ * E = the first 'mail' ldap attribute value in user's entry - joesmithe@acme.com
+ * CN = the (first) 'cn' ldap attribute value in the user's entry - Joe Smith
+ * OU = the second 'ou' value in the ldap entry - IS
+ * O = the (first) 'o' value in the user's entry DN - "Acme.com"
+ * C = the constant string "US"
+ * </pre>
+ *
+ * @param name The name for this authentication manager instance.
+ * @param implName The name of the authentication manager plugin.
+ * @param config - The configuration store for this instance.
+ * @exception EBaseException If an error occurs during initialization.
+ */
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ init(name, implName, config, true);
+ }
+
+ public void init(String name, String implName, IConfigStore config, boolean needBaseDN)
+ throws EBaseException {
+ mName = name;
+ mImplName = implName;
+ mConfig = config;
+
+ /* initialize ldap server configuration */
+ mLdapConfig = mConfig.getSubStore(PROP_LDAP);
+ if (needBaseDN)
+ mBaseDN = mLdapConfig.getString(PROP_BASEDN);
+ if (needBaseDN && ((mBaseDN == null) || (mBaseDN.length() == 0) || (mBaseDN.trim().equals(""))))
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", "basedn"));
+ mConnFactory = CMS.getLdapAnonConnFactory();
+ mConnFactory.init(mLdapConfig);
+
+ /* initialize dn pattern */
+ String pattern = mConfig.getString(PROP_DNPATTERN, null);
+
+ if (pattern == null || pattern.length() == 0)
+ pattern = DEFAULT_DNPATTERN;
+ mPattern = new DNPattern(pattern);
+ String[] patternLdapAttrs = mPattern.getLdapAttrs();
+
+ /* initialize ldap string attribute list */
+ String ldapStringAttrs = mConfig.getString(PROP_LDAPSTRINGATTRS, null);
+
+ if (ldapStringAttrs == null) {
+ mLdapStringAttrs = patternLdapAttrs;
+ } else {
+ StringTokenizer pAttrs =
+ new StringTokenizer(ldapStringAttrs, ",", false);
+ int begin = 0;
+
+ if (patternLdapAttrs != null && patternLdapAttrs.length > 0) {
+ mLdapStringAttrs = new String[
+ patternLdapAttrs.length + pAttrs.countTokens()];
+ System.arraycopy(patternLdapAttrs, 0,
+ mLdapStringAttrs, 0, patternLdapAttrs.length);
+ begin = patternLdapAttrs.length;
+ } else {
+ mLdapStringAttrs = new String[pAttrs.countTokens()];
+ }
+ for (int i = begin; i < mLdapStringAttrs.length; i++) {
+ mLdapStringAttrs[i] = ((String) pAttrs.nextElement()).trim();
+ }
+ }
+
+ /* initialize ldap byte[] attribute list */
+ String ldapByteAttrs = mConfig.getString(PROP_LDAPBYTEATTRS, null);
+
+ if (ldapByteAttrs == null) {
+ mLdapByteAttrs = new String[0];
+ } else {
+ StringTokenizer byteAttrs =
+ new StringTokenizer(ldapByteAttrs, ",", false);
+
+ mLdapByteAttrs = new String[byteAttrs.countTokens()];
+ for (int j = 0; j < mLdapByteAttrs.length; j++) {
+ mLdapByteAttrs[j] = ((String) byteAttrs.nextElement()).trim();
+ }
+ }
+
+ /* make the combined list */
+ mLdapAttrs =
+ new String[mLdapStringAttrs.length + mLdapByteAttrs.length];
+ System.arraycopy(mLdapStringAttrs, 0, mLdapAttrs,
+ 0, mLdapStringAttrs.length);
+ System.arraycopy(mLdapByteAttrs, 0, mLdapAttrs,
+ mLdapStringAttrs.length, mLdapByteAttrs.length);
+
+ log(ILogger.LL_INFO, CMS.getLogMessage("CMS_AUTH_INIT_DONE"));
+ }
+
+ /**
+ * gets the name of this authentication manager instance
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * gets the plugin name of this authentication manager.
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ /**
+ * Authenticates user through LDAP by a set of credentials.
+ * Resulting AuthToken a TOKEN_CERTINFO field of a X509CertInfo
+ * <p>
+ *
+ * @param authCred Authentication credentials, CRED_UID and CRED_PWD.
+ * @return A AuthToken with a TOKEN_SUBJECT of X500name type.
+ * @exception com.netscape.certsrv.authentication.EMissingCredential
+ * If a required authentication credential is missing.
+ * @exception com.netscape.certsrv.authentication.EInvalidCredentials
+ * If credentials failed authentication.
+ * @exception com.netscape.certsrv.base.EBaseException
+ * If an internal error occurred.
+ * @see com.netscape.certsrv.authentication.AuthToken
+ */
+ public IAuthToken authenticate(IAuthCredentials authCred)
+ throws EMissingCredential, EInvalidCredentials, EBaseException {
+ String userdn = null;
+ LDAPConnection conn = null;
+ AuthToken authToken = new AuthToken(this);
+
+ try {
+ if (mConnFactory == null) {
+ conn = null;
+ } else {
+ conn = mConnFactory.getConn();
+ }
+
+ // authenticate the user and get a user entry.
+ userdn = authenticate(conn, authCred, authToken);
+ authToken.set(USER_DN, userdn);
+
+ // formulate the cert info.
+ // set each seperatly since otherwise they won't serialize
+ // in the request queue.
+ X509CertInfo certInfo = new X509CertInfo();
+
+ formCertInfo(conn, userdn, certInfo, authToken);
+
+ // set subject name.
+ try {
+ CertificateSubjectName subjectname = (CertificateSubjectName)
+ certInfo.get(X509CertInfo.SUBJECT);
+
+ if (subjectname != null)
+ authToken.set(AuthToken.TOKEN_CERT_SUBJECT,
+ subjectname.toString());
+ } // error means it's not set.
+ catch (CertificateException e) {
+ } catch (IOException e) {
+ }
+
+ // set validity if any
+ try {
+ CertificateValidity validity = (CertificateValidity)
+ certInfo.get(X509CertInfo.VALIDITY);
+
+ if (validity != null) {
+ // the gets throws IOException but only if attribute
+ // not recognized. In these cases they are always.
+ authToken.set(AuthToken.TOKEN_CERT_NOTBEFORE,
+ (Date) validity.get(CertificateValidity.NOT_BEFORE));
+ authToken.set(AuthToken.TOKEN_CERT_NOTAFTER,
+ (Date) validity.get(CertificateValidity.NOT_AFTER));
+ }
+ } // error means it's not set.
+ catch (CertificateException e) {
+ } catch (IOException e) {
+ }
+
+ // set extensions if any.
+ try {
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+
+ if (extensions != null)
+ authToken.set(AuthToken.TOKEN_CERT_EXTENSIONS, extensions);
+ } // error means it's not set.
+ catch (CertificateException e) {
+ } catch (IOException e) {
+ }
+
+ } finally {
+ if (conn != null)
+ mConnFactory.returnConn(conn);
+ }
+
+ return authToken;
+ }
+
+ /**
+ * get the list of required credentials.
+ *
+ * @return list of required credentials as strings.
+ */
+ public abstract String[] getRequiredCreds();
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public abstract String[] getConfigParams();
+
+ /**
+ * disconnects the ldap connections
+ */
+ public void shutdown() {
+ try {
+ if (mConnFactory != null) {
+ mConnFactory.reset();
+ }
+ } catch (ELdapException e) {
+ // ignore
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_SHUTDOWN_ERROR", e.toString()));
+ }
+ }
+
+ /**
+ * Gets the configuration substore used by this authentication manager
+ *
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Authenticates a user through directory based a set of credentials.
+ *
+ * @param authCreds The authentication credentials.
+ * @return The user's ldap entry dn.
+ * @exception EInvalidCredentials If the uid and password are not valid
+ * @exception EBaseException If an internal error occurs.
+ */
+ protected abstract String authenticate(
+ LDAPConnection conn, IAuthCredentials authCreds, AuthToken token)
+ throws EBaseException;
+
+ /**
+ * Formulate the cert info.
+ *
+ * @param conn A LDAP Connection authenticated to user to use.
+ * @param userdn The user's dn.
+ * @param certinfo A certinfo object to fill.
+ * @param token A authentication token to fill.
+ * @exception EBaseException If an internal error occurs.
+ */
+ protected void formCertInfo(LDAPConnection conn,
+ String userdn,
+ X509CertInfo certinfo,
+ AuthToken token)
+ throws EBaseException {
+ String dn = null;
+ // get ldap attributes to retrieve.
+ String[] attrs = getLdapAttrs();
+
+ // retrieve the attributes.
+ try {
+ if (conn != null) {
+ LDAPEntry entry = null;
+ LDAPSearchResults results =
+ conn.search(userdn, LDAPv2.SCOPE_BASE, "objectclass=*",
+ attrs, false);
+
+ if (!results.hasMoreElements()) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_NO_ATTR_ERROR"));
+ throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_LDAPATTRIBUTES_NOT_FOUND"));
+ }
+ entry = results.next();
+
+ // formulate the subject dn
+ try {
+ dn = formSubjectName(entry);
+ } catch (EBaseException e) {
+ //e.printStackTrace();
+ throw e;
+ }
+ // Put selected values from the entry into the token
+ setAuthTokenValues(entry, token);
+ } else {
+ dn = userdn;
+ }
+
+ // add anything else in cert info such as validity, extensions
+ // (nothing now)
+
+ // pack the dn into X500name and set subject name.
+ if (dn.length() == 0) {
+ EBaseException ex =
+ new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_EMPTY_DN_FORMED", mName));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_NO_DN_ERROR", ex.toString()));
+ throw ex;
+ }
+ X500Name subjectdn = new X500Name(dn);
+
+ certinfo.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(subjectdn));
+ } catch (LDAPException e) {
+ switch (e.getLDAPResultCode()) {
+ case LDAPException.SERVER_DOWN:
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_NO_AUTH_ATTR_ERROR"));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), "" + conn.getPort()));
+
+ case LDAPException.NO_SUCH_OBJECT:
+ case LDAPException.LDAP_PARTIAL_RESULTS:
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_NO_USER_ENTRY_ERROR", userdn));
+
+ // fall to below.
+ default:
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_ERROR", e.toString()));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_OTHER_LDAP_EXCEPTION",
+ e.errorCodeToString()));
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_CREATE_SUBJECT_ERROR", userdn, e.getMessage()));
+ throw new EFormSubjectDN(CMS.getUserMessage("CMS_AUTHENTICATION_FORM_SUBJECTDN_ERROR"));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_CREATE_CERTINFO_ERROR", userdn, e.getMessage()));
+ throw new EFormSubjectDN(CMS.getUserMessage("CMS_AUTHENTICATION_FORM_SUBJECTDN_ERROR"));
+ }
+ }
+
+ /**
+ * Copy values from the LDAPEntry into the AuthToken. The
+ * list of values that should be store this way is given in
+ * a the ldapAttributes configuration parameter.
+ */
+ protected void setAuthTokenValues(LDAPEntry e, AuthToken tok) {
+ for (int i = 0; i < mLdapStringAttrs.length; i++)
+ setAuthTokenStringValue(mLdapStringAttrs[i], e, tok);
+ for (int j = 0; j < mLdapByteAttrs.length; j++)
+ setAuthTokenByteValue(mLdapByteAttrs[j], e, tok);
+ }
+
+ protected void setAuthTokenStringValue(
+ String name, LDAPEntry entry, AuthToken tok) {
+ LDAPAttribute values = entry.getAttribute(name);
+
+ if (values == null)
+ return;
+
+ Vector<String> v = new Vector<String>();
+ @SuppressWarnings("unchecked")
+ Enumeration<String> e = values.getStringValues();
+
+ while (e.hasMoreElements()) {
+ v.addElement(e.nextElement());
+ }
+
+ String a[] = new String[v.size()];
+
+ v.copyInto(a);
+
+ tok.set(name, a);
+ }
+
+ protected void setAuthTokenByteValue(
+ String name, LDAPEntry entry, AuthToken tok) {
+ LDAPAttribute values = entry.getAttribute(name);
+
+ if (values == null)
+ return;
+
+ Vector<byte[]> v = new Vector<byte[]>();
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> e = values.getByteValues();
+
+ while (e.hasMoreElements()) {
+ v.addElement(e.nextElement());
+ }
+
+ byte[][] a = new byte[v.size()][];
+
+ v.copyInto(a);
+
+ tok.set(name, a);
+ }
+
+ /**
+ * Return a list of LDAP attributes with String values to retrieve.
+ * Subclasses can override to return any set of attributes.
+ *
+ * @return Array of LDAP attributes to retrieve from the directory.
+ */
+ protected String[] getLdapAttrs() {
+ return mLdapAttrs;
+ }
+
+ /**
+ * Return a list of LDAP attributes with byte[] values to retrieve.
+ * Subclasses can override to return any set of attributes.
+ *
+ * @return Array of LDAP attributes to retrieve from the directory.
+ */
+ protected String[] getLdapByteAttrs() {
+ return mLdapByteAttrs;
+ }
+
+ /**
+ * Formulate the subject name
+ *
+ * @param entry The LDAP entry
+ * @return The subject name string.
+ * @exception EBaseException If an internal error occurs.
+ */
+ protected String formSubjectName(LDAPEntry entry)
+ throws EAuthException {
+ if (mPattern.mPatternString == null)
+ return entry.getDN();
+
+ /*
+ if (mTestDNString != null) {
+ mPattern.mTestDN = mTestDNString;
+ //System.out.println("Set DNPattern.mTestDN to "+mPattern.mTestDN);
+ }
+ */
+
+ String dn = mPattern.formDN(entry);
+
+ CMS.debug("DirBasedAuthentication: formed DN '" + dn + "'");
+ return dn;
+ }
+
+ /**
+ * Logs a message for this class in the system log file.
+ *
+ * @param level The log level.
+ * @param msg The message to log.
+ * @see com.netscape.certsrv.logging.ILogger
+ */
+ protected void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHENTICATION,
+ level, msg);
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] s = Utils.getStringArrayFromVector(mExtendedPluginInfo);
+
+ return s;
+
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/FlatFileAuth.java b/base/server/cms/src/com/netscape/cms/authentication/FlatFileAuth.java
new file mode 100644
index 000000000..81537f707
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/FlatFileAuth.java
@@ -0,0 +1,686 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+// ldap java sdk
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+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.base.IExtendedPluginInfo;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This represents the authentication manager that authenticates
+ * user against a file where id, and password are stored.
+ *
+ * @version $Revision$, $Date$
+ */
+public class FlatFileAuth
+ implements IProfileAuthenticator, IExtendedPluginInfo {
+
+ /* configuration parameter keys */
+ protected static final String PROP_FILENAME = "fileName";
+ protected static final String PROP_KEYATTRIBUTES = "keyAttributes";
+ protected static final String PROP_AUTHATTRS = "authAttributes";
+ protected static final String PROP_DEFERONFAILURE = "deferOnFailure";
+
+ protected String mFilename = "config/pwfile";
+ protected long mFileLastRead = 0;
+ protected String mKeyAttributes = "UID";
+ protected String mAuthAttrs = "PWD";
+ protected boolean mDeferOnFailure = true;
+ private static final String DATE_PATTERN = "yyyy-MM-dd-HH-mm-ss";
+ private static SimpleDateFormat mDateFormat = new SimpleDateFormat(DATE_PATTERN);
+
+ protected static String[] mConfigParams =
+ new String[] {
+ PROP_FILENAME,
+ PROP_KEYATTRIBUTES,
+ PROP_AUTHATTRS,
+ PROP_DEFERONFAILURE
+ };
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String s[] = {
+ PROP_FILENAME + ";string;Pathname of password file",
+ PROP_KEYATTRIBUTES + ";string;Comma-separated list of attributes" +
+ " which together form a unique identifier for the user",
+ PROP_AUTHATTRS + ";string;Comma-separated list of attributes" +
+ " which are used for further authentication",
+ PROP_DEFERONFAILURE + ";boolean;if user is not found, defer the " +
+ "request to the queue for manual-authentication (true), or " +
+ "simply rejected the request (false)"
+ };
+
+ return s;
+ }
+
+ /** name of this authentication manager instance */
+ protected String mName = null;
+
+ protected String FFAUTH = "FlatFileAuth";
+
+ /** name of the authentication manager plugin */
+ protected String mImplName = null;
+
+ /** configuration store */
+ protected IConfigStore mConfig = null;
+
+ /** system logger */
+ protected ILogger mLogger = CMS.getLogger();
+
+ /**
+ * This array is created as to include all the requested attributes
+ *
+ */
+ String[] reqCreds = null;
+
+ String[] authAttrs = null;
+ String[] keyAttrs = null;
+
+ /**
+ * Hashtable of entries from Auth File. Hash index is the
+ * concatenation of the attributes from matchAttributes property
+ */
+ protected Hashtable<String, Hashtable<String, String>> entries = null;
+
+ /**
+ * Get the named property
+ * If the property is not set, use s as the default, and create
+ * a new value for the property in the config file.
+ *
+ * @param propertyName Property name
+ * @param s The default value of the property
+ */
+ protected String getPropertyS(String propertyName, String s)
+ throws EBaseException {
+ String p;
+
+ try {
+ p = mConfig.getString(propertyName);
+ } catch (EPropertyNotFound e) {
+ mConfig.put(propertyName, s);
+ p = s;
+ }
+ return p;
+ }
+
+ public boolean isSSLClientRequired() {
+ return false;
+ }
+
+ /**
+ * Get the named property,
+ * If the property is not set, use b as the default, and create
+ * a new value for the property in the config file.
+ *
+ * @param propertyName Property name
+ * @param b The default value of the property
+ */
+ protected boolean getPropertyB(String propertyName, boolean b)
+ throws EBaseException {
+ boolean p;
+
+ try {
+ p = mConfig.getBoolean(propertyName);
+ } catch (EPropertyNotFound e) {
+ mConfig.put(propertyName, b ? "true" : "false");
+ p = b;
+ }
+ return p;
+ }
+
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ mName = name;
+ mImplName = implName;
+ mConfig = config;
+
+ try {
+ mFilename = getPropertyS(PROP_FILENAME, mFilename);
+ mKeyAttributes = getPropertyS(PROP_KEYATTRIBUTES, mKeyAttributes);
+ mAuthAttrs = getPropertyS(PROP_AUTHATTRS, mAuthAttrs);
+ mDeferOnFailure = getPropertyB(PROP_DEFERONFAILURE, mDeferOnFailure);
+ } catch (EBaseException e) {
+ return;
+ }
+
+ keyAttrs = splitOnComma(mKeyAttributes);
+ authAttrs = splitOnComma(mAuthAttrs);
+
+ String[][] stringArrays = new String[2][];
+
+ stringArrays[0] = keyAttrs;
+ stringArrays[1] = authAttrs;
+ reqCreds = unionOfStrings(stringArrays);
+
+ print("mFilename = " + mFilename);
+ print("mKeyAttributes = " + mKeyAttributes);
+ print("mAuthAttrs = " + mAuthAttrs);
+ for (int i = 0; i < stringArrays.length; i++) {
+ for (int j = 0; j < stringArrays[i].length; j++) {
+ print("stringArrays[" + i + "][" + j + "] = " + stringArrays[i][j]);
+ }
+ }
+
+ try {
+ File file = new File(mFilename);
+
+ mFileLastRead = file.lastModified();
+ entries = readFile(file, keyAttrs);
+ CMS.debug("FlatFileAuth: " + CMS.getLogMessage("CMS_AUTH_READ_ENTRIES", mFilename));
+ // printAllEntries();
+ } catch (IOException e) {
+ throw new EBaseException(mName
+ + " authentication: Could not open file " + mFilename + " (" + e.getMessage() + ")");
+ } catch (java.lang.StringIndexOutOfBoundsException ee) {
+ CMS.debug("FlatFileAuth: " + CMS.getLogMessage("OPERATION_ERROR", ee.toString()));
+ }
+
+ }
+
+ /**
+ * Log a message.
+ *
+ * @param level The logging level.
+ * @param msg The message to log.
+ */
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHENTICATION,
+ level, msg);
+ }
+
+ void print(String s) {
+ CMS.debug("FlatFileAuth: " + s);
+ }
+
+ /**
+ * Return a string array which is the union of all the string arrays
+ * passed in. The strings are treated as case sensitive
+ */
+
+ public String[] unionOfStrings(String[][] stringArrays) {
+ Hashtable<String, String> ht = new Hashtable<String, String>();
+
+ for (int i = 0; i < stringArrays.length; i++) {
+ String[] sa = stringArrays[i];
+
+ for (int j = 0; j < sa.length; j++) {
+ print("unionOfStrings: " + i + "," + j + " = " + sa[j]);
+ ht.put(sa[j], "");
+ }
+ }
+
+ String[] s = new String[ht.size()];
+ Enumeration<String> e = ht.keys();
+
+ for (int i = 0; e.hasMoreElements(); i++) {
+ s[i] = e.nextElement();
+ }
+ return s;
+
+ }
+
+ /**
+ * Split a comma-delimited String into an array of individual
+ * Strings.
+ */
+ private String[] splitOnComma(String s) {
+ print("Splitting String: " + s + " on commas");
+ StringTokenizer st = new StringTokenizer(s, ",", false);
+ String[] sa = new String[st.countTokens()];
+
+ print(" countTokens:" + st.countTokens());
+
+ for (int i = 0; i < sa.length; i++) {
+ String p = st.nextToken().trim();
+
+ print(" token " + i + " = " + p);
+ sa[i] = p;
+ }
+
+ return sa;
+ }
+
+ /**
+ * Join an array of Strings into one string, with
+ * the specified string between each string
+ */
+
+ private String joinStringArray(String[] s, String sep) {
+
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < s.length; i++) {
+ sb.append(s[i]);
+ if (i < (s.length - 1)) {
+ sb.append(sep);
+ }
+ }
+ return sb.toString();
+ }
+
+ private synchronized void updateFile(String key) {
+ try {
+ String name = writeFile(key);
+ if (name != null) {
+ File orgFile = new File(mFilename);
+ long lastModified = orgFile.lastModified();
+ File newFile = new File(name);
+ if (lastModified > mFileLastRead) {
+ mFileLastRead = lastModified;
+ } else {
+ mFileLastRead = newFile.lastModified();
+ }
+ if (orgFile.renameTo(new File(name.substring(0, name.length() - 1)))) {
+ if (!newFile.renameTo(new File(mFilename))) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("RENAME_FILE_ERROR", name, mFilename));
+ File file = new File(name.substring(0, name.length() - 1));
+ file.renameTo(new File(mFilename));
+ }
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("RENAME_FILE_ERROR", mFilename,
+ name.substring(0, name.length() - 1)));
+ }
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("FILE_ERROR", e.getMessage()));
+ }
+ }
+
+ private String writeFile(String key) {
+ BufferedReader reader = null;
+ BufferedWriter writer = null;
+ String name = null;
+ boolean commentOutNextLine = false;
+ boolean done = false;
+ String line = null;
+ try {
+ reader = new BufferedReader(new FileReader(mFilename));
+ name = mFilename + "." + mDateFormat.format(new Date()) + "~";
+ writer = new BufferedWriter(new FileWriter(name));
+ if (reader != null && writer != null) {
+ while ((line = reader.readLine()) != null) {
+ if (commentOutNextLine) {
+ writer.write("#");
+ commentOutNextLine = false;
+ }
+ if (line.indexOf(key) > -1) {
+ writer.write("#");
+ commentOutNextLine = true;
+ }
+ writer.write(line);
+ writer.newLine();
+ }
+ done = true;
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("FILE_ERROR", e.getMessage()));
+ }
+
+ try {
+ if (reader != null) {
+ reader.close();
+ }
+ if (writer != null) {
+ writer.flush();
+ writer.close();
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("FILE_ERROR", e.getMessage()));
+ }
+
+ try {
+ if (!done) {
+ long s1 = 0;
+ long s2 = 0;
+ File f1 = new File(mFilename);
+ File f2 = new File(name);
+ if (f1.exists())
+ s1 = f1.length();
+ if (f2.exists())
+ s2 = f2.length();
+ if (s1 > 0 && s2 > 0 && s2 > s1) {
+ done = true;
+ } else {
+ if (f2.exists())
+ f2.delete();
+ name = null;
+ }
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("FILE_ERROR", e.getMessage()));
+ }
+
+ return name;
+ }
+
+ /**
+ * Read a file with the following format:
+ * <p>
+ *
+ * <pre>
+ * param1: valuea
+ * param2: valueb
+ * -blank-line-
+ * param1: valuec
+ * param2: valued
+ * </pre>
+ *
+ * @param f The file to read
+ * @param keys The parameters to concat together to form the hash
+ * key
+ * @return a hashtable of hashtables.
+ */
+ protected Hashtable<String, Hashtable<String, String>> readFile(File f, String[] keys)
+ throws IOException {
+ log(ILogger.LL_INFO, "Reading file: " + f.getName());
+ BufferedReader file = new BufferedReader(
+ new FileReader(f)
+ );
+
+ String line;
+ Hashtable<String, Hashtable<String, String>> allusers = new Hashtable<String, Hashtable<String, String>>();
+ Hashtable<String, String> entry = null;
+ int linenum = 0;
+
+ while ((line = file.readLine()) != null) {
+ linenum++;
+ line = line.trim();
+ if (line.length() > 0 && line.charAt(0) == '#') {
+ continue;
+ }
+ int colon = line.indexOf(':');
+
+ if (entry == null) {
+ entry = new Hashtable<String, String>();
+ }
+
+ if (colon == -1) { // no colon -> empty line signifies end of record
+ if (!line.trim().equals("")) {
+ if (file != null) {
+ file.close();
+ }
+ throw new IOException(FFAUTH + ": Parsing error, " +
+ "colon missing from line " + linenum + " of " + f.getName());
+ }
+ if (entry.size() > 0) {
+ putEntry(allusers, entry, keys);
+ entry = null;
+ }
+ continue;
+ }
+
+ String attr = line.substring(0, colon).trim();
+ String val = line.substring(colon + 1).trim();
+
+ entry.put(attr, val);
+ }
+
+ putEntry(allusers, entry, keys);
+ if (file != null) {
+ file.close();
+ }
+ return allusers;
+ }
+
+ private void putEntry(Hashtable<String, Hashtable<String, String>> allUsers,
+ Hashtable<String, String> entry,
+ String[] keys) {
+ if (entry == null) {
+ return;
+ }
+ String key = "";
+
+ print("keys.length = " + keys.length);
+ for (int i = 0; i < keys.length; i++) {
+ String s = entry.get(keys[i]);
+
+ print(" concatenating: " + s);
+ if (s != null) {
+ key = key.concat(s);
+ }
+ }
+ print("putting: key " + key);
+ allUsers.put(key, entry);
+ }
+
+ void printAllEntries() {
+ Enumeration<String> e = entries.keys();
+
+ while (e.hasMoreElements()) {
+ String key = e.nextElement();
+
+ print("* " + key + " *");
+ Hashtable<String, String> ht = entries.get(key);
+ Enumeration<String> f = ht.keys();
+
+ while (f.hasMoreElements()) {
+ String fkey = f.nextElement();
+
+ print(" " + fkey + " -> " + ht.get(fkey));
+ }
+ }
+ }
+
+ /**
+ * Compare attributes provided by the user with those in
+ * in flat file.
+ *
+ */
+
+ private IAuthToken doAuthentication(Hashtable<String, String> user, IAuthCredentials authCred)
+ throws EMissingCredential, EInvalidCredentials, EBaseException {
+ AuthToken authToken = new AuthToken(this);
+
+ for (int i = 0; i < authAttrs.length; i++) {
+ String ffvalue = user.get(authAttrs[i]);
+ String uservalue = (String) authCred.get(authAttrs[i]);
+
+ // print("checking authentication token (" + authAttrs[i] + ": " + uservalue + " against ff value: " + ffvalue);
+ if (!ffvalue.equals(uservalue)) {
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ }
+ return authToken;
+ }
+
+ private void reReadPwFile() {
+
+ try {
+ File file = new File(mFilename);
+ long pwfilelastmodified = file.lastModified();
+
+ if (pwfilelastmodified > mFileLastRead) {
+ mFileLastRead = pwfilelastmodified;
+ entries = readFile(file, keyAttrs);
+ // printAllEntries();
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("READ_FILE_ERROR", mFilename, e.getMessage()));
+ }
+ }
+
+ /**
+ * Authenticate the request
+ *
+ */
+ public IAuthToken authenticate(IAuthCredentials authCred)
+ throws EMissingCredential, EInvalidCredentials, EBaseException {
+ IAuthToken authToken = null;
+ String keyForUser = "";
+
+ /* First check if hashtable has been modified since we last read it in */
+
+ reReadPwFile();
+
+ /* Find the user in our hashtable */
+
+ for (int i = 0; i < keyAttrs.length; i++) {
+ print("concatenating string i=" + i + " keyAttrs[" + i + "] = " + keyAttrs[i]);
+ String credential = (String) authCred.get(keyAttrs[i]);
+
+ if (credential == null) {
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", keyAttrs[i]));
+ }
+ keyForUser = keyForUser.concat((String) authCred.get(keyAttrs[i]));
+ }
+ print("authenticating user: finding user from key: " + keyForUser);
+
+ Hashtable<String, String> user = entries.get(keyForUser);
+
+ try {
+ if (user != null) {
+ authToken = doAuthentication(user, authCred);
+ } else {
+ CMS.debug("FlatFileAuth: " + CMS.getLogMessage("CMS_AUTH_USER_NOT_FOUND"));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ } catch (EInvalidCredentials e) {
+ // If defer on failure is false, then we re-throw the exception
+ // which causes the request to be rejected
+ if (!mDeferOnFailure) {
+ throw e;
+ } else {
+ CMS.debug("FlatFileAuth: Since defering on failure - ignore invalid creds");
+ }
+ }
+
+ // if a dn was specified in the password file for this user,
+ // replace the requested dn with the one in the pwfile
+ if (user != null) {
+ String dn = user.get("dn");
+
+ if (dn != null && authToken != null) {
+ authToken.set(AuthToken.TOKEN_CERT_SUBJECT, dn);
+ }
+ }
+
+ // If defer on failure is true, and the auth failed, authToken will
+ // be null here, which causes the request to be deferred.
+
+ if (user != null && authToken != null) {
+ entries.remove(keyForUser);
+ updateFile(keyForUser);
+ // printAllEntries();
+ }
+ return authToken;
+ }
+
+ /**
+ * Return a list of HTTP parameters which will be taken from the
+ * request posting and placed into the AuthCredentials block
+ *
+ * Note that this method will not be called until after the
+ * init() method is called
+ */
+ public String[] getRequiredCreds() {
+ print("getRequiredCreds returning: " + joinStringArray(reqCreds, ","));
+ return reqCreds;
+
+ }
+
+ /**
+ * Returns a list of configuration parameters, so the console
+ * can prompt the user when configuring.
+ */
+ public String[] getConfigParams() {
+ return mConfigParams;
+ }
+
+ /**
+ * Returns the configuration store used by this authentication manager
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void shutdown() {
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public String getImplName() {
+ return mImplName;
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_AGENT_NAME");
+ }
+
+ /**
+ * Retrieves a list of names of the value parameter.
+ */
+ public Enumeration<String> getValueNames() {
+ return null;
+ }
+
+ public boolean isValueWriteable(String name) {
+ return false;
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public void populate(IAuthToken token, IRequest request)
+ throws EProfileException {
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_AGENT_TEXT");
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/HashAuthData.java b/base/server/cms/src/com/netscape/cms/authentication/HashAuthData.java
new file mode 100644
index 000000000..0635c445a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/HashAuthData.java
@@ -0,0 +1,118 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+// java sdk imports.
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * The structure stores the information of which machine is enabled for
+ * the agent-initiated user enrollment, and whom agents enable this feature,
+ * and the value of the timeout.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class HashAuthData extends Hashtable<String, Vector<Object>> {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -988354133432275910L;
+ public static final long TIMEOUT = 600000;
+ public static final long LASTLOGIN = 0;
+
+ public HashAuthData() {
+ }
+
+ public String getAgentName(String hostname) {
+ Vector<Object> val = get(hostname);
+
+ if (val != null)
+ return (String) val.elementAt(0);
+ return null;
+ }
+
+ public void setAgentName(String hostname, String agentName) {
+ Vector<Object> val = get(hostname);
+
+ if (val == null) {
+ val = new Vector<Object>();
+ put(hostname, val);
+ }
+ val.setElementAt(agentName, 0);
+ }
+
+ public long getTimeout(String hostname) {
+ Vector<Object> val = get(hostname);
+
+ if (val != null) {
+ return ((Long) val.elementAt(1)).longValue();
+ }
+ return TIMEOUT;
+ }
+
+ public void setTimeout(String hostname, long timeout) {
+ Vector<Object> val = get(hostname);
+
+ if (val == null) {
+ val = new Vector<Object>();
+ put(hostname, val);
+ }
+ val.setElementAt(Long.valueOf(timeout), 1);
+ }
+
+ public String getSecret(String hostname) {
+ Vector<Object> val = get(hostname);
+
+ if (val != null) {
+ return (String) val.elementAt(2);
+ }
+ return null;
+ }
+
+ public void setSecret(String hostname, String secret) {
+ Vector<Object> val = get(hostname);
+
+ if (val == null) {
+ val = new Vector<Object>();
+ put(hostname, val);
+ }
+ val.setElementAt(secret, 2);
+ }
+
+ public long getLastLogin(String hostname) {
+ Vector<Object> val = get(hostname);
+
+ if (val != null) {
+ return ((Long) val.elementAt(3)).longValue();
+ }
+ return LASTLOGIN;
+ }
+
+ public void setLastLogin(String hostname, long lastLogin) {
+ Vector<Object> val = get(hostname);
+
+ if (val == null) {
+ val = new Vector<Object>();
+ put(hostname, val);
+ }
+ val.setElementAt(Long.valueOf(lastLogin), 3);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/HashAuthentication.java b/base/server/cms/src/com/netscape/cms/authentication/HashAuthentication.java
new file mode 100644
index 000000000..9ebf8a7c0
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/HashAuthentication.java
@@ -0,0 +1,283 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+// ldap java sdk
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+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.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Hash uid/pwd directory based authentication manager
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class HashAuthentication implements IAuthManager, IExtendedPluginInfo {
+
+ public static final String SALT = "lala123";
+ public static final String CRED_UID = "uid";
+ public static final String CRED_FINGERPRINT = "fingerprint";
+ public static final String CRED_PAGEID = "pageID";
+ public static final String CRED_HOST = "hostname";
+ protected static String[] mRequiredCreds = { CRED_UID,
+ CRED_PAGEID, CRED_FINGERPRINT, CRED_HOST };
+ public static final long DEFAULT_TIMEOUT = 600000;
+
+ private MessageDigest mSHADigest = null;
+ private Hashtable<String, IAuthToken> mData = null;
+ private IConfigStore mConfig;
+ private String mName = null;
+ private String mImplName = null;
+ private ILogger mLogger = CMS.getLogger();
+ private static Vector<String> mExtendedPluginInfo = null;
+ private HashAuthData mHosts = null;
+
+ static String[] mConfigParams =
+ new String[] {};
+
+ static {
+ mExtendedPluginInfo = new Vector<String>();
+ mExtendedPluginInfo.add(IExtendedPluginInfo.HELP_TEXT +
+ ";Authenticate the username and password provided " +
+ "by the user against an LDAP directory. Works with the " +
+ "Dir Based Enrollment HTML form");
+ mExtendedPluginInfo.add(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-authrules-uidpwddirauth");
+ };
+
+ /**
+ * Default constructor, initialization must follow.
+ */
+ public HashAuthentication() {
+ }
+
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ mName = name;
+ mImplName = implName;
+ mConfig = config;
+ mData = new Hashtable<String, IAuthToken>();
+ mHosts = new HashAuthData();
+
+ try {
+ mSHADigest = MessageDigest.getInstance("SHA1");
+ } catch (NoSuchAlgorithmException e) {
+ throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR", e.getMessage()));
+ }
+
+ }
+
+ public IAuthToken getAuthToken(String key) {
+ return mData.remove(key);
+ }
+
+ public void addAuthToken(String pageID, IAuthToken token) {
+ mData.put(pageID, token);
+ }
+
+ public void deleteToken(String pageID) {
+ mData.remove(pageID);
+ }
+
+ public HashAuthData getData() {
+ return mHosts;
+ }
+
+ public void createEntry(String host, String dn, long timeout,
+ String secret, long lastLogin) {
+ Vector<Object> v = new Vector<Object>();
+
+ v.addElement(dn);
+ v.addElement(Long.valueOf(timeout));
+ v.addElement(secret);
+ v.addElement(Long.valueOf(lastLogin));
+ mHosts.put(host, v);
+ }
+
+ public void disable(String hostname) {
+ mHosts.remove(hostname);
+ }
+
+ public String getAgentName(String hostname) {
+ return mHosts.getAgentName(hostname);
+ }
+
+ public void setAgentName(String hostname, String agentName) {
+ mHosts.setAgentName(hostname, agentName);
+ }
+
+ public boolean isEnable(String hostname) {
+ return mHosts.containsKey(hostname);
+ }
+
+ public long getTimeout(String hostname) {
+ return mHosts.getTimeout(hostname);
+ }
+
+ public void setTimeout(String hostname, long timeout) {
+ mHosts.setTimeout(hostname, timeout);
+ }
+
+ public String getSecret(String hostname) {
+ return mHosts.getSecret(hostname);
+ }
+
+ public void setSecret(String hostname, String secret) {
+ mHosts.setSecret(hostname, secret);
+ }
+
+ public long getLastLogin(String hostname) {
+ return mHosts.getLastLogin(hostname);
+ }
+
+ public void setLastLogin(String hostname, long lastlogin) {
+ mHosts.setLastLogin(hostname, lastlogin);
+ }
+
+ public long getPageID() {
+ Date date = new Date();
+
+ return date.getTime();
+ }
+
+ public void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHENTICATION,
+ level, msg);
+ }
+
+ public boolean validFingerprint(String host, String pageID, String uid, String fingerprint) {
+ String val = hashFingerprint(host, pageID, uid);
+
+ if (val.equals(fingerprint))
+ return true;
+ return false;
+ }
+
+ public Enumeration<String> getHosts() {
+ return mHosts.keys();
+ }
+
+ public String hashFingerprint(String host, String pageID, String uid) {
+ byte[] hash =
+ mSHADigest.digest((SALT + pageID + getSecret(host) + uid).getBytes());
+ String b64E = Utils.base64encode(hash);
+
+ return "{SHA}" + b64E;
+ }
+
+ public void shutdown() {
+ }
+
+ /**
+ * Authenticates a user based on uid, pwd in the directory.
+ *
+ * @param authCreds The authentication credentials.
+ * @return The user's ldap entry dn.
+ * @exception EInvalidCredentials If the uid and password are not valid
+ * @exception EBaseException If an internal error occurs.
+ */
+ public IAuthToken authenticate(IAuthCredentials authCreds)
+ throws EBaseException {
+ AuthToken token = new AuthToken(this);
+ String fingerprint = (String) authCreds.get(CRED_FINGERPRINT);
+ String pageID = (String) authCreds.get(CRED_PAGEID);
+ String uid = (String) authCreds.get(CRED_UID);
+ String host = (String) authCreds.get(CRED_HOST);
+
+ if (fingerprint.equals("") ||
+ !validFingerprint(host, pageID, uid, fingerprint)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_INVALID_FINGER_PRINT"));
+ throw new EAuthException("Invalid Fingerprint");
+ }
+
+ // set uid in the token.
+ token.set(CRED_UID, uid);
+
+ return token;
+ }
+
+ /**
+ * Returns array of required credentials for this authentication manager.
+ *
+ * @return Array of required credentials.
+ */
+ public String[] getRequiredCreds() {
+ return mRequiredCreds;
+ }
+
+ /**
+ * Gets the configuration substore used by this authentication manager
+ *
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * gets the name of this authentication manager instance
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * gets the plugin name of this authentication manager.
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] s = Utils.getStringArrayFromVector(mExtendedPluginInfo);
+
+ return s;
+
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/PortalEnroll.java b/base/server/cms/src/com/netscape/cms/authentication/PortalEnroll.java
new file mode 100644
index 000000000..c94cec617
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/PortalEnroll.java
@@ -0,0 +1,468 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+// ldap java sdk
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPObjectClassSchema;
+import netscape.ldap.LDAPSchema;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EAuthInternalError;
+import com.netscape.certsrv.authentication.EAuthUserError;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * uid/pwd directory based authentication manager
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class PortalEnroll extends DirBasedAuthentication {
+
+ /* configuration parameter keys */
+ protected static final String PROP_LDAPAUTH = "ldapauth";
+ protected static final String PROP_AUTHTYPE = "authtype";
+ protected static final String PROP_BINDDN = "bindDN";
+ protected static final String PROP_BINDPW = "bindPW";
+ protected static final String PROP_LDAPCONN = "ldapconn";
+ protected static final String PROP_HOST = "host";
+ protected static final String PROP_PORT = "port";
+ protected static final String PROP_SECURECONN = "secureConn";
+ protected static final String PROP_VERSION = "version";
+ protected static final String PROP_OBJECTCLASS = "objectclass";
+
+ /* required credentials to authenticate. uid and pwd are strings. */
+ public static final String CRED_UID = "uid";
+ public static final String CRED_PWD = "userPassword";
+ protected static String[] mRequiredCreds = { CRED_UID, CRED_PWD };
+
+ /* ldap configuration sub-store */
+ private IArgBlock argblk = null;
+ private String mObjectClass = null;
+ private String mBindDN = null;
+ private String mBaseDN = null;
+ private ILdapConnFactory mLdapFactory = null;
+ private LDAPConnection mLdapConn = null;
+
+ // contains all nested superiors' required attrs in the form of a
+ // vector of "required" attributes in Enumeration
+ Vector<Enumeration<String>> mRequiredAttrs = null;
+
+ // contains all nested superiors' optional attrs in the form of a
+ // vector of "optional" attributes in Enumeration
+ Vector<Enumeration<String>> mOptionalAttrs = null;
+
+ // contains all the objclasses, including superiors and itself
+ Vector<String> mObjClasses = null;
+
+ /* Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ protected static String[] mConfigParams =
+ new String[] {
+ PROP_DNPATTERN,
+ "ldap.ldapconn.host",
+ "ldap.ldapconn.port",
+ "ldap.ldapconn.secureConn",
+ "ldap.ldapconn.version",
+ "ldap.ldapauth.bindDN",
+ "ldap.ldapauth.bindPWPrompt",
+ "ldap.ldapauth.clientCertNickname",
+ "ldap.ldapauth.authtype",
+ "ldap.basedn",
+ "ldap.objectclass",
+ "ldap.minConns",
+ "ldap.maxConns",
+ };
+
+ /**
+ * Default constructor, initialization must follow.
+ */
+ public PortalEnroll()
+ throws EBaseException {
+ super();
+ }
+
+ /**
+ * Initializes the PortalEnrollment auth manager.
+ * <p>
+ *
+ * @param name - The name for this authentication manager instance.
+ * @param implName - The name of the authentication manager plugin.
+ * @param config - The configuration store for this instance.
+ * @exception EBaseException If an error occurs during initialization.
+ */
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ super.init(name, implName, config);
+
+ /* Get Bind DN for directory server */
+ mConfig = mLdapConfig.getSubStore(PROP_LDAPAUTH);
+ mBindDN = mConfig.getString(PROP_BINDDN);
+ if ((mBindDN == null) || (mBindDN.length() == 0) || (mBindDN == ""))
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", "binddn"));
+
+ /* Get Bind DN for directory server */
+ mBaseDN = mLdapConfig.getString(PROP_BASEDN);
+ if ((mBaseDN == null) || (mBaseDN.length() == 0) || (mBaseDN == ""))
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", "basedn"));
+
+ /* Get Object clase name for enrollment */
+ mObjectClass = mLdapConfig.getString(PROP_OBJECTCLASS);
+ if (mObjectClass == null || mObjectClass.length() == 0)
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", "objectclass"));
+
+ /* Get connect parameter */
+ mLdapFactory = CMS.getLdapBoundConnFactory();
+ mLdapFactory.init(mLdapConfig);
+ mLdapConn = mLdapFactory.getConn();
+
+ log(ILogger.LL_INFO, CMS.getLogMessage("CMS_AUTH_PORTAL_INIT"));
+ }
+
+ /**
+ * Authenticates a user based on uid, pwd in the directory.
+ *
+ * @param authCreds The authentication credentials.
+ * @return The user's ldap entry dn.
+ * @exception EInvalidCredentials If the uid and password are not valid
+ * @exception EBaseException If an internal error occurs.
+ */
+ protected String authenticate(LDAPConnection conn,
+ IAuthCredentials authCreds,
+ AuthToken token)
+ throws EBaseException {
+ String uid = null;
+ String pwd = null;
+ String dn = null;
+
+ argblk = authCreds.getArgBlock();
+
+ // authenticate by binding to ldap server with password.
+ try {
+ // get the uid.
+ uid = (String) authCreds.get(CRED_UID);
+ if (uid == null) {
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_UID));
+ }
+
+ // get the password.
+ pwd = (String) authCreds.get(CRED_PWD);
+ if (pwd == null) {
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_PWD));
+ }
+ if (pwd.equals("")) {
+ // anonymous binding not allowed
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ // get user dn.
+ LDAPSearchResults res = conn.search(mBaseDN,
+ LDAPv2.SCOPE_SUB, "(uid=" + uid + ")", null, false);
+
+ if (res.hasMoreElements()) {
+ res.nextElement(); // consume the entry
+
+ throw new EAuthUserError(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_ATTRIBUTE_VALUE",
+ "UID already exists."));
+ } else {
+ dn = regist(token, uid);
+ if (dn == null)
+ throw new EAuthUserError(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_ATTRIBUTE_VALUE",
+ "Could not add user " + uid + "."));
+ }
+
+ // bind as user dn and pwd - authenticates user with pwd.
+ conn.authenticate(dn, pwd);
+
+ // set uid in the token.
+ token.set(CRED_UID, uid);
+
+ log(ILogger.LL_INFO, "portal authentication is done");
+
+ return dn;
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_ERROR", e.toString()));
+ throw e;
+ } catch (LDAPException e) {
+ switch (e.getLDAPResultCode()) {
+ case LDAPException.NO_SUCH_OBJECT:
+ case LDAPException.LDAP_PARTIAL_RESULTS:
+ log(ILogger.LL_SECURITY,
+ CMS.getLogMessage("CMS_AUTH_ADD_USER_ERROR", conn.getHost(), Integer.toString(conn.getPort())));
+ throw new EAuthInternalError(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR",
+ "Check Configuration detail."));
+
+ case LDAPException.INVALID_CREDENTIALS:
+ log(ILogger.LL_SECURITY,
+ CMS.getLogMessage("CMS_AUTH_BAD_PASSWORD", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+
+ case LDAPException.SERVER_DOWN:
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_SERVER_DOWN"));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), "" + conn.getPort()));
+
+ default:
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_ERROR", e.getMessage()));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_OTHER_LDAP_EXCEPTION",
+ e.errorCodeToString()));
+ }
+ } catch (EBaseException e) {
+ if (e.getMessage().equalsIgnoreCase(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND")) == true)
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_MAKE_DN_ERROR", e.toString()));
+ throw e;
+ }
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] s = {
+ PROP_DNPATTERN + ";string;Template for cert" +
+ " Subject Name. ($dn.xxx - get value from user's LDAP " +
+ "DN. $attr.yyy - get value from LDAP attributes in " +
+ "user's entry.) Default: " + DEFAULT_DNPATTERN,
+ "ldap.ldapconn.host;string,required;" + "LDAP host to connect to",
+ "ldap.ldapconn.port;number,required;" + "LDAP port number (default 389, or 636 if SSL)",
+ "ldap.objectclass;string,required;SEE DOCUMENTATION for Object Class. "
+ + "Default is inetOrgPerson.",
+ "ldap.ldapconn.secureConn;boolean;" + "Use SSL to connect to directory?",
+ "ldap.ldapconn.version;choice(3,2);" + "LDAP protocol version",
+ "ldap.ldapauth.bindDN;string,required;DN to bind as for Directory Manager. "
+ + "For example 'CN=Directory Manager'",
+ "ldap.ldapauth.bindPWPrompt;password;Enter password used to bind as " +
+ "the above user",
+ "ldap.ldapauth.authtype;choice(BasicAuth,SslClientAuth);"
+ + "How to bind to the directory (for pin removal only)",
+ "ldap.ldapauth.clientCertNickname;string;If you want to use "
+ + "SSL client auth to the directory, set the client "
+ + "cert nickname here",
+ "ldap.basedn;string,required;Base DN to start searching " +
+ "under. If your user's DN is 'uid=jsmith, o=company', you " +
+ "might want to use 'o=company' here",
+ "ldap.minConns;number;number of connections " +
+ "to keep open to directory server",
+ "ldap.maxConns;number;when needed, connection " +
+ "pool can grow to this many connections",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";This authentication plugin checks to see if a user " +
+ "exists in the directory. If not, then the user is created " +
+ "with the requested password.",
+ IExtendedPluginInfo.HELP_TOKEN + ";configuration-authrules-portalauth"
+ };
+
+ return s;
+ }
+
+ /**
+ * Returns array of required credentials for this authentication manager.
+ *
+ * @return Array of required credentials.
+ */
+ public String[] getRequiredCreds() {
+ return mRequiredCreds;
+ }
+
+ /**
+ * adds a user to the directory.
+ *
+ * @return dn upon success and null upon failure.
+ * @param token authentication token
+ * @param uid the user's id.
+ */
+ public String regist(AuthToken token, String uid) {
+ String dn = "uid=" + uid + "," + mBaseDN;
+
+ /* Specify the attributes of the entry */
+ Vector<String> objectclass_values = null;
+
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+ LDAPAttribute attr = new LDAPAttribute("objectclass");
+
+ // initialized to new
+ mRequiredAttrs = new Vector<Enumeration<String>>();
+ mOptionalAttrs = new Vector<Enumeration<String>>();
+ mObjClasses = new Vector<String>();
+
+ LDAPSchema dirSchema = null;
+
+ try {
+
+ /* Construct a new LDAPSchema object to hold
+ the schema that you want to retrieve. */
+ dirSchema = new LDAPSchema();
+
+ /* Get the schema from the Directory. Anonymous access okay. */
+ dirSchema.fetchSchema(mLdapConn);
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_ERROR", e.getMessage()));
+ }
+ // complete mRequiredAttrs, mOptionalAttrs, and mObjClasses
+ initLdapAttrs(dirSchema, mObjectClass);
+
+ objectclass_values = mObjClasses;
+ for (int i = objectclass_values.size() - 1; i >= 0; i--)
+ attr.addValue(objectclass_values.elementAt(i));
+ attrs.add(attr);
+
+ Enumeration<Enumeration<String>> objClasses = mRequiredAttrs.elements();
+ Enumeration<String> attrnames = null;
+
+ while (objClasses.hasMoreElements()) {
+ attrnames = objClasses.nextElement();
+ CMS.debug("PortalEnroll: Required attrs:");
+ while (attrnames.hasMoreElements()) {
+ String attrname = attrnames.nextElement();
+ String attrval = null;
+
+ CMS.debug("PortalEnroll: attrname is: " + attrname);
+ if (attrname.equalsIgnoreCase("objectclass") == true)
+ continue;
+ try {
+ attrval = argblk.getValueAsString(attrname);
+ } catch (EBaseException e) {
+ if (e.getMessage().equalsIgnoreCase(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND")) == true)
+ continue;
+ }
+
+ CMS.debug("PortalEnroll: " + attrname + " = " + attrval);
+ attrs.add(new LDAPAttribute(attrname, attrval));
+ }
+
+ }
+
+ objClasses = mOptionalAttrs.elements();
+ attrnames = null;
+
+ while (objClasses.hasMoreElements()) {
+ attrnames = objClasses.nextElement();
+ CMS.debug("PortalEnroll: Optional attrs:");
+ while (attrnames.hasMoreElements()) {
+ String attrname = attrnames.nextElement();
+ String attrval = null;
+
+ CMS.debug("PortalEnroll: attrname is: " + attrname);
+ try {
+ attrval = argblk.getValueAsString(attrname);
+ } catch (EBaseException e) {
+ if (e.getMessage().equalsIgnoreCase(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND")) == true)
+ continue;
+ }
+ CMS.debug("PortalEnroll: " + attrname + " = " + attrval);
+ if (attrval != null) {
+ attrs.add(new LDAPAttribute(attrname, attrval));
+ }
+ }
+ }
+
+ /* Create an entry with this DN and these attributes */
+ LDAPEntry entry = new LDAPEntry(dn, attrs);
+
+ try {
+
+ /* Now add the entry to the directory */
+ mLdapConn.add(entry);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_ERROR", e.getMessage()));
+ } else
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_ERROR", e.getMessage()));
+ return null;
+ }
+
+ log(ILogger.LL_INFO, CMS.getLogMessage("CMS_AUTH_REGISTRATION_DONE"));
+
+ return dn;
+ }
+
+ /*
+ * get the superiors of "inetOrgPerson" so the "required
+ * attributes", "optional qttributes", and "object classes" are complete;
+ * should build up
+ * mRequiredAttrs, mOptionalAttrs, and mObjClasses when returned
+ */
+ @SuppressWarnings("unchecked")
+ public void initLdapAttrs(LDAPSchema dirSchema, String oclass) {
+ CMS.debug("PortalEnroll: in initLdapAttrsAttrs");
+ mObjClasses.addElement(oclass);
+ if (oclass.equalsIgnoreCase("top"))
+ return;
+
+ try {
+
+ /* Get and print the def. of the object class. */
+ LDAPObjectClassSchema objClass = dirSchema.getObjectClass(oclass);
+
+ if (objClass != null) {
+ mRequiredAttrs.add(objClass.getRequiredAttributes());
+ mOptionalAttrs.add(objClass.getOptionalAttributes());
+ } else {
+ return;
+ }
+
+ CMS.debug("PortalEnroll: getting superiors for: " + oclass);
+ String superiors[] = objClass.getSuperiors();
+
+ CMS.debug("PortalEnroll: got superiors, superiors.length=" + superiors.length);
+ if (superiors.length == 0)
+ return;
+ for (int i = 0; i < superiors.length; i++) {
+ CMS.debug("Portalenroll: superior" + i + "=" + superiors[i]);
+ objClass = dirSchema.getObjectClass(superiors[i]);
+ initLdapAttrs(dirSchema, superiors[i]);
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_ERROR", e.getMessage()));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/RDNPattern.java b/base/server/cms/src/com/netscape/cms/authentication/RDNPattern.java
new file mode 100644
index 000000000..14d5a2f8f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/RDNPattern.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.StringReader;
+import java.util.Vector;
+
+import netscape.ldap.LDAPEntry;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.base.EBaseException;
+
+/**
+ * class for parsing a DN pattern used to construct a certificate
+ * subject name from ldap attributes and dn.
+ * <p>
+ *
+ * dnpattern is a string representing a subject name pattern to formulate from the directory attributes and entry dn. If
+ * empty or not set, the ldap entry DN will be used as the certificate subject name.
+ * <p>
+ *
+ * The syntax is
+ *
+ * <pre>
+ * dnPattern := rdnPattern *[ "," rdnPattern ]
+ * rdnPattern := avaPattern *[ "+" avaPattern ]
+ * avaPattern := name "=" value |
+ * name "=" "$attr" "." attrName [ "." attrNumber ] |
+ * name "=" "$dn" "." attrName [ "." attrNumber ] |
+ * "$dn" "." "$rdn" "." number
+ * </pre>
+ *
+ * <pre>
+ * Example1: <i>E=$attr.mail.1, CN=$attr.cn, OU=$dn.ou.2, O=$dn.o, C=US </i>
+ * Ldap entry: dn: UID=jjames, OU=IS, OU=people, O=acme.org
+ * Ldap attributes: cn: Jesse James
+ * Ldap attributes: mail: jjames@acme.org
+ * <p>
+ * The subject name formulated will be : <br>
+ * E=jjames@acme.org, CN=Jesse James, OU=people, O=acme.org, C=US
+ * <p>
+ * E = the first 'mail' ldap attribute value in user's entry. <br>
+ * CN = the (first) 'cn' ldap attribute value in the user's entry. <br>
+ * OU = the second 'ou' value in the user's entry DN. <br>
+ * O = the (first) 'o' value in the user's entry DN. <br>
+ * C = the string "US"
+ * <p>
+ * Example2: <i>E=$attr.mail.1, CN=$attr.cn, OU=$dn.ou.2, O=$dn.o, C=US</i>
+ * Ldap entry: dn: UID=jjames, OU=IS+OU=people, O=acme.org
+ * Ldap attributes: cn: Jesse James
+ * Ldap attributes: mail: jjames@acme.org
+ * <p>
+ * The subject name formulated will be : <br>
+ * E=jjames@acme.org, CN=Jesse James, OU=people, O=acme.org, C=US
+ * <p>
+ * E = the first 'mail' ldap attribute value in user's entry. <br>
+ * CN = the (first) 'cn' ldap attribute value in the user's entry. <br>
+ * OU = the second 'ou' value in the user's entry DN. note multiple AVAs
+ * in a RDN in this example. <br>
+ * O = the (first) 'o' value in the user's entry DN. <br>
+ * C = the string "US"
+ * <p>
+ * </pre>
+ *
+ * <pre>
+ * Example3: <i>CN=$attr.cn, $rdn.2, O=$dn.o, C=US</i>
+ * Ldap entry: dn: UID=jjames, OU=IS+OU=people, O=acme.org
+ * Ldap attributes: cn: Jesse James
+ * Ldap attributes: mail: jjames@acme.org
+ * <p>
+ * The subject name formulated will be : <br>
+ * CN=Jesse James, OU=IS+OU=people, O=acme.org, C=US
+ * <p>
+ * CN = the (first) 'cn' ldap attribute value in the user's entry. <br>
+ * followed by the second RDN in the user's entry DN. <br>
+ * O = the (first) 'o' value in the user's entry DN. <br>
+ * C = the string "US"
+ * <p>
+ * Example4: <i>CN=$attr.cn, OU=$dn.ou.2+OU=$dn.ou.1, O=$dn.o, C=US</i>
+ * Ldap entry: dn: UID=jjames, OU=IS+OU=people, O=acme.org
+ * Ldap attributes: cn: Jesse James
+ * Ldap attributes: mail: jjames@acme.org
+ * <p>
+ * The subject name formulated will be : <br>
+ * CN=Jesse James, OU=people+OU=IS, O=acme.org, C=US
+ * <p>
+ * CN = the (first) 'cn' ldap attribute value in the user's entry. <br>
+ * OU = the second 'ou' value in the user's entry DN followed by the
+ * first 'ou' value in the user's entry. note multiple AVAs
+ * in a RDN in this example. <br>
+ * O = the (first) 'o' value in the user's entry DN. <br>
+ * C = the string "US"
+ * <p>
+ * </pre>
+ *
+ * If an attribute or subject DN component does not exist the attribute is skipped.
+ *
+ * @version $Revision$, $Date$
+ */
+class RDNPattern {
+
+ /* ldap attributes needed by this RDN (to retrieve from ldap) */
+ private String[] mLdapAttrs = null;
+
+ /* AVA patterns */
+ protected AVAPattern[] mAVAPatterns = null;
+
+ /* original pattern string */
+ protected String mPatternString = null;
+
+ protected String mTestDN = null;
+
+ /**
+ * Construct a DN pattern by parsing a pattern string.
+ *
+ * @param pattenr the DN pattern
+ * @exception EBaseException If parsing error occurs.
+ */
+ public RDNPattern(String pattern)
+ throws EAuthException {
+ if (pattern == null || pattern.equals("")) {
+ // create an attribute list that is the dn.
+ mLdapAttrs = new String[] { "dn" };
+ } else {
+ mPatternString = pattern;
+ PushbackReader in = new PushbackReader(new StringReader(pattern));
+
+ parse(in);
+ }
+ }
+
+ /**
+ * Construct a DN pattern from a input stream of pattern
+ */
+ public RDNPattern(PushbackReader in)
+ throws EAuthException {
+ parse(in);
+ }
+
+ private void parse(PushbackReader in)
+ throws EAuthException {
+ //System.out.println("_________ begin rdn _________");
+ Vector<AVAPattern> avaPatterns = new Vector<AVAPattern>();
+ AVAPattern avaPattern = null;
+ int lastChar;
+
+ do {
+ avaPattern = new AVAPattern(in);
+ avaPatterns.addElement(avaPattern);
+ //System.out.println("added AVAPattern"+
+ //" mType "+avaPattern.mType+
+ //" mAttr "+avaPattern.mAttr+
+ //" mValue "+avaPattern.mValue+
+ //" mElement "+avaPattern.mElement);
+ try {
+ lastChar = in.read();
+ } catch (IOException e) {
+ throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR", e.toString()));
+ }
+ } while (lastChar == '+');
+
+ if (lastChar != -1) {
+ try {
+ in.unread(lastChar); // pushback last ,
+ } catch (IOException e) {
+ throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR", e.toString()));
+ }
+ }
+
+ mAVAPatterns = new AVAPattern[avaPatterns.size()];
+ avaPatterns.copyInto(mAVAPatterns);
+
+ Vector<String> ldapAttrs = new Vector<String>();
+
+ for (int i = 0; i < mAVAPatterns.length; i++) {
+ String avaAttr = mAVAPatterns[i].getLdapAttr();
+
+ if (avaAttr == null || avaAttr.length() == 0)
+ continue;
+ ldapAttrs.addElement(avaAttr);
+ }
+ mLdapAttrs = new String[ldapAttrs.size()];
+ ldapAttrs.copyInto(mLdapAttrs);
+ }
+
+ /**
+ * Form a Ldap v3 DN string from results of a ldap search.
+ *
+ * @param entry LDAPentry from a ldap search
+ * @return Ldap v3 DN string to use for a subject name.
+ */
+ public String formRDN(LDAPEntry entry)
+ throws EAuthException {
+ StringBuffer formedRDN = new StringBuffer();
+
+ for (int i = 0; i < mAVAPatterns.length; i++) {
+ if (mTestDN != null)
+ mAVAPatterns[i].mTestDN = mTestDN;
+ String ava = mAVAPatterns[i].formAVA(entry);
+
+ if (ava != null && ava.length() > 0) {
+ if (formedRDN.length() != 0)
+ formedRDN.append("+");
+ formedRDN.append(ava);
+ }
+ }
+ //System.out.println("formed RDN "+formedRDN.toString());
+ return formedRDN.toString();
+ }
+
+ public String[] getLdapAttrs() {
+ return mLdapAttrs.clone();
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/SSLclientCertAuthentication.java b/base/server/cms/src/com/netscape/cms/authentication/SSLclientCertAuthentication.java
new file mode 100644
index 000000000..2bec1b68d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/SSLclientCertAuthentication.java
@@ -0,0 +1,352 @@
+// --- 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) 2008 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+import java.security.Principal;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authentication.ISSLClientCertProvider;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.usrgrp.Certificates;
+
+/**
+ * Certificate server SSL client authentication.
+ *
+ * @author Christina Fu
+ * <P>
+ *
+ */
+public class SSLclientCertAuthentication implements IAuthManager,
+ IProfileAuthenticator {
+
+ /* result auth token attributes */
+ public static final String TOKEN_USERDN = "user";
+ public static final String TOKEN_USER_DN = "userdn";
+ public static final String TOKEN_USERID = "userid";
+ public static final String TOKEN_UID = "uid";
+
+ /* required credentials */
+ public static final String CRED_CERT = IAuthManager.CRED_SSL_CLIENT_CERT;
+ protected String[] mRequiredCreds = { CRED_CERT };
+
+ /* config parameters to pass to console (none) */
+ protected static String[] mConfigParams = null;
+
+ private String mName = null;
+ private String mImplName = null;
+ private IConfigStore mConfig = null;
+
+ public SSLclientCertAuthentication() {
+ }
+
+ /**
+ * initializes the SSLClientCertAuthentication auth manager
+ * <p>
+ * called by AuthSubsystem init() method, when initializing all available authentication managers.
+ *
+ * @param name The name of this authentication manager instance.
+ * @param implName The name of the authentication manager plugin.
+ * @param config The configuration store for this authentication manager.
+ */
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ mName = name;
+ mImplName = implName;
+ mConfig = config;
+ }
+
+ /**
+ * Gets the name of this authentication manager.
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Gets the plugin name of authentication manager.
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ public boolean isSSLClientRequired() {
+ return true;
+ }
+
+ /**
+ * authenticates user by certificate
+ * <p>
+ * called by other subsystems or their servlets to authenticate users
+ *
+ * @param authCred - authentication credential that contains
+ * an usrgrp.Certificates of the user (agent)
+ * @return the authentication token that contains the following
+ *
+ * @exception EMissingCredential If a required credential for this
+ * authentication manager is missing.
+ * @exception EInvalidCredentials If credentials cannot be authenticated.
+ * @exception EBaseException If an internal error occurred.
+ * @see com.netscape.certsrv.authentication.AuthToken
+ * @see com.netscape.certsrv.usrgrp.Certificates
+ */
+ public IAuthToken authenticate(IAuthCredentials authCred)
+ throws EMissingCredential, EInvalidCredentials, EBaseException {
+
+ CMS.debug("SSLclientCertAuthentication: start");
+ CMS.debug("authenticator instance name is " + getName());
+
+ // force SSL handshake
+ SessionContext context = SessionContext.getExistingContext();
+ ISSLClientCertProvider provider = (ISSLClientCertProvider)
+ context.get("sslClientCertProvider");
+
+ if (provider == null) {
+ CMS.debug("SSLclientCertAuthentication: No SSL Client Cert Provider Found");
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ CMS.debug("SSLclientCertAuthentication: got provider");
+ CMS.debug("SSLclientCertAuthentication: retrieving client certificate");
+ X509Certificate[] allCerts = provider.getClientCertificateChain();
+
+ if (allCerts == null) {
+ CMS.debug("SSLclientCertAuthentication: No SSL Client Certs Found");
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ CMS.debug("SSLclientCertAuthentication: got certificates");
+
+ // retreive certificate from socket
+ AuthToken authToken = new AuthToken(this);
+ X509Certificate[] x509Certs = allCerts;
+
+ // default certificate default has bugs in version
+ // version(3) is returned as 3, which should be 2
+ X509CertImpl ci[] = new X509CertImpl[x509Certs.length];
+
+ X509Certificate clientCert = null;
+ try {
+ for (int i = 0; i < x509Certs.length; i++) {
+ ci[i] = new X509CertImpl(x509Certs[i].getEncoded());
+ // find out which one is the leaf cert
+ clientCert = ci[i];
+
+ byte[] extBytes = clientCert.getExtensionValue("2.5.29.19");
+ // try to see if this is a leaf cert
+ // look for BasicConstraint extension
+ if (extBytes == null) {
+ // found leaf cert
+ CMS.debug("SSLclientCertAuthentication: authenticate: found leaf cert");
+ break;
+ } else {
+ CMS.debug("SSLclientCertAuthentication: authenticate: found cert having BasicConstraints ext");
+ // it's got BasicConstraints extension
+ // so it's not likely to be a leaf cert,
+ // however, check the isCA field regardless
+ try {
+ BasicConstraintsExtension bce =
+ new BasicConstraintsExtension(true, extBytes);
+ if (bce != null) {
+ if (!(Boolean) bce.get("is_ca")) {
+ CMS.debug("SSLclientCertAuthentication: authenticate: found CA cert in chain");
+ break;
+ } // else found a ca cert, continue
+ }
+ } catch (Exception e) {
+ CMS.debug("SSLclientCertAuthentication: authenticate: exception:" +
+ e.toString());
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ }
+ }
+ if (clientCert == null) {
+ CMS.debug("SSLclientCertAuthentication: authenticate: client cert not found");
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ } catch (CertificateException e) {
+ CMS.debug(e.toString());
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ // check if certificate(s) is revoked
+ boolean checkRevocation = true;
+ try {
+ checkRevocation = mConfig.getBoolean("checkRevocation", true);
+ } catch (EBaseException e) {
+ // do nothing; default to true
+ }
+ if (checkRevocation) {
+ if (CMS.isRevoked(ci)) {
+ CMS.debug("SSLclientCertAuthentication: certificate revoked");
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ }
+ Certificates certs = new Certificates(ci);
+ Principal p_dn = clientCert.getSubjectDN();
+ authToken.set(TOKEN_USERDN, p_dn.getName());
+ authToken.set("userdn", p_dn.getName());
+ String uid = getUidFromDN(p_dn.getName());
+ if (uid != null) {
+ authToken.set(TOKEN_UID, uid);
+ authToken.set(TOKEN_USERID, uid);
+ }
+ /*
+ authToken.set(TOKEN_USER_DN, user.getUserDN());
+ authToken.set(TOKEN_USERID, user.getUserID());
+ authToken.set(TOKEN_UID, user.getUserID());
+ authToken.set(TOKEN_GROUP, groupname);
+ */
+ authToken.set(CRED_CERT, certs);
+
+ CMS.debug("SSLclientCertAuthentication: authenticated ");
+
+ return authToken;
+ }
+
+ String getUidFromDN(String userdn) {
+ StringTokenizer st = new StringTokenizer(userdn, ",");
+ while (st.hasMoreTokens()) {
+ String t = st.nextToken();
+ int i = t.indexOf("=");
+
+ if (i == -1) {
+ continue;
+ }
+ String n = t.substring(0, i);
+ if (n.equalsIgnoreCase("uid")) {
+ String v = t.substring(i + 1);
+ CMS.debug("SSLclientCertAuthentication: getUidFromDN(): uid found:" + v);
+ return v;
+ } else {
+ continue;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * get the list of authentication credential attribute names
+ * required by this authentication manager. Generally used by
+ * the servlets that handle agent operations to authenticate its
+ * users. It calls this method to know which are the
+ * required credentials from the user (e.g. Javascript form data)
+ *
+ * @return attribute names in Vector
+ */
+ public String[] getRequiredCreds() {
+ return (mRequiredCreds);
+ }
+
+ /**
+ * get the list of configuration parameter names
+ * required by this authentication manager. Generally used by
+ * the Certificate Server Console to display the table for
+ * configuration purposes. CertUserDBAuthentication is currently not
+ * exposed in this case, so this method is not to be used.
+ *
+ * @return configuration parameter names in Hashtable of Vectors
+ * where each hashtable entry's key is the substore name, value is a
+ * Vector of parameter names. If no substore, the parameter name
+ * is the Hashtable key itself, with value same as key.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+
+ /**
+ * prepare this authentication manager for shutdown.
+ */
+ public void shutdown() {
+ }
+
+ /**
+ * gets the configuretion substore used by this authentication
+ * manager
+ *
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ // Profile-related methods
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_SSL_CLIENT_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_SSL_CLIENT_TEXT");
+ }
+
+ /**
+ * Retrieves a list of names of the value parameter.
+ */
+ public Enumeration<String> getValueNames() {
+ return null;
+ }
+
+ public boolean isValueWriteable(String name) {
+ return false;
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public void populate(IAuthToken token, IRequest request)
+ throws EProfileException {
+ request.setExtData(IProfileAuthenticator.AUTHENTICATED_NAME,
+ token.getInString(TOKEN_USERDN));
+ request.setExtData(IProfileAuthenticator.AUTHENTICATED_NAME,
+ token.getInString("userDN"));
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/SharedSecret.java b/base/server/cms/src/com/netscape/cms/authentication/SharedSecret.java
new file mode 100644
index 000000000..7a0784c53
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/SharedSecret.java
@@ -0,0 +1,38 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+import java.math.BigInteger;
+
+import org.mozilla.jss.pkix.cmc.PKIData;
+
+import com.netscape.certsrv.authentication.ISharedToken;
+
+public class SharedSecret implements ISharedToken {
+
+ public SharedSecret() {
+ }
+
+ public String getSharedToken(PKIData cmcdata) {
+ return "testing";
+ }
+
+ public String getSharedToken(BigInteger serial) {
+ return "testing";
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/TokenAuthentication.java b/base/server/cms/src/com/netscape/cms/authentication/TokenAuthentication.java
new file mode 100644
index 000000000..99abad7eb
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/TokenAuthentication.java
@@ -0,0 +1,327 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+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.IConfigStore;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cmsutil.http.HttpClient;
+import com.netscape.cmsutil.http.HttpRequest;
+import com.netscape.cmsutil.http.HttpResponse;
+import com.netscape.cmsutil.http.JssSSLSocketFactory;
+import com.netscape.cmsutil.xml.XMLObject;
+
+/**
+ * Token authentication.
+ * Checked if the given token is valid.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class TokenAuthentication implements IAuthManager,
+ IProfileAuthenticator {
+
+ /* result auth token attributes */
+ public static final String TOKEN_UID = "uid";
+ public static final String TOKEN_GID = "gid";
+
+ /* required credentials */
+ public static final String CRED_SESSION_ID = IAuthManager.CRED_SESSION_ID;
+ protected String[] mRequiredCreds = { CRED_SESSION_ID };
+
+ /* config parameters to pass to console (none) */
+ protected static String[] mConfigParams = null;
+
+ private String mName = null;
+ private String mImplName = null;
+ private IConfigStore mConfig = null;
+
+ public TokenAuthentication() {
+ }
+
+ /**
+ * initializes the TokenAuthentication auth manager
+ * <p>
+ * called by AuthSubsystem init() method, when initializing all available authentication managers.
+ *
+ * @param name The name of this authentication manager instance.
+ * @param implName The name of the authentication manager plugin.
+ * @param config The configuration store for this authentication manager.
+ */
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ mName = name;
+ mImplName = implName;
+ mConfig = config;
+ }
+
+ /**
+ * Gets the name of this authentication manager.
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Gets the plugin name of authentication manager.
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ public boolean isSSLClientRequired() {
+ return false;
+ }
+
+ /**
+ * authenticates user(agent) by certificate
+ * <p>
+ * called by other subsystems or their servlets to authenticate users (agents)
+ *
+ * @param authCred - authentication credential that contains
+ * an usrgrp.Certificates of the user (agent)
+ * @return the authentication token that contains the following
+ * @exception EMissingCredential If a required credential for this
+ * authentication manager is missing.
+ * @exception EInvalidCredentials If credentials cannot be authenticated.
+ * @exception EBaseException If an internal error occurred.
+ * @see com.netscape.certsrv.authentication.AuthToken
+ * @see com.netscape.certsrv.usrgrp.Certificates
+ */
+ public IAuthToken authenticate(IAuthCredentials authCred)
+ throws EMissingCredential, EInvalidCredentials, EBaseException {
+
+ CMS.debug("TokenAuthentication: start");
+
+ // force SSL handshake
+ SessionContext context = SessionContext.getExistingContext();
+
+ // retreive certificate from socket
+ AuthToken authToken = new AuthToken(this);
+
+ // get group name from configuration file
+ IConfigStore sconfig = CMS.getConfigStore();
+
+ String sessionId = (String) authCred.get(CRED_SESSION_ID);
+ String givenHost = (String) authCred.get("clientHost");
+ String authHost = sconfig.getString("securitydomain.host");
+ int authAdminPort = sconfig.getInteger("securitydomain.httpsadminport");
+ int authEEPort = sconfig.getInteger("securitydomain.httpseeport");
+ String authURL = "/ca/admin/ca/tokenAuthenticate";
+
+ String content = CRED_SESSION_ID + "=" + sessionId + "&hostname=" + givenHost;
+ CMS.debug("TokenAuthentication: content=" + content);
+
+ String c = null;
+ try {
+ c = sendAuthRequest(authHost, authAdminPort, authURL, content);
+ // in case where the new interface does not exist, EE will return a badly
+ // formatted response which will throw an exception during parsing
+ if (c != null) {
+ @SuppressWarnings("unused")
+ XMLObject parser = new XMLObject(new ByteArrayInputStream(c.getBytes()));
+ }
+ } catch (Exception e) {
+
+ CMS.debug("TokenAuthenticate: failed to contact admin host:port "
+ + authHost + ":" + authAdminPort + " " + e);
+ CMS.debug("TokenAuthenticate: attempting ee port " + authEEPort);
+ authURL = "/ca/ee/ca/tokenAuthenticate";
+ try {
+ c = sendAuthRequest(authHost, authEEPort, authURL, content);
+ } catch (IOException e1) {
+ CMS.debug("TokenAuthenticate: failed to contact EE host:port "
+ + authHost + ":" + authAdminPort + " " + e1);
+ throw new EBaseException(e1.getMessage());
+ }
+ }
+
+ if (c != null) {
+ try {
+ ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes());
+ XMLObject parser = null;
+
+ try {
+ parser = new XMLObject(bis);
+ } catch (Exception e) {
+ CMS.debug("TokenAuthentication::authenticate() - "
+ + "Exception=" + e.toString());
+ throw new EBaseException(e.toString());
+ }
+ String status = parser.getValue("Status");
+
+ CMS.debug("TokenAuthentication: status=" + status);
+ if (!status.equals("0")) {
+ String error = parser.getValue("Error");
+ throw new EBaseException(error);
+ }
+
+ String uid = parser.getValue("uid");
+ String gid = parser.getValue("gid");
+
+ authToken.set(TOKEN_UID, uid);
+ authToken.set(TOKEN_GID, gid);
+
+ if (context != null) {
+ CMS.debug("SessionContext.USER_ID " + uid + " SessionContext.GROUP_ID " + gid);
+ context.put(SessionContext.USER_ID, uid);
+ context.put(SessionContext.GROUP_ID, gid);
+ }
+
+ CMS.debug("TokenAuthentication: authenticated uid=" + uid + ", gid=" + gid);
+ } catch (EBaseException e) {
+ throw e;
+ } catch (Exception e) {
+ }
+ }
+
+ return authToken;
+ }
+
+ private String sendAuthRequest(String authHost, int authPort, String authUrl, String content)
+ throws IOException {
+ HttpClient httpclient = new HttpClient();
+ String c = null;
+
+ JssSSLSocketFactory factory = new JssSSLSocketFactory();
+ httpclient = new HttpClient(factory);
+ httpclient.connect(authHost, authPort);
+ HttpRequest httprequest = new HttpRequest();
+ httprequest.setMethod(HttpRequest.POST);
+ httprequest.setURI(authUrl);
+ httprequest.setHeader("user-agent", "HTTPTool/1.0");
+ httprequest.setHeader("content-length", "" + content.length());
+ httprequest.setHeader("content-type",
+ "application/x-www-form-urlencoded");
+ httprequest.setContent(content);
+
+ HttpResponse httpresponse = httpclient.send(httprequest);
+ c = httpresponse.getContent();
+
+ return c;
+ }
+
+ /**
+ * get the list of authentication credential attribute names
+ * required by this authentication manager. Generally used by
+ * the servlets that handle agent operations to authenticate its
+ * users. It calls this method to know which are the
+ * required credentials from the user (e.g. Javascript form data)
+ *
+ * @return attribute names in Vector
+ */
+ public String[] getRequiredCreds() {
+ return (mRequiredCreds);
+ }
+
+ /**
+ * get the list of configuration parameter names
+ * required by this authentication manager. Generally used by
+ * the Certificate Server Console to display the table for
+ * configuration purposes. CertUserDBAuthentication is currently not
+ * exposed in this case, so this method is not to be used.
+ *
+ * @return configuration parameter names in Hashtable of Vectors
+ * where each hashtable entry's key is the substore name, value is a
+ * Vector of parameter names. If no substore, the parameter name
+ * is the Hashtable key itself, with value same as key.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+
+ /**
+ * prepare this authentication manager for shutdown.
+ */
+ public void shutdown() {
+ }
+
+ /**
+ * gets the configuretion substore used by this authentication
+ * manager
+ *
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ // Profile-related methods
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_AGENT_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_AGENT_TEXT");
+ }
+
+ /**
+ * Retrieves a list of names of the value parameter.
+ */
+ public Enumeration<String> getValueNames() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(CRED_SESSION_ID);
+ return v.elements();
+ }
+
+ public boolean isValueWriteable(String name) {
+ return false;
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public void populate(IAuthToken token, IRequest request)
+ throws EProfileException {
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/UdnPwdDirAuthentication.java b/base/server/cms/src/com/netscape/cms/authentication/UdnPwdDirAuthentication.java
new file mode 100644
index 000000000..2f9fc43bd
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/UdnPwdDirAuthentication.java
@@ -0,0 +1,189 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+// ldap java sdk
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * udn/pwd directory based authentication manager
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class UdnPwdDirAuthentication extends DirBasedAuthentication {
+
+ /* required credentials to authenticate. udn and pwd are strings. */
+ public static final String CRED_UDN = "udn";
+ public static final String CRED_PWD = "pwd";
+ protected static String[] mRequiredCreds = { CRED_UDN, CRED_PWD };
+
+ /* Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ protected static String[] mConfigParams =
+ new String[] { PROP_DNPATTERN,
+ PROP_LDAPSTRINGATTRS,
+ PROP_LDAPBYTEATTRS,
+ "ldap.ldapconn.host",
+ "ldap.ldapconn.port",
+ "ldap.ldapconn.secureConn",
+ "ldap.ldapconn.version",
+ "ldap.minConns",
+ "ldap.maxConns",
+ };
+
+ static {
+ mExtendedPluginInfo.add(IExtendedPluginInfo.HELP_TEXT +
+ ";Authenticate the user distinguished name and password provided " +
+ "by the user against an LDAP directory. Works with the " +
+ "Dir Based Enrollment HTML form");
+ mExtendedPluginInfo.add(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-authentication");
+ };
+
+ /**
+ * Default constructor, initialization must follow.
+ */
+ public UdnPwdDirAuthentication() {
+ super();
+ }
+
+ /**
+ * Initializes the UdnPwdDirAuthentication auth manager.
+ * <p>
+ *
+ * @param name - The name for this authentication manager instance.
+ * @param implName - The name of the authentication manager plugin.
+ * @param config - The configuration store for this instance.
+ * @exception EBaseException If an error occurs during initialization.
+ */
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ super.init(name, implName, config, false);
+ }
+
+ /**
+ * Authenticates a user based on udn, pwd in the directory.
+ *
+ * @param authCreds The authentication credentials.
+ * @return The user's ldap entry dn.
+ * @exception EInvalidCredentials If the udn and password are not valid
+ * @exception EBaseException If an internal error occurs.
+ */
+ protected String authenticate(LDAPConnection conn,
+ IAuthCredentials authCreds,
+ AuthToken token)
+ throws EBaseException {
+ String userdn = null;
+
+ // authenticate by binding to ldap server with password.
+ try {
+ // get the udn.
+ userdn = (String) authCreds.get(CRED_UDN);
+ if (userdn == null) {
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_UDN));
+ }
+
+ // get the password.
+ String pwd = (String) authCreds.get(CRED_PWD);
+
+ if (pwd == null) {
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_PWD));
+ }
+ if (pwd.equals("")) {
+ // anonymous binding not allowed
+ log(ILogger.LL_FAILURE,
+ "user " + userdn + " attempted login with empty password.");
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ // bind as user dn and pwd - authenticates user with pwd.
+ conn.authenticate(userdn, pwd);
+ // set userdn in the token.
+ token.set(CRED_UDN, userdn);
+
+ return userdn;
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE,
+ "Couldn't get ldap connection. Error: " + e.toString());
+ throw e;
+ } catch (LDAPException e) {
+ switch (e.getLDAPResultCode()) {
+ case LDAPException.NO_SUCH_OBJECT:
+ case LDAPException.LDAP_PARTIAL_RESULTS:
+ log(ILogger.LL_SECURITY,
+ "user " + userdn + " does not exist in ldap server host " +
+ conn.getHost() + ", port " + conn.getPort() + ".");
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+
+ case LDAPException.INVALID_CREDENTIALS:
+ log(ILogger.LL_SECURITY,
+ "authenticate user " + userdn + " with bad password.");
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+
+ case LDAPException.SERVER_DOWN:
+ log(ILogger.LL_FAILURE, "Ldap server is down.");
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), "" + conn.getPort()));
+
+ default:
+ log(ILogger.LL_FAILURE,
+ "Ldap error encountered. " + e.getMessage());
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_OTHER_LDAP_EXCEPTION",
+ e.errorCodeToString()));
+ }
+ }
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+
+ /**
+ * Returns array of required credentials for this authentication manager.
+ *
+ * @return Array of required credentials.
+ */
+ public String[] getRequiredCreds() {
+ return mRequiredCreds;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/UidPwdDirAuthentication.java b/base/server/cms/src/com/netscape/cms/authentication/UidPwdDirAuthentication.java
new file mode 100644
index 000000000..ffa8ea42f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/UidPwdDirAuthentication.java
@@ -0,0 +1,269 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+// ldap java sdk
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * uid/pwd directory based authentication manager
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class UidPwdDirAuthentication extends DirBasedAuthentication
+ implements IProfileAuthenticator {
+
+ /* required credentials to authenticate. uid and pwd are strings. */
+ public static final String CRED_UID = "uid";
+ public static final String CRED_PWD = "pwd";
+ protected static String[] mRequiredCreds = { CRED_UID, CRED_PWD };
+
+ /* Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ protected static String[] mConfigParams =
+ new String[] { PROP_DNPATTERN,
+ PROP_LDAPSTRINGATTRS,
+ PROP_LDAPBYTEATTRS,
+ "ldap.ldapconn.host",
+ "ldap.ldapconn.port",
+ "ldap.ldapconn.secureConn",
+ "ldap.ldapconn.version",
+ "ldap.basedn",
+ "ldap.minConns",
+ "ldap.maxConns",
+ };
+
+ static {
+ mExtendedPluginInfo.add(IExtendedPluginInfo.HELP_TEXT +
+ ";Authenticate the username and password provided " +
+ "by the user against an LDAP directory. Works with the " +
+ "Dir Based Enrollment HTML form");
+ mExtendedPluginInfo.add(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-authrules-uidpwddirauth");
+ };
+
+ /**
+ * Default constructor, initialization must follow.
+ */
+ public UidPwdDirAuthentication() {
+ super();
+ }
+
+ /**
+ * Authenticates a user based on uid, pwd in the directory.
+ *
+ * @param authCreds The authentication credentials.
+ * @return The user's ldap entry dn.
+ * @exception EInvalidCredentials If the uid and password are not valid
+ * @exception EBaseException If an internal error occurs.
+ */
+ protected String authenticate(LDAPConnection conn,
+ IAuthCredentials authCreds,
+ AuthToken token)
+ throws EBaseException {
+ String userdn = null;
+ String uid = null;
+
+ // authenticate by binding to ldap server with password.
+ try {
+ // get the uid.
+ uid = (String) authCreds.get(CRED_UID);
+ CMS.debug("Authenticating UID=" + uid);
+ if (uid == null) {
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_UID));
+ }
+
+ // get the password.
+ String pwd = (String) authCreds.get(CRED_PWD);
+
+ if (pwd == null) {
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_PWD));
+ }
+ if (pwd.equals("")) {
+ // anonymous binding not allowed
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_EMPTY_PASSWORD", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ // get user dn.
+ CMS.debug("Authenticating: Searching for UID=" + uid +
+ " base DN=" + mBaseDN);
+ LDAPSearchResults res = conn.search(mBaseDN,
+ LDAPv2.SCOPE_SUB, "(uid=" + uid + ")", null, false);
+
+ if (res.hasMoreElements()) {
+ //LDAPEntry entry = (LDAPEntry)res.nextElement();
+ LDAPEntry entry = res.next();
+
+ userdn = entry.getDN();
+ CMS.debug("Authenticating: Found User DN=" + userdn);
+ } else {
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMS_AUTH_USER_NOT_EXIST", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ // bind as user dn and pwd - authenticates user with pwd.
+ conn.authenticate(userdn, pwd);
+ // set uid in the token.
+ token.set(CRED_UID, uid);
+
+ return userdn;
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CANNOT_CONNECT_LDAP", e.toString()));
+ throw e;
+ } catch (LDAPException e) {
+ switch (e.getLDAPResultCode()) {
+ case LDAPException.NO_SUCH_OBJECT:
+ case LDAPException.LDAP_PARTIAL_RESULTS:
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("USER_NOT_EXIST", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+
+ case LDAPException.INVALID_CREDENTIALS:
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMS_AUTH_BAD_PASSWORD", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+
+ case LDAPException.SERVER_DOWN:
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_SERVER_DOWN"));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), "" + conn.getPort()));
+
+ default:
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.getMessage()));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_OTHER_LDAP_EXCEPTION",
+ e.errorCodeToString()));
+ }
+ }
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+
+ /**
+ * Returns array of required credentials for this authentication manager.
+ *
+ * @return Array of required credentials.
+ */
+ public String[] getRequiredCreds() {
+ return mRequiredCreds;
+ }
+
+ // Profile-related methods
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_LDAP_UID_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_LDAP_UID_TEXT");
+ }
+
+ /**
+ * Retrieves a list of names of the value parameter.
+ */
+ public Enumeration<String> getValueNames() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(CRED_UID);
+ v.addElement(CRED_PWD);
+ return v.elements();
+ }
+
+ public boolean isValueWriteable(String name) {
+ if (name.equals(CRED_UID)) {
+ return true;
+ } else if (name.equals(CRED_PWD)) {
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(CRED_UID)) {
+ return new Descriptor(IDescriptor.STRING, null, null,
+ CMS.getUserMessage(locale, "CMS_AUTHENTICATION_LDAP_UID"));
+ } else if (name.equals(CRED_PWD)) {
+ return new Descriptor(IDescriptor.PASSWORD, null, null,
+ CMS.getUserMessage(locale, "CMS_AUTHENTICATION_LDAP_PWD"));
+
+ }
+ return null;
+ }
+
+ public void populate(IAuthToken token, IRequest request)
+ throws EProfileException {
+ request.setExtData(IProfileAuthenticator.AUTHENTICATED_NAME,
+ token.getInString(USER_DN));
+ }
+
+ public boolean isSSLClientRequired() {
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/UidPwdPinDirAuthentication.java b/base/server/cms/src/com/netscape/cms/authentication/UidPwdPinDirAuthentication.java
new file mode 100644
index 000000000..9e551966c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/UidPwdPinDirAuthentication.java
@@ -0,0 +1,461 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authentication;
+
+// ldap java sdk
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * uid/pwd/pin directory based authentication manager
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class UidPwdPinDirAuthentication extends DirBasedAuthentication
+ implements IExtendedPluginInfo, IProfileAuthenticator {
+
+ /* required credentials to authenticate. uid and pwd are strings. */
+ public static final String CRED_UID = "uid";
+ public static final String CRED_PWD = "pwd";
+ public static final String CRED_PIN = "pin";
+ protected static String[] mRequiredCreds = { CRED_UID, CRED_PWD, CRED_PIN };
+
+ public static final String PROP_REMOVE_PIN = "removePin";
+ public static final String PROP_PIN_ATTR = "pinAttr";
+
+ public static final boolean DEF_REMOVE_PIN = false;
+ public static final String DEF_PIN_ATTR = "pin";
+
+ protected static final byte SENTINEL_SHA = 0;
+ protected static final byte SENTINEL_MD5 = 1;
+ protected static final byte SENTINEL_NONE = 0x2d;
+
+ /* Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ protected static String[] mConfigParams =
+ new String[] { PROP_REMOVE_PIN,
+ PROP_PIN_ATTR,
+ PROP_DNPATTERN,
+ PROP_LDAPSTRINGATTRS,
+ PROP_LDAPBYTEATTRS,
+ "ldap.ldapconn.host",
+ "ldap.ldapconn.port",
+ "ldap.ldapconn.secureConn",
+ "ldap.ldapconn.version",
+ "ldap.ldapauth.bindDN",
+ "ldap.ldapauth.bindPWPrompt",
+ "ldap.ldapauth.clientCertNickname",
+ "ldap.ldapauth.authtype",
+ "ldap.basedn",
+ "ldap.minConns",
+ "ldap.maxConns",
+ };
+
+ static {
+ mExtendedPluginInfo.add(
+ PROP_REMOVE_PIN + ";boolean;SEE DOCUMENTATION for pin removal");
+ mExtendedPluginInfo.add(
+ PROP_PIN_ATTR + ";string;directory attribute to use for pin (default 'pin')");
+ mExtendedPluginInfo.add(
+ "ldap.ldapauth.bindDN;string;DN to bind as for pin removal. "
+ + "For example 'CN=PinRemoval User'");
+ mExtendedPluginInfo.add(
+ "ldap.ldapauth.bindPWPrompt;password;Enter password used to bind as " +
+ "the above user");
+ mExtendedPluginInfo.add(
+ "ldap.ldapauth.clientCertNickname;string;If you want to use "
+ + "SSL client auth to the directory, set the client "
+ + "cert nickname here");
+ mExtendedPluginInfo.add(
+ "ldap.ldapauth.authtype;choice(BasicAuth,SslClientAuth),required;"
+ + "How to bind to the directory (for pin removal only)");
+ mExtendedPluginInfo.add(IExtendedPluginInfo.HELP_TEXT
+ + ";Authenticate the username, password and pin provided "
+ + "by the user against an LDAP directory. Works with the "
+ + "Dir/Pin Based Enrollment HTML form");
+ mExtendedPluginInfo.add(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-authrules-uidpwdpindirauth");
+
+ }
+
+ protected boolean mRemovePin = DEF_REMOVE_PIN;
+ protected String mPinAttr = DEF_PIN_ATTR;
+ protected MessageDigest mSHADigest = null;
+ protected MessageDigest mMD5Digest = null;
+
+ private ILdapConnFactory removePinLdapFactory = null;
+ private LDAPConnection removePinLdapConnection = null;
+ private IConfigStore removePinLdapConfigStore = null;
+
+ /**
+ * Default constructor, initialization must follow.
+ */
+ public UidPwdPinDirAuthentication() {
+ super();
+ }
+
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ super.init(name, implName, config);
+ mRemovePin =
+ config.getBoolean(PROP_REMOVE_PIN, DEF_REMOVE_PIN);
+ mPinAttr =
+ config.getString(PROP_PIN_ATTR, DEF_PIN_ATTR);
+ if (mPinAttr.equals("")) {
+ mPinAttr = DEF_PIN_ATTR;
+ }
+
+ if (mRemovePin) {
+ removePinLdapConfigStore = config.getSubStore("ldap");
+ removePinLdapFactory = CMS.getLdapBoundConnFactory();
+ removePinLdapFactory.init(removePinLdapConfigStore);
+ removePinLdapConnection = removePinLdapFactory.getConn();
+ }
+
+ try {
+ mSHADigest = MessageDigest.getInstance("SHA1");
+ mMD5Digest = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e) {
+ throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR", e.getMessage()));
+ }
+
+ }
+
+ protected void verifyPassword(String Password) {
+ }
+
+ /**
+ * Authenticates a user based on its uid, pwd, pin in the directory.
+ *
+ * @param authCreds The authentication credentials with uid, pwd, pin.
+ * @return The user's ldap entry dn.
+ * @exception EInvalidCredentials If the uid and password are not valid
+ * @exception EBaseException If an internal error occurs.
+ */
+ protected String authenticate(LDAPConnection conn,
+ IAuthCredentials authCreds,
+ AuthToken token)
+ throws EBaseException {
+ String userdn = null;
+ String uid = null;
+ String pwd = null;
+ String pin = null;
+
+ try {
+ // get the uid.
+ uid = (String) authCreds.get(CRED_UID);
+ if (uid == null) {
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_UID));
+ }
+
+ // get the password.
+ pwd = (String) authCreds.get(CRED_PWD);
+ if (pwd == null) {
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_PWD));
+ }
+ if (pwd.equals("")) {
+ // anonymous binding not allowed
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_EMPTY_PASSWORD", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ // get the pin.
+ pin = (String) authCreds.get(CRED_PIN);
+ if (pin == null) {
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_PIN));
+ }
+ if (pin.equals("")) {
+ // empty pin not allowed
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_EMPTY_PIN", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ // get user dn.
+ LDAPSearchResults res = conn.search(mBaseDN,
+ LDAPv2.SCOPE_SUB, "(uid=" + uid + ")", null, false);
+
+ if (res.hasMoreElements()) {
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+
+ userdn = entry.getDN();
+ } else {
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMS_AUTH_USER_NOT_EXIST", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ // bind as user dn and pwd - authenticates user with pwd.
+ conn.authenticate(userdn, pwd);
+
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMS_AUTH_AUTHENTICATED", uid));
+ // log(ILogger.LL_SECURITY, "found user : " + userdn);
+
+ // check pin.
+ checkpin(conn, userdn, uid, pin);
+
+ // set uid in the token.
+ token.set(CRED_UID, uid);
+
+ return userdn;
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CANNOT_CONNECT_LDAP", e.toString()));
+ throw e;
+ } catch (LDAPException e) {
+ switch (e.getLDAPResultCode()) {
+ case LDAPException.NO_SUCH_OBJECT:
+ case LDAPException.LDAP_PARTIAL_RESULTS:
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMS_AUTH_USER_NOT_EXIST", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+
+ case LDAPException.INVALID_CREDENTIALS:
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMS_AUTH_BAD_PASSWORD", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+
+ case LDAPException.SERVER_DOWN:
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("LDAP_SERVER_DOWN"));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), "" + conn.getPort()));
+
+ default:
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.getMessage()));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_OTHER_LDAP_EXCEPTION",
+ e.errorCodeToString()));
+ }
+ }
+ }
+
+ protected void checkpin(LDAPConnection conn, String userdn,
+ String uid, String pin)
+ throws EBaseException, LDAPException {
+ LDAPSearchResults res = null;
+ LDAPEntry entry = null;
+
+ // get pin.
+
+ res = conn.search(userdn, LDAPv2.SCOPE_BASE,
+ "(objectclass=*)", new String[] { mPinAttr }, false);
+ if (res.hasMoreElements()) {
+ entry = (LDAPEntry) res.nextElement();
+ } else {
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMS_AUTH_NO_ENTRY_RETURNED", uid, userdn));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ LDAPAttribute pinAttr = entry.getAttribute(mPinAttr);
+
+ if (pinAttr == null) {
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMS_AUTH_NO_PIN_FOUND", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> pinValues = pinAttr.getByteValues();
+
+ if (!pinValues.hasMoreElements()) {
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMS_AUTH_NO_PIN_FOUND", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ byte[] entrypin = pinValues.nextElement();
+
+ // compare value digest.
+
+ if (entrypin == null || entrypin.length < 2) {
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMS_AUTH_NO_PIN_FOUND", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ byte hashtype = entrypin[0];
+
+ byte[] pinDigest = null;
+ String toBeDigested = userdn + pin;
+
+ if (hashtype == SENTINEL_SHA) {
+
+ pinDigest = mSHADigest.digest(toBeDigested.getBytes());
+ } else if (hashtype == SENTINEL_MD5) {
+ pinDigest = mMD5Digest.digest(toBeDigested.getBytes());
+ } else if (hashtype == SENTINEL_NONE) {
+ pinDigest = toBeDigested.getBytes();
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_UKNOWN_ENCODING_TYPE", mPinAttr, "*", userdn));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ if (pinDigest.length != (entrypin.length - 1)) {
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMS_AUTH_LENGTH_NOT_MATCHED", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ int i;
+
+ for (i = 0; i < (entrypin.length - 1); i++) {
+ if (pinDigest[i] != entrypin[i + 1])
+ break;
+ }
+ if (i != (entrypin.length - 1)) {
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMS_AUTH_BAD_PASSWORD", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ // pin ok. remove pin if so configured
+ // Note that this means that a policy may reject this request later,
+ // but the user will not be able to enroll again as his pin is gone.
+
+ // We remove the pin using a different connection which is bound as
+ // a more privileged user.
+
+ if (mRemovePin) {
+
+ try {
+ removePinLdapConnection.modify(userdn,
+ new LDAPModification(
+ LDAPModification.DELETE,
+ new LDAPAttribute(mPinAttr, entrypin)));
+
+ } catch (LDAPException e) {
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMS_AUTH_CANT_REMOVE_PIN", userdn));
+ }
+
+ }
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+
+ /**
+ * Returns array of required credentials for this authentication manager.
+ *
+ * @return Array of required credentials.
+ */
+ public String[] getRequiredCreds() {
+ return mRequiredCreds;
+ }
+
+ // Profile-related methods
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_LDAP_UID_PIN_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_LDAP_UID_PIN_TEXT");
+ }
+
+ /**
+ * Retrieves a list of names of the value parameter.
+ */
+ public Enumeration<String> getValueNames() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(CRED_UID);
+ v.addElement(CRED_PWD);
+ v.addElement(CRED_PIN);
+ return v.elements();
+ }
+
+ public boolean isValueWriteable(String name) {
+ if (name.equals(CRED_UID)) {
+ return true;
+ } else if (name.equals(CRED_PWD)) {
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(CRED_UID)) {
+ return new Descriptor(IDescriptor.STRING, null, null,
+ CMS.getUserMessage(locale, "CMS_AUTHENTICATION_LDAP_UID"));
+ } else if (name.equals(CRED_PWD)) {
+ return new Descriptor(IDescriptor.PASSWORD, null, null,
+ CMS.getUserMessage(locale, "CMS_AUTHENTICATION_LDAP_PWD"));
+ } else if (name.equals(CRED_PIN)) {
+ return new Descriptor(IDescriptor.PASSWORD, null, null,
+ CMS.getUserMessage(locale, "CMS_AUTHENTICATION_LDAP_PIN"));
+
+ }
+ return null;
+ }
+
+ public void populate(IAuthToken token, IRequest request)
+ throws EProfileException {
+ request.setExtData(IProfileAuthenticator.AUTHENTICATED_NAME,
+ token.getInString(USER_DN));
+ }
+
+ public boolean isSSLClientRequired() {
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authorization/AAclAuthz.java b/base/server/cms/src/com/netscape/cms/authorization/AAclAuthz.java
new file mode 100644
index 000000000..089cca9be
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authorization/AAclAuthz.java
@@ -0,0 +1,858 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authorization;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import com.netscape.certsrv.acls.ACL;
+import com.netscape.certsrv.acls.ACLEntry;
+import com.netscape.certsrv.acls.EACLsException;
+import com.netscape.certsrv.acls.IACL;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.evaluators.IAccessEvaluator;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * An abstract class represents an authorization manager that governs the
+ * access of internal resources such as servlets.
+ * It parses in the ACLs associated with each protected
+ * resources, and provides protected method <CODE>checkPermission</CODE> for code that needs to verify access before
+ * performing
+ * actions.
+ * <P>
+ * Here is a sample resourceACLS for a resource
+ *
+ * <PRE>
+ * certServer.UsrGrpAdminServlet:
+ * execute:
+ * deny (execute) user="tempAdmin";
+ * allow (execute) group="Administrators";
+ * </PRE>
+ *
+ * To perform permission checking, code call authz mgr authorize() method to verify access. See AuthzMgr for calling
+ * example.
+ * <P>
+ * default "evaluators" are used to evaluate the "group=.." or "user=.." rules. See evaluator for more info
+ *
+ * @version $Revision$, $Date$
+ * @see <A HREF="http://developer.netscape.com/library/documentation/enterprise/admnunix/aclfiles.htm">ACL Files</A>
+ */
+public abstract class AAclAuthz {
+
+ protected static final String PROP_CLASS = "class";
+ protected static final String PROP_IMPL = "impl";
+ protected static final String PROP_EVAL = "accessEvaluator";
+
+ protected static final String ACLS_ATTR = "aclResources";
+
+ private IConfigStore mConfig = null;
+
+ private Hashtable<String, ACL> mACLs = new Hashtable<String, ACL>();
+ private Hashtable<String, IAccessEvaluator> mEvaluators = new Hashtable<String, IAccessEvaluator>();
+ private ILogger mLogger = null;
+
+ /* Vector of extendedPluginInfo strings */
+ protected static Vector<String> mExtendedPluginInfo = null;
+
+ protected static String[] mConfigParams = null;
+
+ static {
+ mExtendedPluginInfo = new Vector<String>();
+ }
+
+ /**
+ * Constructor
+ */
+ public AAclAuthz() {
+ }
+
+ /**
+ * Initializes
+ */
+ protected void init(IConfigStore config)
+ throws EBaseException {
+
+ mLogger = CMS.getLogger();
+ CMS.debug("AAclAuthz: init begins");
+
+ mConfig = config;
+
+ // load access evaluators specified in the config file
+ IConfigStore mainConfig = CMS.getConfigStore();
+ IConfigStore evalConfig = mainConfig.getSubStore(PROP_EVAL);
+ IConfigStore i = evalConfig.getSubStore(PROP_IMPL);
+
+ IAccessEvaluator evaluator = null;
+ Enumeration<String> mImpls = i.getSubStoreNames();
+
+ while (mImpls.hasMoreElements()) {
+ String type = mImpls.nextElement();
+ String evalClassPath = null;
+
+ try {
+ evalClassPath = i.getString(type + "." + PROP_CLASS);
+ } catch (Exception e) {
+ log(ILogger.LL_MISCONF, "failed to get config class info");
+
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED",
+ type + "." + PROP_CLASS));
+ }
+
+ // instantiate evaluator
+ try {
+ evaluator =
+ (IAccessEvaluator) Class.forName(evalClassPath).newInstance();
+ } catch (Exception e) {
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_CLASS_LOAD_FAIL",
+ evalClassPath));
+ }
+
+ if (evaluator != null) {
+ evaluator.init();
+ // store evaluator
+ registerEvaluator(type, evaluator);
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("AUTHZ_EVALUATOR_NULL", type));
+ }
+ }
+
+ log(ILogger.LL_INFO, "initialization done");
+ }
+
+ /**
+ * Parse ACL resource attributes, then update the ACLs memory store
+ * This is intended to be used if storing ACLs on ldap is not desired,
+ * and the caller is expected to call this method to add resource
+ * and acl info into acls memory store. The resACLs format should conform
+ * to the following:
+ * <resource ID>:right-1[,right-n]:[allow,deny](right(s))<evaluatorType>=<value>:<comment for this resource acl
+ * <P>
+ * Example: resTurnKnob:left,right:allow(left) group="lefties":door knobs for lefties
+ *
+ * @param resACLs same format as the resourceACLs attribute
+ * @throws EBaseException parsing error from <code>parseACL</code>
+ */
+ public void addACLs(String resACLs) throws EBaseException {
+ ACL acl = (ACL) CMS.parseACL(resACLs);
+
+ if (acl != null) {
+ mACLs.put(acl.getName(), acl);
+ } else {
+ log(ILogger.LL_FAILURE, "parseACL failed");
+ }
+ }
+
+ public void accessInit(String accessInfo) throws EBaseException {
+ addACLs(accessInfo);
+ }
+
+ public IACL getACL(String target) {
+ return mACLs.get(target);
+ }
+
+ protected Enumeration<String> getTargetNames() {
+ return mACLs.keys();
+ }
+
+ public Enumeration<ACL> getACLs() {
+ return mACLs.elements();
+ }
+
+ /**
+ * Returns the configuration store used by this Authz mgr
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] s = Utils.getStringArrayFromVector(mExtendedPluginInfo);
+
+ return s;
+
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return mConfigParams;
+ }
+
+ /**
+ * graceful shutdown
+ */
+ public abstract void shutdown();
+
+ /**
+ * Registers new handler for the given attribute type
+ * in the expressions.
+ */
+ public void registerEvaluator(String type, IAccessEvaluator evaluator) {
+ mEvaluators.put(type, evaluator);
+ log(ILogger.LL_INFO, type + " evaluator registered");
+ }
+
+ /*******************************************************
+ * with session context
+ *******************************************************/
+
+ /**
+ * Checks if the permission is granted or denied in
+ * the current execution context. If the code is
+ * marked as privileged, this methods will simply
+ * return.
+ * <P>
+ * note that if a resource does not exist in the aclResources entry, but a higher level node exist, it will still be
+ * evaluated. The highest level node's acl determines the permission. If the higher level node doesn't contain any
+ * acl information, then it's passed down to the lower node. If a node has no aci in its resourceACLs, then it's
+ * considered passed.
+ * <p>
+ * example: certServer.common.users, if failed permission check for "certServer", then it's considered failed, and
+ * there is no need to continue the check. If passed permission check for "certServer", then it's considered passed,
+ * and no need to continue the check. If certServer contains no aci then "certServer.common" will be checked for
+ * permission instead. If down to the leaf level, the node still contains no aci, then it's considered passed. If at
+ * the leaf level, no such resource exist, or no acis, it's considered passed.
+ * <p>
+ * If there are multiple aci's for a resource, ALL aci's will be checked, and only if all passed permission checks,
+ * will the eventual access be granted.
+ *
+ * @param name resource name
+ * @param perm permission requested
+ * @exception EACLsException access permission denied
+ */
+ protected synchronized void checkPermission(String name, String perm)
+ throws EACLsException {
+ String resource = "";
+ StringTokenizer st = new StringTokenizer(name, ".");
+
+ while (st.hasMoreTokens()) {
+ String node = st.nextToken();
+
+ if (!"".equals(resource)) {
+ resource = resource + "." + node;
+ } else {
+ resource = node;
+ }
+
+ boolean passed = false;
+
+ try {
+ passed = checkACLs(resource, perm);
+ } catch (EACLsException e) {
+ Object[] params = new Object[2];
+
+ params[0] = name;
+ params[1] = perm;
+
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("AUTHZ_EVALUATOR_ACCESS_DENIED", name, perm));
+
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_NO_PERMISSION",
+ (String[]) params));
+ }
+
+ if (passed) {
+ String infoMsg = "checkPermission(): permission granted for the resource " +
+ name + " on operation " + perm;
+
+ log(ILogger.LL_INFO, infoMsg);
+
+ return;
+ } // else, continue
+ }
+ }
+
+ /**
+ * Checks if the permission is granted or denied in
+ * the current execution context.
+ * <P>
+ * An <code>ACL</code> may contain one or more <code>ACLEntry</code>. However, in case of multiple
+ * <code>ACLEntry</code>, a subject must pass ALL of the <code>ACLEntry</code> evaluation for permission to be
+ * granted
+ * <P>
+ * negative ("deny") aclEntries are treated differently than positive ("allow") statements. If a negative aclEntries
+ * fails the acl check, the permission check will return "false" right away; while in the case of a positive
+ * aclEntry, if the the aclEntry fails the acl check, the next aclEntry will be evaluated.
+ *
+ * @param name resource name
+ * @param perm permission requested
+ * @return true if access allowed
+ * false if should be passed down to the next node
+ * @exception EACLsException if access disallowed
+ */
+ private boolean checkACLs(String name, String perm)
+ throws EACLsException {
+ ACL acl = mACLs.get(name);
+
+ // no such resource, pass it down
+ if (acl == null) {
+ String infoMsg = "checkACLs(): no acl for" +
+ name + "...pass down to next node";
+
+ log(ILogger.LL_INFO, infoMsg);
+
+ return false;
+ }
+
+ Enumeration<ACLEntry> e = acl.entries();
+
+ if ((e == null) || (e.hasMoreElements() == false)) {
+ // no acis for node, pass down to next node
+ String infoMsg = " AAclAuthz.checkACLs(): no acis for " +
+ name + " acl entry...pass down to next node";
+
+ log(ILogger.LL_INFO, infoMsg);
+
+ return false;
+ }
+
+ /**
+ * must pass all ACLEntry
+ */
+ for (; e.hasMoreElements();) {
+ ACLEntry entry = e.nextElement();
+
+ // if permission not pertinent, move on to next ACLEntry
+ if (entry.containPermission(perm) == true) {
+ if (evaluateExpressions(entry.getAttributeExpressions())) {
+ if (entry.checkPermission(perm) == false) {
+ log(ILogger.LL_SECURITY, " checkACLs(): permission denied");
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_PERMISSION_DENIED"));
+ }
+ } else if (!entry.isNegative()) {
+ // didn't meet the access expression for "allow", failed
+ log(ILogger.LL_SECURITY, "checkACLs(): permission denied");
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_PERMISSION_DENIED"));
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Resolves the given expressions.
+ * expression || expression || ...
+ * example:
+ * group="Administrators" || group="Operators"
+ */
+ private boolean evaluateExpressions(String s) {
+ // XXX - just handle "||" (or) among multiple expressions for now
+ // XXX - could use some optimization ... later
+
+ CMS.debug("evaluating expressions: " + s);
+
+ Vector<Object> v = new Vector<Object>();
+
+ while (s.length() > 0) {
+ int orIndex = s.indexOf("||");
+ int andIndex = s.indexOf("&&");
+
+ // this is the last expression
+ if (orIndex == -1 && andIndex == -1) {
+ boolean passed = evaluateExpression(s.trim());
+
+ v.addElement(Boolean.valueOf(passed));
+ break;
+
+ // || first
+ } else if (andIndex == -1 || (orIndex != -1 && orIndex < andIndex)) {
+ String s1 = s.substring(0, orIndex);
+ boolean passed = evaluateExpression(s1.trim());
+
+ v.addElement(new Boolean(passed));
+ v.addElement("||");
+ s = s.substring(orIndex + 2);
+ // && first
+ } else {
+ String s1 = s.substring(0, andIndex);
+ boolean passed = evaluateExpression(s1.trim());
+
+ v.addElement(new Boolean(passed));
+ v.addElement("&&");
+ s = s.substring(andIndex + 2);
+ }
+ }
+
+ if (v.size() == 1) {
+ Boolean bool = (Boolean) v.remove(0);
+
+ return bool.booleanValue();
+ }
+ boolean left = false;
+ String op = "";
+ boolean right = false;
+
+ while (v.size() > 0) {
+ if (op.equals(""))
+ left = ((Boolean) v.remove(0)).booleanValue();
+ op = (String) v.remove(0);
+ right = ((Boolean) v.remove(0)).booleanValue();
+ left = evaluateExp(left, op, right);
+ }
+
+ return left;
+ }
+
+ /**
+ * Resolves the given expression.
+ */
+ private boolean evaluateExpression(String expression) {
+ // XXX - just recognize "=" for now!!
+ int i = expression.indexOf("=");
+ String type = expression.substring(0, i);
+ String value = expression.substring(i + 1);
+ IAccessEvaluator evaluator = mEvaluators.get(type);
+
+ if (evaluator == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("AUTHZ_EVALUATOR_NOT_FOUND", type));
+ return false;
+ }
+
+ return evaluator.evaluate(type, "=", value);
+ }
+
+ /*******************************************************
+ * with authToken
+ *******************************************************/
+
+ /**
+ * Checks if the permission is granted or denied with id from authtoken
+ * gotten from authentication that precedes authorization. If the code is
+ * marked as privileged, this methods will simply
+ * return.
+ * <P>
+ * note that if a resource does not exist in the aclResources entry, but a higher level node exist, it will still be
+ * evaluated. The highest level node's acl determines the permission. If the higher level node doesn't contain any
+ * acl information, then it's passed down to the lower node. If a node has no aci in its resourceACLs, then it's
+ * considered passed.
+ * <p>
+ * example: certServer.common.users, if failed permission check for "certServer", then it's considered failed, and
+ * there is no need to continue the check. If passed permission check for "certServer", then it's considered passed,
+ * and no need to continue the check. If certServer contains no aci then "certServer.common" will be checked for
+ * permission instead. If down to the leaf level, the node still contains no aci, then it's considered passed. If at
+ * the leaf level, no such resource exist, or no acis, it's considered passed.
+ * <p>
+ * If there are multiple aci's for a resource, ALL aci's will be checked, and only if all passed permission checks,
+ * will the eventual access be granted.
+ *
+ * @param authToken authentication token gotten from authentication
+ * @param name resource name
+ * @param perm permission requested
+ * @exception EACLsException access permission denied
+ */
+ public synchronized void checkPermission(IAuthToken authToken, String name,
+ String perm)
+ throws EACLsException {
+
+ Vector<String> nodev = getNodes(name);
+ Enumeration<String> nodes = nodev.elements();
+ String order = getOrder();
+ Enumeration<ACLEntry> entries = null;
+
+ if (order.equals("deny"))
+ entries = getDenyEntries(nodes, perm);
+ else
+ entries = getAllowEntries(nodes, perm);
+
+ boolean permitted = false;
+
+ while (entries.hasMoreElements()) {
+ ACLEntry entry = entries.nextElement();
+
+ CMS.debug("checkACLS(): ACLEntry expressions= " +
+ entry.getAttributeExpressions());
+ if (evaluateExpressions(authToken, entry.getAttributeExpressions())) {
+ log(ILogger.LL_SECURITY,
+ " checkACLs(): permission denied");
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_PERMISSION_DENIED"));
+ }
+ }
+
+ nodes = nodev.elements();
+ if (order.equals("deny"))
+ entries = getAllowEntries(nodes, perm);
+ else
+ entries = getDenyEntries(nodes, perm);
+
+ while (entries.hasMoreElements()) {
+ ACLEntry entry = entries.nextElement();
+
+ CMS.debug("checkACLS(): ACLEntry expressions= " +
+ entry.getAttributeExpressions());
+ if (evaluateExpressions(authToken, entry.getAttributeExpressions())) {
+ permitted = true;
+ }
+ }
+
+ nodev = null;
+ if (permitted) {
+ String infoMsg = "checkPermission(): permission granted for the resource " +
+ name + " on operation " + perm;
+
+ log(ILogger.LL_INFO, infoMsg);
+ return;
+ } else {
+ String[] params = new String[2];
+
+ params[0] = name;
+ params[1] = perm;
+
+ log(ILogger.LL_SECURITY,
+ CMS.getLogMessage("AUTHZ_EVALUATOR_ACCESS_DENIED", name, perm));
+
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_NO_PERMISSION",
+ params));
+ }
+ }
+
+ protected Enumeration<ACLEntry> getAllowEntries(Enumeration<String> nodes, String operation) {
+ String name = "";
+ ACL acl = null;
+ Enumeration<ACLEntry> e = null;
+ Vector<ACLEntry> v = new Vector<ACLEntry>();
+
+ while (nodes.hasMoreElements()) {
+ name = nodes.nextElement();
+ acl = mACLs.get(name);
+ if (acl == null)
+ continue;
+ e = acl.entries();
+ while (e.hasMoreElements()) {
+ ACLEntry entry = e.nextElement();
+
+ if (!entry.isNegative() &&
+ entry.containPermission(operation)) {
+ v.addElement(entry);
+ }
+ }
+ }
+
+ return v.elements();
+ }
+
+ protected Enumeration<ACLEntry> getDenyEntries(Enumeration<String> nodes, String operation) {
+ String name = "";
+ ACL acl = null;
+ Enumeration<ACLEntry> e = null;
+ Vector<ACLEntry> v = new Vector<ACLEntry>();
+
+ while (nodes.hasMoreElements()) {
+ name = nodes.nextElement();
+ acl = mACLs.get(name);
+ if (acl == null)
+ continue;
+ e = acl.entries();
+ while (e.hasMoreElements()) {
+ ACLEntry entry = e.nextElement();
+
+ if (entry.isNegative() &&
+ entry.containPermission(operation)) {
+ v.addElement(entry);
+ }
+ }
+ }
+
+ return v.elements();
+ }
+
+ /**
+ * Resolves the given expressions.
+ * expression || expression || ...
+ * example:
+ * group="Administrators" || group="Operators"
+ */
+ private boolean evaluateExpressions(IAuthToken authToken, String s) {
+ // XXX - just handle "||" (or) among multiple expressions for now
+ // XXX - could use some optimization ... later
+ CMS.debug("evaluating expressions: " + s);
+
+ Vector<Object> v = new Vector<Object>();
+
+ while (s.length() > 0) {
+ int orIndex = s.indexOf("||");
+ int andIndex = s.indexOf("&&");
+
+ // this is the last expression
+ if (orIndex == -1 && andIndex == -1) {
+ boolean passed = evaluateExpression(authToken, s.trim());
+
+ CMS.debug("evaluated expression: " + s.trim() + " to be " + passed);
+ v.addElement(Boolean.valueOf(passed));
+ break;
+
+ // || first
+ } else if (andIndex == -1 || (orIndex != -1 && orIndex < andIndex)) {
+ String s1 = s.substring(0, orIndex);
+ boolean passed = evaluateExpression(authToken, s1.trim());
+
+ CMS.debug("evaluated expression: " + s1.trim() + " to be " + passed);
+ v.addElement(new Boolean(passed));
+ v.addElement("||");
+ s = s.substring(orIndex + 2);
+ // && first
+ } else {
+ String s1 = s.substring(0, andIndex);
+ boolean passed = evaluateExpression(authToken, s1.trim());
+
+ CMS.debug("evaluated expression: " + s1.trim() + " to be " + passed);
+ v.addElement(new Boolean(passed));
+ v.addElement("&&");
+ s = s.substring(andIndex + 2);
+ }
+ }
+
+ if (v.size() == 0) {
+ return false;
+ }
+
+ if (v.size() == 1) {
+ Boolean bool = (Boolean) v.remove(0);
+
+ return bool.booleanValue();
+ }
+
+ boolean left = false;
+ String op = "";
+ boolean right = false;
+
+ while (v.size() > 0) {
+ if (op.equals(""))
+ left = ((Boolean) v.remove(0)).booleanValue();
+ op = (String) v.remove(0);
+ right = ((Boolean) v.remove(0)).booleanValue();
+ left = evaluateExp(left, op, right);
+ }
+
+ return left;
+ }
+
+ public Vector<String> getNodes(String resourceID) {
+ Vector<String> v = new Vector<String>();
+
+ if (resourceID != null && !resourceID.equals("")) {
+ v.addElement(resourceID);
+ } else {
+ return v;
+ }
+ int index = resourceID.lastIndexOf(".");
+ String name = resourceID;
+
+ while (index != -1) {
+ name = name.substring(0, index);
+ v.addElement(name);
+ index = name.lastIndexOf(".");
+ }
+
+ return v;
+ }
+
+ /**
+ * Resolves the given expression.
+ */
+ private boolean evaluateExpression(IAuthToken authToken, String expression) {
+ String op = getOp(expression);
+ String type = "";
+ String value = "";
+
+ if (!op.equals("")) {
+ int len = op.length();
+ int i = expression.indexOf(op);
+
+ type = expression.substring(0, i).trim();
+ value = expression.substring(i + len).trim();
+ }
+ IAccessEvaluator evaluator = mEvaluators.get(type);
+
+ if (evaluator == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("AUTHZ_EVALUATOR_NOT_FOUND", type));
+ return false;
+ }
+
+ return evaluator.evaluate(authToken, type, op, value);
+ }
+
+ private String getOp(String exp) {
+ int i = exp.indexOf("!=");
+
+ if (i == -1) {
+ i = exp.indexOf("=");
+ if (i == -1) {
+ i = exp.indexOf(">");
+ if (i == -1) {
+ i = exp.indexOf("<");
+ if (i == -1) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("AUTHZ_OP_NOT_SUPPORTED", exp));
+ } else {
+ return "<";
+ }
+ } else {
+ return ">";
+ }
+ } else {
+ return "=";
+ }
+ } else {
+ return "!=";
+ }
+ return "";
+ }
+
+ private boolean evaluateExp(boolean left, String op, boolean right) {
+ if (op.equals("||")) {
+ if (left == false && right == false)
+ return false;
+ return true;
+ } else if (op.equals("&&")) {
+ if (left == true && right == true)
+ return true;
+ return false;
+ }
+ return false;
+ }
+
+ /*******************************************************
+ * end identification differentiation
+ *******************************************************/
+
+ /**
+ * This one only updates the memory. Classes extend this class should
+ * also update to a permanent storage
+ */
+ public void updateACLs(String id, String rights, String strACLs,
+ String desc) throws EACLsException {
+ String resourceACLs = id;
+
+ if (rights != null)
+ resourceACLs = id + ":" + rights + ":" + strACLs + ":" + desc;
+
+ // memory update
+ ACL ac = null;
+
+ try {
+ ac = (ACL) CMS.parseACL(resourceACLs);
+ } catch (EBaseException ex) {
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_PARSING_ERROR_0"));
+ }
+
+ mACLs.put(ac.getName(), ac);
+ }
+
+ /**
+ * gets an enumeration of resources
+ *
+ * @return an enumeration of resources contained in the ACL table
+ */
+ public Enumeration<ACL> aclResElements() {
+ return (mACLs.elements());
+ }
+
+ /**
+ * gets an enumeration of access evaluators
+ *
+ * @return an enumeraton of access evaluators
+ */
+ public Enumeration<IAccessEvaluator> aclEvaluatorElements() {
+ return (mEvaluators.elements());
+ }
+
+ /**
+ * gets the access evaluators
+ *
+ * @return handle to the access evaluators table
+ */
+ public Hashtable<String, IAccessEvaluator> getAccessEvaluators() {
+ return mEvaluators;
+ }
+
+ /**
+ * is this resource name unique
+ *
+ * @return true if unique; false otherwise
+ */
+ public boolean isTypeUnique(String type) {
+ if (mACLs.containsKey(type)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHORIZATION,
+ level, msg);
+ }
+
+ /*********************************
+ * abstract methods
+ **********************************/
+
+ /**
+ * update acls. called after memory upate is done to flush to permanent
+ * storage.
+ * <p>
+ */
+ protected abstract void flushResourceACLs() throws EACLsException;
+
+ /**
+ * an abstract class that enforces implementation of the
+ * authorize() method that will authorize an operation on a
+ * particular resource
+ *
+ * @param authToken the authToken associated with a user
+ * @param resource - the protected resource name
+ * @param operation - the protected resource operation name
+ * @exception EBaseException If an internal error occurred.
+ * @return authzToken
+ */
+ public abstract AuthzToken authorize(IAuthToken authToken, String resource, String operation) throws EBaseException;
+
+ public String getOrder() {
+ IConfigStore mainConfig = CMS.getConfigStore();
+ String order = "";
+
+ try {
+ order = mainConfig.getString("authz.evaluateOrder", "");
+ if (order.startsWith("allow"))
+ return "allow";
+ else
+ return "deny";
+ } catch (Exception e) {
+ }
+ return "deny";
+ }
+
+ public boolean evaluateACLs(IAuthToken authToken, String exp) {
+ return evaluateExpressions(authToken, exp);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authorization/ACLInterceptor.java b/base/server/cms/src/com/netscape/cms/authorization/ACLInterceptor.java
new file mode 100644
index 000000000..52d9eb899
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authorization/ACLInterceptor.java
@@ -0,0 +1,159 @@
+//--- 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) 2012 Red Hat, Inc.
+//All rights reserved.
+//--- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authorization;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.security.Principal;
+import java.util.Properties;
+
+import javax.servlet.ServletContext;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.ext.Provider;
+
+import org.jboss.resteasy.core.ResourceMethodInvoker;
+import org.jboss.resteasy.spi.Failure;
+
+import com.netscape.certsrv.acls.ACLMapping;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.authorization.IAuthzSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.ForbiddenException;
+import com.netscape.cms.realm.PKIPrincipal;
+
+/**
+ * @author Endi S. Dewata
+ */
+@Provider
+public class ACLInterceptor implements ContainerRequestFilter {
+
+ Properties authProperties;
+
+ @Context
+ ServletContext servletContext;
+
+ @Context
+ SecurityContext securityContext;
+
+ public synchronized void loadAuthProperties() throws IOException {
+
+ if (authProperties != null)
+ return;
+
+ URL url = servletContext.getResource("/WEB-INF/auth.properties");
+ authProperties = new Properties();
+ authProperties.load(url.openStream());
+ }
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ ResourceMethodInvoker methodInvoker = (ResourceMethodInvoker) requestContext
+ .getProperty("org.jboss.resteasy.core.ResourceMethodInvoker");
+ Method method = methodInvoker.getMethod();
+
+ ACLMapping aclMapping = method.getAnnotation(ACLMapping.class);
+
+ // If not available, get ACL mapping for the class.
+ if (aclMapping == null) {
+ Class<?> clazz = method.getDeclaringClass();
+ aclMapping = clazz.getAnnotation(ACLMapping.class);
+ }
+
+ // If still not available, it's unprotected, allow request.
+ if (aclMapping == null) {
+ CMS.debug("ACLInterceptor: No ACL mapping.");
+ return;
+ }
+
+ Principal principal = securityContext.getUserPrincipal();
+
+ // If unauthenticated, reject request.
+ if (principal == null) {
+ CMS.debug("ACLInterceptor: No user principal provided.");
+ throw new ForbiddenException("No user principal provided.");
+ }
+
+ // If unrecognized principal, reject request.
+ if (!(principal instanceof PKIPrincipal)) {
+ CMS.debug("ACLInterceptor: Invalid user principal.");
+ throw new ForbiddenException("Invalid user principal.");
+ }
+
+ PKIPrincipal pkiPrincipal = (PKIPrincipal) principal;
+ IAuthToken authToken = pkiPrincipal.getAuthToken();
+
+ // If missing auth token, reject request.
+ if (authToken == null) {
+ CMS.debug("ACLInterceptor: No authorization token present.");
+ throw new ForbiddenException("No authorization token present.");
+ }
+
+ try {
+ loadAuthProperties();
+
+ String name = aclMapping.value();
+ String value = authProperties.getProperty(name);
+
+ // If no property defined, allow request.
+ if (value == null) {
+ CMS.debug("ACLInterceptor: No ACL configuration.");
+ return;
+ }
+
+ String values[] = value.split(",");
+
+ // If invalid mapping, reject request.
+ if (values.length != 2) {
+ CMS.debug("ACLInterceptor: Invalid ACL mapping.");
+ throw new ForbiddenException("Invalid ACL mapping.");
+ }
+
+ // Check authorization.
+ IAuthzSubsystem mAuthz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ);
+ AuthzToken authzToken = mAuthz.authorize(
+ "DirAclAuthz",
+ authToken,
+ values[0], // resource
+ values[1]); // operation
+
+ // If not authorized, reject request.
+ if (authzToken == null) {
+ CMS.debug("ACLInterceptor: No authorization token present.");
+ throw new ForbiddenException("No authorization token present.");
+ }
+
+ } catch (EAuthzAccessDenied e) {
+ CMS.debug("ACLInterceptor: " + e.getMessage());
+ throw new ForbiddenException(e.toString());
+
+ } catch (IOException | EBaseException e) {
+ e.printStackTrace();
+ throw new Failure(e);
+ }
+
+ // Allow request.
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authorization/AuthMethodInterceptor.java b/base/server/cms/src/com/netscape/cms/authorization/AuthMethodInterceptor.java
new file mode 100644
index 000000000..c42ba26d0
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authorization/AuthMethodInterceptor.java
@@ -0,0 +1,168 @@
+//--- 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 com.netscape.cms.authorization;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.security.Principal;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Properties;
+
+import javax.servlet.ServletContext;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.ext.Provider;
+
+import org.jboss.resteasy.core.ResourceMethodInvoker;
+import org.jboss.resteasy.spi.Failure;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthMethodMapping;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.ForbiddenException;
+import com.netscape.cms.realm.PKIPrincipal;
+
+/**
+ * @author Endi S. Dewata
+ */
+@Provider
+public class AuthMethodInterceptor implements ContainerRequestFilter {
+
+ Properties authProperties;
+
+ @Context
+ ServletContext servletContext;
+
+ @Context
+ SecurityContext securityContext;
+
+ public synchronized void loadAuthProperties() throws IOException {
+
+ if (authProperties != null)
+ return;
+
+ authProperties = new Properties();
+
+ URL url = servletContext.getResource("/WEB-INF/auth-method.properties");
+
+ if (url == null) {
+ authProperties.put("default", "*");
+ authProperties.put("account", "certUserDBAuthMgr,passwdUserDBAuthMgr");
+ authProperties.put("admin", "certUserDBAuthMgr");
+ authProperties.put("agent", "certUserDBAuthMgr");
+ authProperties.put("profiles", "certUserDBAuthMgr");
+ authProperties.put("securityDomain.installToken", "passwdUserDBAuthMgr");
+ } else {
+ authProperties.load(url.openStream());
+ }
+ }
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ ResourceMethodInvoker methodInvoker = (ResourceMethodInvoker) requestContext
+ .getProperty("org.jboss.resteasy.core.ResourceMethodInvoker");
+ Method method = methodInvoker.getMethod();
+ Class<?> clazz = methodInvoker.getResourceClass();
+
+ CMS.debug("AuthMethodInterceptor: " + clazz.getSimpleName() + "." + method.getName() + "()");
+
+ // Get authentication mapping for the method.
+ AuthMethodMapping authMapping = method.getAnnotation(AuthMethodMapping.class);
+
+ // If not available, get authentication mapping for the class.
+ if (authMapping == null) {
+ authMapping = clazz.getAnnotation(AuthMethodMapping.class);
+ }
+
+ String name;
+ if (authMapping == null) {
+ // If not available, use the default mapping.
+ name = "default";
+ } else {
+ // Get the method label
+ name = authMapping.value();
+ }
+
+ CMS.debug("AuthMethodInterceptor: mapping name: " + name);
+
+ try {
+ loadAuthProperties();
+
+ String value = authProperties.getProperty(name);
+ Collection<String> authMethods = new HashSet<String>();
+ if (value != null) {
+ for (String v : value.split(",")) {
+ authMethods.add(v.trim());
+ }
+ }
+
+ CMS.debug("AuthMethodInterceptor: required auth methods: " + authMethods);
+
+ Principal principal = securityContext.getUserPrincipal();
+
+ // If unauthenticated, reject request.
+ if (principal == null) {
+ if (authMethods.isEmpty() || authMethods.contains("anonymous") || authMethods.contains("*")) {
+ CMS.debug("AuthMethodInterceptor: anonymous access allowed");
+ return;
+ }
+ CMS.debug("AuthMethodInterceptor: anonymous access not allowed");
+ throw new ForbiddenException("Anonymous access not allowed.");
+ }
+
+ // If unrecognized principal, reject request.
+ if (!(principal instanceof PKIPrincipal)) {
+ CMS.debug("AuthMethodInterceptor: unknown principal");
+ throw new ForbiddenException("Unknown user principal");
+ }
+
+ PKIPrincipal pkiPrincipal = (PKIPrincipal) principal;
+ IAuthToken authToken = pkiPrincipal.getAuthToken();
+
+ // If missing auth token, reject request.
+ if (authToken == null) {
+ CMS.debug("AuthMethodInterceptor: missing authentication token");
+ throw new ForbiddenException("Missing authentication token.");
+ }
+
+ String authManager = (String) authToken.get(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ CMS.debug("AuthMethodInterceptor: authentication manager: " + authManager);
+
+ if (authManager == null) {
+ CMS.debug("AuthMethodInterceptor: missing authentication manager");
+ throw new ForbiddenException("Missing authentication manager.");
+ }
+
+ if (authMethods.isEmpty() || authMethods.contains(authManager) || authMethods.contains("*")) {
+ CMS.debug("AuthMethodInterceptor: " + authManager + " allowed");
+ return;
+ }
+
+ throw new ForbiddenException("Authentication method not allowed.");
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new Failure(e);
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authorization/BasicAclAuthz.java b/base/server/cms/src/com/netscape/cms/authorization/BasicAclAuthz.java
new file mode 100644
index 000000000..729b017d8
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authorization/BasicAclAuthz.java
@@ -0,0 +1,213 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authorization;
+
+// cert server imports.
+import com.netscape.certsrv.acls.EACLsException;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.authorization.EAuthzInternalError;
+import com.netscape.certsrv.authorization.IAuthzManager;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A class for basic acls authorization manager
+ *
+ * @version $Revision$, $Date$
+ */
+public class BasicAclAuthz extends AAclAuthz
+ implements IAuthzManager, IExtendedPluginInfo {
+
+ // members
+
+ /* name of this authorization manager instance */
+ private String mName = null;
+
+ /* name of the authorization manager plugin */
+ private String mImplName = null;
+
+ /* configuration store */
+ @SuppressWarnings("unused")
+ private IConfigStore mConfig;
+
+ /* the system logger */
+ private ILogger mLogger = null;
+
+ protected static final String PROP_BASEDN = "basedn";
+
+ static {
+ mExtendedPluginInfo.add("nothing for now");
+ }
+
+ /**
+ * Default constructor
+ */
+ public BasicAclAuthz() {
+
+ /* Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ mConfigParams =
+ new String[] {
+ "dummy"
+ };
+ }
+
+ /**
+ *
+ */
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ mName = name;
+ mImplName = implName;
+ mConfig = config;
+ mLogger = CMS.getLogger();
+
+ super.init(config);
+
+ log(ILogger.LL_INFO, "initialization done");
+ }
+
+ /**
+ * gets the name of this authorization manager instance
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * gets the plugin name of this authorization manager.
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ /**
+ * check the authorization permission for the user associated with
+ * authToken on operation
+ * <p>
+ * Example:
+ * <p>
+ * For example, if UsrGrpAdminServlet needs to authorize the caller it would do be done in the following fashion:
+ *
+ * <PRE>
+ * try {
+ * authzTok = mAuthz.authorize(&quot;DirACLBasedAuthz&quot;, authToken, RES_GROUP, &quot;read&quot;);
+ * } catch (EBaseException e) {
+ * log(ILogger.LL_FAILURE, &quot;authorize call: &quot; + e.toString());
+ * }
+ * </PRE>
+ *
+ * @param authToken the authToken associated with a user
+ * @param resource - the protected resource name
+ * @param operation - the protected resource operation name
+ * @exception EAuthzInternalError if an internal error occurred.
+ * @exception EAuthzAccessDenied if access denied
+ * @return authzToken if success
+ */
+ public AuthzToken authorize(IAuthToken authToken, String resource, String operation)
+ throws EAuthzInternalError, EAuthzAccessDenied {
+ AuthzToken authzToken = new AuthzToken(this);
+
+ try {
+ checkPermission(authToken, resource, operation);
+
+ CMS.debug("BasicAclAuthz: authorization passed");
+
+ // compose AuthzToken
+ authzToken.set(AuthzToken.TOKEN_AUTHZ_RESOURCE, resource);
+ authzToken.set(AuthzToken.TOKEN_AUTHZ_OPERATION, operation);
+ authzToken.set(AuthzToken.TOKEN_AUTHZ_STATUS,
+ AuthzToken.AUTHZ_STATUS_SUCCESS);
+ } catch (EACLsException e) {
+ // audit here later
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("AUTHZ_EVALUATOR_AUTHORIZATION_FAILED"));
+ String params[] = { resource, operation };
+
+ throw new EAuthzAccessDenied(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZ_ACCESS_DENIED", params));
+ }
+
+ return authzToken;
+ }
+
+ public AuthzToken authorize(IAuthToken authToken, String expression)
+ throws EAuthzAccessDenied {
+ if (evaluateACLs(authToken, expression)) {
+ return (new AuthzToken(this));
+ } else {
+ String params[] = { expression };
+ throw new EAuthzAccessDenied(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZ_ACCESS_DENIED", params));
+ }
+ }
+
+ /**
+ * This currently does not flush to permanent storage
+ *
+ * @param id is the resource id
+ * @param strACLs
+ */
+ public void updateACLs(String id, String rights, String strACLs,
+ String desc) throws EACLsException {
+ try {
+ super.updateACLs(id, rights, strACLs, desc);
+ // flushResourceACLs();
+ } catch (EACLsException ex) {
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("AUTHZ_EVALUATOR_FLUSH_RESOURCES", ex.toString()));
+
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_UPDATE_FAIL"));
+ }
+ }
+
+ /**
+ * updates resourceACLs to permanent storage.
+ * currently not implemented for this authzMgr
+ */
+ protected void flushResourceACLs() throws EACLsException {
+ log(ILogger.LL_FAILURE, "flushResourceACL() is not implemented");
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_METHOD_NOT_IMPLEMENTED"));
+ }
+
+ /**
+ * graceful shutdown
+ */
+ public void shutdown() {
+ log(ILogger.LL_INFO, "shutting down");
+ }
+
+ /**
+ * Logs a message for this class in the system log file.
+ *
+ * @param level The log level.
+ * @param msg The message to log.
+ * @see com.netscape.certsrv.logging.ILogger
+ */
+ protected void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHORIZATION,
+ level, msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/authorization/DirAclAuthz.java b/base/server/cms/src/com/netscape/cms/authorization/DirAclAuthz.java
new file mode 100644
index 000000000..133fe759e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authorization/DirAclAuthz.java
@@ -0,0 +1,365 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.authorization;
+
+import java.util.Enumeration;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPModificationSet;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.acls.ACL;
+import com.netscape.certsrv.acls.EACLsException;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.authorization.EAuthzInternalError;
+import com.netscape.certsrv.authorization.IAuthzManager;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A class for ldap acls based authorization manager
+ * The ldap server used for acls is the cms internal ldap db.
+ *
+ * @version $Revision$, $Date$
+ */
+public class DirAclAuthz extends AAclAuthz
+ implements IAuthzManager, IExtendedPluginInfo {
+
+ // members
+
+ /* name of this authentication manager instance */
+ private String mName = null;
+
+ /* name of the authentication manager plugin */
+ private String mImplName = null;
+
+ /* configuration store */
+ private IConfigStore mConfig;
+
+ /* the system logger */
+ private ILogger mLogger = null;
+
+ protected static final String PROP_BASEDN = "basedn";
+
+ private ILdapConnFactory mLdapConnFactory = null;
+ private String mBaseDN = null;
+ private static boolean needsFlush = false;
+
+ static {
+ mExtendedPluginInfo.add("ldap.ldapconn.host;string,required;" +
+ "LDAP host to connect to");
+ mExtendedPluginInfo.add("ldap.ldapconn.port;number,required;" +
+ "LDAP port number (use 389, or 636 if SSL)");
+ mExtendedPluginInfo.add("ldap.ldapconn.secureConn;boolean;" +
+ "Use SSL to connect to directory?");
+ mExtendedPluginInfo.add("ldap.ldapconn.version;choice(3,2);" +
+ "LDAP protocol version");
+ mExtendedPluginInfo.add("ldap.basedn;string,required;Base DN to start sarching " +
+ "under. If the ACL's DN is 'cn=resourceACL, o=NetscapeCertificateServer' you " +
+ "might want to use 'o=NetscapeCertificateServer' here");
+ mExtendedPluginInfo.add("ldap.minConns;number;number of connections " +
+ "to keep open to directory server. Default 5.");
+ mExtendedPluginInfo.add("ldap.maxConns;number;when needed, connection "
+ +
+ "pool can grow to this many (multiplexed) connections. Default 1000");
+ }
+
+ /**
+ * Default constructor
+ */
+ public DirAclAuthz() {
+
+ /* Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ mConfigParams =
+ new String[] {
+ "ldap.ldapconn.host",
+ "ldap.ldapconn.port",
+ "ldap.ldapconn.secureConn",
+ "ldap.ldapconn.version",
+ "ldap.basedn",
+ "ldap.minConns",
+ "ldap.maxConns",
+ };
+ }
+
+ /**
+ *
+ */
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ mName = name;
+ mImplName = implName;
+ mConfig = config;
+ mLogger = CMS.getLogger();
+
+ super.init(config);
+
+ // initialize LDAP connection factory
+ IConfigStore ldapConfig = mConfig.getSubStore("ldap");
+
+ if (ldapConfig == null) {
+ log(ILogger.LL_MISCONF, "failed to get config ldap info");
+ return;
+ }
+
+ mBaseDN = ldapConfig.getString(PROP_BASEDN, null);
+
+ try {
+ @SuppressWarnings("unused")
+ String hostname = ldapConfig.getString("ldapconn.host"); // check for errors
+ } catch (EBaseException e) {
+ if (CMS.isPreOpMode())
+ return;
+ }
+
+ mLdapConnFactory = CMS.getLdapBoundConnFactory();
+ mLdapConnFactory.init(ldapConfig);
+
+ // retrieve aclResources from the LDAP server and load
+ // into memory
+ LDAPConnection conn = null;
+
+ CMS.debug("DirAclAuthz: about to ldap search aclResources");
+ try {
+ conn = getConn();
+ LDAPSearchResults res = conn.search(mBaseDN, LDAPv2.SCOPE_SUB,
+ "cn=aclResources", null, false);
+
+ returnConn(conn);
+ if (res.hasMoreElements()) {
+ log(ILogger.LL_INFO, "ldap search found cn=aclResources");
+
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+ LDAPAttribute aclRes = entry.getAttribute("resourceACLS");
+
+ @SuppressWarnings("unchecked")
+ Enumeration<String> en = aclRes.getStringValues();
+
+ for (; en != null && en.hasMoreElements();) {
+ addACLs(en.nextElement());
+ }
+ } else {
+ log(ILogger.LL_INFO, "ldap search found no cn=aclResources");
+ }
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("AUTHZ_EVALUATOR_INIT_ERROR", e.toString()));
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_CONNECT_LDAP_FAIL", mBaseDN));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("AUTHZ_EVALUATOR_INIT_ERROR", e.toString()));
+ }
+
+ log(ILogger.LL_INFO, "initialization done");
+ }
+
+ /**
+ * gets the name of this authorization manager instance
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * gets the plugin name of this authorization manager.
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ /**
+ * check the authorization permission for the user associated with
+ * authToken on operation
+ * <p>
+ * Example:
+ * <p>
+ * For example, if UsrGrpAdminServlet needs to authorize the caller it would do be done in the following fashion:
+ *
+ * <PRE>
+ * try {
+ * authzTok = mAuthz.authorize(&quot;DirAclAuthz&quot;, authToken, RES_GROUP, &quot;read&quot;);
+ * } catch (EBaseException e) {
+ * log(ILogger.LL_FAILURE, &quot;authorize call: &quot; + e.toString());
+ * }
+ * </PRE>
+ *
+ * @param authToken the authToken associated with a user
+ * @param resource - the protected resource name
+ * @param operation - the protected resource operation name
+ * @exception EBaseException If an internal error occurred.
+ * @return authzToken
+ */
+ public AuthzToken authorize(IAuthToken authToken, String resource, String operation)
+ throws EAuthzInternalError, EAuthzAccessDenied {
+ AuthzToken authzToken = new AuthzToken(this);
+
+ try {
+ checkPermission(authToken, resource, operation);
+ // compose AuthzToken
+ authzToken.set(AuthzToken.TOKEN_AUTHZ_RESOURCE, resource);
+ authzToken.set(AuthzToken.TOKEN_AUTHZ_OPERATION, operation);
+ authzToken.set(AuthzToken.TOKEN_AUTHZ_STATUS, AuthzToken.AUTHZ_STATUS_SUCCESS);
+ CMS.debug("DirAclAuthz: authorization passed");
+ } catch (EACLsException e) {
+ // audit here later
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("AUTHZ_EVALUATOR_AUTHORIZATION_FAILED"));
+ String params[] = { resource, operation };
+
+ throw new EAuthzAccessDenied(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZ_ACCESS_DENIED", params));
+ }
+
+ return authzToken;
+ }
+
+ public AuthzToken authorize(IAuthToken authToken, String expression)
+ throws EAuthzAccessDenied {
+ if (evaluateACLs(authToken, expression)) {
+ return (new AuthzToken(this));
+ } else {
+ String params[] = { expression };
+ throw new EAuthzAccessDenied(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZ_ACCESS_DENIED", params));
+ }
+ }
+
+ /**
+ * update acls. when memory update is done, flush to ldap.
+ * <p>
+ * Currently, it is possible that when the memory is updated successfully, and the ldap isn't, the memory upates
+ * lingers. The result is that the changes will only be done on ldap at the next update, or when the system shuts
+ * down, another flush will be attempted.
+ *
+ * @param id is the resource id
+ * @param rights The allowable rights for this resource
+ * @param strACLs has the same format as a resourceACLs entry acis
+ * on the ldap server
+ * @param desc The description for this resource
+ */
+ public void updateACLs(String id, String rights, String strACLs,
+ String desc) throws EACLsException {
+ try {
+ super.updateACLs(id, rights, strACLs, desc);
+ flushResourceACLs();
+ needsFlush = false;
+ } catch (EACLsException ex) {
+ // flushing failed, set flag
+ needsFlush = true;
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("AUTHZ_EVALUATOR_FLUSH_RESOURCES", ex.toString()));
+
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_UPDATE_FAIL"));
+ }
+ }
+
+ /**
+ * updates resourceACLs to ldap.
+ */
+ protected void flushResourceACLs() throws EACLsException {
+ // ldap update
+ LDAPConnection conn = null;
+
+ try {
+ LDAPAttribute attrs = new LDAPAttribute("resourceACLS");
+ LDAPModificationSet mod = new LDAPModificationSet();
+
+ Enumeration<ACL> en = aclResElements();
+
+ if (en.hasMoreElements() == true) {
+ while (en.hasMoreElements()) {
+ ACL a = en.nextElement();
+ String resAclString = a.getResourceACLs();
+
+ attrs.addValue(resAclString);
+ }
+
+ mod.add(LDAPModification.REPLACE, attrs);
+
+ conn = getConn();
+ conn.modify("cn=aclResources," + mBaseDN, mod);
+ }
+ } catch (LDAPException ex) {
+ System.out.println(ex.toString());
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_UPDATE_FAIL"));
+ } catch (Exception ex) {
+ System.out.println(ex.toString());
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_UPDATE_FAIL"));
+ } finally {
+ try {
+ returnConn(conn);
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, "couldn't return conn ?");
+ }
+ }
+ }
+
+ protected LDAPConnection getConn() throws ELdapException {
+ return mLdapConnFactory.getConn();
+ }
+
+ protected void returnConn(LDAPConnection conn) throws ELdapException {
+ mLdapConnFactory.returnConn(conn);
+ }
+
+ /**
+ * graceful shutdown
+ */
+ public void shutdown() {
+ if (needsFlush) {
+ // flush the changes
+ try {
+ flushResourceACLs();
+ } catch (EACLsException e) {
+ // flushing failed again...too bad
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("AUTHZ_EVALUATOR_FLUSH_ERROR", e.toString()));
+ }
+ }
+
+ try {
+ if (mLdapConnFactory != null) mLdapConnFactory.reset();
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("AUTHZ_EVALUATOR_LDAP_ERROR", e.toString()));
+ }
+ }
+
+ /**
+ * Logs a message for this class in the system log file.
+ *
+ * @param level The log level.
+ * @param msg The message to log.
+ * @see com.netscape.certsrv.logging.ILogger
+ */
+ protected void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHORIZATION,
+ level, msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/crl/CMSAuthInfoAccessExtension.java b/base/server/cms/src/com/netscape/cms/crl/CMSAuthInfoAccessExtension.java
new file mode 100644
index 000000000..8a8de4174
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/crl/CMSAuthInfoAccessExtension.java
@@ -0,0 +1,259 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.crl;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.extensions.AuthInfoAccessExtension;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.Extension;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.URIName;
+import netscape.security.x509.X500Name;
+
+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.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ca.ICMSCRLExtension;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * This represents a Authority Information Access CRL extension.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSAuthInfoAccessExtension
+ implements ICMSCRLExtension, IExtendedPluginInfo {
+ public static final String PROP_NUM_ADS = "numberOfAccessDescriptions";
+ public static final String PROP_ACCESS_METHOD = "accessMethod";
+ public static final String PROP_ACCESS_LOCATION_TYPE = "accessLocationType";
+ public static final String PROP_ACCESS_LOCATION = "accessLocation";
+
+ private static final String PROP_ACCESS_METHOD_OCSP = "ocsp";
+ private static final String PROP_ACCESS_METHOD_CAISSUERS = "caIssuers";
+ private static final String PROP_DIRNAME = "DirectoryName";
+ private static final String PROP_URINAME = "URI";
+
+ private ILogger mLogger = CMS.getLogger();
+
+ public CMSAuthInfoAccessExtension() {
+ }
+
+ public Extension setCRLExtensionCriticality(Extension ext,
+ boolean critical) {
+ AuthInfoAccessExtension authInfoAccessExt = (AuthInfoAccessExtension) ext;
+
+ authInfoAccessExt.setCritical(critical);
+
+ return authInfoAccessExt;
+ }
+
+ public Extension getCRLExtension(IConfigStore config, Object ip,
+ boolean critical) {
+ AuthInfoAccessExtension authInfoAccessExt = new AuthInfoAccessExtension(critical);
+
+ int numberOfAccessDescriptions = 0;
+
+ try {
+ numberOfAccessDescriptions = config.getInteger(PROP_NUM_ADS, 0);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_AIA_INVALID_NUM_ADS", e.toString()));
+ }
+
+ if (numberOfAccessDescriptions > 0) {
+
+ for (int i = 0; i < numberOfAccessDescriptions; i++) {
+ String accessMethod = null;
+ String accessLocationType = null;
+ String accessLocation = null;
+ ObjectIdentifier method = AuthInfoAccessExtension.METHOD_CA_ISSUERS;
+
+ try {
+ accessMethod = config.getString(PROP_ACCESS_METHOD + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_AIA_AD_AM_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_AIA_AD_AM_INVALID", e.toString()));
+ }
+
+ if (accessMethod != null && accessMethod.equals(PROP_ACCESS_METHOD_OCSP)) {
+ method = AuthInfoAccessExtension.METHOD_OCSP;
+ }
+
+ try {
+ accessLocationType = config.getString(PROP_ACCESS_LOCATION_TYPE + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_AIA_AD_ALT_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_AIA_AD_ALT_INVALID", e.toString()));
+ }
+
+ try {
+ accessLocation = config.getString(PROP_ACCESS_LOCATION + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_INVALID", e.toString()));
+ }
+
+ if (accessLocationType != null && accessLocation != null && accessLocation.length() > 0) {
+ if (accessLocationType.equalsIgnoreCase(PROP_DIRNAME)) {
+ try {
+ X500Name dirName = new X500Name(accessLocation);
+ authInfoAccessExt.addAccessDescription(method, new GeneralName(dirName));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_INVALID_500NAME", e.toString()));
+ }
+ } else if (accessLocationType.equalsIgnoreCase(PROP_URINAME)) {
+ URIName uriName = new URIName(accessLocation);
+ authInfoAccessExt.addAccessDescription(method, new GeneralName(uriName));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_INVALID_POTINT_TYPE", accessLocation));
+ }
+ } else {
+ accessLocationType = PROP_URINAME;
+ String hostname = CMS.getEENonSSLHost();
+ String port = CMS.getEENonSSLPort();
+ if (hostname != null && port != null) {
+ accessLocation = "http://" + hostname + ":" + port + "/ca/ee/ca/getCAChain?op=downloadBIN";
+ }
+ URIName uriName = new URIName(accessLocation);
+ authInfoAccessExt.addAccessDescription(AuthInfoAccessExtension.METHOD_CA_ISSUERS, new GeneralName(
+ uriName));
+ }
+ }
+ }
+
+ return authInfoAccessExt;
+ }
+
+ public String getCRLExtOID() {
+ return AuthInfoAccessExtension.ID.toString();
+ }
+
+ public void getConfigParams(IConfigStore config, NameValuePairs nvp) {
+
+ int numberOfAccessDescriptions = 0;
+
+ try {
+ numberOfAccessDescriptions = config.getInteger(PROP_NUM_ADS, 0);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_AIA_INVALID_NUM_ADS", e.toString()));
+ }
+ nvp.put(PROP_NUM_ADS, String.valueOf(numberOfAccessDescriptions));
+
+ for (int i = 0; i < numberOfAccessDescriptions; i++) {
+ String accessMethod = null;
+ String accessLocationType = null;
+ String accessLocation = null;
+
+ try {
+ accessMethod = config.getString(PROP_ACCESS_METHOD + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_AIA_AD_AM_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_AIA_AD_AM_INVALID", e.toString()));
+ }
+
+ if (accessMethod != null && accessMethod.length() > 0) {
+ nvp.put(PROP_ACCESS_METHOD + i, accessMethod);
+ } else {
+ nvp.put(PROP_ACCESS_METHOD + i, PROP_ACCESS_METHOD_CAISSUERS);
+ }
+
+ try {
+ accessLocationType = config.getString(PROP_ACCESS_LOCATION_TYPE + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_AIA_AD_ALT_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_AIA_AD_ALT_INVALID", e.toString()));
+ }
+
+ if (accessLocationType != null && accessLocationType.length() > 0) {
+ nvp.put(PROP_ACCESS_LOCATION_TYPE + i, accessLocationType);
+ } else {
+ nvp.put(PROP_ACCESS_LOCATION_TYPE + i, PROP_URINAME);
+ }
+
+ try {
+ accessLocation = config.getString(PROP_ACCESS_LOCATION + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_AIA_AD_AL_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_AIA_AD_AL_INVALID", e.toString()));
+ }
+
+ if (accessLocation != null && accessLocation.length() > 0) {
+ nvp.put(PROP_ACCESS_LOCATION + i, accessLocation);
+ } else {
+ String hostname = CMS.getEENonSSLHost();
+ String port = CMS.getEENonSSLPort();
+ if (hostname != null && port != null) {
+ accessLocation = "http://" + hostname + ":" + port + "/ca/ee/ca/getCAChain?op=downloadBIN";
+ }
+ nvp.put(PROP_ACCESS_LOCATION + i, accessLocation);
+ }
+ }
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ "enable;boolean;Check to enable Authority Information Access extension.",
+ "critical;boolean;Set criticality for Authority Information Access extension.",
+ PROP_NUM_ADS + ";number;Set number of Access Descriptions.",
+ PROP_ACCESS_METHOD + "0;choice(" + PROP_ACCESS_METHOD_CAISSUERS + "," +
+ PROP_ACCESS_METHOD_OCSP + ");Select access description method.",
+ PROP_ACCESS_LOCATION_TYPE + "0;choice(" + PROP_URINAME + "," +
+ PROP_DIRNAME + ");Select access location type.",
+ PROP_ACCESS_LOCATION + "0;string;Enter access location " +
+ "corresponding to the selected access location type.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-authorityinformationaccess",
+ PROP_ACCESS_METHOD + "1;choice(" + PROP_ACCESS_METHOD_CAISSUERS + "," +
+ PROP_ACCESS_METHOD_OCSP + ");Select access description method.",
+ PROP_ACCESS_LOCATION_TYPE + "1;choice(" + PROP_URINAME + "," +
+ PROP_DIRNAME + ");Select access location type.",
+ PROP_ACCESS_LOCATION + "1;string;Enter access location " +
+ "corresponding to the selected access location type.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-authorityinformationaccess",
+ PROP_ACCESS_METHOD + "2;choice(" + PROP_ACCESS_METHOD_CAISSUERS + "," +
+ PROP_ACCESS_METHOD_OCSP + ");Select access description method.",
+ PROP_ACCESS_LOCATION_TYPE + "2;choice(" + PROP_URINAME + "," +
+ PROP_DIRNAME + ");Select access location type.",
+ PROP_ACCESS_LOCATION + "2;string;Enter access location " +
+ "corresponding to the selected access location type.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-authorityinformationaccess",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";The Freshest CRL is a non critical CRL extension " +
+ "that identifies the delta CRL distribution points for a particular CRL."
+ };
+
+ return params;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_CA, level,
+ "CMSAuthInfoAccessExtension - " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/crl/CMSAuthorityKeyIdentifierExtension.java b/base/server/cms/src/com/netscape/cms/crl/CMSAuthorityKeyIdentifierExtension.java
new file mode 100644
index 000000000..a34a99373
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/crl/CMSAuthorityKeyIdentifierExtension.java
@@ -0,0 +1,165 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.crl;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateParsingException;
+import java.util.Locale;
+
+import netscape.security.x509.AuthorityKeyIdentifierExtension;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.Extension;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.KeyIdentifier;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.SerialNumber;
+import netscape.security.x509.SubjectKeyIdentifierExtension;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ca.ICMSCRLExtension;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * This represents an authority key identifier extension.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSAuthorityKeyIdentifierExtension
+ implements ICMSCRLExtension, IExtendedPluginInfo {
+ private ILogger mLogger = CMS.getLogger();
+
+ public CMSAuthorityKeyIdentifierExtension() {
+ }
+
+ public Extension setCRLExtensionCriticality(Extension ext,
+ boolean critical) {
+ AuthorityKeyIdentifierExtension authKeyIdExt = null;
+ KeyIdentifier keyId = null;
+ GeneralNames names = null;
+ SerialNumber sn = null;
+
+ try {
+ keyId = (KeyIdentifier) ((AuthorityKeyIdentifierExtension) ext).get(
+ AuthorityKeyIdentifierExtension.KEY_ID);
+ names = (GeneralNames) ((AuthorityKeyIdentifierExtension) ext).get(
+ AuthorityKeyIdentifierExtension.AUTH_NAME);
+ sn = (SerialNumber) ((AuthorityKeyIdentifierExtension) ext).get(
+ AuthorityKeyIdentifierExtension.SERIAL_NUMBER);
+ authKeyIdExt = new AuthorityKeyIdentifierExtension(critical, keyId, names, sn);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_AKI_EXT", e.toString()));
+ }
+ return authKeyIdExt;
+ }
+
+ public Extension getCRLExtension(IConfigStore config,
+ Object ip,
+ boolean critical) {
+ AuthorityKeyIdentifierExtension authKeyIdExt = null;
+ ICRLIssuingPoint crlIssuingPoint = (ICRLIssuingPoint) ip;
+
+ try {
+ KeyIdentifier keyId = null;
+
+ try {
+ X509CertInfo info = (X509CertInfo)
+ ((ICertificateAuthority) crlIssuingPoint.getCertificateAuthority()).getCACert().get(
+ X509CertImpl.NAME + "." + X509CertImpl.INFO);
+
+ if (info != null) {
+ CertificateExtensions caCertExtensions = (CertificateExtensions)
+ info.get(X509CertInfo.EXTENSIONS);
+
+ if (caCertExtensions != null) {
+ for (int i = 0; i < caCertExtensions.size(); i++) {
+ Extension caCertExt = caCertExtensions.elementAt(i);
+
+ if (caCertExt instanceof SubjectKeyIdentifierExtension) {
+ SubjectKeyIdentifierExtension id =
+ (SubjectKeyIdentifierExtension) caCertExt;
+
+ keyId = (KeyIdentifier)
+ id.get(SubjectKeyIdentifierExtension.KEY_ID);
+ }
+ }
+ }
+ }
+
+ } catch (CertificateParsingException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CERT_PARSING_ERROR", e.toString()));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CERT_CERT_EXCEPTION", e.toString()));
+ }
+
+ if (keyId != null) {
+ authKeyIdExt = new AuthorityKeyIdentifierExtension(critical, keyId, null, null);
+ } else {
+ GeneralNames gNames = new GeneralNames();
+
+ gNames.addElement(((ICertificateAuthority) crlIssuingPoint.getCertificateAuthority()).getX500Name());
+
+ authKeyIdExt =
+ new AuthorityKeyIdentifierExtension(critical, null, gNames,
+ new SerialNumber(((ICertificateAuthority) crlIssuingPoint.getCertificateAuthority())
+ .getCACert().getSerialNumber()));
+ }
+
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_AKI_EXT", e.toString()));
+ }
+
+ return authKeyIdExt;
+ }
+
+ public String getCRLExtOID() {
+ return PKIXExtensions.AuthorityKey_Id.toString();
+ }
+
+ public void getConfigParams(IConfigStore config, NameValuePairs nvp) {
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ //"type;choice(CRLExtension,CRLEntryExtension);CRL Extension Type. "+
+ //"This field is not editable.",
+ "enable;boolean;Check to enable Authority Key Identifier CRL extension.",
+ "critical;boolean;Set criticality for Authority Key Identifier CRL extension.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-authoritykeyidentifier",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";The authority key identifier extension provides a means " +
+ "of identifying the public key corresponding to the private " +
+ "key used to sign a CRL."
+ };
+
+ return params;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_CA, level,
+ "CMSAuthorityKeyIdentifierExtension - " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/crl/CMSCRLNumberExtension.java b/base/server/cms/src/com/netscape/cms/crl/CMSCRLNumberExtension.java
new file mode 100644
index 000000000..4e51b5c9b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/crl/CMSCRLNumberExtension.java
@@ -0,0 +1,107 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.crl;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Locale;
+
+import netscape.security.x509.CRLNumberExtension;
+import netscape.security.x509.Extension;
+import netscape.security.x509.PKIXExtensions;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ca.ICMSCRLExtension;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * This represents a CRL number extension.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSCRLNumberExtension
+ implements ICMSCRLExtension, IExtendedPluginInfo {
+ private ILogger mLogger = CMS.getLogger();
+
+ public CMSCRLNumberExtension() {
+ }
+
+ public Extension setCRLExtensionCriticality(Extension ext,
+ boolean critical) {
+ BigInteger crlNumber = null;
+ CRLNumberExtension crlNumberExt = null;
+
+ try {
+ crlNumber = (BigInteger)
+ ((CRLNumberExtension) ext).get(CRLNumberExtension.NUMBER);
+ crlNumberExt = new CRLNumberExtension(Boolean.valueOf(critical),
+ crlNumber);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_CRL_NUMBER_EXT", e.toString()));
+ }
+ return crlNumberExt;
+ }
+
+ public Extension getCRLExtension(IConfigStore config,
+ Object ip,
+ boolean critical) {
+ CRLNumberExtension crlNumberExt = null;
+ ICRLIssuingPoint crlIssuingPoint = (ICRLIssuingPoint) ip;
+
+ try {
+ crlNumberExt = new CRLNumberExtension(Boolean.valueOf(critical),
+ crlIssuingPoint.getNextCRLNumber());
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_CRL_NUMBER_EXT", e.toString()));
+ }
+ return crlNumberExt;
+ }
+
+ public String getCRLExtOID() {
+ return PKIXExtensions.CRLNumber_Id.toString();
+ }
+
+ public void getConfigParams(IConfigStore config, NameValuePairs nvp) {
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ //"type;choice(CRLExtension,CRLEntryExtension);"+
+ //"CRL Extension type. This field is not editable.",
+ "enable;boolean;Check to enable CRL Number extension.",
+ "critical;boolean;Set criticality for CRL Number extension.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-crlnumber",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";The CRL number is a non-critical CRL extension " +
+ "which conveys a monotonically increasing sequence number " +
+ "for each CRL issued by a CA"
+ };
+
+ return params;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_CA, level,
+ "CMSCRLNumberExtension - " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/crl/CMSCRLReasonExtension.java b/base/server/cms/src/com/netscape/cms/crl/CMSCRLReasonExtension.java
new file mode 100644
index 000000000..02bd40927
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/crl/CMSCRLReasonExtension.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.crl;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.Extension;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.RevocationReason;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ca.ICMSCRLExtension;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * This represents a CRL reason extension.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSCRLReasonExtension
+ implements ICMSCRLExtension, IExtendedPluginInfo {
+ private ILogger mLogger = CMS.getLogger();
+
+ public CMSCRLReasonExtension() {
+ }
+
+ public Extension setCRLExtensionCriticality(Extension ext,
+ boolean critical) {
+ RevocationReason reason = null;
+ CRLReasonExtension crlReasonExt = null;
+
+ try {
+ reason = (RevocationReason) ((CRLReasonExtension) ext).get(CRLReasonExtension.REASON);
+ crlReasonExt = new CRLReasonExtension(Boolean.valueOf(critical), reason);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_CRL_REASON_EXT", e.toString()));
+ }
+ return crlReasonExt;
+ }
+
+ public Extension getCRLExtension(IConfigStore config,
+ Object crlIssuingPoint,
+ boolean critical) {
+ CRLReasonExtension crlReasonExt = null;
+
+ return crlReasonExt;
+ }
+
+ public String getCRLExtOID() {
+ return PKIXExtensions.ReasonCode_Id.toString();
+ }
+
+ public void getConfigParams(IConfigStore config, NameValuePairs nvp) {
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ //"type;choice(CRLExtension,CRLEntryExtension);"+
+ //"CRL Entry Extension type. This field is not editable.",
+ "enable;boolean;Check to enable reason code CRL entry extension.",
+ "critical;boolean;Set criticality for reason code CRL entry extension.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-crlreason",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";The CRL reason code is a non-critical CRL entry extension " +
+ "that identifies the reason for the certificate revocation."
+ };
+
+ return params;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_CA, level,
+ "CMSCRLReasonExtension - " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/crl/CMSCertificateIssuerExtension.java b/base/server/cms/src/com/netscape/cms/crl/CMSCertificateIssuerExtension.java
new file mode 100644
index 000000000..84181a8dd
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/crl/CMSCertificateIssuerExtension.java
@@ -0,0 +1,224 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.crl;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateIssuerExtension;
+import netscape.security.x509.Extension;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.URIName;
+import netscape.security.x509.X500Name;
+
+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.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ca.ICMSCRLExtension;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * This represents a certificate issuer extension.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSCertificateIssuerExtension
+ implements ICMSCRLExtension, IExtendedPluginInfo {
+ private ILogger mLogger = CMS.getLogger();
+
+ public CMSCertificateIssuerExtension() {
+ }
+
+ public Extension setCRLExtensionCriticality(Extension ext,
+ boolean critical) {
+ CertificateIssuerExtension certIssuerExt = null;
+ GeneralNames names = null;
+
+ try {
+ names = (GeneralNames) ((CertificateIssuerExtension) ext).get(
+ CertificateIssuerExtension.CERTIFICATE_ISSUER);
+ certIssuerExt = new CertificateIssuerExtension(Boolean.valueOf(critical),
+ names);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_CERT_ISSUER_EXT", e.toString()));
+ }
+ return certIssuerExt;
+ }
+
+ public Extension getCRLExtension(IConfigStore config,
+ Object ip,
+ boolean critical) {
+ CertificateIssuerExtension certIssuerExt = null;
+ int numNames = 0;
+
+ try {
+ numNames = config.getInteger("numNames", 0);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_INVALID_NUM_NAMES", e.toString()));
+ }
+ if (numNames > 0) {
+ GeneralNames names = new GeneralNames();
+
+ for (int i = 0; i < numNames; i++) {
+ String nameType = null;
+
+ try {
+ nameType = config.getString("nameType" + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CRL_CREATE_UNDEFINED_TYPE", Integer.toString(i), e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CRL_CREATE_INVALID_TYPE", Integer.toString(i), e.toString()));
+ }
+
+ if (nameType != null) {
+ String name = null;
+
+ try {
+ name = config.getString("name" + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CRL_CREATE_UNDEFINED_TYPE", Integer.toString(i), e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CRL_CREATE_INVALID_TYPE", Integer.toString(i), e.toString()));
+ }
+
+ if (name != null && name.length() > 0) {
+ if (nameType.equalsIgnoreCase("DirectoryName")) {
+ try {
+ X500Name dirName = new X500Name(name);
+
+ names.addElement(dirName);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_INVALID_500NAME", e.toString()));
+ }
+ } else if (nameType.equalsIgnoreCase("URI")) {
+ URIName uriName = new URIName(name);
+
+ names.addElement(uriName);
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_INVALID_NAME_TYPE", nameType));
+ }
+ }
+ }
+ }
+
+ if (names.size() > 0) {
+ try {
+ certIssuerExt = new CertificateIssuerExtension(
+ Boolean.valueOf(critical), names);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_CERT_ISSUER_EXT", e.toString()));
+ }
+ }
+ }
+
+ return certIssuerExt;
+ }
+
+ public String getCRLExtOID() {
+ return PKIXExtensions.CertificateIssuer_Id.toString();
+ }
+
+ public void getConfigParams(IConfigStore config, NameValuePairs nvp) {
+ int numNames = 0;
+
+ try {
+ numNames = config.getInteger("numNames", 0);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_INVALID_NUM_NAMES", e.toString()));
+ }
+ nvp.put("numNames", String.valueOf(numNames));
+
+ for (int i = 0; i < numNames; i++) {
+ String nameType = null;
+
+ try {
+ nameType = config.getString("nameType" + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CRL_CREATE_UNDEFINED_TYPE", Integer.toString(i), e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_INVALID_TYPE", Integer.toString(i), e.toString()));
+ }
+
+ if (nameType != null && nameType.length() > 0) {
+ nvp.put("nameType" + i, nameType);
+ } else {
+ nvp.put("nameType" + i, "");
+ }
+
+ String name = null;
+
+ try {
+ name = config.getString("name" + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CRL_CREATE_UNDEFINED_TYPE", Integer.toString(i), e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_INVALID_TYPE", Integer.toString(i), e.toString()));
+ }
+
+ if (name != null && name.length() > 0) {
+ nvp.put("name" + i, name);
+ } else {
+ nvp.put("name" + i, "");
+ }
+ }
+
+ if (numNames < 3) {
+ for (int i = numNames; i < 3; i++) {
+ nvp.put("nameType" + i, "");
+ nvp.put("name" + i, "");
+ }
+ }
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ //"type;choice(CRLExtension,CRLEntryExtension);CRL Entry Extension type."+
+ //" This field is not editable.",
+ "enable;boolean;Check to enable Certificate Issuer CRL entry extension.",
+ "critical;boolean;Set criticality for Certificate Issuer CRL entry extension.",
+ "numNames;number;Set number of certificate issuer names for the CRL entry.",
+ "nameType0;choice(DirectoryName,URI);Select Certificate Issuer name type.",
+ "name0;string;Enter Certificate Issuer name corresponding to the selected name type.",
+ "nameType1;choice(DirectoryName,URI);Select Certificate Issuer name type.",
+ "name1;string;Enter Certificate Issuer name corresponding to the selected name type.",
+ "nameType2;choice(DirectoryName,URI);Select Certificate Issuer name type.",
+ "name2;string;Enter Certificate Issuer name corresponding to the selected name type.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-certificateissuer",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";This CRL entry extension identifies the certificate issuer" +
+ " associated with an entry in an indirect CRL."
+ };
+
+ return params;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_CA, level, msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/crl/CMSDeltaCRLIndicatorExtension.java b/base/server/cms/src/com/netscape/cms/crl/CMSDeltaCRLIndicatorExtension.java
new file mode 100644
index 000000000..e3e8d2311
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/crl/CMSDeltaCRLIndicatorExtension.java
@@ -0,0 +1,108 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.crl;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Locale;
+
+import netscape.security.x509.DeltaCRLIndicatorExtension;
+import netscape.security.x509.Extension;
+import netscape.security.x509.PKIXExtensions;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ca.ICMSCRLExtension;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * This represents a delta CRL indicator extension.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSDeltaCRLIndicatorExtension
+ implements ICMSCRLExtension, IExtendedPluginInfo {
+ private ILogger mLogger = CMS.getLogger();
+
+ public CMSDeltaCRLIndicatorExtension() {
+ }
+
+ public Extension setCRLExtensionCriticality(Extension ext,
+ boolean critical) {
+ BigInteger baseCRLNumber = null;
+ DeltaCRLIndicatorExtension deltaCRLIndicatorExt = null;
+
+ try {
+ baseCRLNumber = (BigInteger)
+ ((DeltaCRLIndicatorExtension) ext).get(DeltaCRLIndicatorExtension.NUMBER);
+ deltaCRLIndicatorExt = new DeltaCRLIndicatorExtension(
+ Boolean.valueOf(critical),
+ baseCRLNumber);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DELTA_CRL_EXT", e.toString()));
+ }
+ return deltaCRLIndicatorExt;
+ }
+
+ public Extension getCRLExtension(IConfigStore config,
+ Object ip,
+ boolean critical) {
+ DeltaCRLIndicatorExtension deltaCRLIndicatorExt = null;
+ ICRLIssuingPoint crlIssuingPoint = (ICRLIssuingPoint) ip;
+
+ try {
+ deltaCRLIndicatorExt = new DeltaCRLIndicatorExtension(
+ Boolean.valueOf(critical),
+ crlIssuingPoint.getCRLNumber());
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DELTA_CRL_EXT", e.toString()));
+ }
+ return deltaCRLIndicatorExt;
+ }
+
+ public String getCRLExtOID() {
+ return PKIXExtensions.DeltaCRLIndicator_Id.toString();
+ }
+
+ public void getConfigParams(IConfigStore config, NameValuePairs nvp) {
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ //"type;choice(CRLExtension,CRLEntryExtension);"+
+ //"CRL Extension type. This field is not editable.",
+ "enable;boolean;Check to enable Delta CRL Indicator extension.",
+ "critical;boolean;Set criticality for Delta CRL Indicator extension.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-crlnumber",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";The Delta CRL Indicator is a critical CRL extension " +
+ "which identifies a delta-CRL."
+ };
+
+ return params;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_CA, level,
+ "CMSDeltaCRLIndicatorExtension - " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/crl/CMSFreshestCRLExtension.java b/base/server/cms/src/com/netscape/cms/crl/CMSFreshestCRLExtension.java
new file mode 100644
index 000000000..50031c61a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/crl/CMSFreshestCRLExtension.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.crl;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.x509.CRLDistributionPoint;
+import netscape.security.x509.Extension;
+import netscape.security.x509.FreshestCRLExtension;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.GeneralNamesException;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.URIName;
+import netscape.security.x509.X500Name;
+
+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.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ca.ICMSCRLExtension;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * This represents a freshest CRL extension.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSFreshestCRLExtension
+ implements ICMSCRLExtension, IExtendedPluginInfo {
+ public static final String PROP_NUM_POINTS = "numPoints";
+ public static final String PROP_POINTTYPE = "pointType";
+ public static final String PROP_POINTNAME = "pointName";
+ public static final String PROP_DIRNAME = "DirectoryName";
+ public static final String PROP_URINAME = "URI";
+
+ private ILogger mLogger = CMS.getLogger();
+
+ public CMSFreshestCRLExtension() {
+ }
+
+ public Extension setCRLExtensionCriticality(Extension ext,
+ boolean critical) {
+ FreshestCRLExtension freshestCRLExt = (FreshestCRLExtension) ext;
+
+ freshestCRLExt.setCritical(critical);
+
+ return freshestCRLExt;
+ }
+
+ public Extension getCRLExtension(IConfigStore config, Object ip,
+ boolean critical) {
+ FreshestCRLExtension freshestCRLExt = null;
+
+ int numPoints = 0;
+
+ try {
+ numPoints = config.getInteger("numPoints", 0);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_ISSUER_INVALID_NUM_NAMES", e.toString()));
+ }
+
+ if (numPoints > 0) {
+
+ for (int i = 0; i < numPoints; i++) {
+ CRLDistributionPoint crlDP = new CRLDistributionPoint();
+ GeneralNames names = new GeneralNames();
+ String pointType = null;
+
+ try {
+ pointType = config.getString(PROP_POINTTYPE + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_INVALID", e.toString()));
+ }
+
+ if (pointType != null) {
+ String pointName = null;
+
+ try {
+ pointName = config.getString(PROP_POINTNAME + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_INVALID", e.toString()));
+ }
+
+ if (pointName != null && pointName.length() > 0) {
+ if (pointType.equalsIgnoreCase(PROP_DIRNAME)) {
+ try {
+ X500Name dirName = new X500Name(pointName);
+
+ names.addElement(dirName);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_INVALID_500NAME", e.toString()));
+ }
+ } else if (pointType.equalsIgnoreCase(PROP_URINAME)) {
+ URIName uriName = new URIName(pointName);
+
+ names.addElement(uriName);
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_INVALID_POTINT_TYPE", pointType));
+ }
+ }
+ }
+
+ if (names.size() > 0) {
+ try {
+ crlDP.setFullName(names);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CANNOT_SET_NAME", e.toString()));
+ } catch (GeneralNamesException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CANNOT_SET_NAME", e.toString()));
+ }
+ }
+
+ if (i > 0) {
+ freshestCRLExt.addPoint(crlDP);
+ } else {
+ freshestCRLExt = new FreshestCRLExtension(crlDP);
+ }
+ }
+ }
+
+ return freshestCRLExt;
+ }
+
+ public String getCRLExtOID() {
+ return PKIXExtensions.FreshestCRL_Id.toString();
+ }
+
+ public void getConfigParams(IConfigStore config, NameValuePairs nvp) {
+
+ int numPoints = 0;
+
+ try {
+ numPoints = config.getInteger(PROP_NUM_POINTS, 0);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, "Invalid numPoints property for CRL " +
+ "Freshest CRL extension - " + e);
+ }
+ nvp.put(PROP_NUM_POINTS, String.valueOf(numPoints));
+
+ for (int i = 0; i < numPoints; i++) {
+ String pointType = null;
+
+ try {
+ pointType = config.getString(PROP_POINTTYPE + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_INVALID", e.toString()));
+ }
+
+ if (pointType != null && pointType.length() > 0) {
+ nvp.put(PROP_POINTTYPE + i, pointType);
+ } else {
+ nvp.put(PROP_POINTTYPE + i, "");
+ }
+
+ String pointName = null;
+
+ try {
+ pointName = config.getString(PROP_POINTNAME + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_INVALID", e.toString()));
+ }
+
+ if (pointName != null && pointName.length() > 0) {
+ nvp.put(PROP_POINTNAME + i, pointName);
+ } else {
+ nvp.put(PROP_POINTNAME + i, "");
+ }
+ }
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ "enable;boolean;Check to enable Freshest CRL extension.",
+ "critical;boolean;Set criticality for Freshest CRL extension.",
+ PROP_NUM_POINTS + ";number;Set number of CRL distribution points.",
+ PROP_POINTTYPE + "0;choice(" + PROP_DIRNAME + "," + PROP_URINAME +
+ ");Select CRL distribution point name type.",
+ PROP_POINTNAME + "0;string;Enter CRL distribution point name " +
+ "corresponding to the selected point type.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-issuingdistributionpoint",
+ PROP_POINTTYPE + "1;choice(" + PROP_DIRNAME + "," + PROP_URINAME +
+ ");Select CRL distribution point name type.",
+ PROP_POINTNAME + "1;string;Enter CRL distribution point name " +
+ "corresponding to the selected point type.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-issuingdistributionpoint",
+ PROP_POINTTYPE + "2;choice(" + PROP_DIRNAME + "," + PROP_URINAME +
+ ");Select CRL distribution point name type.",
+ PROP_POINTNAME + "2;string;Enter CRL distribution point name " +
+ "corresponding to the selected point type.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-issuingdistributionpoint",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";The Freshest CRL is a non critical CRL extension " +
+ "that identifies the delta CRL distribution points for a particular CRL."
+ };
+
+ return params;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_CA, level,
+ "CMSFreshestCRLExtension - " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/crl/CMSHoldInstructionExtension.java b/base/server/cms/src/com/netscape/cms/crl/CMSHoldInstructionExtension.java
new file mode 100644
index 000000000..b7945c0b6
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/crl/CMSHoldInstructionExtension.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.crl;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.Extension;
+import netscape.security.x509.HoldInstructionExtension;
+import netscape.security.x509.PKIXExtensions;
+
+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.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ca.ICMSCRLExtension;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * This represents a hold instruction extension.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSHoldInstructionExtension
+ implements ICMSCRLExtension, IExtendedPluginInfo {
+ public static final String PROP_INSTR = "instruction";
+ public static final String PROP_INSTR_NONE = "none";
+ public static final String PROP_INSTR_CALLISSUER = "callissuer";
+ public static final String PROP_INSTR_REJECT = "reject";
+
+ private ILogger mLogger = CMS.getLogger();
+
+ public CMSHoldInstructionExtension() {
+ }
+
+ public Extension setCRLExtensionCriticality(Extension ext,
+ boolean critical) {
+ HoldInstructionExtension holdInstrExt = null;
+
+ try {
+ ObjectIdentifier holdInstr =
+ ((HoldInstructionExtension) ext).getHoldInstructionCode();
+
+ holdInstrExt = new HoldInstructionExtension(Boolean.valueOf(critical),
+ holdInstr);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_HOLD_INSTR_EXT", e.toString()));
+ }
+ return holdInstrExt;
+ }
+
+ public Extension getCRLExtension(IConfigStore config,
+ Object ip,
+ boolean critical) {
+ HoldInstructionExtension holdInstrExt = null;
+ String instruction = null;
+
+ try {
+ instruction = config.getString(PROP_INSTR);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_HOLD_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_HOLD_INVALID", e.toString()));
+ }
+
+ ObjectIdentifier holdInstr = HoldInstructionExtension.NONE_HOLD_INSTR_OID;
+
+ if (instruction != null) {
+ if (instruction.equalsIgnoreCase(PROP_INSTR_CALLISSUER)) {
+ holdInstr = HoldInstructionExtension.CALL_ISSUER_HOLD_INSTR_OID;
+ } else if (instruction.equalsIgnoreCase(PROP_INSTR_REJECT)) {
+ holdInstr = HoldInstructionExtension.REJECT_HOLD_INSTR_OID;
+ }
+ }
+ try {
+ holdInstrExt = new HoldInstructionExtension(Boolean.valueOf(critical),
+ holdInstr);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_HOLD_INSTR_EXT", e.toString()));
+ }
+
+ return holdInstrExt;
+ }
+
+ public String getCRLExtOID() {
+ return PKIXExtensions.HoldInstructionCode_Id.toString();
+ }
+
+ public void getConfigParams(IConfigStore config, NameValuePairs nvp) {
+ String instruction = null;
+
+ try {
+ instruction = config.getString(PROP_INSTR);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_HOLD_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_HOLD_INVALID", e.toString()));
+ }
+ if (instruction != null) {
+ if (!(instruction.equalsIgnoreCase(PROP_INSTR_NONE) ||
+ instruction.equalsIgnoreCase(PROP_INSTR_CALLISSUER) ||
+ instruction.equalsIgnoreCase(PROP_INSTR_REJECT))) {
+ instruction = PROP_INSTR_NONE;
+ }
+ } else {
+ instruction = PROP_INSTR_NONE;
+ }
+ nvp.put(PROP_INSTR, instruction);
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ //"type;choice(CRLExtension,CRLEntryExtension);"+
+ //"CRL Entry Extension type. This field is not editable.",
+ "enable;boolean;Check to enable Hold Instruction CRL entry extension.",
+ "critical;boolean;Set criticality for Hold Instruction CRL entry extension.",
+ PROP_INSTR + ";choice(" + PROP_INSTR_NONE + "," + PROP_INSTR_CALLISSUER + "," +
+ PROP_INSTR_REJECT + ");Select hold instruction code.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-holdinstruction",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";The hold instruction code is a non-critical CRL entry " +
+ "extension that provides a registered instruction identifier " +
+ "which indicates the action to be taken after encountering " +
+ "a certificate that has been placed on hold."
+ };
+
+ return params;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_CA, level,
+ "CMSHoldInstructionExtension - " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/crl/CMSInvalidityDateExtension.java b/base/server/cms/src/com/netscape/cms/crl/CMSInvalidityDateExtension.java
new file mode 100644
index 000000000..6ff61fb44
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/crl/CMSInvalidityDateExtension.java
@@ -0,0 +1,99 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.crl;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Locale;
+
+import netscape.security.x509.Extension;
+import netscape.security.x509.InvalidityDateExtension;
+import netscape.security.x509.PKIXExtensions;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ca.ICMSCRLExtension;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * This represents a invalidity date extension.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSInvalidityDateExtension
+ implements ICMSCRLExtension, IExtendedPluginInfo {
+ private ILogger mLogger = CMS.getLogger();
+
+ public CMSInvalidityDateExtension() {
+ }
+
+ public Extension setCRLExtensionCriticality(Extension ext,
+ boolean critical) {
+ InvalidityDateExtension invalidityDateExt = null;
+
+ try {
+ Date invalidityDate = ((InvalidityDateExtension) ext).getInvalidityDate();
+
+ invalidityDateExt = new InvalidityDateExtension(Boolean.valueOf(critical),
+ invalidityDate);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_INVALIDITY_DATE_EXT", e.toString()));
+ }
+ return invalidityDateExt;
+ }
+
+ public Extension getCRLExtension(IConfigStore config,
+ Object crlIssuingPoint,
+ boolean critical) {
+ InvalidityDateExtension invalidityDateExt = null;
+
+ return invalidityDateExt;
+ }
+
+ public String getCRLExtOID() {
+ return PKIXExtensions.InvalidityDate_Id.toString();
+ }
+
+ public void getConfigParams(IConfigStore config, NameValuePairs nvp) {
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ //"type;choice(CRLExtension,CRLEntryExtension);"+
+ //"CRL Entry Extension type. This field is not editable.",
+ "enable;boolean;Check to enable Invalidity Date CRL entry extension.",
+ "critical;boolean;Set criticality for Invalidity Date CRL entry extension.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-invaliditydate",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";The invalidity date is a non-critical CRL entry extension " +
+ "that provides the date on which it is known or suspected " +
+ "that the private key was compromised or that the certificate" +
+ " otherwise became invalid."
+ };
+
+ return params;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_CA, level,
+ "CMSInvalidityDateExtension - " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/crl/CMSIssuerAlternativeNameExtension.java b/base/server/cms/src/com/netscape/cms/crl/CMSIssuerAlternativeNameExtension.java
new file mode 100644
index 000000000..fb2a6e0d5
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/crl/CMSIssuerAlternativeNameExtension.java
@@ -0,0 +1,284 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.crl;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.util.DerValue;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.DNSName;
+import netscape.security.x509.EDIPartyName;
+import netscape.security.x509.Extension;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.IPAddressName;
+import netscape.security.x509.IssuerAlternativeNameExtension;
+import netscape.security.x509.OIDName;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.RFC822Name;
+import netscape.security.x509.URIName;
+import netscape.security.x509.X500Name;
+
+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.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ca.ICMSCRLExtension;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * This represents a issuer alternative name extension.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSIssuerAlternativeNameExtension
+ implements ICMSCRLExtension, IExtendedPluginInfo {
+ private static final String PROP_RFC822_NAME = "rfc822Name";
+ private static final String PROP_DNS_NAME = "dNSName";
+ private static final String PROP_DIR_NAME = "directoryName";
+ private static final String PROP_EDI_NAME = "ediPartyName";
+ private static final String PROP_URI_NAME = "URI";
+ private static final String PROP_IP_NAME = "iPAddress";
+ private static final String PROP_OID_NAME = "OID";
+ private static final String PROP_OTHER_NAME = "otherName";
+
+ private ILogger mLogger = CMS.getLogger();
+
+ public CMSIssuerAlternativeNameExtension() {
+ }
+
+ public Extension setCRLExtensionCriticality(Extension ext,
+ boolean critical) {
+ IssuerAlternativeNameExtension issuerAltNameExt = null;
+ GeneralNames names = null;
+
+ try {
+ names = (GeneralNames) ((IssuerAlternativeNameExtension) ext)
+ .get(IssuerAlternativeNameExtension.ISSUER_NAME);
+ issuerAltNameExt = new IssuerAlternativeNameExtension(Boolean.valueOf(critical), names);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_ISSUER_ALT_NAME_EXT", e.toString()));
+ }
+ return issuerAltNameExt;
+ }
+
+ public Extension getCRLExtension(IConfigStore config,
+ Object ip,
+ boolean critical) {
+ IssuerAlternativeNameExtension issuerAltNameExt = null;
+ int numNames = 0;
+
+ try {
+ numNames = config.getInteger("numNames", 0);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_ISSUER_INVALID_NUM_NAMES", e.toString()));
+ }
+ if (numNames > 0) {
+ GeneralNames names = new GeneralNames();
+
+ for (int i = 0; i < numNames; i++) {
+ String nameType = null;
+
+ try {
+ nameType = config.getString("nameType" + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CRL_CREATE_ISSUER_UNDEFINED_TYPE", Integer.toString(i), e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CRL_CREATE_ISSUER_INVALID_TYPE", Integer.toString(i), e.toString()));
+ }
+
+ if (nameType != null && nameType.length() > 0) {
+ String name = null;
+
+ try {
+ name = config.getString("name" + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_ISSUER_UNDEFINED_TYPE",
+ Integer.toString(i), e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CRL_CREATE_ISSUER_INVALID_TYPE", Integer.toString(i), e.toString()));
+ }
+
+ if (name != null && name.length() > 0) {
+ if (nameType.equalsIgnoreCase(PROP_DIR_NAME)) {
+ try {
+ X500Name dirName = new X500Name(name);
+
+ names.addElement(dirName);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_INVALID_500NAME", e.toString()));
+ }
+ } else if (nameType.equalsIgnoreCase(PROP_RFC822_NAME)) {
+ RFC822Name rfc822Name = new RFC822Name(name);
+
+ names.addElement(rfc822Name);
+ } else if (nameType.equalsIgnoreCase(PROP_DNS_NAME)) {
+ DNSName dnsName = new DNSName(name);
+
+ names.addElement(dnsName);
+ } else if (nameType.equalsIgnoreCase(PROP_EDI_NAME)) {
+ EDIPartyName ediName = new EDIPartyName(name);
+
+ names.addElement(ediName);
+ } else if (nameType.equalsIgnoreCase(PROP_URI_NAME)) {
+ URIName uriName = new URIName(name);
+
+ names.addElement(uriName);
+ } else if (nameType.equalsIgnoreCase(PROP_IP_NAME)) {
+ IPAddressName ipName = new IPAddressName(name);
+
+ names.addElement(ipName);
+ } else if (nameType.equalsIgnoreCase(PROP_OID_NAME)) {
+ ObjectIdentifier oid = new ObjectIdentifier(name);
+ OIDName oidNmae = new OIDName(oid);
+
+ names.addElement(oidNmae);
+ } else if (nameType.equalsIgnoreCase(PROP_OTHER_NAME)) {
+
+ try {
+ byte[] val = Utils.base64decode(name);
+ DerValue derVal = new DerValue(new ByteArrayInputStream(val));
+ GeneralName generalName = new GeneralName(derVal);
+
+ names.addElement(generalName);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_INVALID_OTHER_NAME", e.toString()));
+ }
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_ISSUER_INVALID_TYPE", nameType, ""));
+ }
+ }
+ }
+ }
+
+ if (names.size() > 0) {
+ try {
+ issuerAltNameExt = new IssuerAlternativeNameExtension(
+ Boolean.valueOf(critical), names);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_ISSUER_ALT_NAME_EXT", e.toString()));
+ }
+ }
+ }
+
+ return issuerAltNameExt;
+ }
+
+ public String getCRLExtOID() {
+ return PKIXExtensions.IssuerAlternativeName_Id.toString();
+ }
+
+ public void getConfigParams(IConfigStore config, NameValuePairs nvp) {
+ int numNames = 0;
+
+ try {
+ numNames = config.getInteger("numNames", 0);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, "Invalid numNames property for CRL " +
+ "IssuerAlternativeName extension - " + e);
+ }
+ nvp.put("numNames", String.valueOf(numNames));
+
+ for (int i = 0; i < numNames; i++) {
+ String nameType = null;
+
+ try {
+ nameType = config.getString("nameType" + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, "Undefined nameType" + i + " property for " +
+ "CRL IssuerAlternativeName extension - " + e);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, "Invalid nameType" + i + " property for " +
+ "CRL IssuerAlternativeName extension - " + e);
+ }
+
+ if (nameType != null && nameType.length() > 0) {
+ nvp.put("nameType" + i, nameType);
+ } else {
+ nvp.put("nameType" + i, "");
+ }
+
+ String name = null;
+
+ try {
+ name = config.getString("name" + i);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, "Undefined name" + i + " property for " +
+ "CRL IssuerAlternativeName extension - " + e);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, "Invalid name" + i + " property for " +
+ "CRL IssuerAlternativeName extension - " + e);
+ }
+
+ if (name != null && name.length() > 0) {
+ nvp.put("name" + i, name);
+ } else {
+ nvp.put("name" + i, "");
+ }
+ }
+
+ if (numNames < 3) {
+ for (int i = numNames; i < 3; i++) {
+ nvp.put("nameType" + i, "");
+ nvp.put("name" + i, "");
+ }
+ }
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ //"type;choice(CRLExtension,CRLEntryExtension);"+
+ //"CRL Extension type. This field is not editable.",
+ "enable;boolean;Check to enable Issuer Alternative Name CRL extension.",
+ "critical;boolean;Set criticality for Issuer Alternative Name CRL extension.",
+ "numNames;number;Set number of alternative names for the CRL issuer.",
+ "nameType0;choice(" + PROP_RFC822_NAME + "," + PROP_DIR_NAME + "," + PROP_DNS_NAME + "," +
+ PROP_EDI_NAME + "," + PROP_URI_NAME + "," + PROP_IP_NAME + "," + PROP_OID_NAME + "," +
+ PROP_OTHER_NAME + ");Select Issuer Alternative Name type.",
+ "name0;string;Enter Issuer Alternative Name corresponding to the selected name type.",
+ "nameType1;choice(" + PROP_RFC822_NAME + "," + PROP_DIR_NAME + "," + PROP_DNS_NAME + "," +
+ PROP_EDI_NAME + "," + PROP_URI_NAME + "," + PROP_IP_NAME + "," + PROP_OID_NAME + "," +
+ PROP_OTHER_NAME + ");Select Issuer Alternative Name type.",
+ "name1;string;Enter Issuer Alternative Name corresponding to the selected name type.",
+ "nameType2;choice(" + PROP_RFC822_NAME + "," + PROP_DIR_NAME + "," + PROP_DNS_NAME + "," +
+ PROP_EDI_NAME + "," + PROP_URI_NAME + "," + PROP_IP_NAME + "," + PROP_OID_NAME + "," +
+ PROP_OTHER_NAME + ");Select Issuer Alternative Name type.",
+ "name2;string;Enter Issuer Alternative Name corresponding to the selected name type.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-issueralternativename",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";The issuer alternative names extension allows additional" +
+ " identities to be associated with the issuer of the CRL."
+ };
+
+ return params;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_CA, level,
+ "CMSIssuerAlternativeNameExtension - " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/crl/CMSIssuingDistributionPointExtension.java b/base/server/cms/src/com/netscape/cms/crl/CMSIssuingDistributionPointExtension.java
new file mode 100644
index 000000000..02cc129c4
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/crl/CMSIssuingDistributionPointExtension.java
@@ -0,0 +1,332 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.crl;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import netscape.security.util.BitArray;
+import netscape.security.x509.Extension;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.GeneralNamesException;
+import netscape.security.x509.IssuingDistributionPoint;
+import netscape.security.x509.IssuingDistributionPointExtension;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.RDN;
+import netscape.security.x509.URIName;
+import netscape.security.x509.X500Name;
+
+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.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ca.ICMSCRLExtension;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * This represents a issuing distribution point extension.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSIssuingDistributionPointExtension
+ implements ICMSCRLExtension, IExtendedPluginInfo {
+ public static final String PROP_POINTTYPE = "pointType";
+ public static final String PROP_POINTNAME = "pointName";
+ public static final String PROP_DIRNAME = "DirectoryName";
+ public static final String PROP_URINAME = "URI";
+ public static final String PROP_RDNNAME = "RelativeToIssuer";
+ public static final String PROP_CACERTS = "onlyContainsCACerts";
+ public static final String PROP_USERCERTS = "onlyContainsUserCerts";
+ public static final String PROP_INDIRECT = "indirectCRL";
+ public static final String PROP_REASONS = "onlySomeReasons";
+
+ private static final String[] reasonFlags = { "unused",
+ "keyCompromise",
+ "cACompromise",
+ "affiliationChanged",
+ "superseded",
+ "cessationOfOperation",
+ "certificateHold",
+ "privilegeWithdrawn" };
+
+ private ILogger mLogger = CMS.getLogger();
+
+ public CMSIssuingDistributionPointExtension() {
+ }
+
+ public Extension setCRLExtensionCriticality(Extension ext,
+ boolean critical) {
+ IssuingDistributionPointExtension issuingDPointExt =
+ (IssuingDistributionPointExtension) ext;
+
+ issuingDPointExt.setCritical(critical);
+
+ return issuingDPointExt;
+ }
+
+ public Extension getCRLExtension(IConfigStore config,
+ Object ip,
+ boolean critical) {
+
+ CMS.debug("in CMSIssuingDistributionPointExtension::getCRLExtension.");
+ IssuingDistributionPointExtension issuingDPointExt = null;
+ IssuingDistributionPoint issuingDPoint = new IssuingDistributionPoint();
+
+ GeneralNames names = new GeneralNames();
+ RDN rdnName = null;
+
+ String pointType = null;
+
+ try {
+ pointType = config.getString(PROP_POINTTYPE);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_INVALID", e.toString()));
+ }
+
+ if (pointType != null) {
+ String pointName = null;
+
+ try {
+ pointName = config.getString(PROP_POINTNAME);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_INVALID", e.toString()));
+ }
+
+ if (pointName != null && pointName.length() > 0) {
+ if (pointType.equalsIgnoreCase(PROP_RDNNAME)) {
+ try {
+ rdnName = new RDN(pointName);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_RDN", e.toString()));
+ }
+ } else if (pointType.equalsIgnoreCase(PROP_DIRNAME)) {
+ try {
+ X500Name dirName = new X500Name(pointName);
+
+ names.addElement(dirName);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_INVALID_500NAME", e.toString()));
+ }
+ } else if (pointType.equalsIgnoreCase(PROP_URINAME)) {
+ URIName uriName = new URIName(pointName);
+
+ names.addElement(uriName);
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_INVALID_POTINT_TYPE", pointType));
+ }
+ }
+ }
+
+ if (rdnName != null) {
+ issuingDPoint.setRelativeName(rdnName);
+ } else if (names.size() > 0) {
+ try {
+ issuingDPoint.setFullName(names);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CANNOT_SET_NAME", e.toString()));
+ } catch (GeneralNamesException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CANNOT_SET_NAME", e.toString()));
+ }
+ }
+
+ String reasons = null;
+
+ try {
+ reasons = config.getString(PROP_REASONS, null);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_INVALID_PROPERTY", PROP_REASONS, e.toString()));
+ }
+ if (reasons != null && reasons.length() > 0) {
+
+ boolean[] bits = { false, false, false, false, false, false, false };
+ int k = 0;
+ StringTokenizer st = new StringTokenizer(reasons, ",");
+
+ while (st.hasMoreTokens()) {
+ String bitName = st.nextToken();
+
+ for (int i = 1; i < reasonFlags.length; i++) {
+ if (bitName.equalsIgnoreCase(reasonFlags[i])) {
+ bits[i] = true;
+ k++;
+ break;
+ }
+ }
+ }
+ if (k > 0) {
+ BitArray ba = new BitArray(bits);
+
+ issuingDPoint.setOnlySomeReasons(ba);
+ }
+
+ }
+
+ try {
+ boolean caCertsOnly = config.getBoolean(PROP_CACERTS, false);
+
+ if (caCertsOnly)
+ issuingDPoint.setOnlyContainsCACerts(caCertsOnly);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_INVALID_PROPERTY", "caCertsOnly", e.toString()));
+ }
+ try {
+ boolean userCertsOnly = config.getBoolean(PROP_USERCERTS, false);
+
+ if (userCertsOnly)
+ issuingDPoint.setOnlyContainsUserCerts(userCertsOnly);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_INVALID_PROPERTY", "userCertsOnly", e.toString()));
+ }
+ try {
+ boolean indirectCRL = config.getBoolean(PROP_INDIRECT, false);
+
+ if (indirectCRL)
+ issuingDPoint.setIndirectCRL(indirectCRL);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_INVALID_PROPERTY", "indirectCRL", e.toString()));
+ }
+
+ issuingDPointExt = new IssuingDistributionPointExtension(issuingDPoint);
+ issuingDPointExt.setCritical(critical);
+
+ return issuingDPointExt;
+ }
+
+ public String getCRLExtOID() {
+ return PKIXExtensions.IssuingDistributionPoint_Id.toString();
+ }
+
+ public void getConfigParams(IConfigStore config, NameValuePairs nvp) {
+ String pointType = null;
+
+ try {
+ pointType = config.getString(PROP_POINTTYPE);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_INVALID", e.toString()));
+ }
+ if (pointType != null && pointType.length() > 0) {
+ nvp.put("pointType", pointType);
+ } else {
+ nvp.put("pointType", "");
+ }
+
+ String pointName = null;
+
+ try {
+ pointName = config.getString(PROP_POINTNAME);
+ } catch (EPropertyNotFound e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_UNDEFINED", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_CREATE_DIST_POINT_INVALID", e.toString()));
+ }
+ if (pointName != null && pointName.length() > 0) {
+ nvp.put("pointName", pointName);
+ } else {
+ nvp.put("pointName", "");
+ }
+
+ String reasons = null;
+
+ try {
+ reasons = config.getString(PROP_REASONS, null);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_INVALID_PROPERTY", PROP_REASONS, e.toString()));
+ }
+ if (reasons != null && reasons.length() > 0) {
+ nvp.put(PROP_REASONS, reasons);
+ } else {
+ nvp.put(PROP_REASONS, "");
+ }
+
+ try {
+ boolean caCertsOnly = config.getBoolean(PROP_CACERTS, false);
+
+ nvp.put(PROP_CACERTS, String.valueOf(caCertsOnly));
+ } catch (EBaseException e) {
+ nvp.put(PROP_CACERTS, "false");
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_INVALID_PROPERTY", "caCertsOnly", e.toString()));
+ }
+ // Disable these for now unitl we support them fully
+ /*
+ try {
+ boolean userCertsOnly = config.getBoolean(PROP_USERCERTS, false);
+
+ nvp.add(PROP_USERCERTS, String.valueOf(userCertsOnly));
+ } catch (EBaseException e) {
+ nvp.add(PROP_USERCERTS, "false");
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_INVALID_PROPERTY", "userCertsOnly", e.toString()));
+ }
+
+ try {
+ boolean indirectCRL = config.getBoolean(PROP_INDIRECT, false);
+
+ nvp.add(PROP_INDIRECT, String.valueOf(indirectCRL));
+ } catch (EBaseException e) {
+ nvp.add(PROP_INDIRECT, "false");
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CRL_INVALID_PROPERTY", "indirectCRL", e.toString()));
+ }
+ */
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ StringBuffer sb_reasons = new StringBuffer();
+ sb_reasons.append(reasonFlags[1]);
+
+ for (int i = 2; i < reasonFlags.length; i++) {
+ sb_reasons.append(", ");
+ sb_reasons.append(reasonFlags[i]);
+ }
+ String[] params = {
+ //"type;choice(CRLExtension,CRLEntryExtension);"+
+ //"CRL Extension type. This field is not editable.",
+ "enable;boolean;Check to enable Issuing Distribution Point CRL extension.",
+ "critical;boolean;Set criticality for Issuing Distribution Point CRL extension.",
+ PROP_POINTTYPE + ";choice(" + PROP_DIRNAME + "," + PROP_URINAME + "," +
+ PROP_RDNNAME + ");Select Issuing Distribution Point name type.",
+ PROP_POINTNAME + ";string;Enter Issuing Distribution Point name " +
+ "corresponding to the selected point type.",
+ PROP_REASONS + ";string;Select any combination of the following reasons: " +
+ sb_reasons.toString(),
+ PROP_CACERTS + ";boolean;Check if CRL contains CA certificates only",
+ // Remove these from the UI until they can be supported fully.
+ // PROP_USERCERTS + ";boolean;Check if CRL contains user certificates only",
+ // PROP_INDIRECT + ";boolean;Check if CRL is built indirectly.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ca-edit-crlextension-issuingdistributionpoint",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";The issuing distribution point is a critical CRL extension " +
+ "that identifies the CRL distribution point for a particular CRL."
+ };
+
+ return params;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_CA, level,
+ "CMSIssuingDistributionPointExtension - " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/evaluators/GroupAccessEvaluator.java b/base/server/cms/src/com/netscape/cms/evaluators/GroupAccessEvaluator.java
new file mode 100644
index 000000000..e8a32d752
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/evaluators/GroupAccessEvaluator.java
@@ -0,0 +1,183 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.evaluators;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.evaluators.IAccessEvaluator;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * A class represents a group acls evaluator.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class GroupAccessEvaluator implements IAccessEvaluator {
+ private String mType = "group";
+ private IUGSubsystem mUG = null;
+ private String mDescription = "group membership evaluator";
+ private ILogger mLogger = CMS.getLogger();
+
+ /**
+ * Class constructor.
+ */
+ public GroupAccessEvaluator() {
+
+ mUG = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+
+ if (mUG == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("EVALUTOR_UG_NULL"));
+ }
+ }
+
+ /**
+ * initialization. nothing for now.
+ */
+ public void init() {
+ CMS.debug("GroupAccessEvaluator: init");
+ }
+
+ /**
+ * gets the type name for this acl evaluator
+ *
+ * @return type for this acl evaluator: "group" or "at_group"
+ */
+ public String getType() {
+ return mType;
+ }
+
+ /**
+ * gets the description for this acl evaluator
+ *
+ * @return description for this acl evaluator
+ */
+ public String getDescription() {
+ return mDescription;
+ }
+
+ public String[] getSupportedOperators() {
+ String[] s = new String[2];
+
+ s[0] = "=";
+ s[1] = "!=";
+ return s;
+ }
+
+ /**
+ * evaluates uid in AuthToken to see if it has membership in
+ * group value
+ *
+ * @param authToken authentication token
+ * @param type must be "at_group"
+ * @param op must be "="
+ * @param value the group name
+ * @return true if AuthToken uid belongs to the group value,
+ * false otherwise
+ */
+ public boolean evaluate(IAuthToken authToken, String type, String op, String value) {
+
+ if (type.equals(mType)) {
+ // should define "uid" at a common place
+ String uid = null;
+
+ uid = authToken.getInString("userid");
+ if (uid == null) {
+ uid = authToken.getInString("uid");
+ if (uid == null) {
+ CMS.debug("GroupAccessEvaluator: evaluate: uid null");
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("EVALUTOR_UID_NULL"));
+ return false;
+ }
+ }
+ CMS.debug("GroupAccessEvaluator: evaluate: uid=" + uid + " value=" + value);
+
+ String groupname = authToken.getInString("gid");
+
+ if (groupname != null) {
+ CMS.debug("GroupAccessEvaluator: evaluate: authToken gid=" + groupname);
+ if (op.equals("=")) {
+ return groupname.equals(Utils.stripQuotes(value));
+ } else if (op.equals("!=")) {
+ return !groupname.equals(Utils.stripQuotes(value));
+ }
+ } else {
+ CMS.debug("GroupAccessEvaluator: evaluate: no gid in authToken");
+ IUser id = null;
+ try {
+ id = mUG.getUser(uid);
+ } catch (EBaseException e) {
+ CMS.debug("GroupAccessEvaluator: " + e.toString());
+ return false;
+ }
+
+ if (op.equals("=")) {
+ return mUG.isMemberOf(id, Utils.stripQuotes(value));
+ } else if (op.equals("!=")) {
+ return !(mUG.isMemberOf(id, Utils.stripQuotes(value)));
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * evaluates uid in SessionContext to see if it has membership in
+ * group value
+ *
+ * @param type must be "group"
+ * @param op must be "="
+ * @param value the group name
+ * @return true if SessionContext uid belongs to the group value,
+ * false otherwise
+ */
+ public boolean evaluate(String type, String op, String value) {
+
+ SessionContext mSC = SessionContext.getContext();
+
+ if (type.equals(mType)) {
+ IUser id = (IUser) mSC.get(SessionContext.USER);
+
+ if (id == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("EVALUTOR_UID_NULL"));
+ return false;
+ }
+ if (op.equals("="))
+ return mUG.isMemberOf(id, Utils.stripQuotes(value));
+ else
+ return !(mUG.isMemberOf(id, Utils.stripQuotes(value)));
+
+ }
+
+ return false;
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_ACLS,
+ level, "GroupAccessEvaluator: " + msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/evaluators/IPAddressAccessEvaluator.java b/base/server/cms/src/com/netscape/cms/evaluators/IPAddressAccessEvaluator.java
new file mode 100644
index 000000000..fe784f3a9
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/evaluators/IPAddressAccessEvaluator.java
@@ -0,0 +1,128 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.evaluators;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.evaluators.IAccessEvaluator;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * A class represents a IP address acls evaluator.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class IPAddressAccessEvaluator implements IAccessEvaluator {
+ private String mType = "ipaddress";
+ private String mDescription = "IP Address evaluator";
+ private ILogger mLogger = CMS.getLogger();
+
+ /**
+ * Class constructor.
+ */
+ public IPAddressAccessEvaluator() {
+ }
+
+ /**
+ * initialization. nothing for now.
+ */
+ public void init() {
+ }
+
+ /**
+ * gets the type name for this acl evaluator
+ *
+ * @return type for this acl evaluator: ipaddress
+ */
+ public String getType() {
+ return mType;
+ }
+
+ /**
+ * gets the description for this acl evaluator
+ *
+ * @return description for this acl evaluator
+ */
+ public String getDescription() {
+ return mDescription;
+ }
+
+ public String[] getSupportedOperators() {
+ String[] s = new String[2];
+
+ s[0] = "=";
+ s[1] = "!=";
+ return s;
+ }
+
+ /**
+ * Gets the IP address from session context
+ *
+ * @param authToken authentication token
+ * @param type must be "ipaddress"
+ * @param op must be "=" or "!="
+ * @param value the ipaddress
+ */
+ public boolean evaluate(IAuthToken authToken, String type, String op, String value) {
+
+ return evaluate(type, op, value);
+ }
+
+ /**
+ * evaluates uid in SessionContext to see if it has membership in
+ * group value
+ *
+ * @param type must be "group"
+ * @param op must be "="
+ * @param value the group name
+ * @return true if SessionContext uid belongs to the group value,
+ * false otherwise
+ */
+ public boolean evaluate(String type, String op, String value) {
+
+ SessionContext mSC = SessionContext.getContext();
+
+ value = Utils.stripQuotes(value);
+ String ipaddress = (String) mSC.get(SessionContext.IPADDRESS);
+
+ if (type.equals(mType)) {
+ if (ipaddress == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("EVALUATOR_IPADDRESS_NULL"));
+ return false;
+ }
+ if (op.equals("=")) {
+ return ipaddress.matches(value);
+ } else {
+ return !(ipaddress.matches(value));
+ }
+
+ }
+
+ return false;
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_ACLS,
+ level, "GroupAccessEvaluator: " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/evaluators/UserAccessEvaluator.java b/base/server/cms/src/com/netscape/cms/evaluators/UserAccessEvaluator.java
new file mode 100644
index 000000000..c343b110a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/evaluators/UserAccessEvaluator.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.evaluators;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.evaluators.IAccessEvaluator;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * A class represents a user acls evaluator.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class UserAccessEvaluator implements IAccessEvaluator {
+ private String mType = "user";
+ private String mDescription = "user equivalence evaluator";
+ private ILogger mLogger = CMS.getLogger();
+
+ private final static String ANYBODY = "anybody";
+ private final static String EVERYBODY = "everybody";
+
+ /**
+ * Class constructor.
+ */
+ public UserAccessEvaluator() {
+ }
+
+ /**
+ * initialization. nothing for now.
+ */
+ public void init() {
+ CMS.debug("UserAccessEvaluator: init");
+ }
+
+ /**
+ * gets the type name for this acl evaluator
+ *
+ * @return type for this acl evaluator: "user" or "at_user"
+ */
+ public String getType() {
+ return mType;
+ }
+
+ /**
+ * gets the description for this acl evaluator
+ *
+ * @return description for this acl evaluator
+ */
+ public String getDescription() {
+ return mDescription;
+ }
+
+ public String[] getSupportedOperators() {
+ String[] s = new String[2];
+
+ s[0] = "=";
+ s[1] = "!=";
+ return s;
+ }
+
+ /**
+ * Evaluates the user in AuthToken to see if it's equal to value
+ *
+ * @param authToken AuthToken from authentication
+ * @param type must be "at_user"
+ * @param op must be "="
+ * @param value the user id
+ * @return true if AuthToken uid is same as value, false otherwise
+ */
+ public boolean evaluate(IAuthToken authToken, String type, String op, String value) {
+
+ if (type.equals(mType)) {
+ String s = Utils.stripQuotes(value);
+
+ if ((s.equals(ANYBODY) || s.equals(EVERYBODY)) && op.equals("="))
+ return true;
+
+ // should define "uid" at a common place
+ String uid = null;
+
+ uid = authToken.getInString("uid");
+
+ if (uid == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("EVALUTOR_UID_IS_NULL"));
+ return false;
+ }
+
+ if (op.equals("="))
+ return s.equalsIgnoreCase(uid);
+ else if (op.equals("!="))
+ return !(s.equalsIgnoreCase(uid));
+ }
+
+ return false;
+ }
+
+ /**
+ * Evaluates the user in session context to see if it's equal to value
+ *
+ * @param type must be "user"
+ * @param op must be "="
+ * @param value the user id
+ * @return true if SessionContext uid is same as value, false otherwise
+ */
+ public boolean evaluate(String type, String op, String value) {
+
+ SessionContext mSC = SessionContext.getContext();
+
+ if (type.equals(mType)) {
+ String s = Utils.stripQuotes(value);
+
+ if (s.equals(ANYBODY) && op.equals("="))
+ return true;
+
+ IUser id = (IUser) mSC.get(SessionContext.USER);
+
+ if (op.equals("="))
+ return s.equalsIgnoreCase(id.getName());
+ else if (op.equals("!="))
+ return !(s.equalsIgnoreCase(id.getName()));
+ }
+
+ return false;
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_ACLS,
+ level, "UserAccessEvaluator: " + msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/evaluators/UserOrigReqAccessEvaluator.java b/base/server/cms/src/com/netscape/cms/evaluators/UserOrigReqAccessEvaluator.java
new file mode 100644
index 000000000..65032608c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/evaluators/UserOrigReqAccessEvaluator.java
@@ -0,0 +1,163 @@
+// --- 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) 2008 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.evaluators;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.evaluators.IAccessEvaluator;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * A class represents a user-origreq uid mapping acls evaluator.
+ * This is primarily used for renewal. During renewal, the orig_req
+ * uid is placed in the SessionContext of the renewal session context
+ * to be evaluated by this evaluator
+ * <P>
+ *
+ * @author Christina Fu
+ * @version $Revision$, $Date$
+ */
+public class UserOrigReqAccessEvaluator implements IAccessEvaluator {
+ private String mType = "user_origreq";
+ private String mDescription = "user origreq matching evaluator";
+
+ private final static String ANYBODY = "anybody";
+ private final static String EVERYBODY = "everybody";
+
+ /**
+ * Class constructor.
+ */
+ public UserOrigReqAccessEvaluator() {
+ }
+
+ /**
+ * initialization. nothing for now.
+ */
+ public void init() {
+ CMS.debug("UserOrigReqAccessEvaluator: init");
+ }
+
+ /**
+ * gets the type name for this acl evaluator
+ *
+ * @return type for this acl evaluator: "user_origreq" or "at_user_origreq"
+ */
+ public String getType() {
+ return mType;
+ }
+
+ /**
+ * gets the description for this acl evaluator
+ *
+ * @return description for this acl evaluator
+ */
+ public String getDescription() {
+ return mDescription;
+ }
+
+ public String[] getSupportedOperators() {
+ String[] s = new String[2];
+
+ s[0] = "=";
+ s[1] = "!=";
+ return s;
+ }
+
+ /**
+ * Evaluates the user in AuthToken to see if it's equal to value
+ *
+ * @param authToken AuthToken from authentication
+ * @param type must be "at_userreq"
+ * @param op must be "="
+ * @param value the request param name
+ * @return true if AuthToken uid is same as value, false otherwise
+ */
+ public boolean evaluate(IAuthToken authToken, String type, String op, String value) {
+ CMS.debug("UserOrigReqAccessEvaluator: evaluate() begins");
+ if (type.equals(mType)) {
+ String s = Utils.stripQuotes(value);
+
+ if ((s.equals(ANYBODY) || s.equals(EVERYBODY)) && op.equals("="))
+ return true;
+
+ // should define "uid" at a common place
+ String uid = null;
+
+ uid = authToken.getInString("uid");
+
+ if (uid == null) {
+ CMS.debug("UserOrigReqAccessEvaluator: evaluate() uid in authtoken null");
+ return false;
+ } else
+ CMS.debug("UserOrigReqAccessEvaluator: evaluate() uid in authtoken =" + uid);
+
+ // find value of param in request
+ SessionContext mSC = SessionContext.getContext();
+ CMS.debug("UserOrigReqAccessEvaluator: evaluate() getting " + "orig_req." + s + " in SessionContext");
+ // "orig_req.auth_token.uid"
+ String orig_id = (String) mSC.get("orig_req." + s);
+
+ if (orig_id == null) {
+ CMS.debug("UserOrigReqAccessEvaluator: evaluate() orig_id null");
+ return false;
+ }
+ CMS.debug("UserOrigReqAccessEvaluator: evaluate() orig_id =" + orig_id);
+ if (op.equals("="))
+ return uid.equalsIgnoreCase(orig_id);
+ else if (op.equals("!="))
+ return !(uid.equalsIgnoreCase(orig_id));
+ }
+
+ return false;
+ }
+
+ /**
+ * Evaluates the user in session context to see if it's equal to value
+ *
+ * @param type must be "user_origreq"
+ * @param op must be "="
+ * @param value the user id
+ * @return true if SessionContext uid is same as value, false otherwise
+ */
+ public boolean evaluate(String type, String op, String value) {
+
+ SessionContext mSC = SessionContext.getContext();
+
+ if (type.equals(mType)) {
+ // what do I do with s here?
+ String s = Utils.stripQuotes(value);
+
+ if (s.equals(ANYBODY) && op.equals("="))
+ return true;
+
+ IUser id = (IUser) mSC.get(SessionContext.USER);
+ // "orig_req.auth_token.uid"
+ String orig_id = (String) mSC.get("orig_req" + s);
+
+ if (op.equals("="))
+ return id.getName().equalsIgnoreCase(orig_id);
+ else if (op.equals("!="))
+ return !(id.getName().equalsIgnoreCase(orig_id));
+ }
+
+ return false;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/jobs/AJobBase.java b/base/server/cms/src/com/netscape/cms/jobs/AJobBase.java
new file mode 100644
index 000000000..bd319b94e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/jobs/AJobBase.java
@@ -0,0 +1,301 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.jobs;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.jobs.IJob;
+import com.netscape.certsrv.jobs.IJobCron;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.notification.ENotificationException;
+import com.netscape.certsrv.notification.IEmailFormProcessor;
+import com.netscape.certsrv.notification.IEmailTemplate;
+import com.netscape.certsrv.notification.IMailNotification;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This abstract class is a base job for real job extentions for the
+ * Jobs Scheduler.
+ *
+ * @version $Revision$, $Date$
+ * @see com.netscape.certsrv.jobs.IJob
+ */
+public abstract class AJobBase implements IJob, Runnable {
+ // config parameters...
+ protected static final String PROP_SUMMARY = "summary";
+ protected static final String PROP_ENABLED = "enabled";
+ protected static final String PROP_EMAIL_SUBJECT = "emailSubject";
+ protected static final String PROP_EMAIL_TEMPLATE = "emailTemplate";
+ protected static final String PROP_ITEM_TEMPLATE = "itemTemplate";
+ protected static final String PROP_SENDER_EMAIL = "senderEmail";
+ protected static final String PROP_RECEIVER_EMAIL = "recipientEmail";
+
+ protected static final String STATUS_FAILURE = "failed";
+ protected static final String STATUS_SUCCESS = "succeeded";
+
+ // variables used by the Job Scheduler Daemon
+ protected String mImplName = null;
+ protected IConfigStore mConfig;
+ protected String mId = null;
+ protected String mCron = null;
+ protected IJobCron mJobCron = null;
+
+ protected ILogger mLogger = CMS.getLogger();
+ protected static String[] mConfigParams = null;
+
+ protected String mSummaryMailSubject = null;
+ protected boolean mMailHTML = false;
+ protected String mMailForm = null;
+ protected String mItemForm = null;
+ protected String mSummarySenderEmail = null;
+ protected String mSummaryReceiverEmail = null;
+ protected Hashtable<String, Object> mContentParams = new Hashtable<String, Object>();
+ protected Hashtable<String, Object> mItemParams = new Hashtable<String, Object>();
+
+ boolean stopped;
+
+ public AJobBase() {
+ }
+
+ /**
+ * tells if the job is enabled
+ *
+ * @return a boolean value indicating whether the job is enabled
+ * or not
+ */
+ public boolean isEnabled() {
+ boolean enabled = false;
+
+ try {
+ enabled = mConfig.getBoolean(PROP_ENABLED, false);
+ } catch (EBaseException e) {
+ }
+ return enabled;
+ }
+
+ /***********************
+ * abstract methods
+ ***********************/
+ public abstract void init(ISubsystem owner, String id, String implName, IConfigStore
+ config) throws EBaseException;
+
+ public abstract void run();
+
+ /***********************
+ * public methods
+ ***********************/
+
+ /**
+ * get instance id.
+ *
+ * @return a String identifier
+ */
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * set instance id.
+ *
+ * @param id String id of the instance
+ */
+ public void setId(String id) {
+ mId = id;
+ }
+
+ /**
+ * get cron string associated with this job
+ *
+ * @return a JobCron object that represents the schedule of this job
+ */
+ public IJobCron getJobCron() {
+ return mJobCron;
+ }
+
+ /**
+ * gets the plugin name of this job.
+ *
+ * @return a String that is the name of this implementation
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ /**
+ * Gets the configuration substore used by this job
+ *
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /*
+ * get form file content from disk
+ */
+ protected String getTemplateContent(String templatePath) {
+ String templateString = null;
+
+ /*
+ * get template file from disk
+ */
+ IEmailTemplate template = CMS.getEmailTemplate(templatePath);
+
+ if (template != null) {
+ if (!template.init()) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("JOBS_TEMPLATE_INIT_ERROR"));
+ return null;
+ }
+
+ // this should take care of inner tempaltes not being html
+ // we go with the outter template
+ if (template.isHTML()) {
+ mMailHTML = true;
+ }
+ templateString = template.toString();
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("JOBS_TEMPLATE_INIT_ERROR"));
+ }
+
+ return templateString;
+ }
+
+ protected void mailSummary(String content) {
+ // no need for email resolver here...
+ IMailNotification mn = CMS.getMailNotification();
+
+ mn.setFrom(mSummarySenderEmail);
+ mn.setTo(mSummaryReceiverEmail);
+ mn.setSubject(mSummaryMailSubject);
+ if (mMailHTML == true) {
+ mn.setContentType("text/html");
+ }
+
+ mn.setContent(content);
+ try {
+ mn.sendNotification();
+ } catch (ENotificationException e) {
+ // already logged, lets audit
+ mLogger.log(ILogger.EV_AUDIT, null,
+ ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("JOBS_SEND_NOTIFICATION", e.toString()));
+ } catch (IOException e) {
+ // already logged, lets audit
+ mLogger.log(ILogger.EV_AUDIT, null,
+ ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("JOBS_SEND_NOTIFICATION", e.toString()));
+ }
+ }
+
+ protected void buildItemParams(X509CertImpl cert) {
+ mItemParams.put(IEmailFormProcessor.TOKEN_SERIAL_NUM,
+ cert.getSerialNumber().toString());
+ mItemParams.put(IEmailFormProcessor.TOKEN_HEX_SERIAL_NUM,
+ cert.getSerialNumber().toString(16));
+ mItemParams.put(IEmailFormProcessor.TOKEN_ISSUER_DN,
+ cert.getIssuerDN().toString());
+ mItemParams.put(IEmailFormProcessor.TOKEN_SUBJECT_DN,
+ cert.getSubjectDN().toString());
+ mItemParams.put(IEmailFormProcessor.TOKEN_NOT_AFTER,
+ cert.getNotAfter().toString());
+ mItemParams.put(IEmailFormProcessor.TOKEN_NOT_BEFORE,
+ cert.getNotBefore().toString());
+ // ... and more
+ }
+
+ protected void buildItemParams(IRequest r) {
+ String re = r.getExtDataInString(IRequest.HTTP_PARAMS, "csrRequestorEmail");
+
+ if (re != null) {
+ mItemParams.put(IEmailFormProcessor.TOKEN_REQUESTOR_EMAIL, re);
+ }
+
+ String ct = r.getExtDataInString(IRequest.HTTP_PARAMS, IRequest.CERT_TYPE);
+
+ if (ct != null) {
+ mItemParams.put(IEmailFormProcessor.TOKEN_CERT_TYPE, ct);
+ }
+
+ String rt = r.getExtDataInString(IRequest.REQ_TYPE);
+
+ if (rt != null) {
+ mItemParams.put(IEmailFormProcessor.TOKEN_REQUEST_TYPE, rt);
+ }
+ }
+
+ protected void buildItemParams(String name, String val) {
+ if (val != null)
+ mItemParams.put(name, val);
+ else {
+ CMS.debug("AJobBase: buildItemParams: null value for name= " + name);
+ mItemParams.put(name, "");
+ }
+ }
+
+ protected void buildContentParams(String name, String val) {
+ if (val != null)
+ mContentParams.put(name, val);
+ else {
+ CMS.debug("AJobBase: buildContentParams: null value for name= " + name);
+ mContentParams.put(name, "");
+ }
+ }
+
+ /**
+ * logs an entry in the log file. Used by classes extending this class.
+ *
+ * @param level log level
+ * @param msg log message in String
+ */
+ public void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, mId + ": " + msg);
+ }
+
+ /**
+ * capable of logging multiline entry in the log file. Used by classes extending this class.
+ *
+ * @param level log level
+ * @param msg log message in String
+ * @param multiline boolean indicating whether the message is a
+ * multi-lined message.
+ */
+ public void log(int level, String msg, boolean multiline) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, mId + ": " + msg, multiline);
+ }
+
+ public void stop() {
+ stopped = true;
+ }
+
+ public boolean isStopped() {
+ return stopped;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/jobs/PublishCertsJob.java b/base/server/cms/src/com/netscape/cms/jobs/PublishCertsJob.java
new file mode 100644
index 000000000..25c80817b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/jobs/PublishCertsJob.java
@@ -0,0 +1,392 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.jobs;
+
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.jobs.IJob;
+import com.netscape.certsrv.jobs.IJobCron;
+import com.netscape.certsrv.jobs.IJobsScheduler;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.notification.IEmailFormProcessor;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+
+/**
+ * a job for the Jobs Scheduler. This job checks in the internal ldap
+ * db for valid certs that have not been published to the
+ * publishing directory.
+ * <p>
+ * the $TOKENS that are available for the this jobs's summary outer form are:<br>
+ * <UL>
+ * $Status $InstanceID $SummaryItemList $SummaryTotalNum $SummaryTotalSuccess $SummaryTotalfailure $ExecutionTime
+ * </UL>
+ * and for the inner list items:
+ * <UL>
+ * $SerialNumber $IssuerDN $SubjectDN $NotAfter $NotBefore $RequestorEmail $CertType
+ * </UL>
+ *
+ * @version $Revision$, $Date$
+ */
+public class PublishCertsJob extends AJobBase
+ implements IJob, Runnable, IExtendedPluginInfo {
+
+ ICertificateAuthority mCa = null;
+ IRequestQueue mReqQ = null;
+ ICertificateRepository mRepository = null;
+ IPublisherProcessor mPublisherProcessor = null;
+ private boolean mSummary = false;
+
+ /* Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ protected static String[] mConfigParams =
+ new String[] {
+ "enabled",
+ "cron",
+ "summary.enabled",
+ "summary.emailSubject",
+ "summary.emailTemplate",
+ "summary.itemTemplate",
+ "summary.senderEmail",
+ "summary.recipientEmail"
+ };
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String s[] = {
+ IExtendedPluginInfo.HELP_TEXT +
+ "; A job that checks for valid certificates in the " +
+ "database, that have not been published and publish them to " +
+ "the publishing directory",
+ "cron;string;Format: minute hour dayOfMonth month " +
+ "dayOfWeek. Use '*' for 'every'. For dayOfWeek, 0 is Sunday",
+ "summary.senderEmail;string;Specify the address to be used " +
+ "as the email's 'sender'. Bounces go to this address.",
+ "summary.recipientEmail;string;Who should receive summaries",
+ "enabled;boolean;Enable this plugin",
+ "summary.enabled;boolean;Enable the summary. You must enabled " +
+ "this for the job to work.",
+ "summary.emailSubject;string;Subject of summary email",
+ "summary.emailTemplate;string;Fully qualified pathname of " +
+ "template file of email to be sent",
+ "summary.itemTemplate;string;Fully qualified pathname of " +
+ "file containing template for each item",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-jobrules-unpublishexpiredjobs",
+ };
+
+ return s;
+ }
+
+ /**
+ * initialize from the configuration file
+ */
+ public void init(ISubsystem owner, String id, String implName, IConfigStore config) throws
+ EBaseException {
+ mConfig = config;
+ mId = id;
+ mImplName = implName;
+
+ mCa = (ICertificateAuthority)
+ CMS.getSubsystem("ca");
+ if (mCa == null) {
+ return;
+ }
+
+ mReqQ = mCa.getRequestQueue();
+ mRepository = mCa.getCertificateRepository();
+ mPublisherProcessor = mCa.getPublisherProcessor();
+
+ // read from the configuration file
+ mCron = mConfig.getString(IJobCron.PROP_CRON);
+ if (mCron == null) {
+ return;
+ }
+
+ // parse cron string into a JobCron class
+ IJobsScheduler scheduler = (IJobsScheduler) owner;
+
+ mJobCron = scheduler.createJobCron(mCron);
+
+ // initialize the summary related config info
+ IConfigStore sc = mConfig.getSubStore(PROP_SUMMARY);
+
+ if (sc.getBoolean(PROP_ENABLED, false)) {
+ mSummary = true;
+ mSummaryMailSubject = sc.getString(PROP_EMAIL_SUBJECT);
+ mMailForm = sc.getString(PROP_EMAIL_TEMPLATE);
+ mItemForm = sc.getString(PROP_ITEM_TEMPLATE);
+ mSummarySenderEmail = sc.getString(PROP_SENDER_EMAIL);
+ mSummaryReceiverEmail = sc.getString(PROP_RECEIVER_EMAIL);
+ } else {
+ mSummary = false;
+ }
+ }
+
+ /**
+ * look in the internal db for certificateRecords that are
+ * valid but not published
+ * The publish() method should set <b>InLdapPublishDir</b> flag accordingly.
+ * if publish unsuccessfully, log it -- unsuccessful certs should be
+ * picked up and attempted again at the next scheduled run
+ */
+ public void run() {
+ CMS.debug("in PublishCertsJob " +
+ getId() + " : run()");
+ // get time now..."now" is before the loop
+ Date date = CMS.getCurrentDate();
+ DateFormat dateFormat = DateFormat.getDateTimeInstance();
+ String nowString = dateFormat.format(date);
+
+ // form filter
+ String filter = // might need to use "metaInfo"
+ "(!(certMetainfo=" + ICertRecord.META_LDAPPUBLISH +
+ ":true))";
+
+ Enumeration<Object> unpublishedCerts = null;
+
+ try {
+ unpublishedCerts = mRepository.findCertRecs(filter);
+ // bug 399150
+ /*
+ CertRecordList list = null;
+ list = mRepository.findCertRecordsInList(filter, null, "serialno", 5);
+ int size = list.getSize();
+ expired = list.getCertRecords(0, size - 1);
+ */
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+
+ int count = 0; // how many have been published successfully
+ int negCount = 0; // how many have NOT been published successfully
+ String contentForm = null;
+ String itemForm = null;
+ String itemListContent = null;
+
+ if (mSummary == true) {
+ contentForm = getTemplateContent(mMailForm);
+ itemForm = getTemplateContent(mItemForm);
+ }
+
+ // filter out the invalid ones and publish them
+ // publish() will set inLdapPublishDir flag
+ while (unpublishedCerts != null && unpublishedCerts.hasMoreElements()) {
+ ICertRecord rec = (ICertRecord) unpublishedCerts.nextElement();
+
+ if (rec == null)
+ break;
+ X509CertImpl cert = rec.getCertificate();
+ Date notAfter = cert.getNotAfter();
+
+ // skip CA certs
+ if (cert.getBasicConstraintsIsCA() == true)
+ continue;
+
+ // skip the expired certs
+ if (notAfter.before(date))
+ continue;
+
+ if (mSummary == true)
+ buildItemParams(cert);
+
+ // get request id from cert record MetaInfo
+ MetaInfo minfo = null;
+
+ try {
+ minfo = (MetaInfo) rec.get(ICertRecord.ATTR_META_INFO);
+ } catch (EBaseException e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_META_INFO_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+
+ String ridString = null;
+
+ try {
+ if (minfo != null)
+ ridString = (String) minfo.get(ICertRecord.META_REQUEST_ID);
+ } catch (EBaseException e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_META_REQUEST_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ } catch (NullPointerException e) {
+ // no requestId in MetaInfo...skip to next record
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_META_REQUEST_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+
+ if (ridString != null) {
+ RequestId rid = new RequestId(ridString);
+
+ // get request from request id
+ IRequest req = null;
+
+ try {
+ req = mReqQ.findRequest(rid);
+ if (req != null) {
+ if (mSummary == true)
+ buildItemParams(req);
+ }
+ } catch (EBaseException e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_FIND_REQUEST_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+ try {
+ if ((mPublisherProcessor != null) &&
+ mPublisherProcessor.enabled()) {
+ mPublisherProcessor.publishCert(cert, req);
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_SUCCESS);
+ count += 1;
+ } else {
+ negCount += 1;
+ }
+ } catch (Exception e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_PUBLISH_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+ } // ridString != null
+ else {
+ try {
+ if ((mPublisherProcessor != null) &&
+ mPublisherProcessor.enabled()) {
+ mPublisherProcessor.publishCert(cert, null);
+
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_SUCCESS);
+ count += 1;
+ } else {
+ negCount += 1;
+ }
+ } catch (Exception e) {
+ negCount += 1;
+
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_PUBLISH_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+ } // ridString == null
+
+ // inLdapPublishDir flag should have been set by the
+ // publish() method
+
+ // if summary is enabled, form the item content
+ if (mSummary) {
+ IEmailFormProcessor emailItemFormProcessor =
+ CMS.getEmailFormProcessor();
+ String c = emailItemFormProcessor.getEmailContent(itemForm,
+ mItemParams);
+
+ // add item content to the item list
+ if (itemListContent == null) {
+ itemListContent = c;
+ } else {
+ itemListContent += c;
+ }
+ }
+ }
+
+ // time for summary
+ if (mSummary == true) {
+ buildContentParams(IEmailFormProcessor.TOKEN_ID,
+ mId);
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_ITEM_LIST,
+ itemListContent);
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_TOTAL_NUM,
+ String.valueOf(count + negCount));
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_SUCCESS_NUM,
+ String.valueOf(count));
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_FAILURE_NUM,
+ String.valueOf(negCount));
+ buildContentParams(IEmailFormProcessor.TOKEN_EXECUTION_TIME,
+ nowString);
+
+ IEmailFormProcessor emailFormProcessor = CMS.getEmailFormProcessor();
+ String mailContent =
+ emailFormProcessor.getEmailContent(contentForm,
+ mContentParams);
+
+ mailSummary(mailContent);
+ }
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return mConfigParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/jobs/RenewalNotificationJob.java b/base/server/cms/src/com/netscape/cms/jobs/RenewalNotificationJob.java
new file mode 100644
index 000000000..37c0e918b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/jobs/RenewalNotificationJob.java
@@ -0,0 +1,705 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.jobs;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.IElementProcessor;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.jobs.IJob;
+import com.netscape.certsrv.jobs.IJobCron;
+import com.netscape.certsrv.jobs.IJobsScheduler;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.notification.ENotificationException;
+import com.netscape.certsrv.notification.IEmailFormProcessor;
+import com.netscape.certsrv.notification.IEmailResolver;
+import com.netscape.certsrv.notification.IEmailResolverKeys;
+import com.netscape.certsrv.notification.IMailNotification;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestId;
+
+/**
+ * A job for the Jobs Scheduler. This job checks in the internal ldap
+ * db for certs about to expire within the next configurable days and
+ * sends email notifications to the appropriate recipients.
+ *
+ * the $TOKENS that are available for the this jobs's summary outer form are:<br
+ >
+ * <UL>
+ * <LI>$Status
+ * <LI>$InstanceID
+ * <LI>$SummaryItemList
+ * <LI>$SummaryTotalNum
+ * <LI>$SummaryTotalSuccess
+ * <LI>$SummaryTotalfailure
+ * <LI>$ExecutionTime
+ * </UL>
+ * and for the inner list items:
+ * <UL>
+ * <LI>$SerialNumber
+ * <LI>$IssuerDN
+ * <LI>$SubjectDN
+ * <LI>$NotAfter
+ * <LI>$NotBefore
+ * <LI>$RequestorEmail
+ * <LI>$CertType
+ * <LI>$RequestType
+ * <LI>$HttpHost
+ * <LI>$HttpPort
+ * </UL>
+ *
+ * @version $Revision$, $Date$
+ * @see com.netscape.certsrv.jobs.IJob
+ * @see com.netscape.cms.jobs.AJobBase
+ */
+public class RenewalNotificationJob
+ extends AJobBase
+ implements IJob, Runnable, IExtendedPluginInfo {
+
+ // config parameters...
+ public static final String PROP_CRON = "cron";
+
+ /**
+ * Profile ID specifies which profile approves the certificate.
+ */
+ public static final String PROP_PROFILE_ID = "profileId";
+
+ /**
+ * This job will send notification at this much time before the
+ * enpiration date
+ */
+ public static final String PROP_NOTIFYTRIGGEROFFSET =
+ "notifyTriggerOffset";
+
+ /**
+ * This job will stop sending notification this much time after
+ * the expiration date
+ */
+ public static final String PROP_NOTIFYENDOFFSET = "notifyEndOffset";
+
+ /**
+ * sender email address as appeared on the notification email
+ */
+ public static final String PROP_SENDEREMAIL =
+ "senderEmail";
+
+ /**
+ * email subject line as appeared on the notification email
+ */
+ public static final String PROP_EMAILSUBJECT =
+ "emailSubject";
+
+ /**
+ * location of the template file used for email notification
+ */
+ public static final String PROP_EMAILTEMPLATE = "emailTemplate";
+ public static final String PROP_MAXNOTIFYCOUNT = "maxNotifyCount";
+
+ /**
+ * sender email as appeared on the notification summary email
+ */
+ public static final String PROP_SUMMARY_SENDEREMAIL = "summary.senderEmail";
+
+ /**
+ * recipient of the notification summary email
+ */
+ public static final String PROP_SUMMARY_RECIPIENTEMAIL = "summary.recipientEmail";
+
+ /**
+ * email subject as appeared on the notification summary email
+ */
+ public static final String PROP_SUMMARY_SUBJECT = "summary.emailSubject";
+
+ /**
+ * location of the email template used for notification summary
+ */
+ public static final String PROP_SUMMARY_TEMPLATE = "summary.emailTemplate";
+
+ /**
+ * location of the template file for each item appeared on the
+ * notification summary
+ */
+ public static final String PROP_SUMMARY_ITEMTEMPLATE = "summary.itemTemplate";
+
+ /*
+ * Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ protected static String[] mConfigParams =
+ new String[] {
+ "enabled",
+ PROP_CRON,
+ PROP_PROFILE_ID,
+ PROP_NOTIFYTRIGGEROFFSET,
+ PROP_NOTIFYENDOFFSET,
+ PROP_SENDEREMAIL,
+ PROP_EMAILSUBJECT,
+ PROP_EMAILTEMPLATE,
+ "summary.enabled",
+ PROP_SUMMARY_RECIPIENTEMAIL,
+ PROP_SUMMARY_SENDEREMAIL,
+ PROP_SUMMARY_SUBJECT,
+ PROP_SUMMARY_ITEMTEMPLATE,
+ PROP_SUMMARY_TEMPLATE,
+ };
+
+ protected ICertificateRepository mCertDB = null;
+ protected ICertificateAuthority mCA = null;
+ protected boolean mSummary = false;
+ protected String mEmailSender = null;
+ protected String mEmailSubject = null;
+ protected String mEmailTemplateName = null;
+ protected String mSummaryItemTemplateName = null;
+ protected String mSummaryTemplateName = null;
+ protected boolean mSummaryHTML = false;
+ protected boolean mHTML = false;
+
+ protected String mHttpHost = null;
+ protected String mHttpPort = null;
+
+ private int mPreDays = 0;
+ private long mPreMS = 0;
+ private int mPostDays = 0;
+ private long mPostMS = 0;
+ private String[] mProfileId = null;
+
+ /**
+ * class constructor
+ */
+ public RenewalNotificationJob() {
+ }
+
+ /**
+ * holds help text for this plugin
+ */
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String s[] = {
+ IExtendedPluginInfo.HELP_TEXT +
+ "; A job that checks for expiring or expired certs" +
+ "notifyTriggerOffset before and notifyEndOffset after " +
+ "the expiration date",
+
+ PROP_PROFILE_ID + ";string;Specify the ID of the profile which " +
+ "approved the certificates that are about to expire. For multiple " +
+ "profiles, each entry is separated by white space. For example, " +
+ "if the administrator just wants to give automated notification " +
+ "when the SSL server certificates are about to expire, then " +
+ "he should enter \"caServerCert caAgentServerCert\" in the profileId textfield. " +
+ "Blank field means all profiles.",
+ PROP_NOTIFYTRIGGEROFFSET + ";number,required;How long (in days) before " +
+ "certificate expiration will the first notification " +
+ "be sent",
+ PROP_NOTIFYENDOFFSET + ";number,required;How long (in days) after " +
+ "certificate expiration will notifications " +
+ "continue to be resent if certificate is not renewed",
+ PROP_CRON + ";string,required;Format: minute hour dayOfMonth Mmonth " +
+ "dayOfWeek. Use '*' for 'every'. For dayOfWeek, 0 is Sunday",
+ PROP_SENDEREMAIL + ";string,required;Specify the address to be used " +
+ "as the email's 'sender'. Bounces go to this address.",
+ PROP_EMAILSUBJECT + ";string,required;Email subject",
+ PROP_EMAILTEMPLATE + ";string,required;Fully qualified pathname of " +
+ "template file of email to be sent",
+ "enabled;boolean;Enable this plugin",
+ "summary.enabled;boolean;Enabled sending of summaries",
+ PROP_SUMMARY_SENDEREMAIL + ";string,required;Sender email address of summary",
+ PROP_SUMMARY_RECIPIENTEMAIL + ";string,required;Who should receive summaries",
+ PROP_SUMMARY_SUBJECT + ";string,required;Subject of summary email",
+ PROP_SUMMARY_TEMPLATE + ";string,required;Fully qualified pathname of " +
+ "template file of email to be sent",
+ PROP_SUMMARY_ITEMTEMPLATE + ";string,required;Fully qualified pathname of " +
+ "file with template to be used for each summary item",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-jobrules-renewalnotification",
+ };
+
+ return s;
+ }
+
+ /**
+ * Initialize from the configuration file.
+ *
+ * @param id String name of this instance
+ * @param implName string name of this implementation
+ * @param config configuration store for this instance
+ * @exception EBaseException
+ */
+ public void init(ISubsystem owner, String id, String implName, IConfigStore config) throws
+ EBaseException {
+ mConfig = config;
+ mId = id;
+ mImplName = implName;
+
+ mCA = (ICertificateAuthority)
+ CMS.getSubsystem("ca");
+ if (mCA == null) {
+ mSummary = false;
+ return;
+ }
+
+ mCertDB = mCA.getCertificateRepository();
+
+ mCron = mConfig.getString(IJobCron.PROP_CRON);
+ if (mCron == null) {
+ return;
+ }
+
+ // parse cron string into a JobCron class
+ IJobsScheduler scheduler = (IJobsScheduler) owner;
+
+ mJobCron = scheduler.createJobCron(mCron);
+ }
+
+ /**
+ * finds out which cert needs notification and notifies the
+ * responsible parties
+ */
+ public void run() {
+ // for forming renewal URL at template
+ mHttpHost = CMS.getEEHost();
+ mHttpPort = CMS.getEESSLPort();
+
+ // read from the configuration file
+ try {
+ mPreDays = mConfig.getInteger(PROP_NOTIFYTRIGGEROFFSET, 30); // in days
+ mPostDays = mConfig.getInteger(PROP_NOTIFYENDOFFSET, 15); // in days
+
+ mEmailSender = mConfig.getString(PROP_SENDEREMAIL);
+ mEmailSubject = mConfig.getString(PROP_EMAILSUBJECT);
+ mEmailTemplateName = mConfig.getString(PROP_EMAILTEMPLATE);
+
+ // initialize the summary related config info
+ IConfigStore sc = mConfig.getSubStore(PROP_SUMMARY);
+
+ if (sc.getBoolean(PROP_ENABLED, false)) {
+ mSummary = true;
+ mSummaryItemTemplateName =
+ mConfig.getString(PROP_SUMMARY_ITEMTEMPLATE);
+ mSummarySenderEmail =
+ mConfig.getString(PROP_SUMMARY_SENDEREMAIL);
+ mSummaryReceiverEmail =
+ mConfig.getString(PROP_SUMMARY_RECIPIENTEMAIL);
+ mSummaryMailSubject =
+ mConfig.getString(PROP_SUMMARY_SUBJECT);
+ mSummaryTemplateName =
+ mConfig.getString(PROP_SUMMARY_TEMPLATE);
+ } else {
+ mSummary = false;
+ }
+
+ long msperday = 86400 * 1000;
+ long mspredays = mPreDays;
+ long mspostdays = mPostDays;
+
+ mPreMS = mspredays * msperday;
+ mPostMS = mspostdays * msperday;
+
+ Date now = CMS.getCurrentDate();
+ DateFormat dateFormat = DateFormat.getDateTimeInstance();
+ String nowString = dateFormat.format(now);
+
+ /*
+ * look in the internal db for certificateRecords that are
+ * 1. within the expiration notification period
+ * 2. has not yet been renewed
+ * 3. notify - use EmailTemplateProcessor to formulate
+ * content, then send
+ * if notified successfully, mark "STATUS_SUCCESS",
+ * else, if notified unsuccessfully, mark "STATUS_FAILURE".
+ */
+
+ /* 1) make target notAfter string */
+
+ Date expiryDate = null;
+ Date stopDate = null;
+
+ /* 2) Assemble ldap Search filter string */
+ // date format: 19991215125306Z
+ long expiryMS = now.getTime() + mPreMS;
+ long stopMS = now.getTime() - mPostMS;
+
+ expiryDate = new Date(expiryMS);
+ stopDate = new Date(stopMS);
+
+ // All cert records which:
+ // 1) expire before the deadline
+ // 2) have not already been renewed
+ // filter format:
+ // (& (notafter<='time')(!(certAutoRenew=DONE))(!certAutoRenew=DISABLED))
+
+ StringBuffer f = new StringBuffer();
+ String profileId = "";
+ try {
+ profileId = mConfig.getString(PROP_PROFILE_ID, "");
+ } catch (EBaseException ee) {
+ }
+
+ if (profileId != null && profileId.length() > 0) {
+ StringTokenizer tokenizer = new StringTokenizer(profileId);
+ int num = tokenizer.countTokens();
+ mProfileId = new String[num];
+ for (int i = 0; i < num; i++)
+ mProfileId[i] = tokenizer.nextToken();
+ }
+
+ f.append("(&");
+ if (mProfileId != null) {
+ if (mProfileId.length == 1)
+ f.append("(" + ICertRecord.ATTR_META_INFO + "=" +
+ ICertRecord.META_PROFILE_ID + ":" + mProfileId[0] + ")");
+ else {
+ f.append("(|");
+ for (int i = 0; i < mProfileId.length; i++) {
+ f.append("(" + ICertRecord.ATTR_META_INFO + "=" +
+ ICertRecord.META_PROFILE_ID + ":" + mProfileId[i] + ")");
+ }
+ f.append(")");
+ }
+ }
+
+ f.append("(" + ICertRecord.ATTR_X509CERT + ".notAfter" + "<=" + expiryDate.getTime() + ")");
+ f.append("(" + ICertRecord.ATTR_X509CERT + ".notAfter" + ">=" + stopDate.getTime() + ")");
+ f.append("(!(" + ICertRecord.ATTR_AUTO_RENEW + "=" + ICertRecord.AUTO_RENEWAL_DONE + "))");
+ f.append("(!(" + ICertRecord.ATTR_AUTO_RENEW + "=" + ICertRecord.AUTO_RENEWAL_DISABLED + "))");
+ f.append("(!(" + ICertRecord.ATTR_CERT_STATUS + "=" + ICertRecord.STATUS_REVOKED + "))");
+ f.append("(!(" + ICertRecord.ATTR_CERT_STATUS + "=" + ICertRecord.STATUS_REVOKED_EXPIRED + "))");
+ f.append(")");
+ String filter = f.toString();
+
+ String emailTemplate =
+ getTemplateContent(mEmailTemplateName);
+
+ mHTML = mMailHTML;
+
+ try {
+ String summaryItemTemplate = null;
+
+ if (mSummary == true) {
+ summaryItemTemplate =
+ getTemplateContent(mSummaryItemTemplateName);
+ }
+
+ ItemCounter ic = new ItemCounter();
+ CertRecProcessor cp = new CertRecProcessor(this, emailTemplate, summaryItemTemplate, ic);
+ //CertRecordList list = mCertDB.findCertRecordsInList(filter, null, "serialno", 5);
+ //list.processCertRecords(0, list.getSize() - 1, cp);
+
+ Enumeration<Object> en = mCertDB.findCertRecs(filter);
+
+ while (en.hasMoreElements()) {
+ Object element = en.nextElement();
+
+ try {
+ cp.process(element);
+ } catch (Exception e) {
+ //Don't abort the entire operation. The error should already be logged
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("JOBS_FAILED_PROCESS", e.toString()));
+ }
+ }
+
+ // Now send the summary
+
+ if (mSummary == true) {
+ try {
+ String summaryTemplate =
+ getTemplateContent(mSummaryTemplateName);
+
+ mSummaryHTML = mMailHTML;
+
+ buildContentParams(IEmailFormProcessor.TOKEN_ID,
+ mId);
+
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_ITEM_LIST,
+ ic.mItemListContent);
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_TOTAL_NUM,
+ String.valueOf(ic.mNumFail + ic.mNumSuccessful));
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_SUCCESS_NUM,
+ String.valueOf(ic.mNumSuccessful));
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_FAILURE_NUM,
+ String.valueOf(ic.mNumFail));
+
+ buildContentParams(IEmailFormProcessor.TOKEN_EXECUTION_TIME,
+ nowString);
+
+ IEmailFormProcessor summaryEmfp = CMS.getEmailFormProcessor();
+
+ String summaryContent =
+ summaryEmfp.getEmailContent(summaryTemplate,
+ mContentParams);
+
+ if (summaryContent == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("JOBS_SUMMARY_CONTENT_NULL"));
+ mailSummary(" no summaryContent");
+ } else {
+ mMailHTML = mSummaryHTML;
+ mailSummary(summaryContent);
+ }
+ } catch (Exception e) {
+ // log error
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("JOBS_EXCEPTION_IN_RUN", e.toString()));
+ }
+ }
+ } catch (EBaseException e) {
+ // log error
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+ } catch (EBaseException ex) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("Configuration error:", ex.toString()));
+ }
+ }
+
+ /**
+ * get instance id.
+ *
+ * @return a String identifier
+ */
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * set instance id.
+ *
+ * @param id String id of the instance
+ */
+ public void setId(String id) {
+ mId = id;
+ }
+
+ /**
+ * get cron string associated with this job
+ *
+ * @return a JobCron object that represents the schedule of this job
+ */
+ public IJobCron getJobCron() {
+ return mJobCron;
+ }
+
+ /**
+ * gets the plugin name of this job.
+ *
+ * @return a String that is the name of this implementation
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ /**
+ * Gets the configuration substore used by this job
+ *
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ protected void mailUser(String subject,
+ String msg,
+ String sender,
+ IRequest req,
+ ICertRecord cr)
+ throws IOException, ENotificationException, EBaseException {
+
+ IMailNotification mn = CMS.getMailNotification();
+
+ String rcp = null;
+ // boolean sendFailed = false;
+ Exception sendFailedException = null;
+
+ IEmailResolverKeys keys = CMS.getEmailResolverKeys();
+
+ try {
+ if (req != null) {
+ keys.set(IEmailResolverKeys.KEY_REQUEST, req);
+ }
+ if (cr != null) {
+ Object c = cr.getCertificate();
+
+ if (c != null) {
+ keys.set(IEmailResolverKeys.KEY_CERT, cr.getCertificate());
+ }
+ }
+
+ IEmailResolver er = CMS.getReqCertSANameEmailResolver();
+
+ rcp = er.getEmail(keys);
+
+ } catch (Exception e) {
+ // already logged by the resolver
+ // sendFailed = true;
+ sendFailedException = e;
+ throw (ENotificationException) sendFailedException;
+ }
+
+ mn.setTo(rcp);
+
+ if (sender != null)
+ mn.setFrom(sender);
+ else
+ mn.setFrom("nobody");
+
+ if (subject != null)
+ mn.setSubject(subject);
+ else
+ mn.setFrom("Important message from Certificate Authority");
+
+ if (mHTML == true)
+ mn.setContentType("text/html");
+
+ mn.setContent(msg);
+
+ mn.sendNotification();
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+}
+
+class CertRecProcessor implements IElementProcessor {
+ protected RenewalNotificationJob mJob;
+ protected String mEmailTemplate;
+ protected String mSummaryItemTemplate;
+ protected ItemCounter mIC;
+
+ public CertRecProcessor(RenewalNotificationJob job, String emailTemplate,
+ String summaryItemTemplate, ItemCounter ic) {
+ mJob = job;
+ mEmailTemplate = emailTemplate;
+ mSummaryItemTemplate = summaryItemTemplate;
+ mIC = ic;
+ }
+
+ public void process(Object o) throws EBaseException {
+
+ // Get each certRecord
+ ICertRecord cr = (ICertRecord) o;
+
+ String ridString = null;
+ boolean numFailCounted = false;
+
+ if (cr != null) {
+ mJob.buildItemParams(cr.getCertificate());
+ mJob.buildItemParams(IEmailFormProcessor.TOKEN_HTTP_HOST,
+ mJob.mHttpHost);
+ mJob.buildItemParams(IEmailFormProcessor.TOKEN_HTTP_PORT, mJob.mHttpPort);
+
+ MetaInfo metaInfo = null;
+
+ metaInfo = (MetaInfo) cr.get(ICertRecord.ATTR_META_INFO);
+ if (metaInfo == null) {
+ mIC.mNumFail++;
+ numFailCounted = true;
+ if (mJob.mSummary == true)
+ mJob.buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ AJobBase.STATUS_FAILURE);
+ mJob.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_GET_CERT_ERROR",
+ cr.getCertificate().getSerialNumber().toString(16)));
+ } else {
+ ridString = (String) metaInfo.get(ICertRecord.META_REQUEST_ID);
+ }
+ }
+
+ IRequest req = null;
+
+ if (ridString != null) {
+ RequestId rid = new RequestId(ridString);
+
+ try {
+ req = mJob.mCA.getRequestQueue().findRequest(rid);
+ } catch (Exception e) {
+ // it is ok not to be able to get the request. The main reason
+ // to get the request is to retrieve the requestor's email.
+ // We can retrieve the email from the CertRecord.
+ CMS.debug("huh RenewalNotificationJob Exception: " + e.toString());
+ }
+
+ if (req != null)
+ mJob.buildItemParams(req);
+ } // ridString != null
+
+ try {
+ // send mail to user
+
+ IEmailFormProcessor emfp = CMS.getEmailFormProcessor();
+ String message = emfp.getEmailContent(mEmailTemplate,
+ mJob.mItemParams);
+
+ mJob.mailUser(mJob.mEmailSubject,
+ message,
+ mJob.mEmailSender,
+ req,
+ cr);
+
+ mJob.buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ AJobBase.STATUS_SUCCESS);
+
+ mIC.mNumSuccessful++;
+
+ } catch (Exception e) {
+ CMS.debug("RenewalNotificationJob Exception: " + e.toString());
+ mJob.buildItemParams(IEmailFormProcessor.TOKEN_STATUS, AJobBase.STATUS_FAILURE);
+ mJob.log(ILogger.LL_FAILURE, e.toString(), ILogger.L_MULTILINE);
+ if (numFailCounted == false) {
+ mIC.mNumFail++;
+ }
+ }
+
+ if (mJob.mSummary == true) {
+ IEmailFormProcessor summaryItemEmfp =
+ CMS.getEmailFormProcessor();
+ String c =
+ summaryItemEmfp.getEmailContent(mSummaryItemTemplate,
+ mJob.mItemParams);
+
+ if (mIC.mItemListContent == null) {
+ mIC.mItemListContent = c;
+ } else {
+ mIC.mItemListContent += c;
+ }
+ }
+ }
+}
+
+class ItemCounter {
+ public int mNumSuccessful = 0;
+ public int mNumFail = 0;
+ public String mItemListContent = null;
+}
diff --git a/base/server/cms/src/com/netscape/cms/jobs/RequestInQueueJob.java b/base/server/cms/src/com/netscape/cms/jobs/RequestInQueueJob.java
new file mode 100644
index 000000000..5d1ea2f2b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/jobs/RequestInQueueJob.java
@@ -0,0 +1,217 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.jobs;
+
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+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.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.jobs.IJob;
+import com.netscape.certsrv.jobs.IJobCron;
+import com.netscape.certsrv.jobs.IJobsScheduler;
+import com.netscape.certsrv.notification.IEmailFormProcessor;
+import com.netscape.certsrv.request.IRequestList;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestStatus;
+
+/**
+ * A job for the Jobs Scheduler. This job checks in the internal ldap
+ * db for requests currently in the request queue and send a summary
+ * report to the administrator
+ * <p>
+ * the $TOKENS that are available for the this jobs's summary outer form are:<br>
+ * <UL>
+ * $InstanceID $SummaryTotalNum $ExecutionTime
+ * </UL>
+ *
+ * @version $Revision$, $Date$
+ * @see com.netscape.certsrv.jobs.IJob
+ * @see com.netscape.cms.jobs.AJobBase
+ */
+public class RequestInQueueJob extends AJobBase
+ implements IJob, Runnable, IExtendedPluginInfo {
+ protected static final String PROP_SUBSYSTEM_ID = "subsystemId";
+
+ IAuthority mSub = null;
+ IRequestQueue mReqQ = null;
+ private boolean mSummary = false;
+
+ /* Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ protected static String[] mConfigParams =
+ new String[] {
+ "enabled",
+ "cron",
+ "subsystemId",
+ "summary.enabled",
+ "summary.emailSubject",
+ "summary.emailTemplate",
+ "summary.senderEmail",
+ "summary.recipientEmail"
+ };
+
+ /**
+ * holds help text for this plugin
+ */
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String s[] = {
+ IExtendedPluginInfo.HELP_TEXT +
+ "; A job that checks for enrollment requests in the " +
+ "queue, and reports to recipientEmail",
+ "cron;string;Format: minute hour dayOfMonth month " +
+ "dayOfWeek. Use '*' for 'every'. For dayOfWeek, 0 is Sunday",
+ "summary.senderEmail;string;Specify the address to be used " +
+ "as the email's 'sender'. Bounces go to this address.",
+ "summary.recipientEmail;string;Who should receive summaries",
+ "enabled;boolean;Enable this plugin",
+ "summary.enabled;boolean;Enable the summary. You must enabled " +
+ "this for the job to work.",
+ "summary.emailSubject;string;Subject of summary email",
+ "summary.emailTemplate;string;Fully qualified pathname of " +
+ "template file of email to be sent",
+ "subsystemId;choice(ca,ra);The type of subsystem this job is " +
+ "for",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-jobrules-requestinqueuejob",
+ };
+
+ return s;
+ }
+
+ /**
+ * initialize from the configuration file
+ *
+ * @param id String name of this instance
+ * @param implName string name of this implementation
+ * @param config configuration store for this instance
+ * @exception EBaseException
+ */
+ public void init(ISubsystem owner, String id, String implName, IConfigStore config) throws
+ EBaseException {
+ mConfig = config;
+ mId = id;
+ mImplName = implName;
+
+ // read from the configuration file
+ String sub = mConfig.getString(PROP_SUBSYSTEM_ID);
+
+ mSub = (IAuthority)
+ CMS.getSubsystem(sub);
+ if (mSub == null) {
+ // take this as disable
+ mSummary = false;
+ return;
+ }
+
+ mReqQ = mSub.getRequestQueue();
+
+ mCron = mConfig.getString(IJobCron.PROP_CRON);
+ if (mCron == null) {
+ return;
+ }
+
+ // parse cron string into a JobCron class
+ IJobsScheduler scheduler = (IJobsScheduler) owner;
+
+ mJobCron = scheduler.createJobCron(mCron);
+
+ // initialize the summary related config info
+ IConfigStore sc = mConfig.getSubStore(PROP_SUMMARY);
+
+ if (sc.getBoolean(PROP_ENABLED, false)) {
+ mSummary = true;
+ mSummaryMailSubject = sc.getString(PROP_EMAIL_SUBJECT);
+ mMailForm = sc.getString(PROP_EMAIL_TEMPLATE);
+ // mItemForm = sc.getString(PROP_ITEM_TEMPLATE);
+ mSummarySenderEmail = sc.getString(PROP_SENDER_EMAIL);
+ mSummaryReceiverEmail = sc.getString(PROP_RECEIVER_EMAIL);
+ } else {
+ mSummary = false;
+ }
+ }
+
+ /**
+ * summarize the queue status and mail it
+ */
+ public void run() {
+ if (mSummary == false)
+ return;
+
+ Date date = CMS.getCurrentDate();
+ DateFormat dateFormat = DateFormat.getDateTimeInstance();
+ String nowString = dateFormat.format(date);
+
+ int count = 0;
+ IRequestList list =
+ mReqQ.listRequestsByStatus(RequestStatus.PENDING);
+
+ while (list != null && list.hasMoreElements()) {
+ list.nextRequestId();
+
+ /* This is way too slow
+ // get request from request id
+ IRequest req = null;
+ try {
+ req = mReqQ.findRequest(rid);
+ } catch (EBaseException e) {
+ System.out.println(e.toString());
+ }
+ */
+ count++;
+ }
+
+ // if (count == 0) return;
+
+ String contentForm = null;
+
+ contentForm = getTemplateContent(mMailForm);
+
+ buildContentParams(IEmailFormProcessor.TOKEN_ID, mId);
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_TOTAL_NUM,
+ String.valueOf(count));
+ buildContentParams(IEmailFormProcessor.TOKEN_EXECUTION_TIME,
+ nowString);
+
+ IEmailFormProcessor emailFormProcessor = CMS.getEmailFormProcessor();
+ String mailContent =
+ emailFormProcessor.getEmailContent(contentForm,
+ mContentParams);
+
+ mailSummary(mailContent);
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return mConfigParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/jobs/UnpublishExpiredJob.java b/base/server/cms/src/com/netscape/cms/jobs/UnpublishExpiredJob.java
new file mode 100644
index 000000000..b28e93751
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/jobs/UnpublishExpiredJob.java
@@ -0,0 +1,384 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.jobs;
+
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.jobs.IJob;
+import com.netscape.certsrv.jobs.IJobCron;
+import com.netscape.certsrv.jobs.IJobsScheduler;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.notification.IEmailFormProcessor;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+
+/**
+ * a job for the Jobs Scheduler. This job checks in the internal ldap
+ * db for certs that have expired and remove them from the ldap
+ * publishing directory.
+ * <p>
+ * the $TOKENS that are available for the this jobs's summary outer form are:<br>
+ * <UL>
+ * $Status $InstanceID $SummaryItemList $SummaryTotalNum $SummaryTotalSuccess $SummaryTotalfailure $ExecutionTime
+ * </UL>
+ * and for the inner list items:
+ * <UL>
+ * $SerialNumber $IssuerDN $SubjectDN $NotAfter $NotBefore $RequestorEmail $CertType
+ * </UL>
+ *
+ * @version $Revision$, $Date$
+ */
+public class UnpublishExpiredJob extends AJobBase
+ implements IJob, Runnable, IExtendedPluginInfo {
+
+ ICertificateAuthority mCa = null;
+ IRequestQueue mReqQ = null;
+ ICertificateRepository mRepository = null;
+ IPublisherProcessor mPublisherProcessor = null;
+ private boolean mSummary = false;
+
+ /* Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ protected static String[] mConfigParams =
+ new String[] {
+ "enabled",
+ "cron",
+ "summary.enabled",
+ "summary.emailSubject",
+ "summary.emailTemplate",
+ "summary.itemTemplate",
+ "summary.senderEmail",
+ "summary.recipientEmail"
+ };
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String s[] = {
+ IExtendedPluginInfo.HELP_TEXT +
+ "; A job that checks for expired certificates in the " +
+ "database, and removes them from the publishing " +
+ "directory",
+ "cron;string;Format: minute hour dayOfMonth month " +
+ "dayOfWeek. Use '*' for 'every'. For dayOfWeek, 0 is Sunday",
+ "summary.senderEmail;string;Specify the address to be used " +
+ "as the email's 'sender'. Bounces go to this address.",
+ "summary.recipientEmail;string;Who should receive summaries",
+ "enabled;boolean;Enable this plugin",
+ "summary.enabled;boolean;Enable the summary. You must enabled " +
+ "this for the job to work.",
+ "summary.emailSubject;string;Subject of summary email",
+ "summary.emailTemplate;string;Fully qualified pathname of " +
+ "template file of email to be sent",
+ "summary.itemTemplate;string;Fully qualified pathname of " +
+ "file containing template for each item",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-jobrules-unpublishexpiredjobs",
+ };
+
+ return s;
+ }
+
+ /**
+ * initialize from the configuration file
+ */
+ public void init(ISubsystem owner, String id, String implName, IConfigStore config) throws
+ EBaseException {
+ mConfig = config;
+ mId = id;
+ mImplName = implName;
+
+ mCa = (ICertificateAuthority)
+ CMS.getSubsystem("ca");
+ if (mCa == null) {
+ return;
+ }
+
+ mReqQ = mCa.getRequestQueue();
+ mRepository = mCa.getCertificateRepository();
+ mPublisherProcessor = mCa.getPublisherProcessor();
+
+ // read from the configuration file
+ mCron = mConfig.getString(IJobCron.PROP_CRON);
+ if (mCron == null) {
+ return;
+ }
+
+ // parse cron string into a JobCron class
+ IJobsScheduler scheduler = (IJobsScheduler) owner;
+
+ mJobCron = scheduler.createJobCron(mCron);
+
+ // initialize the summary related config info
+ IConfigStore sc = mConfig.getSubStore(PROP_SUMMARY);
+
+ if (sc.getBoolean(PROP_ENABLED, false)) {
+ mSummary = true;
+ mSummaryMailSubject = sc.getString(PROP_EMAIL_SUBJECT);
+ mMailForm = sc.getString(PROP_EMAIL_TEMPLATE);
+ mItemForm = sc.getString(PROP_ITEM_TEMPLATE);
+ mSummarySenderEmail = sc.getString(PROP_SENDER_EMAIL);
+ mSummaryReceiverEmail = sc.getString(PROP_RECEIVER_EMAIL);
+ } else {
+ mSummary = false;
+ }
+ }
+
+ /**
+ * look in the internal db for certificateRecords that are
+ * expired.
+ * remove them from ldap publishing directory
+ * if remove successfully, mark <i>false</i> on the
+ * <b>InLdapPublishDir</b> flag,
+ * else, if remove unsuccessfully, log it
+ */
+ public void run() {
+ // System.out.println("in ExpiredUnpublishJob "+
+ // getId()+ " : run()");
+ // get time now..."now" is before the loop
+ Date date = CMS.getCurrentDate();
+ long now = date.getTime();
+ DateFormat dateFormat = DateFormat.getDateTimeInstance();
+ String nowString = dateFormat.format(date);
+
+ // form filter
+ String filter = "(&(x509Cert.notAfter<=" + now +
+ ")(!(x509Cert.notAfter=" + now + "))" +
+ "(" + "certMetainfo=" + ICertRecord.META_LDAPPUBLISH +
+ ":true))";
+ // a test for without CertRecord.META_LDAPPUBLISH
+ //String filter = "(x509Cert.notAfter<="+ now +")";
+
+ Enumeration<Object> expired = null;
+
+ try {
+ expired = mRepository.findCertRecs(filter);
+ // bug 399150
+ /*
+ CertRecordList list = null;
+ list = mRepository.findCertRecordsInList(filter, null, "serialno", 5);
+ int size = list.getSize();
+ expired = list.getCertRecords(0, size - 1);
+ */
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+
+ int count = 0; // how many have been unpublished successfully
+ int negCount = 0; // how many have NOT been unpublished successfully
+ String contentForm = null;
+ String itemForm = null;
+ String itemListContent = null;
+
+ if (mSummary == true) {
+ contentForm = getTemplateContent(mMailForm);
+ itemForm = getTemplateContent(mItemForm);
+ }
+
+ // unpublish them and unpublish() will set inLdapPublishDir flag
+ while (expired != null && expired.hasMoreElements()) {
+ ICertRecord rec = (ICertRecord) expired.nextElement();
+
+ if (rec == null)
+ break;
+ X509CertImpl cert = rec.getCertificate();
+
+ if (mSummary == true)
+ buildItemParams(cert);
+
+ // get request id from cert record MetaInfo
+ MetaInfo minfo = null;
+
+ try {
+ minfo = (MetaInfo) rec.get(ICertRecord.ATTR_META_INFO);
+ } catch (EBaseException e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_META_INFO_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+
+ String ridString = null;
+
+ try {
+ if (minfo != null)
+ ridString = (String) minfo.get(ICertRecord.META_REQUEST_ID);
+ } catch (EBaseException e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_META_REQUEST_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ } catch (NullPointerException e) {
+ // no requestId in MetaInfo...skip to next record
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_META_REQUEST_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+
+ if (ridString != null) {
+ RequestId rid = new RequestId(ridString);
+
+ // get request from request id
+ IRequest req = null;
+
+ try {
+ req = mReqQ.findRequest(rid);
+ if (req != null) {
+ if (mSummary == true)
+ buildItemParams(req);
+ }
+ } catch (EBaseException e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_FIND_REQUEST_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+ try {
+ if ((mPublisherProcessor != null) &&
+ mPublisherProcessor.enabled()) {
+ mPublisherProcessor.unpublishCert(cert, req);
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_SUCCESS);
+ count += 1;
+ } else {
+ negCount += 1;
+ }
+ } catch (Exception e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_UNPUBLISH_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+ } // ridString != null
+ else {
+ try {
+ if ((mPublisherProcessor != null) &&
+ mPublisherProcessor.enabled()) {
+ mPublisherProcessor.unpublishCert(cert, null);
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_SUCCESS);
+ count += 1;
+ } else {
+ negCount += 1;
+ }
+ } catch (Exception e) {
+ negCount += 1;
+ if (mSummary == true)
+ buildItemParams(IEmailFormProcessor.TOKEN_STATUS,
+ STATUS_FAILURE);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("JOBS_UNPUBLISH_ERROR",
+ cert.getSerialNumber().toString(16) +
+ e.toString()));
+ }
+ } // ridString == null
+
+ // inLdapPublishDir flag should have been set by the
+ // unpublish() method
+
+ // if summary is enabled, form the item content
+ if (mSummary) {
+ IEmailFormProcessor emailItemFormProcessor =
+ CMS.getEmailFormProcessor();
+ String c = emailItemFormProcessor.getEmailContent(itemForm,
+ mItemParams);
+
+ // add item content to the item list
+ if (itemListContent == null) {
+ itemListContent = c;
+ } else {
+ itemListContent += c;
+ }
+ }
+ }
+
+ // time for summary
+ if (mSummary == true) {
+ buildContentParams(IEmailFormProcessor.TOKEN_ID,
+ mId);
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_ITEM_LIST,
+ itemListContent);
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_TOTAL_NUM,
+ String.valueOf(count + negCount));
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_SUCCESS_NUM,
+ String.valueOf(count));
+ buildContentParams(IEmailFormProcessor.TOKEN_SUMMARY_FAILURE_NUM,
+ String.valueOf(negCount));
+ buildContentParams(IEmailFormProcessor.TOKEN_EXECUTION_TIME,
+ nowString);
+
+ IEmailFormProcessor emailFormProcessor = CMS.getEmailFormProcessor();
+ String mailContent =
+ emailFormProcessor.getEmailContent(contentForm,
+ mContentParams);
+
+ mailSummary(mailContent);
+ }
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/listeners/CertificateIssuedListener.java b/base/server/cms/src/com/netscape/cms/listeners/CertificateIssuedListener.java
new file mode 100644
index 000000000..44ff46a9b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/listeners/CertificateIssuedListener.java
@@ -0,0 +1,449 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.listeners;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.Hashtable;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.listeners.EListenersException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.notification.ENotificationException;
+import com.netscape.certsrv.notification.IEmailFormProcessor;
+import com.netscape.certsrv.notification.IEmailResolver;
+import com.netscape.certsrv.notification.IEmailResolverKeys;
+import com.netscape.certsrv.notification.IEmailTemplate;
+import com.netscape.certsrv.notification.IMailNotification;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestListener;
+import com.netscape.certsrv.request.RequestId;
+
+/**
+ * a listener for every completed enrollment request
+ * <p>
+ * Here is a list of available $TOKENs for email notification templates if certificate is successfully issued:
+ * <UL>
+ * <LI>$InstanceID
+ * <LI>$SerialNumber
+ * <LI>$HexSerialNumber
+ * <LI>$HttpHost
+ * <LI>$HttpPort
+ * <LI>$RequestId
+ * <LI>$IssuerDN
+ * <LI>$SubjectDN
+ * <LI>$NotBefore
+ * <LI>$NotAfter
+ * <LI>$SenderEmail
+ * <LI>$RecipientEmail
+ * </UL>
+ * <p>
+ * Here is a list of available $TOKENs for email notification templates if certificate request is rejected:
+ * <UL>
+ * <LI>$RequestId
+ * <LI>$InstanceID
+ * </UL>
+ *
+ * @version $Revision$, $Date$
+ */
+public class CertificateIssuedListener implements IRequestListener {
+ protected final static String PROP_CERT_ISSUED_SUBSTORE = "certIssued";
+ protected static final String PROP_ENABLED = "enabled";
+ protected final static String PROP_NOTIFY_SUBSTORE = "notification";
+
+ protected final static String PROP_SENDER_EMAIL = "senderEmail";
+ protected final static String PROP_EMAIL_SUBJECT = "emailSubject";
+ public final static String PROP_EMAIL_TEMPLATE = "emailTemplate";
+
+ protected final static String REJECT_FILE_NAME = "certRequestRejected";
+
+ private boolean mEnabled = false;
+ private ILogger mLogger = CMS.getLogger();
+ private String mSenderEmail = null;
+ private String mSubject = null;
+ private String mSubject_Success = null;
+ private String mFormPath = null;
+ private String mRejectPath = null;
+ private Hashtable<String, Object> mContentParams = new Hashtable<String, Object>();
+
+ private IConfigStore mConfig = null;
+ private DateFormat mDateFormat = null;
+ private ICertAuthority mSubsystem = null;
+ private String mHttpHost = null;
+ private String mHttpPort = null;
+ private RequestId mReqId = null;
+
+ public CertificateIssuedListener() {
+ }
+
+ public void init(ISubsystem sub, IConfigStore config)
+ throws EListenersException, EPropertyNotFound, EBaseException {
+ mSubsystem = (ICertAuthority) sub;
+ mConfig = mSubsystem.getConfigStore();
+
+ IConfigStore nc = mConfig.getSubStore(PROP_NOTIFY_SUBSTORE);
+ IConfigStore rc = nc.getSubStore(PROP_CERT_ISSUED_SUBSTORE);
+
+ mEnabled = rc.getBoolean(PROP_ENABLED, false);
+
+ mSenderEmail = rc.getString(PROP_SENDER_EMAIL);
+ if (mSenderEmail == null) {
+ throw new EListenersException(CMS.getLogMessage("NO_NOTIFY_SENDER_EMAIL_CONFIG_FOUND"));
+ }
+
+ mFormPath = rc.getString(PROP_EMAIL_TEMPLATE);
+ String mDir = null;
+
+ // figure out the reject email path: same dir as form path,
+ // same ending as form path
+ int ridx = mFormPath.lastIndexOf(File.separator);
+
+ if (ridx == -1) {
+ CMS.debug("CertificateIssuedListener: file separator: " + File.separator
+ +
+ " not found. Use default /");
+ ridx = mFormPath.lastIndexOf("/");
+ mDir = mFormPath.substring(0, ridx + 1);
+ } else {
+ mDir = mFormPath.substring(0, ridx +
+ File.separator.length());
+ }
+ CMS.debug("CertificateIssuedListener: template file directory: " + mDir);
+ mRejectPath = mDir + REJECT_FILE_NAME;
+ if (mFormPath.endsWith(".html"))
+ mRejectPath += ".html";
+ else if (mFormPath.endsWith(".HTML"))
+ mRejectPath += ".HTML";
+ else if (mFormPath.endsWith(".htm"))
+ mRejectPath += ".htm";
+ else if (mFormPath.endsWith(".HTM"))
+ mRejectPath += ".HTM";
+
+ CMS.debug("CertificateIssuedListener: Reject file path: " + mRejectPath);
+
+ mDateFormat = DateFormat.getDateTimeInstance();
+
+ mSubject_Success = rc.getString(PROP_EMAIL_SUBJECT,
+ "Your Certificate Request");
+ mSubject = new String(mSubject_Success);
+
+ // form the cert retrieval URL for the notification
+ mHttpHost = CMS.getEEHost();
+ mHttpPort = CMS.getEESSLPort();
+
+ // register for this event listener
+ mSubsystem.registerRequestListener(this);
+ }
+
+ public void accept(IRequest r) {
+ CMS.debug("CertificateIssuedListener: accept " +
+ r.getRequestId().toString());
+ if (mEnabled != true)
+ return;
+
+ mSubject = mSubject_Success;
+ mReqId = r.getRequestId();
+ // is it rejected?
+ String rs = r.getRequestStatus().toString();
+
+ if (rs.equals("rejected")) {
+ CMS.debug("CertificateIssuedListener: Request status: " + rs);
+ rejected(r);
+ return;
+ }
+
+ CMS.debug("CertificateIssuedListener: accept check status ");
+
+ // check if it is profile request
+ String profileId = r.getExtDataInString("profileId");
+
+ // check if request failed.
+ if (profileId == null) {
+ if (r.getExtDataInInteger(IRequest.RESULT) == null)
+ return;
+ if ((r.getExtDataInInteger(IRequest.RESULT)).equals(IRequest.RES_ERROR)) {
+ CMS.debug("CertificateIssuedListener: Request errored. " +
+ "No need to email notify for enrollment request id " +
+ mReqId);
+ return;
+ }
+ }
+ String requestType = r.getRequestType();
+
+ if (requestType.equals(IRequest.ENROLLMENT_REQUEST) ||
+ requestType.equals(IRequest.RENEWAL_REQUEST)) {
+ CMS.debug("accept() enrollment/renewal request...");
+ // Get the certificate from the request
+ X509CertImpl issuedCert[] = null;
+
+ // handle profile-based enrollment's notification
+ if (profileId == null) {
+ issuedCert = r.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+ } else {
+ issuedCert = new X509CertImpl[1];
+ issuedCert[0] =
+ r.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
+ }
+
+ if (issuedCert != null) {
+ CMS.debug("CertificateIssuedListener: Sending email notification..");
+
+ // do we have an email to send?
+ String mEmail = null;
+ IEmailResolverKeys keys = CMS.getEmailResolverKeys();
+
+ try {
+ keys.set(IEmailResolverKeys.KEY_REQUEST, r);
+ keys.set(IEmailResolverKeys.KEY_CERT,
+ issuedCert[0]);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_SET_RESOLVER", e.toString()));
+ }
+
+ IEmailResolver er = CMS.getReqCertSANameEmailResolver();
+
+ try {
+ mEmail = er.getEmail(keys);
+ } catch (ENotificationException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_EXCEPTION",
+ e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_EXCEPTION",
+ e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_EXCEPTION",
+ e.toString()));
+ }
+
+ // now we can mail
+ if ((mEmail != null) && (!mEmail.equals(""))) {
+ mailIt(mEmail, issuedCert);
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_NOTIFY_ERROR",
+ issuedCert[0].getSerialNumber().toString(), mReqId.toString()));
+ // send failure notification to "sender"
+ mSubject = "Certificate Issued notification undeliverable";
+ mailIt(mSenderEmail, issuedCert);
+ }
+ }
+ }
+ }
+
+ private void mailIt(String mEmail, X509CertImpl issuedCert[]) {
+ IMailNotification mn = CMS.getMailNotification();
+
+ mn.setFrom(mSenderEmail);
+ mn.setTo(mEmail);
+ mn.setSubject(mSubject);
+
+ /*
+ * get template file from disk
+ */
+ IEmailTemplate template = CMS.getEmailTemplate(mFormPath);
+
+ /*
+ * parse and process the template
+ */
+ if (template != null) {
+ if (!template.init()) {
+ return;
+ }
+
+ buildContentParams(issuedCert, mEmail);
+ IEmailFormProcessor et = CMS.getEmailFormProcessor();
+ String c = et.getEmailContent(template.toString(), mContentParams);
+
+ if (template.isHTML()) {
+ mn.setContentType("text/html");
+ }
+ mn.setContent(c);
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_TEMPLATE_ERROR",
+ issuedCert[0].getSerialNumber().toString(), mReqId.toString()));
+
+ mn.setContent("Serial Number = " +
+ issuedCert[0].getSerialNumber() +
+ "; Request ID = " + mReqId);
+ }
+
+ try {
+ mn.sendNotification();
+ } catch (ENotificationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+ }
+
+ private void rejected(IRequest r) {
+ // do we have an email to send?
+ String mEmail = null;
+ IEmailResolverKeys keys = CMS.getEmailResolverKeys();
+
+ try {
+ keys.set(IEmailResolverKeys.KEY_REQUEST, r);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_SET_RESOLVER", e.toString()));
+ }
+
+ IEmailResolver er = CMS.getReqCertSANameEmailResolver();
+
+ try {
+ mEmail = er.getEmail(keys);
+ } catch (ENotificationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+
+ // now we can mail
+ if ((mEmail != null) && !mEmail.equals("")) {
+ IMailNotification mn = CMS.getMailNotification();
+
+ mn.setFrom(mSenderEmail);
+ mn.setTo(mEmail);
+ mn.setSubject(mSubject);
+
+ /*
+ * get rejection file from disk
+ */
+ IEmailTemplate template = CMS.getEmailTemplate(mRejectPath);
+
+ if (template != null) {
+ if (!template.init()) {
+ return;
+ }
+
+ if (template.isHTML()) {
+ mn.setContentType("text/html");
+ }
+
+ // build some token data
+ mContentParams.put(IEmailFormProcessor.TOKEN_ID, mConfig.getName());
+ mReqId = r.getRequestId();
+ mContentParams.put(IEmailFormProcessor.TOKEN_REQUEST_ID,
+ mReqId.toString());
+ IEmailFormProcessor et = CMS.getEmailFormProcessor();
+ String c = et.getEmailContent(template.toString(), mContentParams);
+
+ mn.setContent(c);
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LISTENERS_CERT_ISSUED_REJECTION"));
+ mn.setContent("Your Certificate Request has been rejected. Please contact your administrator for assistance");
+ }
+
+ try {
+ mn.sendNotification();
+ } catch (ENotificationException e) {
+ // already logged, lets audit
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_REJECTION_NOTIFICATION", mReqId.toString()));
+
+ }
+ }
+
+ private void buildContentParams(X509CertImpl issuedCert[], String mEmail) {
+ mContentParams.put(IEmailFormProcessor.TOKEN_ID,
+ mConfig.getName());
+ mContentParams.put(IEmailFormProcessor.TOKEN_SERIAL_NUM,
+ issuedCert[0].getSerialNumber().toString());
+ mContentParams.put(IEmailFormProcessor.TOKEN_HEX_SERIAL_NUM,
+ Long.toHexString(issuedCert[0].getSerialNumber().longValue()));
+ mContentParams.put(IEmailFormProcessor.TOKEN_REQUEST_ID,
+ mReqId.toString());
+ mContentParams.put(IEmailFormProcessor.TOKEN_HTTP_HOST,
+ mHttpHost);
+ mContentParams.put(IEmailFormProcessor.TOKEN_HTTP_PORT,
+ mHttpPort);
+ mContentParams.put(IEmailFormProcessor.TOKEN_ISSUER_DN,
+ issuedCert[0].getIssuerDN().toString());
+ mContentParams.put(IEmailFormProcessor.TOKEN_SUBJECT_DN,
+ issuedCert[0].getSubjectDN().toString());
+
+ Date date = issuedCert[0].getNotAfter();
+
+ mContentParams.put(IEmailFormProcessor.TOKEN_NOT_AFTER,
+ mDateFormat.format(date));
+
+ date = issuedCert[0].getNotBefore();
+ mContentParams.put(IEmailFormProcessor.TOKEN_NOT_BEFORE,
+ mDateFormat.format(date));
+
+ mContentParams.put(IEmailFormProcessor.TOKEN_SENDER_EMAIL,
+ mSenderEmail);
+ mContentParams.put(IEmailFormProcessor.TOKEN_RECIPIENT_EMAIL,
+ mEmail);
+ // ... and more
+ }
+
+ /**
+ * sets the configurable parameters
+ */
+ public void set(String name, String val) {
+ if (name.equalsIgnoreCase(PROP_ENABLED)) {
+ if (val.equalsIgnoreCase("true")) {
+ mEnabled = true;
+ } else {
+ mEnabled = false;
+ }
+ } else if (name.equalsIgnoreCase(PROP_SENDER_EMAIL)) {
+ mSenderEmail = val;
+ } else if (name.equalsIgnoreCase(PROP_EMAIL_SUBJECT)) {
+ mSubject_Success = val;
+ mSubject = mSubject_Success;
+ } else if (name.equalsIgnoreCase(PROP_EMAIL_TEMPLATE)) {
+ mFormPath = val;
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LISTENERS_CERT_ISSUED_SET"));
+ }
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/listeners/CertificateRevokedListener.java b/base/server/cms/src/com/netscape/cms/listeners/CertificateRevokedListener.java
new file mode 100644
index 000000000..b361057b4
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/listeners/CertificateRevokedListener.java
@@ -0,0 +1,368 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.listeners;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.Hashtable;
+
+import netscape.security.x509.RevokedCertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.listeners.EListenersException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.notification.ENotificationException;
+import com.netscape.certsrv.notification.IEmailFormProcessor;
+import com.netscape.certsrv.notification.IEmailResolver;
+import com.netscape.certsrv.notification.IEmailResolverKeys;
+import com.netscape.certsrv.notification.IEmailTemplate;
+import com.netscape.certsrv.notification.IMailNotification;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestListener;
+import com.netscape.certsrv.request.RequestId;
+
+/**
+ * a listener for every completed enrollment request
+ * <p>
+ * Here is a list of available $TOKENs for email notification templates if certificate is successfully issued:
+ * <UL>
+ * <LI>$InstanceID
+ * <LI>$SerialNumber
+ * <LI>$HexSerialNumber
+ * <LI>$HttpHost
+ * <LI>$HttpPort
+ * <LI>$RequestId
+ * <LI>$IssuerDN
+ * <LI>$SubjectDN
+ * <LI>$NotBefore
+ * <LI>$NotAfter
+ * <LI>$SenderEmail
+ * <LI>$RecipientEmail
+ * </UL>
+ * <p>
+ * Here is a list of available $TOKENs for email notification templates if certificate request is revoked:
+ * <UL>
+ * <LI>$RequestId
+ * <LI>$InstanceID
+ * </UL>
+ *
+ * @version $Revision$, $Date$
+ */
+public class CertificateRevokedListener implements IRequestListener {
+ protected final static String PROP_CERT_ISSUED_SUBSTORE = "certRevoked";
+ protected static final String PROP_ENABLED = "enabled";
+ protected final static String PROP_NOTIFY_SUBSTORE = "notification";
+
+ protected final static String PROP_SENDER_EMAIL = "senderEmail";
+ protected final static String PROP_EMAIL_SUBJECT = "emailSubject";
+ public final static String PROP_EMAIL_TEMPLATE = "emailTemplate";
+
+ protected final static String REJECT_FILE_NAME = "certRequestRejected";
+
+ private boolean mEnabled = false;
+ private ILogger mLogger = CMS.getLogger();
+ private String mSenderEmail = null;
+ private String mSubject = null;
+ private String mSubject_Success = null;
+ private String mFormPath = null;
+ private String mRejectPath = null;
+ private Hashtable<String, Object> mContentParams = new Hashtable<String, Object>();
+
+ private IConfigStore mConfig = null;
+ private DateFormat mDateFormat = null;
+ private ICertAuthority mSubsystem = null;
+ private String mHttpHost = null;
+ private String mHttpPort = null;
+ private RequestId mReqId = null;
+
+ public CertificateRevokedListener() {
+ }
+
+ public void init(ISubsystem sub, IConfigStore config)
+ throws EListenersException, EPropertyNotFound, EBaseException {
+ mSubsystem = (ICertAuthority) sub;
+ mConfig = mSubsystem.getConfigStore();
+
+ IConfigStore nc = mConfig.getSubStore(PROP_NOTIFY_SUBSTORE);
+ IConfigStore rc = nc.getSubStore(PROP_CERT_ISSUED_SUBSTORE);
+
+ mEnabled = rc.getBoolean(PROP_ENABLED, false);
+
+ mSenderEmail = rc.getString(PROP_SENDER_EMAIL);
+ if (mSenderEmail == null) {
+ throw new EListenersException(CMS.getLogMessage("NO_NOTIFY_SENDER_EMAIL_CONFIG_FOUND"));
+ }
+
+ mFormPath = rc.getString(PROP_EMAIL_TEMPLATE);
+ String mDir = null;
+
+ // figure out the reject email path: same dir as form path,
+ // same ending as form path
+ int ridx = mFormPath.lastIndexOf(File.separator);
+
+ if (ridx == -1) {
+ CMS.debug("CertificateRevokedListener: file separator: " + File.separator
+ +
+ " not found. Use default /");
+ ridx = mFormPath.lastIndexOf("/");
+ mDir = mFormPath.substring(0, ridx + 1);
+ } else {
+ mDir = mFormPath.substring(0, ridx +
+ File.separator.length());
+ }
+ CMS.debug("CertificateRevokedListener: template file directory: " + mDir);
+ mRejectPath = mDir + REJECT_FILE_NAME;
+ if (mFormPath.endsWith(".html"))
+ mRejectPath += ".html";
+ else if (mFormPath.endsWith(".HTML"))
+ mRejectPath += ".HTML";
+ else if (mFormPath.endsWith(".htm"))
+ mRejectPath += ".htm";
+ else if (mFormPath.endsWith(".HTM"))
+ mRejectPath += ".HTM";
+
+ CMS.debug("CertificateRevokedListener: Reject file path: " + mRejectPath);
+
+ mDateFormat = DateFormat.getDateTimeInstance();
+
+ mSubject_Success = rc.getString(PROP_EMAIL_SUBJECT,
+ "Your Certificate Request");
+ mSubject = new String(mSubject_Success);
+
+ // form the cert retrieval URL for the notification
+ mHttpHost = CMS.getEEHost();
+ mHttpPort = CMS.getEESSLPort();
+
+ // register for this event listener
+ mSubsystem.registerRequestListener(this);
+ }
+
+ public void accept(IRequest r) {
+ if (mEnabled != true)
+ return;
+
+ mSubject = mSubject_Success;
+ mReqId = r.getRequestId();
+ // is it revoked?
+ String rs = r.getRequestStatus().toString();
+ String requestType = r.getRequestType();
+
+ if (requestType.equals(IRequest.REVOCATION_REQUEST) == false)
+ return;
+ if (rs.equals("complete") == false) {
+ CMS.debug("CertificateRevokedListener: Request status: " + rs);
+ //revoked(r);
+ return;
+ }
+
+ // check if request failed.
+ if (r.getExtDataInInteger(IRequest.RESULT) == null)
+ return;
+
+ if ((r.getExtDataInInteger(IRequest.RESULT)).equals(IRequest.RES_ERROR)) {
+ CMS.debug("CertificateRevokedListener: Request errored. " +
+ "No need to email notify for enrollment request id " +
+ mReqId);
+ return;
+ }
+
+ if (requestType.equals(IRequest.REVOCATION_REQUEST)) {
+ CMS.debug("CertificateRevokedListener: accept() revocation request...");
+ // Get the certificate from the request
+ //X509CertImpl issuedCert[] =
+ // (X509CertImpl[])
+ RevokedCertImpl crlentries[] =
+ r.getExtDataInRevokedCertArray(IRequest.CERT_INFO);
+
+ if (crlentries != null) {
+ CMS.debug("CertificateRevokedListener: Sending email notification..");
+
+ // do we have an email to send?
+ String mEmail = null;
+ IEmailResolverKeys keys = CMS.getEmailResolverKeys();
+
+ try {
+ keys.set(IEmailResolverKeys.KEY_REQUEST, r);
+ keys.set(IEmailResolverKeys.KEY_CERT,
+ crlentries[0]);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_SET_RESOLVER", e.toString()));
+ }
+
+ IEmailResolver er = CMS.getReqCertSANameEmailResolver();
+
+ try {
+ mEmail = er.getEmail(keys);
+ } catch (ENotificationException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_EXCEPTION",
+ e.toString()));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_EXCEPTION",
+ e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_EXCEPTION",
+ e.toString()));
+ }
+
+ // now we can mail
+ if ((mEmail != null) && (!mEmail.equals(""))) {
+ mailIt(mEmail, crlentries);
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_NOTIFY_ERROR",
+ crlentries[0].getSerialNumber().toString(), mReqId.toString()));
+ // send failure notification to "sender"
+ mSubject = "Certificate Issued notification undeliverable";
+ mailIt(mSenderEmail, crlentries);
+ }
+ }
+ }
+ }
+
+ private void mailIt(String mEmail, RevokedCertImpl crlentries[]) {
+ IMailNotification mn = CMS.getMailNotification();
+
+ mn.setFrom(mSenderEmail);
+ mn.setTo(mEmail);
+ mn.setSubject(mSubject);
+
+ /*
+ * get template file from disk
+ */
+ IEmailTemplate template = CMS.getEmailTemplate(mFormPath);
+
+ /*
+ * parse and process the template
+ */
+ if (template != null) {
+ if (!template.init()) {
+ return;
+ }
+
+ buildContentParams(crlentries, mEmail);
+ IEmailFormProcessor et = CMS.getEmailFormProcessor();
+ String c = et.getEmailContent(template.toString(), mContentParams);
+
+ if (template.isHTML()) {
+ mn.setContentType("text/html");
+ }
+ mn.setContent(c);
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_TEMPLATE_ERROR",
+ crlentries[0].getSerialNumber().toString(), mReqId.toString()));
+
+ mn.setContent("Serial Number = " +
+ crlentries[0].getSerialNumber() +
+ "; Request ID = " + mReqId);
+ }
+
+ try {
+ mn.sendNotification();
+ } catch (ENotificationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+ }
+
+ private void buildContentParams(RevokedCertImpl crlentries[], String mEmail) {
+ mContentParams.put(IEmailFormProcessor.TOKEN_ID,
+ mConfig.getName());
+ mContentParams.put(IEmailFormProcessor.TOKEN_SERIAL_NUM,
+ crlentries[0].getSerialNumber().toString());
+ mContentParams.put(IEmailFormProcessor.TOKEN_HEX_SERIAL_NUM,
+ Long.toHexString(crlentries[0].getSerialNumber().longValue()));
+ mContentParams.put(IEmailFormProcessor.TOKEN_REQUEST_ID,
+ mReqId.toString());
+ mContentParams.put(IEmailFormProcessor.TOKEN_HTTP_HOST,
+ mHttpHost);
+ mContentParams.put(IEmailFormProcessor.TOKEN_HTTP_PORT,
+ mHttpPort);
+
+ try {
+ RevokedCertImpl revCert = crlentries[0];
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ ICertificateRepository certDB = ca.getCertificateRepository();
+ X509Certificate cert = certDB.getX509Certificate(revCert.getSerialNumber());
+
+ mContentParams.put(IEmailFormProcessor.TOKEN_ISSUER_DN,
+ cert.getIssuerDN().toString());
+ mContentParams.put(IEmailFormProcessor.TOKEN_SUBJECT_DN,
+ cert.getSubjectDN().toString());
+ Date date = crlentries[0].getRevocationDate();
+
+ mContentParams.put(IEmailFormProcessor.TOKEN_REVOCATION_DATE,
+ mDateFormat.format(date));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_CERT_ISSUED_SET_RESOLVER", e.toString()));
+ }
+
+ mContentParams.put(IEmailFormProcessor.TOKEN_SENDER_EMAIL,
+ mSenderEmail);
+ mContentParams.put(IEmailFormProcessor.TOKEN_RECIPIENT_EMAIL,
+ mEmail);
+ // ... and more
+ }
+
+ /**
+ * sets the configurable parameters
+ */
+ public void set(String name, String val) {
+ if (name.equalsIgnoreCase(PROP_ENABLED)) {
+ if (val.equalsIgnoreCase("true")) {
+ mEnabled = true;
+ } else {
+ mEnabled = false;
+ }
+ } else if (name.equalsIgnoreCase(PROP_SENDER_EMAIL)) {
+ mSenderEmail = val;
+ } else if (name.equalsIgnoreCase(PROP_EMAIL_SUBJECT)) {
+ mSubject_Success = val;
+ mSubject = mSubject_Success;
+ } else if (name.equalsIgnoreCase(PROP_EMAIL_TEMPLATE)) {
+ mFormPath = val;
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LISTENERS_CERT_ISSUED_SET"));
+ }
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/listeners/PinRemovalListener.java b/base/server/cms/src/com/netscape/cms/listeners/PinRemovalListener.java
new file mode 100644
index 000000000..21d69e29d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/listeners/PinRemovalListener.java
@@ -0,0 +1,171 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.listeners;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestListener;
+
+/**
+ * This represnets a listener that removes pin from LDAP directory.
+ *
+ * @version $Revision$, $Date$
+ */
+public class PinRemovalListener implements IRequestListener {
+ protected static final String PROP_ENABLED = "enabled";
+ protected static final String PROP_LDAP = "ldap";
+ protected static final String PROP_BASEDN = "ldap.basedn";
+ protected static final String PROP_PINATTR = "pinAttr";
+
+ protected String mName = null;
+ protected String mImplName = null;
+ protected String mBaseDN = null;
+ protected String mPinAttr = null;
+
+ private boolean mEnabled = false;
+ private ILogger mLogger = CMS.getLogger();
+
+ private IConfigStore mConfig = null;
+ private IConfigStore mLdapConfig = null;
+ private ILdapConnFactory mConnFactory = null;
+ private LDAPConnection mRemovePinLdapConnection = null;
+
+ public PinRemovalListener() {
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public String getImplName() {
+ return mImplName;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void shutdown() {
+ }
+
+ protected String[] configParams = { "a" };
+
+ public String[] getConfigParams()
+ throws EBaseException {
+
+ return configParams;
+ }
+
+ public void init(ISubsystem sub, IConfigStore config) throws EBaseException {
+ init(null, null, config);
+ }
+
+ public void init(String name, String ImplName, IConfigStore config)
+ throws EBaseException {
+ mName = name;
+ mImplName = ImplName;
+ mConfig = config;
+
+ mLdapConfig = mConfig.getSubStore(PROP_LDAP);
+ mConnFactory = CMS.getLdapBoundConnFactory();
+ mConnFactory.init(mLdapConfig);
+ mRemovePinLdapConnection = mConnFactory.getConn();
+
+ mEnabled = mConfig.getBoolean(PROP_ENABLED, false);
+ mBaseDN = mConfig.getString(PROP_BASEDN, "");
+ mPinAttr = mConfig.getString(PROP_PINATTR, "pin");
+
+ }
+
+ public void accept(IRequest r) {
+ if (mEnabled != true)
+ return;
+
+ String rs = r.getRequestStatus().toString();
+
+ CMS.debug("PinRemovalListener: Request status: " + rs);
+ if (!rs.equals("complete")) {
+ CMS.debug("PinRemovalListener: - request not complete - not removing pin");
+ return;
+ }
+ String requestType = r.getRequestType();
+
+ if (requestType.equals(IRequest.ENROLLMENT_REQUEST) ||
+ requestType.equals(IRequest.RENEWAL_REQUEST)) {
+
+ String uid = r.getExtDataInString(
+ IRequest.HTTP_PARAMS, "uid");
+
+ if (uid == null) {
+ log(ILogger.LL_INFO, "did not find UID parameter in this request");
+ return;
+ }
+
+ String userdn = null;
+
+ try {
+ LDAPSearchResults res = mRemovePinLdapConnection.search(mBaseDN,
+ LDAPv2.SCOPE_SUB, "(uid=" + uid + ")", null, false);
+
+ if (!res.hasMoreElements()) {
+ log(ILogger.LL_SECURITY, "uid " + uid + " does not exist in the ldap " +
+ " server. Could not remove pin");
+ return;
+ }
+
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+
+ userdn = entry.getDN();
+
+ mRemovePinLdapConnection.modify(userdn,
+ new LDAPModification(
+ LDAPModification.DELETE,
+ new LDAPAttribute(mPinAttr)));
+
+ log(ILogger.LL_INFO, "Removed pin for user \"" + userdn + "\"");
+
+ } catch (LDAPException e) {
+ log(ILogger.LL_SECURITY, "could not remove pin for " + userdn);
+ }
+
+ }
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, "PinRemovalListener: " + msg);
+ }
+
+ public void set(String name, String val) {
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/listeners/RequestInQListener.java b/base/server/cms/src/com/netscape/cms/listeners/RequestInQListener.java
new file mode 100644
index 000000000..f1f396ca3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/listeners/RequestInQListener.java
@@ -0,0 +1,277 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.listeners;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.listeners.EListenersException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.notification.ENotificationException;
+import com.netscape.certsrv.notification.IEmailFormProcessor;
+import com.netscape.certsrv.notification.IEmailTemplate;
+import com.netscape.certsrv.notification.IMailNotification;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestListener;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.cms.profile.input.SubjectNameInput;
+import com.netscape.cms.profile.input.SubmitterInfoInput;
+
+/**
+ * a listener for every request gets into the request queue.
+ * <p>
+ * Here is a list of available $TOKENs for email notification templates:
+ * <UL>
+ * <LI>$RequestorEmail
+ * <LI>$CertType
+ * <LI>$RequestType
+ * <LI>$RequestId
+ * <LI>$HttpHost
+ * <LI>$HttpPort
+ * <LI>$SenderEmail
+ * <LI>$RecipientEmail
+ * </UL>
+ *
+ */
+public class RequestInQListener implements IRequestListener {
+ protected static final String PROP_ENABLED = "enabled";
+ protected final static String PROP_SENDER_EMAIL = "senderEmail";
+ protected final static String PROP_RECVR_EMAIL = "recipientEmail";
+ public final static String PROP_EMAIL_TEMPLATE = "emailTemplate";
+ protected static final String PROP_EMAIL_SUBJECT = "emailSubject";
+
+ protected final static String PROP_NOTIFY_SUBSTORE = "notification";
+ protected final static String PROP_REQ_IN_Q_SUBSTORE = "requestInQ";
+
+ private boolean mEnabled = false;
+ private ILogger mLogger = CMS.getLogger();
+ private String mSenderEmail = null;
+ private String mRecipientEmail = null;
+ private String mEmailSubject = null;
+ private String mFormPath = null;
+ private IConfigStore mConfig = null;
+ private Hashtable<String, Object> mContentParams = new Hashtable<String, Object>();
+ private String mId = "RequestInQListener";
+ private ICertAuthority mSubsystem = null;
+ private String mHttpHost = null;
+ private String mAgentPort = null;
+
+ /**
+ * Constructor
+ */
+ public RequestInQListener() {
+ }
+
+ /**
+ * initializes the listener from the configuration
+ */
+ public void init(ISubsystem sub, IConfigStore config)
+ throws EListenersException, EPropertyNotFound, EBaseException {
+
+ mSubsystem = (ICertAuthority) sub;
+ mConfig = mSubsystem.getConfigStore();
+
+ IConfigStore nc = mConfig.getSubStore(PROP_NOTIFY_SUBSTORE);
+ IConfigStore rq = nc.getSubStore(PROP_REQ_IN_Q_SUBSTORE);
+
+ mEnabled = rq.getBoolean(PROP_ENABLED, false);
+
+ mSenderEmail = rq.getString(PROP_SENDER_EMAIL);
+ if (mSenderEmail == null) {
+ throw new EListenersException(CMS.getLogMessage("NO_NOTIFY_SENDER_EMAIL_CONFIG_FOUND"));
+ }
+ mRecipientEmail = rq.getString(PROP_RECVR_EMAIL);
+ if (mRecipientEmail == null) {
+ throw new EListenersException(CMS.getLogMessage("NO_NOTIFY_RECVR_EMAIL_CONFIG_FOUND"));
+ }
+
+ mEmailSubject = rq.getString(PROP_EMAIL_SUBJECT);
+ if (mEmailSubject == null) {
+ mEmailSubject = "Request in Queue";
+ }
+
+ mFormPath = rq.getString(PROP_EMAIL_TEMPLATE);
+
+ // make available http host and port for forming url in templates
+ mHttpHost = CMS.getAgentHost();
+ mAgentPort = CMS.getAgentPort();
+ if (mAgentPort == null)
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LISTENERS_REQUEST_PORT_NOT_FOUND"));
+ else
+ CMS.debug("RequestInQuListener: agentport = " + mAgentPort);
+
+ // register for this event listener
+ mSubsystem.registerPendingListener(this);
+ }
+
+ /**
+ * carries out the operation when the listener is triggered.
+ *
+ * @param r IRequest structure holding the request information
+ * @see com.netscape.certsrv.request.IRequest
+ */
+ public void accept(IRequest r) {
+
+ if (mEnabled != true)
+ return;
+
+ // regardless of type of request...notify for everything
+ // no need for email resolver here...
+ IMailNotification mn = CMS.getMailNotification();
+
+ mn.setFrom(mSenderEmail);
+ mn.setTo(mRecipientEmail);
+ mn.setSubject(mEmailSubject + " (request id: " +
+ r.getRequestId() + ")");
+
+ /*
+ * get form file from disk
+ */
+ IEmailTemplate template = CMS.getEmailTemplate(mFormPath);
+
+ /*
+ * parse and process the template
+ */
+ if (template != null) {
+ if (!template.init()) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LISTENERS_TEMPLATE_NOT_INIT"));
+ return;
+ }
+
+ buildContentParams(r);
+ IEmailFormProcessor et = CMS.getEmailFormProcessor();
+ String c = et.getEmailContent(template.toString(), mContentParams);
+
+ if (template.isHTML()) {
+ mn.setContentType("text/html");
+ }
+ mn.setContent(c);
+ } else {
+ // log and mail
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_TEMPLATE_NOT_GET"));
+ mn.setContent("Template not retrievable for Request in Queue notification");
+ }
+
+ try {
+ mn.sendNotification();
+ } catch (ENotificationException e) {
+ // already logged, lets audit
+ mLogger.log(ILogger.EV_AUDIT, null,
+ ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_SEND_FAILED", e.toString()));
+
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LISTENERS_SEND_FAILED", e.toString()));
+ }
+ }
+
+ private void buildContentParams(IRequest r) {
+ mContentParams.clear();
+ mContentParams.put(IEmailFormProcessor.TOKEN_ID,
+ mConfig.getName());
+ Object val = null;
+
+ String profileId = r.getExtDataInString("profileId");
+
+ if (profileId == null) {
+ val = r.getExtDataInString(IRequest.HTTP_PARAMS, "csrRequestorEmail");
+ } else {
+ // use the submitter info if available, otherwise, use the
+ // subject name input email
+ val = r.getExtDataInString(SubmitterInfoInput.EMAIL);
+
+ if ((val == null) || (((String) val).compareTo("") == 0)) {
+ val = r.getExtDataInString(SubjectNameInput.VAL_EMAIL);
+ }
+ }
+ if (val != null)
+ mContentParams.put(IEmailFormProcessor.TOKEN_REQUESTOR_EMAIL,
+ val);
+
+ if (profileId == null) {
+ val = r.getExtDataInString(IRequest.HTTP_PARAMS, IRequest.CERT_TYPE);
+ } else {
+ val = profileId;
+ }
+ if (val != null) {
+ mContentParams.put(IEmailFormProcessor.TOKEN_CERT_TYPE,
+ val);
+ }
+
+ RequestId reqId = r.getRequestId();
+
+ mContentParams.put(IEmailFormProcessor.TOKEN_REQUEST_ID, reqId.toString());
+
+ mContentParams.put(IEmailFormProcessor.TOKEN_ID, mId);
+
+ val = r.getRequestType();
+ if (val != null)
+ mContentParams.put(IEmailFormProcessor.TOKEN_REQUEST_TYPE, val);
+
+ mContentParams.put(IEmailFormProcessor.TOKEN_HTTP_HOST, mHttpHost);
+ mContentParams.put(IEmailFormProcessor.TOKEN_HTTP_PORT, mAgentPort);
+
+ mContentParams.put(IEmailFormProcessor.TOKEN_SENDER_EMAIL, mSenderEmail);
+ mContentParams.put(IEmailFormProcessor.TOKEN_RECIPIENT_EMAIL, mRecipientEmail);
+ }
+
+ /**
+ * sets the configurable parameters
+ *
+ * @param name a String represents the name of the configuration parameter to be set
+ * @param val a String containing the value to be set for name
+ */
+ public void set(String name, String val) {
+ if (name.equalsIgnoreCase(PROP_ENABLED)) {
+ if (val.equalsIgnoreCase("true")) {
+ mEnabled = true;
+ } else {
+ mEnabled = false;
+ }
+ } else if (name.equalsIgnoreCase(PROP_SENDER_EMAIL)) {
+ mSenderEmail = val;
+ } else if (name.equalsIgnoreCase(PROP_RECVR_EMAIL)) {
+ mRecipientEmail = val;
+ } else if (name.equalsIgnoreCase(PROP_EMAIL_SUBJECT)) {
+ mEmailSubject = val;
+ } else if (name.equalsIgnoreCase(PROP_EMAIL_TEMPLATE)) {
+ mFormPath = val;
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LISTENERS_CERT_ISSUED_SET"));
+ }
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/logging/LogEntry.java b/base/server/cms/src/com/netscape/cms/logging/LogEntry.java
new file mode 100644
index 000000000..ac8d16f54
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/logging/LogEntry.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.logging;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Vector;
+
+/**
+ * A log entry of LogFile
+ *
+ * @version $Revision$, $Date$
+ */
+public class LogEntry {
+ private String mEntry;
+ private String mLevel;
+ private String mSource;
+ private String mDetail;
+ private String mDate;
+ private String mTime;
+ private Vector<String> mRow;
+
+ private final String DATE_PATTERN = "dd/MMM/yyyy:HH:mm:ss z";
+
+ /**
+ * Constructor for a LogEntry.
+ *
+ */
+ public LogEntry(String entry) throws ParseException {
+ mEntry = entry;
+ mRow = parse();
+ }
+
+ /**
+ * parse a log entry
+ *
+ * return a vector of the segments of the entry
+ */
+
+ public Vector<String> parse() throws ParseException {
+ int x = mEntry.indexOf("[");
+
+ if (x == -1)
+ throw new ParseException(mEntry, 0);
+ String temp = mEntry.substring(x + 1);
+
+ x = temp.indexOf("]");
+ if (x == -1)
+ throw new ParseException(mEntry, 0);
+
+ String dateStr = temp.substring(0, x);
+ SimpleDateFormat format = new SimpleDateFormat(DATE_PATTERN);
+ Date date = format.parse(dateStr);
+
+ mDate = DateFormat.getDateInstance().format(date);
+ mTime = DateFormat.getTimeInstance().format(date);
+
+ temp = temp.substring(x + 2);
+ x = temp.indexOf("]");
+ if (x == -1)
+ throw new ParseException(mEntry, 0);
+ mSource = temp.substring(1, x);
+
+ temp = temp.substring(x + 2);
+ x = temp.indexOf("]");
+ if (x == -1)
+ throw new ParseException(mEntry, 0);
+ mLevel = temp.substring(1, x);
+
+ mDetail = temp.substring(x + 2);
+
+ Vector<String> row = new Vector<String>();
+
+ row.addElement(mSource);
+ row.addElement(mLevel);
+ row.addElement(mDate);
+ row.addElement(mTime);
+ row.addElement(mDetail);
+
+ //System.out.println(mSource +"," + mLevel +","+ mDate+","+mTime+","+mDetail);
+ return row;
+
+ }
+
+ public String getSource() {
+ return mSource;
+ }
+
+ public String getLevel() {
+ return mLevel;
+ }
+
+ public String getDetail() {
+ return mDetail;
+ }
+
+ public String getDate() {
+ return mDate;
+ }
+
+ public String getTime() {
+ return mTime;
+ }
+
+ public Vector<String> getRow() {
+ return mRow;
+ }
+
+ public String getEntry() {
+ return mEntry;
+ }
+
+ public void appendDetail(String msg) {
+ mDetail = mDetail + "\n" + msg;
+ mEntry = mEntry + "\n" + msg;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/logging/LogFile.java b/base/server/cms/src/com/netscape/cms/logging/LogFile.java
new file mode 100644
index 000000000..c465a4e53
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/logging/LogFile.java
@@ -0,0 +1,1546 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.logging;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
+import java.io.CharArrayReader;
+import java.io.CharArrayWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.RandomAccessFile;
+import java.io.UnsupportedEncodingException;
+import java.security.GeneralSecurityException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.servlet.ServletException;
+
+import org.apache.commons.lang.StringUtils;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.ObjectNotFoundException;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.util.Base64OutputStream;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.AuditEvent;
+import com.netscape.certsrv.logging.ConsoleError;
+import com.netscape.certsrv.logging.ELogException;
+import com.netscape.certsrv.logging.ILogEvent;
+import com.netscape.certsrv.logging.ILogEventListener;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.SignedAuditEvent;
+import com.netscape.certsrv.logging.SystemEvent;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * A log event listener which write logs to log files
+ *
+ * @version $Revision$, $Date$
+ **/
+public class LogFile implements ILogEventListener, IExtendedPluginInfo {
+ public static final String PROP_TYPE = "type";
+ public static final String PROP_REGISTER = "register";
+ public static final String PROP_ON = "enable";
+ public static final String PROP_TRACE = "trace";
+ public static final String PROP_SIGNED_AUDIT_LOG_SIGNING = "logSigning";
+ public static final String PROP_SIGNED_AUDIT_CERT_NICKNAME =
+ "signedAuditCertNickname";
+ public static final String PROP_SIGNED_AUDIT_SELECTED_EVENTS = "events";
+ public static final String PROP_SIGNED_AUDIT_UNSELECTED_EVENTS = "unselected.events";
+ public static final String PROP_SIGNED_AUDIT_MANDATORY_EVENTS = "mandatory.events";
+ public static final String PROP_LEVEL = "level";
+ static final String PROP_FILE_NAME = "fileName";
+ static final String PROP_LAST_HASH_FILE_NAME = "lastHashFileName";
+ static final String PROP_BUFFER_SIZE = "bufferSize";
+ static final String PROP_FLUSH_INTERVAL = "flushInterval";
+
+ private final static String LOGGING_SIGNED_AUDIT_AUDIT_LOG_STARTUP =
+ "LOGGING_SIGNED_AUDIT_AUDIT_LOG_STARTUP_2";
+ private final static String LOGGING_SIGNED_AUDIT_SIGNING =
+ "LOGGING_SIGNED_AUDIT_SIGNING_3";
+ private final static String LOGGING_SIGNED_AUDIT_AUDIT_LOG_SHUTDOWN =
+ "LOGGING_SIGNED_AUDIT_AUDIT_LOG_SHUTDOWN_2";
+ private final static String LOG_SIGNED_AUDIT_EXCEPTION =
+ "LOG_SIGNED_AUDIT_EXCEPTION_1";
+
+ protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+ protected IConfigStore mConfig = null;
+
+ /**
+ * The date string used in the log file name
+ */
+ static final String DATE_PATTERN = "yyyyMMddHHmmss";
+
+ //It may be interesting to make this flexable someday....
+ protected SimpleDateFormat mLogFileDateFormat = new SimpleDateFormat(DATE_PATTERN);
+
+ /**
+ * The default output stream buffer size in bytes
+ */
+ static final int BUFFER_SIZE = 512;
+
+ /**
+ * The default output flush interval in seconds
+ */
+ static final int FLUSH_INTERVAL = 5;
+
+ /**
+ * The log file
+ */
+ protected File mFile = null;
+
+ /**
+ * The log file name
+ */
+ protected String mFileName = null;
+
+ /**
+ * The log file output stream
+ */
+ protected BufferedWriter mLogWriter = null;
+
+ /**
+ * The log date entry format pattern
+ */
+ protected String mDatePattern = "dd/MMM/yyyy:HH:mm:ss z";
+
+ /**
+ * The log date entry format
+ */
+ protected SimpleDateFormat mLogDateFormat = new SimpleDateFormat(mDatePattern);
+
+ /**
+ * The date object used for log entries
+ */
+ protected Date mDate = new Date();
+
+ /**
+ * The number of bytes written to the current log file
+ */
+ protected int mBytesWritten = 0;
+
+ /**
+ * The output buffer size in bytes
+ */
+ protected int mBufferSize = BUFFER_SIZE;
+
+ /**
+ * The output buffer flush interval
+ */
+ protected int mFlushInterval = FLUSH_INTERVAL;
+
+ /**
+ * The number of unflushed bytes
+ */
+ protected int mBytesUnflushed = 0;
+
+ /**
+ * The output buffer flush interval thread
+ */
+ private Thread mFlushThread = null;
+
+ /**
+ * The mandatory log event types
+ */
+ protected Set<String> mandatoryEvents = new LinkedHashSet<String>();
+
+ /**
+ * The selected log event types
+ */
+ protected Set<String> selectedEvents = new LinkedHashSet<String>();
+
+ /**
+ * The unselected log event types
+ */
+ protected Set<String> unselectedEvents = new LinkedHashSet<String>();
+
+ /**
+ * The eventType that this log is triggered
+ */
+ protected String mType = null;
+
+ /**
+ * The log is turned on/off
+ */
+ protected boolean mOn = false;
+
+ /**
+ * Should this log listener self-register or not
+ */
+ protected boolean mRegister = false;
+
+ protected boolean mTrace = false;
+
+ /**
+ * Log signing is on/off
+ */
+ protected boolean mLogSigning = false;
+
+ /**
+ * Nickname of certificate to use to sign log.
+ */
+ private String mSAuditCertNickName = "";
+
+ /**
+ * The provider used by the KeyGenerator and Mac
+ */
+ static final String CRYPTO_PROVIDER = "Mozilla-JSS";
+
+ /**
+ * The log level threshold
+ * Only logs with level greater or equal than this value will be written
+ */
+ protected long mLevel = 1;
+
+ /**
+ * Constructor for a LogFile.
+ *
+ */
+ public LogFile() {
+ }
+
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+
+ try {
+ mOn = config.getBoolean(PROP_ON, true);
+ } catch (EBaseException e) {
+ throw new ELogException(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED",
+ config.getName() + "." + PROP_ON));
+ }
+
+ try {
+ mLogSigning = config.getBoolean(PROP_SIGNED_AUDIT_LOG_SIGNING,
+ false);
+ } catch (EBaseException e) {
+ throw new ELogException(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED",
+ config.getName() + "." + PROP_SIGNED_AUDIT_LOG_SIGNING));
+ }
+
+ if (mOn && mLogSigning) {
+ try {
+ mSAuditCertNickName = config.getString(
+ PROP_SIGNED_AUDIT_CERT_NICKNAME);
+ CMS.debug("LogFile: init(): audit log signing enabled. signedAuditCertNickname=" + mSAuditCertNickName);
+ } catch (EBaseException e) {
+ throw new ELogException(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED",
+ config.getName() + "."
+ + PROP_SIGNED_AUDIT_CERT_NICKNAME));
+ }
+ if (mSAuditCertNickName == null ||
+ mSAuditCertNickName.trim().equals("")) {
+ throw new ELogException(CMS.getUserMessage(
+ "CMS_BASE_GET_PROPERTY_FAILED",
+ config.getName() + "."
+ + PROP_SIGNED_AUDIT_CERT_NICKNAME));
+ }
+ }
+
+ // mandatory events
+ String mandatoryEventsList = config.getString(PROP_SIGNED_AUDIT_MANDATORY_EVENTS, "");
+ for (String event : StringUtils.split(mandatoryEventsList, ", ")) {
+ mandatoryEvents.add(event);
+ }
+
+ // selected events
+ String selectedEventsList = config.getString(PROP_SIGNED_AUDIT_SELECTED_EVENTS, "");
+ for (String event : StringUtils.split(selectedEventsList, ", ")) {
+ selectedEvents.add(event);
+ }
+
+ // unselected events
+ String unselectedEventsList = config.getString(PROP_SIGNED_AUDIT_UNSELECTED_EVENTS, "");
+ for (String event : StringUtils.split(unselectedEventsList, ", ")) {
+ unselectedEvents.add(event);
+ }
+
+ try {
+ init(config);
+ } catch (IOException e) {
+ throw new ELogException(CMS.getUserMessage("CMS_LOG_UNEXPECTED_EXCEPTION", e.toString()));
+ }
+ }
+
+ /**
+ * add the event to the selected events list
+ *
+ * @param event to be selected
+ */
+ public void selectEvent(String event) {
+ selectedEvents.add(event);
+ unselectedEvents.remove(event);
+ }
+
+ /**
+ * remove the event from the selected events list
+ *
+ * @param event to be de-selected
+ */
+ public void deselectEvent(String event) {
+ selectedEvents.remove(event);
+ unselectedEvents.add(event);
+ }
+
+ /**
+ * replace the selected events list
+ *
+ * @param events comma-separated event list
+ */
+ public void replaceEvents(String events) {
+ // unselect all events
+ unselectedEvents.addAll(selectedEvents);
+ selectedEvents.clear();
+
+ // select specified events
+ for (String event : StringUtils.split(events, ", ")) {
+ selectEvent(event);
+ }
+ }
+
+ public static String base64Encode(byte[] bytes) throws IOException {
+ // All this streaming is lame, but Base64OutputStream needs a
+ // PrintStream
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ try (Base64OutputStream b64 = new Base64OutputStream(
+ new PrintStream(new FilterOutputStream(output)))) {
+ b64.write(bytes);
+ b64.flush();
+
+ // This is internationally safe because Base64 chars are
+ // contained within 8859_1
+ return output.toString("8859_1");
+ }
+ }
+
+ private static boolean mInSignedAuditLogFailureMode = false;
+
+ private static synchronized void shutdownCMS() {
+ if (mInSignedAuditLogFailureMode == false) {
+
+ // Set signed audit log failure mode true
+ // No, this isn't a race condition, because the method is
+ // synchronized. We just want to avoid an infinite loop.
+ mInSignedAuditLogFailureMode = true;
+
+ // Block all new incoming requests
+ if (CMS.areRequestsDisabled() == false) {
+ // XXX is this a race condition?
+ CMS.disableRequests();
+ }
+
+ // Terminate all requests in process
+ CMS.terminateRequests();
+
+ // Call graceful shutdown of the CMS server
+ // Call force shutdown to get added functionality of
+ // making sure to kill the web server.
+
+ CMS.forceShutdown();
+ }
+ }
+
+ /**
+ * Initialize and open the log using the parameters from a config store
+ *
+ * @param config The property config store to find values in
+ */
+ public void init(IConfigStore config) throws IOException,
+ EBaseException {
+ String fileName = null;
+ String defaultFileName = null;
+ String signedAuditDefaultFileName = "";
+
+ mConfig = config;
+
+ try {
+ mTrace = config.getBoolean(PROP_TRACE, false);
+ } catch (EBaseException e) {
+ throw new ELogException(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED",
+ config.getName() + "." + PROP_TRACE));
+ }
+
+ try {
+ mType = config.getString(PROP_TYPE, "system");
+ } catch (EBaseException e) {
+ throw new ELogException(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED",
+ config.getName() + "." + PROP_TYPE));
+ }
+
+ try {
+ mRegister = config.getBoolean(PROP_REGISTER, true);
+ } catch (EBaseException e) {
+ throw new ELogException(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED",
+ config.getName() + "." + PROP_REGISTER));
+ }
+
+ if (mOn) {
+ if (mRegister) {
+ CMS.getLogger().getLogQueue().addLogEventListener(this);
+ }
+ } else {
+ // shutdown the listener, remove the listener
+ if (mRegister) {
+ CMS.getLogger().getLogQueue().removeLogEventListener(this);
+ shutdown();
+ }
+ }
+
+ try {
+ mLevel = config.getInteger(PROP_LEVEL, 3);
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ throw new ELogException(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED",
+ config.getName() + "." + PROP_LEVEL));
+ }
+
+ try {
+ // retrieve the subsystem
+ String subsystem = "";
+
+ ISubsystem caSubsystem = CMS.getSubsystem("ca");
+ if (caSubsystem != null) {
+ subsystem = "ca";
+ }
+
+ ISubsystem raSubsystem = CMS.getSubsystem("ra");
+ if (raSubsystem != null) {
+ subsystem = "ra";
+ }
+
+ ISubsystem kraSubsystem = CMS.getSubsystem("kra");
+ if (kraSubsystem != null) {
+ subsystem = "kra";
+ }
+
+ ISubsystem ocspSubsystem = CMS.getSubsystem("ocsp");
+ if (ocspSubsystem != null) {
+ subsystem = "ocsp";
+ }
+
+ // retrieve the instance name
+ String instIDPath = CMS.getInstanceDir();
+ int index = instIDPath.lastIndexOf("/");
+ String instID = instIDPath.substring(index + 1);
+
+ // build the default signedAudit file name
+ signedAuditDefaultFileName = subsystem + "_"
+ + instID + "_" + "audit";
+
+ } catch (Exception e2) {
+ throw new ELogException(
+ CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED",
+ config.getName() + "." +
+ PROP_FILE_NAME));
+ }
+
+ // the default value is determined by the eventType.
+ if (mType.equals(ILogger.PROP_SIGNED_AUDIT)) {
+ defaultFileName = "logs/signedAudit/" + signedAuditDefaultFileName;
+ } else if (mType.equals(ILogger.PROP_SYSTEM)) {
+ defaultFileName = "logs/system";
+ } else if (mType.equals(ILogger.PROP_AUDIT)) {
+ defaultFileName = "logs/transactions";
+ } else {
+ //wont get here
+ throw new ELogException(CMS.getUserMessage("CMS_LOG_INVALID_LOG_TYPE",
+ config.getName()));
+ }
+
+ try {
+ fileName = config.getString(PROP_FILE_NAME, defaultFileName);
+ } catch (EBaseException e) {
+ throw new ELogException(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED",
+ config.getName() + "." + PROP_FILE_NAME));
+ }
+
+ if (mOn) {
+ init(fileName, config.getInteger(PROP_BUFFER_SIZE, BUFFER_SIZE),
+ config.getInteger(PROP_FLUSH_INTERVAL, FLUSH_INTERVAL));
+ }
+ }
+
+ /**
+ * Initialize and open the log
+ *
+ * @param bufferSize The buffer size for the output stream in bytes
+ * @param flushInterval The interval in seconds to flush the log
+ */
+ public void init(String fileName, int bufferSize, int flushInterval) throws IOException, ELogException {
+
+ if (fileName == null)
+ throw new ELogException(CMS.getUserMessage("CMS_LOG_INVALID_FILE_NAME", "null"));
+
+ //If we want to reuse the old log files
+ //mFileName = fileName + "." + mLogFileDateFormat.format(mDate);
+ mFileName = fileName;
+ if (!Utils.isNT()) {
+ // Always insure that a physical file exists!
+ Utils.exec("touch " + mFileName);
+ Utils.exec("chmod 00640 " + mFileName);
+ }
+ mFile = new File(mFileName);
+ mBufferSize = bufferSize;
+ setFlushInterval(flushInterval);
+ open();
+ }
+
+ private PrivateKey mSigningKey = null;
+ private Signature mSignature = null;
+
+ private void setupSigning() throws EBaseException {
+ try {
+
+ Provider[] providers = java.security.Security.getProviders();
+ int ps = providers.length;
+ for (int i = 0; i < ps; i++) {
+ CMS.debug("LogFile: provider " + i + "= " + providers[i].getName());
+ }
+
+ CryptoManager cm = CryptoManager.getInstance();
+
+ // find CertServer's private key
+ X509Certificate cert = cm.findCertByNickname(mSAuditCertNickName);
+ if (cert != null) {
+ CMS.debug("LogFile: setupSignig(): found cert:" + mSAuditCertNickName);
+ } else {
+ CMS.debug("LogFile: setupSignig(): cert not found:" + mSAuditCertNickName);
+ }
+ mSigningKey = cm.findPrivKeyByCert(cert);
+
+ String sigAlgorithm;
+ if (mSigningKey instanceof RSAPrivateKey) {
+ sigAlgorithm = "SHA-256/RSA";
+ } else if (mSigningKey instanceof DSAPrivateKey) {
+ sigAlgorithm = "SHA-256/DSA";
+ } else {
+ throw new NoSuchAlgorithmException("Unknown private key type");
+ }
+
+ CryptoToken savedToken = cm.getThreadToken();
+ try {
+ CryptoToken keyToken =
+ ((org.mozilla.jss.pkcs11.PK11PrivKey) mSigningKey)
+ .getOwningToken();
+ cm.setThreadToken(keyToken);
+ mSignature = java.security.Signature.getInstance(sigAlgorithm,
+ CRYPTO_PROVIDER);
+ } finally {
+ cm.setThreadToken(savedToken);
+ }
+
+ mSignature.initSign(mSigningKey);
+
+ // get the last signature from the currently-opened file
+ String entry = getLastSignature(mFile);
+ if (entry != null) {
+ mSignature.update(entry.getBytes("UTF-8"));
+ mSignature.update(LINE_SEP_BYTE);
+ }
+
+ // Always start off with a signature. That way, even if there
+ // were problems with the log file we inherited, we will
+ // get a fresh start with this instance.
+ pushSignature();
+
+ } catch (CryptoManager.NotInitializedException nie) {
+ setupSigningFailure("BASE_CRYPTOMANAGER_UNINITIALIZED", nie);
+ } catch (ObjectNotFoundException onfe) {
+ setupSigningFailure("LOG_SIGNING_CERT_NOT_FOUND", onfe);
+ } catch (TokenException te) {
+ setupSigningFailure("BASE_TOKEN_ERROR_0", te);
+ } catch (NoSuchAlgorithmException nsae) {
+ setupSigningFailure("LOG_NO_SUCH_ALGORITHM_0", nsae);
+ } catch (NoSuchProviderException nspe) {
+ setupSigningFailure("BASE_PROVIDER_NOT_SUPPORTED", nspe);
+ } catch (InvalidKeyException ike) {
+ setupSigningFailure("BASE_INVALID_KEY", ike);
+ } catch (SignatureException se) {
+ setupSigningFailure("LOG_SIGNING_OP_FAILED", se);
+ } catch (UnsupportedEncodingException uee) {
+ setupSigningFailure("LOG_UNEXPECTED_EXCEPTION", uee);
+ } catch (IOException ioe) {
+ setupSigningFailure("LOG_UNEXPECTED_EXCEPTION", ioe);
+ } catch (Exception e) {
+ setupSigningFailure("LOG_UNEXPECTED_EXCEPTION", e);
+ }
+ }
+
+ private static void setupSigningFailure(String logMessageCode, Exception e)
+ throws EBaseException {
+ try {
+ ConsoleError.send(new SystemEvent(
+ CMS.getLogMessage(logMessageCode)));
+ } catch (Exception e2) {
+ // don't allow an exception while printing to the console
+ // prevent us from running the rest of this function.
+ e2.printStackTrace();
+ }
+ e.printStackTrace();
+ shutdownCMS();
+ throw new EBaseException(e.toString());
+ }
+
+ /**
+ * Startup the instance
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_AUDIT_LOG_STARTUP used at audit function startup
+ * </ul>
+ *
+ * @exception EBaseException if an internal error occurred
+ */
+ public void startup() throws EBaseException {
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ CMS.debug("LogFile: entering LogFile.startup()");
+ if (mOn && mLogSigning) {
+ try {
+ setupSigning();
+ audit(CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUDIT_LOG_STARTUP,
+ ILogger.SYSTEM_UID,
+ ILogger.SUCCESS));
+ } catch (EBaseException e) {
+ audit(CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUDIT_LOG_STARTUP,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE));
+ throw e;
+ }
+ }
+
+ }
+
+ /**
+ * Retrieves the eventType this log is triggered.
+ */
+ public String getType() {
+ return mType;
+ }
+
+ /**
+ * Retrieves the log on/off.
+ */
+ public String getOn() {
+ return String.valueOf(mOn);
+ }
+
+ /**
+ * Retrieves the log level threshold.
+ */
+ public long getLevel() {
+ return mLevel;
+ }
+
+ /**
+ * Retrieves the base log file name.
+ */
+ public String getName() {
+ return mFileName;
+ }
+
+ /**
+ * Record that the signed audit log has been signed
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_SIGNING used when a signature on the audit log is generated (same as
+ * "flush" time)
+ * </ul>
+ *
+ * @exception IOException for input/output problems
+ * @exception ELogException when plugin implementation fails
+ * @exception SignatureException when signing fails
+ * @exception InvalidKeyException when an invalid key is utilized
+ */
+ private void pushSignature() throws IOException, ELogException,
+ SignatureException, InvalidKeyException {
+ byte[] sigBytes = null;
+
+ if (mSignature == null) {
+ return;
+ }
+
+ sigBytes = mSignature.sign();
+ mSignature.initSign(mSigningKey);
+
+ Object o[] = new Object[1];
+ o[0] = null;
+
+ // cook up a signed audit log message to record mac
+ // so as to avoid infinite recursiveness of calling
+ // the log() method
+ String auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SIGNING,
+ ILogger.SYSTEM_UID,
+ ILogger.SUCCESS,
+ base64Encode(sigBytes));
+
+ if (mSignedAuditLogger == null) {
+ return;
+ }
+
+ ILogEvent ev = mSignedAuditLogger.create(
+ ILogger.EV_SIGNED_AUDIT,
+ (Properties) null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ auditMessage,
+ o,
+ ILogger.L_SINGLELINE);
+
+ String logMesg = logEvt2String(ev);
+ doLog(logMesg, true);
+ }
+
+ private static String getLastSignature(File f) throws IOException {
+ BufferedReader r = new BufferedReader(new FileReader(f));
+ String lastSig = null;
+ String curLine = null;
+ while ((curLine = r.readLine()) != null) {
+ if (curLine.indexOf("AUDIT_LOG_SIGNING") != -1) {
+ lastSig = curLine;
+ }
+ }
+ r.close();
+ return lastSig;
+ }
+
+ /**
+ * Open the log file. This creates the buffered FileWriter
+ *
+ */
+ protected synchronized void open() throws IOException {
+ RandomAccessFile out;
+
+ try {
+ out = new RandomAccessFile(mFile, "rw");
+ out.seek(out.length());
+ //XXX int or long?
+ mBytesWritten = (int) out.length();
+ if (!Utils.isNT()) {
+ try {
+ Utils.exec("chmod 00640 " + mFile.getCanonicalPath());
+ } catch (IOException e) {
+ CMS.debug("Unable to change file permissions on "
+ + mFile.toString());
+ }
+ }
+ mLogWriter = new BufferedWriter(
+ new FileWriter(out.getFD()), mBufferSize);
+
+ // The first time we open, mSignature will not have been
+ // initialized yet. That's ok, we will push our first signature
+ // in setupSigning().
+ if (mLogSigning && (mSignature != null)) {
+ try {
+ pushSignature();
+ } catch (ELogException le) {
+ ConsoleError.send(
+ new SystemEvent(CMS.getUserMessage("CMS_LOG_ILLEGALARGUMENT",
+ mFileName)));
+ }
+ }
+ } catch (IllegalArgumentException iae) {
+ ConsoleError.send(
+ new SystemEvent(CMS.getUserMessage("CMS_LOG_ILLEGALARGUMENT",
+ mFileName)));
+ } catch (GeneralSecurityException gse) {
+ // error with signed audit log, shutdown CMS
+ gse.printStackTrace();
+ shutdownCMS();
+ }
+
+ mBytesUnflushed = 0;
+ }
+
+ /**
+ * Flush the log file. Also update the MAC for hash protected logs
+ *
+ */
+ public synchronized void flush() {
+ try {
+ if (mLogSigning) {
+ try {
+ pushSignature();
+ } catch (ELogException le) {
+ ConsoleError.send(new SystemEvent(CMS.getUserMessage("CMS_LOG_FLUSH_LOG_FAILED", mFileName,
+ le.toString())));
+ }
+ }
+
+ if (mLogWriter != null) {
+ mLogWriter.flush();
+ }
+ } catch (IOException e) {
+ ConsoleError.send(new SystemEvent(CMS.getUserMessage("CMS_LOG_FLUSH_LOG_FAILED", mFileName, e.toString())));
+ if (mLogSigning) {
+ //error in writing to signed audit log, shut down CMS
+ e.printStackTrace();
+ shutdownCMS();
+ }
+ } catch (GeneralSecurityException gse) {
+ // error with signed audit log, shutdown CMS
+ gse.printStackTrace();
+ shutdownCMS();
+ }
+
+ mBytesUnflushed = 0;
+ }
+
+ /**
+ * Close the log file
+ *
+ */
+ protected synchronized void close() {
+ try {
+ flush();
+ if (mLogWriter != null) {
+ mLogWriter.close();
+ }
+ } catch (IOException e) {
+ ConsoleError.send(new SystemEvent(CMS.getUserMessage("CMS_LOG_CLOSE_FAILED", mFileName, e.toString())));
+ }
+ mLogWriter = null;
+ }
+
+ /**
+ * Shutdown this log file.
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_AUDIT_LOG_SHUTDOWN used at audit function shutdown
+ * </ul>
+ */
+ public synchronized void shutdown() {
+ String auditMessage = null;
+
+ CMS.debug("LogFile:In log shutdown");
+
+ setFlushInterval(0);
+
+ // log signed audit shutdown success
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUDIT_LOG_SHUTDOWN,
+ ILogger.SYSTEM_UID,
+ ILogger.SUCCESS);
+
+ audit(auditMessage);
+
+ close();
+ }
+
+ /**
+ * Set the flush interval
+ * <P>
+ *
+ * @param flushInterval The amount of time in seconds until the log
+ * is flush. A value of 0 will disable autoflush. This will also set
+ * the update period for hash protected logs.
+ **/
+ public synchronized void setFlushInterval(int flushInterval) {
+ mFlushInterval = flushInterval * 1000;
+
+ if ((mFlushThread == null) && (mFlushInterval > 0)) {
+ mFlushThread = new FlushThread();
+ mFlushThread.setDaemon(true);
+ mFlushThread.start();
+ }
+
+ this.notify();
+ }
+
+ /**
+ * Log flush thread. Sleep for the flush interval and flush the
+ * log. Changing flush interval to 0 will cause this thread to exit.
+ */
+ final class FlushThread extends Thread {
+
+ /**
+ * Flush thread constructor including thread name
+ */
+ public FlushThread() {
+ super();
+ super.setName(mFileName + ".flush-" + (Thread.activeCount() + 1));
+ }
+
+ public void run() {
+ while (mFlushInterval > 0) {
+ // Sleep for the interval and then flush the log
+ synchronized (LogFile.this) {
+ try {
+ LogFile.this.wait(mFlushInterval);
+ } catch (InterruptedException e) {
+ // This shouldn't happen very often
+ ConsoleError.send(new
+ SystemEvent(CMS.getUserMessage("CMS_LOG_THREAD_INTERRUPT", "flush")));
+ }
+ }
+
+ if (mFlushInterval == 0) {
+ break;
+ }
+
+ if (mBytesUnflushed > 0) {
+ flush();
+ }
+ }
+ mFlushThread = null;
+ }
+ }
+
+ /**
+ * Synchronized method to write a string to the log file. All I18N
+ * should take place before this call.
+ *
+ * @param entry The log entry string
+ */
+ protected synchronized void log(String entry) throws ELogException {
+ doLog(entry, false);
+ }
+
+ // Standard line separator byte. We always sign this line separator,
+ // regardless of what we actually write to the file, so that signature
+ // verification is platform-independent.
+ private static final byte LINE_SEP_BYTE = 0x0a;
+
+ /**
+ * This method actually does the logging, and is not overridden
+ * by subclasses, so you can call it and know that it will do exactly
+ * what you see below.
+ */
+ private synchronized void doLog(String entry, boolean noFlush)
+ throws ELogException {
+ if (mLogWriter == null) {
+ String[] params = { mFileName, entry };
+
+ throw new ELogException(CMS.getUserMessage("CMS_LOG_LOGFILE_CLOSED", params));
+ } else {
+ try {
+ mLogWriter.write(entry, 0/*offset*/, entry.length());
+
+ if (mLogSigning == true) {
+ if (mSignature != null) {
+ // include newline for calculating MAC
+ mSignature.update(entry.getBytes("UTF-8"));
+ } else {
+ CMS.debug("LogFile: mSignature is not yet ready... null in log()");
+ }
+ }
+ if (mTrace) {
+ CharArrayWriter cw = new CharArrayWriter(200);
+ PrintWriter pw = new PrintWriter(cw);
+ Exception e = new Exception();
+ e.printStackTrace(pw);
+ char[] c = cw.toCharArray();
+ cw.close();
+ pw.close();
+
+ CharArrayReader cr = new CharArrayReader(c);
+ LineNumberReader lr = new LineNumberReader(cr);
+
+ String text = null;
+ String method = null;
+ String fileAndLine = null;
+ if (lr.ready()) {
+ text = lr.readLine();
+ do {
+ text = lr.readLine();
+ } while (text.indexOf("logging") != -1);
+ int p = text.indexOf("(");
+ fileAndLine = text.substring(p);
+
+ String classandmethod = text.substring(0, p);
+ int q = classandmethod.lastIndexOf(".");
+ method = classandmethod.substring(q + 1);
+ mLogWriter.write(fileAndLine, 0/*offset*/, fileAndLine.length());
+ mLogWriter.write(" ", 0/*offset*/, " ".length());
+ mLogWriter.write(method, 0/*offset*/, method.length());
+ }
+ }
+ mLogWriter.newLine();
+
+ if (mLogSigning == true) {
+ if (mSignature != null) {
+ mSignature.update(LINE_SEP_BYTE);
+ } else {
+ CMS.debug("LogFile: mSignature is null in log() 2");
+ }
+ }
+ } catch (IOException e) {
+ ConsoleError.send(new SystemEvent(CMS.getUserMessage("CMS_LOG_WRITE_FAILED", mFileName, entry,
+ e.toString())));
+ if (mLogSigning) {
+ // Failed to write to audit log, shut down CMS
+ e.printStackTrace();
+ shutdownCMS();
+ }
+ } catch (IllegalStateException e) {
+ CMS.debug("LogFile: exception thrown in log(): " + e.toString());
+ ConsoleError.send(new SignedAuditEvent(CMS.getLogMessage(LOG_SIGNED_AUDIT_EXCEPTION, e.toString())));
+ } catch (GeneralSecurityException gse) {
+ // DJN: handle error
+ CMS.debug("LogFile: exception thrown in log(): "
+ + gse.toString());
+ gse.printStackTrace();
+ ConsoleError.send(new SignedAuditEvent(CMS.getLogMessage(
+ LOG_SIGNED_AUDIT_EXCEPTION, gse.toString())));
+ }
+
+ // XXX
+ // Although length will be in Unicode dual-bytes, the PrintWriter
+ // will only print out 1 byte per character. I suppose this could
+ // be dependent on the encoding of your log file, but it ain't that
+ // smart yet. Also, add one for the newline. (hmm, on NT, CR+LF)
+ int nBytes = entry.length() + 1;
+
+ mBytesWritten += nBytes;
+ mBytesUnflushed += nBytes;
+
+ if (mBufferSize > 0 && mBytesUnflushed > mBufferSize && !noFlush) {
+ flush();
+ }
+ }
+ }
+
+ /**
+ * Write an event to the log file
+ *
+ * @param ev The event to be logged.
+ */
+ public void log(ILogEvent ev) throws ELogException {
+ if (ev instanceof AuditEvent) {
+ if (!mType.equals("transaction") || (!mOn) || mLevel > ev.getLevel()) {
+ return;
+ }
+ } else if (ev instanceof SystemEvent) {
+ if (!mType.equals("system") || (!mOn) || mLevel > ev.getLevel()) {
+ return;
+ }
+ } else if (ev instanceof SignedAuditEvent) {
+ if (!mType.equals("signedAudit") || (!mOn) || mLevel > ev.getLevel()) {
+ return;
+ }
+ }
+
+ // If no selection specified in configuration, then all are selected
+ if (selectedEvents.isEmpty()) {
+ String entry = logEvt2String(ev);
+ log(entry);
+ return;
+ }
+
+ // If no type specified in propertity file, then treated as selected
+ String type = ev.getEventType();
+ if (type == null) {
+ String entry = logEvt2String(ev);
+ log(entry);
+ return;
+ }
+
+ // Is the event type mandatory or selected?
+ if (mandatoryEvents.contains(type) || selectedEvents.contains(type)) {
+ String entry = logEvt2String(ev);
+ log(entry);
+ return;
+ }
+
+ CMS.debug("LogFile: event type not selected: " + type);
+ }
+
+ public String logEvt2String(ILogEvent ev) {
+ String entry = null;
+
+ // Hmm.. multiple threads could hit this and reset the time.
+ // Do we care?
+ mDate.setTime(ev.getTimeStamp());
+
+ // XXX
+ // This should follow the Common Log Format which still needs
+ // some work.
+ if (ev.getMultiline() == ILogger.L_MULTILINE) {
+ entry = CMS.getPID() + "." + Thread.currentThread().getName() + " - ["
+ + mLogDateFormat.format(mDate) + "] [" +
+ Integer.toString(ev.getSource()) + "] [" + Integer.toString(ev.getLevel())
+ + "] " + prepareMultiline(ev.toString());
+ } else {
+ entry = CMS.getPID() + "." + Thread.currentThread().getName() + " - ["
+ + mLogDateFormat.format(mDate) + "] [" +
+ Integer.toString(ev.getSource()) + "] [" + Integer.toString(ev.getLevel())
+ + "] " + ev.toString();
+ }
+
+ return entry;
+ }
+
+ /**
+ * change multi-line log entry by replace "\n" with "\n "
+ *
+ * @param original The original multi-line log entry.
+ */
+ private String prepareMultiline(String original) {
+ int i, last = 0;
+
+ //NT: \r\n, unix: \n
+ while ((i = original.indexOf("\n", last)) != -1) {
+ last = i + 1;
+ original = original.substring(0, i + 1) + " " + original.substring(i + 1);
+ }
+ return original;
+ }
+
+ /**
+ * Read all entries whose logLevel>=lowLevel && log source = source
+ * to at most maxLine entries(from end)
+ * If the parameter is -1, it's ignored and return all entries
+ *
+ * @param maxLine The maximum lines to be returned
+ * @param lowLevel The lowest log level to be returned
+ * @param source The particular log source to be returned
+ * @param fName The log file name to be read. If it's null, read the current
+ * log file
+ */
+ public Vector<LogEntry> readEntry(int maxLine, int lowLevel, int source, String fName) {
+ Vector<LogEntry> mEntries = new Vector<LogEntry>();
+ String fileName = mFileName;
+ BufferedReader fBuffer;
+ int lineNo = 0; // lineNo of the current entry in the log file
+ int line = 0; // line of readed valid entries
+ String firstLine = null; // line buffer
+ String nextLine = null;
+ String entry = null;
+ LogEntry logEntry = null;
+
+ /*
+ this variable is added to accormodate misplaced multiline entries
+ write out buffered log entry when next entry is parsed successfully
+ this implementation is assuming parsing is more time consuming than
+ condition check
+ */
+ LogEntry preLogEntry = null;
+
+ if (fName != null) {
+ fileName = fName;
+ }
+ try {
+ //XXX think about this
+ fBuffer = new BufferedReader(new FileReader(fileName));
+ do {
+ try {
+ nextLine = fBuffer.readLine();
+ if (nextLine != null) {
+ if ((nextLine.length() == 0) || (nextLine.charAt(0) == ' ')) {
+ // It's a continuous line
+ entry = null;
+ if (nextLine.length() > 1)
+ firstLine = firstLine + "\n" + nextLine.substring(1);
+ else
+ firstLine = firstLine + "\n";
+
+ } else {
+ // It's a new entry
+ entry = firstLine;
+ firstLine = nextLine;
+ }
+ // parse the previous entry, the current one is buffered
+ if (entry != null) {
+ try {
+ logEntry = new LogEntry(entry);
+ // if parse succeed, write out previous entry
+ if (preLogEntry != null) {
+ if ((Integer.parseInt(preLogEntry.getLevel()) >= lowLevel) &&
+ ((Integer.parseInt(preLogEntry.getSource()) == source) ||
+ (source == ILogger.S_ALL)
+ )) {
+ mEntries.addElement(preLogEntry);
+ if (maxLine == -1) {
+ line++;
+ } else if (line < maxLine) {
+ line++;
+ } else {
+ mEntries.removeElementAt(0);
+ }
+ }
+ }
+ preLogEntry = logEntry;
+ } catch (ParseException e) {
+ if (preLogEntry != null) {
+ preLogEntry.appendDetail(entry);
+ } else {
+ firstLine = firstLine + "\n" + nextLine;
+ }
+ entry = null;
+ logEntry = null;
+ }
+ }
+ }
+ lineNo++;
+
+ } catch (IOException e) {
+ CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE,
+ CMS.getLogMessage("LOGGING_READ_ERROR", fileName,
+ Integer.toString(lineNo)));
+ }
+
+ } while (nextLine != null);
+
+ // need to process the last 2 entries of the file
+ if (firstLine != null) {
+ if (logEntry != null) {
+ preLogEntry = logEntry;
+ }
+ entry = firstLine;
+ try {
+ logEntry = new LogEntry(entry);
+
+ /* System.out.println(
+ Integer.toString(Integer.parseInt(logEntry.getLevel()))
+ +","+Integer.toString(lowLevel)+","+
+ Integer.toString(Integer.parseInt(logEntry.getSource()))
+ +","+Integer.toString(source) );
+ */
+ if (preLogEntry != null) {
+ if ((Integer.parseInt(preLogEntry.getLevel()) >= lowLevel) &&
+ ((Integer.parseInt(preLogEntry.getSource()) == source) ||
+ (source == ILogger.S_ALL)
+ )) {
+ mEntries.addElement(preLogEntry);
+ if (maxLine == -1) {
+ line++;
+ } else if (line < maxLine) {
+ line++;
+ } else {
+ mEntries.removeElementAt(0);
+ }
+ }
+ }
+ preLogEntry = logEntry;
+ } catch (ParseException e) {
+ preLogEntry.appendDetail(entry);
+ }
+
+ if (preLogEntry != null) {
+ if ((Integer.parseInt(preLogEntry.getLevel()) >= lowLevel)
+ &&
+ ((Integer.parseInt(preLogEntry.getSource()) == source)
+ ||
+ (source == ILogger.S_ALL)
+ )) {
+ // parse the entry, pass to UI
+ mEntries.addElement(preLogEntry);
+ if (maxLine == -1) {
+ line++;
+ } else if (line < maxLine) {
+ line++;
+ } else {
+ mEntries.removeElementAt(0);
+ }
+ }
+ }
+
+ }// end: last entry
+
+ try {
+ fBuffer.close();
+ } catch (IOException e) {
+ CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE, "logging:" + fileName +
+ " failed to close for reading");
+ }
+
+ } catch (FileNotFoundException e) {
+ CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE,
+ CMS.getLogMessage("LOGGING_FILE_NOT_FOUND",
+ fileName));
+ }
+ return mEntries;
+ }
+
+ /**
+ * Retrieves the configuration store of this subsystem.
+ * <P>
+ *
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Retrieve last "maxLine" number of system log with log lever >"level"
+ * and from source "source". If the parameter is omitted. All entries
+ * are sent back.
+ */
+ public synchronized NameValuePairs retrieveLogContent(Hashtable<String, String> req) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ String tmp, fName = null;
+ int maxLine = -1, level = -1, source = -1;
+ Vector<LogEntry> entries = null;
+
+ if ((tmp = req.get(Constants.PR_LOG_ENTRY)) != null) {
+ maxLine = Integer.parseInt(tmp);
+ }
+ if ((tmp = req.get(Constants.PR_LOG_LEVEL)) != null) {
+ level = Integer.parseInt(tmp);
+ }
+ if ((tmp = req.get(Constants.PR_LOG_SOURCE)) != null) {
+ source = Integer.parseInt(tmp);
+ }
+ tmp = req.get(Constants.PR_LOG_NAME);
+ if (!(tmp.equals(Constants.PR_CURRENT_LOG))) {
+ fName = tmp;
+ } else {
+ flush();
+ }
+
+ try {
+ entries = readEntry(maxLine, level, source, fName);
+ for (int i = 0; i < entries.size(); i++) {
+ params.put(Integer.toString(i) +
+ entries.elementAt(i).getEntry(), "");
+ }
+ } catch (Exception e) {
+ CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_WARN,
+ "System log parse error");
+ }
+ return params;
+ }
+
+ /**
+ * Retrieve log file list.
+ */
+ public synchronized NameValuePairs retrieveLogList(Hashtable<String, String> req) throws ServletException,
+ IOException, EBaseException {
+ return null;
+ }
+
+ public String getImplName() {
+ return "LogFile";
+ }
+
+ public String getDescription() {
+ return "LogFile";
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(PROP_TYPE + "=");
+ v.addElement(PROP_ON + "=");
+ v.addElement(PROP_LEVEL + "=");
+ v.addElement(PROP_FILE_NAME + "=");
+ v.addElement(PROP_BUFFER_SIZE + "=");
+ v.addElement(PROP_FLUSH_INTERVAL + "=");
+
+ // needs to find a way to determine what type you want. if this
+ // is not for the signed audit type, then we should not show the
+ // following parameters.
+ //if( mType.equals( ILogger.PROP_SIGNED_AUDIT ) ) {
+ v.addElement(PROP_SIGNED_AUDIT_LOG_SIGNING + "=");
+ v.addElement(PROP_SIGNED_AUDIT_CERT_NICKNAME + "=");
+ v.addElement(PROP_SIGNED_AUDIT_MANDATORY_EVENTS + "=");
+ v.addElement(PROP_SIGNED_AUDIT_SELECTED_EVENTS + "=");
+ v.addElement(PROP_SIGNED_AUDIT_UNSELECTED_EVENTS + "=");
+ //}
+
+ return v;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ try {
+
+ if (mType == null) {
+ v.addElement(PROP_TYPE + "=");
+ } else {
+ v.addElement(PROP_TYPE + "=" +
+ mConfig.getString(PROP_TYPE));
+ }
+ v.addElement(PROP_ON + "=" + String.valueOf(mOn));
+ if (mLevel == 0)
+ v.addElement(PROP_LEVEL + "=" + ILogger.LL_DEBUG_STRING);
+ else if (mLevel == 1)
+ v.addElement(PROP_LEVEL + "=" + ILogger.LL_INFO_STRING);
+ else if (mLevel == 2)
+ v.addElement(PROP_LEVEL + "=" + ILogger.LL_WARN_STRING);
+ else if (mLevel == 3)
+ v.addElement(PROP_LEVEL + "=" + ILogger.LL_FAILURE_STRING);
+ else if (mLevel == 4)
+ v.addElement(PROP_LEVEL + "=" + ILogger.LL_MISCONF_STRING);
+ else if (mLevel == 5)
+ v.addElement(PROP_LEVEL + "=" + ILogger.LL_CATASTRPHE_STRING);
+ else if (mLevel == 6)
+ v.addElement(PROP_LEVEL + "=" + ILogger.LL_SECURITY_STRING);
+
+ if (mFileName == null) {
+ v.addElement(PROP_FILE_NAME + "=");
+ } else {
+ v.addElement(PROP_FILE_NAME + "=" +
+ mFileName);
+ }
+ v.addElement(PROP_BUFFER_SIZE + "=" + mBufferSize);
+ v.addElement(PROP_FLUSH_INTERVAL + "=" + mFlushInterval / 1000);
+
+ if ((mType != null) && mType.equals(ILogger.PROP_SIGNED_AUDIT)) {
+ v.addElement(PROP_SIGNED_AUDIT_LOG_SIGNING + "="
+ + String.valueOf(mLogSigning));
+
+ if (mSAuditCertNickName == null) {
+ v.addElement(PROP_SIGNED_AUDIT_CERT_NICKNAME + "=");
+ } else {
+ v.addElement(PROP_SIGNED_AUDIT_CERT_NICKNAME + "="
+ + mSAuditCertNickName);
+ }
+
+ v.addElement(PROP_SIGNED_AUDIT_MANDATORY_EVENTS + "=" + StringUtils.join(mandatoryEvents, ","));
+ v.addElement(PROP_SIGNED_AUDIT_SELECTED_EVENTS + "=" + StringUtils.join(selectedEvents, ","));
+ v.addElement(PROP_SIGNED_AUDIT_UNSELECTED_EVENTS + "=" + StringUtils.join(unselectedEvents, ","));
+ }
+ } catch (Exception e) {
+ }
+ return v;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ if (mType.equals(ILogger.PROP_SIGNED_AUDIT)) {
+ String[] params = {
+ PROP_TYPE
+ + ";choice(transaction,signedAudit,system);The log event type this instance is listening to",
+ PROP_ON + ";boolean;Turn on the listener",
+ PROP_LEVEL + ";choice(" + ILogger.LL_DEBUG_STRING + "," +
+ ILogger.LL_INFO_STRING + "," +
+ ILogger.LL_WARN_STRING + "," +
+ ILogger.LL_FAILURE_STRING + "," +
+ ILogger.LL_MISCONF_STRING + "," +
+ ILogger.LL_CATASTRPHE_STRING + "," +
+ ILogger.LL_SECURITY_STRING
+ + ");Only log message with level higher than this filter will be written by this listener",
+ PROP_FILE_NAME + ";string;The name of the file the log is written to",
+ PROP_BUFFER_SIZE + ";integer;The size of the buffer to receive log messages in kilobytes(KB)",
+ PROP_FLUSH_INTERVAL
+ + ";integer;The maximum time in seconds before the buffer is flushed to the file",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-logrules-logfile",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Write the log messages to a file",
+ PROP_SIGNED_AUDIT_LOG_SIGNING +
+ ";boolean;Enable audit logs to be signed",
+ PROP_SIGNED_AUDIT_CERT_NICKNAME +
+ ";string;The nickname of the certificate to be used to sign audit logs",
+ PROP_SIGNED_AUDIT_MANDATORY_EVENTS +
+ ";string;A comma-separated list of strings used to specify mandatory signed audit log events",
+ PROP_SIGNED_AUDIT_SELECTED_EVENTS +
+ ";string;A comma-separated list of strings used to specify selected signed audit log events",
+ PROP_SIGNED_AUDIT_UNSELECTED_EVENTS +
+ ";string;A comma-separated list of strings used to specify unselected signed audit log events",
+ };
+
+ return params;
+ } else {
+ // mType.equals( ILogger.PROP_AUDIT ) ||
+ // mType.equals( ILogger.PROP_SYSTEM )
+ String[] params = {
+ PROP_TYPE
+ + ";choice(transaction,signedAudit,system);The log event type this instance is listening to",
+ PROP_ON + ";boolean;Turn on the listener",
+ PROP_LEVEL + ";choice(" + ILogger.LL_DEBUG_STRING + "," +
+ ILogger.LL_INFO_STRING + "," +
+ ILogger.LL_WARN_STRING + "," +
+ ILogger.LL_FAILURE_STRING + "," +
+ ILogger.LL_MISCONF_STRING + "," +
+ ILogger.LL_CATASTRPHE_STRING + "," +
+ ILogger.LL_SECURITY_STRING
+ + ");Only log message with level higher than this filter will be written by this listener",
+ PROP_FILE_NAME + ";string;The name of the file the log is written to",
+ PROP_BUFFER_SIZE + ";integer;The size of the buffer to receive log messages in kilobytes(KB)",
+ PROP_FLUSH_INTERVAL
+ + ";integer;The maximum time in seconds before the buffer is flushed to the file",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-logrules-logfile",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Write the log messages to a file"
+ };
+
+ return params;
+ }
+ }
+
+ /**
+ * Signed Audit Log
+ *
+ * This method is inherited by all classes that extend this "LogFile"
+ * class, and is called to store messages to the signed audit log.
+ * <P>
+ *
+ * @param msg signed audit log message
+ */
+ protected void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+
+ if (mSignedAuditLogger == null) {
+ return;
+ }
+
+ mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/logging/RollingLogFile.java b/base/server/cms/src/com/netscape/cms/logging/RollingLogFile.java
new file mode 100644
index 000000000..0a7a9f098
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/logging/RollingLogFile.java
@@ -0,0 +1,650 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.logging;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.ConsoleError;
+import com.netscape.certsrv.logging.ELogException;
+import com.netscape.certsrv.logging.ILogEvent;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.SystemEvent;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * A rotating log file for Certificate log events. This class loosely follows
+ * the Netscape Common Log API implementing rollover interval, size and file
+ * naming conventions. It does not yet implement Disk Usage.
+ *
+ * @version $Revision$, $Date$
+ */
+public class RollingLogFile extends LogFile {
+ public static final String PROP_MAX_FILE_SIZE = "maxFileSize";
+ public static final String PROP_ROLLOVER_INTERVAL = "rolloverInterval";
+ public static final String PROP_EXPIRATION_TIME = "expirationTime";
+
+ /**
+ * The default max file size in bytes
+ */
+ static final int MAX_FILE_SIZE = 100;
+
+ /**
+ * The default rollover interval in seconds
+ */
+ static final String ROLLOVER_INTERVAL = "2592000";
+
+ /**
+ * The default expiration time in seconds
+ */
+ static final String EXPIRATION_TIME = "2592000";
+
+ /**
+ * The maximum file size in bytes
+ */
+ protected int mMaxFileSize = 0;
+
+ /**
+ * The amount of time in miniseconds between log rotations
+ */
+ protected long mRolloverInterval = 0;
+
+ /**
+ * The thread responsible for rotating the log
+ */
+ private Thread mRolloverThread = null;
+
+ /**
+ * The amount of time before a backed up log is removed in milliseconds
+ */
+ protected long mExpirationTime = 0;
+
+ /**
+ * The thread responsible for removing expired log files
+ */
+ private Thread mExpirationThread = null;
+
+ /**
+ * The object used as a lock for expiration thread synchronization
+ */
+ private Object mExpLock = new Object();
+
+ private final static String LOGGING_SIGNED_AUDIT_LOG_DELETE =
+ "LOGGING_SIGNED_AUDIT_LOG_DELETE_3";
+
+ /**
+ * Construct a RollingLogFile
+ */
+ public RollingLogFile() {
+ }
+
+ /**
+ * Initialize and open a RollingLogFile using the prop config store
+ *
+ * @param config The property config store to find values in
+ */
+ public void init(IConfigStore config) throws IOException,
+ EBaseException {
+ super.init(config);
+
+ rl_init(config.getInteger(PROP_MAX_FILE_SIZE, MAX_FILE_SIZE),
+ config.getString(PROP_ROLLOVER_INTERVAL, ROLLOVER_INTERVAL),
+ config.getString(PROP_EXPIRATION_TIME, EXPIRATION_TIME));
+ }
+
+ /**
+ * Convenience routine to initialized the RollingLogFile specific
+ * attributes.
+ */
+ protected void rl_init(int maxFileSize, String rolloverInterval,
+ String expirationTime) {
+ mMaxFileSize = maxFileSize * 1024;
+ setRolloverTime(rolloverInterval);
+ setExpirationTime(expirationTime);
+ }
+
+ public void startup() throws EBaseException {
+ super.startup();
+ }
+
+ /**
+ * Shutdown this log file.
+ */
+ public synchronized void shutdown() {
+ setRolloverTime("0");
+ setExpirationTime("0");
+ super.shutdown();
+ }
+
+ /**
+ * Set the rollover interval
+ *
+ * @param rolloverSeconds The amount of time in seconds until the log
+ * is rotated. A value of 0 will disable log rollover.
+ **/
+ public synchronized void setRolloverTime(String rolloverSeconds) {
+ mRolloverInterval = Long.valueOf(rolloverSeconds).longValue() * 1000;
+
+ if ((mRolloverThread == null) && (mRolloverInterval > 0)) {
+ mRolloverThread = new RolloverThread();
+ mRolloverThread.setDaemon(true);
+ mRolloverThread.start();
+ }
+
+ this.notify();
+ }
+
+ /**
+ * Get the rollover interval
+ *
+ * @return The interval in seconds in which the log is rotated
+ **/
+ public synchronized int getRolloverTime() {
+ return (int) (mRolloverInterval / 1000);
+ }
+
+ /**
+ * Set the file expiration time
+ *
+ * @param expirationSeconds The amount of time in seconds until log files
+ * are deleted
+ **/
+ public void setExpirationTime(String expirationSeconds) {
+
+ // Need to completely protect changes to mExpiration time
+ // and make sure they only happen while the thread is sleeping
+ synchronized (mExpLock) {
+ mExpirationTime = Long.valueOf(expirationSeconds).longValue() * 1000;
+
+ if (mExpirationThread == null) {
+ if (mExpirationTime > 0) {
+ mExpirationThread = new ExpirationThread();
+ mExpirationThread.setDaemon(true);
+ mExpirationThread.start();
+ }
+ } else {
+ mExpLock.notify();
+ }
+ }
+ }
+
+ /**
+ * Get the expiration time
+ *
+ * @return The age in seconds in which log files are delete
+ **/
+ public int getExpirationTime() {
+ return (int) (mExpirationTime / 1000);
+ }
+
+ /**
+ * Rotate the log file to a backup file with timestamp
+ **/
+ public synchronized void rotate()
+ throws IOException {
+
+ File backupFile = new File(mFileName + "." + mLogFileDateFormat.format(mDate));
+
+ // close, backup, and reopen the log file zeroizing its contents
+ super.close();
+ try {
+ if (Utils.isNT()) {
+ // NT is very picky on the path
+ Utils.exec("copy " +
+ mFile.getCanonicalPath().replace('/', '\\') +
+ " " +
+ backupFile.getCanonicalPath().replace('/',
+ '\\'));
+ } else {
+ // Create a copy of the original file which
+ // preserves the original file permissions.
+ Utils.exec("cp -p " + mFile.getCanonicalPath() + " " +
+ backupFile.getCanonicalPath());
+ }
+
+ // Zeroize the original file if and only if
+ // the backup copy was successful.
+ if (backupFile.exists()) {
+
+ // Make certain that the backup file has
+ // the correct permissions.
+ if (!Utils.isNT()) {
+ Utils.exec("chmod 00640 " + backupFile.getCanonicalPath());
+ }
+
+ try {
+ // Open and close the original file
+ // to zeroize its contents.
+ PrintWriter pw = new PrintWriter(mFile);
+ pw.close();
+
+ // Make certain that the original file retains
+ // the correct permissions.
+ if (!Utils.isNT()) {
+ Utils.exec("chmod 00640 " + mFile.getCanonicalPath());
+ }
+ } catch (FileNotFoundException e) {
+ CMS.debug("Unable to zeroize "
+ + mFile.toString());
+ }
+ } else {
+ CMS.debug("Unable to backup "
+ + mFile.toString() + " to "
+ + backupFile.toString());
+ }
+ } catch (Exception e) {
+ CMS.debug("Unable to backup "
+ + mFile.toString() + " to "
+ + backupFile.toString());
+ }
+ super.open(); // will reset mBytesWritten
+ }
+
+ /**
+ * Remove any log files which have not been modified in the specified
+ * time
+ * <P>
+ *
+ * NOTE: automatic removal of log files is currently NOT supported!
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_LOG_DELETE used AFTER audit log expires (authorization should not allow,
+ * but in case authorization gets compromised make sure it is written AFTER the log expiration happens)
+ * </ul>
+ *
+ * @param expirationSeconds The number of seconds since the expired files
+ * have been modified.
+ * @return the time in milliseconds when the next file expires
+ **/
+ public long expire(long expirationSeconds) throws ELogException {
+ String auditMessage = null;
+
+ if (expirationSeconds <= 0)
+ throw new ELogException(CMS.getUserMessage("CMS_LOG_EXPIRATION_TIME_ZERO"));
+
+ long expirationTime = expirationSeconds * 1000;
+ long currentTime = System.currentTimeMillis();
+ long oldestFile = currentTime;
+
+ String dirName = mFile.getParent();
+
+ if (dirName == null)
+ dirName = ".";
+ File dir = new File(dirName);
+
+ // Get just the base name, minus the .date extension
+ //int len = mFile.getName().length() - LogFile.DATE_PATTERN.length() - 1;
+ //String baseName = mFile.getName().substring(0, len);
+ String fileName = mFile.getName();
+ String baseName = null, pathName = null;
+ int index = fileName.lastIndexOf("/");
+
+ if (index != -1) { // "/" exist in fileName
+ pathName = fileName.substring(0, index);
+ baseName = fileName.substring(index + 1);
+ dirName = dirName.concat("/" + pathName);
+ } else { // "/" NOT exist in fileName
+ baseName = fileName;
+ }
+
+ fileFilter ff = new fileFilter(baseName + ".");
+ String[] filelist = dir.list(ff);
+
+ if (filelist == null) { // Crap! Something is wrong.
+ throw new ELogException(CMS.getUserMessage("CMS_LOG_DIRECTORY_LIST_FAILED",
+ dirName, ff.toString()));
+ }
+
+ // Walk through the list of files which match this log file name
+ // and delete the old ones.
+ for (int i = 0; i < filelist.length; i++) {
+ if (pathName != null) {
+ filelist[i] = pathName + "/" + filelist[i];
+ } else {
+ filelist[i] = dirName + "/" + filelist[i];
+ }
+
+ String fullname = dirName + File.separatorChar + filelist[i];
+ File file = new File(fullname);
+ long fileTime = file.lastModified();
+
+ // Java documentation on File says lastModified() should not
+ // be interpeted. The doc is wrong. See JavaSoft bug #4094538
+ if ((currentTime - fileTime) > expirationTime) {
+ file.delete();
+
+ if (file.exists()) {
+ // log failure in deleting an expired signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_DELETE,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ fullname);
+ } else {
+ // log success in deleting an expired signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_DELETE,
+ ILogger.SYSTEM_UID,
+ ILogger.SUCCESS,
+ fullname);
+ }
+
+ audit(auditMessage);
+ } else if (fileTime < oldestFile) {
+ oldestFile = fileTime;
+ }
+ }
+ return oldestFile + expirationTime;
+ }
+
+ //
+ // Rollover and Expiration threads
+ //
+ // At first glance you may think it's a waste of thread resources to have
+ // two threads for every log file, but the truth is that these threads are
+ // sleeping 99% of the time. NxN thread implementations (Solaris, NT,
+ // IRIX 6.4, Unixware, etc...) will handle these in user space.
+ //
+ // You may be able to join these into one thread, and deal with
+ // multiple wakeup times, but the code would sure look ugly, and the race
+ // conditions are numerous as is. Furthermore, this is what user space
+ // threads will do for you anyways.
+ //
+
+ /**
+ * Log rotation thread. Sleep for the rollover interval and rotate the
+ * log. Changing rollover interval to 0 will cause this thread to exit.
+ */
+ final class RolloverThread extends Thread {
+
+ /**
+ * Rollover thread constructor including thread name
+ */
+ public RolloverThread() {
+ super();
+ super.setName(mFileName + ".rollover-" + (Thread.activeCount() + 1));
+ }
+
+ public void run() {
+ while (mRolloverInterval > 0) {
+ // Sleep for the interval and then rotate the log
+ synchronized (RollingLogFile.this) {
+ try {
+ RollingLogFile.this.wait(mRolloverInterval);
+ } catch (InterruptedException e) {
+ // This shouldn't happen very often
+ CMS.getLogger().getLogQueue().log(new
+ SystemEvent(CMS.getUserMessage("CMS_LOG_THREAD_INTERRUPT", "rollover")));
+ }
+ }
+
+ if (mRolloverInterval == 0) {
+ break;
+ }
+
+ if (mBytesWritten > 0) {
+ try {
+ rotate();
+ } catch (IOException e) {
+ ConsoleError.send(new
+ SystemEvent(CMS.getUserMessage("CMS_LOG_ROTATE_LOG_FAILED", mFile.getName(),
+ e.toString())));
+ break;
+ }
+ }
+ // else
+ // Don't rotate empty logs
+ // flag in log summary file?
+ }
+ mRolloverThread = null;
+ }
+ }
+
+ /**
+ * Log expiration thread. Sleep for the expiration interval and
+ * delete any files which are too old.
+ * Changing expiration interval to 0 will cause this thread to exit.
+ */
+ final class ExpirationThread extends Thread {
+
+ /**
+ * ExpirationThread thread constructor including thread name
+ */
+ public ExpirationThread() {
+ super();
+ super.setName(mFileName + ".expiration-" + (Thread.activeCount() + 1));
+ }
+
+ public void run() {
+ synchronized (mExpLock) {
+ while (mExpirationTime > 0) {
+ long wakeupTime = 0;
+ long sleepTime = 0;
+
+ // First, remove any old log files and figure out when the
+ // next one expires
+ try {
+ wakeupTime = expire(mExpirationTime / 1000);
+ } catch (SecurityException e) {
+ ConsoleError.send(new
+ SystemEvent(CMS.getUserMessage("CMS_LOG_EXPIRE_LOG_FAILED", e.toString())));
+ break;
+ } catch (ELogException e) {
+ ConsoleError.send(new
+ SystemEvent(CMS.getUserMessage("CMS_LOG_EXPIRE_LOG_FAILED", e.toString())));
+ break;
+ }
+
+ sleepTime = wakeupTime - System.currentTimeMillis();
+ //System.out.println("wakeup " + wakeupTime);
+ //System.out.println("current "+System.currentTimeMillis());
+ //System.out.println("sleep " + sleepTime);
+ // Sleep for the interval and then check the directory
+ // Note: mExpirationTime can only change while we're
+ // sleeping
+ if (sleepTime > 0) {
+ try {
+ mExpLock.wait(sleepTime);
+ } catch (InterruptedException e) {
+ // This shouldn't happen very often
+ ConsoleError.send(new
+ SystemEvent(CMS.getUserMessage("CMS_LOG_THREAD_INTERRUPT", "expiration")));
+ }
+ }
+ }
+ }
+ mExpirationThread = null;
+ }
+ }
+
+ /**
+ * Write an event to the log file
+ *
+ * @param ev The event to be logged.
+ **/
+ public synchronized void log(ILogEvent ev) throws ELogException {
+ //xxx, Shall we log first without checking if it exceed the maximum?
+ super.log(ev); // Will increment mBytesWritten
+
+ if ((0 != mMaxFileSize) && (mBytesWritten > mMaxFileSize)) {
+ flush();
+ try {
+ rotate();
+ } catch (IOException e) {
+ throw new ELogException(CMS.getUserMessage("CMS_LOG_ROTATE_LOG_FAILED", mFile.getName(), e.toString()));
+ }
+ }
+ }
+
+ /**
+ * Retrieve log file list.
+ */
+ public synchronized NameValuePairs retrieveLogList(Hashtable<String, String> req
+ ) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ String[] files = null;
+
+ files = fileList();
+ for (int i = 0; i < files.length; i++) {
+ params.put(files[i], "");
+ }
+ return params;
+ }
+
+ /**
+ * Get the log file list in the log directory
+ *
+ * @return an array of filenames with related path to cert server root
+ */
+ protected String[] fileList() {
+ String pathName = null, baseName = null;
+
+ String dirName = mFile.getParent();
+ String fileName = mFile.getName();
+ int index = fileName.lastIndexOf("/");
+
+ if (index != -1) { // "/" exist in fileName
+ pathName = fileName.substring(0, index);
+ baseName = fileName.substring(index + 1);
+ if (dirName == null) {
+ dirName = pathName;
+ } else {
+ dirName = dirName.concat("/" + pathName);
+ }
+ } else { // "/" NOT exist in fileName
+ baseName = fileName;
+ }
+
+ File dir = new File(dirName);
+
+ fileFilter ff = new fileFilter(baseName + ".");
+ //There are some difference here. both should work
+ //error,logs,logs/error jdk115
+ //logs/system,., logs/system jdk116
+ //System.out.println(mFile.getName()+","+dirName+","+mFile.getPath()); //log/system,.
+
+ String[] filelist = dir.list(ff);
+
+ for (int i = 0; i < filelist.length; i++) {
+ if (pathName != null) {
+ filelist[i] = pathName + "/" + filelist[i];
+ } else {
+ filelist[i] = dirName + "/" + filelist[i];
+ }
+ }
+ return filelist;
+ }
+
+ public String getImplName() {
+ return "RollingLogFile";
+ }
+
+ public String getDescription() {
+ return "RollingLogFile";
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = super.getDefaultParams();
+
+ v.addElement(PROP_MAX_FILE_SIZE + "=");
+ v.addElement(PROP_ROLLOVER_INTERVAL + "=");
+ //v.addElement(PROP_EXPIRATION_TIME + "=");
+ return v;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = super.getInstanceParams();
+
+ try {
+ v.addElement(PROP_MAX_FILE_SIZE + "=" + mMaxFileSize / 1024);
+ if (mRolloverInterval / 1000 <= 60 * 60)
+ v.addElement(PROP_ROLLOVER_INTERVAL + "=" + "Hourly");
+ else if (mRolloverInterval / 1000 <= 60 * 60 * 24)
+ v.addElement(PROP_ROLLOVER_INTERVAL + "=" + "Daily");
+ else if (mRolloverInterval / 1000 <= 60 * 60 * 24 * 7)
+ v.addElement(PROP_ROLLOVER_INTERVAL + "=" + "Weekly");
+ else if (mRolloverInterval / 1000 <= 60 * 60 * 24 * 30)
+ v.addElement(PROP_ROLLOVER_INTERVAL + "=" + "Monthly");
+ else if (mRolloverInterval / 1000 <= 60 * 60 * 24 * 366)
+ v.addElement(PROP_ROLLOVER_INTERVAL + "=" + "Yearly");
+
+ //v.addElement(PROP_EXPIRATION_TIME + "=" + mExpirationTime / 1000);
+ } catch (Exception e) {
+ }
+ return v;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] p = super.getExtendedPluginInfo(locale);
+ Vector<String> info = new Vector<String>();
+
+ for (int i = 0; i < p.length; i++) {
+ if (!p[i].startsWith(IExtendedPluginInfo.HELP_TOKEN) && !p[i].startsWith(IExtendedPluginInfo.HELP_TEXT))
+ info.addElement(p[i]);
+ }
+ info.addElement(PROP_MAX_FILE_SIZE
+ + ";integer;If the current log file size if bigger than this parameter in kilobytes(KB), the file will be rotated.");
+ info.addElement(PROP_ROLLOVER_INTERVAL
+ + ";choice(Hourly,Daily,Weekly,Monthly,Yearly);The frequency of the log being rotated.");
+ info.addElement(PROP_EXPIRATION_TIME
+ + ";integer;The amount of time before a backed up log is removed in seconds");
+ info.addElement(IExtendedPluginInfo.HELP_TOKEN +
+ //";configuration-logrules-rollinglogfile");
+ ";configuration-adminbasics");
+ info.addElement(IExtendedPluginInfo.HELP_TEXT +
+ ";Write the log messages to a file which will be rotated automatically.");
+ String[] params = new String[info.size()];
+
+ info.copyInto(params);
+ return params;
+
+ }
+}
+
+/**
+ * A file filter to select the file with a given prefix
+ */
+class fileFilter implements FilenameFilter {
+ String patternToMatch = null;
+
+ public fileFilter(String pattern) {
+ patternToMatch = pattern;
+ }
+
+ public boolean accept(File dir, String name) {
+ if (name.startsWith(patternToMatch))
+ return true;
+ else
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/notification/MailNotification.java b/base/server/cms/src/com/netscape/cms/notification/MailNotification.java
new file mode 100644
index 000000000..cd4ee431c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/notification/MailNotification.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.notification;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Vector;
+
+import netscape.net.smtp.SmtpClient;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.notification.ENotificationException;
+import com.netscape.certsrv.notification.IMailNotification;
+
+/**
+ * This class handles mail notification via SMTP.
+ * This class uses <b>smtp.host</b> in the configuration for smtp
+ * host. The port default (25) is used. If no smtp specified, local
+ * host is used
+ *
+ * @version $Revision$, $Date$
+ */
+public class MailNotification implements IMailNotification {
+ private ILogger mLogger = CMS.getLogger();
+ protected final static String PROP_SMTP_SUBSTORE = "smtp";
+ protected final static String PROP_HOST = "host";
+
+ private String mHost = null;
+
+ private String mFrom = null;
+ private String mTo = null;
+ private String mSubject = null;
+ private String mContent = null;
+ private String mContentType = null;
+
+ public MailNotification() {
+ if (mHost == null) {
+ try {
+ IConfigStore mConfig =
+ CMS.getConfigStore();
+
+ IConfigStore c =
+ mConfig.getSubStore(PROP_SMTP_SUBSTORE);
+
+ if (c == null) {
+ return;
+ }
+ mHost = c.getString(PROP_HOST);
+
+ // log it
+ // if (mHost !=null) {
+ // String msg =" using external SMTP host: "+mHost;
+ // CMS.debug("MailNotification: " + msg);
+ //}
+ } catch (Exception e) {
+ // don't care
+ }
+ }
+ }
+
+ /**
+ * send one message to one or more addressees
+ */
+ public void sendNotification() throws IOException, ENotificationException {
+ // create smtp client
+ SmtpClient sc = null;
+
+ if (!mHost.equals("")) {
+ sc = new SmtpClient(mHost);
+ } else {
+ sc = new SmtpClient();
+ }
+
+ // set "from", message subject
+ if ((mFrom != null) && (!mFrom.equals("")))
+ sc.from(mFrom);
+ else {
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_NO_SMTP_SENDER"));
+ }
+
+ // set "to"
+ if ((mTo != null) && (!mTo.equals(""))) {
+ log(ILogger.LL_INFO, "mail to be sent to " + mTo);
+ sc.to(mTo);
+ } else {
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_NO_SMTP_RECEIVER"));
+ }
+
+ // set message content
+ PrintStream msgStream = sc.startMessage();
+
+ if (mContentType != null) {
+ msgStream.print("From: " + mFrom + "\n");
+ msgStream.print("MIME-Version: 1.0\n");
+ msgStream.print("To: " + mTo + "\n");
+ msgStream.print(mSubject + "\n");
+ msgStream.print(mContentType + "\n");
+ } else {
+ msgStream.print("From: " + mFrom + "\n");
+ msgStream.print("To: " + mTo + "\n");
+ msgStream.print(mSubject + "\n");
+ }
+ msgStream.print("\r\n");
+ msgStream.print(mContent + "\r\n");
+
+ // send
+ try {
+ sc.closeServer();
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_SMTP_SEND_FAILED", mTo));
+ }
+ }
+
+ /**
+ * sets the "From" field
+ *
+ * @param from email address of the sender
+ */
+ public void setFrom(String from) {
+ mFrom = from;
+ }
+
+ /**
+ * sets the "Subject" field
+ *
+ * @param subject subject of the email
+ */
+ public void setSubject(String subject) {
+ mSubject = "Subject: " + subject;
+ }
+
+ /**
+ * sets the "Content-Type" field
+ *
+ * @param contentType content type of the email
+ */
+ public void setContentType(String contentType) {
+ mContentType = "Content-Type: " + contentType;
+ }
+
+ /**
+ * sets the content of the email
+ *
+ * @param content the message content
+ */
+ public void setContent(String content) {
+ mContent = content;
+ }
+
+ /**
+ * sets the recipients' email addresses
+ *
+ * @param addresses a list of email addresses of the recipients
+ */
+ public void setTo(Vector<String> addresses) {
+ // concatenate addresses into comma separated mTo String
+
+ }
+
+ /**
+ * sets the recipient's email address
+ *
+ * @param to address of the recipient email address
+ */
+ public void setTo(String to) {
+ mTo = to;
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, "MailNotification: " + msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/ocsp/DefStore.java b/base/server/cms/src/com/netscape/cms/ocsp/DefStore.java
new file mode 100644
index 000000000..86e0c68b1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/ocsp/DefStore.java
@@ -0,0 +1,958 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.ocsp;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.cert.X509CRL;
+import java.security.cert.X509CRLEntry;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.RevokedCertificate;
+import netscape.security.x509.X509CRLImpl;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509Key;
+
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.GeneralizedTime;
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.asn1.OCTET_STRING;
+import org.mozilla.jss.pkix.cert.Extension;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSearchResults;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+import com.netscape.certsrv.dbs.repository.IRepositoryRecord;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ocsp.IDefStore;
+import com.netscape.certsrv.ocsp.IOCSPAuthority;
+import com.netscape.certsrv.util.IStatsSubsystem;
+import com.netscape.cmsutil.ocsp.BasicOCSPResponse;
+import com.netscape.cmsutil.ocsp.CertID;
+import com.netscape.cmsutil.ocsp.CertStatus;
+import com.netscape.cmsutil.ocsp.GoodInfo;
+import com.netscape.cmsutil.ocsp.OCSPRequest;
+import com.netscape.cmsutil.ocsp.OCSPResponse;
+import com.netscape.cmsutil.ocsp.OCSPResponseStatus;
+import com.netscape.cmsutil.ocsp.ResponderID;
+import com.netscape.cmsutil.ocsp.ResponseBytes;
+import com.netscape.cmsutil.ocsp.ResponseData;
+import com.netscape.cmsutil.ocsp.RevokedInfo;
+import com.netscape.cmsutil.ocsp.SingleResponse;
+import com.netscape.cmsutil.ocsp.TBSRequest;
+import com.netscape.cmsutil.ocsp.UnknownInfo;
+
+/**
+ * This is the default OCSP store that stores revocation information
+ * as certificate record (CMS internal data structure).
+ *
+ * @version $Revision$, $Date$
+ */
+public class DefStore implements IDefStore, IExtendedPluginInfo {
+
+ // refreshInSec is useful in the master-clone situation.
+ // clone does not know that the CRL has been updated in
+ // the master (by default no refresh)
+ private static final String PROP_USE_CACHE = "useCache";
+
+ private static final String PROP_REFRESH_IN_SEC = "refreshInSec";
+ private static final int DEF_REFRESH_IN_SEC = 0;
+
+ public static final BigInteger BIG_ZERO = new BigInteger("0");
+ public static final Long MINUS_ONE = Long.valueOf(-1);
+
+ private final static String PROP_BY_NAME =
+ "byName";
+ private final static String PROP_WAIT_ON_CRL_UPDATE =
+ "waitOnCRLUpdate";
+ private final static String PROP_NOT_FOUND_GOOD = "notFoundAsGood";
+ private final static String PROP_INCLUDE_NEXT_UPDATE =
+ "includeNextUpdate";
+
+ protected Hashtable<String, Long> mReqCounts = new Hashtable<String, Long>();
+ protected boolean mNotFoundGood = true;
+ protected boolean mUseCache = true;
+ protected boolean mByName = true;
+ protected boolean mIncludeNextUpdate = false;
+ protected Hashtable<String, CRLIPContainer> mCacheCRLIssuingPoints = new Hashtable<String, CRLIPContainer>();
+ private IOCSPAuthority mOCSPAuthority = null;
+ private IConfigStore mConfig = null;
+ private String mId = null;
+ private IDBSubsystem mDBService = null;
+ private int mStateCount = 0;
+
+ /**
+ * Constructs the default store.
+ */
+ public DefStore() {
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(PROP_NOT_FOUND_GOOD
+ + ";boolean; " + CMS.getUserMessage(locale, "CMS_OCSP_DEFSTORE_PROP_NOT_FOUND_GOOD"));
+ v.addElement(PROP_BY_NAME + ";boolean; " + CMS.getUserMessage(locale, "CMS_OCSP_DEFSTORE_PROP_BY_NAME"));
+ v.addElement(PROP_INCLUDE_NEXT_UPDATE
+ + ";boolean; " + CMS.getUserMessage(locale, "CMS_OCSP_DEFSTORE_PROP_INCLUDE_NEXT_UPDATE"));
+ v.addElement(IExtendedPluginInfo.HELP_TEXT + "; " + CMS.getUserMessage(locale, "CMS_OCSP_DEFSTORE_DESC"));
+ v.addElement(IExtendedPluginInfo.HELP_TOKEN + ";configuration-ocspstores-defstore");
+ return com.netscape.cmsutil.util.Utils.getStringArrayFromVector(v);
+ }
+
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mOCSPAuthority = (IOCSPAuthority) owner;
+ mConfig = config;
+
+ mDBService = (IDBSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_DBS);
+
+ // Standalone OCSP server only stores information about revoked
+ // certificates. So there is no way for the OCSP server to
+ // tell if a certificate is good (issued) or not.
+ // When an OCSP client asks the status of a certificate,
+ // the OCSP server by default returns GOOD. If the server
+ // returns UNKNOWN, the OCSP client (browser) will display
+ // a error dialog that confuses the end-user.
+ //
+ // OCSP response can return unknown or good when a certificate
+ // is not revoked.
+ mNotFoundGood = mConfig.getBoolean(PROP_NOT_FOUND_GOOD, true);
+
+ mUseCache = mConfig.getBoolean(PROP_USE_CACHE, true);
+
+ mByName = mConfig.getBoolean(PROP_BY_NAME, true);
+
+ // To include next update in the OCSP response. If included,
+ // PSM (client) will check to see if the revoked information
+ // is too old or not
+ mIncludeNextUpdate = mConfig.getBoolean(PROP_INCLUDE_NEXT_UPDATE,
+ false);
+
+ // init web gateway.
+ initWebGateway();
+
+ /**
+ * DeleteOldCRLsThread t = new DeleteOldCRLsThread(this);
+ * t.start();
+ **/
+ // deleteOldCRLs();
+ }
+
+ /**
+ * init web gateway - just gets the ee gateway for this CA.
+ */
+ private void initWebGateway()
+ throws EBaseException {
+ }
+
+ public IRepositoryRecord createRepositoryRecord() {
+ return CMS.createRepositoryRecord();
+ }
+
+ /**
+ * Returns to the client once the CRL is received.
+ */
+ public boolean waitOnCRLUpdate() {
+ boolean defaultVal = true;
+
+ try {
+ return mConfig.getBoolean(PROP_WAIT_ON_CRL_UPDATE, defaultVal);
+ } catch (EBaseException e) {
+ return defaultVal;
+ }
+ }
+
+ public boolean includeNextUpdate() {
+ return mIncludeNextUpdate;
+ }
+
+ public boolean isNotFoundGood() {
+ return mNotFoundGood;
+ }
+
+ public long getReqCount(String id) {
+ Long c = mReqCounts.get(id);
+
+ if (c == null)
+ return 0;
+ else
+ return c.longValue();
+ }
+
+ public void incReqCount(String id) {
+ mReqCounts.put(id, Long.valueOf(getReqCount(id) + 1));
+ }
+
+ /**
+ * This store will not delete the old CRL until the
+ * new one is totally committed.
+ */
+ public void deleteOldCRLs() throws EBaseException {
+ Enumeration<ICRLIssuingPointRecord> recs = searchCRLIssuingPointRecord(
+ "objectclass=" +
+ CMS.getCRLIssuingPointRecordName(),
+ 100);
+ while (recs.hasMoreElements()) {
+ ICRLIssuingPointRecord rec = recs.nextElement();
+ deleteOldCRLsInCA(rec.getId());
+ }
+ }
+
+ public void deleteOldCRLsInCA(String caName) throws EBaseException {
+ deleteCRLsInCA (caName, true);
+ }
+
+ public void deleteAllCRLsInCA(String caName) throws EBaseException {
+ deleteCRLsInCA (caName, false);
+ }
+
+ public void deleteCRLsInCA(String caName, boolean oldCRLs) throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ ICRLIssuingPointRecord cp = readCRLIssuingPoint(caName);
+
+ if (cp == null)
+ return; // nothing to do
+ if (cp.getThisUpdate() == null)
+ return; // nothing to do
+ String thisUpdate = Long.toString(
+ cp.getThisUpdate().getTime());
+ String filter = (oldCRLs)? "(!" + IRepositoryRecord.ATTR_SERIALNO + "=" + thisUpdate + ")": "ou=*";
+ Enumeration<IRepositoryRecord> e = searchRepository( caName, filter);
+
+ while (e != null && e.hasMoreElements()) {
+ IRepositoryRecord r = e.nextElement();
+ Enumeration<ICertRecord> recs =
+ searchCertRecord(caName,
+ r.getSerialNumber().toString(),
+ ICertRecord.ATTR_ID + "=*");
+
+ log(ILogger.LL_INFO, "remove CRL 0x" +
+ r.getSerialNumber().toString(16) +
+ " of " + caName);
+ String rep_dn = "ou=" +
+ r.getSerialNumber().toString() +
+ ",cn=" + transformDN(caName) + "," +
+ getBaseDN();
+
+ while (recs != null && recs.hasMoreElements()) {
+ ICertRecord rec = recs.nextElement();
+ String cert_dn = "cn=" +
+ rec.getSerialNumber().toString() + "," + rep_dn;
+
+ s.delete(cert_dn);
+ }
+ s.delete(rep_dn);
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ public void log(int event, int level, String msg) {
+ mOCSPAuthority.log(event, level, msg);
+ }
+
+ public void log(int level, String msg) {
+ mOCSPAuthority.log(level, msg);
+ }
+
+ public void startup() throws EBaseException {
+ int refresh = mConfig.getInteger(PROP_REFRESH_IN_SEC,
+ DEF_REFRESH_IN_SEC);
+ if (refresh > 0) {
+ DefStoreCRLUpdater updater =
+ new DefStoreCRLUpdater(mCacheCRLIssuingPoints, refresh);
+ updater.start();
+ }
+ }
+
+ public void shutdown() {
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * Validate an OCSP request.
+ */
+ public OCSPResponse validate(OCSPRequest request)
+ throws EBaseException {
+
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+
+ mOCSPAuthority.incNumOCSPRequest(1);
+ long startTime = CMS.getCurrentDate().getTime();
+ try {
+ mOCSPAuthority.log(ILogger.LL_INFO, "start OCSP request");
+ TBSRequest tbsReq = request.getTBSRequest();
+
+ // (3) look into database to check the
+ // certificate's status
+ Vector<SingleResponse> singleResponses = new Vector<SingleResponse>();
+ if (statsSub != null) {
+ statsSub.startTiming("lookup");
+ }
+
+ long lookupStartTime = CMS.getCurrentDate().getTime();
+ for (int i = 0; i < tbsReq.getRequestCount(); i++) {
+ com.netscape.cmsutil.ocsp.Request req =
+ tbsReq.getRequestAt(i);
+ CertID cid = req.getCertID();
+ SingleResponse sr = processRequest(cid);
+
+ singleResponses.addElement(sr);
+ }
+ long lookupEndTime = CMS.getCurrentDate().getTime();
+ if (statsSub != null) {
+ statsSub.endTiming("lookup");
+ }
+ mOCSPAuthority.incLookupTime(lookupEndTime - lookupStartTime);
+
+ if (singleResponses.size() <= 0) {
+ CMS.debug("DefStore: No Request Found");
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OCSP_REQUEST_FAILURE", "No Request Found"));
+ return null;
+ }
+ if (statsSub != null) {
+ statsSub.startTiming("build_response");
+ }
+ SingleResponse res[] = new SingleResponse[singleResponses.size()];
+
+ singleResponses.copyInto(res);
+
+ ResponderID rid = null;
+
+ if (mByName) {
+ rid = mOCSPAuthority.getResponderIDByName();
+ } else {
+ rid = mOCSPAuthority.getResponderIDByHash();
+ }
+
+ Extension nonce[] = null;
+
+ for (int j = 0; j < tbsReq.getExtensionsCount(); j++) {
+ Extension thisExt = tbsReq.getRequestExtensionAt(j);
+
+ if (thisExt.getExtnId().equals(IOCSPAuthority.OCSP_NONCE)) {
+ nonce = new Extension[1];
+ nonce[0] = thisExt;
+ }
+ }
+
+ ResponseData rd = new ResponseData(rid,
+ new GeneralizedTime(CMS.getCurrentDate()), res, nonce);
+ if (statsSub != null) {
+ statsSub.endTiming("build_response");
+ }
+
+ if (statsSub != null) {
+ statsSub.startTiming("signing");
+ }
+ long signStartTime = CMS.getCurrentDate().getTime();
+ BasicOCSPResponse basicRes = mOCSPAuthority.sign(rd);
+ long signEndTime = CMS.getCurrentDate().getTime();
+ if (statsSub != null) {
+ statsSub.endTiming("signing");
+ }
+ mOCSPAuthority.incSignTime(signEndTime - signStartTime);
+
+ OCSPResponse response = new OCSPResponse(
+ OCSPResponseStatus.SUCCESSFUL,
+ new ResponseBytes(ResponseBytes.OCSP_BASIC,
+ new OCTET_STRING(ASN1Util.encode(basicRes))));
+
+ log(ILogger.LL_INFO, "done OCSP request");
+ long endTime = CMS.getCurrentDate().getTime();
+ mOCSPAuthority.incTotalTime(endTime - startTime);
+ return response;
+ } catch (Exception e) {
+ CMS.debug("DefStore: validation failed " + e.toString());
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OCSP_REQUEST_FAILURE", e.toString()));
+ return null;
+ }
+ }
+
+ /**
+ * Check against the database for status.
+ */
+ private SingleResponse processRequest(CertID cid) {
+ // need to find the right CA
+
+ CMS.debug("DefStore: process request");
+ try {
+ // cache result to speed up the performance
+ X509CertImpl theCert = null;
+ X509CRLImpl theCRL = null;
+ ICRLIssuingPointRecord theRec = null;
+ byte keyhsh[] = cid.getIssuerKeyHash().toByteArray();
+ CRLIPContainer matched = mCacheCRLIssuingPoints.get(new String(keyhsh));
+
+ if (matched == null) {
+ Enumeration<ICRLIssuingPointRecord> recs = searchCRLIssuingPointRecord(
+ "objectclass=" +
+ CMS.getCRLIssuingPointRecordName(),
+ 100);
+
+ while (recs.hasMoreElements()) {
+ ICRLIssuingPointRecord rec = recs.nextElement();
+ byte certdata[] = rec.getCACert();
+ X509CertImpl cert = null;
+
+ try {
+ cert = new X509CertImpl(certdata);
+ } catch (Exception e) {
+ // error
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OCSP_DECODE_CERT", e.toString()));
+ return null;
+ }
+ MessageDigest md = MessageDigest.getInstance(
+ mOCSPAuthority.getDigestName(cid.getHashAlgorithm()));
+ X509Key key = (X509Key) cert.getPublicKey();
+ byte digest[] = md.digest(key.getKey());
+
+ if (mOCSPAuthority.arraysEqual(digest, keyhsh)) {
+ theCert = cert;
+ theRec = rec;
+ incReqCount(theRec.getId());
+ byte crldata[] = rec.getCRL();
+
+ if (rec.getCRLCache() == null) {
+ CMS.debug("DefStore: start building x509 crl impl");
+ try {
+ theCRL = new X509CRLImpl(crldata);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OCSP_DECODE_CRL", e.toString()));
+ }
+ CMS.debug("DefStore: done building x509 crl impl");
+ } else {
+ CMS.debug("DefStore: using crl cache");
+ }
+ mCacheCRLIssuingPoints.put(new String(digest), new CRLIPContainer(theRec, theCert, theCRL));
+ break;
+ }
+ }
+ } else {
+ theCert = matched.getX509CertImpl();
+ theRec = matched.getCRLIssuingPointRecord();
+ theCRL = matched.getX509CRLImpl();
+ incReqCount(theRec.getId());
+ }
+
+ // check the serial number
+ if (theCert != null) {
+ INTEGER serialNo = cid.getSerialNumber();
+
+ log(ILogger.EV_AUDIT, AuditFormat.LEVEL, "Checked Status of certificate 0x" + serialNo.toString(16));
+ CMS.debug("DefStore: process request 0x" + serialNo.toString(16));
+ CertStatus certStatus = null;
+ GeneralizedTime thisUpdate = null;
+
+ if (theRec == null) {
+ thisUpdate = new GeneralizedTime(CMS.getCurrentDate());
+ } else {
+ thisUpdate = new GeneralizedTime(
+ theRec.getThisUpdate());
+ }
+ GeneralizedTime nextUpdate = null;
+
+ if (includeNextUpdate()) {
+ // this is an optional field
+ if (theRec == null) {
+ nextUpdate = new GeneralizedTime(CMS.getCurrentDate());
+ } else {
+ nextUpdate = new GeneralizedTime(
+ theRec.getNextUpdate());
+ }
+ }
+
+ if (theCRL == null) {
+ certStatus = new UnknownInfo();
+
+ // if crl is not available, we can try crl cache
+ if (theRec != null) {
+ CMS.debug("DefStore: evaluating crl cache");
+ Hashtable<BigInteger, RevokedCertificate> cache = theRec.getCRLCacheNoClone();
+ if (cache != null) {
+ RevokedCertificate rc = cache.get(new BigInteger(serialNo.toString()));
+ if (rc == null) {
+ if (isNotFoundGood()) {
+ certStatus = new GoodInfo();
+ } else {
+ certStatus = new UnknownInfo();
+ }
+ } else {
+
+ certStatus = new RevokedInfo(
+ new GeneralizedTime(
+ rc.getRevocationDate()));
+ }
+ }
+ }
+
+ } else {
+ CMS.debug("DefStore: evaluating x509 crl impl");
+ X509CRLEntry crlentry = theCRL.getRevokedCertificate(new BigInteger(serialNo.toString()));
+
+ if (crlentry == null) {
+ // good or unknown
+ if (isNotFoundGood()) {
+ certStatus = new GoodInfo();
+ } else {
+ certStatus = new UnknownInfo();
+ }
+ } else {
+ certStatus = new RevokedInfo(new GeneralizedTime(
+ crlentry.getRevocationDate()));
+
+ }
+ }
+ return new SingleResponse(cid, certStatus, thisUpdate,
+ nextUpdate);
+ }
+ } catch (Exception e) {
+ // error log
+ CMS.debug("DefStore: failed processing request e=" + e);
+ }
+ return null;
+ }
+
+ private String transformDN(String dn) {
+ String newdn = dn;
+
+ newdn = newdn.replace(',', '_');
+ newdn = newdn.replace('=', '-');
+ return newdn;
+ }
+
+ public String getBaseDN() {
+ return mDBService.getBaseDN();
+ }
+
+ public Enumeration<ICRLIssuingPointRecord> searchAllCRLIssuingPointRecord(int maxSize)
+ throws EBaseException {
+ return searchCRLIssuingPointRecord(
+ "objectclass=" +
+ CMS.getCRLIssuingPointRecordName(),
+ maxSize);
+ }
+
+ public Enumeration<ICRLIssuingPointRecord> searchCRLIssuingPointRecord(String filter,
+ int maxSize)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Vector<ICRLIssuingPointRecord> v = new Vector<ICRLIssuingPointRecord>();
+
+ try {
+ IDBSearchResults sr = s.search(getBaseDN(), filter, maxSize);
+ while (sr.hasMoreElements()) {
+ v.add((ICRLIssuingPointRecord) sr.nextElement());
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return v.elements();
+ }
+
+ public synchronized void modifyCRLIssuingPointRecord(String name,
+ ModificationSet mods) throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String dn = "cn=" +
+ transformDN(name) + "," + getBaseDN();
+
+ s.modify(dn, mods);
+ } catch (EBaseException e) {
+ CMS.debug("modifyCRLIssuingPointRecord: error=" + e);
+ CMS.debug(e);
+ throw e;
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ /**
+ * Returns an issuing point.
+ */
+ public ICRLIssuingPointRecord readCRLIssuingPoint(String name)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ ICRLIssuingPointRecord rec = null;
+
+ try {
+ String dn = "cn=" +
+ transformDN(name) + "," + getBaseDN();
+
+ if (s != null) {
+ rec = (ICRLIssuingPointRecord) s.read(dn);
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return rec;
+ }
+
+ public ICRLIssuingPointRecord createCRLIssuingPointRecord(
+ String name, BigInteger crlNumber,
+ Long crlSize, Date thisUpdate, Date nextUpdate) {
+ return CMS.createCRLIssuingPointRecord(
+ name, crlNumber, crlSize, thisUpdate, nextUpdate);
+ }
+
+ public void deleteCRLIssuingPointRecord(String id)
+ throws EBaseException {
+
+ IDBSSession s = null;
+
+ try {
+ s = mDBService.createSession();
+ String name = "cn=" + transformDN(id) + "," + getBaseDN();
+ CMS.debug("DefStore::deleteCRLIssuingPointRecord: Attempting to delete: " + name);
+ if (s != null) {
+ deleteAllCRLsInCA(id);
+ s.delete(name);
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ /**
+ * Creates a new issuing point in OCSP.
+ */
+ public void addCRLIssuingPoint(String name, ICRLIssuingPointRecord rec)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String dn = "cn=" +
+ transformDN(name) + "," + getBaseDN();
+
+ s.add(dn, rec);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ public Enumeration<IRepositoryRecord> searchRepository(String name, String filter)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Vector<IRepositoryRecord> v = new Vector<IRepositoryRecord>();
+
+ try {
+ IDBSearchResults sr = s.search("cn=" + transformDN(name) + "," + getBaseDN(),
+ filter);
+ while (sr.hasMoreElements()) {
+ v.add((IRepositoryRecord) sr.nextElement());
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return v.elements();
+ }
+
+ /**
+ * Creates a new issuing point in OCSP.
+ */
+ public void addRepository(String name, String thisUpdate,
+ IRepositoryRecord rec)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String dn = "ou=" + thisUpdate + ",cn=" +
+ transformDN(name) + "," + getBaseDN();
+
+ s.add(dn, rec);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ public void modifyCertRecord(String name, String thisUpdate,
+ String sno,
+ ModificationSet mods) throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String dn = "cn=" + sno + ",ou=" + thisUpdate +
+ ",cn=" + transformDN(name) + "," + getBaseDN();
+
+ if (s != null)
+ s.modify(dn, mods);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ public Enumeration<ICertRecord> searchCertRecord(String name, String thisUpdate,
+ String filter) throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Vector<ICertRecord> v = new Vector<ICertRecord>();
+
+ try {
+ IDBSearchResults sr = s.search("ou=" + thisUpdate + ",cn=" +
+ transformDN(name) + "," + getBaseDN(),
+ filter);
+ while (sr.hasMoreElements()) {
+ v.add((ICertRecord) sr.nextElement());
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return v.elements();
+ }
+
+ public ICertRecord readCertRecord(String name, String thisUpdate,
+ String sno)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ ICertRecord rec = null;
+
+ try {
+ String dn = "cn=" + sno + ",ou=" + thisUpdate +
+ ",cn=" + transformDN(name) + "," + getBaseDN();
+
+ if (s != null) {
+ rec = (ICertRecord) s.read(dn);
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return rec;
+ }
+
+ /**
+ * Creates a new issuing point in OCSP.
+ */
+ public void addCertRecord(String name, String thisUpdate,
+ String sno, ICertRecord rec)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String dn = "cn=" + sno + ",ou=" + thisUpdate +
+ ",cn=" + transformDN(name) + "," + getBaseDN();
+
+ s.add(dn, rec);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ public NameValuePairs getConfigParameters() {
+ try {
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_OCSPSTORE_IMPL_NAME,
+ mConfig.getString("class"));
+ params.put(PROP_NOT_FOUND_GOOD,
+ mConfig.getString(PROP_NOT_FOUND_GOOD, "true"));
+ params.put(PROP_BY_NAME,
+ mConfig.getString(PROP_BY_NAME, "true"));
+ params.put(PROP_INCLUDE_NEXT_UPDATE,
+ mConfig.getString(PROP_INCLUDE_NEXT_UPDATE, "false"));
+ return params;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public void setConfigParameters(NameValuePairs pairs)
+ throws EBaseException {
+
+ for (String key : pairs.keySet()) {
+ mConfig.put(key, pairs.get(key));
+ }
+ }
+
+ public void updateCRL(X509CRL crl) throws EBaseException {
+ try {
+ mStateCount++;
+
+ CMS.debug("DefStore: Ready to update Issuer");
+
+ try {
+ if (!((X509CRLImpl) crl).areEntriesIncluded())
+ crl = new X509CRLImpl(((X509CRLImpl) crl).getEncoded());
+ } catch (Exception e) {
+ CMS.debug(e);
+ }
+
+ // commit update
+ ModificationSet mods = new ModificationSet();
+
+ if (crl.getThisUpdate() != null)
+ mods.add(ICRLIssuingPointRecord.ATTR_THIS_UPDATE,
+ Modification.MOD_REPLACE, crl.getThisUpdate());
+ if (crl.getNextUpdate() != null)
+ mods.add(ICRLIssuingPointRecord.ATTR_NEXT_UPDATE,
+ Modification.MOD_REPLACE, crl.getNextUpdate());
+ if (mUseCache) {
+ if (((X509CRLImpl) crl).getListOfRevokedCertificates() != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_CRL_CACHE,
+ Modification.MOD_REPLACE,
+ ((X509CRLImpl) crl).getListOfRevokedCertificates());
+ }
+ }
+ if (((X509CRLImpl) crl).getNumberOfRevokedCertificates() < 0) {
+ mods.add(ICRLIssuingPointRecord.ATTR_CRL_SIZE,
+ Modification.MOD_REPLACE, Long.valueOf(0));
+ } else {
+ mods.add(ICRLIssuingPointRecord.ATTR_CRL_SIZE,
+ Modification.MOD_REPLACE, Long.valueOf(((X509CRLImpl) crl).getNumberOfRevokedCertificates()));
+ }
+ BigInteger crlNumber = ((X509CRLImpl) crl).getCRLNumber();
+ if (crlNumber == null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_CRL_NUMBER,
+ Modification.MOD_REPLACE, new BigInteger("-1"));
+ } else {
+ mods.add(ICRLIssuingPointRecord.ATTR_CRL_NUMBER,
+ Modification.MOD_REPLACE, crlNumber);
+ }
+ try {
+ mods.add(ICRLIssuingPointRecord.ATTR_CRL,
+ Modification.MOD_REPLACE, crl.getEncoded());
+ } catch (Exception e) {
+ // ignore
+ }
+ CMS.debug("DefStore: ready to CRL update " +
+ crl.getIssuerDN().getName());
+ modifyCRLIssuingPointRecord(
+ crl.getIssuerDN().getName(), mods);
+ CMS.debug("DefStore: done CRL update " +
+ crl.getIssuerDN().getName());
+
+ // update cache
+ mCacheCRLIssuingPoints.clear();
+
+ log(ILogger.LL_INFO, "AddCRLServlet: Finish Committing CRL." +
+ " thisUpdate=" + crl.getThisUpdate() +
+ " nextUpdate=" + crl.getNextUpdate());
+
+ } finally {
+ mStateCount--;
+ }
+ }
+
+ public int getStateCount() {
+ return mStateCount;
+ }
+
+}
+
+class DeleteOldCRLsThread extends Thread {
+ private DefStore mDefStore = null;
+
+ public DeleteOldCRLsThread(DefStore defStore) {
+ mDefStore = defStore;
+ }
+
+ public void run() {
+ try {
+ mDefStore.deleteOldCRLs();
+ } catch (EBaseException e) {
+ }
+ }
+}
+
+class CRLIPContainer {
+ private ICRLIssuingPointRecord mRec = null;
+ private X509CertImpl mCert = null;
+ private X509CRLImpl mCRL = null;
+
+ public CRLIPContainer(ICRLIssuingPointRecord rec, X509CertImpl cert, X509CRLImpl crl) {
+ mRec = rec;
+ mCert = cert;
+ mCRL = crl;
+ }
+
+ public ICRLIssuingPointRecord getCRLIssuingPointRecord() {
+ return mRec;
+ }
+
+ public X509CertImpl getX509CertImpl() {
+ return mCert;
+ }
+
+ public X509CRLImpl getX509CRLImpl() {
+ return mCRL;
+ }
+}
+
+class DefStoreCRLUpdater extends Thread {
+ private Hashtable<String, CRLIPContainer> mCache = null;
+ private int mSec = 0;
+
+ public DefStoreCRLUpdater(Hashtable<String, CRLIPContainer> cache, int sec) {
+ mCache = cache;
+ mSec = sec;
+ }
+
+ public void run() {
+ while (true) {
+ try {
+ CMS.debug("DefStore: CRLUpdater invoked");
+ mCache.clear();
+ sleep(mSec * 1000); // turn sec into millis-sec
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/ocsp/LDAPStore.java b/base/server/cms/src/com/netscape/cms/ocsp/LDAPStore.java
new file mode 100644
index 000000000..e2e5fc493
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/ocsp/LDAPStore.java
@@ -0,0 +1,749 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.ocsp;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.cert.X509CRL;
+import java.security.cert.X509CRLEntry;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+import netscape.security.x509.RevokedCertificate;
+import netscape.security.x509.X509CRLImpl;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509Key;
+
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.GeneralizedTime;
+import org.mozilla.jss.asn1.OCTET_STRING;
+import org.mozilla.jss.pkix.cert.Extension;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+import com.netscape.certsrv.dbs.repository.IRepositoryRecord;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ocsp.IDefStore;
+import com.netscape.certsrv.ocsp.IOCSPAuthority;
+import com.netscape.certsrv.util.IStatsSubsystem;
+import com.netscape.cmsutil.ocsp.BasicOCSPResponse;
+import com.netscape.cmsutil.ocsp.CertID;
+import com.netscape.cmsutil.ocsp.CertStatus;
+import com.netscape.cmsutil.ocsp.GoodInfo;
+import com.netscape.cmsutil.ocsp.OCSPRequest;
+import com.netscape.cmsutil.ocsp.OCSPResponse;
+import com.netscape.cmsutil.ocsp.OCSPResponseStatus;
+import com.netscape.cmsutil.ocsp.ResponderID;
+import com.netscape.cmsutil.ocsp.ResponseBytes;
+import com.netscape.cmsutil.ocsp.ResponseData;
+import com.netscape.cmsutil.ocsp.RevokedInfo;
+import com.netscape.cmsutil.ocsp.SingleResponse;
+import com.netscape.cmsutil.ocsp.TBSRequest;
+import com.netscape.cmsutil.ocsp.UnknownInfo;
+
+/**
+ * This is the LDAP OCSP store. It reads CA certificate and
+ * revocation list attributes from the CA entry.
+ *
+ * @version $Revision$, $Date$
+ */
+public class LDAPStore implements IDefStore, IExtendedPluginInfo {
+ private static final String PROP_NUM_CONNS = "numConns";
+ private static final String PROP_REFRESH_IN_SEC = "refreshInSec";
+ private static final int DEF_REFRESH_IN_SEC = 60 * 60 * 24;
+ private static final String PROP_BASE_DN = "baseDN";
+ private static final String PROP_BY_NAME = "byName";
+ private static final String PROP_CRL_ATTR = "crlAttr";
+ private static final String DEF_CRL_ATTR = "certificateRevocationList;binary";
+ private static final String PROP_CA_CERT_ATTR = "caCertAttr";
+ private static final String DEF_CA_CERT_ATTR = "cACertificate;binary";
+ private static final String PROP_HOST = "host";
+ private static final String PROP_PORT = "port";
+
+ private final static String PROP_NOT_FOUND_GOOD = "notFoundAsGood";
+ private final static String PROP_INCLUDE_NEXT_UPDATE =
+ "includeNextUpdate";
+
+ private IOCSPAuthority mOCSPAuthority = null;
+ private IConfigStore mConfig = null;
+ private String mId = null;
+ private String mCRLAttr = null;
+ private boolean mByName = true;
+ private String mCACertAttr = null;
+ protected Hashtable<String, Long> mReqCounts = new Hashtable<String, Long>();
+ private Hashtable<X509CertImpl, X509CRLImpl> mCRLs = new Hashtable<X509CertImpl, X509CRLImpl>();
+
+ /**
+ * Constructs the default store.
+ */
+ public LDAPStore() {
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(PROP_NOT_FOUND_GOOD
+ + ";boolean; " + CMS.getUserMessage(locale, "CMS_OCSP_LDAPSTORE_PROP_NOT_FOUND_GOOD"));
+ v.addElement(PROP_INCLUDE_NEXT_UPDATE
+ + ";boolean; " + CMS.getUserMessage(locale, "CMS_OCSP_LDAPSTORE_PROP_INCLUDE_NEXT_UPDATE"));
+ v.addElement(PROP_NUM_CONNS + ";number; " + CMS.getUserMessage(locale, "CMS_OCSP_LDAPSTORE_PROP_NUM_CONNS"));
+ v.addElement(PROP_BY_NAME + ";boolean; " + CMS.getUserMessage(locale, "CMS_OCSP_LDAPSTORE_PROP_BY_NAME"));
+ v.addElement(PROP_CRL_ATTR + ";string; " + CMS.getUserMessage(locale, "CMS_OCSP_LDAPSTORE_PROP_CRL_ATTR"));
+ v.addElement(PROP_CA_CERT_ATTR
+ + ";string; " + CMS.getUserMessage(locale, "CMS_OCSP_LDAPSTORE_PROP_CA_CERT_ATTR"));
+ v.addElement(IExtendedPluginInfo.HELP_TEXT + "; " + CMS.getUserMessage(locale, "CMS_OCSP_LDAPSTORE_DESC"));
+ v.addElement(IExtendedPluginInfo.HELP_TOKEN + ";configuration-ocspstores-ldapstore");
+ return com.netscape.cmsutil.util.Utils.getStringArrayFromVector(v);
+ }
+
+ /**
+ * Fetch CA certificate and CRL from LDAP server.
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mOCSPAuthority = (IOCSPAuthority) owner;
+ mConfig = config;
+
+ mCRLAttr = mConfig.getString(PROP_CRL_ATTR, DEF_CRL_ATTR);
+ mCACertAttr = mConfig.getString(PROP_CA_CERT_ATTR,
+ DEF_CA_CERT_ATTR);
+ mByName = mConfig.getBoolean(PROP_BY_NAME, true);
+
+ }
+
+ /**
+ * Locates the CA certificate.
+ */
+ public X509CertImpl locateCACert(LDAPConnection conn, String baseDN)
+ throws EBaseException {
+ try {
+ LDAPSearchResults results = conn.search(baseDN,
+ LDAPv2.SCOPE_SUB, mCACertAttr + "=*",
+ null, false);
+
+ if (!results.hasMoreElements()) {
+ throw new EBaseException("error - no entry");
+ }
+ LDAPEntry entry = results.next();
+ LDAPAttribute crls = entry.getAttribute(mCACertAttr);
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> vals = crls.getByteValues();
+
+ if (!vals.hasMoreElements()) {
+ throw new EBaseException("error - no values");
+ }
+ byte caCertData[] = vals.nextElement();
+ X509CertImpl caCert = new X509CertImpl(caCertData);
+
+ return caCert;
+ } catch (Exception e) {
+ CMS.debug("LDAPStore: locateCACert " + e.toString());
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("OCSP_LOCATE_CA", e.toString()));
+ }
+ return null;
+ }
+
+ /**
+ * Locates the CRL.
+ */
+ public X509CRLImpl locateCRL(LDAPConnection conn, String baseDN)
+ throws EBaseException {
+ try {
+ LDAPSearchResults results = conn.search(baseDN,
+ LDAPv2.SCOPE_SUB, mCRLAttr + "=*",
+ null, false);
+
+ if (!results.hasMoreElements()) {
+ throw new EBaseException("error - no entry");
+ }
+ LDAPEntry entry = results.next();
+ LDAPAttribute crls = entry.getAttribute(mCRLAttr);
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> vals = crls.getByteValues();
+
+ if (!vals.hasMoreElements()) {
+ throw new EBaseException("error - no values");
+ }
+ byte crlData[] = vals.nextElement();
+ X509CRLImpl crl = new X509CRLImpl(crlData);
+
+ return crl;
+ } catch (Exception e) {
+ CMS.debug("LDAPStore: locateCRL " + e.toString());
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("OCSP_LOCATE_CRL", e.toString()));
+ }
+ return null;
+ }
+
+ public void updateCRLHash(X509CertImpl caCert, X509CRLImpl crl)
+ throws EBaseException {
+ X509CRLImpl oldCRL = mCRLs.get(caCert);
+
+ if (oldCRL != null) {
+ if (oldCRL.getThisUpdate().getTime() >= crl.getThisUpdate().getTime()) {
+ log(ILogger.LL_INFO,
+ "LDAPStore: no update, received CRL is older than current CRL");
+ return; // no update
+ }
+ }
+ CMS.debug("Added '" + caCert.getSubjectDN().toString() + "' into CRL hash");
+ mCRLs.put(caCert, crl);
+ }
+
+ public void log(int level, String msg) {
+ mOCSPAuthority.log(level, msg);
+ }
+
+ public void startup() throws EBaseException {
+ int num = mConfig.getInteger(PROP_NUM_CONNS, 0);
+
+ for (int i = 0; i < num; i++) {
+ String host = mConfig.getString(PROP_HOST + Integer.toString(i), null);
+ int port = mConfig.getInteger(PROP_PORT + Integer.toString(i), 0);
+ LDAPConnection c = new LDAPConnection();
+
+ try {
+ c.connect(host, port);
+ } catch (LDAPException e) {
+ throw new EBaseException("LDAP " + e);
+ }
+ String baseDN = mConfig.getString(PROP_BASE_DN + Integer.toString(i), null);
+ CRLUpdater updater = new CRLUpdater(
+ this, c, baseDN,
+ mConfig.getInteger(PROP_REFRESH_IN_SEC + Integer.toString(i),
+ DEF_REFRESH_IN_SEC));
+
+ updater.start();
+ }
+ }
+
+ public void shutdown() {
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * Validate an OCSP request.
+ */
+ public OCSPResponse validate(OCSPRequest request)
+ throws EBaseException {
+
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+
+ mOCSPAuthority.incNumOCSPRequest(1);
+ long startTime = CMS.getCurrentDate().getTime();
+ try {
+ mOCSPAuthority.log(ILogger.LL_INFO, "start OCSP request");
+ TBSRequest tbsReq = request.getTBSRequest();
+
+ Vector<SingleResponse> singleResponses = new Vector<SingleResponse>();
+
+ if (statsSub != null) {
+ statsSub.startTiming("lookup");
+ }
+
+ long lookupStartTime = CMS.getCurrentDate().getTime();
+ for (int i = 0; i < tbsReq.getRequestCount(); i++) {
+ com.netscape.cmsutil.ocsp.Request req =
+ tbsReq.getRequestAt(i);
+ CertID cid = req.getCertID();
+ SingleResponse sr = processRequest(cid);
+
+ singleResponses.addElement(sr);
+ }
+ long lookupEndTime = CMS.getCurrentDate().getTime();
+ if (statsSub != null) {
+ statsSub.endTiming("lookup");
+ }
+ mOCSPAuthority.incLookupTime(lookupEndTime - lookupStartTime);
+
+ if (statsSub != null) {
+ statsSub.startTiming("build_response");
+ }
+ SingleResponse res[] = new SingleResponse[singleResponses.size()];
+
+ singleResponses.copyInto(res);
+
+ ResponderID rid = null;
+
+ if (mByName) {
+ rid = mOCSPAuthority.getResponderIDByName();
+ } else {
+ rid = mOCSPAuthority.getResponderIDByHash();
+ }
+
+ Extension nonce[] = null;
+
+ for (int j = 0; j < tbsReq.getExtensionsCount(); j++) {
+ Extension thisExt = tbsReq.getRequestExtensionAt(j);
+
+ if (thisExt.getExtnId().equals(IOCSPAuthority.OCSP_NONCE)) {
+ nonce = new Extension[1];
+ nonce[0] = thisExt;
+ }
+ }
+
+ ResponseData rd = new ResponseData(rid,
+ new GeneralizedTime(CMS.getCurrentDate()), res, nonce);
+ if (statsSub != null) {
+ statsSub.endTiming("build_response");
+ }
+
+ if (statsSub != null) {
+ statsSub.startTiming("signing");
+ }
+
+ long signStartTime = CMS.getCurrentDate().getTime();
+ BasicOCSPResponse basicRes = mOCSPAuthority.sign(rd);
+ long signEndTime = CMS.getCurrentDate().getTime();
+ mOCSPAuthority.incSignTime(signEndTime - signStartTime);
+ if (statsSub != null) {
+ statsSub.endTiming("signing");
+ }
+
+ OCSPResponse response = new OCSPResponse(
+ OCSPResponseStatus.SUCCESSFUL,
+ new ResponseBytes(ResponseBytes.OCSP_BASIC,
+ new OCTET_STRING(ASN1Util.encode(basicRes))));
+
+ log(ILogger.LL_INFO, "done OCSP request");
+ long endTime = CMS.getCurrentDate().getTime();
+ mOCSPAuthority.incTotalTime(endTime - startTime);
+ return response;
+ } catch (Exception e) {
+ CMS.debug("LDAPStore: validation " + e.toString());
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OCSP_REQUEST_FAILURE", e.toString()));
+ return null;
+ }
+ }
+
+ public int getStateCount() {
+ return 0;
+ }
+
+ public long getReqCount(String id) {
+ Long c = mReqCounts.get(id);
+
+ if (c == null)
+ return 0;
+ else
+ return c.longValue();
+ }
+
+ public IRepositoryRecord createRepositoryRecord() {
+ return null;
+ }
+
+ public void addRepository(String name, String thisUpdate,
+ IRepositoryRecord rec)
+ throws EBaseException {
+ throw new EBaseException("NOT SUPPORTED");
+ }
+
+ public boolean waitOnCRLUpdate() {
+ return false;
+ }
+
+ public void updateCRL(X509CRL crl) throws EBaseException {
+ throw new EBaseException("NOT SUPPORTED");
+ }
+
+ public ICRLIssuingPointRecord readCRLIssuingPoint(String name)
+ throws EBaseException {
+ throw new EBaseException("NOT SUPPORTED");
+ }
+
+ public Enumeration<ICRLIssuingPointRecord> searchAllCRLIssuingPointRecord(int maxSize)
+ throws EBaseException {
+ Vector<ICRLIssuingPointRecord> recs = new Vector<ICRLIssuingPointRecord>();
+ Enumeration<X509CertImpl> keys = mCRLs.keys();
+
+ while (keys.hasMoreElements()) {
+ X509CertImpl caCert = keys.nextElement();
+ X509CRLImpl crl = mCRLs.get(caCert);
+
+ recs.addElement(new TempCRLIssuingPointRecord(caCert, crl));
+ }
+ return recs.elements();
+ }
+
+ public Enumeration<ICRLIssuingPointRecord> searchCRLIssuingPointRecord(String filter,
+ int maxSize)
+ throws EBaseException {
+ return null;
+ }
+
+ public ICRLIssuingPointRecord createCRLIssuingPointRecord(
+ String name, BigInteger crlNumber,
+ Long crlSize, Date thisUpdate, Date nextUpdate) {
+ return null;
+ }
+
+ public void addCRLIssuingPoint(String name, ICRLIssuingPointRecord rec)
+ throws EBaseException {
+ throw new EBaseException("NOT SUPPORTED");
+ }
+
+ public void deleteCRLIssuingPointRecord(String id)
+ throws EBaseException {
+ throw new EBaseException("NOT SUPPORTED");
+ }
+
+ public boolean isNotFoundGood() {
+ try {
+ return isNotFoundGood1();
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ public boolean includeNextUpdate() throws EBaseException {
+ return mConfig.getBoolean(PROP_INCLUDE_NEXT_UPDATE, false);
+ }
+
+ public boolean isNotFoundGood1() throws EBaseException {
+ return mConfig.getBoolean(PROP_NOT_FOUND_GOOD, true);
+ }
+
+ public void incReqCount(String id) {
+ mReqCounts.put(id, Long.valueOf(getReqCount(id) + 1));
+ }
+
+ /**
+ * Check against the database for status.
+ */
+ private SingleResponse processRequest(CertID cid) throws EBaseException {
+ // locate the right CRL
+ X509CertImpl theCert = null;
+ X509CRLImpl theCRL = null;
+
+ Enumeration<X509CertImpl> caCerts = mCRLs.keys();
+
+ while (caCerts.hasMoreElements()) {
+ X509CertImpl caCert = caCerts.nextElement();
+ MessageDigest md = null;
+
+ try {
+ md = MessageDigest.getInstance(
+ mOCSPAuthority.getDigestName(cid.getHashAlgorithm()));
+ } catch (Exception e) {
+ }
+ X509Key key = (X509Key) caCert.getPublicKey();
+
+ if (key == null) {
+ System.out.println("LDAPStore::processRequest - key is null!");
+ return null;
+ }
+
+ byte digest[] = md.digest(key.getKey());
+ byte keyhsh[] = cid.getIssuerKeyHash().toByteArray();
+
+ if (mOCSPAuthority.arraysEqual(digest, keyhsh)) {
+ theCert = caCert;
+ incReqCount(caCert.getSubjectDN().toString());
+ theCRL = mCRLs.get(caCert);
+ break;
+ }
+ }
+
+ if (theCert == null) {
+ return null;
+ }
+
+ if (theCRL == null) {
+ return null;
+ }
+
+ GeneralizedTime thisUpdate = new GeneralizedTime(
+ theCRL.getThisUpdate());
+ GeneralizedTime nextUpdate = null;
+
+ if (includeNextUpdate()) {
+ nextUpdate = new GeneralizedTime(
+ theCRL.getNextUpdate());
+ }
+
+ CertStatus certStatus = null;
+ X509CRLEntry entry = theCRL.getRevokedCertificate(
+ cid.getSerialNumber());
+
+ if (entry == null) {
+ if (isNotFoundGood1()) {
+ certStatus = new GoodInfo();
+ } else {
+ certStatus = new UnknownInfo();
+ }
+ } else {
+ certStatus = new RevokedInfo(new GeneralizedTime(
+ entry.getRevocationDate()));
+ }
+
+ return new SingleResponse(cid, certStatus, thisUpdate, nextUpdate);
+ }
+
+ /**
+ * Provides configuration parameters.
+ */
+ public NameValuePairs getConfigParameters() {
+ try {
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_OCSPSTORE_IMPL_NAME,
+ mConfig.getString("class"));
+ int num = mConfig.getInteger(PROP_NUM_CONNS, 0);
+
+ params.put(PROP_NUM_CONNS, Integer.toString(num));
+ for (int i = 0; i < num; i++) {
+ params.put(PROP_HOST + Integer.toString(i),
+ mConfig.getString(PROP_HOST +
+ Integer.toString(i), ""));
+ params.put(PROP_PORT + Integer.toString(i),
+ mConfig.getString(PROP_PORT +
+ Integer.toString(i), "389"));
+ params.put(PROP_BASE_DN + Integer.toString(i),
+ mConfig.getString(PROP_BASE_DN +
+ Integer.toString(i), ""));
+ params.put(PROP_REFRESH_IN_SEC + Integer.toString(i),
+ mConfig.getString(PROP_REFRESH_IN_SEC +
+ Integer.toString(i), Integer.toString(DEF_REFRESH_IN_SEC)));
+ }
+ params.put(PROP_BY_NAME,
+ mConfig.getString(PROP_BY_NAME, "true"));
+ params.put(PROP_CA_CERT_ATTR,
+ mConfig.getString(PROP_CA_CERT_ATTR, DEF_CA_CERT_ATTR));
+ params.put(PROP_CRL_ATTR,
+ mConfig.getString(PROP_CRL_ATTR, DEF_CRL_ATTR));
+ params.put(PROP_NOT_FOUND_GOOD,
+ mConfig.getString(PROP_NOT_FOUND_GOOD, "true"));
+ params.put(PROP_INCLUDE_NEXT_UPDATE,
+ mConfig.getString(PROP_INCLUDE_NEXT_UPDATE, "false"));
+ return params;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public void setConfigParameters(NameValuePairs pairs)
+ throws EBaseException {
+
+ for (String key : pairs.keySet()) {
+ mConfig.put(key, pairs.get(key));
+ }
+ }
+}
+
+class CRLUpdater extends Thread {
+ private LDAPConnection mC = null;
+ private String mBaseDN = null;
+ private int mSec = 0;
+ private LDAPStore mStore = null;
+
+ public CRLUpdater(LDAPStore store, LDAPConnection c,
+ String baseDN, int sec) {
+ mC = c;
+ mSec = sec;
+ mBaseDN = baseDN;
+ mStore = store;
+ }
+
+ public void run() {
+ while (true) {
+ try {
+ LDAPConnection conn = mC;
+ CMS.debug("Started CRL Update '" + mBaseDN);
+ X509CertImpl caCert = mStore.locateCACert(conn, mBaseDN);
+ X509CRLImpl crl = mStore.locateCRL(conn, mBaseDN);
+
+ mStore.updateCRLHash(caCert, crl);
+ CMS.debug("Finished CRL Update - '" + mBaseDN);
+ sleep(mSec * 1000); // turn sec into millis-sec
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+}
+
+class TempCRLIssuingPointRecord implements ICRLIssuingPointRecord {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5299660983298765746L;
+ private X509CertImpl mCACert = null;
+ private X509CRLImpl mCRL = null;
+
+ TempCRLIssuingPointRecord(X509CertImpl caCert, X509CRLImpl crl) {
+ mCACert = caCert;
+ mCRL = crl;
+ }
+
+ public String getId() {
+ return mCACert.getSubjectDN().toString();
+ }
+
+ /**
+ * Retrieves CRL serial number.
+ */
+ public BigInteger getCRLNumber() {
+ return null;
+ }
+
+ /**
+ * Retrieves delta CRL serial number.
+ */
+ public BigInteger getDeltaCRLNumber() {
+ return null;
+ }
+
+ /**
+ * Retrieves CRL size.
+ */
+ public Long getCRLSize() {
+ return Long.valueOf(mCRL.getNumberOfRevokedCertificates());
+ }
+
+ /**
+ * Retrieves CRL size.
+ */
+ public Long getDeltaCRLSize() {
+ return Long.valueOf(-1);
+ }
+
+ /**
+ * Retrieves this update time.
+ */
+ public Date getThisUpdate() {
+ return mCRL.getThisUpdate();
+ }
+
+ /**
+ * Retrieves next update time.
+ */
+ public Date getNextUpdate() {
+ return mCRL.getNextUpdate();
+ }
+
+ public String getFirstUnsaved() {
+ return null;
+ }
+
+ public Hashtable<BigInteger, RevokedCertificate> getCRLCacheNoClone() {
+ return null;
+ }
+
+ public Hashtable<BigInteger, RevokedCertificate> getCRLCache() {
+ return null;
+ }
+
+ /**
+ * Retrieves CRL encodings.
+ */
+ public byte[] getCRL() {
+ try {
+ return mCRL.getEncoded();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Retrieves CRL encodings.
+ */
+ public byte[] getDeltaCRL() {
+ return null;
+ }
+
+ public int isCRLIssuingPointInitialized() {
+ return 1;
+ }
+
+ public byte[] getCACert() {
+ try {
+ return mCACert.getEncoded();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Retrieves cache info of revoked certificates.
+ */
+ public Hashtable<BigInteger, RevokedCertificate> getRevokedCerts() {
+ return mCRL.getListOfRevokedCertificates();
+ }
+
+ /**
+ * Retrieves cache info of unrevoked certificates.
+ */
+ public Hashtable<BigInteger, RevokedCertificate> getUnrevokedCerts() {
+ return null;
+ }
+
+ /**
+ * Retrieves cache info of expired certificates.
+ */
+ public Hashtable<BigInteger, RevokedCertificate> getExpiredCerts() {
+ return null;
+ }
+
+ public Enumeration<String> getSerializableAttrNames() {
+ return null;
+ }
+
+ public void set(String name, Object obj) throws EBaseException {
+ }
+
+ public Object get(String name) throws EBaseException {
+ return null;
+ }
+
+ public void delete(String name) throws EBaseException {
+
+ }
+
+ public Enumeration<String> getElements() {
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/password/PasswordChecker.java b/base/server/cms/src/com/netscape/cms/password/PasswordChecker.java
new file mode 100644
index 000000000..ae379761d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/password/PasswordChecker.java
@@ -0,0 +1,103 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.password;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.password.EPasswordCheckException;
+import com.netscape.certsrv.password.IConfigPasswordCheck;
+import com.netscape.certsrv.password.IPasswordCheck;
+
+/**
+ * This class checks the given password if it meets the specific requirements.
+ * For example, it can also specify the format of the password which has to
+ * be 8 characters long and must be in alphanumeric.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class PasswordChecker implements IPasswordCheck, IConfigPasswordCheck {
+
+ public static final int MIN_LEN = 8;
+
+ /**
+ * Default constructor.
+ */
+ public PasswordChecker() {
+ }
+
+ public boolean isGoodConfigPassword(String mPassword) {
+ if (mPassword == null || mPassword.length() == 0) {
+ return false;
+ } else if (mPassword.length() < MIN_LEN) {
+ return false;
+ }
+ return true;
+ }
+
+ public String getConfigReason(String mPassword) {
+ if (mPassword == null || mPassword.length() == 0) {
+ EPasswordCheckException e = new EPasswordCheckException(
+ "Empty Password");
+
+ return e.toString();
+ } else if (mPassword.length() < MIN_LEN) {
+ EPasswordCheckException e = new EPasswordCheckException(
+ "Minimium Length is " + MIN_LEN);
+
+ return e.toString();
+ }
+ return null;
+ }
+
+ /**
+ * Returns true if the given password meets the quality requirement;
+ * otherwise returns false.
+ *
+ * @param mPassword The given password being checked.
+ * @return true if the password meets the quality requirement; otherwise
+ * returns false.
+ */
+ public boolean isGoodPassword(String mPassword) {
+ if (mPassword == null || mPassword.length() == 0) {
+ return false;
+ } else if (mPassword.length() < MIN_LEN) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns a reason if the password doesnt meet the quality requirement.
+ *
+ * @return string as a reason if the password quality requirement is not met.
+ */
+ public String getReason(String mPassword) {
+ if (mPassword == null || mPassword.length() == 0) {
+ EPasswordCheckException e = new EPasswordCheckException(
+ CMS.getUserMessage("CMS_PASSWORD_EMPTY_PASSWORD"));
+
+ return e.toString();
+ } else if (mPassword.length() < MIN_LEN) {
+ EPasswordCheckException e = new EPasswordCheckException(
+ CMS.getUserMessage("CMS_PASSWORD_INVALID_LEN", "" + MIN_LEN));
+
+ return e.toString();
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/APolicyRule.java b/base/server/cms/src/com/netscape/cms/policy/APolicyRule.java
new file mode 100644
index 000000000..8ed943503
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/APolicyRule.java
@@ -0,0 +1,363 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy;
+
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.KeyIdentifier;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IExpression;
+import com.netscape.certsrv.policy.IPolicyRule;
+import com.netscape.certsrv.request.AgentApprovals;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+
+/**
+ * The abstract policy rule that concrete implementations will
+ * extend.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public abstract class APolicyRule implements IPolicyRule {
+ protected String NAME = null;
+ protected String DESC = null;
+ protected IExpression mFilterExp = null;
+ protected String mInstanceName = null;
+ protected ILogger mLogger = CMS.getLogger();
+
+ public APolicyRule() {
+ }
+
+ /**
+ * Initializes the policy rule.
+ * <P>
+ *
+ * @param config The config store reference
+ */
+ public abstract void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException;
+
+ /**
+ * Gets the description for this policy rule.
+ * <P>
+ *
+ * @return The Description for this rule.
+ */
+ public String getDescription() {
+ return DESC;
+ }
+
+ /**
+ * Sets a predicate expression for rule matching.
+ * <P>
+ *
+ * @param exp The predicate expression for the rule.
+ */
+ public void setPredicate(IExpression exp) {
+ mFilterExp = exp;
+ }
+
+ /**
+ * Returns the predicate expression for the rule.
+ * <P>
+ *
+ * @return The predicate expression for the rule.
+ */
+ public IExpression getPredicate() {
+ return mFilterExp;
+ }
+
+ /**
+ * Returns the name of the policy rule.
+ * <P>
+ *
+ * @return The name of the policy class.
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /**
+ * Sets the instance name for a policy rule.
+ * <P>
+ *
+ * @param instanceName The name of the rule instance.
+ */
+ public void setInstanceName(String instanceName) {
+ mInstanceName = instanceName;
+ }
+
+ /**
+ * Returns the name of the policy rule instance.
+ * <P>
+ *
+ * @return The name of the policy rule instance if set, else
+ * the name of the rule class.
+ */
+ public String getInstanceName() {
+ return mInstanceName != null ? mInstanceName : NAME;
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public abstract PolicyResult apply(IRequest req);
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public abstract Vector<String> getInstanceParams();
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public abstract Vector<String> getDefaultParams();
+
+ public void setError(IRequest req, String format, Object[] params) {
+ setPolicyException(req, format, params);
+ }
+
+ public void setError(IRequest req, String format, String arg1,
+ String arg2) {
+ Object[] np = new Object[2];
+
+ np[0] = arg1;
+ np[1] = arg2;
+ setPolicyException(req, format, np);
+ }
+
+ public void setError(IRequest req, String format, String arg) {
+ Object[] np = new Object[1];
+
+ np[0] = arg;
+ setPolicyException(req, format, np);
+ }
+
+ public void setPolicyException(IRequest req, EBaseException ex) {
+ Vector<String> ev = req.getExtDataInStringVector(IRequest.ERRORS);
+ if (ev == null) {
+ ev = new Vector<String>();
+ }
+ ev.addElement(ex.toString());
+ req.setExtData(IRequest.ERRORS, ev);
+
+ }
+
+ /**
+ * determines whether a DEFERRED policy result should be returned
+ * by checking the contents of the AgentApprovals attribute. This
+ * call should be used by policy modules instead of returning
+ * PolicyResult.DEFERRED directly.
+ * <p>
+ */
+ protected PolicyResult deferred(IRequest req) {
+ // Try to find an agent approval
+ AgentApprovals aa = AgentApprovals.fromStringVector(
+ req.getExtDataInStringVector(AgentApprovals.class.getName()));
+
+ // Any approvals causes success
+ if (aa != null && aa.elements().hasMoreElements()) {
+ return PolicyResult.ACCEPTED;
+ } else {
+ return PolicyResult.DEFERRED;
+ }
+ }
+
+ /**
+ * request has previously been approved by an agent
+ */
+ protected boolean agentApproved(IRequest req) {
+ // Try to find an agent approval
+ AgentApprovals aa = AgentApprovals.fromStringVector(
+ req.getExtDataInStringVector(AgentApprovals.class.getName()));
+
+ // Any approvals causes success
+ if (aa != null && aa.elements().hasMoreElements()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public void setPolicyException(IRequest req, String format,
+ Object[] params) {
+ if (format == null)
+ return;
+
+ EPolicyException ex;
+
+ if (params == null)
+ ex = new EPolicyException(format);
+ else
+ ex = new EPolicyException(format, params);
+
+ Vector<String> ev = req.getExtDataInStringVector(IRequest.ERRORS);
+ if (ev == null) {
+ ev = new Vector<String>();
+ }
+ ev.addElement(ex.toString());
+ req.setExtData(IRequest.ERRORS, ev);
+ }
+
+ /**
+ * log a message for this policy rule.
+ */
+ protected void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, level,
+ "APolicyRule " + NAME + ": " + msg);
+ }
+
+ public static KeyIdentifier createKeyIdentifier(X509Key key)
+ throws NoSuchAlgorithmException, InvalidKeyException {
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+
+ md.update(key.getEncoded());
+ return new KeyIdentifier(md.digest());
+ }
+
+ /**
+ * Form a byte array of octet string key identifier from the sha-1 hash of
+ * the Subject Public Key INFO. (including algorithm ID, etc.)
+ * <p>
+ *
+ * @param certInfo cert info of the certificate.
+ * @return A Key identifier with the sha-1 hash of subject public key.
+ */
+ protected KeyIdentifier formSpkiSHA1KeyId(X509CertInfo certInfo)
+ throws EBaseException {
+ KeyIdentifier keyId = null;
+
+ try {
+ CertificateX509Key certKey =
+ (CertificateX509Key) certInfo.get(X509CertInfo.KEY);
+
+ if (certKey == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_MISSING_KEY_1", ""));
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_MISSING_KEY", NAME));
+ }
+ X509Key key = (X509Key) certKey.get(CertificateX509Key.KEY);
+
+ if (key == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_MISSING_KEY_1", ""));
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_MISSING_KEY", NAME));
+ }
+ keyId = createKeyIdentifier(key);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_SUBJECT_KEY_ID_1", NAME));
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_SUBJECT_KEY_ID_ERROR", NAME));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_SUBJECT_KEY_ID_1", NAME));
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_SUBJECT_KEY_ID_ERROR", NAME));
+ } catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_SUBJECT_KEY_ID_1", NAME));
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_SUBJECT_KEY_ID_ERROR", NAME));
+ } catch (InvalidKeyException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_SUBJECT_KEY_ID_1", NAME));
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_SUBJECT_KEY_ID_ERROR", NAME));
+ }
+ return keyId;
+ }
+
+ /**
+ * Form a byte array of octet string key identifier from the sha-1 hash of
+ * the Subject Public Key BIT STRING.
+ * <p>
+ *
+ * @param certInfo cert info of the certificate.
+ * @return A Key identifier with the sha-1 hash of subject public key.
+ */
+ protected KeyIdentifier formSHA1KeyId(X509CertInfo certInfo)
+ throws EBaseException {
+ KeyIdentifier keyId = null;
+
+ try {
+ CertificateX509Key certKey =
+ (CertificateX509Key) certInfo.get(X509CertInfo.KEY);
+
+ if (certKey == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_MISSING_KEY_1", ""));
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_MISSING_KEY", NAME));
+ }
+ X509Key key = (X509Key) certKey.get(CertificateX509Key.KEY);
+
+ if (key == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_MISSING_KEY_1", ""));
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_MISSING_KEY", NAME));
+ }
+ byte[] rawKey = key.getKey();
+
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+
+ md.update(rawKey);
+ keyId = new KeyIdentifier(md.digest());
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_SUBJECT_KEY_ID_1", NAME));
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_SUBJECT_KEY_ID_ERROR", NAME));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_SUBJECT_KEY_ID_1", NAME));
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_SUBJECT_KEY_ID_ERROR", NAME));
+ } catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_SUBJECT_KEY_ID_1", NAME));
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_SUBJECT_KEY_ID_ERROR", NAME));
+ }
+ return keyId;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/AgentPolicy.java b/base/server/cms/src/com/netscape/cms/policy/constraints/AgentPolicy.java
new file mode 100644
index 000000000..2129f0f00
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/AgentPolicy.java
@@ -0,0 +1,161 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.AgentApprovals;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * AgentPolicy is an enrollment policy wraps another policy module.
+ * Requests are sent first to the contained module, but if the
+ * policy indicates that the request should be deferred, a check
+ * for agent approvals is done. If any are found, the request
+ * is approved.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class AgentPolicy extends APolicyRule
+ implements IEnrollmentPolicy {
+ public AgentPolicy() {
+ NAME = "AgentPolicy";
+ DESC = "Agent Approval Policy";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ra.Policy.rule.<ruleName>.implName=AgentPolicy ra.Policy.rule.<ruleName>.enable=true
+ * ra.Policy.rule.<ruleName>.predicate= ou == engineering AND o == netscape.com ra.Policy.rule.<ruleName>.class=xxxx
+ * ra.Policy.rule.<ruleName>.params.*
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EPolicyException {
+
+ // Create subordinate object
+ String className = config.get("class");
+
+ System.err.println("Creating agent policy with class " + className);
+ if (className != null) {
+ IConfigStore substore = config.getSubStore("params");
+
+ try {
+ @SuppressWarnings("unchecked")
+ Class<APolicyRule> c = (Class<APolicyRule>) Class.forName(className);
+
+ Object o = c.newInstance();
+
+ if (!(o instanceof APolicyRule)) {
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CLASS",
+ getInstanceName(), className));
+ }
+
+ APolicyRule pr = (APolicyRule) o;
+
+ pr.init(owner, substore);
+ mPolicy = pr;
+ } catch (EPolicyException e) {
+ System.err.println("Agent Policy Error: " + e);
+ throw e;
+ } catch (Exception e) {
+ System.err.println("Agent Policy Error: " + e);
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_LOADING_POLICY_ERROR",
+ getInstanceName(), className));
+ }
+ }
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+
+ // The default is to require manual approval for everything
+ PolicyResult result = PolicyResult.DEFERRED;
+
+ // Give the underlying object a chance
+ if (mPolicy != null) {
+ result = mPolicy.apply(req);
+ System.err.println("Subordinate policy returns " + result);
+ }
+
+ if (result == PolicyResult.DEFERRED) {
+ System.err.println("Checking agent approvals");
+ // Try to find an agent approval
+ AgentApprovals aa = AgentApprovals.fromStringVector(
+ req.getExtDataInStringVector(AgentApprovals.class.getName()));
+
+ //Object o = req.get("agentApprovals");
+
+ // Any approvals causes success
+ if (aa != null && aa.elements().hasMoreElements()) //if (o != null)
+ {
+ System.err.println("Agent approval found");
+ result = PolicyResult.ACCEPTED;
+ }
+ }
+ System.err.println("Agent policy returns " + result);
+ return result;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ return null;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return null;
+ }
+
+ APolicyRule mPolicy = null;
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/AttributePresentConstraints.java b/base/server/cms/src/com/netscape/cms/policy/constraints/AttributePresentConstraints.java
new file mode 100644
index 000000000..e12b8220f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/AttributePresentConstraints.java
@@ -0,0 +1,399 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * This checks if attribute present.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class AttributePresentConstraints extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ protected static final String PROP_ENABLED = "enabled";
+ protected static final String PROP_LDAP = "ldap";
+
+ protected String mName = null;
+ protected String mImplName = null;
+
+ private ILogger mLogger = CMS.getLogger();
+
+ private IConfigStore mConfig = null;
+ private IConfigStore mLdapConfig = null;
+ private ILdapConnFactory mConnFactory = null;
+ private LDAPConnection mCheckAttrLdapConnection = null;
+
+ public AttributePresentConstraints() {
+ DESC = "Rejects request if ldap attribute is not present in the " +
+ "directory.";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String params[] = {
+ PROP_ATTR + ";string,required;Ldap attribute to check presence of (default " +
+ DEF_ATTR + ")",
+ PROP_VALUE + ";string;if this parameter is non-empty, the attribute must " +
+ "match this value for the request to proceed ",
+ PROP_LDAP_BASE + ";string,required;Base DN to start searching " +
+ "under. If your user's DN is 'uid=jsmith, o=company', you " +
+ "might want to use 'o=company' here",
+ PROP_LDAP_HOST + ";string,required;" +
+ "LDAP host to connect to",
+ PROP_LDAP_PORT + ";number,required;" +
+ "LDAP port number (use 389, or 636 if SSL)",
+ PROP_LDAP_SSL + ";boolean;" +
+ "Use SSL to connect to directory?",
+ PROP_LDAP_VER + ";choice(3,2),required;" +
+ "LDAP protocol version",
+ PROP_LDAP_BIND + ";string;DN to bind as for attribute checking. " +
+ "For example 'CN=Pincheck User'",
+ PROP_LDAP_PW + ";password;Enter password used to bind as " +
+ "the above user",
+ PROP_LDAP_AUTH + ";choice(BasicAuth,SslClientAuth),required;" +
+ "How to bind to the directory",
+ PROP_LDAP_CERT + ";string;If you want to use " +
+ "SSL client auth to the directory, set the client " +
+ "cert nickname here",
+ PROP_LDAP_BASE + ";string,required;Base DN to start searching " +
+ "under. If your user's DN is 'uid=jsmith, o=company', you " +
+ "might want to use 'o=company' here",
+ PROP_LDAP_MINC + ";number;number of connections " +
+ "to keep open to directory server. Default " + DEF_LDAP_MINC,
+ PROP_LDAP_MAXC + ";number;when needed, connection " +
+ "pool can grow to this many (multiplexed) connections. Default " + DEF_LDAP_MAXC,
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-pinpresent",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";" + DESC + " This plugin can be used to " +
+ "check the presence (and, optionally, the value) of any LDAP " +
+ "attribute for the user. "
+ };
+
+ return params;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public String getImplName() {
+ return mImplName;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void shutdown() {
+ }
+
+ // Parameters
+
+ protected static final String PROP_LDAP_HOST = "ldap.ldapconn.host";
+ protected static final String DEF_LDAP_HOST = "localhost";
+
+ protected static final String PROP_LDAP_PORT = "ldap.ldapconn.port";
+ protected static final Integer DEF_LDAP_PORT = Integer.valueOf(389);
+
+ protected static final String PROP_LDAP_SSL = "ldap.ldapconn.secureConn";
+ protected static final Boolean DEF_LDAP_SSL = Boolean.FALSE;
+
+ protected static final String PROP_LDAP_VER = "ldap.ldapconn.version";
+ protected static final Integer DEF_LDAP_VER = Integer.valueOf(3);
+
+ protected static final String PROP_LDAP_BIND = "ldap.ldapauth.bindDN";
+ protected static final String DEF_LDAP_BIND = "CN=Directory Manager";
+
+ protected static final String PROP_LDAP_PW = "ldap.ldapauth.bindPWPrompt";
+ protected static final String DEF_LDAP_PW = "";
+
+ protected static final String PROP_LDAP_CERT = "ldap.ldapauth.clientCertNickname";
+ protected static final String DEF_LDAP_CERT = "";
+
+ protected static final String PROP_LDAP_AUTH = "ldap.ldapauth.authtype";
+ protected static final String DEF_LDAP_AUTH = "BasicAuth";
+
+ protected static final String PROP_LDAP_BASE = "ldap.ldapconn.basedn";
+ protected static final String DEF_LDAP_BASE = "";
+
+ protected static final String PROP_LDAP_MINC = "ldap.ldapconn.minConns";
+ protected static final Integer DEF_LDAP_MINC = Integer.valueOf(1);
+
+ protected static final String PROP_LDAP_MAXC = "ldap.ldapconn.maxConns";
+ protected static final Integer DEF_LDAP_MAXC = Integer.valueOf(5);
+
+ protected static final String PROP_ATTR = "attribute";
+ protected static final String DEF_ATTR = "pin";
+
+ protected static final String PROP_VALUE = "value";
+ protected static final String DEF_VALUE = "";
+
+ protected static Vector<String> mParamNames;
+ protected static Hashtable<String, Object> mParamDefault;
+ protected Hashtable<String, Object> mParamValue = null;
+
+ static {
+ mParamNames = new Vector<String>();
+ mParamDefault = new Hashtable<String, Object>();
+ addParam(PROP_LDAP_HOST, DEF_LDAP_HOST);
+ addParam(PROP_LDAP_PORT, DEF_LDAP_PORT);
+ addParam(PROP_LDAP_SSL, DEF_LDAP_SSL);
+ addParam(PROP_LDAP_VER, DEF_LDAP_VER);
+ addParam(PROP_LDAP_BIND, DEF_LDAP_BIND);
+ addParam(PROP_LDAP_PW, DEF_LDAP_PW);
+ addParam(PROP_LDAP_CERT, DEF_LDAP_CERT);
+ addParam(PROP_LDAP_AUTH, DEF_LDAP_AUTH);
+ addParam(PROP_LDAP_BASE, DEF_LDAP_BASE);
+ addParam(PROP_LDAP_MINC, DEF_LDAP_MINC);
+ addParam(PROP_LDAP_MAXC, DEF_LDAP_MAXC);
+ addParam(PROP_ATTR, DEF_ATTR);
+ addParam(PROP_VALUE, DEF_VALUE);
+ };
+
+ protected static void addParam(String name, Object value) {
+ mParamNames.addElement(name);
+ mParamDefault.put(name, value);
+ }
+
+ protected void getStringConfigParam(IConfigStore config, String paramName) {
+ try {
+ mParamValue.put(
+ paramName, config.getString(paramName, (String) mParamDefault.get(paramName))
+ );
+ } catch (Exception e) {
+ }
+ }
+
+ protected void getIntConfigParam(IConfigStore config, String paramName) {
+ try {
+ mParamValue.put(
+ paramName, Integer.valueOf(
+ config.getInteger(paramName,
+ ((Integer) mParamDefault.get(paramName)).intValue()
+ )
+ )
+ );
+ } catch (Exception e) {
+ }
+ }
+
+ protected void getBooleanConfigParam(IConfigStore config, String paramName) {
+ try {
+ mParamValue.put(
+ paramName, Boolean.valueOf(
+ config.getBoolean(paramName,
+ ((Boolean) mParamDefault.get(paramName)).booleanValue()
+ )
+ )
+ );
+ } catch (Exception e) {
+ }
+ }
+
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+
+ mParamValue = new Hashtable<String, Object>();
+
+ getStringConfigParam(mConfig, PROP_LDAP_HOST);
+ getIntConfigParam(mConfig, PROP_LDAP_PORT);
+ getBooleanConfigParam(mConfig, PROP_LDAP_SSL);
+ getIntConfigParam(mConfig, PROP_LDAP_VER);
+ getStringConfigParam(mConfig, PROP_LDAP_BIND);
+ getStringConfigParam(mConfig, PROP_LDAP_PW);
+ getStringConfigParam(mConfig, PROP_LDAP_CERT);
+ getStringConfigParam(mConfig, PROP_LDAP_AUTH);
+ getStringConfigParam(mConfig, PROP_LDAP_BASE);
+ getIntConfigParam(mConfig, PROP_LDAP_MINC);
+ getIntConfigParam(mConfig, PROP_LDAP_MAXC);
+ getStringConfigParam(mConfig, PROP_ATTR);
+ getStringConfigParam(mConfig, PROP_VALUE);
+
+ mLdapConfig = mConfig.getSubStore(PROP_LDAP);
+
+ mConnFactory = CMS.getLdapBoundConnFactory();
+ mConnFactory.init(mLdapConfig);
+ mCheckAttrLdapConnection = mConnFactory.getConn();
+
+ }
+
+ public PolicyResult apply(IRequest r) {
+ PolicyResult res = PolicyResult.ACCEPTED;
+
+ String requestType = r.getRequestType();
+
+ if (requestType.equals(IRequest.ENROLLMENT_REQUEST) ||
+ requestType.equals(IRequest.RENEWAL_REQUEST)) {
+
+ String uid = r.getExtDataInString(IRequest.HTTP_PARAMS, "uid");
+
+ if (uid == null) {
+ log(ILogger.LL_INFO, "did not find UID parameter in request " + r.getRequestId());
+ setError(r, CMS.getUserMessage("CMS_POLICY_PIN_UNAUTHORIZED"), "");
+ return PolicyResult.REJECTED;
+ }
+
+ String userdn = null;
+
+ try {
+ String[] attrs = { (String) mParamValue.get(PROP_ATTR) };
+ LDAPSearchResults searchResult =
+ mCheckAttrLdapConnection.search((String) mParamValue.get(PROP_LDAP_BASE),
+ LDAPv2.SCOPE_SUB, "(uid=" + uid + ")", attrs, false);
+
+ if (!searchResult.hasMoreElements()) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_NO_PIN_FOUND", uid));
+ setError(r, CMS.getUserMessage("CMS_POLICY_PIN_UNAUTHORIZED"), "");
+ return PolicyResult.REJECTED;
+ }
+
+ LDAPEntry entry = (LDAPEntry) searchResult.nextElement();
+
+ userdn = entry.getDN();
+
+ LDAPAttribute attr = entry.getAttribute((String) mParamValue.get(PROP_ATTR));
+
+ /* if attribute not present, reject the request */
+ if (attr == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_NO_PIN_FOUND", userdn));
+ setError(r, CMS.getUserMessage("CMS_POLICY_PIN_UNAUTHORIZED"), "");
+ return PolicyResult.REJECTED;
+ }
+ String acceptedValue = ((String) mParamValue.get(PROP_VALUE));
+
+ if (!acceptedValue.equals("")) {
+ int matches = 0;
+
+ String[] values = attr.getStringValueArray();
+
+ for (int i = 0; i < values.length; i++) {
+ if (values[i].equals(acceptedValue)) {
+ matches++;
+ }
+ }
+ if (matches == 0) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_NO_PIN_FOUND", userdn));
+ setError(r, CMS.getUserMessage("CMS_POLICY_PIN_UNAUTHORIZED"), "");
+ return PolicyResult.REJECTED;
+ }
+ }
+
+ CMS.debug("AttributePresentConstraints: Attribute is present for user: \"" + userdn + "\"");
+
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_PIN_UNAUTHORIZED"));
+ setError(r, CMS.getUserMessage("CMS_POLICY_PIN_UNAUTHORIZED"), "");
+ return PolicyResult.REJECTED;
+ }
+
+ }
+ return res;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> params = new Vector<String>();
+
+ Enumeration<String> e = mParamNames.elements();
+
+ while (e.hasMoreElements()) {
+ try {
+ String paramName = e.nextElement();
+ String paramValue = mParamValue.get(paramName).toString();
+ String temp = paramName + "=" + paramValue;
+
+ params.addElement(temp);
+ } catch (Exception ex) {
+ }
+ }
+
+ return params;
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> params = new Vector<String>();
+
+ Enumeration<String> e = mParamNames.elements();
+
+ while (e.hasMoreElements()) {
+ try {
+ String paramName = e.nextElement();
+ String paramValue = mParamDefault.get(paramName).toString();
+ String temp = paramName + "=" + paramValue;
+
+ params.addElement(temp);
+ } catch (Exception ex) {
+ }
+ }
+
+ return params;
+
+ /*
+ params.addElement("ldap.ldapconn.host=localhost");
+ params.addElement("ldap.ldapconn.port=389");
+ params.addElement("ldap.ldapconn.secureConn=false");
+ params.addElement("ldap.ldapconn.version=3");
+ params.addElement("ldap.ldapauth.bindDN=CN=Directory Manager");
+ params.addElement("ldap.ldapauth.bindPWPrompt=");
+ params.addElement("ldap.ldapauth.clientCertNickname=");
+ params.addElement("ldap.ldapauth.authtype=BasicAuth");
+ params.addElement("ldap.basedn=");
+ params.addElement("ldap.minConns=1");
+ params.addElement("ldap.maxConns=5");
+ */
+ }
+
+ protected void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, "AttributePresentConstraints: " + msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/DSAKeyConstraints.java b/base/server/cms/src/com/netscape/cms/policy/constraints/DSAKeyConstraints.java
new file mode 100644
index 000000000..9b5fbd152
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/DSAKeyConstraints.java
@@ -0,0 +1,252 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.math.BigInteger;
+import java.security.interfaces.DSAParams;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.provider.DSAPublicKey;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * DSAKeyConstraints policy enforces min and max size of the key.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class DSAKeyConstraints extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ private int mMinSize;
+ private int mMaxSize;
+
+ private final static int INCREMENT = 64;
+ private final static int DEF_MIN_SIZE = 512;
+ private final static int DEF_MAX_SIZE = 1024;
+
+ private final static String DSA = "DSA";
+ private final static String PROP_MIN_SIZE = "minSize";
+ private final static String PROP_MAX_SIZE = "maxSize";
+
+ private final static Vector<String> defConfParams = new Vector<String>();
+
+ private IConfigStore mConfig = null;
+
+ static {
+ defConfParams.addElement(PROP_MIN_SIZE + "=" + DEF_MIN_SIZE);
+ defConfParams.addElement(PROP_MAX_SIZE + "=" + DEF_MAX_SIZE);
+ }
+
+ public DSAKeyConstraints() {
+ NAME = "DSAKeyConstraints";
+ DESC = "Enforces DSA Key Constraints.";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_MIN_SIZE + ";number;Minimum key size",
+ PROP_MAX_SIZE + ";number;Maximum key size",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-dsakeyconstraints",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Rejects request if DSA key size is out of range"
+ };
+
+ return params;
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries probably are of the form ra.Policy.rule.<ruleName>.implName=DSAKeyConstraints
+ * ra.Policy.rule.<ruleName>.enable=true ra.Policy.rule.<ruleName>.minSize=512
+ * ra.Policy.rule.<ruleName>.maxSize=1024 ra.Policy.rule.<ruleName>.predicate= ou == engineering AND o ==
+ * netscape.com
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EPolicyException {
+
+ // Get Min and Max sizes
+ mConfig = config;
+
+ try {
+ mMinSize = config.getInteger(PROP_MIN_SIZE, DEF_MIN_SIZE);
+ mMaxSize = config.getInteger(PROP_MAX_SIZE, DEF_MAX_SIZE);
+
+ if (mMaxSize > DEF_MAX_SIZE) {
+ String msg = "cannot be more than " + DEF_MAX_SIZE;
+
+ log(ILogger.LL_FAILURE, PROP_MAX_SIZE + " " + msg);
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ PROP_MAX_SIZE, msg));
+ }
+ if (mMinSize < DEF_MIN_SIZE) {
+ String msg = "cannot be less than " + DEF_MIN_SIZE;
+
+ log(ILogger.LL_FAILURE, PROP_MIN_SIZE + " " + msg);
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ PROP_MIN_SIZE, msg));
+ }
+ if (mMaxSize % INCREMENT != 0) {
+ String msg = "must be in increments of " + INCREMENT;
+
+ log(ILogger.LL_FAILURE, PROP_MAX_SIZE + " " + msg);
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ PROP_MIN_SIZE, msg));
+ }
+ if (mMaxSize % INCREMENT != 0) {
+ String msg = "must be in increments of " + INCREMENT;
+
+ log(ILogger.LL_FAILURE, PROP_MIN_SIZE + " " + msg);
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ PROP_MIN_SIZE, msg));
+ }
+
+ config.putInteger(PROP_MIN_SIZE, mMinSize);
+ config.putInteger(PROP_MAX_SIZE, mMaxSize);
+
+ } catch (Exception e) {
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CONFIG", getInstanceName(), e.toString()));
+ }
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+
+ PolicyResult result = PolicyResult.ACCEPTED;
+
+ try {
+ // Get the certificate info from the request
+ X509CertInfo ci[] =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ // There should be a certificate info set.
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO", NAME), "");
+ return PolicyResult.REJECTED;
+ }
+
+ // Else check if the key size(s) are within the limit.
+ for (int i = 0; i < ci.length; i++) {
+ CertificateX509Key certKey = (CertificateX509Key)
+ ci[i].get(X509CertInfo.KEY);
+ X509Key key = (X509Key) certKey.get(CertificateX509Key.KEY);
+ String alg = key.getAlgorithmId().toString();
+
+ if (!alg.equalsIgnoreCase(DSA))
+ continue;
+
+ // Check DSAKey parameters.
+ // size refers to the p parameter.
+ DSAPublicKey dsaKey = new DSAPublicKey(key.getEncoded());
+ DSAParams keyParams = dsaKey.getParams();
+
+ if (keyParams == null) {
+ // key parameters could not be parsed.
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_NO_KEY_PARAMS", getInstanceName(), String.valueOf(i + 1)),
+ "");
+ return PolicyResult.REJECTED;
+ }
+ BigInteger p = keyParams.getP();
+ int len = p.bitLength();
+
+ if (len < mMinSize || len > mMaxSize ||
+ (len % INCREMENT) != 0) {
+ String[] parms = new String[] {
+ getInstanceName(),
+ String.valueOf(len),
+ String.valueOf(mMinSize),
+ String.valueOf(mMaxSize),
+ String.valueOf(INCREMENT) };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_KEY_SIZE_VIOLATION_1", parms), "");
+ return PolicyResult.REJECTED;
+ }
+ }
+ } catch (Exception e) {
+ // e.printStackTrace();
+ String[] params = { getInstanceName(), e.toString() };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", params), "");
+ result = PolicyResult.REJECTED;
+ }
+ return result;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> confParams = new Vector<String>();
+
+ try {
+ confParams.addElement(PROP_MIN_SIZE + "=" + mConfig.getInteger(PROP_MIN_SIZE, DEF_MIN_SIZE));
+ confParams.addElement(PROP_MAX_SIZE + "=" + mConfig.getInteger(PROP_MAX_SIZE, DEF_MAX_SIZE));
+ } catch (EBaseException e) {
+ ;
+ }
+ return confParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return defConfParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/DefaultRevocation.java b/base/server/cms/src/com/netscape/cms/policy/constraints/DefaultRevocation.java
new file mode 100644
index 000000000..fecb59049
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/DefaultRevocation.java
@@ -0,0 +1,104 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.util.Locale;
+import java.util.Vector;
+
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IRevocationPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * This is the default revocation policy. Currently this does
+ * nothing. We can later add checks like whether or not to
+ * revoke expired certs ..etc here.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class DefaultRevocation extends APolicyRule
+ implements IRevocationPolicy, IExtendedPluginInfo {
+ public DefaultRevocation() {
+ NAME = "DefaultRevocation";
+ DESC = "Default Revocation Policy";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ra.Policy.rule.<ruleName>.implName=DefaultRevocation ra.Policy.rule.<ruleName>.enable=true
+ * ra.Policy.rule.<ruleName>.predicate= ou == engineering AND o == netscape.com
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EPolicyException {
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ return PolicyResult.ACCEPTED;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ return null;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return null;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ IExtendedPluginInfo.HELP_TOKEN + ";configuration-policyrules-defaultrevocation"
+ };
+
+ return params;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/IssuerConstraints.java b/base/server/cms/src/com/netscape/cms/policy/constraints/IssuerConstraints.java
new file mode 100644
index 000000000..efd306bf3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/IssuerConstraints.java
@@ -0,0 +1,215 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * IssuerConstraints is a rule for restricting the issuers of the
+ * certificates used for certificate-based enrollments.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$ $Date$
+ */
+public class IssuerConstraints extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ private final static String PROP_ISSUER_DN = "issuerDN";
+ private static final String CLIENT_ISSUER = "clientIssuer";
+ private X500Name mIssuerDN = null;
+ private String mIssuerDNString;
+
+ /**
+ * checks the issuer of the ssl client-auth cert. Only one issuer
+ * is allowed for now
+ */
+ public IssuerConstraints() {
+ NAME = "IssuerConstraints";
+ DESC = "Checks to see if the Issuer is one allowed";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_ISSUER_DN
+ + ";string;Subject DN of the Issuer. The IssuerDN of the authenticating cert must match what's specified here",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-issuerconstraints",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Rejects the request if the issuer in the certificate is" +
+ "not of the one specified"
+ };
+
+ return params;
+
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EPolicyException {
+ try {
+ mIssuerDNString = config.getString(PROP_ISSUER_DN, null);
+ if ((mIssuerDNString != null) &&
+ !mIssuerDNString.equals("")) {
+ mIssuerDN = new X500Name(mIssuerDNString);
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ NAME + CMS.getLogMessage("CA_GET_ISSUER_NAME_FAILED"));
+
+ String[] params = { getInstanceName(), e.toString() };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CONFIG", params));
+ }
+ CMS.debug(
+ NAME + ": init() done");
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ PolicyResult result = PolicyResult.ACCEPTED;
+
+ if (mIssuerDN == null)
+ return result;
+
+ try {
+ String clientIssuerDN = req.getExtDataInString(CLIENT_ISSUER);
+
+ if (clientIssuerDN != null) {
+ X500Name ci_name = new X500Name(clientIssuerDN);
+
+ if (!ci_name.equals(mIssuerDN)) {
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_INVALID_ISSUER",
+ getInstanceName()), "");
+ result = PolicyResult.REJECTED;
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CA_GET_ISSUER_NAME_FAILED"));
+ CMS.debug(
+ NAME + ": apply() - issuerDN mismatch: client issuerDN = " + clientIssuerDN
+ + "; expected issuerDN = " + mIssuerDNString);
+ }
+ } else {
+
+ // Get the certificate info from the request
+ X509CertInfo certInfo[] =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (certInfo == null) {
+ log(ILogger.LL_FAILURE,
+ NAME + ": apply() - missing certInfo");
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO",
+ getInstanceName()), "");
+ return PolicyResult.REJECTED;
+ }
+
+ for (int i = 0; i < certInfo.length; i++) {
+ String oldIssuer = certInfo[i].get(X509CertInfo.ISSUER).toString();
+
+ if (oldIssuer == null) {
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_CLIENT_ISSUER_NOT_FOUND",
+ getInstanceName()), "");
+ result = PolicyResult.REJECTED;
+ log(ILogger.LL_FAILURE,
+ NAME + ": apply() - client issuerDN not found");
+ }
+ X500Name oi_name = new X500Name(oldIssuer);
+
+ if (!oi_name.equals(mIssuerDN)) {
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_INVALID_ISSUER",
+ getInstanceName()), "");
+ result = PolicyResult.REJECTED;
+ log(ILogger.LL_FAILURE,
+ NAME + ": apply() - cert issuerDN mismatch: client issuerDN = " + oldIssuer
+ + "; expected issuerDN = " + mIssuerDNString);
+ }
+ }
+ }
+ } catch (Exception e) {
+ String params[] = { getInstanceName(), e.toString() };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", params), "");
+ result = PolicyResult.REJECTED;
+ }
+
+ if (result.equals(PolicyResult.ACCEPTED)) {
+ log(ILogger.LL_INFO,
+ NAME + ": apply() - accepted");
+ }
+ return result;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> confParams = new Vector<String>();
+
+ confParams.addElement(PROP_ISSUER_DN + "=" +
+ mIssuerDNString);
+ return confParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> defParams = new Vector<String>();
+
+ defParams.addElement(PROP_ISSUER_DN + "=");
+ return defParams;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/KeyAlgorithmConstraints.java b/base/server/cms/src/com/netscape/cms/policy/constraints/KeyAlgorithmConstraints.java
new file mode 100644
index 000000000..d656ed463
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/KeyAlgorithmConstraints.java
@@ -0,0 +1,225 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * KeyAlgorithmConstraints enforces a constraint that the RA or a CA
+ * honor only the keys generated using one of the permitted algorithms
+ * such as RSA, DSA or DH.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class KeyAlgorithmConstraints extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ private Vector<String> mAlgorithms;
+ private final static String DEF_KEY_ALGORITHM = "RSA,DSA";
+ private final static String PROP_ALGORITHMS = "algorithms";
+ private final static String[] supportedAlgorithms =
+ { "RSA", "DSA", "DH" };
+
+ private final static Vector<String> defConfParams = new Vector<String>();
+
+ static {
+ defConfParams.addElement(PROP_ALGORITHMS + "=" +
+ DEF_KEY_ALGORITHM);
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String params[] = {
+ "algorithms;choice(RSA\\,DSA,RSA,DSA);Certificate's key can be one of these algorithms",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-keyalgorithmconstraints",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Rejects the request if the key in the certificate is " +
+ "not of the type specified"
+ };
+
+ return params;
+ }
+
+ public KeyAlgorithmConstraints() {
+ NAME = "KeyAlgorithmConstraints";
+ DESC = "Enforces Key Algorithm Constraints.";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries probably are of the form ra.Policy.rule.<ruleName>.implName=KeyAlgorithmConstraints
+ * ra.Policy.rule.<ruleName>.algorithms=RSA,DSA ra.Policy.rule.<ruleName>.enable=true
+ * ra.Policy.rule.<ruleName>.predicate=ou==Sales
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EPolicyException {
+
+ mAlgorithms = new Vector<String>();
+
+ if (config == null || config.size() == 0) {
+ mAlgorithms.addElement(DEF_KEY_ALGORITHM);
+ return;
+ }
+
+ // Get Algorithm names
+ String algNames = null;
+
+ try {
+ algNames = config.getString(PROP_ALGORITHMS, null);
+ } catch (Exception e) {
+ String[] params = { getInstanceName(), e.toString() };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CONFIG", params));
+ }
+
+ if (algNames == null) {
+ mAlgorithms.addElement(DEF_KEY_ALGORITHM);
+ return;
+ }
+ StringTokenizer tok = new StringTokenizer(algNames, ",");
+
+ while (tok.hasMoreTokens()) {
+ String alg = tok.nextToken().trim().toUpperCase();
+
+ if (alg.length() == 0)
+ continue;
+ mAlgorithms.addElement(alg);
+ }
+
+ // Check if configured algorithms are supported.
+ for (Enumeration<String> e = mAlgorithms.elements(); e.hasMoreElements();) {
+ int i;
+ String configuredAlg = e.nextElement();
+
+ // See if it is a supported algorithm.
+ for (i = 0; i < supportedAlgorithms.length; i++) {
+ if (configuredAlg.equals(supportedAlgorithms[i]))
+ break;
+ }
+
+ // Did we not find it?
+ if (i == supportedAlgorithms.length)
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_UNSUPPORTED_KEY_ALG",
+ getInstanceName(), configuredAlg));
+ }
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+
+ PolicyResult result = PolicyResult.ACCEPTED;
+
+ try {
+ // Get the certificate info from the request
+ // X509CertInfo certInfo[] = (X509CertInfo[])
+ // req.get(IRequest.CERT_INFO);
+ X509CertInfo certInfo[] = req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ // We need to have a certificate info set
+ if (certInfo == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO",
+ getInstanceName()), "");
+ return PolicyResult.REJECTED;
+ }
+
+ // Else check if the key algorithm is supported.
+ for (int i = 0; i < certInfo.length; i++) {
+ CertificateX509Key certKey = (CertificateX509Key)
+ certInfo[i].get(X509CertInfo.KEY);
+ X509Key key = (X509Key) certKey.get(CertificateX509Key.KEY);
+ String alg = key.getAlgorithmId().getName().toUpperCase();
+
+ if (!mAlgorithms.contains(alg)) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_KEY_ALG_VIOLATION",
+ getInstanceName(), alg), "");
+ result = PolicyResult.REJECTED;
+ }
+ }
+ } catch (Exception e) {
+ String params[] = { getInstanceName(), e.toString() };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR",
+ params), "");
+ result = PolicyResult.REJECTED;
+ }
+ return result;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+ StringBuffer sb = new StringBuffer();
+
+ for (Enumeration<String> e = mAlgorithms.elements(); e.hasMoreElements();) {
+ sb.append(e.nextElement());
+ sb.append(",");
+ }
+ if (sb.length() > 0)
+ sb.setLength(sb.length() - 1);
+ v.addElement(PROP_ALGORITHMS + "=" + sb.toString());
+ return v;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return defConfParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/ManualAuthentication.java b/base/server/cms/src/com/netscape/cms/policy/constraints/ManualAuthentication.java
new file mode 100644
index 000000000..56b96f95f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/ManualAuthentication.java
@@ -0,0 +1,101 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.util.Vector;
+
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * ManualAuthentication is an enrollment policy that queues
+ * all requests for issuing agent's approval if no authentication
+ * is present. The policy rejects a request if any of the auth tokens
+ * indicates authentication failure.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class ManualAuthentication extends APolicyRule
+ implements IEnrollmentPolicy {
+ public ManualAuthentication() {
+ NAME = "ManualAuthentication";
+ DESC = "Manual Authentication Policy";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ra.Policy.rule.<ruleName>.implName=ManualAuthentication ra.Policy.rule.<ruleName>.enable=true
+ * ra.Policy.rule.<ruleName>.predicate= ou == engineering AND o == netscape.com
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EPolicyException {
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ IAuthToken authToken = req.getExtDataInAuthToken(IRequest.AUTH_TOKEN);
+
+ if (authToken == null)
+ return deferred(req);
+
+ return PolicyResult.ACCEPTED;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ return null;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/RSAKeyConstraints.java b/base/server/cms/src/com/netscape/cms/policy/constraints/RSAKeyConstraints.java
new file mode 100644
index 000000000..363856197
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/RSAKeyConstraints.java
@@ -0,0 +1,280 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.security.provider.RSAPublicKey;
+import netscape.security.util.BigInt;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * RSAKeyConstraints policy enforces min and max size of the key.
+ * Optionally checks the exponents.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class RSAKeyConstraints extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ private Vector<BigInt> mExponents;
+ private int mMinSize;
+ private int mMaxSize;
+
+ private final static int DEF_MIN_SIZE = 512;
+ private final static int DEF_MAX_SIZE = 2048;
+ private final static String PROP_MIN_SIZE = "minSize";
+ private final static String PROP_MAX_SIZE = "maxSize";
+ private final static String PROP_EXPONENTS = "exponents";
+ private final static String RSA = "RSA";
+
+ private final static Vector<String> defConfParams = new Vector<String>();
+
+ static {
+ defConfParams.addElement(PROP_MIN_SIZE + "=" + DEF_MIN_SIZE);
+ defConfParams.addElement(PROP_MAX_SIZE + "=" + DEF_MAX_SIZE);
+ defConfParams.addElement(PROP_EXPONENTS + "=" + " ");
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_MIN_SIZE + ";number;Minimum size of user's RSA key (bits)",
+ PROP_MAX_SIZE + ";number;Maximum size of user's RSA key (bits)",
+ PROP_EXPONENTS + ";string;Comma-separated list of permissible exponents",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-rsakeyconstraints",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Reject request if RSA key length is not within the " +
+ "specified constraints"
+ };
+
+ return params;
+ }
+
+ public RSAKeyConstraints() {
+ NAME = "RSAKeyConstraints";
+ DESC = "Enforces RSA Key Constraints.";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries probably are of the form:
+ *
+ * ra.Policy.rule.<ruleName>.implName=RSAKeyConstraints ra.Policy.rule.<ruleName>.enable=true
+ * ra.Policy.rule.<ruleName>.minSize=512 ra.Policy.rule.<ruleName>.maxSize=2048
+ * ra.Policy.rule.<ruleName>.predicate=ou==Marketing
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+
+ if (config == null || config.size() == 0)
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_MISSING_POLICY_CONFIG",
+ getInstanceName()));
+ String exponents = null;
+
+ // Get Min and Max sizes
+ mMinSize = config.getInteger(PROP_MIN_SIZE, DEF_MIN_SIZE);
+ mMaxSize = config.getInteger(PROP_MAX_SIZE, DEF_MAX_SIZE);
+
+ if (mMinSize <= 0)
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_MUST_BE_POSITIVE_NUMBER", PROP_MIN_SIZE));
+ if (mMaxSize <= 0)
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_MUST_BE_POSITIVE_NUMBER", PROP_MAX_SIZE));
+
+ if (mMinSize > mMaxSize)
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_A_GREATER_THAN_EQUAL_B", PROP_MIN_SIZE, PROP_MAX_SIZE));
+
+ mExponents = new Vector<BigInt>();
+
+ // Get exponents
+ exponents = config.getString(PROP_EXPONENTS, null);
+
+ if (exponents != null) {
+ StringTokenizer tok = new StringTokenizer(exponents, ",");
+
+ try {
+ while (tok.hasMoreTokens()) {
+ String exp = tok.nextToken().trim();
+
+ mExponents.addElement(new BigInt(Integer.parseInt(exp)));
+ }
+ } catch (Exception e) {
+ // e.printStackTrace();
+ String[] params = { getInstanceName(), exponents,
+ PROP_EXPONENTS };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_CONFIG_PARAM", params));
+ }
+ }
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+
+ PolicyResult result = PolicyResult.ACCEPTED;
+
+ try {
+ // Get the certificate info from the request
+ X509CertInfo certInfo[] =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ // There should be a certificate info set.
+ if (certInfo == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO",
+ getInstanceName()), "");
+ return PolicyResult.REJECTED;
+ }
+
+ // Else check if the key size(s) are within the limit.
+ for (int i = 0; i < certInfo.length; i++) {
+ CertificateX509Key certKey = (CertificateX509Key)
+ certInfo[i].get(X509CertInfo.KEY);
+ X509Key key = (X509Key) certKey.get(CertificateX509Key.KEY);
+ String alg = key.getAlgorithmId().toString();
+
+ if (!alg.equalsIgnoreCase(RSA))
+ continue;
+ X509Key newkey = null;
+
+ try {
+ newkey = new X509Key(AlgorithmId.get("RSA"),
+ key.getKey());
+ } catch (Exception e) {
+ CMS.debug("RSAKeyConstraints::apply() - "
+ + "Exception=" + e.toString());
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_KEY_SIZE_VIOLATION",
+ getInstanceName()),
+ "");
+ return PolicyResult.REJECTED;
+ }
+ RSAPublicKey rsaKey = new RSAPublicKey(newkey.getEncoded());
+ int keySize = rsaKey.getKeySize();
+
+ if (keySize < mMinSize || keySize > mMaxSize) {
+ String[] params = { getInstanceName(),
+ String.valueOf(keySize),
+ String.valueOf(mMinSize),
+ String.valueOf(mMaxSize) };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_KEY_SIZE_VIOLATION",
+ params), "");
+ result = PolicyResult.REJECTED;
+ }
+
+ // If the exponents are configured, see if the key's
+ // exponent is a configured one.
+ if (mExponents.size() > 0) {
+ BigInt exp = rsaKey.getPublicExponent();
+
+ if (!mExponents.contains(exp)) {
+ StringBuffer sb = new StringBuffer();
+
+ for (Enumeration<BigInt> e = mExponents.elements(); e.hasMoreElements();) {
+ BigInt bi = e.nextElement();
+
+ sb.append(bi.toBigInteger().toString());
+ sb.append(" ");
+ }
+ String[] params = { getInstanceName(),
+ exp.toBigInteger().toString(), new String(sb) };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_EXPONENT_VIOLATION", params), "");
+ result = PolicyResult.REJECTED;
+ }
+ }
+ }
+ } catch (Exception e) {
+ // e.printStackTrace();
+ String params[] = { getInstanceName(), e.toString() };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", params), "");
+ result = PolicyResult.REJECTED;
+ }
+ return result;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> confParams = new Vector<String>();
+
+ confParams.addElement(PROP_MIN_SIZE + "=" + mMinSize);
+ confParams.addElement(PROP_MAX_SIZE + "=" + mMaxSize);
+ StringBuffer sb = new StringBuffer();
+
+ for (Enumeration<BigInt> e = mExponents.elements(); e.hasMoreElements();) {
+ sb.append(e.nextElement().toInt());
+ sb.append(",");
+ }
+ if (sb.length() > 0)
+ sb.setLength(sb.length() - 1);
+ confParams.addElement(PROP_EXPONENTS + "=" + sb.toString());
+ return confParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return defConfParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/RenewalConstraints.java b/base/server/cms/src/com/netscape/cms/policy/constraints/RenewalConstraints.java
new file mode 100644
index 000000000..3ff977df5
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/RenewalConstraints.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IRenewalPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Whether to allow renewal of an expired cert.
+ *
+ * @version $Revision$, $Date$
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class RenewalConstraints extends APolicyRule
+ implements IRenewalPolicy, IExtendedPluginInfo {
+
+ private static final String PROP_ALLOW_EXPIRED_CERTS = "allowExpiredCerts";
+ private static final String PROP_RENEWAL_NOT_AFTER = "renewalNotAfter";
+
+ private boolean mAllowExpiredCerts = true;
+ private long mRenewalNotAfter = 0;
+
+ public final static int DEF_RENEWAL_NOT_AFTER = 30;
+ public final static long DAYS_TO_MS_FACTOR = 24L * 3600 * 1000;
+
+ private final static Vector<String> defConfParams = new Vector<String>();
+ static {
+ defConfParams.addElement(PROP_ALLOW_EXPIRED_CERTS + "=" + true);
+ defConfParams.addElement(PROP_RENEWAL_NOT_AFTER + "=" +
+ DEF_RENEWAL_NOT_AFTER);
+ }
+
+ public RenewalConstraints() {
+ NAME = "RenewalConstraints";
+ DESC = "Whether to allow renewal of expired certs.";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_ALLOW_EXPIRED_CERTS + ";boolean;Allow a user to renew an already-expired certificate",
+ PROP_RENEWAL_NOT_AFTER
+ + ";number;Number of days since certificate expiry after which renewal request would be rejected",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-renewalconstraints",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Permit administrator to decide policy on whether to " +
+ "permit renewals for already-expired certificates"
+ };
+
+ return params;
+
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries probably are of the form:
+ *
+ * ra.Policy.rule.<ruleName>.implName=ValidityConstraints ra.Policy.rule.<ruleName>.enable=true
+ * ra.Policy.rule.<ruleName>.allowExpiredCerts=true
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EPolicyException {
+ // Get min and max validity in days and configure them.
+ try {
+ mAllowExpiredCerts =
+ config.getBoolean(PROP_ALLOW_EXPIRED_CERTS, true);
+ String val = config.getString(PROP_RENEWAL_NOT_AFTER, null);
+
+ if (val == null)
+ mRenewalNotAfter = DEF_RENEWAL_NOT_AFTER * DAYS_TO_MS_FACTOR;
+ else {
+ mRenewalNotAfter = Long.parseLong(val) * DAYS_TO_MS_FACTOR;
+ }
+
+ } catch (EBaseException e) {
+ // never happen.
+ }
+
+ CMS.debug("RenewalConstraints: allow expired certs " + mAllowExpiredCerts);
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ PolicyResult result = PolicyResult.ACCEPTED;
+
+ try {
+ // Get the certificates being renwed.
+ X509CertImpl[] oldCerts =
+ req.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ if (oldCerts == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_OLD_CERT",
+ getInstanceName()), "");
+ return PolicyResult.REJECTED;
+ }
+
+ if (mAllowExpiredCerts) {
+ CMS.debug("checking validity of each cert");
+ // check if each cert to be renewed is expired for more than // allowed days.
+ for (int i = 0; i < oldCerts.length; i++) {
+ X509CertInfo oldCertInfo = (X509CertInfo)
+ oldCerts[i].get(X509CertImpl.NAME + "." +
+ X509CertImpl.INFO);
+ CertificateValidity oldValidity = (CertificateValidity)
+ oldCertInfo.get(X509CertInfo.VALIDITY);
+ Date notAfter = (Date)
+ oldValidity.get(CertificateValidity.NOT_AFTER);
+
+ // Is the Certificate eligible for renewal ?
+
+ Date now = CMS.getCurrentDate();
+
+ Date renewedNotAfter = new Date(notAfter.getTime() +
+ mRenewalNotAfter);
+
+ CMS.debug("RenewalConstraints: cert " + i + " renewedNotAfter " + renewedNotAfter + " now=" + now);
+
+ if (renewedNotAfter.before(now)) {
+ CMS.debug(
+ "One or more certificates is expired for more than "
+ + (mRenewalNotAfter / DAYS_TO_MS_FACTOR) + " days");
+ String params[] = { getInstanceName(), Long.toString(mRenewalNotAfter / DAYS_TO_MS_FACTOR) };
+
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_CANNOT_RENEW_EXPIRED_CERTS_AFTER_ALLOWED_PERIOD",
+ params), "");
+ return PolicyResult.REJECTED;
+ }
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ CMS.debug("RenewalConstraints: checking validity of each cert");
+ // check if each cert to be renewed is expired.
+ for (int i = 0; i < oldCerts.length; i++) {
+ X509CertInfo oldCertInfo = (X509CertInfo)
+ oldCerts[i].get(
+ X509CertImpl.NAME + "." + X509CertImpl.INFO);
+ CertificateValidity oldValidity = (CertificateValidity)
+ oldCertInfo.get(X509CertInfo.VALIDITY);
+ Date notAfter = (Date)
+ oldValidity.get(CertificateValidity.NOT_AFTER);
+
+ // Is the Certificate still valid?
+ Date now = CMS.getCurrentDate();
+
+ CMS.debug("RenewalConstraints: cert " + i + " notAfter " + notAfter + " now=" + now);
+ if (notAfter.before(now)) {
+ CMS.debug(
+ "RenewalConstraints: One or more certificates is expired.");
+ String params[] = { getInstanceName() };
+
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_CANNOT_RENEW_EXPIRED_CERTS",
+ params), "");
+ result = PolicyResult.REJECTED;
+ break;
+ }
+ }
+
+ } catch (Exception e) {
+ String params[] = { getInstanceName(), e.toString() };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", params), "");
+ result = PolicyResult.REJECTED;
+ }
+ return result;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> confParams = new Vector<String>();
+
+ confParams.addElement(
+ PROP_ALLOW_EXPIRED_CERTS + "=" + mAllowExpiredCerts);
+ confParams.addElement(PROP_RENEWAL_NOT_AFTER + "=" +
+ mRenewalNotAfter / DAYS_TO_MS_FACTOR);
+ return confParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return defConfParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/RenewalValidityConstraints.java b/base/server/cms/src/com/netscape/cms/policy/constraints/RenewalValidityConstraints.java
new file mode 100644
index 000000000..2810fae10
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/RenewalValidityConstraints.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IRenewalPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * RenewalValidityConstraints is a default rule for Certificate
+ * Renewal. This policy enforces the no of days before which a
+ * currently active certificate can be renewed and sets new validity
+ * period for the renewed certificate starting from the the ending
+ * period in the old certificate.
+ *
+ * The main parameters are:
+ *
+ * The renewal leadtime in days: - i.e how many days before the
+ * expiry of the current certificate can one request the renewal.
+ * min and max validity duration.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class RenewalValidityConstraints extends APolicyRule
+ implements IRenewalPolicy, IExtendedPluginInfo {
+ private long mMinValidity;
+ private long mMaxValidity;
+ private long mRenewalInterval;
+
+ private final static String PROP_MIN_VALIDITY = "minValidity";
+ private final static String PROP_MAX_VALIDITY = "maxValidity";
+ private final static String PROP_RENEWAL_INTERVAL = "renewalInterval";
+ public final static int DEF_MIN_VALIDITY = 180;
+ public final static int DEF_MAX_VALIDITY = 730;
+ public final static long DEF_RENEWAL_INTERVAL = 15;
+ public final static long DAYS_TO_MS_FACTOR = 24L * 3600 * 1000;
+ public static final String CERT_HEADER = "-----BEGIN CERTIFICATE-----\n";
+ public static final String CERT_TRAILER = "-----END CERTIFICATE-----\n";
+
+ private final static Vector<String> defConfParams = new Vector<String>();
+
+ static {
+ defConfParams.addElement(PROP_MIN_VALIDITY + "=" +
+ DEF_MIN_VALIDITY);
+ defConfParams.addElement(PROP_MAX_VALIDITY + "=" +
+ DEF_MAX_VALIDITY);
+ defConfParams.addElement(PROP_RENEWAL_INTERVAL + "=" +
+ DEF_RENEWAL_INTERVAL);
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_MIN_VALIDITY
+ + ";number;Specifies the minimum validity period, in days, for renewed certificates.",
+ PROP_MAX_VALIDITY
+ + ";number;Specifies the maximum validity period, in days, for renewed certificates.",
+ PROP_RENEWAL_INTERVAL
+ + ";number;Specifies how many days before its expiration that a certificate can be renewed.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-renewalvalidityconstraints",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Reject renewal request if the certificate is too far " +
+ "before it's expiry date"
+ };
+
+ return params;
+
+ }
+
+ public RenewalValidityConstraints() {
+ NAME = "RenewalValidityConstraints";
+ DESC = "Enforces minimum and maximum validity and renewal interval for certificate renewal.";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries probably are of the form:
+ *
+ * ra.Policy.rule.<ruleName>.implName=ValidityConstraints ra.Policy.rule.<ruleName>.enable=true
+ * ra.Policy.rule.<ruleName>.minValidity=30 ra.Policy.rule.<ruleName>.maxValidity=180
+ * ra.Policy.rule.<ruleName>.renewalInterval=15 ra.Policy.rule.<ruleName>.predicate=ou==Sales
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EPolicyException {
+
+ // Get min and max validity in days and onfigure them.
+ try {
+ String val = config.getString(PROP_MIN_VALIDITY, null);
+
+ if (val == null)
+ mMinValidity = DEF_MIN_VALIDITY * DAYS_TO_MS_FACTOR;
+ else
+ mMinValidity = Long.parseLong(val) * DAYS_TO_MS_FACTOR;
+
+ val = config.getString(PROP_MAX_VALIDITY, null);
+ if (val == null)
+ mMaxValidity = DEF_MAX_VALIDITY * DAYS_TO_MS_FACTOR;
+ else {
+ mMaxValidity = Long.parseLong(val) * DAYS_TO_MS_FACTOR;
+ }
+ val = config.getString(PROP_RENEWAL_INTERVAL, null);
+ if (val == null)
+ mRenewalInterval = DEF_RENEWAL_INTERVAL * DAYS_TO_MS_FACTOR;
+ else {
+ mRenewalInterval = Long.parseLong(val) * DAYS_TO_MS_FACTOR;
+ }
+
+ // minValidity can't be bigger than maxValidity.
+ if (mMinValidity > mMaxValidity) {
+ String params[] = { getInstanceName(),
+ String.valueOf(mMinValidity / DAYS_TO_MS_FACTOR),
+ String.valueOf(mMaxValidity / DAYS_TO_MS_FACTOR) };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_RENEWAL_MIN_MAX", params));
+ }
+
+ // Renewal interval can't be more than maxValidity.
+ if (mRenewalInterval > mMaxValidity) {
+ String params[] = { getInstanceName(),
+ String.valueOf(mRenewalInterval / DAYS_TO_MS_FACTOR),
+ String.valueOf(mMaxValidity / DAYS_TO_MS_FACTOR) };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_RENEWAL_INTERVAL", params));
+ }
+ } catch (Exception e) {
+ // e.printStackTrace();
+ String[] params = { getInstanceName(), e.toString() };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CONFIG", params));
+ }
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+
+ PolicyResult result = PolicyResult.ACCEPTED;
+
+ if (agentApproved(req))
+ return result;
+
+ try {
+ // Get the certificate info from the request
+ X509CertInfo certInfo[] =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ // Get the certificates being renwed.
+ X509CertImpl currentCerts[] =
+ req.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ // Both certificate info and current certs should be set
+ if (certInfo == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO",
+ getInstanceName()), "");
+ return PolicyResult.REJECTED;
+ }
+ if (currentCerts == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_OLD_CERT",
+ getInstanceName()), "");
+ return PolicyResult.REJECTED;
+ }
+ if (certInfo.length != currentCerts.length) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_MISMATCHED_CERTINFO",
+ getInstanceName()), "");
+ return PolicyResult.REJECTED;
+ }
+
+ // Else check if the renewal interval is okay and then
+ // set the validity.
+ for (int i = 0; i < certInfo.length; i++) {
+ X509CertInfo oldCertInfo = (X509CertInfo)
+ currentCerts[i].get(X509CertImpl.NAME +
+ "." + X509CertImpl.INFO);
+ CertificateValidity oldValidity = (CertificateValidity)
+ oldCertInfo.get(X509CertInfo.VALIDITY);
+ Date notAfter = (Date)
+ oldValidity.get(CertificateValidity.NOT_AFTER);
+
+ // Is the Certificate still valid?
+ Date now = CMS.getCurrentDate();
+
+ if (notAfter.after(now)) {
+ // Check if the renewal interval is alright.
+ long interval = notAfter.getTime() - now.getTime();
+
+ if (interval > mRenewalInterval) {
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_LONG_RENEWAL_LEAD_TIME",
+ getInstanceName(),
+ String.valueOf(mRenewalInterval / DAYS_TO_MS_FACTOR)), "");
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_EXISTING_CERT_DETAILS",
+ getInstanceName(),
+ getCertDetails(req, currentCerts[i])), "");
+
+ result = PolicyResult.REJECTED;
+ setDummyValidity(certInfo[i]);
+ continue;
+ }
+ }
+
+ // Else compute new validity.
+ Date renewedNotBef = notAfter;
+ Date renewedNotAfter = new Date(notAfter.getTime() +
+ mMaxValidity);
+
+ // If the new notAfter is within renewal interval days from
+ // today or already expired, set the notBefore to today.
+ if (renewedNotAfter.before(now) ||
+ (renewedNotAfter.getTime() - now.getTime()) <=
+ mRenewalInterval) {
+ renewedNotBef = now;
+ renewedNotAfter = new Date(now.getTime() +
+ mMaxValidity);
+ }
+ CertificateValidity newValidity =
+ new CertificateValidity(renewedNotBef, renewedNotAfter);
+
+ certInfo[i].set(X509CertInfo.VALIDITY, newValidity);
+ }
+ } catch (Exception e) {
+ String params[] = { getInstanceName(), e.toString() };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", params), "");
+ result = PolicyResult.REJECTED;
+ }
+ return result;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> confParams = new Vector<String>();
+
+ confParams.addElement(PROP_MIN_VALIDITY + "=" +
+ mMinValidity / DAYS_TO_MS_FACTOR);
+ confParams.addElement(PROP_MAX_VALIDITY + "=" +
+ mMaxValidity / DAYS_TO_MS_FACTOR);
+ confParams.addElement(PROP_RENEWAL_INTERVAL + "=" +
+ mRenewalInterval / DAYS_TO_MS_FACTOR);
+ return confParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return defConfParams;
+ }
+
+ // Set dummy validity field so the request will serialize properly
+ private void setDummyValidity(X509CertInfo certInfo) {
+ try {
+ certInfo.set(X509CertInfo.VALIDITY,
+ new CertificateValidity(CMS.getCurrentDate(), new Date()));
+ } catch (Exception e) {
+ }
+ }
+
+ private String getCertDetails(IRequest req, X509CertImpl cert) {
+ StringBuffer sb = new StringBuffer();
+
+ sb.append("\n");
+ sb.append("Serial No: " + cert.getSerialNumber().toString(16));
+ sb.append("\n");
+ sb.append("Validity: " + cert.getNotBefore().toString() +
+ " - " + cert.getNotAfter().toString());
+ sb.append("\n");
+ String certType = req.getExtDataInString(IRequest.CERT_TYPE);
+
+ if (certType == null)
+ certType = IRequest.SERVER_CERT;
+ if (certType.equals(IRequest.CLIENT_CERT)) {
+
+ /***
+ * Take this our - URL formulation hard to do here.
+ * sb.append("Use the following url with your CA/RA gateway spec to download the certificate.");
+ * sb.append("\n");
+ * sb.append("/query/certImport?op=displayByserial&serialNumber=");
+ * sb.append(cert.getSerialNumber().toString(16));
+ ***/
+ sb.append("\n");
+ } else {
+ sb.append("Certificate Content is as follows:");
+ sb.append("\n");
+ try {
+ byte[] ba = cert.getEncoded();
+ String encodedCert = Utils.base64encode(ba);
+
+ sb.append(CERT_HEADER + encodedCert + CERT_TRAILER);
+ } catch (Exception e) {
+ //throw new AssertionException(e.toString());
+ }
+ }
+ return sb.toString();
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/RevocationConstraints.java b/base/server/cms/src/com/netscape/cms/policy/constraints/RevocationConstraints.java
new file mode 100644
index 000000000..88c59b2fd
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/RevocationConstraints.java
@@ -0,0 +1,215 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IRevocationPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Whether to allow revocation of an expired cert.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class RevocationConstraints extends APolicyRule
+ implements IRevocationPolicy, IExtendedPluginInfo {
+ private static final String PROP_ALLOW_EXPIRED_CERTS = "allowExpiredCerts";
+ private static final String PROP_ALLOW_ON_HOLD = "allowOnHold";
+
+ private boolean mAllowExpiredCerts = true;
+ private boolean mAllowOnHold = true;
+
+ private final static Vector<String> defConfParams = new Vector<String>();
+ static {
+ defConfParams.addElement(PROP_ALLOW_EXPIRED_CERTS + "=" + true);
+ defConfParams.addElement(PROP_ALLOW_ON_HOLD + "=" + true);
+ }
+
+ public RevocationConstraints() {
+ NAME = "RevocationConstraints";
+ DESC = "Whether to allow revocation of expired certs and on-hold.";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_ALLOW_EXPIRED_CERTS + ";boolean;Allow a user to revoke an already-expired certificate",
+ PROP_ALLOW_ON_HOLD + ";boolean;Allow a user to set reason to On-Hold",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-revocationconstraints",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Allow administrator to decide policy on whether to allow " +
+ "recovation of expired certificates" +
+ "and set reason to On-Hold"
+
+ };
+
+ return params;
+
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries probably are of the form:
+ *
+ * ra.Policy.rule.<ruleName>.implName=ValidityConstraints ra.Policy.rule.<ruleName>.enable=true
+ * ra.Policy.rule.<ruleName>.allowExpiredCerts=true
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EPolicyException {
+ // Get min and max validity in days and onfigure them.
+ try {
+ mAllowExpiredCerts =
+ config.getBoolean(PROP_ALLOW_EXPIRED_CERTS, true);
+ mAllowOnHold =
+ config.getBoolean(PROP_ALLOW_ON_HOLD, true);
+ } catch (EBaseException e) {
+ // never happen.
+ }
+
+ CMS.debug("RevocationConstraints: allow expired certs " + mAllowExpiredCerts);
+ CMS.debug("RevocationConstraints: allow on hold " + mAllowOnHold);
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ CMS.debug("RevocationConstraints: apply begins");
+ if (req.getExtDataInInteger(IRequest.REVOKED_REASON) == null) {
+ CMS.debug("RevocationConstraints: apply: no revocationReason found in request");
+ return PolicyResult.REJECTED;
+ }
+ RevocationReason rr = RevocationReason.fromInt(
+ req.getExtDataInInteger(IRequest.REVOKED_REASON).intValue());
+
+ if (!mAllowOnHold && (rr != null)) {
+ int reason = rr.toInt();
+
+ if (reason == RevocationReason.CERTIFICATE_HOLD.toInt()) {
+ String params[] = { getInstanceName() };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_ON_HOLD_ALLOWED", params), "");
+ return PolicyResult.REJECTED;
+ }
+ }
+
+ if (mAllowExpiredCerts)
+ // nothing to check.
+ return PolicyResult.ACCEPTED;
+
+ PolicyResult result = PolicyResult.ACCEPTED;
+
+ try {
+ // Get the certificates being renwed.
+ X509CertImpl[] oldCerts =
+ req.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ if (oldCerts == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_OLD_CERT"),
+ getInstanceName());
+ return PolicyResult.REJECTED;
+ }
+
+ // check if each cert to be renewed is expired.
+ for (int i = 0; i < oldCerts.length; i++) {
+ X509CertInfo oldCertInfo = (X509CertInfo)
+ oldCerts[i].get(
+ X509CertImpl.NAME + "." + X509CertImpl.INFO);
+ CertificateValidity oldValidity = (CertificateValidity)
+ oldCertInfo.get(X509CertInfo.VALIDITY);
+ Date notAfter = (Date)
+ oldValidity.get(CertificateValidity.NOT_AFTER);
+
+ // Is the Certificate still valid?
+ Date now = CMS.getCurrentDate();
+
+ if (notAfter.before(now)) {
+ String params[] = { getInstanceName() };
+
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_CANNOT_REVOKE_EXPIRED_CERTS",
+ params), "");
+ result = PolicyResult.REJECTED;
+ break;
+ }
+ }
+
+ } catch (Exception e) {
+ String params[] = { getInstanceName(), e.toString() };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", params), "");
+ result = PolicyResult.REJECTED;
+ }
+ return result;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> confParams = new Vector<String>();
+
+ confParams.addElement(
+ PROP_ALLOW_EXPIRED_CERTS + "=" + mAllowExpiredCerts);
+ confParams.addElement(
+ PROP_ALLOW_ON_HOLD + "=" + mAllowOnHold);
+ return confParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return defConfParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/SigningAlgorithmConstraints.java b/base/server/cms/src/com/netscape/cms/policy/constraints/SigningAlgorithmConstraints.java
new file mode 100644
index 000000000..15b12af40
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/SigningAlgorithmConstraints.java
@@ -0,0 +1,449 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * SigningAlgorithmConstraints enforces that only a supported
+ * signing algorithm be requested.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class SigningAlgorithmConstraints extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ private String[] mAllowedAlgs = null; // algs allowed by this policy
+ static String[] mDefaultAllowedAlgs = null; // default algs allowed by this policy based on CA's key
+ private String[] mConfigAlgs = null; // algs listed in config file
+ private boolean winnowedByKey = false;
+ IAuthority mAuthority = null;
+ private final static String PROP_ALGORITHMS = "algorithms";
+
+ private final static Vector<String> defConfParams = new Vector<String>();
+
+ static {
+ StringBuffer sb = new StringBuffer();
+ sb.append(PROP_ALGORITHMS);
+ sb.append("=");
+ int i = 0;
+ boolean first = true;
+
+ mDefaultAllowedAlgs = new String[AlgorithmId.ALL_SIGNING_ALGORITHMS.length];
+ for (i = 0; i < AlgorithmId.ALL_SIGNING_ALGORITHMS.length; i++) {
+ mDefaultAllowedAlgs[i] = AlgorithmId.ALL_SIGNING_ALGORITHMS[i];
+ if (first == true) {
+ sb.append(AlgorithmId.ALL_SIGNING_ALGORITHMS[i]);
+ first = false;
+ } else {
+ sb.append(",");
+ sb.append(AlgorithmId.ALL_SIGNING_ALGORITHMS[i]);
+ }
+ }
+ defConfParams.addElement(sb.toString());
+ }
+
+ public SigningAlgorithmConstraints() {
+ NAME = "SigningAlgorithmConstraints";
+ DESC = "Enforces Signing Algorithm Constraints.";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries probably are of the form ra.Policy.rule.<ruleName>.implName=SigningAlgorithmConstraints
+ * ra.Policy.rule.<ruleName>.algorithms=SHA-1WithRSA, SHA-1WithDSA ra.Policy.rule.<ruleName>.enable=true
+ * ra.Policy.rule.<ruleName>.predicate=ou==Sales
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mAuthority = (IAuthority) ((IPolicyProcessor) owner).getAuthority();
+
+ // Get allowed algorithms from config file
+ if (config != null) {
+ String algNames = null;
+
+ try {
+ algNames = config.getString(PROP_ALGORITHMS, null);
+ } catch (Exception e) {
+ String[] params = { getInstanceName(), e.toString(), PROP_ALGORITHMS };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_PARAM_CONFIG_ERROR", params));
+ }
+
+ if (algNames != null) {
+ // parse alg names into Vector
+ StringTokenizer tok = new StringTokenizer(algNames, ",");
+ Vector<String> algs = new Vector<String>();
+
+ while (tok.hasMoreTokens()) {
+ algs.addElement(tok.nextToken().trim());
+ }
+
+ // convert to array for speedy traversals during apply()
+ int itemCount = algs.size();
+
+ mAllowedAlgs = new String[itemCount];
+ for (int i = 0; i < itemCount; i++) {
+ mAllowedAlgs[i] = algs.elementAt(i);
+ }
+
+ }
+
+ }
+
+ // these are the algorithms from the config file
+ mConfigAlgs = mAllowedAlgs;
+ if (mConfigAlgs == null) {
+ mConfigAlgs = new String[0];
+ }
+
+ if (mAllowedAlgs != null) {
+ // winnow out unknown algorithms
+ winnowAlgs(AlgorithmId.ALL_SIGNING_ALGORITHMS,
+ "CMS_POLICY_UNKNOWN_SIGNING_ALG", true);
+ } else {
+ // if nothing was in the config file, allow all known algs
+ mAllowedAlgs = AlgorithmId.ALL_SIGNING_ALGORITHMS;
+ }
+
+ // winnow out algorithms that don't make sense for the key
+ winnowByKey();
+
+ if (mAllowedAlgs.length == 0) {
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_SIGNALG_NOT_MATCH_CAKEY", NAME));
+ }
+
+ }
+
+ /**
+ * winnow out algorithms that don't make sense for the CA's key
+ */
+ private synchronized void winnowByKey() throws EBaseException {
+ // only do this successfully once
+ if (winnowedByKey) {
+ return;
+ }
+
+ // don't do this ever for DRM
+ if (!(mAuthority instanceof ICertAuthority)) {
+ winnowedByKey = true;
+ return;
+ }
+
+ // get list of algorithms allowed for the key
+ String[] allowedByKey =
+ ((ICertAuthority) mAuthority).getCASigningAlgorithms();
+
+ if (allowedByKey != null) {
+ // don't show algorithms that don't match CA's key in UI.
+ mDefaultAllowedAlgs = new String[allowedByKey.length];
+ for (int i = 0; i < allowedByKey.length; i++)
+ mDefaultAllowedAlgs[i] = allowedByKey[i];
+ // winnow out algorithms that don't match CA's signing key
+ winnowAlgs(allowedByKey,
+ "CMS_POLICY_SIGNALG_NOT_MATCH_CAKEY_1", false);
+ winnowedByKey = true;
+ } else {
+ // We don't know the CA's signing algorithms. Maybe we're
+ // an RA that hasn't talked to the CA yet? Try again later.
+ }
+ }
+
+ /**
+ * Winnows out of mAllowedAlgorithms those algorithms that aren't allowed
+ * for some reason.
+ *
+ * @param allowed An array of allowed algorithms. Only algorithms in this
+ * list will survive the winnowing process.
+ * @param reason A string describing the problem with an algorithm
+ * that is not allowed by this list. Must be a predefined string in PolicyResources.
+ */
+ private void winnowAlgs(String[] allowed, String reason, boolean isError)
+ throws EBaseException {
+ int i, j, goodSize;
+
+ // validate the currently-allowed algorithms
+ Vector<String> goodAlgs = new Vector<String>();
+
+ for (i = 0; i < mAllowedAlgs.length; i++) {
+ for (j = 0; j < allowed.length; j++) {
+ if (mAllowedAlgs[i].equals(allowed[j])) {
+ goodAlgs.addElement(mAllowedAlgs[i]);
+ break;
+ }
+ }
+ // if algorithm is not allowed, log a warning
+ if (j == allowed.length) {
+ EPolicyException e = new EPolicyException(CMS.getUserMessage(reason, NAME, mAllowedAlgs[i]));
+
+ if (isError) {
+ log(ILogger.LL_FAILURE, e.toString());
+ throw new EPolicyException(CMS.getUserMessage(reason,
+ NAME, mAllowedAlgs[i]));
+ } else {
+ log(ILogger.LL_WARN, e.toString());
+ }
+ }
+ }
+
+ // convert back into an array
+ goodSize = goodAlgs.size();
+ if (mAllowedAlgs.length != goodSize) {
+ mAllowedAlgs = new String[goodSize];
+ for (i = 0; i < goodSize; i++) {
+ mAllowedAlgs[i] = goodAlgs.elementAt(i);
+ }
+ }
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ int i, j;
+
+ PolicyResult result = PolicyResult.ACCEPTED;
+
+ try {
+
+ // Get the certificate info from the request
+ //X509CertInfo certInfo[] = (X509CertInfo[])
+ // req.get(IRequest.CERT_INFO);
+ X509CertInfo certInfo[] = req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ // We need to have a certificate info set
+ if (certInfo == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO",
+ getInstanceName()), "");
+ return PolicyResult.REJECTED;
+ }
+
+ // Else check if the key algorithm is supported.
+ for (i = 0; i < certInfo.length; i++) {
+ // make sure our list of allowed algorithms makes
+ // sense for our key. Do this each time.
+ if (!winnowedByKey) {
+ winnowByKey();
+ }
+
+ CertificateAlgorithmId certAlgId = (CertificateAlgorithmId)
+ certInfo[i].get(X509CertInfo.ALGORITHM_ID);
+
+ AlgorithmId algId = (AlgorithmId)
+ certAlgId.get(CertificateAlgorithmId.ALGORITHM);
+ String alg = algId.getName();
+
+ // test against the list of allowed algorithms
+ for (j = 0; j < mAllowedAlgs.length; j++) {
+ if (mAllowedAlgs[j].equals(alg)) {
+ break;
+ }
+ }
+ if (j == mAllowedAlgs.length) {
+ // if the algor doesn't match the CA's key replace
+ // it with one that does.
+ if (mAllowedAlgs[0].equals("SHA1withDSA") ||
+ alg.equals("SHA1withDSA")) {
+ certInfo[i].set(X509CertInfo.ALGORITHM_ID,
+ new CertificateAlgorithmId(
+ AlgorithmId.get(mAllowedAlgs[0])));
+ return PolicyResult.ACCEPTED;
+ }
+
+ // didn't find a match, alg not allowed
+ setError(req, CMS.getUserMessage("CMS_POLICY_SIGNING_ALG_VIOLATION",
+ getInstanceName(), alg), "");
+ result = PolicyResult.REJECTED;
+ }
+ }
+ } catch (Exception e) {
+ // e.printStackTrace();
+ String params[] = { getInstanceName(), e.toString() };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR",
+ params), "");
+ result = PolicyResult.REJECTED;
+ }
+ return result;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> confParams = new Vector<String>();
+ StringBuffer sb = new StringBuffer();
+
+ for (int i = 0; i < mConfigAlgs.length; i++) {
+ sb.append(mConfigAlgs[i]);
+ sb.append(",");
+ }
+ if (sb.length() > 0)
+ sb.setLength(sb.length() - 1);
+ confParams.addElement(PROP_ALGORITHMS + "=" + sb.toString());
+ return confParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(PROP_ALGORITHMS);
+ sb.append("=");
+ boolean first = true;
+
+ defConfParams.removeAllElements();
+
+ for (int i = 0; i < mDefaultAllowedAlgs.length; i++) {
+ if (first == true) {
+ sb.append(mDefaultAllowedAlgs[i]);
+ first = false;
+ } else {
+ sb.append(",");
+ sb.append(mDefaultAllowedAlgs[i]);
+ }
+ }
+ defConfParams.addElement(sb.toString());
+
+ return defConfParams;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ if (!winnowedByKey) {
+ try {
+ winnowByKey();
+ } catch (Exception e) {
+ }
+ }
+
+ String[] params = null;
+
+ String[] params_BOTH = {
+ PROP_ALGORITHMS
+ + ";"
+ + "choice(MD2withRSA\\,MD5withRSA\\,SHA1withRSA\\,SHA256withRSA\\,SHA512withRSA\\,SHA1withDSA,"
+ +
+ "MD2withRSA\\,MD5withRSA\\,SHA1withRSA\\,SHA1withDSA," +
+ "MD2withRSA\\,MD5withRSA\\,SHA1withRSA," +
+ "MD2withRSA\\,SHA1withRSA\\,SHA1withDSA," +
+ "MD5withRSA\\,SHA1withRSA\\,SHA1withDSA," +
+ "MD2withRSA\\,MD5withRSA\\,SHA1withDSA," +
+ "MD2withRSA\\,MD5withRSA," +
+ "MD2withRSA\\,SHA1withRSA," +
+ "MD2withRSA\\,SHA1withDSA," +
+ "MD5withRSA\\,SHA1withRSA," +
+ "MD5withRSA\\,SHA1withDSA," +
+ "SHA1withRSA\\,SHA1withDSA," +
+ "MD2withRSA," +
+ "MD5withRSA," +
+ "SHA1withRSA," +
+ "SHA1withDSA);List of algorithms to restrict the requested signing algorithm " +
+ "to be one of the algorithms supported by Certificate System",
+ IExtendedPluginInfo.HELP_TOKEN + ";configuration-policyrules-signingalgconstraints",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Restricts the requested signing algorithm to be one of" +
+ " the algorithms supported by Certificate System"
+ };
+
+ String[] params_RSA = {
+ PROP_ALGORITHMS + ";" + "choice(MD2withRSA\\,MD5withRSA\\,SHA1withRSA," +
+ "MD2withRSA\\,MD5withRSA," +
+ "MD2withRSA\\,SHA1withRSA," +
+ "MD5withRSA\\,SHA1withRSA," +
+ "MD2withRSA," +
+ "MD5withRSA," +
+ "SHA1withRSA);Restrict the requested signing algorithm to be " +
+ "one of the algorithms supported by Certificate System",
+ IExtendedPluginInfo.HELP_TOKEN + ";configuration-policyrules-signingalgconstraints",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Restricts the requested signing algorithm to be one of" +
+ " the algorithms supported by Certificate System"
+ };
+
+ String[] params_DSA = {
+ PROP_ALGORITHMS + ";" + "choice(SHA1withDSA);Restrict the requested signing " +
+ "algorithm to be one of the algorithms supported by Certificate " +
+ "System",
+ IExtendedPluginInfo.HELP_TOKEN + ";configuration-policyrules-signingalgconstraints",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Restricts the requested signing algorithm to be one of" +
+ " the algorithms supported by Certificate System"
+ };
+
+ switch (mDefaultAllowedAlgs.length) {
+ case 1:
+ params = params_DSA;
+ break;
+
+ case 3:
+ params = params_RSA;
+ break;
+
+ case 4:
+ default:
+ params = params_BOTH;
+ break;
+
+ }
+
+ return params;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/SubCANameConstraints.java b/base/server/cms/src/com/netscape/cms/policy/constraints/SubCANameConstraints.java
new file mode 100644
index 000000000..07cc3b956
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/SubCANameConstraints.java
@@ -0,0 +1,195 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.certsrv.security.ISigningUnit;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * This simple policy checks the subordinate CA CSR to see
+ * if it is the same as the local CA.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class SubCANameConstraints extends APolicyRule implements IEnrollmentPolicy, IExtendedPluginInfo {
+ public ICertificateAuthority mCA = null;
+ public String mIssuerNameStr = null;
+
+ public SubCANameConstraints() {
+ NAME = "SubCANameConstraints";
+ DESC = "Enforces Subordinate CA name.";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-subcanamecheck",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Checks if subordinate CA request matches the local CA. There are no parameters to change"
+ };
+
+ return params;
+
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries probably are of the form ra.Policy.rule.<ruleName>.implName=KeyAlgorithmConstraints
+ * ra.Policy.rule.<ruleName>.algorithms=RSA,DSA ra.Policy.rule.<ruleName>.enable=true
+ * ra.Policy.rule.<ruleName>.predicate=ou==Sales
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ // get CA's public key to create authority key id.
+ ICertAuthority certAuthority = (ICertAuthority)
+ ((IPolicyProcessor) owner).getAuthority();
+
+ if (certAuthority == null) {
+ // should never get here.
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CANT_FIND_MANAGER"));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Cannot find the Certificate Manager"));
+ }
+ if (!(certAuthority instanceof ICertificateAuthority)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CANT_FIND_MANAGER"));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Cannot find the Certificate Manager"));
+ }
+ mCA = (ICertificateAuthority) certAuthority;
+ ISigningUnit su = mCA.getSigningUnit();
+ if (su == null || CMS.isPreOpMode()) {
+ return;
+ }
+
+ X509CertImpl cert = su.getCertImpl();
+
+ if (cert == null)
+ return;
+ X500Name issuerName = (X500Name) cert.getSubjectDN();
+
+ if (issuerName == null)
+ return;
+ mIssuerNameStr = issuerName.toString();
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ PolicyResult result = PolicyResult.ACCEPTED;
+
+ try {
+
+ // Get the certificate templates
+ X509CertInfo[] certInfos = req.getExtDataInCertInfoArray(
+ IRequest.CERT_INFO);
+
+ if (certInfos == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_NO_CERT_INFO", getInstanceName()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO", NAME + ":" + getInstanceName()), "");
+ return PolicyResult.REJECTED;
+ }
+
+ // retrieve the subject name and check its unqiueness
+ for (int i = 0; i < certInfos.length; i++) {
+ CertificateSubjectName subName = (CertificateSubjectName) certInfos[i].get(X509CertInfo.SUBJECT);
+
+ // if there is no name set, set one here.
+ if (subName == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_NO_SUBJECT_NAME_1", getInstanceName()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_SUBJECT_NAME", NAME + ":" + getInstanceName()), "");
+ return PolicyResult.REJECTED;
+ }
+ String certSubjectName = subName.toString();
+
+ if (certSubjectName.equalsIgnoreCase(mIssuerNameStr)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_SUBJECT_NAME_EXIST_1", mIssuerNameStr));
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_SUBJECT_NAME_EXIST", NAME + ":" + "Same As Issuer Name "
+ + mIssuerNameStr), "");
+ result = PolicyResult.REJECTED;
+ }
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_NO_SUBJECT_NAME_1", getInstanceName()));
+ String params[] = { getInstanceName(), e.toString() };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR",
+ params), "");
+ result = PolicyResult.REJECTED;
+ }
+ return result;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ return v;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ return v;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/UniqueSubjectName.java b/base/server/cms/src/com/netscape/cms/policy/constraints/UniqueSubjectName.java
new file mode 100644
index 000000000..27b5d1a92
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/UniqueSubjectName.java
@@ -0,0 +1,33 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+/**
+ * This class is used to help migrate CMS4.1 to CMS4.2.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class UniqueSubjectName extends UniqueSubjectNameConstraints {
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/UniqueSubjectNameConstraints.java b/base/server/cms/src/com/netscape/cms/policy/constraints/UniqueSubjectNameConstraints.java
new file mode 100644
index 000000000..fb52b1302
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/UniqueSubjectNameConstraints.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Checks the uniqueness of the subject name. This policy
+ * can only be used (installed) in Certificate Authority
+ * subsystem.
+ *
+ * This policy can perform pre-agent-approval checking or
+ * post-agent-approval checking based on configuration
+ * setting.
+ *
+ * In some situations, user may want to have 2 certificates with
+ * the same subject name. For example, one key for encryption,
+ * and one for signing. This policy does not deal with this case
+ * directly. But it can be easily extended to do that.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class UniqueSubjectNameConstraints extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ protected static final String PROP_PRE_AGENT_APPROVAL_CHECKING =
+ "enablePreAgentApprovalChecking";
+ protected static final String PROP_KEY_USAGE_EXTENSION_CHECKING =
+ "enableKeyUsageExtensionChecking";
+
+ public ICertificateAuthority mCA = null;
+
+ public boolean mPreAgentApprovalChecking = false;
+ public boolean mKeyUsageExtensionChecking = true;
+
+ public UniqueSubjectNameConstraints() {
+ NAME = "UniqueSubjectName";
+ DESC = "Ensure the uniqueness of the subject name.";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_PRE_AGENT_APPROVAL_CHECKING
+ + ";boolean;If checked, check subject name uniqueness BEFORE agent approves, (else checks AFTER approval)",
+ PROP_KEY_USAGE_EXTENSION_CHECKING
+ + ";boolean;If checked, allow non-unique subject names if Key Usage Extension differs",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-uniquesubjectname",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Rejects a request if there exists an unrevoked, unexpired " +
+ "certificate with the same subject name"
+ };
+
+ return params;
+
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries probably are of the form:
+ *
+ * ca.Policy.rule.<ruleName>.implName=UniqueSubjectName ca.Policy.rule.<ruleName>.enable=true
+ * ca.Policy.rule.<ruleName>.enable=true ca.Policy.rule.<ruleName>.enablePreAgentApprovalChecking=true
+ * ca.Policy.rule.<ruleName>.enableKeyUsageExtensionChecking=true
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ // get CA's public key to create authority key id.
+ ICertAuthority certAuthority = (ICertAuthority)
+ ((IPolicyProcessor) owner).getAuthority();
+
+ if (certAuthority == null) {
+ // should never get here.
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CANT_FIND_MANAGER"));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Cannot find the Certificate Manager or Registration Manager"));
+ }
+ if (!(certAuthority instanceof ICertificateAuthority)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CANT_FIND_MANAGER"));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Cannot find the Certificate Manager"));
+ }
+
+ mCA = (ICertificateAuthority) certAuthority;
+ try {
+ mPreAgentApprovalChecking =
+ config.getBoolean(PROP_PRE_AGENT_APPROVAL_CHECKING, false);
+ } catch (EBaseException e) {
+ }
+ try {
+ mKeyUsageExtensionChecking =
+ config.getBoolean(PROP_KEY_USAGE_EXTENSION_CHECKING, true);
+ } catch (EBaseException e) {
+ }
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ if (!mPreAgentApprovalChecking) {
+ // post agent approval checking
+ if (!agentApproved(req))
+ return PolicyResult.ACCEPTED;
+ }
+ PolicyResult result = PolicyResult.ACCEPTED;
+
+ try {
+
+ // Get the certificate templates
+ X509CertInfo[] certInfos = req.getExtDataInCertInfoArray(
+ IRequest.CERT_INFO);
+
+ if (certInfos == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO",
+ getInstanceName()), "");
+ return PolicyResult.REJECTED;
+ }
+
+ // retrieve the subject name and check its unqiueness
+ for (int i = 0; i < certInfos.length; i++) {
+ CertificateSubjectName subName = (CertificateSubjectName)
+ certInfos[i].get(X509CertInfo.SUBJECT);
+
+ // if there is no name set, set one here.
+ if (subName == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_SUBJECT_NAME",
+ getInstanceName()), "");
+ return PolicyResult.REJECTED;
+ }
+ String certSubjectName = subName.toString();
+ String filter = "x509Cert.subject=" + certSubjectName;
+ // subject name is indexed, so we only use subject name
+ // in the filter
+ Enumeration<ICertRecord> matched =
+ mCA.getCertificateRepository().findCertRecords(filter);
+
+ while (matched.hasMoreElements()) {
+ ICertRecord rec = matched.nextElement();
+ String status = rec.getStatus();
+
+ if (status.equals(ICertRecord.STATUS_REVOKED)
+ || status.equals(ICertRecord.STATUS_EXPIRED)
+ || status.equals(ICertRecord.STATUS_REVOKED_EXPIRED)) {
+ // accept this only if we have a REVOKED,
+ // EXPIRED or REVOKED_EXPIRED certificate
+ continue;
+
+ }
+ // you already have an VALID or INVALID (not yet valid) certificate
+ if (mKeyUsageExtensionChecking && agentApproved(req)) {
+ // This request is agent approved which
+ // means all requested extensions are finalized
+ // to the request,
+ // We will accept duplicated subject name with
+ // different keyUsage extension if
+ // keyUsageExtension is different.
+ if (!sameKeyUsageExtension(rec, certInfos[i])) {
+ continue;
+ }
+ }
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_SUBJECT_NAME_EXIST",
+ getInstanceName() + " " + certSubjectName), "");
+ return PolicyResult.REJECTED;
+ }
+ }
+ } catch (Exception e) {
+ String params[] = { getInstanceName(), e.toString() };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR",
+ params), "");
+ result = PolicyResult.REJECTED;
+ }
+ return result;
+ }
+
+ /**
+ * Checks if the key extension in the issued certificate
+ * is the same as the one in the certificate template.
+ */
+ private boolean sameKeyUsageExtension(ICertRecord rec,
+ X509CertInfo certInfo) {
+ X509CertImpl impl = rec.getCertificate();
+ boolean bits[] = impl.getKeyUsage();
+
+ CertificateExtensions extensions = null;
+
+ try {
+ extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+ } catch (IOException e) {
+ } catch (java.security.cert.CertificateException e) {
+ }
+ KeyUsageExtension ext = null;
+
+ if (extensions == null) {
+ if (bits != null)
+ return false;
+ } else {
+ try {
+ ext = (KeyUsageExtension) extensions.get(
+ KeyUsageExtension.NAME);
+ } catch (IOException e) {
+ // extension isn't there.
+ }
+
+ if (ext == null) {
+ if (bits != null)
+ return false;
+ } else {
+ boolean[] InfoBits = ext.getBits();
+
+ if (InfoBits == null) {
+ if (bits != null)
+ return false;
+ } else {
+ if (bits == null)
+ return false;
+ if (InfoBits.length != bits.length) {
+ return false;
+ }
+ for (int i = 0; i < InfoBits.length; i++) {
+ if (InfoBits[i] != bits[i])
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> confParams = new Vector<String>();
+
+ confParams.addElement(PROP_PRE_AGENT_APPROVAL_CHECKING +
+ "=" + mPreAgentApprovalChecking);
+ confParams.addElement(PROP_KEY_USAGE_EXTENSION_CHECKING +
+ "=" + mKeyUsageExtensionChecking);
+ return confParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> defParams = new Vector<String>();
+
+ defParams.addElement(PROP_PRE_AGENT_APPROVAL_CHECKING + "=");
+ defParams.addElement(PROP_KEY_USAGE_EXTENSION_CHECKING + "=");
+ return defParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/constraints/ValidityConstraints.java b/base/server/cms/src/com/netscape/cms/policy/constraints/ValidityConstraints.java
new file mode 100644
index 000000000..72be9d75a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/constraints/ValidityConstraints.java
@@ -0,0 +1,317 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.constraints;
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * ValidityConstraints is a default rule for Enrollment and
+ * Renewal that enforces minimum and maximum validity periods
+ * and changes them if not met.
+ *
+ * Optionally the lead and lag times - i.e how far back into the
+ * front or back the notBefore date could go in minutes can also
+ * be specified.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class ValidityConstraints extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ protected long mMinValidity;
+ protected long mMaxValidity;
+ protected long mLeadTime;
+ protected long mLagTime;
+ protected long mNotBeforeSkew;
+
+ private final static String PROP_MIN_VALIDITY = "minValidity";
+ private final static String PROP_MAX_VALIDITY = "maxValidity";
+ private final static String PROP_LEAD_TIME = "leadTime";
+ private final static String PROP_LAG_TIME = "lagTime";
+ private final static String PROP_NOT_BEFORE_SKEW = "notBeforeSkew";
+ public final static int DEF_MIN_VALIDITY = 180;
+ public final static int DEF_MAX_VALIDITY = 730;
+ public final static int DEF_LEAD_TIME = 10;
+ public final static int DEF_LAG_TIME = 10;
+ public final static int DEF_NOT_BEFORE_SKEW = 5;
+ public final static long DAYS_TO_MS_FACTOR = 24L * 3600 * 1000;
+ public final static long MINS_TO_MS_FACTOR = 60L * 1000;
+
+ private final static Vector<String> defConfParams = new Vector<String>();
+
+ static {
+ defConfParams.addElement(PROP_MIN_VALIDITY + "=" +
+ DEF_MIN_VALIDITY);
+ defConfParams.addElement(PROP_MAX_VALIDITY + "=" +
+ DEF_MAX_VALIDITY);
+ defConfParams.addElement(PROP_LEAD_TIME + "=" +
+ DEF_LEAD_TIME);
+ defConfParams.addElement(PROP_LAG_TIME + "=" +
+ DEF_LAG_TIME);
+ defConfParams.addElement(PROP_NOT_BEFORE_SKEW + "=" +
+ DEF_NOT_BEFORE_SKEW);
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_MIN_VALIDITY + ";number;Minimum Validity time, in days",
+ PROP_MAX_VALIDITY + ";number;Maximum Validity time, in days",
+ PROP_LEAD_TIME + ";number;Number of minutes in the future a request's notBefore can be",
+ PROP_LAG_TIME + ";number;NOT CURRENTLY IN USE",
+ PROP_NOT_BEFORE_SKEW + ";number;Number of minutes a cert's notBefore should be in the past",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-validityconstraints",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Ensures that the user's requested validity period is " +
+ "acceptable. If not specified, as is usually the case, " +
+ "this policy will set the validity. See RFC 2459."
+ };
+
+ return params;
+
+ }
+
+ public ValidityConstraints() {
+ NAME = "ValidityConstraints";
+ DESC = "Enforces minimum and maximum validity constraints.";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries probably are of the form:
+ *
+ * ra.Policy.rule.<ruleName>.implName=ValidityConstraints ra.Policy.rule.<ruleName>.enable=true
+ * ra.Policy.rule.<ruleName>.minValidity=30 ra.Policy.rule.<ruleName>.maxValidity=180
+ * ra.Policy.rule.<ruleName>.predicate=ou==Sales
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EPolicyException {
+
+ // Get min and max validity in days and configure them.
+ try {
+ String val = config.getString(PROP_MIN_VALIDITY, null);
+
+ if (val == null)
+ mMinValidity = DEF_MIN_VALIDITY * DAYS_TO_MS_FACTOR;
+ else
+ mMinValidity = Long.parseLong(val) * DAYS_TO_MS_FACTOR;
+
+ val = config.getString(PROP_MAX_VALIDITY, null);
+ if (val == null)
+ mMaxValidity = DEF_MAX_VALIDITY * DAYS_TO_MS_FACTOR;
+ else
+ mMaxValidity = Long.parseLong(val) * DAYS_TO_MS_FACTOR;
+
+ val = config.getString(PROP_LEAD_TIME, null);
+ if (val != null)
+ mLeadTime = Long.parseLong(val) * MINS_TO_MS_FACTOR;
+ else
+ mLeadTime = DEF_LEAD_TIME * MINS_TO_MS_FACTOR;
+
+ val = config.getString(PROP_LAG_TIME, null);
+ if (val != null)
+ mLagTime = Long.parseLong(val) * MINS_TO_MS_FACTOR;
+ else
+ mLagTime = DEF_LAG_TIME * MINS_TO_MS_FACTOR;
+
+ val = config.getString(PROP_NOT_BEFORE_SKEW, null);
+ if (val != null)
+ mNotBeforeSkew = Long.parseLong(val) * MINS_TO_MS_FACTOR;
+ else
+ mNotBeforeSkew = DEF_NOT_BEFORE_SKEW * MINS_TO_MS_FACTOR;
+ } catch (Exception e) {
+ // e.printStackTrace();
+ String[] params = { getInstanceName(), e.toString() };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CONFIG", params));
+ }
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+
+ PolicyResult result = PolicyResult.ACCEPTED;
+
+ try {
+ // Get the certificate info from the request
+ //X509CertInfo certInfo[] = (X509CertInfo[])
+ // req.get(IRequest.CERT_INFO);
+ X509CertInfo certInfo[] = req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ // There should be a certificate info set.
+ if (certInfo == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO",
+ getInstanceName()), "");
+ return PolicyResult.REJECTED;
+ }
+
+ // Else check if validity is within the limit
+ for (int i = 0; i < certInfo.length; i++) {
+ CertificateValidity validity = (CertificateValidity)
+ certInfo[i].get(X509CertInfo.VALIDITY);
+
+ Date notBefore = null, notAfter = null;
+
+ if (validity != null) {
+ notBefore = (Date)
+ validity.get(CertificateValidity.NOT_BEFORE);
+ notAfter = (Date)
+ validity.get(CertificateValidity.NOT_AFTER);
+ }
+
+ // If no validity is supplied yet, make one. The default
+ // validity is supposed to pass the following checks, so
+ // bypass further checking.
+ // (date = 0 is hack for serialization)
+
+ if (validity == null ||
+ (notBefore.getTime() == 0 && notAfter.getTime() == 0)) {
+ certInfo[i].set(X509CertInfo.VALIDITY,
+ makeDefaultValidity(req));
+ continue;
+ }
+
+ Date now = CMS.getCurrentDate();
+
+ if (notBefore.getTime() > (now.getTime() + mLeadTime)) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_INVALID_BEGIN_TIME",
+ getInstanceName()), "");
+ result = PolicyResult.REJECTED;
+ }
+ if ((notAfter.getTime() - notBefore.getTime()) > mMaxValidity) {
+ String params[] = { getInstanceName(),
+ String.valueOf(
+ ((notAfter.getTime() - notBefore.getTime()) / DAYS_TO_MS_FACTOR)),
+ String.valueOf(mMaxValidity / DAYS_TO_MS_FACTOR) };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_MORE_THAN_MAX_VALIDITY", params), "");
+ result = PolicyResult.REJECTED;
+ }
+ if ((notAfter.getTime() - notBefore.getTime()) < mMinValidity) {
+ String params[] = { getInstanceName(),
+ String.valueOf(
+ ((notAfter.getTime() - notBefore.getTime()) / DAYS_TO_MS_FACTOR)),
+ String.valueOf(mMinValidity / DAYS_TO_MS_FACTOR) };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_LESS_THAN_MIN_VALIDITY", params), "");
+ result = PolicyResult.REJECTED;
+ }
+ }
+ } catch (Exception e) {
+ // e.printStackTrace();
+ String params[] = { getInstanceName(), e.toString() };
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR",
+ params), "");
+ result = PolicyResult.REJECTED;
+ }
+ return result;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> confParams = new Vector<String>();
+
+ confParams.addElement(PROP_MIN_VALIDITY + "=" +
+ mMinValidity / DAYS_TO_MS_FACTOR);
+ confParams.addElement(PROP_MAX_VALIDITY + "=" +
+ mMaxValidity / DAYS_TO_MS_FACTOR);
+ confParams.addElement(PROP_LEAD_TIME + "="
+ + mLeadTime / MINS_TO_MS_FACTOR);
+ confParams.addElement(PROP_LAG_TIME + "=" +
+ mLagTime / MINS_TO_MS_FACTOR);
+ confParams.addElement(PROP_NOT_BEFORE_SKEW + "=" +
+ mNotBeforeSkew / MINS_TO_MS_FACTOR);
+ return confParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return defConfParams;
+ }
+
+ /**
+ * Create a default validity value for a request
+ *
+ * This code can be easily overridden in a derived class, if the
+ * calculations here aren't accepatble.
+ *
+ * TODO: it might be good to base this calculation on the creation
+ * time of the request.
+ */
+ protected CertificateValidity makeDefaultValidity(IRequest req) {
+ long now = roundTimeToSecond((CMS.getCurrentDate()).getTime());
+
+ // We will set the max duration as the default validity.
+ long notBeforeTime = now - mNotBeforeSkew;
+ Date notBefore = new Date(notBeforeTime);
+ Date notAfter = new Date(notBeforeTime + mMaxValidity);
+
+ return new CertificateValidity(notBefore, notAfter);
+ }
+
+ /**
+ * convert a millisecond resolution time into one with 1 second
+ * resolution. Most times in certificates are storage at 1
+ * second resolution, so its better if we deal with things at
+ * that level.
+ */
+ protected long roundTimeToSecond(long input) {
+ return (input / 1000) * 1000;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/AuthInfoAccessExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/AuthInfoAccessExt.java
new file mode 100644
index 000000000..21e4ad920
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/AuthInfoAccessExt.java
@@ -0,0 +1,394 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.security.cert.CertificateException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.extensions.AuthInfoAccessExtension;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IGeneralNameUtil;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Authority Information Access extension policy.
+ * If this policy is enabled, it adds an authority
+ * information access extension to the certificate.
+ *
+ * The following listed sample configuration parameters:
+ *
+ * ca.Policy.impl.AuthInfoAccess.class=com.netscape.certsrv.policy.AuthInfoAccessExt
+ * ca.Policy.rule.aia.ad0_location=uriName:http://ocsp1.netscape.com
+ * ca.Policy.rule.aia.ad0_method=ocsp
+ * ca.Policy.rule.aia.ad1_location_type=URI
+ * ca.Policy.rule.aia.ad1_location=http://ocsp2.netscape.com
+ * ca.Policy.rule.aia.ad1_method=ocsp
+ * ca.Policy.rule.aia.ad2_location=
+ * ca.Policy.rule.aia.ad2_method=
+ * ca.Policy.rule.aia.ad3_location=
+ * ca.Policy.rule.aia.ad3_method=
+ * ca.Policy.rule.aia.ad4_location=
+ * ca.Policy.rule.aia.ad4_method=
+ * ca.Policy.rule.aia.critical=true
+ * ca.Policy.rule.aia.enable=true
+ * ca.Policy.rule.aia.implName=AuthInfoAccess
+ * ca.Policy.rule.aia.predicate=
+ *
+ * Currently, this policy only supports the following location:
+ * uriName:[URI], dirName:[DN]
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class AuthInfoAccessExt extends APolicyRule implements
+ IEnrollmentPolicy, IExtendedPluginInfo {
+ protected static final String PROP_CRITICAL =
+ "critical";
+ protected static final String PROP_AD =
+ "ad";
+ protected static final String PROP_METHOD =
+ "method";
+ protected static final String PROP_LOCATION =
+ "location";
+ protected static final String PROP_LOCATION_TYPE =
+ "location_type";
+
+ protected static final String PROP_NUM_ADS =
+ "numADs";
+
+ public static final int MAX_AD = 5;
+
+ public IConfigStore mConfig = null;
+
+ public AuthInfoAccessExt() {
+ NAME = "AuthInfoAccessExt";
+ DESC = "Sets authority information access extension for certificates";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(PROP_CRITICAL +
+ ";boolean;RFC 2459 recommendation: This extension MUST be non-critical.");
+ v.addElement(PROP_NUM_ADS +
+ ";number;The total number of access descriptions.");
+ v.addElement(IExtendedPluginInfo.HELP_TEXT +
+ ";Adds Authority Info Access Extension. Defined in RFC 2459 " + "(4.2.2.1)");
+ v.addElement(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-authinfoaccess");
+
+ for (int i = 0; i < MAX_AD; i++) {
+ v.addElement(PROP_AD
+ + Integer.toString(i)
+ + "_"
+ + PROP_METHOD
+ + ";string;"
+ + "A unique,valid OID specified in dot-separated numeric component notation. e.g. 1.3.6.1.5.5.7.48.1 (ocsp), 1.3.6.1.5.5.7.48.2 (caIssuers), 2.16.840.1.113730.1.16.1 (renewal)");
+ v.addElement(PROP_AD
+ + Integer.toString(i) + "_" + PROP_LOCATION_TYPE + ";" + IGeneralNameUtil.GENNAME_CHOICE_INFO);
+ v.addElement(PROP_AD
+ + Integer.toString(i) + "_" + PROP_LOCATION + ";" + IGeneralNameUtil.GENNAME_VALUE_INFO);
+ }
+ return com.netscape.cmsutil.util.Utils.getStringArrayFromVector(v);
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ca.Policy.rule.<ruleName>.implName=AuthInfoAccessExt ca.Policy.rule.<ruleName>.enable=true
+ * ca.Policy.rule.<ruleName>.predicate=
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+ }
+
+ /**
+ * Returns a sequence of access descriptions.
+ */
+ private Enumeration<Vector<Serializable>> getAccessDescriptions() throws EBaseException {
+ Vector<Vector<Serializable>> ads = new Vector<Vector<Serializable>>();
+
+ //
+ // read until there is *NO* ad<NUM>_method
+ //
+ for (int i = 0;; i++) {
+ ObjectIdentifier methodOID = null;
+ String method = mConfig.getString(PROP_AD +
+ Integer.toString(i) + "_" + PROP_METHOD, null);
+
+ if (method == null)
+ break;
+ method = method.trim();
+ if (method.equals(""))
+ break;
+
+ //
+ // method ::= ocsp | caIssuers | <OID>
+ // OID ::= [object identifier]
+ //
+ try {
+ if (method.equalsIgnoreCase("ocsp")) {
+ methodOID = ObjectIdentifier.getObjectIdentifier("1.3.6.1.5.5.7.48.1");
+ } else if (method.equalsIgnoreCase("caIssuers")) {
+ methodOID = ObjectIdentifier.getObjectIdentifier("1.3.6.1.5.5.7.48.2");
+ } else if (method.equalsIgnoreCase("renewal")) {
+ methodOID = ObjectIdentifier.getObjectIdentifier("2.16.840.1.113730.1.16.1");
+ } else {
+ // it could be an object identifier, test it
+ methodOID = ObjectIdentifier.getObjectIdentifier(method);
+ }
+ } catch (IOException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NAME_CAN_NOT_BE_RESOLVED", method));
+ }
+
+ //
+ // location ::= <TAG> : <VALUE>
+ // TAG ::= uriName | dirName
+ // VALUE ::= [value defined by TAG]
+ //
+ String location_type = mConfig.getString(PROP_AD +
+ Integer.toString(i) +
+ "_" + PROP_LOCATION_TYPE, null);
+ String location = mConfig.getString(PROP_AD +
+ Integer.toString(i) +
+ "_" + PROP_LOCATION, null);
+
+ if (location == null)
+ break;
+ GeneralName gn = CMS.form_GeneralName(location_type, location);
+ Vector<Serializable> e = new Vector<Serializable>();
+
+ e.addElement(methodOID);
+ e.addElement(gn);
+ ads.addElement(e);
+ }
+ return ads.elements();
+ }
+
+ /**
+ * If this policy is enabled, add the authority information
+ * access extension to the certificate.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ PolicyResult res = PolicyResult.ACCEPTED;
+
+ X509CertInfo certInfo;
+ X509CertInfo[] ci = req.getExtDataInCertInfoArray(
+ IRequest.CERT_INFO);
+
+ if (ci == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO", NAME), "");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ for (int j = 0; j < ci.length; j++) {
+
+ certInfo = ci[j];
+ if (certInfo == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_UNEXPECTED_POLICY_ERROR", NAME, ""));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR",
+ NAME, "Configuration Info Error"), "");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ try {
+ // Find the extensions in the certInfo
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+
+ // add access descriptions
+ Enumeration<Vector<Serializable>> e = getAccessDescriptions();
+
+ if (!e.hasMoreElements()) {
+ return res;
+ }
+
+ if (extensions == null) {
+ // create extension if not exist
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ } else {
+ // check to see if AIA is already exist
+ try {
+ extensions.delete(AuthInfoAccessExtension.NAME);
+ log(ILogger.LL_WARN,
+ "Previous extension deleted: " + AuthInfoAccessExtension.NAME);
+ } catch (IOException ex) {
+ }
+ }
+
+ // Create the extension
+ AuthInfoAccessExtension aiaExt = new
+ AuthInfoAccessExtension(mConfig.getBoolean(
+ PROP_CRITICAL, false));
+
+ while (e.hasMoreElements()) {
+ Vector<Serializable> ad = e.nextElement();
+ ObjectIdentifier oid = (ObjectIdentifier) ad.elementAt(0);
+ GeneralName gn = (GeneralName) ad.elementAt(1);
+
+ aiaExt.addAccessDescription(oid, gn);
+ }
+ extensions.set(AuthInfoAccessExtension.NAME, aiaExt);
+
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_UNEXPECTED_POLICY_ERROR", NAME, e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR",
+ NAME, e.getMessage()), "");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_UNEXPECTED_POLICY_ERROR", NAME, e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR",
+ NAME, "Configuration Info Error"), "");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_UNEXPECTED_POLICY_ERROR", NAME, e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR",
+ NAME, "Certificate Info Error"), "");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> params = new Vector<String>();
+
+ try {
+ params.addElement(PROP_CRITICAL + "=" +
+ mConfig.getBoolean(PROP_CRITICAL, false));
+ } catch (EBaseException e) {
+ params.addElement(PROP_CRITICAL + "=false");
+ }
+
+ int numADs = MAX_AD;
+
+ try {
+ numADs = mConfig.getInteger(PROP_NUM_ADS, MAX_AD);
+ params.addElement(PROP_NUM_ADS + "=" + numADs);
+ } catch (EBaseException e) {
+ params.addElement(PROP_NUM_ADS + "=" + MAX_AD);
+ }
+
+ for (int i = 0; i < numADs; i++) {
+ String method = null;
+
+ try {
+ method = mConfig.getString(PROP_AD +
+ Integer.toString(i) + "_" + PROP_METHOD,
+ "");
+ } catch (EBaseException e) {
+ }
+ params.addElement(PROP_AD +
+ Integer.toString(i) +
+ "_" + PROP_METHOD + "=" + method);
+ String location_type = null;
+
+ try {
+ location_type = mConfig.getString(PROP_AD +
+ Integer.toString(i) + "_" + PROP_LOCATION_TYPE,
+ IGeneralNameUtil.GENNAME_CHOICE_URL);
+ } catch (EBaseException e) {
+ }
+ params.addElement(PROP_AD +
+ Integer.toString(i) +
+ "_" + PROP_LOCATION_TYPE + "=" + location_type);
+ String location = null;
+
+ try {
+ location = mConfig.getString(PROP_AD +
+ Integer.toString(i) + "_" + PROP_LOCATION,
+ "");
+ } catch (EBaseException e) {
+ }
+ params.addElement(PROP_AD +
+ Integer.toString(i) +
+ "_" + PROP_LOCATION + "=" + location);
+ }
+ return params;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> defParams = new Vector<String>();
+
+ defParams.addElement(PROP_CRITICAL + "=false");
+ defParams.addElement(PROP_NUM_ADS + "=" + MAX_AD);
+
+ //
+ // By default, we create MAX_AD access descriptions.
+ // If this is not enough, admin can manually edit
+ // the CMS.cfg
+ //
+ for (int i = 0; i < MAX_AD; i++) {
+ defParams.addElement(PROP_AD + Integer.toString(i) +
+ "_" + PROP_METHOD + "=");
+ defParams.addElement(PROP_AD + Integer.toString(i) +
+ "_" + PROP_LOCATION_TYPE + "=" + IGeneralNameUtil.GENNAME_CHOICE_URL);
+ defParams.addElement(PROP_AD + Integer.toString(i) +
+ "_" + PROP_LOCATION + "=");
+ }
+ return defParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/AuthorityKeyIdentifierExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/AuthorityKeyIdentifierExt.java
new file mode 100644
index 000000000..d7e058bf8
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/AuthorityKeyIdentifierExt.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.AuthorityKeyIdentifierExtension;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.KeyIdentifier;
+import netscape.security.x509.SubjectKeyIdentifierExtension;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Authority Public Key Extension Policy
+ * Adds the subject public key id extension to certificates.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class AuthorityKeyIdentifierExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ protected static final String PROP_CRITICAL = "critical";
+ protected static final String PROP_ALT_KEYID_TYPE = "AltKeyIdType";
+
+ protected static final String ALT_KEYID_TYPE_SPKISHA1 = "SpkiSHA1";
+ protected static final String ALT_KEYID_TYPE_NONE = "None";
+ protected static final String ALT_KEYID_TYPE_EMPTY = "Empty";
+
+ protected static final boolean DEF_CRITICAL = false;
+ protected static final String DEF_ALT_KEYID_TYPE = ALT_KEYID_TYPE_SPKISHA1;
+
+ protected boolean mEnabled = false;
+ protected IConfigStore mConfig = null;
+
+ // config params.
+ protected boolean mCritical = DEF_CRITICAL;
+ protected String mAltKeyIdType = DEF_ALT_KEYID_TYPE;
+
+ // the extension to add to certs.
+ protected AuthorityKeyIdentifierExtension mTheExtension = null;
+
+ // instance params for console
+ protected Vector<String> mInstanceParams = new Vector<String>();
+
+ // default params for console.
+ protected static Vector<String> mDefaultParams = new Vector<String>();
+ static {
+ // form static default params.
+ mDefaultParams.addElement(PROP_CRITICAL + "=" + DEF_CRITICAL);
+ mDefaultParams.addElement(PROP_ALT_KEYID_TYPE + "=" + DEF_ALT_KEYID_TYPE);
+ }
+
+ public AuthorityKeyIdentifierExt() {
+ NAME = "AuthorityKeyIdentifierExt";
+ DESC = "Adds Authority Key Idenifier Extension to certs";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * Reads configuration file and creates a authority key identifier
+ * extension to add. Key identifier inside the extension is constructed as
+ * the CA's subject key identifier extension if it exists.
+ * If it does not exist this can be configured to use:
+ * (1) sha-1 hash of the CA's subject public key info
+ * (what communicator expects if the CA does not have a subject key
+ * identifier extension) or (2) No extension set (3) Empty sequence
+ * in Authority Key Identifier extension.
+ *
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ca.Policy.rule.<ruleName>.predicate= ca.Policy.rule.<ruleName>.implName= ca.Policy.rule.<ruleName>.enable=true
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+
+ mEnabled = mConfig.getBoolean(
+ IPolicyProcessor.PROP_ENABLE, false);
+ mCritical = mConfig.getBoolean(PROP_CRITICAL, DEF_CRITICAL);
+
+ mAltKeyIdType = mConfig.getString(
+ PROP_ALT_KEYID_TYPE, DEF_ALT_KEYID_TYPE);
+
+ if (mAltKeyIdType.equalsIgnoreCase(ALT_KEYID_TYPE_SPKISHA1))
+ mAltKeyIdType = ALT_KEYID_TYPE_SPKISHA1;
+
+ /*
+ else if (mAltKeyIdType.equalsIgnoreCase(ALT_KEYID_TYPE_EMPTY))
+ mAltKeyIdType = ALT_KEYID_TYPE_EMPTY;
+ */
+ else if (mAltKeyIdType.equalsIgnoreCase(ALT_KEYID_TYPE_NONE))
+ mAltKeyIdType = ALT_KEYID_TYPE_NONE;
+ else {
+ log(ILogger.LL_FAILURE, NAME +
+ CMS.getLogMessage("CA_UNKNOWN_ALT_KEY_ID_TYPE", mAltKeyIdType));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", PROP_ALT_KEYID_TYPE,
+ "value must be one of " + ALT_KEYID_TYPE_SPKISHA1 + ", " + ALT_KEYID_TYPE_NONE));
+ }
+
+ // create authority key id extension.
+ ICertAuthority certAuthority = (ICertAuthority)
+ ((IPolicyProcessor) owner).getAuthority();
+
+ if (certAuthority == null) {
+ // should never get here.
+ String msg = NAME + ": " +
+ "Cannot find the Certificate Manager or Registration Manager";
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CANT_FIND_MANAGER"));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", msg));
+ }
+ if (!(certAuthority instanceof ICertificateAuthority)) {
+ log(ILogger.LL_FAILURE, NAME +
+ CMS.getLogMessage("POLICY_INVALID_POLICY", NAME));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ NAME + " policy can only be used in a Certificate Authority."));
+ }
+ //CertificateChain caChain = certAuthority.getCACertChain();
+ //X509Certificate caCert = caChain.getFirstCertificate();
+ X509CertImpl caCert = certAuthority.getCACert();
+ if (caCert == null || CMS.isPreOpMode()) {
+ return;
+ }
+ KeyIdentifier keyId = formKeyIdentifier(caCert);
+
+ if (keyId != null) {
+ try {
+ mTheExtension = new AuthorityKeyIdentifierExtension(
+ mCritical, keyId, null, null);
+ } catch (IOException e) {
+ String msg = NAME + ": " +
+ "Error forming Authority Key Identifier extension: " + e;
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_ERROR_AUTHORITY_KEY_ID_1", NAME));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", msg));
+ }
+ } else {
+ }
+
+ // form instance params
+ mInstanceParams.addElement(PROP_CRITICAL + "=" + mCritical);
+ mInstanceParams.addElement(PROP_ALT_KEYID_TYPE + "=" + mAltKeyIdType);
+ }
+
+ /**
+ * Adds Authority Key Identifier Extension to a certificate.
+ * If the extension is already there, accept it if it's from the agent,
+ * else replace it.
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ // get certInfo from request.
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO", NAME), "");
+ return PolicyResult.REJECTED;
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certResult = applyCert(req, ci[i]);
+
+ if (certResult == PolicyResult.REJECTED)
+ return certResult;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+
+ try {
+ // if authority key id extension already exists, leave it if
+ // from agent. else replace it.
+ AuthorityKeyIdentifierExtension authorityKeyIdExt = null;
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+
+ try {
+ if (extensions != null) {
+ authorityKeyIdExt = (AuthorityKeyIdentifierExtension)
+ extensions.get(AuthorityKeyIdentifierExtension.NAME);
+ }
+ } catch (IOException e) {
+ // extension isn't there.
+ }
+ if (authorityKeyIdExt != null) {
+ if (agentApproved(req)) {
+ CMS.debug(
+ "AuthorityKeyIdentifierKeyExt: agent approved request id " + req.getRequestId() +
+ " already has authority key id extension with value " +
+ authorityKeyIdExt);
+ return PolicyResult.ACCEPTED;
+ } else {
+ CMS.debug(
+ "AuthorityKeyIdentifierKeyExt: request id from user " + req.getRequestId() +
+ " had authority key identifier - deleted");
+ extensions.delete(AuthorityKeyIdentifierExtension.NAME);
+ }
+ }
+
+ // if no authority key identifier should be set b/c CA does not
+ // have a subject key identifier, return here.
+ if (mTheExtension == null)
+ return PolicyResult.ACCEPTED;
+
+ // add authority key id extension.
+ if (extensions == null) {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ }
+ extensions.set(
+ AuthorityKeyIdentifierExtension.NAME, mTheExtension);
+ CMS.debug(
+ "AuthorityKeyIdentifierKeyExt: added authority key id ext to request " + req.getRequestId());
+ return PolicyResult.ACCEPTED;
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_UNEXPECTED_POLICY_ERROR", NAME, e.toString()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR",
+ NAME, e.getMessage()), "");
+ return PolicyResult.REJECTED;
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("BASE_INVALID_CERT", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR",
+ NAME, "Certificate Info Error"), "");
+ return PolicyResult.REJECTED;
+ }
+ }
+
+ /**
+ * Form the Key Identifier in the Authority Key Identifier extension.
+ * from the CA's cert.
+ * <p>
+ *
+ * @param caCertImpl Certificate Info
+ * @return A Key Identifier.
+ * @throws com.netscape.certsrv.base.EBaseException on error
+ */
+ protected KeyIdentifier formKeyIdentifier(X509CertImpl caCertImpl)
+ throws EBaseException {
+ KeyIdentifier keyId = null;
+
+ // get CA's certInfo.
+ X509CertInfo certInfo = null;
+
+ try {
+ certInfo = (X509CertInfo) caCertImpl.get(
+ X509CertImpl.NAME + "." + X509CertImpl.INFO);
+ if (certInfo == null) {
+ String msg = "Bad CA certificate encountered. " +
+ "TBS Certificate missing.";
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_CERT_FORMAT"));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", NAME + ": " + msg));
+ }
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, NAME + ": " +
+ CMS.getLogMessage("BASE_DECODE_CERT_FAILED_1", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ NAME + " Error decoding the CA Certificate: " + e));
+ }
+
+ // get Key Id from CA's Subject Key Id extension in CA's CertInfo.
+ keyId = getKeyIdentifier(certInfo);
+ if (keyId != null)
+ return keyId;
+
+ // if none exists use the configured alternate.
+ if (mAltKeyIdType == ALT_KEYID_TYPE_SPKISHA1) {
+ keyId = formSpkiSHA1KeyId(certInfo);
+ } /*
+ else if (mAltKeyIdType == ALT_KEYID_TYPE_EMPTY) {
+ keyId = formEmptyKeyId(certInfo);
+ }
+ */else if (mAltKeyIdType == ALT_KEYID_TYPE_NONE) {
+ keyId = null;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ mAltKeyIdType,
+ "Unknown Alternate Key Identifier type."));
+ }
+ return keyId;
+ }
+
+ /**
+ * Get the Key Identifier in a subject key identifier extension from a
+ * CertInfo.
+ *
+ * @param certInfo the CertInfo structure.
+ * @return Key Identifier in a Subject Key Identifier extension if any.
+ */
+ protected KeyIdentifier getKeyIdentifier(X509CertInfo certInfo)
+ throws EBaseException {
+ CertificateExtensions exts = null;
+ SubjectKeyIdentifierExtension subjKeyIdExt = null;
+ KeyIdentifier keyId = null;
+
+ try {
+ exts = (CertificateExtensions) certInfo.get(X509CertInfo.EXTENSIONS);
+ } catch (IOException e) {
+ // extension isn't there.
+ CMS.debug(NAME + ": " + "No extensions found. Error " + e);
+ return null;
+ } catch (CertificateException e) {
+ // extension isn't there.
+ CMS.debug(NAME + ": " + "No extensions found. Error " + e);
+ return null;
+ }
+ if (exts == null)
+ return null;
+
+ try {
+ subjKeyIdExt = (SubjectKeyIdentifierExtension)
+ exts.get(SubjectKeyIdentifierExtension.NAME);
+ } catch (IOException e) {
+ // extension isn't there.
+ CMS.debug(
+ "AuthorityKeyIdentifierKeyExt: No Subject Key Identifier Extension found. Error: " + e);
+ return null;
+ }
+ if (subjKeyIdExt == null)
+ return null;
+
+ try {
+ keyId = (KeyIdentifier) subjKeyIdExt.get(
+ SubjectKeyIdentifierExtension.KEY_ID);
+ } catch (IOException e) {
+ // no key identifier in subject key id extension.
+ String msg = NAME + ": " +
+ "Bad Subject Key Identifier Extension found. Error: " + e;
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_ERROR_AUTHORITY_KEY_ID_1", NAME));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", msg));
+ }
+ return keyId;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ return mInstanceParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return mDefaultParams;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_CRITICAL + ";boolean;" +
+ "RFC 2459 recommendation: MUST NOT be marked critical.",
+ PROP_ALT_KEYID_TYPE + ";" +
+ "choice(" + ALT_KEYID_TYPE_SPKISHA1 + "," + ALT_KEYID_TYPE_NONE + ");" +
+ "Specifies whether to use a SHA1 hash of the CA's subject " +
+ "public key info for key identifier or leave out the " +
+ "authority key identifier extension if the CA certificate " +
+ "does not have a Subject Key Identifier extension.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-authkeyid",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Adds Authority Key Identifier Extension. " +
+ "See RFC 2459 (4.2.1.1)"
+ };
+
+ return params;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/BasicConstraintsExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/BasicConstraintsExt.java
new file mode 100644
index 000000000..eeee26994
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/BasicConstraintsExt.java
@@ -0,0 +1,508 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotDefined;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Basic Constraints policy.
+ * Adds the Basic constraints extension.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class BasicConstraintsExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ protected static final String PROP_MAXPATHLEN = "maxPathLen";
+ protected static final String PROP_IS_CA = "isCA";
+ protected static final String PROP_IS_CRITICAL = "critical";
+
+ protected static final String ARG_PATHLEN = "BasicConstraintsPathLen";
+
+ protected int mMaxPathLen = 0; // < 0 means unlimited
+ protected String mOrigMaxPathLen = ""; // for UI display only
+ protected boolean mCritical = true;
+ protected int mDefaultMaxPathLen = 0; // depends on the CA's path length.
+ protected int mCAPathLen = 0;
+ protected boolean mRemoveExt = true;
+ protected boolean mIsCA = true;
+
+ public static final boolean DEFAULT_CRITICALITY = true;
+
+ /**
+ * Adds the basic constraints extension as a critical extension in
+ * CA certificates i.e. certype is ca, with either a requested
+ * or configured path len.
+ * The requested or configured path length cannot be greater than
+ * or equal to the CA's basic constraints path length.
+ * If the CA path length is 0, all requests for CA certs are rejected.
+ */
+ public BasicConstraintsExt() {
+ NAME = "BasicConstraintsExt";
+ DESC =
+ "Sets critical basic constraints extension in subordinate CA certs";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <p>
+ * The entries may be of the form:
+ *
+ * ca.Policy.rule.<ruleName>.implName=BasicConstraintsExtImpl ca.Policy.rule.<ruleName>.pathLen=<n>, -1 for
+ * undefined. ca.Policy.rule.<ruleName>.enable=true
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+
+ // get the CA's path len to check against configured max path len.
+ ICertAuthority certAuthority = (ICertAuthority)
+ ((IPolicyProcessor) owner).getAuthority();
+
+ if (certAuthority == null) {
+ // should never get here.
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CANT_FIND_MANAGER"));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Cannot find the Certificate Manager or Registration Manager"));
+ }
+ if (certAuthority instanceof IRegistrationAuthority) {
+ log(ILogger.LL_WARN,
+ "default basic constraints extension path len to -1.");
+ mCAPathLen = -1;
+ } else {
+ CertificateChain caChain = certAuthority.getCACertChain();
+ if (caChain == null || CMS.isPreOpMode()) {
+ return;
+ }
+ X509Certificate caCert = caChain.getFirstCertificate();
+
+ mCAPathLen = caCert.getBasicConstraints();
+ }
+ // set default to one less than the CA's pathlen or 0 if CA's
+ // pathlen is 0.
+ // If it's unlimited default the max pathlen also to unlimited.
+ if (mCAPathLen < 0)
+ mDefaultMaxPathLen = -1;
+ else if (mCAPathLen > 0)
+ mDefaultMaxPathLen = mCAPathLen - 1;
+ else // (mCAPathLen == 0)
+ {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("POLICY_PATHLEN_ZERO"));
+ //return;
+ }
+
+ // get configured max path len, use defaults if not configured.
+ boolean pathLenConfigured = true;
+
+ try {
+ mCritical = config.getBoolean(PROP_IS_CRITICAL, true);
+ mIsCA = config.getBoolean(PROP_IS_CA, true);
+ mMaxPathLen = config.getInteger(PROP_MAXPATHLEN);
+ if (mMaxPathLen < 0) {
+ log(ILogger.LL_MISCONF,
+ CMS.getLogMessage("POLICY_INVALID_MAXPATHLEN_4", "",
+ String.valueOf(mMaxPathLen)));
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_MAXPATHLEN_1",
+ NAME, String.valueOf(mMaxPathLen)));
+ }
+ mOrigMaxPathLen = Integer.toString(mMaxPathLen);
+ } catch (EBaseException e) {
+ if (!(e instanceof EPropertyNotFound) &&
+ !(e instanceof EPropertyNotDefined)) {
+ log(ILogger.LL_MISCONF,
+ CMS.getLogMessage("POLICY_INVALID_MAXPATHLEN"));
+ throw e;
+ }
+
+ // Set the max path len to default if not configured.
+ pathLenConfigured = false;
+ mMaxPathLen = mDefaultMaxPathLen;
+ mOrigMaxPathLen = "";
+ }
+
+ // check if configured path len is valid.
+ if (pathLenConfigured) {
+ // if CA's pathlen is unlimited, any max pathlen is ok.
+ // else maxPathlen must be at most one less than the CA's
+ // pathlen or 0 if CA's pathlen is 0.
+
+ if (mCAPathLen > 0 &&
+ (mMaxPathLen >= mCAPathLen || mMaxPathLen < 0)) {
+ String maxStr = (mMaxPathLen < 0) ?
+ String.valueOf(mMaxPathLen) + "(unlimited)" :
+ String.valueOf(mMaxPathLen);
+
+ log(ILogger.LL_MISCONF,
+ CMS.getLogMessage("POLICY_MAXPATHLEN_TOO_BIG_3", "",
+ maxStr,
+ String.valueOf(mCAPathLen)));
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_MAXPATHLEN_TOO_BIG_1",
+ NAME, maxStr, Integer.toString(mCAPathLen)));
+ } else if (mCAPathLen == 0 && mMaxPathLen != 0) {
+ log(ILogger.LL_MISCONF,
+ CMS.getLogMessage("POLICY_INVALID_MAXPATHLEN_2", "", String.valueOf(mMaxPathLen)));
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_MAXPATHLEN",
+ NAME, String.valueOf(mMaxPathLen)));
+ }
+ }
+
+ }
+
+ /**
+ * Checks if the basic contraints extension in certInfo is valid and
+ * add the basic constraints extension for CA certs if none exists.
+ * Non-CA certs do not get a basic constraints extension.
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+
+ // get cert info.
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ X509CertInfo certInfo = null;
+
+ if (ci == null || (certInfo = ci[0]) == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO", NAME), "");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ // get cert type
+ boolean isCA = mIsCA;
+
+ /**
+ * boolean isCA = false;
+ * String type = (String)req.get(IRequest.HTTP_PARAMS, IRequest.CERT_TYPE);
+ * if (type != null && type.equalsIgnoreCase(IRequest.CA_CERT)) {
+ * isCA = true;
+ * }
+ **/
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certResult = applyCert(req, isCA, certInfo);
+
+ if (certResult == PolicyResult.REJECTED)
+ return certResult;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(
+ IRequest req, boolean isCA, X509CertInfo certInfo) {
+
+ // get basic constraints extension from cert info if any.
+ CertificateExtensions extensions = null;
+ BasicConstraintsExtension basicExt = null;
+
+ try {
+ // get basic constraints extension if any.
+ extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+ if (extensions != null) {
+ basicExt = (BasicConstraintsExtension)
+ extensions.get(BasicConstraintsExtension.NAME);
+ }
+ } catch (IOException e) {
+ // no extensions or basic constraints extension.
+ } catch (CertificateException e) {
+ // no extensions or basic constraints extension.
+ }
+
+ // for non-CA certs, pkix says it SHOULD NOT have the extension
+ // so remove it.
+ if (!isCA) {
+ if (extensions == null) {
+ try {
+ // create extensions set if none.
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ } catch (CertificateException e) {
+ } catch (IOException e) {
+ // not possible
+ }
+ }
+ if (basicExt != null) {
+ try {
+ extensions.delete(BasicConstraintsExtension.NAME);
+ } catch (IOException e) {
+ }
+ }
+
+ BasicConstraintsExtension critExt;
+
+ try {
+ critExt = new BasicConstraintsExtension(isCA, mCritical, mMaxPathLen);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_BASIC_CONSTRAINTS_2",
+ e.toString()));
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_BASIC_CONSTRAINTS_ERROR", NAME), "");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ try {
+ extensions.set(BasicConstraintsExtension.NAME, critExt);
+ } catch (IOException e) {
+ }
+ CMS.debug(
+ "BasicConstraintsExt: PolicyRule BasicConstraintsExt: added the extension to request " +
+ req.getRequestId());
+ return PolicyResult.ACCEPTED;
+ }
+
+ // For CA certs, check if existing extension is valid, and adjust.
+ // Extension must be marked critial and pathlen must be < CA's pathlen.
+ // if CA's pathlen is 0 all ca certs are rejected.
+
+ if (mCAPathLen == 0) {
+ // reject all subordinate CA cert requests because CA's
+ // path length is 0.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_NO_SUB_CA_CERTS_ALLOWED_1", NAME));
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_SUB_CA_CERTS_ALLOWED", NAME), "");
+ return PolicyResult.REJECTED;
+ }
+
+ if (basicExt != null) {
+ try {
+ boolean extIsCA =
+ ((Boolean) basicExt.get(BasicConstraintsExtension.IS_CA)).booleanValue();
+ int pathLen =
+ ((Integer) basicExt.get(BasicConstraintsExtension.PATH_LEN)).intValue();
+
+ if (mMaxPathLen > -1) {
+ if (pathLen > mMaxPathLen || pathLen < 0) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_MAXPATHLEN_TOO_BIG_3", NAME, "unlimited",
+ String.valueOf(pathLen)));
+ if (pathLen < 0)
+ setError(req, CMS.getUserMessage("CMS_POLICY_MAXPATHLEN_TOO_BIG",
+ NAME, "unlimited", Integer.toString(mMaxPathLen)), "");
+ else
+ setError(req, CMS.getUserMessage("CMS_POLICY_MAXPATHLEN_TOO_BIG",
+ NAME, Integer.toString(pathLen),
+ Integer.toString(mMaxPathLen)), "");
+ return PolicyResult.REJECTED;
+ }
+ }
+
+ // adjust isCA field
+ if (!extIsCA) {
+ basicExt.set(BasicConstraintsExtension.IS_CA,
+ Boolean.valueOf(true));
+ }
+
+ // adjust path length field.
+ if (mMaxPathLen == 0) {
+ if (pathLen != 0) {
+ basicExt.set(BasicConstraintsExtension.PATH_LEN,
+ Integer.valueOf(0));
+ pathLen = 0;
+ }
+ } else if (mMaxPathLen > 0 && pathLen > mMaxPathLen) {
+ basicExt.set(BasicConstraintsExtension.PATH_LEN,
+ Integer.valueOf(mMaxPathLen));
+ pathLen = mMaxPathLen;
+ }
+
+ // adjust critical field.
+ if (!basicExt.isCritical()) {
+ BasicConstraintsExtension critExt;
+
+ try {
+ critExt = new BasicConstraintsExtension(isCA, mCritical, pathLen);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_BASIC_CONSTRAINTS_1", NAME));
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_BASIC_CONSTRAINTS_ERROR", NAME), "");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+ extensions.delete(BasicConstraintsExtension.NAME);
+ extensions.set(BasicConstraintsExtension.NAME, critExt);
+ }
+ } catch (IOException e) {
+ // not possible in these cases.
+ }
+ CMS.debug(
+ "BasicConstraintsExt: PolicyRule BasicConstraintsExt: added the extension to request " +
+ req.getRequestId());
+ return PolicyResult.ACCEPTED;
+ }
+
+ // add the extension for the CA cert.
+ if (extensions == null) {
+ try {
+ // create extensions set if none.
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ } catch (CertificateException e) {
+ // not possible
+ } catch (IOException e) {
+ // not possible
+ }
+ }
+
+ // set path len to requested path len if it's valid.
+ // if no path len requested set path len to max allowed path len.
+ String reqPathLenStr = req.getExtDataInString(ARG_PATHLEN);
+ int reqPathLen;
+
+ if (reqPathLenStr == null) {
+ reqPathLen = mMaxPathLen;
+ } else {
+ try {
+ reqPathLen = Integer.parseInt(reqPathLenStr);
+ if ((mMaxPathLen == 0 && reqPathLen != 0) ||
+ (mMaxPathLen > 0 &&
+ (reqPathLen > mMaxPathLen || reqPathLen < 0))) {
+ String plenStr =
+ ((reqPathLen < 0) ?
+ reqPathLenStr + "(unlimited)" : reqPathLenStr);
+
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_PATHLEN_TOO_BIG_3", plenStr,
+ String.valueOf(mMaxPathLen)));
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_PATHLEN_TOO_BIG",
+ NAME, plenStr, String.valueOf(mMaxPathLen)), "");
+ return PolicyResult.REJECTED;
+ }
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_INVALID_PATHLEN_FORMAT_2", NAME, reqPathLenStr));
+ setError(req, CMS.getUserMessage("CMS_POLICY_INVALID_PATHLEN_FORMAT",
+ NAME, reqPathLenStr), "");
+ return PolicyResult.REJECTED;
+ }
+ }
+ BasicConstraintsExtension newExt;
+
+ try {
+ newExt = new BasicConstraintsExtension(isCA, mCritical, reqPathLen);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_BASIC_CONSTRAINTS_2", e.toString()));
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_BASIC_CONSTRAINTS_ERROR", NAME), "");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+ try {
+ extensions.set(BasicConstraintsExtension.NAME, newExt);
+ } catch (IOException e) {
+ // doesn't happen.
+ }
+ CMS.debug(
+ "BasicConstraintsExt: added the extension to request " +
+ req.getRequestId());
+ return PolicyResult.ACCEPTED;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> params = new Vector<String>();
+
+ // Because of one of the UI bugs 385273, we should leave the empty space
+ // as is. Do not convert the space to some definite numbers.
+ params.addElement(PROP_MAXPATHLEN + "=" + mOrigMaxPathLen);
+ params.addElement(PROP_IS_CRITICAL + "=" + mCritical);
+ params.addElement(PROP_IS_CA + "=" + mIsCA);
+ return params;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> defParams = new Vector<String>();
+
+ defParams.addElement(PROP_IS_CRITICAL + "=true");
+ defParams.addElement(PROP_MAXPATHLEN + "=");
+ defParams.addElement(PROP_IS_CA + "=true");
+ return defParams;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_MAXPATHLEN
+ + ";number;'0' means : no subordinates allowed, 'n' means : at most n subordinates allowed.",
+ PROP_IS_CRITICAL + ";boolean;" +
+ "RFC 2459 recommendation: MUST be critical in CA certs, SHOULD NOT appear in EE certs.",
+ PROP_IS_CA + ";boolean;" +
+ "Identifies the subject of the certificate is a CA or not.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-basicconstraints",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Adds the Basic Constraints extension. See RFC 2459 (4.2.1.10)"
+ };
+
+ return params;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/CRLDistributionPointsExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/CRLDistributionPointsExt.java
new file mode 100644
index 000000000..7cf50385e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/CRLDistributionPointsExt.java
@@ -0,0 +1,484 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.security.util.BitArray;
+import netscape.security.x509.CRLDistributionPoint;
+import netscape.security.x509.CRLDistributionPointsExtension;
+import netscape.security.x509.CRLDistributionPointsExtension.Reason;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.GeneralNamesException;
+import netscape.security.x509.RDN;
+import netscape.security.x509.URIName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * The type of the distribution point or issuer name. The name is expressed
+ * as a simple string in the configuration file, so this attribute is needed
+ * to tell whether the simple string should be stored in an X.500 Name,
+ * a URL, or an RDN.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+class NameType {
+ private NameType() {
+ } // no default constructor
+
+ private String stringRep; // string representation of this type
+
+ private NameType(String s) {
+ map.put(s, this);
+ stringRep = s;
+ }
+
+ private static Hashtable<String, NameType> map = new Hashtable<String, NameType>();
+
+ /**
+ * Looks up a NameType from its string representation. Returns null
+ * if no matching NameType was found.
+ */
+ public static NameType fromString(String s) {
+ return map.get(s);
+ }
+
+ public String toString() {
+ return stringRep;
+ }
+
+ public static final NameType DIRECTORY_NAME = new NameType("DirectoryName");
+ public static final NameType URI = new NameType("URI");
+ public static final NameType RELATIVE_TO_ISSUER =
+ new NameType("RelativeToIssuer");
+}
+
+/**
+ * These are the parameters that may be given in the configuration file
+ * for each distribution point. They are parsed by DPParamsToDP().
+ * Any of them may be null.
+ */
+class DistPointParams {
+ public String pointName;
+ public String pointType;
+
+ public String reasons;
+
+ public String issuerName;
+ public String issuerType;
+
+ public DistPointParams() {
+ }
+
+ public DistPointParams(DistPointParams old) {
+ pointName = old.pointName;
+ pointType = old.pointType;
+ reasons = old.reasons;
+ issuerName = old.issuerName;
+ issuerType = old.issuerType;
+ }
+
+}
+
+/**
+ * CRL Distribution Points policy.
+ * Adds the CRL Distribution Points extension to the certificate.
+ */
+public class CRLDistributionPointsExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+
+ public static final String PROP_IS_CRITICAL = "critical";
+ public static final String PROP_NUM_POINTS = "numPoints";
+ public static final String PROP_POINT_TYPE = "pointType";
+ public static final String PROP_POINT_NAME = "pointName";
+ public static final String PROP_REASONS = "reasons";
+ public static final String PROP_ISSUER_NAME = "issuerName";
+ public static final String PROP_ISSUER_TYPE = "issuerType";
+
+ private static final int MAX_POINTS = 10;
+ private static final int DEFAULT_NUM_BLANK_POINTS = 3;
+ private int mNumPoints = DEFAULT_NUM_BLANK_POINTS;
+
+ // PKIX specifies the that the extension SHOULD NOT be critical
+ public static final boolean DEFAULT_CRITICALITY = false;
+
+ private Vector<String> defaultParams = new Vector<String>();
+
+ private Vector<String> mParams = new Vector<String>();
+ private String mExtParams[] = null;
+ private CRLDistributionPointsExtension mCrldpExt = null;
+
+ public CRLDistributionPointsExt() {
+ NAME = "CRLDistributionPointsExt";
+ DESC = "Sets CRL distribution points extension";
+ defaultParams.addElement(PROP_IS_CRITICAL + "=" + DEFAULT_CRITICALITY);
+ defaultParams.addElement(PROP_NUM_POINTS + "=0");
+ for (int i = 0; i < DEFAULT_NUM_BLANK_POINTS; i++) {
+ defaultParams.addElement(PROP_POINT_NAME + i + "=");
+ defaultParams.addElement(PROP_POINT_TYPE + i + "=");
+ defaultParams.addElement(PROP_REASONS + i + "=");
+ defaultParams.addElement(PROP_ISSUER_NAME + i + "=");
+ defaultParams.addElement(PROP_ISSUER_TYPE + i + "=");
+ }
+ }
+
+ private void setExtendedPluginInfo() {
+ Vector<String> v = new Vector<String>();
+
+ // should replace MAX_POINTS with mNumPoints if bug 385118 is fixed
+ for (int i = 0; i < MAX_POINTS; i++) {
+ v.addElement(PROP_POINT_TYPE + Integer.toString(i) + ";choice(" +
+ "DirectoryName,URI,RelativeToIssuer);" +
+ "The type of the CRL distribution point.");
+ v.addElement(PROP_POINT_NAME + Integer.toString(i) + ";string;" +
+ "The name of the CRL distribution point depending on the CRLDP type.");
+ v.addElement(PROP_REASONS
+ + Integer.toString(i)
+ + ";string;"
+ +
+ "The revocation reasons for the CRL maintained at this distribution point. It's a comma-seperated list of the following constants: unused, keyCompromise, cACompromise, affiliationChanged, superseded, cessationOfOperation, certificateHold.");
+ v.addElement(PROP_ISSUER_TYPE + Integer.toString(i) + ";choice(" +
+ "DirectoryName,URI);" +
+ "The type of the issuer that has signed the CRL maintained at this distribution point.");
+ v.addElement(PROP_ISSUER_NAME
+ + Integer.toString(i)
+ + ";string;"
+ +
+ "The name of the issuer that has signed the CRL maintained at this distribution point. The value depends on the issuer type.");
+ }
+
+ v.addElement(PROP_NUM_POINTS +
+ ";number;The total number of CRL distribution points to be contained or allowed in the extension.");
+ v.addElement(PROP_IS_CRITICAL
+ +
+ ";boolean;RFC 2459 recommendation: SHOULD be non-critical. But recommends support for this extension by CAs and applications.");
+ v.addElement(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-crldistributionpoints");
+ v.addElement(IExtendedPluginInfo.HELP_TEXT +
+ ";This policy inserts the CRL Distribution Points " +
+ "Extension into the certificate. See RFC 2459 (4.2.1.14). "
+ );
+
+ mExtParams = com.netscape.cmsutil.util.Utils.getStringArrayFromVector(v);
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ if (mExtParams == null) {
+ setExtendedPluginInfo();
+ }
+ return mExtParams;
+
+ }
+
+ /**
+ * Performs one-time initialization of the policy.
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ // Register the CRL Distribution Points extension.
+ try {
+ netscape.security.x509.OIDMap.addAttribute(
+ CRLDistributionPointsExtension.class.getName(),
+ CRLDistributionPointsExtension.OID,
+ CRLDistributionPointsExtension.NAME);
+ } catch (CertificateException e) {
+ // ignore, just means it has already been added
+ }
+
+ // assemble the list of Distribution Points from the config file
+ int numPoints = config.getInteger(PROP_NUM_POINTS, 0);
+
+ mParams.addElement(PROP_NUM_POINTS + "=" + numPoints);
+ mNumPoints = numPoints;
+
+ for (int i = 0; i < numPoints; i++) {
+ // construct a distribution point from the parameters
+ DistPointParams params = new DistPointParams();
+
+ params.pointType = config.getString(PROP_POINT_TYPE + i, "");
+ params.pointName = config.getString(PROP_POINT_NAME + i, "");
+ params.reasons = config.getString(PROP_REASONS + i, "");
+ params.issuerType = config.getString(PROP_ISSUER_TYPE + i, "");
+ params.issuerName = config.getString(PROP_ISSUER_NAME + i, "");
+
+ DistPointParams configparams = new DistPointParams(params);
+ CRLDistributionPoint crldp = DPParamsToDP(params);
+
+ mParams.addElement(PROP_POINT_TYPE + i + "=" + configparams.pointType);
+ mParams.addElement(PROP_POINT_NAME + i + "=" + configparams.pointName);
+ mParams.addElement(PROP_REASONS + i + "=" + configparams.reasons);
+ mParams.addElement(PROP_ISSUER_TYPE + i + "=" + configparams.issuerType);
+ mParams.addElement(PROP_ISSUER_NAME + i + "=" + configparams.issuerName);
+
+ // add the distribution point to the extension
+ if (mCrldpExt == null) {
+ mCrldpExt = new CRLDistributionPointsExtension(crldp);
+ } else {
+ mCrldpExt.addPoint(crldp);
+ }
+ }
+
+ boolean crit = config.getBoolean(PROP_IS_CRITICAL,
+ DEFAULT_CRITICALITY);
+
+ mParams.addElement(PROP_IS_CRITICAL + "=" + crit);
+ if (mCrldpExt != null) {
+ // configure the extension itself
+ mCrldpExt.setCritical(crit);
+ }
+ setExtendedPluginInfo();
+
+ }
+
+ /**
+ * Parses the parameters in the config file to create an
+ * actual CRL Distribution Point object.
+ */
+ private CRLDistributionPoint DPParamsToDP(DistPointParams params)
+ throws EBaseException {
+ CRLDistributionPoint crlDP = new CRLDistributionPoint();
+
+ try {
+
+ if (params.pointName != null && params.pointName.length() == 0) {
+ params.pointName = null;
+ }
+ if (params.pointType != null && params.pointType.length() == 0) {
+ params.pointType = null;
+ }
+ if (params.reasons != null && params.reasons.length() == 0) {
+ params.reasons = null;
+ }
+ if (params.issuerName != null && params.issuerName.length() == 0) {
+ params.issuerName = null;
+ }
+ if (params.issuerType != null && params.issuerType.length() == 0) {
+ params.issuerType = null;
+ }
+
+ // deal with the distribution point name
+ if (params.pointName != null && params.pointType != null) {
+ // decode the type of the name
+ NameType nType = NameType.fromString(params.pointType);
+
+ if (nType == null) {
+ String err = "Unknown name type: " + params.pointType;
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_UNKNOWN_NAME_TYPE", params.pointType));
+ throw new EBaseException(err);
+ }
+
+ if (nType == NameType.DIRECTORY_NAME) {
+ GeneralNames gen = new GeneralNames();
+
+ gen.addElement(new GeneralName(new X500Name(params.pointName)));
+ crlDP.setFullName(gen);
+ } else if (nType == NameType.URI) {
+ GeneralNames gen = new GeneralNames();
+
+ gen.addElement(new GeneralName(new URIName(params.pointName)));
+ crlDP.setFullName(gen);
+ } else if (nType == NameType.RELATIVE_TO_ISSUER) {
+ crlDP.setRelativeName(new RDN(params.pointName));
+ } else {
+ String err = "Unknown name type: " + nType.toString();
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_UNKNOWN_NAME_TYPE", nType.toString()));
+ throw new EBaseException(err);
+ }
+ }
+
+ // deal with the reasons
+ if (params.reasons != null) {
+ StringTokenizer tok = new StringTokenizer(params.reasons, ", \t");
+ byte reasonBits = 0;
+
+ while (tok.hasMoreTokens()) {
+ String s = tok.nextToken();
+ Reason r = Reason.fromString(s);
+
+ if (r == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_UNKNOWN_REASON", s));
+ throw new EBaseException("Unknown reason: " + s);
+ } else {
+ reasonBits |= r.getBitMask();
+ }
+ }
+ if (reasonBits != 0) {
+ BitArray ba = new BitArray(8, new byte[] { reasonBits }
+ );
+
+ crlDP.setReasons(ba);
+ }
+ }
+
+ // deal with the issuer name
+ if (params.issuerName != null && params.issuerType != null) {
+ // decode the type of the name
+ NameType nType = NameType.fromString(params.issuerType);
+
+ if (nType == null) {
+ String err = "Unknown name type: " + params.issuerType;
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_UNKNOWN_NAME_TYPE", params.issuerType));
+ throw new EBaseException(err);
+ }
+
+ if (nType == NameType.DIRECTORY_NAME) {
+ GeneralNames gen = new GeneralNames();
+
+ gen.addElement(new GeneralName(new X500Name(params.issuerName)));
+ crlDP.setCRLIssuer(gen);
+ } else if (nType == NameType.URI) {
+ GeneralNames gen = new GeneralNames();
+
+ gen.addElement(new GeneralName(new URIName(params.issuerName)));
+ crlDP.setCRLIssuer(gen);
+ } else {
+ String err = "Unknown name type: " + nType.toString();
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_UNKNOWN_NAME_TYPE", nType.toString()));
+ throw new EBaseException(err);
+ }
+ }
+
+ } catch (GeneralNamesException e) {
+ throw new EBaseException(e.getMessage());
+ } catch (IOException e) {
+ throw new EBaseException(e.getMessage());
+ }
+
+ // done, return this distribution point
+ return crlDP;
+ }
+
+ /**
+ * Applies the policy to the given request.
+ */
+ public PolicyResult apply(IRequest req) {
+
+ // if the extension was not configured correctly, just skip it
+ if (mCrldpExt == null) {
+ return PolicyResult.ACCEPTED;
+ }
+
+ X509CertInfo[] ci = req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED;
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certRes = applyCert(req, ci[i]);
+
+ if (certRes == PolicyResult.REJECTED)
+ return certRes;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+
+ try {
+ // find the extensions in the certInfo
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+
+ // prepare the extensions data structure
+ if (extensions == null) {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ } else {
+ // remove any previously computed version of the extension
+ try {
+ extensions.delete(CRLDistributionPointsExtension.NAME);
+ } catch (IOException e) {
+ // extension isn't there
+ }
+ }
+ extensions.set(CRLDistributionPointsExtension.NAME, mCrldpExt);
+
+ return PolicyResult.ACCEPTED;
+
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_UNEXPECTED_POLICY_ERROR", NAME, e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"), NAME,
+ e.getMessage());
+ return PolicyResult.REJECTED;
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR",
+ e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"), NAME,
+ e.getMessage());
+ return PolicyResult.REJECTED;
+ }
+ }
+
+ // parameters must be entered in the config file
+ public Vector<String> getDefaultParams() {
+ for (int i = DEFAULT_NUM_BLANK_POINTS; i < mNumPoints; i++) {
+ defaultParams.addElement(PROP_POINT_NAME + i + "=");
+ defaultParams.addElement(PROP_POINT_TYPE + i + "=");
+ defaultParams.addElement(PROP_REASONS + i + "=");
+ defaultParams.addElement(PROP_ISSUER_NAME + i + "=");
+ defaultParams.addElement(PROP_ISSUER_TYPE + i + "=");
+ }
+ return defaultParams;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ return mParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/CertificatePoliciesExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/CertificatePoliciesExt.java
new file mode 100644
index 000000000..4124d430d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/CertificatePoliciesExt.java
@@ -0,0 +1,534 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.CPSuri;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificatePoliciesExtension;
+import netscape.security.x509.CertificatePolicyId;
+import netscape.security.x509.CertificatePolicyInfo;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.DisplayText;
+import netscape.security.x509.NoticeReference;
+import netscape.security.x509.PolicyQualifierInfo;
+import netscape.security.x509.PolicyQualifiers;
+import netscape.security.x509.UserNotice;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Certificate Policies.
+ * Adds certificate policies extension.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class CertificatePoliciesExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ protected static final String PROP_CRITICAL = "critical";
+ protected static final String PROP_NUM_CERTPOLICIES = "numCertPolicies";
+
+ protected static final String PROP_CERTPOLICY = "certPolicy";
+
+ protected static final boolean DEF_CRITICAL = false;
+ protected static final int DEF_NUM_CERTPOLICIES = 1;
+
+ protected boolean mEnabled = false;
+ protected IConfigStore mConfig = null;
+
+ protected boolean mCritical = DEF_CRITICAL;
+ protected int mNumCertPolicies = DEF_NUM_CERTPOLICIES;
+ protected CertPolicy[] mCertPolicies = null;
+
+ protected Vector<String> mInstanceParams = new Vector<String>();
+ protected CertificatePoliciesExtension mCertificatePoliciesExtension = null;
+
+ public CertificatePoliciesExt() {
+ NAME = "CertificatePoliciesExt";
+ DESC = "Sets non-critical certificate policies extension in certs";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ca.Policy.rule.<ruleName>.predicate=certType==ca ca.Policy.rule.<ruleName>.implName=
+ * ca.Policy.rule.<ruleName>.enable=true
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+
+ mEnabled = mConfig.getBoolean(
+ IPolicyProcessor.PROP_ENABLE, false);
+ mCritical = mConfig.getBoolean(PROP_CRITICAL, DEF_CRITICAL);
+
+ mNumCertPolicies = mConfig.getInteger(
+ PROP_NUM_CERTPOLICIES, DEF_NUM_CERTPOLICIES);
+ if (mNumCertPolicies < 1) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_ATTR_VALUE_2", NAME, ""));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ PROP_NUM_CERTPOLICIES,
+ "value must be greater than or equal to 1"));
+ }
+
+ // init Policy Mappings, check values if enabled.
+ mCertPolicies = new CertPolicy[mNumCertPolicies];
+ for (int i = 0; i < mNumCertPolicies; i++) {
+ String subtreeName = PROP_CERTPOLICY + i;
+
+ try {
+ mCertPolicies[i] = new CertPolicy(subtreeName, mConfig, mEnabled);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, NAME + ": " +
+ CMS.getLogMessage("POLICY_ERROR_CREATE_CERT_POLICY", e.toString()));
+ throw e;
+ }
+ }
+
+ // create instance of certificate policy extension if enabled.
+ if (mEnabled) {
+ try {
+ Vector<CertificatePolicyInfo> CertPolicies = new Vector<CertificatePolicyInfo>();
+
+ for (int j = 0; j < mNumCertPolicies; j++) {
+ CertPolicies.addElement(
+ mCertPolicies[j].mCertificatePolicyInfo);
+ }
+ mCertificatePoliciesExtension =
+ new CertificatePoliciesExtension(mCritical, CertPolicies);
+ } catch (IOException e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Error initializing " + NAME + " Error: " + e));
+ }
+ }
+
+ // form instance params
+ mInstanceParams.addElement(PROP_CRITICAL + "=" + mCritical);
+ mInstanceParams.addElement(
+ PROP_NUM_CERTPOLICIES + "=" + mNumCertPolicies);
+ for (int i = 0; i < mNumCertPolicies; i++) {
+ mCertPolicies[i].getInstanceParams(mInstanceParams);
+ }
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <p>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+
+ // get certInfo from request.
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED;
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certRes = applyCert(req, ci[i]);
+
+ if (certRes == PolicyResult.REJECTED)
+ return certRes;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+ CertificateExtensions extensions = null;
+
+ try {
+ extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+ if (extensions == null) {
+ extensions = new CertificateExtensions();
+ try {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ } catch (Exception e) {
+ }
+ } else {
+ // remove any previously computed version of the extension
+ try {
+ extensions.delete(CertificatePoliciesExtension.NAME);
+ } catch (IOException e) {
+ // this is the hack: for some reason, the key which is the name
+ // of the policy has been converted into the OID
+ try {
+ extensions.delete("2.5.29.32");
+ } catch (IOException ee) {
+ }
+ }
+ }
+ extensions.set(CertificatePoliciesExtension.NAME,
+ mCertificatePoliciesExtension);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_ERROR_CERTIFICATE_POLICIES_1",
+ e.toString()));
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_CERTIFICATE_POLICIES_ERROR"), NAME);
+ return PolicyResult.REJECTED;
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_ERROR_CERTIFICATE_POLICIES_1",
+ e.toString()));
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_CERTIFICATE_POLICIES_ERROR"), NAME);
+ return PolicyResult.REJECTED;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_ERROR_CERTIFICATE_POLICIES_1",
+ e.toString()));
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_CERTIFICATE_POLICIES_ERROR"), NAME);
+ return PolicyResult.REJECTED;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ return mInstanceParams;
+ }
+
+ /**
+ * Default config parameters.
+ * To add more permitted or excluded subtrees,
+ * increase the num to greater than 0 and more configuration params
+ * will show up in the console.
+ */
+ private static Vector<String> mDefParams = new Vector<String>();
+ static {
+ mDefParams.addElement(PROP_CRITICAL + "=" + DEF_CRITICAL);
+ mDefParams.addElement(
+ PROP_NUM_CERTPOLICIES + "=" + DEF_NUM_CERTPOLICIES);
+ String certPolicy0Dot = PROP_CERTPOLICY + "0.";
+
+ mDefParams.addElement(
+ certPolicy0Dot + CertPolicy.PROP_POLICY_IDENTIFIER + "=" + "");
+ mDefParams.addElement(
+ certPolicy0Dot + CertPolicy.PROP_NOTICE_REF_ORG + "=" + "");
+ mDefParams.addElement(
+ certPolicy0Dot + CertPolicy.PROP_NOTICE_REF_NUMS + "=" + "");
+ mDefParams.addElement(
+ certPolicy0Dot + CertPolicy.PROP_USER_NOTICE_TEXT + "=" + "");
+ mDefParams.addElement(
+ certPolicy0Dot + CertPolicy.PROP_CPS_URI + "=" + "");
+
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return mDefParams;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ Vector<String> theparams = new Vector<String>();
+
+ theparams.addElement(PROP_CRITICAL + ";boolean;RFC 3280 recommendation: MUST be non-critical.");
+ theparams.addElement(PROP_NUM_CERTPOLICIES
+ + ";number; Number of certificate policies. The value must be greater than or equal to 1");
+
+ for (int k = 0; k < 5; k++) {
+ String certPolicykDot = PROP_CERTPOLICY + k + ".";
+
+ theparams.addElement(certPolicykDot +
+ CertPolicy.PROP_POLICY_IDENTIFIER + ";string,required;An object identifier in the form n.n.n.n");
+ theparams.addElement(certPolicykDot +
+ CertPolicy.PROP_NOTICE_REF_ORG + ";string;See RFC 3280 sec 4.2.1.5");
+ theparams.addElement(certPolicykDot +
+ CertPolicy.PROP_NOTICE_REF_NUMS +
+ ";string;comma-separated list of numbers. See RFC 3280 sec 4.2.1.5");
+ theparams.addElement(certPolicykDot +
+ CertPolicy.PROP_USER_NOTICE_TEXT + ";string;See RFC 3280 sec 4.2.1.5");
+ theparams.addElement(certPolicykDot +
+ CertPolicy.PROP_CPS_URI + ";string;See RFC 3280 sec 4.2.1.5");
+ }
+
+ theparams.addElement(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-certificatepolicies");
+ theparams.addElement(IExtendedPluginInfo.HELP_TEXT +
+ ";Adds Certificate Policies Extension. See RFC 3280 (4.2.1.5)");
+
+ String[] params = new String[theparams.size()];
+
+ theparams.copyInto(params);
+ return params;
+ }
+}
+
+class CertPolicy {
+
+ protected static final String PROP_POLICY_IDENTIFIER = "policyId";
+ protected static final String PROP_NOTICE_REF_ORG = "noticeRefOrganization";
+ protected static final String PROP_NOTICE_REF_NUMS = "noticeRefNumbers";
+ protected static final String PROP_USER_NOTICE_TEXT = "userNoticeExplicitText";
+ protected static final String PROP_CPS_URI = "cpsURI";
+
+ protected String mName = null;
+ protected String mNameDot = null;
+ protected IConfigStore mConfig = null;
+
+ protected String mPolicyId = null;
+ protected String mNoticeRefOrg = null;
+ protected String mNoticeRefNums = null;
+ protected String mNoticeRefExplicitText = null;
+ protected String mCpsUri = null;
+
+ protected CertificatePolicyInfo mCertificatePolicyInfo = null;
+
+ /**
+ * forms policy map parameters.
+ *
+ * @param name name of this policy map, for example certPolicy0
+ * @param config parent's config from where we find this configuration.
+ * @param enabled whether policy was enabled.
+ */
+ protected CertPolicy(String name, IConfigStore config, boolean enabled)
+ throws EBaseException {
+ mName = name;
+ mConfig = config.getSubStore(mName);
+ mNameDot = mName + ".";
+
+ if (mConfig == null) {
+ CMS.debug("CertificatePoliciesExt::CertPolicy - mConfig is " +
+ "null!");
+ throw new EBaseException("mConfig is null");
+ }
+
+ // if there's no configuration for this policy put it there.
+ if (mConfig.size() == 0) {
+ config.putString(mNameDot + PROP_POLICY_IDENTIFIER, "");
+ config.putString(mNameDot + PROP_NOTICE_REF_ORG, "");
+ config.putString(mNameDot + PROP_NOTICE_REF_NUMS, "");
+ config.putString(mNameDot + PROP_USER_NOTICE_TEXT, "");
+ config.putString(mNameDot + PROP_CPS_URI, "");
+ mConfig = config.getSubStore(mName);
+ if (mConfig == null || mConfig.size() == 0) {
+ CMS.debug("CertificatePoliciesExt::CertPolicy - mConfig " +
+ "is null or empty!");
+ throw new EBaseException("mConfig is null or empty");
+ }
+ }
+
+ // get policy ids from configuration.
+ mPolicyId = mConfig.getString(PROP_POLICY_IDENTIFIER, null);
+ mNoticeRefOrg = mConfig.getString(PROP_NOTICE_REF_ORG, null);
+ mNoticeRefNums = mConfig.getString(PROP_NOTICE_REF_NUMS, null);
+ mNoticeRefExplicitText = mConfig.getString(PROP_USER_NOTICE_TEXT, null);
+ mCpsUri = mConfig.getString(PROP_CPS_URI, null);
+
+ // adjust for "" and console returning "null"
+ if (mPolicyId != null &&
+ (mPolicyId.length() == 0 ||
+ mPolicyId.equals("null"))) {
+ mPolicyId = null;
+ }
+ if (mNoticeRefOrg != null &&
+ (mNoticeRefOrg.length() == 0 ||
+ mNoticeRefOrg.equals("null"))) {
+ mNoticeRefOrg = null;
+ }
+ if (mNoticeRefNums != null &&
+ (mNoticeRefNums.length() == 0 ||
+ mNoticeRefNums.equals("null"))) {
+ mNoticeRefNums = null;
+ }
+ if (mNoticeRefExplicitText != null &&
+ (mNoticeRefExplicitText.length() == 0 ||
+ mNoticeRefExplicitText.equals("null"))) {
+ mNoticeRefExplicitText = null;
+ }
+ if (mCpsUri != null &&
+ (mCpsUri.length() == 0 ||
+ mCpsUri.equals("null"))) {
+ mCpsUri = null;
+ }
+
+ // policy ids cannot be null if policy is enabled.
+ String msg = "value cannot be null.";
+
+ if (mPolicyId == null && enabled)
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ mNameDot + PROP_POLICY_IDENTIFIER, msg));
+ msg = "NoticeReference is optional; If chosen to include, NoticeReference must at least has 'organization'";
+ if (mNoticeRefOrg == null && mNoticeRefNums != null && enabled)
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ mNameDot + PROP_NOTICE_REF_ORG, msg));
+
+ // if a policy id is not null check that it is a valid OID.
+
+ if (mPolicyId != null)
+ CMS.checkOID(mNameDot + PROP_POLICY_IDENTIFIER, mPolicyId);
+
+ // if enabled, form CertificatePolicyInfo to be encoded in
+ // extension. Policy ids should be all set.
+ if (enabled) {
+ CMS.debug("CertPolicy: in CertPolicy");
+ DisplayText displayText = null;
+
+ if (mNoticeRefExplicitText != null &&
+ !mNoticeRefExplicitText.equals(""))
+ displayText = new DisplayText(DisplayText.tag_VisibleString, mNoticeRefExplicitText);
+ // new DisplayText(DisplayText.tag_IA5String, mNoticeRefExplicitText);
+ DisplayText orgName = null;
+
+ if (mNoticeRefOrg != null &&
+ !mNoticeRefOrg.equals(""))
+ orgName =
+ new DisplayText(DisplayText.tag_VisibleString, mNoticeRefOrg);
+ // new DisplayText(DisplayText.tag_VisibleString, mNoticeRefOrg);
+
+ int[] nums = new int[0];
+ ;
+ if (mNoticeRefNums != null &&
+ !mNoticeRefNums.equals("")) {
+
+ // should add a method to NoticeReference to take a
+ // Vector...but let's do this for now
+
+ Vector<String> numsVector = new Vector<String>();
+ StringTokenizer tokens = new StringTokenizer(mNoticeRefNums,
+ ",");
+
+ while (tokens.hasMoreTokens()) {
+ String num = tokens.nextToken().trim();
+
+ numsVector.addElement(num);
+ }
+
+ nums = new int[numsVector.size()];
+
+ for (int i = 0; i < numsVector.size(); i++) {
+ Integer ii = new Integer(numsVector.elementAt(i));
+
+ nums[i] = ii.intValue();
+ }
+ }
+ CertificatePolicyId cpolicyId = null;
+
+ try {
+ cpolicyId = new CertificatePolicyId(ObjectIdentifier.getObjectIdentifier(mPolicyId));
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_POLICY_CERTIFICATE_POLICIES_ERROR", mPolicyId));
+ }
+
+ PolicyQualifiers policyQualifiers = new PolicyQualifiers();
+
+ NoticeReference noticeReference = null;
+
+ if (orgName != null)
+ noticeReference = new NoticeReference(orgName, nums);
+
+ UserNotice userNotice = null;
+
+ if (displayText != null || noticeReference != null) {
+ userNotice = new UserNotice(noticeReference, displayText);
+
+ PolicyQualifierInfo policyQualifierInfo1 =
+ new PolicyQualifierInfo(PolicyQualifierInfo.QT_UNOTICE, userNotice);
+
+ policyQualifiers.add(policyQualifierInfo1);
+ }
+
+ CPSuri cpsUri = null;
+
+ if (mCpsUri != null && mCpsUri.length() > 0) {
+ cpsUri = new CPSuri(mCpsUri);
+ PolicyQualifierInfo policyQualifierInfo2 =
+ new PolicyQualifierInfo(PolicyQualifierInfo.QT_CPS, cpsUri);
+
+ policyQualifiers.add(policyQualifierInfo2);
+ }
+
+ if ((mNoticeRefOrg == null || mNoticeRefOrg.equals("")) &&
+ (mNoticeRefExplicitText == null || mNoticeRefExplicitText.equals("")) &&
+ (mCpsUri == null || mCpsUri.equals(""))) {
+ CMS.debug("CertPolicy mNoticeRefOrg = " + mNoticeRefOrg);
+ CMS.debug("CertPolicy mNoticeRefExplicitText = " + mNoticeRefExplicitText);
+ CMS.debug("CertPolicy mCpsUri = " + mCpsUri);
+
+ mCertificatePolicyInfo = new CertificatePolicyInfo(cpolicyId);
+ } else {
+ CMS.debug("CertPolicy mNoticeRefOrg = " + mNoticeRefOrg);
+ CMS.debug("CertPolicy mNoticeRefExplicitText = " + mNoticeRefExplicitText);
+ CMS.debug("CertPolicy mCpsUri = " + mCpsUri);
+ mCertificatePolicyInfo = new CertificatePolicyInfo(cpolicyId, policyQualifiers);
+ }
+ }
+ }
+
+ protected void getInstanceParams(Vector<String> instanceParams) {
+ instanceParams.addElement(
+ mNameDot + PROP_POLICY_IDENTIFIER + "=" + (mPolicyId == null ? "" :
+ mPolicyId));
+ instanceParams.addElement(
+ mNameDot + PROP_NOTICE_REF_ORG + "=" + (mNoticeRefOrg == null ? "" :
+ mNoticeRefOrg));
+ instanceParams.addElement(
+ mNameDot + PROP_NOTICE_REF_NUMS + "=" + (mNoticeRefNums == null ? "" :
+ mNoticeRefNums));
+ instanceParams.addElement(
+ mNameDot + PROP_USER_NOTICE_TEXT + "=" + (mNoticeRefExplicitText == null ? "" :
+ mNoticeRefExplicitText));
+ instanceParams.addElement(
+ mNameDot + PROP_CPS_URI + "=" + (mCpsUri == null ? "" :
+ mCpsUri));
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/CertificateRenewalWindowExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/CertificateRenewalWindowExt.java
new file mode 100644
index 000000000..58ce112f3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/CertificateRenewalWindowExt.java
@@ -0,0 +1,254 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.extensions.CertificateRenewalWindowExtension;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Certificate Renewal Window Extension Policy
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class CertificateRenewalWindowExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+
+ protected static final String PROP_END_TIME = "relativeEndTime";
+ protected static final String PROP_BEGIN_TIME = "relativeBeginTime";
+ protected static final String PROP_CRITICAL = "critical";
+
+ protected boolean mCritical;
+ protected String mBeginTime;
+ protected String mEndTime;
+
+ /**
+ * Adds the Netscape comment in the end-entity certificates or
+ * CA certificates. The policy is set to be non-critical with the
+ * provided OID.
+ */
+ public CertificateRenewalWindowExt() {
+ NAME = "CertificateRenewalWindowExt";
+ DESC = "Sets non-critical Certificate Renewal Window extension in certs";
+ }
+
+ /**
+ * Initializes this policy rule.
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mCritical = config.getBoolean(PROP_CRITICAL, false);
+ mBeginTime = config.getString(PROP_BEGIN_TIME, null);
+ mEndTime = config.getString(PROP_END_TIME, null);
+
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <p>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ PolicyResult res = PolicyResult.ACCEPTED;
+
+ // get cert info.
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult r = applyCert(req, ci[i]);
+
+ if (r == PolicyResult.REJECTED)
+ return r;
+ }
+ return res;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+
+ CertificateExtensions extensions = null;
+
+ try {
+ extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+ } catch (IOException e) {
+ } catch (CertificateException e) {
+ }
+
+ if (extensions == null) {
+ extensions = new CertificateExtensions();
+ try {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ } catch (Exception e) {
+ }
+ } else {
+ // remove any previously computed version of the extension
+ try {
+ extensions.delete(CertificateRenewalWindowExtension.NAME);
+
+ } catch (IOException e) {
+ // this is the hack: for some reason, the key which is the name
+ // of the policy has been converted into the OID
+ try {
+ extensions.delete("2.16.840.1.113730.1.15");
+ } catch (IOException ee) {
+ }
+ }
+ }
+
+ try {
+ Date now = CMS.getCurrentDate();
+ CertificateRenewalWindowExtension crwExt = null;
+
+ if (mEndTime == null || mEndTime.equals("")) {
+ crwExt = new CertificateRenewalWindowExtension(
+ mCritical,
+ getDateValue(now, mBeginTime),
+ null);
+ } else {
+ crwExt = new CertificateRenewalWindowExtension(
+ mCritical,
+ getDateValue(now, mBeginTime),
+ getDateValue(now, mEndTime));
+ }
+ extensions.set(CertificateRenewalWindowExtension.NAME,
+ crwExt);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_CERTIFICATE_POLICIES_1", NAME));
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_CERTIFICATE_POLICIES_ERROR"), NAME);
+ return PolicyResult.REJECTED;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public Date getDateValue(Date relativeFrom, String s) {
+ long time;
+
+ if (s.endsWith("s")) {
+ time = 1000 * Long.parseLong(s.substring(0,
+ s.length() - 1));
+ } else if (s.endsWith("m")) {
+ time = 60 * 1000 * Long.parseLong(s.substring(0,
+ s.length() - 1));
+ } else if (s.endsWith("h")) {
+ time = 60 * 60 * 1000 * Long.parseLong(s.substring(0,
+ s.length() - 1));
+ } else if (s.endsWith("D")) {
+ time = 24 * 60 * 60 * 1000 * Long.parseLong(
+ s.substring(0, s.length() - 1));
+ } else if (s.endsWith("M")) {
+ time = 30 * 60 * 60 * 1000 * Long.parseLong(
+ s.substring(0, s.length() - 1));
+ } else {
+ time = 1000 * Long.parseLong(s);
+ }
+
+ return new Date(relativeFrom.getTime() + time);
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_CRITICAL + ";boolean;Netscape recommendation: non-critical.",
+ PROP_BEGIN_TIME
+ + ";string;Start Time in seconds (Relative to the time of issuance). Optionally, time unit (s - seconds, m - minutes, h - hours, D - days, M - months) can be specified right after the value. For example, 5 days can be expressed as 5D.",
+ PROP_END_TIME
+ + ";string;End Time in seconds (Optional, Relative to the time of issuance). Optionally, time unit (s - seconds, m - minutes, h - hours, D - days, M - months) can be specified right after the value. For example, 5 days can be expressed as 5D.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-certificaterenewalwindow",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Adds 'Certificate Renewal Window' extension. See manual"
+ };
+
+ return params;
+
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> params = new Vector<String>();
+
+ params.addElement(PROP_CRITICAL + "=" + mCritical);
+ if (mBeginTime == null) {
+ params.addElement(PROP_BEGIN_TIME + "=");
+ } else {
+ params.addElement(PROP_BEGIN_TIME + "=" + mBeginTime);
+ }
+ if (mEndTime == null) {
+ params.addElement(PROP_END_TIME + "=");
+ } else {
+ params.addElement(PROP_END_TIME + "=" + mEndTime);
+ }
+ return params;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> defParams = new Vector<String>();
+
+ defParams.addElement(PROP_CRITICAL + "=false");
+ defParams.addElement(PROP_BEGIN_TIME + "=");
+ defParams.addElement(PROP_END_TIME + "=");
+ return defParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/CertificateScopeOfUseExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/CertificateScopeOfUseExt.java
new file mode 100644
index 000000000..779be165b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/CertificateScopeOfUseExt.java
@@ -0,0 +1,326 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.extensions.CertificateScopeEntry;
+import netscape.security.extensions.CertificateScopeOfUseExtension;
+import netscape.security.util.BigInt;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IGeneralNameUtil;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Certificate Scope Of Use extension policy. This extension
+ * is defined in draft-thayes-cert-scope-00.txt
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class CertificateScopeOfUseExt extends APolicyRule implements
+ IEnrollmentPolicy, IExtendedPluginInfo {
+ protected static final String PROP_CRITICAL =
+ "critical";
+ protected static final String PROP_ENTRY =
+ "entry";
+ protected static final String PROP_NAME =
+ "name";
+ protected static final String PROP_NAME_TYPE =
+ "name_type";
+ protected static final String PROP_PORT_NUMBER =
+ "port_number";
+
+ public static final int MAX_ENTRY = 5;
+
+ public IConfigStore mConfig = null;
+
+ public CertificateScopeOfUseExt() {
+ NAME = "CertificateScopeOfUseExt";
+ DESC = "Sets scope of use extension for certificates";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(PROP_CRITICAL +
+ ";boolean; This extension may be either critical or non-critical.");
+ v.addElement(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-certificatescopeofuse");
+ v.addElement(IExtendedPluginInfo.HELP_TEXT +
+ ";Adds Certificate Scope of Use Extension.");
+
+ for (int i = 0; i < MAX_ENTRY; i++) {
+ v.addElement(PROP_ENTRY + Integer.toString(i) + "_" + PROP_NAME + ";" + IGeneralNameUtil.GENNAME_VALUE_INFO);
+ v.addElement(PROP_ENTRY
+ + Integer.toString(i) + "_" + PROP_NAME_TYPE + ";" + IGeneralNameUtil.GENNAME_CHOICE_INFO);
+ v.addElement(PROP_ENTRY
+ + Integer.toString(i) + "_" + PROP_PORT_NUMBER + ";string;" + "The port number (optional).");
+ }
+ return com.netscape.cmsutil.util.Utils.getStringArrayFromVector(v);
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ca.Policy.rule.<ruleName>.implName=AuthInfoAccessExt ca.Policy.rule.<ruleName>.enable=true
+ * ca.Policy.rule.<ruleName>.predicate=
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+ }
+
+ /**
+ * Returns a sequence of scope entry.
+ */
+ private Vector<CertificateScopeEntry> getScopeEntries() throws EBaseException {
+ Vector<CertificateScopeEntry> entries = new Vector<CertificateScopeEntry>();
+
+ //
+ // read until there is *NO* ad<NUM>_method
+ //
+ for (int i = 0;; i++) {
+ // get port number (optional)
+ String port = mConfig.getString(PROP_ENTRY +
+ Integer.toString(i) + "_" + PROP_PORT_NUMBER, null);
+ BigInt portNumber = null;
+
+ if (port != null && !port.equals("")) {
+ portNumber = new BigInt(Integer.parseInt(port));
+ }
+
+ //
+ // location ::= <TAG> : <VALUE>
+ // TAG ::= uriName | dirName
+ // VALUE ::= [value defined by TAG]
+ //
+ String name_type = mConfig.getString(PROP_ENTRY +
+ Integer.toString(i) +
+ "_" + PROP_NAME_TYPE, null);
+ String name = mConfig.getString(PROP_ENTRY +
+ Integer.toString(i) +
+ "_" + PROP_NAME, null);
+
+ if (name == null || name.equals(""))
+ break;
+ GeneralName gn = CMS.form_GeneralNameAsConstraints(name_type, name);
+
+ entries.addElement(new CertificateScopeEntry(gn, portNumber));
+ }
+ return entries;
+ }
+
+ /**
+ * If this policy is enabled, add the authority information
+ * access extension to the certificate.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ PolicyResult res = PolicyResult.ACCEPTED;
+
+ X509CertInfo certInfo;
+ X509CertInfo[] ci = req.getExtDataInCertInfoArray(
+ IRequest.CERT_INFO);
+
+ if (ci == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ for (int j = 0; j < ci.length; j++) {
+
+ certInfo = ci[j];
+ if (certInfo == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CA_CERT_INFO_ERROR", NAME));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Configuration Info Error");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ try {
+ // Find the extensions in the certInfo
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+
+ // add access descriptions
+ Vector<CertificateScopeEntry> entries = getScopeEntries();
+
+ if (entries.size() == 0) {
+ return res;
+ }
+
+ if (extensions == null) {
+ // create extension if not exist
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ } else {
+ // check to see if AIA is already exist
+ try {
+ extensions.delete(CertificateScopeOfUseExtension.NAME);
+ log(ILogger.LL_INFO, "Previous extension deleted: " + CertificateScopeOfUseExtension.NAME);
+ } catch (IOException ex) {
+ }
+ }
+
+ // Create the extension
+ CertificateScopeOfUseExtension suExt = new
+ CertificateScopeOfUseExtension(mConfig.getBoolean(
+ PROP_CRITICAL, false), entries);
+
+ extensions.set(CertificateScopeOfUseExtension.NAME, suExt);
+
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_IO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, e.getMessage());
+ return PolicyResult.REJECTED; // unrecoverable error.
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ "Configuration Info Error encountered: " +
+ e.getMessage());
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Configuration Info Error");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CA_CERT_INFO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Certificate Info Error");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> params = new Vector<String>();
+
+ try {
+ params.addElement(PROP_CRITICAL + "=" +
+ mConfig.getBoolean(PROP_CRITICAL, false));
+ } catch (EBaseException e) {
+ }
+
+ for (int i = 0;; i++) {
+ String name_type = null;
+
+ try {
+ name_type = mConfig.getString(PROP_ENTRY +
+ Integer.toString(i) + "_" + PROP_NAME_TYPE,
+ null);
+ } catch (EBaseException e) {
+ }
+ if (name_type == null)
+ break;
+ params.addElement(PROP_ENTRY +
+ Integer.toString(i) +
+ "_" + PROP_NAME_TYPE + "=" + name_type);
+ String name = null;
+
+ try {
+ name = mConfig.getString(PROP_ENTRY +
+ Integer.toString(i) + "_" + PROP_NAME,
+ null);
+ } catch (EBaseException e) {
+ }
+ if (name == null)
+ break;
+ params.addElement(PROP_ENTRY +
+ Integer.toString(i) +
+ "_" + PROP_NAME + "=" + name);
+ String port = null;
+
+ try {
+ port = mConfig.getString(PROP_ENTRY +
+ Integer.toString(i) + "_" + PROP_PORT_NUMBER,
+ "");
+ } catch (EBaseException e) {
+ }
+ params.addElement(PROP_ENTRY +
+ Integer.toString(i) +
+ "_" + PROP_PORT_NUMBER + "=" + port);
+ }
+ return params;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> defParams = new Vector<String>();
+
+ defParams.addElement(PROP_CRITICAL + "=false");
+
+ //
+ // By default, we create MAX_AD access descriptions.
+ // If this is not enough, admin can manually edit
+ // the CMS.cfg
+ //
+ for (int i = 0; i < MAX_ENTRY; i++) {
+ defParams.addElement(PROP_ENTRY + Integer.toString(i) +
+ "_" + PROP_NAME_TYPE + "=");
+ defParams.addElement(PROP_ENTRY + Integer.toString(i) +
+ "_" + PROP_NAME + "=");
+ defParams.addElement(PROP_ENTRY + Integer.toString(i) +
+ "_" + PROP_PORT_NUMBER + "=");
+ }
+ return defParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/ExtendedKeyUsageExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/ExtendedKeyUsageExt.java
new file mode 100644
index 000000000..5f33efe1b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/ExtendedKeyUsageExt.java
@@ -0,0 +1,285 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.extensions.ExtendedKeyUsageExtension;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * This implements the extended key usage extension.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class ExtendedKeyUsageExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ public static final String PROP_CRITICAL = "critical";
+ protected static final String PROP_PURPOSE_ID = "id";
+ protected static final String PROP_NUM_IDS = "numIds";
+ protected static int MAX_PURPOSE_ID = 10;
+ private boolean mCritical = false;
+ private IConfigStore mConfig = null;
+ private Vector<ObjectIdentifier> mUsages = null;
+
+ private String[] mParams = null;
+
+ // PKIX specifies the that the extension SHOULD NOT be critical
+ public static final boolean DEFAULT_CRITICALITY = false;
+
+ private ExtendedKeyUsageExtension mExtendedKeyUsage = null;
+
+ /**
+ * Constructs extended Key Usage extension.
+ */
+ public ExtendedKeyUsageExt() {
+ NAME = "ExtendedKeyUsageExt";
+ DESC = "Sets ExtendedKeyUsage extension for certificates";
+ }
+
+ /**
+ * Performs one-time initialization of the policy.
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+ setExtendedPluginInfo();
+ setupParams();
+ mExtendedKeyUsage = new ExtendedKeyUsageExtension(mCritical, mUsages);
+ }
+
+ /**
+ * Applies the policy to the given request.
+ */
+ public PolicyResult apply(IRequest req) {
+
+ // if the extension was not configured correctly, just skip it
+ if (mExtendedKeyUsage == null) {
+ return PolicyResult.ACCEPTED;
+ }
+
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED;
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certRes = applyCert(req, ci[i]);
+
+ if (certRes == PolicyResult.REJECTED)
+ return certRes;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+ try {
+ // find the extensions in the certInfo
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+
+ // prepare the extensions data structure
+ if (extensions == null) {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ } else {
+ try {
+ extensions.delete(ExtendedKeyUsageExtension.NAME);
+ } catch (IOException ex) {
+ // ExtendedKeyUsage extension is not already there
+ }
+ }
+
+ extensions.set(ExtendedKeyUsageExtension.NAME, mExtendedKeyUsage);
+
+ return PolicyResult.ACCEPTED;
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_IO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"), NAME,
+ e.getMessage());
+ return PolicyResult.REJECTED;
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR",
+ e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"), NAME,
+ e.getMessage());
+ return PolicyResult.REJECTED;
+ }
+ }
+
+ /**
+ * Returns instance specific parameters.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> params = new Vector<String>();
+
+ params.addElement(PROP_CRITICAL + "=" + mCritical);
+ int numIds = MAX_PURPOSE_ID;
+
+ try {
+ numIds = mConfig.getInteger(PROP_NUM_IDS, MAX_PURPOSE_ID);
+ } catch (EBaseException e) {
+ }
+ params.addElement(PROP_NUM_IDS + "=" + numIds);
+ String usage = null;
+
+ for (int i = 0; i < numIds; i++) {
+ if (mUsages.size() <= i) {
+ params.addElement(PROP_PURPOSE_ID +
+ Integer.toString(i) + "=");
+ } else {
+ usage = mUsages.elementAt(i).toString();
+ if (usage == null) {
+ params.addElement(PROP_PURPOSE_ID +
+ Integer.toString(i) + "=");
+ } else {
+ params.addElement(PROP_PURPOSE_ID +
+ Integer.toString(i) + "=" + usage);
+ }
+ }
+ }
+ return params;
+ }
+
+ private void setExtendedPluginInfo() {
+ Vector<String> v = new Vector<String>();
+ int mNum = MAX_PURPOSE_ID;
+
+ if (mConfig != null) {
+ try {
+ mConfig.getInteger(PROP_NUM_IDS, MAX_PURPOSE_ID);
+ } catch (EBaseException e) {
+ }
+ }
+ for (int i = 0; i < mNum; i++) {
+ v.addElement(PROP_PURPOSE_ID
+ + Integer.toString(i)
+ + ";string;"
+ +
+ "A unique,valid OID specified in dot-separated numeric component notation. e.g. 2.16.840.1.113730.1.99");
+ }
+
+ v.addElement(PROP_NUM_IDS + ";number;The total number of policy IDs.");
+ v.addElement(PROP_CRITICAL
+ +
+ ";boolean;RFC 2459 recommendation: This extension may, at the option of the certificate issuer, be either critical or non-critical.");
+ v.addElement(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-extendedkeyusage");
+ v.addElement(IExtendedPluginInfo.HELP_TEXT +
+ ";Adds Extended Key Usage Extension. Defined in RFC 2459 " +
+ "(4.2.1.13)");
+
+ mParams = com.netscape.cmsutil.util.Utils.getStringArrayFromVector(v);
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ if (mParams == null) {
+ setExtendedPluginInfo();
+ }
+ return mParams;
+ }
+
+ /**
+ * Returns default parameters.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> defParams = new Vector<String>();
+
+ defParams.addElement(PROP_CRITICAL + "=false");
+ defParams.addElement(PROP_NUM_IDS + "=" + MAX_PURPOSE_ID);
+ for (int i = 0; i < MAX_PURPOSE_ID; i++) {
+ defParams.addElement(PROP_PURPOSE_ID + Integer.toString(i) + "=");
+ }
+ return defParams;
+ }
+
+ /**
+ * Setups parameters.
+ */
+ private void setupParams() throws EBaseException {
+
+ mCritical = mConfig.getBoolean(PROP_CRITICAL, false);
+ if (mUsages == null) {
+ mUsages = new Vector<ObjectIdentifier>();
+ }
+
+ int mNum = mConfig.getInteger(PROP_NUM_IDS, MAX_PURPOSE_ID);
+
+ for (int i = 0; i < mNum; i++) {
+ ObjectIdentifier usageOID = null;
+
+ String usage = mConfig.getString(PROP_PURPOSE_ID +
+ Integer.toString(i), null);
+
+ try {
+
+ if (usage == null)
+ break;
+ usage = usage.trim();
+ if (usage.equals(""))
+ break;
+ if (usage.equalsIgnoreCase("ocspsigning")) {
+ usageOID = ObjectIdentifier.getObjectIdentifier(ExtendedKeyUsageExtension.OID_OCSPSigning);
+ } else if (usage.equalsIgnoreCase("codesigning")) {
+ usageOID = ObjectIdentifier.getObjectIdentifier(ExtendedKeyUsageExtension.OID_CODESigning);
+ } else {
+ // it could be an object identifier, test it
+ usageOID = ObjectIdentifier.getObjectIdentifier(usage);
+ }
+ } catch (IOException ex) {
+ throw new EBaseException(this.getClass().getName() + ":" +
+ ex.getMessage());
+ } catch (NumberFormatException ex) {
+ throw new EBaseException(this.getClass().getName() + ":" +
+ "OID '" + usage + "' format error");
+ }
+ mUsages.addElement(usageOID);
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/GenericASN1Ext.java b/base/server/cms/src/com/netscape/cms/policy/extensions/GenericASN1Ext.java
new file mode 100644
index 000000000..35f5313c1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/GenericASN1Ext.java
@@ -0,0 +1,509 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.text.ParseException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.extensions.GenericASN1Extension;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.OIDMap;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Private Integer extension policy.
+ * If this policy is enabled, it adds an Private Integer
+ * extension to the certificate.
+ *
+ * The following listed sample configuration parameters:
+ *
+ * ca.Policy.impl.privateInteger.class=com.netscape.certsrv.policy.genericASNExt
+ * ca.Policy.rule.genericASNExt.enable=true
+ * ca.Policy.rule.genericASNExt.name=myIntegerExtension
+ * ca.Policy.rule.genericASNExt.pattern={{{12}34}5}
+ * ca.Policy.rule.genericASNExt.oid=280.230.123.1234.1
+ * ca.Policy.rule.genericASNExt.critical=false
+ * ca.Policy.rule.genericASNExt.attribute1.type=integer
+ * ca.Policy.rule.genericASNExt.attribute1.source=value
+ * ca.Policy.rule.genericASNExt.attribute1.value=9999
+ * ca.Policy.rule.genericASNExt.attribute2.type=ia5string
+ * ca.Policy.rule.genericASNExt.attribute2.source=value
+ * ca.Policy.rule.genericASNExt.attribute2.value=hello
+ * ca.Policy.rule.genericASNExt.attribute3.type=octetstring
+ * ca.Policy.rule.genericASNExt.attribute3.source=value
+ * ca.Policy.rule.genericASNExt.attribute3.value=hellohello
+ * ca.Policy.rule.genericASNExt.attribute4.type=octetstring
+ * ca.Policy.rule.genericASNExt.attribute4.source=file
+ * ca.Policy.rule.genericASNExt.attribute4.value=c:/tmp/test.txt
+ * ca.Policy.rule.genericASNExt.attribute5.type=
+ * ca.Policy.rule.genericASNExt.attribute5.source=
+ * ca.Policy.rule.genericASNExt.attribute5.value=
+ * ca.Policy.rule.genericASNExt.implName=genericASNExt
+ * ca.Policy.rule.genericASNExt.predicate=
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class GenericASN1Ext extends APolicyRule implements
+ IEnrollmentPolicy, IExtendedPluginInfo {
+ protected static final int MAX_ATTR = 10;
+
+ protected static final String PROP_CRITICAL =
+ "critical";
+ protected static final String PROP_NAME =
+ "name";
+ protected static final String PROP_OID =
+ "oid";
+ protected static final String PROP_PATTERN =
+ "pattern";
+ protected static final String PROP_ATTRIBUTE =
+ "attribute";
+ protected static final String PROP_TYPE =
+ "type";
+ protected static final String PROP_SOURCE =
+ "source";
+ protected static final String PROP_VALUE =
+ "value";
+ protected static final String PROP_PREDICATE =
+ "predicate";
+
+ protected static final String PROP_ENABLE =
+ "enable";
+
+ public IConfigStore mConfig = null;
+
+ private String pattern = null;
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String s[] = {
+ "enable" + ";boolean;Enable this policy",
+ "predicate" + ";string;",
+ PROP_CRITICAL + ";boolean;",
+ PROP_NAME + ";string;Name for this extension.",
+ PROP_OID + ";string;OID number for this extension. It should be unique.",
+ PROP_PATTERN + ";string;Pattern for extension; {012}34",
+ // Attribute 0
+ PROP_ATTRIBUTE + "." + "0" + "." + PROP_TYPE
+ + ";choice(Integer,IA5String,OctetString,PrintableString,VisibleString,UTCTime,OID,Boolean);Attribute type for extension",
+ PROP_ATTRIBUTE + "." + "0" + "." + PROP_SOURCE
+ + ";choice(Value,File);Data Source for the extension. You can specify the value here or file name has value.",
+ PROP_ATTRIBUTE + "." + "0" + "." + PROP_VALUE
+ + ";string;If data source is 'value', specity value here. If data source is 'file', specify the file name with full path.",
+ // Attribute 1
+ PROP_ATTRIBUTE + "." + "1" + "." + PROP_TYPE
+ + ";choice(Integer,IA5String,OctetString,PrintableString,VisibleString,UTCTime,OID,Boolean);Attribute type for extension",
+ PROP_ATTRIBUTE + "." + "1" + "." + PROP_SOURCE
+ + ";choice(Value,File);Data Source for the extension. You can specify the value here or file name has value.",
+ PROP_ATTRIBUTE + "." + "1" + "." + PROP_VALUE
+ + ";string;If data source is 'value', specity value here. If data source is 'file', specify the file name with full path.",
+ // Attribute 2
+ PROP_ATTRIBUTE + "." + "2" + "." + PROP_TYPE
+ + ";choice(Integer,IA5String,OctetString,PrintableString,VisibleString,UTCTime,OID,Boolean);Attribute type for extension",
+ PROP_ATTRIBUTE + "." + "2" + "." + PROP_SOURCE
+ + ";choice(Value,File);Data Source for the extension. You can specify the value here or file name has value.",
+ PROP_ATTRIBUTE + "." + "2" + "." + PROP_VALUE
+ + ";string;If data source is 'value', specity value here. If data source is 'file', specify the file name with full path.",
+ // Attribute 3
+ PROP_ATTRIBUTE + "." + "3" + "." + PROP_TYPE
+ + ";choice(Integer,IA5String,OctetString,PrintableString,VisibleString,UTCTime,OID,Boolean);Attribute type for extension",
+ PROP_ATTRIBUTE + "." + "3" + "." + PROP_SOURCE
+ + ";choice(Value,File);Data Source for the extension. You can specify the value here or file name has value.",
+ PROP_ATTRIBUTE + "." + "3" + "." + PROP_VALUE
+ + ";string;If data source is 'value', specity value here. If data source is 'file', specify the file name with full path.",
+ // Attribute 4
+ PROP_ATTRIBUTE + "." + "4" + "." + PROP_TYPE
+ + ";choice(Integer,IA5String,OctetString,PrintableString,VisibleString,UTCTime,OID,Boolean);Attribute type for extension",
+ PROP_ATTRIBUTE + "." + "4" + "." + PROP_SOURCE
+ + ";choice(Value,File);Data Source for the extension. You can specify the value here or file name has value.",
+ PROP_ATTRIBUTE + "." + "4" + "." + PROP_VALUE
+ + ";string;If data source is 'value', specity value here. If data source is 'file', specify the file name with full path.",
+ // Attribute 5
+ PROP_ATTRIBUTE + "." + "5" + "." + PROP_TYPE
+ + ";choice(Integer,IA5String,OctetString,PrintableString,VisibleString,UTCTime,OID,Boolean);Attribute type for extension",
+ PROP_ATTRIBUTE + "." + "5" + "." + PROP_SOURCE
+ + ";choice(Value,File);Data Source for the extension. You can specify the value here or file name has value.",
+ PROP_ATTRIBUTE + "." + "5" + "." + PROP_VALUE
+ + ";string;If data source is 'value', specity value here. If data source is 'file', specify the file name with full path.",
+ // Attribute 6
+ PROP_ATTRIBUTE + "." + "6" + "." + PROP_TYPE
+ + ";choice(Integer,IA5String,OctetString,PrintableString,VisibleString,UTCTime,OID,Boolean);Attribute type for extension",
+ PROP_ATTRIBUTE + "." + "6" + "." + PROP_SOURCE
+ + ";choice(Value,File);Data Source for the extension. You can specify the value here or file name has value.",
+ PROP_ATTRIBUTE + "." + "6" + "." + PROP_VALUE
+ + ";string;If data source is 'value', specity value here. If data source is 'file', specify the file name with full path.",
+ // Attribute 7
+ PROP_ATTRIBUTE + "." + "7" + "." + PROP_TYPE
+ + ";choice(Integer,IA5String,OctetString,PrintableString,VisibleString,UTCTime,OID,Boolean);Attribute type for extension",
+ PROP_ATTRIBUTE + "." + "7" + "." + PROP_SOURCE
+ + ";choice(Value,File);Data Source for the extension. You can specify the value here or file name has value.",
+ PROP_ATTRIBUTE + "." + "7" + "." + PROP_VALUE
+ + ";string;If data source is 'value', specity value here. If data source is 'file', specify the file name with full path.",
+ // Attribute 8
+ PROP_ATTRIBUTE + "." + "8" + "." + PROP_TYPE
+ + ";choice(Integer,IA5String,OctetString,PrintableString,VisibleString,UTCTime,OID,Boolean);Attribute type for extension",
+ PROP_ATTRIBUTE + "." + "8" + "." + PROP_SOURCE
+ + ";choice(Value,File);Data Source for the extension. You can specify the value here or file name has value.",
+ PROP_ATTRIBUTE + "." + "8" + "." + PROP_VALUE
+ + ";string;If data source is 'value', specity value here. If data source is 'file', specify the file name with full path.",
+ // Attribute 9
+ PROP_ATTRIBUTE + "." + "9" + "." + PROP_TYPE
+ + ";choice(Integer,IA5String,OctetString,PrintableString,VisibleString,UTCTime,OID,Boolean);Attribute type for extension",
+ PROP_ATTRIBUTE + "." + "9" + "." + PROP_SOURCE
+ + ";choice(Value,File);Data Source for the extension. You can specify the value here or file name has value.",
+ PROP_ATTRIBUTE + "." + "9" + "." + PROP_VALUE
+ + ";string;If data source is 'value', specity value here. If data source is 'file', specify the file name with full path.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-genericasn1ext",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Adds Private extension based on ASN1. See manual"
+ };
+
+ return s;
+ }
+
+ public GenericASN1Ext() {
+ NAME = "GenericASN1Ext";
+ DESC = "Sets Generic extension for certificates";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ca.Policy.rule.<ruleName>.implName=genericASNExt ca.Policy.rule.<ruleName>.enable=true
+ * ca.Policy.rule.<ruleName>.predicate=
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+ if (mConfig == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_INIT_ERROR"));
+ return;
+ }
+
+ boolean enable = mConfig.getBoolean(PROP_ENABLE, false);
+
+ if (enable == false)
+ return;
+
+ String oid = mConfig.getString(PROP_OID, null);
+
+ if ((oid == null) || (oid.length() == 0)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_INIT_ERROR"));
+ return;
+ }
+
+ String name = mConfig.getString(PROP_NAME, null);
+
+ if ((name == null) || (name.length() == 0)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_INIT_ERROR"));
+ return;
+ }
+
+ try {
+ if (File.separatorChar == '\\') {
+ pattern = mConfig.getString(PROP_PATTERN, null);
+ checkFilename(0);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, "" + e.toString());
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, "" + e.toString());
+ }
+
+ // Check OID value
+ CMS.checkOID(name, oid);
+ pattern = mConfig.getString(PROP_PATTERN, null);
+ checkOID(0);
+
+ try {
+ ObjectIdentifier tmpid = new ObjectIdentifier(oid);
+
+ if (OIDMap.getName(tmpid) == null)
+ OIDMap.addAttribute("netscape.security.extensions.GenericASN1Extension", oid, name);
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, "" + e.toString());
+ }
+
+ }
+
+ // Check filename
+ private int checkFilename(int index)
+ throws IOException, EBaseException {
+ String source = null;
+
+ while (index < pattern.length()) {
+ char ch = pattern.charAt(index);
+
+ switch (ch) {
+ case '{':
+ index++;
+ index = checkFilename(index);
+ break;
+
+ case '}':
+ return index;
+
+ default:
+ source = mConfig.getString(PROP_ATTRIBUTE + "." + ch + "." + PROP_SOURCE, null);
+ if ((source != null) && (source.equalsIgnoreCase("file"))) {
+ String oValue = mConfig.getString(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE, null);
+ String nValue = oValue.replace('\\', '/');
+
+ mConfig.putString(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE, nValue);
+ FileInputStream fis = new FileInputStream(nValue);
+ fis.close();
+ }
+ }
+ index++;
+ }
+
+ return index;
+ }
+
+ // Check oid
+ private int checkOID(int index)
+ throws EBaseException {
+ String type = null;
+ String oid = null;
+
+ while (index < pattern.length()) {
+ char ch = pattern.charAt(index);
+
+ switch (ch) {
+ case '{':
+ index++;
+ index = checkOID(index);
+ break;
+
+ case '}':
+ return index;
+
+ default:
+ type = mConfig.getString(PROP_ATTRIBUTE + "." + ch + "." + PROP_TYPE, null);
+ if ((type != null) && (type.equalsIgnoreCase("OID"))) {
+ oid = mConfig.getString(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE, null);
+ CMS.checkOID(oid, oid);
+ }
+ }
+ index++;
+ }
+
+ return index;
+ }
+
+ /**
+ * If this policy is enabled, add the private Integer
+ * information extension to the certificate.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ PolicyResult res = PolicyResult.ACCEPTED;
+ X509CertInfo certInfo;
+ X509CertInfo[] ci = req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ for (int j = 0; j < ci.length; j++) {
+
+ certInfo = ci[j];
+ if (certInfo == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR", ""));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"), NAME,
+ "Configuration Info Error");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ try {
+ // Find the extensions in the certInfo
+ CertificateExtensions extensions = (CertificateExtensions) certInfo.get(X509CertInfo.EXTENSIONS);
+
+ if (extensions == null) {
+ // create extension if not exist
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ } else {
+ //
+ // Remove any previousely computed extension
+ //
+ try {
+ extensions.delete(mConfig.getString(PROP_NAME, ""));
+ } catch (Exception e) {/* extension isn't there */
+ }
+ }
+
+ // Create the extension
+ GenericASN1Extension priExt = mkExtension();
+
+ extensions.set(priExt.getName(), priExt);
+
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_IO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, e.getMessage());
+ return PolicyResult.REJECTED; // unrecoverable error.
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Configuration Info Error");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Certificate Info Error");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ } catch (ParseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("BASE_EXTENSION_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Pattern parsing error");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("BASE_UNKNOWN_EXCEPTION", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Unknown Error");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Construct GenericASN1Extension with value from CMS.cfg
+ */
+ protected GenericASN1Extension mkExtension()
+ throws IOException, EBaseException, ParseException {
+ GenericASN1Extension ext;
+
+ Hashtable<String, String> h = new Hashtable<String, String>();
+ // This only show one level, not substores!
+ Enumeration<String> e = mConfig.getPropertyNames();
+
+ while (e.hasMoreElements()) {
+ String n = e.nextElement();
+
+ h.put(n, mConfig.getString(n));
+ }
+ for (int idx = 0; idx < MAX_ATTR; idx++) {
+ String proptype = PROP_ATTRIBUTE + "." + idx + "." + PROP_TYPE;
+ String propsource = PROP_ATTRIBUTE + "." + idx + "." + PROP_SOURCE;
+ String propvalue = PROP_ATTRIBUTE + "." + idx + "." + PROP_VALUE;
+
+ h.put(proptype, mConfig.getString(proptype, null));
+ h.put(propsource, mConfig.getString(propsource, null));
+ h.put(propvalue, mConfig.getString(propvalue, null));
+ }
+ ext = new GenericASN1Extension(h);
+ return ext;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ int idx = 0;
+ Vector<String> params = new Vector<String>();
+
+ try {
+ params.addElement(PROP_CRITICAL + "=" + mConfig.getBoolean(PROP_CRITICAL, false));
+ params.addElement(PROP_NAME + "=" + mConfig.getString(PROP_NAME, null));
+ params.addElement(PROP_OID + "=" + mConfig.getString(PROP_OID, null));
+ params.addElement(PROP_PATTERN + "=" + mConfig.getString(PROP_PATTERN, null));
+
+ for (idx = 0; idx < MAX_ATTR; idx++) {
+ String proptype = PROP_ATTRIBUTE + "." + idx + "." + PROP_TYPE;
+ String propsource = PROP_ATTRIBUTE + "." + idx + "." + PROP_SOURCE;
+ String propvalue = PROP_ATTRIBUTE + "." + idx + "." + PROP_VALUE;
+
+ params.addElement(proptype + "=" + mConfig.getString(proptype, null));
+ params.addElement(propsource + "=" + mConfig.getString(propsource, null));
+ params.addElement(propvalue + "=" + mConfig.getString(propvalue, null));
+ }
+ params.addElement(PROP_PREDICATE + "=" + mConfig.getString(PROP_PREDICATE, null));
+ } catch (EBaseException e) {
+ ;
+ }
+
+ return params;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ int idx = 0;
+
+ Vector<String> defParams = new Vector<String>();
+
+ defParams.addElement(PROP_CRITICAL + "=false");
+ defParams.addElement(PROP_NAME + "=");
+ defParams.addElement(PROP_OID + "=");
+ defParams.addElement(PROP_PATTERN + "=");
+
+ for (idx = 0; idx < MAX_ATTR; idx++) {
+ defParams.addElement(PROP_ATTRIBUTE + "." + idx + "." + PROP_TYPE + "=");
+ defParams.addElement(PROP_ATTRIBUTE + "." + idx + "." + PROP_SOURCE + "=");
+ defParams.addElement(PROP_ATTRIBUTE + "." + idx + "." + PROP_VALUE + "=");
+ }
+
+ return defParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/IssuerAltNameExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/IssuerAltNameExt.java
new file mode 100644
index 000000000..9ceaf99bd
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/IssuerAltNameExt.java
@@ -0,0 +1,249 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.IssuerAlternativeNameExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IGeneralNamesConfig;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Issuer Alt Name Extension policy.
+ *
+ * This extension is used to associate Internet-style identities
+ * with the Certificate issuer.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class IssuerAltNameExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ public static final String PROP_CRITICAL = "critical";
+
+ // PKIX specifies the that the extension SHOULD NOT be critical
+ public static final boolean DEFAULT_CRITICALITY = false;
+
+ private static Vector<String> defaultParams = new Vector<String>();
+ private static String[] mInfo = null;
+
+ static {
+ defaultParams.addElement(PROP_CRITICAL + "=" + DEFAULT_CRITICALITY);
+ CMS.getGeneralNamesConfigDefaultParams(null, true, defaultParams);
+
+ Vector<String> info = new Vector<String>();
+
+ info.addElement(PROP_CRITICAL + ";boolean;RFC 2459 recommendation: SHOULD NOT be marked critical.");
+ info.addElement(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-issueraltname");
+ info.addElement(IExtendedPluginInfo.HELP_TEXT +
+ ";This policy inserts the Issuer Alternative Name " +
+ "Extension into the certificate. See RFC 2459 (4.2.1.8). ");
+
+ CMS.getGeneralNamesConfigExtendedPluginInfo(null, true, info);
+
+ mInfo = new String[info.size()];
+ info.copyInto(mInfo);
+ }
+
+ private Vector<String> mParams = new Vector<String>();
+ private IConfigStore mConfig = null;
+ private boolean mCritical = DEFAULT_CRITICALITY;
+ private boolean mEnabled = false;
+ IGeneralNamesConfig mGNs = null;
+ IssuerAlternativeNameExtension mExtension = null;
+
+ /**
+ * Adds the issuer alternate name extension to all certs.
+ */
+ public IssuerAltNameExt() {
+ NAME = "IssuerAltNameExt";
+ DESC = "Associate Internet-style Identities with Issuer";
+ }
+
+ /**
+ * Initializes this policy rule.
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+
+ // get criticality
+ mCritical = mConfig.getBoolean(PROP_CRITICAL, DEFAULT_CRITICALITY);
+
+ // get enabled.
+ mEnabled = mConfig.getBoolean(
+ IPolicyProcessor.PROP_ENABLE, false);
+
+ // form general names.
+ mGNs = CMS.createGeneralNamesConfig(null, config, true, mEnabled);
+
+ // form extension
+ try {
+ if (mEnabled &&
+ mGNs.getGeneralNames() != null && !mGNs.getGeneralNames().isEmpty()) {
+ mExtension =
+ new IssuerAlternativeNameExtension(
+ Boolean.valueOf(mCritical), mGNs.getGeneralNames());
+ }
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+
+ // init instance params
+ mParams.addElement(PROP_CRITICAL + "=" + mCritical);
+ mGNs.getInstanceParams(mParams);
+
+ return;
+ }
+
+ /**
+ * Adds a extension if none exists.
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ PolicyResult res = PolicyResult.ACCEPTED;
+
+ if (mEnabled == false || mExtension == null)
+ return res;
+
+ // get cert info.
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certRes = applyCert(req, ci[i]);
+
+ if (certRes == PolicyResult.REJECTED)
+ return certRes;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+
+ // get extension from cert info if any.
+ CertificateExtensions extensions = null;
+
+ try {
+ // get extension if any.
+ extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+ } catch (IOException e) {
+ // no extensions.
+ } catch (CertificateException e) {
+ // no extension.
+ }
+
+ if (extensions == null) {
+ extensions = new CertificateExtensions();
+ try {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ } catch (CertificateException e) {
+ // not possible
+ } catch (Exception e) {
+ }
+ } else {
+
+ // remove any previously computed version of the extension
+ try {
+ extensions.delete(IssuerAlternativeNameExtension.NAME);
+
+ } catch (IOException e) {
+ // this is the hack
+ // If name is not found, try deleting using the OID
+
+ try {
+ extensions.delete("2.5.29.18");
+ } catch (IOException ee) {
+ }
+ }
+ }
+
+ try {
+ extensions.set(IssuerAlternativeNameExtension.NAME, mExtension);
+ } catch (Exception e) {
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CRL_CREATE_ISSUER_ALT_NAME_EXT", e.toString()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_SUBJECT_KEY_ID_ERROR"), NAME);
+ return PolicyResult.REJECTED;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return Empty Vector since this policy has no configuration parameters.
+ * for this policy instance.
+ */
+ public Vector<String> getInstanceParams() {
+ return mParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return Empty Vector since this policy implementation has no
+ * configuration parameters.
+ */
+ public Vector<String> getDefaultParams() {
+ return defaultParams;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ return mInfo;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/KeyUsageExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/KeyUsageExt.java
new file mode 100644
index 000000000..24e5f45ed
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/KeyUsageExt.java
@@ -0,0 +1,362 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Policy to add Key Usage Extension.
+ * Adds the key usage extension based on what's requested.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class KeyUsageExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+
+ private final static String HTTP_INPUT = "HTTP_INPUT";
+ protected static final boolean[] DEF_BITS =
+ new boolean[KeyUsageExtension.NBITS];
+ protected int mCAPathLen = -1;
+ protected IConfigStore mConfig = null;
+ protected static final String PROP_CRITICAL = "critical";
+ protected static final String PROP_DIGITAL_SIGNATURE = "digitalSignature";
+ protected static final String PROP_NON_REPUDIATION = "nonRepudiation";
+ protected static final String PROP_KEY_ENCIPHERMENT = "keyEncipherment";
+ protected static final String PROP_DATA_ENCIPHERMENT = "dataEncipherment";
+ protected static final String PROP_KEY_AGREEMENT = "keyAgreement";
+ protected static final String PROP_KEY_CERTSIGN = "keyCertsign";
+ protected static final String PROP_CRL_SIGN = "crlSign";
+ protected static final String PROP_ENCIPHER_ONLY = "encipherOnly";
+ protected static final String PROP_DECIPHER_ONLY = "decipherOnly";
+
+ protected boolean mCritical;
+ protected String mDigitalSignature;
+ protected String mNonRepudiation;
+ protected String mKeyEncipherment;
+ protected String mDataEncipherment;
+ protected String mKeyAgreement;
+ protected String mKeyCertsign;
+ protected String mCrlSign;
+ protected String mEncipherOnly;
+ protected String mDecipherOnly;
+
+ protected KeyUsageExtension mKeyUsage;
+
+ public KeyUsageExt() {
+ NAME = "KeyUsageExtPolicy";
+ DESC = "Sets Key Usage Extension in certificates.";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ca.Policy.rule.<ruleName>.implName=KeyUsageExt ca.Policy.rule.<ruleName>.enable=true ca.Policy.rule.<ruleName>.
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+
+ ICertAuthority certAuthority = (ICertAuthority)
+ ((IPolicyProcessor) owner).getAuthority();
+
+ if (certAuthority == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CANT_FIND_MANAGER"));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Cannot find the Certificate Manager or Registration Manager"));
+ }
+
+ if (certAuthority instanceof ICertificateAuthority) {
+ CertificateChain caChain = certAuthority.getCACertChain();
+ X509Certificate caCert = null;
+
+ // Note that in RA the chain could be null if CA was not up when
+ // RA was started. In that case just set the length to -1 and let
+ // CA reject if it does not allow any subordinate CA certs.
+ if (caChain != null) {
+ caCert = caChain.getFirstCertificate();
+ mCAPathLen = caCert.getBasicConstraints();
+ }
+ }
+
+ mCritical = mConfig.getBoolean(PROP_CRITICAL, true);
+ mDigitalSignature = mConfig.getString(PROP_DIGITAL_SIGNATURE, HTTP_INPUT);
+ mNonRepudiation = mConfig.getString(PROP_NON_REPUDIATION, HTTP_INPUT);
+ mKeyEncipherment = mConfig.getString(PROP_KEY_ENCIPHERMENT, HTTP_INPUT);
+ mDataEncipherment = mConfig.getString(PROP_DATA_ENCIPHERMENT, HTTP_INPUT);
+ mKeyAgreement = mConfig.getString(PROP_KEY_AGREEMENT, HTTP_INPUT);
+ mKeyCertsign = mConfig.getString(PROP_KEY_CERTSIGN, HTTP_INPUT);
+ mCrlSign = mConfig.getString(PROP_CRL_SIGN, HTTP_INPUT);
+ mEncipherOnly = mConfig.getString(PROP_ENCIPHER_ONLY, HTTP_INPUT);
+ mDecipherOnly = mConfig.getString(PROP_DECIPHER_ONLY, HTTP_INPUT);
+ }
+
+ /**
+ * Adds the key usage extension if not set already.
+ * (CRMF, agent, authentication (currently) or PKCS#10 (future)
+ * or RA could have set the extension.)
+ * If not set, set from http input parameters or use default if
+ * no http input parameters are set.
+ *
+ * Note: this allows any bits requested - does not check if user
+ * authenticated is allowed to have a Key Usage Extension with
+ * those bits. Unless the CA's certificate path length is 0, then
+ * we do not allow CA sign or CRL sign bits in any request.
+ *
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certRes = applyCert(req, ci[i]);
+
+ if (certRes == PolicyResult.REJECTED)
+ return certRes;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+ try {
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+ KeyUsageExtension ext = null;
+
+ if (extensions != null) {
+ try {
+ ext = (KeyUsageExtension)
+ extensions.get(KeyUsageExtension.NAME);
+ } catch (IOException e) {
+ // extension isn't there.
+ ext = null;
+ }
+ // check if CA does not allow subordinate CA certs.
+ // otherwise accept existing key usage extension.
+ if (ext != null) {
+ if (mCAPathLen == 0) {
+ boolean[] bits = ext.getBits();
+
+ if ((bits.length > KeyUsageExtension.KEY_CERTSIGN_BIT &&
+ bits[KeyUsageExtension.KEY_CERTSIGN_BIT] == true) ||
+ (bits.length > KeyUsageExtension.CRL_SIGN_BIT &&
+ bits[KeyUsageExtension.CRL_SIGN_BIT] == true)) {
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_NO_SUB_CA_CERTS_ALLOWED"),
+ NAME);
+ return PolicyResult.REJECTED;
+ }
+ }
+ return PolicyResult.ACCEPTED;
+ }
+ } else {
+ // create extensions set if none.
+ if (extensions == null) {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ }
+ }
+
+ boolean[] bits = new boolean[KeyUsageExtension.NBITS];
+
+ bits[KeyUsageExtension.DIGITAL_SIGNATURE_BIT] = getBit("digital_signature",
+ mDigitalSignature, req);
+ bits[KeyUsageExtension.NON_REPUDIATION_BIT] = getBit("non_repudiation",
+ mNonRepudiation, req);
+ bits[KeyUsageExtension.KEY_ENCIPHERMENT_BIT] = getBit("key_encipherment",
+ mKeyEncipherment, req);
+ bits[KeyUsageExtension.DATA_ENCIPHERMENT_BIT] = getBit("data_encipherment",
+ mDataEncipherment, req);
+ bits[KeyUsageExtension.KEY_AGREEMENT_BIT] = getBit("key_agreement",
+ mKeyAgreement, req);
+ bits[KeyUsageExtension.KEY_CERTSIGN_BIT] = getBit("key_certsign",
+ mKeyCertsign, req);
+ bits[KeyUsageExtension.CRL_SIGN_BIT] = getBit("crl_sign", mCrlSign, req);
+ bits[KeyUsageExtension.ENCIPHER_ONLY_BIT] = getBit("encipher_only",
+ mEncipherOnly, req);
+ bits[KeyUsageExtension.DECIPHER_ONLY_BIT] = getBit("decipher_only",
+ mDecipherOnly, req);
+
+ // don't allow no bits set or the extension does not
+ // encode/decode properlly.
+ boolean bitset = false;
+
+ for (int i = 0; i < bits.length; i++) {
+ if (bits[i]) {
+ bitset = true;
+ break;
+ }
+ }
+ if (!bitset) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_NO_KEYUSAGE_EXTENSION_BITS_SET", NAME));
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_KEYUSAGE_EXTENSION_BITS_SET"),
+ NAME);
+ return PolicyResult.REJECTED;
+ }
+
+ // create the extension.
+ try {
+ mKeyUsage = new KeyUsageExtension(mCritical, bits);
+ } catch (IOException e) {
+ }
+ extensions.set(KeyUsageExtension.NAME, mKeyUsage);
+ return PolicyResult.ACCEPTED;
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_IO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, e.getMessage());
+ return PolicyResult.REJECTED; // unrecoverable error.
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Certificate Info Error");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> params = new Vector<String>();
+
+ params.addElement(PROP_CRITICAL + "=" + mCritical);
+ params.addElement(PROP_DIGITAL_SIGNATURE + "=" + mDigitalSignature);
+ params.addElement(PROP_NON_REPUDIATION + "=" + mNonRepudiation);
+ params.addElement(PROP_KEY_ENCIPHERMENT + "=" + mKeyEncipherment);
+ params.addElement(PROP_DATA_ENCIPHERMENT + "=" + mDataEncipherment);
+ params.addElement(PROP_KEY_AGREEMENT + "=" + mKeyAgreement);
+ params.addElement(PROP_KEY_CERTSIGN + "=" + mKeyCertsign);
+ params.addElement(PROP_CRL_SIGN + "=" + mCrlSign);
+ params.addElement(PROP_ENCIPHER_ONLY + "=" + mEncipherOnly);
+ params.addElement(PROP_DECIPHER_ONLY + "=" + mDecipherOnly);
+ return params;
+ }
+
+ private static Vector<String> mDefParams = new Vector<String>();
+ static {
+ mDefParams.addElement(PROP_CRITICAL + "=true");
+ mDefParams.addElement(PROP_DIGITAL_SIGNATURE + "=");
+ mDefParams.addElement(PROP_NON_REPUDIATION + "=");
+ mDefParams.addElement(PROP_KEY_ENCIPHERMENT + "=");
+ mDefParams.addElement(PROP_DATA_ENCIPHERMENT + "=");
+ mDefParams.addElement(PROP_KEY_AGREEMENT + "=");
+ mDefParams.addElement(PROP_KEY_CERTSIGN + "=");
+ mDefParams.addElement(PROP_CRL_SIGN + "=");
+ mDefParams.addElement(PROP_ENCIPHER_ONLY + "=");
+ mDefParams.addElement(PROP_DECIPHER_ONLY + "=");
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_CRITICAL + ";boolean;RFC 2459 recommendation: SHOULD be critical",
+ PROP_DIGITAL_SIGNATURE
+ + ";choice(true,false,HTTP_INPUT);true means always set this bit, false means don't set this bit, HTTP_INPUT means get this bit from the HTTP input",
+ PROP_NON_REPUDIATION
+ + ";choice(true,false,HTTP_INPUT);true means always set this bit, false means don't set this bit, HTTP_INPUT means get this bit from the HTTP input",
+ PROP_KEY_ENCIPHERMENT
+ + ";choice(true,false,HTTP_INPUT);true means always set this bit, false means don't set this bit, HTTP_INPUT means get this bit from the HTTP input",
+ PROP_DATA_ENCIPHERMENT
+ + ";choice(true,false,HTTP_INPUT);true means always set this bit, false means don't set this bit, HTTP_INPUT means get this bit from the HTTP input",
+ PROP_KEY_AGREEMENT
+ + ";choice(true,false,HTTP_INPUT);true means always set this bit, false means don't set this bit, HTTP_INPUT means get this bit from the HTTP input",
+ PROP_KEY_CERTSIGN
+ + ";choice(true,false,HTTP_INPUT);true means always set this bit, false means don't set this bit, HTTP_INPUT means get this bit from the HTTP input",
+ PROP_CRL_SIGN
+ + ";choice(true,false,HTTP_INPUT);true means always set this bit, false means don't set this bit, HTTP_INPUT means get this bit from the HTTP input",
+ PROP_ENCIPHER_ONLY
+ + ";choice(true,false,HTTP_INPUT);true means always set this bit, false means don't set this bit, HTTP_INPUT means get this bit from the HTTP input",
+ PROP_DECIPHER_ONLY
+ + ";choice(true,false,HTTP_INPUT);true means always set this bit, false means don't set this bit, HTTP_INPUT means get this bit from the HTTP input",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-keyusage",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Adds Key Usage Extension; See in RFC 2459 (4.2.1.3)"
+
+ };
+
+ return params;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return mDefParams;
+ }
+
+ private boolean getBit(String usage, String choice, IRequest req) {
+ if (choice.equals(HTTP_INPUT)) {
+ choice = req.getExtDataInString(IRequest.HTTP_PARAMS, usage);
+ if (choice == null)
+ choice = "false";
+ }
+ return Boolean.valueOf(choice).booleanValue();
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/NSCCommentExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/NSCCommentExt.java
new file mode 100644
index 000000000..ca18b8023
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/NSCCommentExt.java
@@ -0,0 +1,293 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.NSCCommentExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Netscape comment
+ * Adds Netscape comment policy
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class NSCCommentExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+
+ protected static final String PROP_USER_NOTICE_DISPLAY_TEXT = "displayText";
+ protected static final String PROP_COMMENT_FILE = "commentFile";
+ protected static final String PROP_CRITICAL = "critical";
+ protected static final String PROP_INPUT_TYPE = "inputType";
+ protected static final String TEXT = "Text";
+ protected static final String FILE = "File";
+
+ protected String mUserNoticeDisplayText;
+ protected String mCommentFile;
+ protected String mInputType;
+ protected boolean mCritical;
+ private Vector<String> mParams = new Vector<String>();
+
+ protected String tempCommentFile;
+ protected boolean certApplied = false;
+
+ /**
+ * Adds the Netscape comment in the end-entity certificates or
+ * CA certificates. The policy is set to be non-critical with the
+ * provided OID.
+ */
+ public NSCCommentExt() {
+ NAME = "NSCCommentExt";
+ DESC = "Sets non-critical Netscape Comment extension in certs";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <p>
+ * The entries may be of the form:
+ *
+ * ca.Policy.rule.<ruleName>.implName=NSCCommentExtImpl ca.Policy.rule.<ruleName>.displayText=<n>
+ * ca.Policy.rule.<ruleName>.commentFile=<n> ca.Policy.rule.<ruleName>.enable=false
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+
+ FileInputStream fileStream = null;
+
+ try {
+ mCritical = config.getBoolean(PROP_CRITICAL, false);
+ mParams.addElement(PROP_CRITICAL + "=" + mCritical);
+
+ mInputType = config.getString(PROP_INPUT_TYPE, null);
+ mParams.addElement(PROP_INPUT_TYPE + "=" + mInputType);
+
+ mUserNoticeDisplayText = config.getString(PROP_USER_NOTICE_DISPLAY_TEXT, "");
+ mParams.addElement(PROP_USER_NOTICE_DISPLAY_TEXT + "=" + mUserNoticeDisplayText);
+
+ tempCommentFile = config.getString(PROP_COMMENT_FILE, "");
+
+ boolean enable = config.getBoolean(PROP_ENABLE, false);
+
+ if ((enable == true)) {
+
+ if (mInputType.equals("File")) {
+ if (tempCommentFile.equals(""))
+ throw new Exception("No file name provided");
+
+ fileStream = new FileInputStream(tempCommentFile);
+ fileStream.close();
+ }
+ }
+
+ if (tempCommentFile.equals(""))
+ mCommentFile = "";
+ else
+ mCommentFile = tempCommentFile.replace('\\', '/');
+
+ config.putString(PROP_COMMENT_FILE, mCommentFile);
+
+ mParams.addElement(PROP_COMMENT_FILE + "=" + mCommentFile);
+ } catch (FileNotFoundException e) {
+ Object[] params = { getInstanceName(), "File not found : " + tempCommentFile };
+
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CONFIG"), params);
+ } catch (Exception e) {
+ Object[] params = { getInstanceName(), e.getMessage() };
+
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CONFIG"), params);
+ }
+ }
+
+ /**
+ * Applies the policy on the given Request.
+ * <p>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ PolicyResult res = PolicyResult.ACCEPTED;
+
+ // get cert info.
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult r = applyCert(req, ci[i]);
+
+ if (r == PolicyResult.REJECTED)
+ return r;
+ }
+ return res;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+
+ certApplied = false;
+ CertificateExtensions extensions = null;
+
+ try {
+ extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+ } catch (IOException e) {
+ } catch (CertificateException e) {
+ }
+
+ if (extensions == null) {
+ extensions = new CertificateExtensions();
+ try {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ } catch (Exception e) {
+ }
+ } else {
+ // remove any previously computed version of the extension
+ try {
+ extensions.delete(NSCCommentExtension.NAME);
+
+ } catch (IOException e) {
+ // this is the hack: for some reason, the key which is the name
+ // of the policy has been converted into the OID
+ try {
+ extensions.delete("2.16.840.1.113730.1.13");
+ } catch (IOException ee) {
+ }
+ }
+ }
+ if (mInputType.equals("File")) {
+ // if ((mUserNoticeDisplayText.equals("")) && !(mCommentFile.equals(""))) {
+ try {
+ // Read the comments file
+ BufferedReader fis = new BufferedReader(new FileReader(mCommentFile));
+
+ String line = null;
+ StringBuffer buffer = new StringBuffer();
+
+ while ((line = fis.readLine()) != null)
+ buffer.append(line);
+ mUserNoticeDisplayText = new String(buffer);
+ fis.close();
+ } catch (IOException e) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, " Comment Text file not found : " + mCommentFile);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_COMMENT_FILE_NOT_FOUND", e.toString()));
+ return PolicyResult.REJECTED;
+
+ }
+
+ }
+
+ certApplied = true;
+
+ try {
+ NSCCommentExtension cpExt =
+ new NSCCommentExtension(mCritical, mUserNoticeDisplayText);
+
+ extensions.set(NSCCommentExtension.NAME, cpExt);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_CERTIFICATE_POLICIES_1", NAME));
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_CERTIFICATE_POLICIES_ERROR"), NAME);
+ return PolicyResult.REJECTED;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_CRITICAL + ";boolean;Netscape recommendation: non-critical.",
+ PROP_INPUT_TYPE + ";choice(Text,File);Whether the comments " +
+ "would be entered in the displayText field or come from " +
+ "a file.",
+ PROP_USER_NOTICE_DISPLAY_TEXT + ";string;The comment that may be " +
+ "displayed to the user when the certificate is viewed.",
+ PROP_COMMENT_FILE + ";string; If data source is 'File', specify " +
+ "the file name with full path.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-nsccomment",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Adds 'netscape comment' extension. See manual"
+ };
+
+ return params;
+
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ return mParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> defParams = new Vector<String>();
+
+ defParams.addElement(PROP_CRITICAL + "=false");
+ defParams.addElement(PROP_INPUT_TYPE + "=" + TEXT);
+ defParams.addElement(PROP_USER_NOTICE_DISPLAY_TEXT + "=");
+ defParams.addElement(PROP_COMMENT_FILE + "=");
+ return defParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/NSCertTypeExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/NSCertTypeExt.java
new file mode 100644
index 000000000..c5daabed9
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/NSCertTypeExt.java
@@ -0,0 +1,535 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.extensions.NSCertTypeExtension;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * NS Cert Type policy.
+ * Adds the ns cert type extension depending on cert type requested.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class NSCertTypeExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ protected static final String PROP_SET_DEFAULT_BITS = "setDefaultBits";
+ protected static final boolean DEF_SET_DEFAULT_BITS = true;
+ protected static final String DEF_SET_DEFAULT_BITS_VAL =
+ Boolean.valueOf(DEF_SET_DEFAULT_BITS).toString();
+
+ protected static final int DEF_PATHLEN = -1;
+
+ protected static final boolean[] DEF_BITS =
+ new boolean[NSCertTypeExtension.NBITS];
+
+ // XXX for future use. currenlty always allow.
+ protected static final String PROP_AGENT_OVERR = "allowAgentOverride";
+ protected static final String PROP_EE_OVERR = "AllowEEOverride";
+
+ // XXX for future use. currently always critical
+ // (standard says SHOULD be marked critical if included.)
+ protected static final String PROP_CRITICAL = "critical";
+
+ // XXX for future use to allow overrides from forms.
+ // request must be agent approved or authenticated.
+ protected boolean mAllowAgentOverride = false;
+ protected boolean mAllowEEOverride = false;
+
+ // XXX for future use. currently always non-critical
+ protected boolean mCritical = false;
+
+ protected int mCAPathLen = -1;
+
+ protected IConfigStore mConfig = null;
+ protected boolean mSetDefaultBits = false;
+
+ static {
+ // set default bits used when request missing ns cert type info.
+ // default is a client cert
+ DEF_BITS[NSCertTypeExtension.SSL_CLIENT_BIT] = true;
+ DEF_BITS[NSCertTypeExtension.SSL_SERVER_BIT] = false;
+ DEF_BITS[NSCertTypeExtension.EMAIL_BIT] = true;
+ DEF_BITS[NSCertTypeExtension.OBJECT_SIGNING_BIT] = true;
+ DEF_BITS[NSCertTypeExtension.SSL_CA_BIT] = false;
+ DEF_BITS[NSCertTypeExtension.EMAIL_CA_BIT] = false;
+ DEF_BITS[NSCertTypeExtension.OBJECT_SIGNING_CA_BIT] = false;
+ }
+
+ public NSCertTypeExt() {
+ NAME = "NSCertType";
+ DESC = "Sets Netscape Cert Type on all certs";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ra.Policy.rule.<ruleName>.implName=nsCertTypeExt ra.Policy.rule.<ruleName>.enable=true
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+
+ // XXX future use.
+ //mAllowAgentOverride = config.getBoolean(PROP_AGENT_OVERR, false);
+ //mAllowEEOverride = config.getBoolean(PROP_EE_OVERR, false);
+ mCritical = config.getBoolean(PROP_CRITICAL, false);
+
+ ICertAuthority certAuthority = (ICertAuthority)
+ ((IPolicyProcessor) owner).getAuthority();
+
+ if (certAuthority instanceof ICertificateAuthority) {
+ CertificateChain caChain = certAuthority.getCACertChain();
+ X509Certificate caCert = null;
+
+ // Note that in RA the chain could be null if CA was not up when
+ // RA was started. In that case just set the length to -1 and let
+ // CA reject if it does not allow any subordinate CA certs.
+ if (caChain != null) {
+ caCert = caChain.getFirstCertificate();
+ if (caCert != null)
+ mCAPathLen = caCert.getBasicConstraints();
+ }
+ }
+
+ mSetDefaultBits = mConfig.getBoolean(
+ PROP_SET_DEFAULT_BITS, DEF_SET_DEFAULT_BITS);
+ }
+
+ /**
+ * Adds the ns cert type if not set already.
+ * reads ns cert type choices from form. If no choices from form
+ * will defaults to all.
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ CMS.debug("NSCertTypeExt: Impl: " + NAME + ", Instance: " + getInstanceName() + "::apply()");
+
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certRes = applyCert(req, ci[i]);
+
+ if (certRes == PolicyResult.REJECTED)
+ return certRes;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+ try {
+ String certType =
+ req.getExtDataInString(IRequest.HTTP_PARAMS, IRequest.CERT_TYPE);
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+ NSCertTypeExtension nsCertTypeExt = null;
+
+ if (extensions != null) {
+ // See if extension is already set and contains correct values.
+ try {
+ nsCertTypeExt = (NSCertTypeExtension)
+ extensions.get(NSCertTypeExtension.NAME);
+ } catch (IOException e) {
+ // extension isn't there.
+ nsCertTypeExt = null;
+ }
+ // XXX agent servlet currently sets this. it should be
+ // delayed to here.
+ if (nsCertTypeExt != null &&
+ extensionIsGood(nsCertTypeExt, req)) {
+ CMS.debug(
+ "NSCertTypeExt: already has correct ns cert type ext");
+ return PolicyResult.ACCEPTED;
+ } else if ((nsCertTypeExt != null) &&
+ (certType.equals("ocspResponder"))) {
+ // Fix for #528732 : Always delete
+ // this extension from OCSP signing cert
+ extensions.delete(NSCertTypeExtension.NAME);
+ return PolicyResult.ACCEPTED;
+ }
+ } else {
+ // create extensions set if none.
+ if (extensions == null) {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ CMS.debug(
+ "NSCertTypeExt: Created extensions for adding ns cert type..");
+ }
+ }
+ // add ns cert type extension if not set or not set correctly.
+ boolean[] bits = null;
+
+ bits = getBitsFromRequest(req, mSetDefaultBits);
+
+ // check if ca doesn't allow any subordinate ca
+ if (mCAPathLen == 0 && bits != null) {
+ if (bits[NSCertTypeExtension.SSL_CA_BIT] ||
+ bits[NSCertTypeExtension.EMAIL_CA_BIT] ||
+ bits[NSCertTypeExtension.OBJECT_SIGNING_CA_BIT]) {
+ setError(req,
+ CMS.getUserMessage("CMS_POLICY_NO_SUB_CA_CERTS_ALLOWED"), NAME);
+ return PolicyResult.REJECTED;
+ }
+ }
+
+ if (nsCertTypeExt != null) {
+ // replace with correct bits to comply to policy.
+ // take all that are true.
+ extensions.delete(NSCertTypeExtension.NAME);
+ }
+
+ int j;
+
+ for (j = 0; bits != null && j < bits.length; j++)
+ if (bits[j])
+ break;
+ if (bits == null || j == bits.length) {
+ if (!mSetDefaultBits) {
+ CMS.debug(
+ "NSCertTypeExt: no bits requested, not setting default.");
+ return PolicyResult.ACCEPTED;
+ } else
+ bits = DEF_BITS;
+ }
+
+ nsCertTypeExt = new NSCertTypeExtension(mCritical, bits);
+ extensions.set(NSCertTypeExtension.NAME, nsCertTypeExt);
+ return PolicyResult.ACCEPTED;
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_IO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, e.getMessage());
+ return PolicyResult.REJECTED; // unrecoverable error.
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR", e.getMessage()));
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Certificate Info Error");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+ }
+
+ /**
+ * check if ns cert type extension is set correctly,
+ * correct bits if not.
+ * if not authorized to set extension, bits will be replaced.
+ */
+ protected boolean extensionIsGood(
+ NSCertTypeExtension nsCertTypeExt, IRequest req)
+ throws IOException, CertificateException {
+ // always return false for now to make sure minimum is set.
+ // agents and ee can add others.
+
+ // must be agent approved or authenticated for allowing extensions
+ // which is always the case if we get to this point.
+ IAuthToken token = req.getExtDataInAuthToken(IRequest.AUTH_TOKEN);
+
+ if (!agentApproved(req) && token == null) {
+ // don't know where this came from.
+ // set all bits to false to reset.
+ CMS.debug(
+ "NSCertTypeExt: unknown origin: setting ns cert type bits to false");
+ boolean[] bits = new boolean[8];
+
+ for (int i = bits.length - 1; i >= 0; i--) {
+ nsCertTypeExt.set(i, false);
+ }
+ return false;
+ } else {
+ // check for min bits, set default if not there.
+ String certType = req.getExtDataInString(IRequest.HTTP_PARAMS,
+ IRequest.CERT_TYPE);
+
+ if ((certType != null) && certType.equals("ocspResponder")) {
+ return false;
+ }
+ if (certType == null || certType.length() == 0) {
+ // if don't know cert type let agent override anything.
+ return true;
+ }
+ if (certType.equals(IRequest.CA_CERT)) {
+ if (!nsCertTypeExt.isSet(NSCertTypeExtension.SSL_CA_BIT) &&
+ !nsCertTypeExt.isSet(NSCertTypeExtension.EMAIL_CA_BIT) &&
+ !nsCertTypeExt.isSet(
+ NSCertTypeExtension.OBJECT_SIGNING_CA_BIT)) {
+ // min not set so set all.
+ CMS.debug(
+ "NSCertTypeExt: is extension good: no ca bits set. set all");
+
+ nsCertTypeExt.set(NSCertTypeExtension.SSL_CA,
+ Boolean.valueOf(true));
+ nsCertTypeExt.set(NSCertTypeExtension.EMAIL_CA,
+ Boolean.valueOf(true));
+ nsCertTypeExt.set(NSCertTypeExtension.OBJECT_SIGNING_CA,
+ Boolean.valueOf(true));
+ }
+ return true;
+ } else if (certType.equals(IRequest.CLIENT_CERT)) {
+ if (!nsCertTypeExt.isSet(NSCertTypeExtension.SSL_CLIENT_BIT) &&
+ !nsCertTypeExt.isSet(NSCertTypeExtension.EMAIL_BIT) &&
+ !nsCertTypeExt.isSet(NSCertTypeExtension.SSL_SERVER_BIT) &&
+ !nsCertTypeExt.isSet(
+ NSCertTypeExtension.OBJECT_SIGNING_BIT)) {
+ // min not set so set all.
+ CMS.debug(
+ "NSCertTypeExt: is extension good: no cl bits set. set all");
+ nsCertTypeExt.set(NSCertTypeExtension.SSL_CLIENT,
+ new Boolean(true));
+ nsCertTypeExt.set(NSCertTypeExtension.EMAIL,
+ new Boolean(true));
+ nsCertTypeExt.set(NSCertTypeExtension.OBJECT_SIGNING,
+ new Boolean(true));
+ }
+ return true;
+ } else if (certType.equals(IRequest.SERVER_CERT)) {
+ // this bit must be true.
+ nsCertTypeExt.set(NSCertTypeExtension.SSL_SERVER_BIT, true);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Gets ns cert type bits from request.
+ * If none set, use cert type to determine correct bits.
+ * If no cert type, use default.
+ */
+
+ protected boolean[] getBitsFromRequest(IRequest req, boolean setDefault) {
+ boolean[] bits = null;
+
+ CMS.debug("NSCertTypeExt: ns cert type getting ns cert type vars");
+ bits = getNSCertTypeBits(req);
+ if (bits == null && setDefault) {
+ // no ns cert type bits set in request. go with cert type.
+ CMS.debug("NSCertTypeExt: ns cert type getting cert type vars");
+ bits = getCertTypeBits(req);
+
+ if (bits == null && setDefault) {
+ CMS.debug("NSCertTypeExt: ns cert type getting def bits");
+ bits = DEF_BITS;
+ }
+ }
+ return bits;
+ }
+
+ /**
+ * get ns cert type bits from actual sets in the request
+ */
+ protected boolean[] getNSCertTypeBits(IRequest req) {
+ boolean[] bits = new boolean[NSCertTypeExtension.NBITS];
+
+ bits[NSCertTypeExtension.SSL_CLIENT_BIT] =
+ // XXX should change this to is ns cert type ssl_client defn.
+ req.getExtDataInBoolean(IRequest.HTTP_PARAMS,
+ NSCertTypeExtension.SSL_CLIENT, false);
+
+ bits[NSCertTypeExtension.SSL_SERVER_BIT] =
+ req.getExtDataInBoolean(IRequest.HTTP_PARAMS,
+ NSCertTypeExtension.SSL_SERVER, false);
+
+ bits[NSCertTypeExtension.EMAIL_BIT] =
+ // XXX should change this to is ns cert type ssl_client defn.
+ req.getExtDataInBoolean(IRequest.HTTP_PARAMS,
+ NSCertTypeExtension.EMAIL, false);
+
+ bits[NSCertTypeExtension.OBJECT_SIGNING_BIT] =
+ // XXX should change this to is ns cert type ssl_client defn.
+ req.getExtDataInBoolean(IRequest.HTTP_PARAMS,
+ NSCertTypeExtension.OBJECT_SIGNING, false);
+
+ bits[NSCertTypeExtension.SSL_CA_BIT] =
+ req.getExtDataInBoolean(IRequest.HTTP_PARAMS,
+ NSCertTypeExtension.SSL_CA, false);
+
+ bits[NSCertTypeExtension.EMAIL_CA_BIT] =
+ req.getExtDataInBoolean(IRequest.HTTP_PARAMS,
+ NSCertTypeExtension.EMAIL_CA, false);
+
+ bits[NSCertTypeExtension.OBJECT_SIGNING_CA_BIT] =
+ req.getExtDataInBoolean(IRequest.HTTP_PARAMS,
+ NSCertTypeExtension.OBJECT_SIGNING_CA, false);
+
+ // if nothing set, return null.
+ int i;
+
+ for (i = bits.length - 1; i >= 0; i--) {
+ if (bits[i] == true) {
+ CMS.debug("NSCertTypeExt: bit " + i + " is set.");
+ break;
+ }
+ }
+ if (i < 0) {
+ // nothing was set.
+ CMS.debug("NSCertTypeExt: No bits were set.");
+ bits = null;
+ }
+ return bits;
+ }
+
+ /**
+ * get cert type bits according to cert type.
+ */
+ protected boolean[] getCertTypeBits(IRequest req) {
+ String certType =
+ req.getExtDataInString(IRequest.HTTP_PARAMS, IRequest.CERT_TYPE);
+
+ if (certType == null || certType.length() == 0)
+ return null;
+
+ boolean[] bits = new boolean[KeyUsageExtension.NBITS];
+
+ for (int i = bits.length - 1; i >= 0; i--)
+ bits[i] = false;
+
+ if (certType.equals(IRequest.CLIENT_CERT)) {
+ CMS.debug("NSCertTypeExt: setting bits for client cert");
+ // we can only guess here when it's client.
+ // sets all client bit for default.
+ bits[NSCertTypeExtension.SSL_CLIENT_BIT] = true;
+ bits[NSCertTypeExtension.EMAIL_BIT] = true;
+ //bits[NSCertTypeExtension.OBJECT_SIGNING_BIT] = true;
+ } else if (certType.equals(IRequest.SERVER_CERT)) {
+ CMS.debug("NSCertTypeExt: setting bits for server cert");
+ bits[NSCertTypeExtension.SSL_SERVER_BIT] = true;
+ } else if (certType.equals(IRequest.CA_CERT)) {
+ CMS.debug("NSCertType: setting bits for ca cert");
+ bits[NSCertTypeExtension.SSL_CA_BIT] = true;
+ bits[NSCertTypeExtension.EMAIL_CA_BIT] = true;
+ bits[NSCertTypeExtension.OBJECT_SIGNING_CA_BIT] = true;
+ } else if (certType.equals(IRequest.RA_CERT)) {
+ CMS.debug("NSCertType: setting bits for ra cert");
+ bits[NSCertTypeExtension.SSL_CLIENT_BIT] = true;
+ } else {
+ CMS.debug("NSCertTypeExt: no other cert bits set");
+ // return null to use default.
+ bits = DEF_BITS;
+ }
+ return bits;
+ }
+
+ /**
+ * merge bits with those set from form.
+ * make sure required minimum is set. Agent or auth can set others.
+ * XXX form shouldn't set the extension
+ */
+ public void mergeBits(NSCertTypeExtension nsCertTypeExt, boolean[] bits) {
+ for (int i = bits.length - 1; i >= 0; i--) {
+ if (bits[i] == true) {
+ CMS.debug("NSCertTypeExt: ns cert type merging bit " + i);
+ nsCertTypeExt.set(i, true);
+ }
+ }
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> params = new Vector<String>();
+
+ params.addElement(PROP_CRITICAL + "=" + mCritical);
+ params.addElement(PROP_SET_DEFAULT_BITS + "=" + mSetDefaultBits);
+ //new Boolean(mSetDefaultBits).toString());
+ return params;
+ }
+
+ private static Vector<String> mDefParams = new Vector<String>();
+ static {
+ mDefParams.addElement(
+ PROP_CRITICAL + "=false");
+ mDefParams.addElement(
+ PROP_SET_DEFAULT_BITS + "=" + DEF_SET_DEFAULT_BITS);
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_CRITICAL + ";boolean;Netscape recommendation: non-critical.",
+ PROP_SET_DEFAULT_BITS + ";boolean;Specify whether to set the Netscape certificate " +
+ "type extension with default bits ('ssl client' and 'email') in certificates " +
+ "specified by the predicate " +
+ "expression.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-nscerttype",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Adds Netscape Certificate Type extension."
+ };
+
+ return params;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return mDefParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/NameConstraintsExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/NameConstraintsExt.java
new file mode 100644
index 000000000..1b132e835
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/NameConstraintsExt.java
@@ -0,0 +1,475 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.GeneralSubtree;
+import netscape.security.x509.GeneralSubtrees;
+import netscape.security.x509.NameConstraintsExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IGeneralNameAsConstraintsConfig;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Name Constraints Extension Policy
+ * Adds the name constraints extension to a (CA) certificate.
+ * Filtering of CA certificates is done through predicates.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class NameConstraintsExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ protected static final String PROP_CRITICAL = "critical";
+ protected static final String PROP_NUM_PERMITTEDSUBTREES = "numPermittedSubtrees";
+ protected static final String PROP_NUM_EXCLUDEDSUBTREES = "numExcludedSubtrees";
+
+ protected static final String PROP_PERMITTEDSUBTREES = "permittedSubtrees";
+ protected static final String PROP_EXCLUDEDSUBTREES = "excludedSubtrees";
+
+ protected static final boolean DEF_CRITICAL = true;
+ protected static final int DEF_NUM_PERMITTEDSUBTREES = 8;
+ protected static final int DEF_NUM_EXCLUDEDSUBTREES = 8;
+
+ protected boolean mEnabled = false;
+ protected IConfigStore mConfig = null;
+
+ protected boolean mCritical = DEF_CRITICAL;
+ protected int mNumPermittedSubtrees = 0;
+ protected int mNumExcludedSubtrees = 0;
+ protected Subtree[] mPermittedSubtrees = null;
+ protected Subtree[] mExcludedSubtrees = null;
+ protected NameConstraintsExtension mNameConstraintsExtension = null;
+
+ protected Vector<String> mInstanceParams = new Vector<String>();
+
+ public NameConstraintsExt() {
+ NAME = "NameConstraintsExt";
+ DESC = "Sets Name Constraints Extension on subordinate CA certificates";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ca.Policy.rule.<ruleName>.predicate=certType==ca ca.Policy.rule.<ruleName>.implName=
+ * ca.Policy.rule.<ruleName>.enable=true
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+
+ // XXX should do do this ?
+ // if CA does not allow subordinate CAs by way of basic constraints,
+ // this policy always rejects
+ /*****
+ * ICertAuthority certAuthority = (ICertAuthority)
+ * ((IPolicyProcessor)owner).getAuthority();
+ * if (certAuthority instanceof ICertificateAuthority) {
+ * CertificateChain caChain = certAuthority.getCACertChain();
+ * X509Certificate caCert = null;
+ * // Note that in RA the chain could be null if CA was not up when
+ * // RA was started. In that case just set the length to -1 and let
+ * // CA reject if it does not allow any subordinate CA certs.
+ * if (caChain != null) {
+ * caCert = caChain.getFirstCertificate();
+ * if (caCert != null)
+ * mCAPathLen = caCert.getBasicConstraints();
+ * }
+ * }
+ ****/
+
+ mEnabled = mConfig.getBoolean(
+ IPolicyProcessor.PROP_ENABLE, false);
+ mCritical = mConfig.getBoolean(PROP_CRITICAL, DEF_CRITICAL);
+ mNumPermittedSubtrees = mConfig.getInteger(
+ PROP_NUM_PERMITTEDSUBTREES, DEF_NUM_PERMITTEDSUBTREES);
+ mNumExcludedSubtrees = mConfig.getInteger(
+ PROP_NUM_EXCLUDEDSUBTREES, DEF_NUM_EXCLUDEDSUBTREES);
+
+ if (mNumPermittedSubtrees < 0) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ PROP_NUM_PERMITTEDSUBTREES,
+ "value must be greater than or equal to 0"));
+ }
+ if (mNumExcludedSubtrees < 0) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ PROP_NUM_EXCLUDEDSUBTREES,
+ "value must be greater than or equal to 0"));
+ }
+
+ // init permitted subtrees if any.
+ if (mNumPermittedSubtrees > 0) {
+ mPermittedSubtrees =
+ form_subtrees(PROP_PERMITTEDSUBTREES, mNumPermittedSubtrees);
+ CMS.debug("NameConstraintsExt: formed permitted subtrees");
+ }
+
+ // init excluded subtrees if any.
+ if (mNumExcludedSubtrees > 0) {
+ mExcludedSubtrees =
+ form_subtrees(PROP_EXCLUDEDSUBTREES, mNumExcludedSubtrees);
+ CMS.debug("NameConstraintsExt: formed excluded subtrees");
+ }
+
+ // create instance of name constraints extension if enabled.
+ if (mEnabled) {
+ try {
+ Vector<GeneralSubtree> permittedSubtrees = new Vector<GeneralSubtree>();
+
+ for (int i = 0; i < mNumPermittedSubtrees; i++) {
+ permittedSubtrees.addElement(
+ mPermittedSubtrees[i].mGeneralSubtree);
+ }
+ Vector<GeneralSubtree> excludedSubtrees = new Vector<GeneralSubtree>();
+
+ for (int j = 0; j < mNumExcludedSubtrees; j++) {
+ excludedSubtrees.addElement(
+ mExcludedSubtrees[j].mGeneralSubtree);
+ }
+ GeneralSubtrees psb = null;
+
+ if (permittedSubtrees.size() > 0) {
+ psb = new GeneralSubtrees(permittedSubtrees);
+ }
+ GeneralSubtrees esb = null;
+
+ if (excludedSubtrees.size() > 0) {
+ esb = new GeneralSubtrees(excludedSubtrees);
+ }
+ mNameConstraintsExtension =
+ new NameConstraintsExtension(mCritical,
+ psb,
+ esb);
+ CMS.debug("NameConstraintsExt: formed Name Constraints Extension " +
+ mNameConstraintsExtension);
+ } catch (IOException e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Error initializing Name Constraints Extension: " + e));
+ }
+ }
+
+ // form instance params
+ mInstanceParams.addElement(PROP_CRITICAL + "=" + mCritical);
+ mInstanceParams.addElement(
+ PROP_NUM_PERMITTEDSUBTREES + "=" + mNumPermittedSubtrees);
+ mInstanceParams.addElement(
+ PROP_NUM_EXCLUDEDSUBTREES + "=" + mNumExcludedSubtrees);
+ if (mNumPermittedSubtrees > 0) {
+ for (int i = 0; i < mPermittedSubtrees.length; i++)
+ mPermittedSubtrees[i].getInstanceParams(mInstanceParams);
+ }
+ if (mNumExcludedSubtrees > 0) {
+ for (int j = 0; j < mExcludedSubtrees.length; j++)
+ mExcludedSubtrees[j].getInstanceParams(mInstanceParams);
+ }
+ }
+
+ Subtree[] form_subtrees(String subtreesName, int numSubtrees)
+ throws EBaseException {
+ Subtree[] subtrees = new Subtree[numSubtrees];
+
+ for (int i = 0; i < numSubtrees; i++) {
+ String subtreeName = subtreesName + i;
+ IConfigStore subtreeConfig = mConfig.getSubStore(subtreeName);
+ Subtree subtree =
+ new Subtree(subtreeName, subtreeConfig, mEnabled);
+
+ subtrees[i] = subtree;
+ }
+ return subtrees;
+ }
+
+ /**
+ * Adds Name Constraints Extension to a (CA) certificate.
+ *
+ * If a Name constraints Extension is already there, accept it if
+ * it's been approved by agent, else replace it.
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ // if extension hasn't been properly configured reject requests until
+ // it has been resolved (or disabled).
+ if (mNameConstraintsExtension == null) {
+ //setError(req, PolicyResources.EXTENSION_NOT_INITED_1, NAME);
+ //return PolicyResult.REJECTED;
+ return PolicyResult.ACCEPTED;
+ }
+
+ // get certInfo from request.
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED;
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certRes = applyCert(req, ci[i]);
+
+ if (certRes == PolicyResult.REJECTED)
+ return certRes;
+ }
+ return PolicyResult.ACCEPTED;
+
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+ // check if name constraints extension already exists.
+ // if not agent approved, replace name constraints extension with ours.
+ // else ignore.
+ try {
+ NameConstraintsExtension nameConstraintsExt = null;
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+
+ try {
+ if (extensions != null) {
+ nameConstraintsExt = (NameConstraintsExtension)
+ extensions.get(NameConstraintsExtension.NAME);
+ }
+ } catch (IOException e) {
+ // extension isn't there.
+ }
+
+ if (nameConstraintsExt != null) {
+ if (agentApproved(req)) {
+ CMS.debug(
+ "NameConstraintsExt: request id from agent " + req.getRequestId() +
+ " already has name constraints - accepted");
+ return PolicyResult.ACCEPTED;
+ } else {
+ CMS.debug(
+ "NameConstraintsExt: request id " + req.getRequestId() + " from user " +
+ " already has name constraints - deleted");
+ extensions.delete(NameConstraintsExtension.NAME);
+ }
+ }
+
+ if (extensions == null) {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ }
+ extensions.set(
+ NameConstraintsExtension.NAME, mNameConstraintsExtension);
+ CMS.debug(
+ "NameConstraintsExt: added Name Constraints Extension to request " +
+ req.getRequestId());
+ return PolicyResult.ACCEPTED;
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_NAME_CONST_EXTENSION", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, e.getMessage());
+ return PolicyResult.REJECTED;
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR", e.toString()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Certificate Info Error");
+ return PolicyResult.REJECTED;
+ }
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ return mInstanceParams;
+ }
+
+ /**
+ * Default config parameters.
+ * To add more permitted or excluded subtrees,
+ * increase the num to greater than 0 and more configuration params
+ * will show up in the console.
+ */
+ private static Vector<String> mDefParams = new Vector<String>();
+ static {
+ mDefParams.addElement(PROP_CRITICAL + "=" + DEF_CRITICAL);
+ mDefParams.addElement(
+ PROP_NUM_PERMITTEDSUBTREES + "=" + DEF_NUM_PERMITTEDSUBTREES);
+ mDefParams.addElement(
+ PROP_NUM_EXCLUDEDSUBTREES + "=" + DEF_NUM_EXCLUDEDSUBTREES);
+ for (int k = 0; k < DEF_NUM_PERMITTEDSUBTREES; k++) {
+ Subtree.getDefaultParams(PROP_PERMITTEDSUBTREES + k, mDefParams);
+ }
+ for (int l = 0; l < DEF_NUM_EXCLUDEDSUBTREES; l++) {
+ Subtree.getDefaultParams(PROP_EXCLUDEDSUBTREES + l, mDefParams);
+ }
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return mDefParams;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ Vector<String> theparams = new Vector<String>();
+
+ theparams.addElement(PROP_CRITICAL + ";boolean;RFC 2459 recommendation: MUST be critical.");
+ theparams.addElement(
+ PROP_NUM_PERMITTEDSUBTREES + ";number;See RFC 2459 sec 4.2.1.11");
+ theparams.addElement(
+ PROP_NUM_EXCLUDEDSUBTREES + ";number;See RFC 2459 sec 4.2.1.11");
+
+ // now do the subtrees.
+ for (int k = 0; k < DEF_NUM_PERMITTEDSUBTREES; k++) {
+ Subtree.getExtendedPluginInfo(PROP_PERMITTEDSUBTREES + k, theparams);
+ }
+ for (int l = 0; l < DEF_NUM_EXCLUDEDSUBTREES; l++) {
+ Subtree.getExtendedPluginInfo(PROP_EXCLUDEDSUBTREES + l, theparams);
+ }
+ theparams.addElement(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-nameconstraints");
+ theparams.addElement(IExtendedPluginInfo.HELP_TEXT +
+ ";Adds Name Constraints Extension. See RFC 2459");
+
+ String[] info = new String[theparams.size()];
+
+ theparams.copyInto(info);
+ return info;
+ }
+}
+
+/**
+ * subtree configuration
+ */
+class Subtree {
+
+ protected static final String PROP_BASE = "base";
+ protected static final String PROP_MIN = "min";
+ protected static final String PROP_MAX = "max";
+
+ protected static final int DEF_MIN = 0;
+ protected static final int DEF_MAX = -1; // -1 (less than 0) means not set.
+
+ protected static final String MINMAX_INFO = "number;See RFC 2459 section 4.2.1.11";
+
+ String mName = null;
+ IConfigStore mConfig = null;
+ int mMin = DEF_MIN, mMax = DEF_MAX;
+ IGeneralNameAsConstraintsConfig mBase = null;
+ GeneralSubtree mGeneralSubtree = null;
+
+ String mNameDot = null;
+ String mNameDotMin = null;
+ String mNameDotMax = null;
+
+ public Subtree(
+ String subtreeName, IConfigStore config, boolean policyEnabled)
+ throws EBaseException {
+ mName = subtreeName;
+ mConfig = config;
+
+ if (mName != null) {
+ mNameDot = mName + ".";
+ mNameDotMin = mNameDot + PROP_MIN;
+ mNameDotMax = mNameDot + PROP_MAX;
+ } else {
+ mNameDot = "";
+ mNameDotMin = PROP_MIN;
+ mNameDotMax = PROP_MAX;
+ }
+
+ // necessary to expand/shrink # general names from console.
+ if (mConfig.size() == 0) {
+ mConfig.putInteger(mNameDotMin, mMin);
+ mConfig.putInteger(mNameDotMax, mMax);
+ // GeneralNameConfig will take care of stuff for generalname.
+ }
+
+ // if policy enabled get values to form the general subtree.
+ mMin = mConfig.getInteger(PROP_MIN, DEF_MIN);
+ mMax = mConfig.getInteger(PROP_MAX, DEF_MAX);
+ if (mMax < -1)
+ mMax = -1;
+ mBase = CMS.createGeneralNameAsConstraintsConfig(
+ mNameDot + PROP_BASE, mConfig.getSubStore(PROP_BASE),
+ true, policyEnabled);
+
+ if (policyEnabled) {
+ mGeneralSubtree =
+ new GeneralSubtree(mBase.getGeneralName(), mMin, mMax);
+ }
+ }
+
+ void getInstanceParams(Vector<String> instanceParams) {
+ mBase.getInstanceParams(instanceParams);
+ instanceParams.addElement(mNameDotMin + "=" + mMin);
+ instanceParams.addElement(mNameDotMax + "=" + mMax);
+ }
+
+ static void getDefaultParams(String name, Vector<String> params) {
+ String nameDot = "";
+
+ if (name != null && name.length() >= 0)
+ nameDot = name + ".";
+ CMS.getGeneralNameConfigDefaultParams(nameDot + PROP_BASE, true, params);
+ params.addElement(nameDot + PROP_MIN + "=" + DEF_MIN);
+ params.addElement(nameDot + PROP_MAX + "=" + DEF_MAX);
+ }
+
+ static void getExtendedPluginInfo(String name, Vector<String> info) {
+ String nameDot = "";
+
+ if (name != null && name.length() > 0)
+ nameDot = name + ".";
+ CMS.getGeneralNameConfigExtendedPluginInfo(nameDot + PROP_BASE, true, info);
+ info.addElement(nameDot + PROP_MIN + ";" + MINMAX_INFO);
+ info.addElement(nameDot + PROP_MAX + ";" + MINMAX_INFO);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/OCSPNoCheckExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/OCSPNoCheckExt.java
new file mode 100644
index 000000000..aece9664a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/OCSPNoCheckExt.java
@@ -0,0 +1,190 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.extensions.OCSPNoCheckExtension;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * This implements an OCSP Signing policy, it
+ * adds the OCSP Signing extension to the certificate.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$ $Date$
+ */
+public class OCSPNoCheckExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+
+ public static final String PROP_CRITICAL = "critical";
+ private boolean mCritical = false;
+
+ // PKIX specifies the that the extension SHOULD NOT be critical
+ public static final boolean DEFAULT_CRITICALITY = false;
+
+ private OCSPNoCheckExtension mOCSPNoCheck = null;
+
+ /**
+ * Constructs an OCSP No check extension.
+ */
+ public OCSPNoCheckExt() {
+ NAME = "OCSPNoCheckExt";
+ DESC = "Sets OCSPNoCheck extension for certificates";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_CRITICAL + ";boolean;RFC 2560 recommendation: SHOULD be non-critical.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-ocspnocheck",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Adds OCSP signing extension to certificate"
+ };
+
+ return params;
+
+ }
+
+ /**
+ * Performs one-time initialization of the policy.
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mOCSPNoCheck = new OCSPNoCheckExtension();
+
+ if (mOCSPNoCheck != null) {
+ // configure the extension itself
+ mCritical = config.getBoolean(PROP_CRITICAL,
+ DEFAULT_CRITICALITY);
+ mOCSPNoCheck.setCritical(mCritical);
+ }
+ }
+
+ /**
+ * Applies the policy to the given request.
+ */
+ public PolicyResult apply(IRequest req) {
+
+ // if the extension was not configured correctly, just skip it
+ if (mOCSPNoCheck == null) {
+ return PolicyResult.ACCEPTED;
+ }
+
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED;
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certRes = applyCert(req, ci[i]);
+
+ if (certRes == PolicyResult.REJECTED)
+ return certRes;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+ try {
+
+ // find the extensions in the certInfo
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+
+ // prepare the extensions data structure
+ if (extensions == null) {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ } else {
+ try {
+ extensions.delete(OCSPNoCheckExtension.NAME);
+ } catch (IOException ex) {
+ // OCSPNoCheck extension is not already there
+ // log(ILogger.LL_FAILURE, "No previous extension: "+OCSPNoCheckExtension.NAME+" "+ex.getMessage());
+ }
+ }
+
+ extensions.set(OCSPNoCheckExtension.NAME, mOCSPNoCheck);
+
+ return PolicyResult.ACCEPTED;
+
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_IO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"), NAME,
+ e.getMessage());
+ return PolicyResult.REJECTED;
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"), NAME,
+ e.getMessage());
+ return PolicyResult.REJECTED;
+ }
+ }
+
+ /**
+ * Returns instance parameters.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> params = new Vector<String>();
+
+ params.addElement(PROP_CRITICAL + "=" + mCritical);
+ return params;
+
+ }
+
+ /**
+ * Returns default parameters.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> defParams = new Vector<String>();
+
+ defParams.addElement(PROP_CRITICAL + "=false");
+ return defParams;
+
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/PolicyConstraintsExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/PolicyConstraintsExt.java
new file mode 100644
index 000000000..0bb77e207
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/PolicyConstraintsExt.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.PolicyConstraintsExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Policy Constraints Extension Policy
+ * Adds the policy constraints extension to (CA) certificates.
+ * Filtering of CA certificates is done through predicates.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class PolicyConstraintsExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ protected static final String PROP_CRITICAL = "critical";
+ protected static final String PROP_REQ_EXPLICIT_POLICY = "reqExplicitPolicy";
+ protected static final String PROP_INHIBIT_POLICY_MAPPING = "inhibitPolicyMapping";
+
+ protected static final boolean DEF_CRITICAL = false;
+ protected static final int DEF_REQ_EXPLICIT_POLICY = -1; // not set
+ protected static final int DEF_INHIBIT_POLICY_MAPPING = -1; // not set
+
+ protected boolean mEnabled = false;
+ protected IConfigStore mConfig = null;
+
+ protected boolean mCritical = DEF_CRITICAL;
+ protected int mReqExplicitPolicy = DEF_REQ_EXPLICIT_POLICY;
+ protected int mInhibitPolicyMapping = DEF_INHIBIT_POLICY_MAPPING;
+ protected PolicyConstraintsExtension mPolicyConstraintsExtension = null;
+
+ protected Vector<String> mInstanceParams = new Vector<String>();
+
+ protected static Vector<String> mDefaultParams = new Vector<String>();
+ static {
+ mDefaultParams.addElement(PROP_CRITICAL + "=" + DEF_CRITICAL);
+ mDefaultParams.addElement(
+ PROP_REQ_EXPLICIT_POLICY + "=" + DEF_REQ_EXPLICIT_POLICY);
+ mDefaultParams.addElement(
+ PROP_INHIBIT_POLICY_MAPPING + "=" + DEF_INHIBIT_POLICY_MAPPING);
+ }
+
+ public PolicyConstraintsExt() {
+ NAME = "PolicyConstriantsExt";
+ DESC = "Sets Policy Constraints Extension on subordinate CA certs";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ca.Policy.rule.<ruleName>.predicate=certType==ca ca.Policy.rule.<ruleName>.implName=
+ * ca.Policy.rule.<ruleName>.enable=true
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+
+ // XXX should do do this ?
+ // if CA does not allow subordinate CAs by way of basic constraints,
+ // this policy always rejects
+ /*****
+ * ICertAuthority certAuthority = (ICertAuthority)
+ * ((GenericPolicyProcessor)owner).mAuthority;
+ * if (certAuthority instanceof ICertificateAuthority) {
+ * CertificateChain caChain = certAuthority.getCACertChain();
+ * X509Certificate caCert = null;
+ * // Note that in RA the chain could be null if CA was not up when
+ * // RA was started. In that case just set the length to -1 and let
+ * // CA reject if it does not allow any subordinate CA certs.
+ * if (caChain != null) {
+ * caCert = caChain.getFirstCertificate();
+ * if (caCert != null)
+ * mCAPathLen = caCert.getBasicConstraints();
+ * }
+ * }
+ ****/
+
+ mEnabled = mConfig.getBoolean(
+ IPolicyProcessor.PROP_ENABLE, false);
+ mCritical = mConfig.getBoolean(PROP_CRITICAL, DEF_CRITICAL);
+
+ mReqExplicitPolicy = mConfig.getInteger(
+ PROP_REQ_EXPLICIT_POLICY, DEF_REQ_EXPLICIT_POLICY);
+ mInhibitPolicyMapping = mConfig.getInteger(
+ PROP_INHIBIT_POLICY_MAPPING, DEF_INHIBIT_POLICY_MAPPING);
+
+ if (mReqExplicitPolicy < -1)
+ mReqExplicitPolicy = -1;
+ if (mInhibitPolicyMapping < -1)
+ mInhibitPolicyMapping = -1;
+
+ // create instance of policy constraings extension
+ try {
+ mPolicyConstraintsExtension =
+ new PolicyConstraintsExtension(mCritical,
+ mReqExplicitPolicy, mInhibitPolicyMapping);
+ CMS.debug(
+ "PolicyConstraintsExt: Created Policy Constraints Extension: " +
+ mPolicyConstraintsExtension);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_CANT_INIT_POLICY_CONST_EXT", e.toString()));
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Could not init Policy Constraints Extension. Error: " + e));
+ }
+
+ // form instance params
+ mInstanceParams.addElement(PROP_CRITICAL + "=" + mCritical);
+ mInstanceParams.addElement(
+ PROP_REQ_EXPLICIT_POLICY + "=" + mReqExplicitPolicy);
+ mInstanceParams.addElement(
+ PROP_INHIBIT_POLICY_MAPPING + "=" + mInhibitPolicyMapping);
+ }
+
+ /**
+ * Adds Policy Constraints Extension to a (CA) certificate.
+ *
+ * If a Policy constraints Extension is already there, accept it if
+ * it's been approved by agent, else replace it.
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ // if extension hasn't been properly configured reject requests until
+ // it has been resolved (or disabled).
+ if (mPolicyConstraintsExtension == null) {
+ return PolicyResult.ACCEPTED;
+ }
+
+ // get certInfo from request.
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED;
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certRes = applyCert(req, ci[i]);
+
+ if (certRes == PolicyResult.REJECTED)
+ return certRes;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+
+ // check if name constraints extension already exists.
+ // if not agent approved, replace name constraints extension with ours.
+ // else ignore.
+ try {
+ PolicyConstraintsExtension policyConstraintsExt = null;
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+
+ try {
+ if (extensions != null) {
+ policyConstraintsExt = (PolicyConstraintsExtension)
+ extensions.get(PolicyConstraintsExtension.NAME);
+ }
+ } catch (IOException e) {
+ // extension isn't there.
+ }
+
+ if (policyConstraintsExt != null) {
+ if (agentApproved(req)) {
+ return PolicyResult.ACCEPTED;
+ } else {
+ extensions.delete(PolicyConstraintsExtension.NAME);
+ }
+ }
+
+ if (extensions == null) {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ }
+ extensions.set(
+ "PolicyConstriantsExt", mPolicyConstraintsExtension);
+ CMS.debug("PolicyConstraintsExt: added our policy constraints extension");
+ return PolicyResult.ACCEPTED;
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_CANT_PROCESS_POLICY_CONST_EXT", e.toString()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, e.getMessage());
+ return PolicyResult.REJECTED;
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR", e.toString()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Certificate Info Error");
+ return PolicyResult.REJECTED;
+ }
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ return mInstanceParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return mDefaultParams;
+ }
+
+ /**
+ * gets plugin info for pretty console edit displays.
+ */
+ public String[] getExtendedPluginInfo(Locale locale) {
+ mInstanceParams.addElement(PROP_CRITICAL + "=" + mCritical);
+ mInstanceParams.addElement(
+ PROP_REQ_EXPLICIT_POLICY + "=" + mReqExplicitPolicy);
+ mInstanceParams.addElement(
+ PROP_INHIBIT_POLICY_MAPPING + "=" + mInhibitPolicyMapping);
+
+ String[] params = {
+ PROP_CRITICAL + ";boolean;RFC 2459 recommendation: may be critical or non-critical.",
+ PROP_REQ_EXPLICIT_POLICY
+ + ";integer;Number of addional certificates that may appear in the path before an explicit policy is required. If less than 0 this field is unset in the extension.",
+ PROP_INHIBIT_POLICY_MAPPING
+ + ";integer;Number of addional certificates that may appear in the path before policy mapping is no longer permitted. If less than 0 this field is unset in the extension.",
+ IExtendedPluginInfo.HELP_TOKEN + ";configuration-policyrules-policyconstraints"
+ };
+
+ return params;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/PolicyMappingsExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/PolicyMappingsExt.java
new file mode 100644
index 000000000..0af8b86ca
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/PolicyMappingsExt.java
@@ -0,0 +1,426 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificatePolicyId;
+import netscape.security.x509.CertificatePolicyMap;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.PolicyMappingsExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Policy Mappings Extension Policy
+ * Adds the Policy Mappings extension to a (CA) certificate.
+ * Filtering of CA certificates is done through predicates.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class PolicyMappingsExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ protected static final String PROP_CRITICAL = "critical";
+ protected static final String PROP_NUM_POLICYMAPPINGS = "numPolicyMappings";
+
+ protected static final String PROP_POLICYMAP = "policyMap";
+
+ protected static final boolean DEF_CRITICAL = false;
+ protected static final int DEF_NUM_POLICYMAPPINGS = 1;
+
+ protected boolean mEnabled = false;
+ protected IConfigStore mConfig = null;
+
+ protected boolean mCritical = DEF_CRITICAL;
+ protected int mNumPolicyMappings = DEF_NUM_POLICYMAPPINGS;
+ protected PolicyMap[] mPolicyMaps = null;
+ protected PolicyMappingsExtension mPolicyMappingsExtension = null;
+
+ protected Vector<String> mInstanceParams = new Vector<String>();
+
+ public PolicyMappingsExt() {
+ NAME = "PolicyMappingsExt";
+ DESC = "Sets Policy Mappings Extension on subordinate CA certificates";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ca.Policy.rule.<ruleName>.predicate=certType==ca ca.Policy.rule.<ruleName>.implName=
+ * ca.Policy.rule.<ruleName>.enable=true
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+
+ // XXX should do do this ?
+ // if CA does not allow subordinate CAs by way of basic constraints,
+ // this policy always rejects
+ /*****
+ * ICertAuthority certAuthority = (ICertAuthority)
+ * ((IPolicyProcessor)owner).getAuthority();
+ * if (certAuthority instanceof ICertificateAuthority) {
+ * CertificateChain caChain = certAuthority.getCACertChain();
+ * X509Certificate caCert = null;
+ * // Note that in RA the chain could be null if CA was not up when
+ * // RA was started. In that case just set the length to -1 and let
+ * // CA reject if it does not allow any subordinate CA certs.
+ * if (caChain != null) {
+ * caCert = caChain.getFirstCertificate();
+ * if (caCert != null)
+ * mCAPathLen = caCert.getBasicConstraints();
+ * }
+ * }
+ ****/
+
+ mEnabled = mConfig.getBoolean(
+ IPolicyProcessor.PROP_ENABLE, false);
+ mCritical = mConfig.getBoolean(PROP_CRITICAL, DEF_CRITICAL);
+
+ mNumPolicyMappings = mConfig.getInteger(
+ PROP_NUM_POLICYMAPPINGS, DEF_NUM_POLICYMAPPINGS);
+ if (mNumPolicyMappings < 1) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_ATTR_VALUE_2", NAME, ""));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ PROP_NUM_POLICYMAPPINGS,
+ "value must be greater than or equal to 1"));
+ }
+
+ // init Policy Mappings, check values if enabled.
+ mPolicyMaps = new PolicyMap[mNumPolicyMappings];
+ for (int i = 0; i < mNumPolicyMappings; i++) {
+ String subtreeName = PROP_POLICYMAP + i;
+
+ try {
+ mPolicyMaps[i] = new PolicyMap(subtreeName, mConfig, mEnabled);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, NAME + ": " +
+ CMS.getLogMessage("POLICY_ERROR_CREATE_MAP", e.toString()));
+ throw e;
+ }
+ }
+
+ // create instance of policy mappings extension if enabled.
+ if (mEnabled) {
+ try {
+ Vector<CertificatePolicyMap> certPolicyMaps = new Vector<CertificatePolicyMap>();
+
+ for (int j = 0; j < mNumPolicyMappings; j++) {
+ certPolicyMaps.addElement(
+ mPolicyMaps[j].mCertificatePolicyMap);
+ }
+ mPolicyMappingsExtension =
+ new PolicyMappingsExtension(mCritical, certPolicyMaps);
+ } catch (IOException e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Error initializing " + NAME + " Error: " + e));
+ }
+ }
+
+ // form instance params
+ mInstanceParams.addElement(PROP_CRITICAL + "=" + mCritical);
+ mInstanceParams.addElement(
+ PROP_NUM_POLICYMAPPINGS + "=" + mNumPolicyMappings);
+ for (int i = 0; i < mNumPolicyMappings; i++) {
+ mPolicyMaps[i].getInstanceParams(mInstanceParams);
+ }
+ }
+
+ /**
+ * Adds policy mappings Extension to a (CA) certificate.
+ *
+ * If a policy mappings Extension is already there, accept it if
+ * it's been approved by agent, else replace it.
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ // if extension hasn't been properly configured reject requests until
+ // it has been resolved (or disabled).
+ if (mPolicyMappingsExtension == null) {
+ //setError(req, PolicyResources.EXTENSION_NOT_INITED_1, NAME);
+ //return PolicyResult.REJECTED;
+ return PolicyResult.ACCEPTED;
+ }
+
+ // get certInfo from request.
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED;
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certRes = applyCert(req, ci[i]);
+
+ if (certRes == PolicyResult.REJECTED)
+ return certRes;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+ // check if policy mappings extension already exists.
+ // if not agent approved, replace policy mappings extension with ours.
+ // else ignore.
+ try {
+ PolicyMappingsExtension policyMappingsExt = null;
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+
+ try {
+ if (extensions != null) {
+ policyMappingsExt = (PolicyMappingsExtension)
+ extensions.get(PolicyMappingsExtension.NAME);
+ }
+ } catch (IOException e) {
+ // extension isn't there.
+ }
+
+ if (policyMappingsExt != null) {
+ if (agentApproved(req)) {
+ return PolicyResult.ACCEPTED;
+ } else {
+ extensions.delete(PolicyMappingsExtension.NAME);
+ }
+ }
+
+ if (extensions == null) {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ }
+ extensions.set(
+ PolicyMappingsExtension.NAME, mPolicyMappingsExtension);
+ return PolicyResult.ACCEPTED;
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_PROCESS_POLICYMAP_EXT", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, e.getMessage());
+ return PolicyResult.REJECTED;
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR", e.toString()));
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Certificate Info Error");
+ return PolicyResult.REJECTED;
+ }
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ return mInstanceParams;
+ }
+
+ /**
+ * Default config parameters.
+ * To add more permitted or excluded subtrees,
+ * increase the num to greater than 0 and more configuration params
+ * will show up in the console.
+ */
+ private static Vector<String> mDefParams = new Vector<String>();
+ static {
+ mDefParams.addElement(PROP_CRITICAL + "=" + DEF_CRITICAL);
+ mDefParams.addElement(
+ PROP_NUM_POLICYMAPPINGS + "=" + DEF_NUM_POLICYMAPPINGS);
+ String policyMap0Dot = PROP_POLICYMAP + "0.";
+
+ mDefParams.addElement(
+ policyMap0Dot + PolicyMap.PROP_ISSUER_DOMAIN_POLICY + "=" + "");
+ mDefParams.addElement(
+ policyMap0Dot + PolicyMap.PROP_SUBJECT_DOMAIN_POLICY + "=" + "");
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return mDefParams;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ Vector<String> theparams = new Vector<String>();
+
+ theparams.addElement(PROP_CRITICAL + ";boolean;RFC 2459 recommendation: MUST be non-critical.");
+ theparams.addElement(PROP_NUM_POLICYMAPPINGS
+ + ";number; Number of policy mappings. The value must be greater than or equal to 1");
+
+ String policyInfo =
+ ";string;An object identifier in the form n.n.n.n";
+
+ for (int k = 0; k < 5; k++) {
+ String policyMapkDot = PROP_POLICYMAP + k + ".";
+
+ theparams.addElement(policyMapkDot +
+ PolicyMap.PROP_ISSUER_DOMAIN_POLICY + policyInfo);
+ theparams.addElement(policyMapkDot +
+ PolicyMap.PROP_SUBJECT_DOMAIN_POLICY + policyInfo);
+ }
+
+ theparams.addElement(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-policymappings");
+ theparams.addElement(IExtendedPluginInfo.HELP_TEXT +
+ ";Adds Policy Mappings Extension. See RFC 2459 (4.2.1.6)");
+
+ String[] params = new String[theparams.size()];
+
+ theparams.copyInto(params);
+ return params;
+ }
+}
+
+class PolicyMap {
+
+ protected static String PROP_ISSUER_DOMAIN_POLICY = "issuerDomainPolicy";
+ protected static String PROP_SUBJECT_DOMAIN_POLICY = "subjectDomainPolicy";
+
+ protected String mName = null;
+ protected String mNameDot = null;
+ protected IConfigStore mConfig = null;
+ protected String mIssuerDomainPolicy = null;
+ protected String mSubjectDomainPolicy = null;
+ protected CertificatePolicyMap mCertificatePolicyMap = null;
+
+ /**
+ * forms policy map parameters.
+ *
+ * @param name name of this policy map, for example policyMap0
+ * @param config parent's config from where we find this configuration.
+ * @param enabled whether policy was enabled.
+ */
+ protected PolicyMap(String name, IConfigStore config, boolean enabled)
+ throws EBaseException {
+ mName = name;
+ mConfig = config.getSubStore(mName);
+ mNameDot = mName + ".";
+
+ if (mConfig == null) {
+ CMS.debug("PolicyMappingsExt::PolicyMap - mConfig is null!");
+ return;
+ }
+
+ // if there's no configuration for this map put it there.
+ if (mConfig.size() == 0) {
+ config.putString(mNameDot + PROP_ISSUER_DOMAIN_POLICY, "");
+ config.putString(mNameDot + PROP_SUBJECT_DOMAIN_POLICY, "");
+ mConfig = config.getSubStore(mName);
+ if (mConfig == null || mConfig.size() == 0) {
+ CMS.debug("PolicyMappingsExt::PolicyMap - mConfig " +
+ "is null or empty!");
+ return;
+ }
+ }
+
+ // get policy ids from configuration.
+ mIssuerDomainPolicy =
+ mConfig.getString(PROP_ISSUER_DOMAIN_POLICY, null);
+ mSubjectDomainPolicy =
+ mConfig.getString(PROP_SUBJECT_DOMAIN_POLICY, null);
+
+ // adjust for "" and console returning "null"
+ if (mIssuerDomainPolicy != null &&
+ (mIssuerDomainPolicy.length() == 0 ||
+ mIssuerDomainPolicy.equals("null"))) {
+ mIssuerDomainPolicy = null;
+ }
+ if (mSubjectDomainPolicy != null &&
+ (mSubjectDomainPolicy.length() == 0 ||
+ mSubjectDomainPolicy.equals("null"))) {
+ mSubjectDomainPolicy = null;
+ }
+
+ // policy ids cannot be null if policy is enabled.
+ String msg = "value cannot be null.";
+
+ if (mIssuerDomainPolicy == null && enabled)
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ mNameDot + PROP_ISSUER_DOMAIN_POLICY, msg));
+ if (mSubjectDomainPolicy == null && enabled)
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ mNameDot + PROP_SUBJECT_DOMAIN_POLICY, msg));
+
+ // if a policy id is not null check that it is a valid OID.
+ ObjectIdentifier issuerPolicyId = null;
+ ObjectIdentifier subjectPolicyId = null;
+
+ if (mIssuerDomainPolicy != null)
+ issuerPolicyId = CMS.checkOID(
+ mNameDot + PROP_ISSUER_DOMAIN_POLICY, mIssuerDomainPolicy);
+ if (mSubjectDomainPolicy != null)
+ subjectPolicyId = CMS.checkOID(
+ mNameDot + PROP_SUBJECT_DOMAIN_POLICY, mSubjectDomainPolicy);
+
+ // if enabled, form CertificatePolicyMap to be encoded in extension.
+ // policy ids should be all set.
+ if (enabled) {
+ mCertificatePolicyMap = new CertificatePolicyMap(
+ new CertificatePolicyId(issuerPolicyId),
+ new CertificatePolicyId(subjectPolicyId));
+ }
+ }
+
+ protected void getInstanceParams(Vector<String> instanceParams) {
+ instanceParams.addElement(
+ mNameDot + PROP_ISSUER_DOMAIN_POLICY + "=" + (mIssuerDomainPolicy == null ? "" :
+ mIssuerDomainPolicy));
+ instanceParams.addElement(
+ mNameDot + PROP_SUBJECT_DOMAIN_POLICY + "=" + (mSubjectDomainPolicy == null ? "" :
+ mSubjectDomainPolicy));
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/PresenceExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/PresenceExt.java
new file mode 100644
index 000000000..7f44c8eb0
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/PresenceExt.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.util.Locale;
+import java.util.Vector;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Checks extension presence.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class PresenceExt extends APolicyRule {
+ private static Vector<String> mDefParams = new Vector<String>();
+ @SuppressWarnings("unused")
+ private IConfigStore mConfig;
+ private String mOID = null;
+ private boolean mCritical;
+ private int mVersion = 0;
+ private String mStreetAddress;
+ private String mTelephoneNumber;
+ private String mRFC822Name;
+ private String mID;
+ private String mHostName;
+ private int mPortNumber = 0;
+ private int mMaxUsers = 0;
+ private int mServiceLevel = 0;
+
+ public static final String PROP_IS_CRITICAL = "critical";
+ public static final String PROP_OID = "oid";
+ public static final String PROP_VERSION = "version";
+ public static final String PROP_STREET_ADDRESS = "streetAddress";
+ public static final String PROP_TELEPHONE_NUMBER = "telephoneNumber";
+ public static final String PROP_RFC822_NAME = "rfc822Name";
+ public static final String PROP_ID = "id";
+ public static final String PROP_HOSTNAME = "hostName";
+ public static final String PROP_PORT_NUMBER = "portNumber";
+ public static final String PROP_MAX_USERS = "maxUsers";
+ public static final String PROP_SERVICE_LEVEL = "serviceLevel";
+
+ static {
+ mDefParams.addElement(PROP_IS_CRITICAL + "=false");
+ }
+
+ public PresenceExt() {
+ NAME = "PresenceExtPolicy";
+ DESC = "Sets Presence Server Extension in certificates.";
+ }
+
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+
+ mCritical = config.getBoolean(PROP_IS_CRITICAL, false);
+ mOID = config.getString(PROP_OID, "");
+ mVersion = config.getInteger(PROP_VERSION, 0);
+ mStreetAddress = config.getString(PROP_STREET_ADDRESS, "");
+ mTelephoneNumber = config.getString(PROP_TELEPHONE_NUMBER, "");
+ mRFC822Name = config.getString(PROP_RFC822_NAME, "");
+ mID = config.getString(PROP_ID, "");
+ mHostName = config.getString(PROP_HOSTNAME, "");
+ mPortNumber = config.getInteger(PROP_PORT_NUMBER, 0);
+ mMaxUsers = config.getInteger(PROP_MAX_USERS, 0);
+ mServiceLevel = config.getInteger(PROP_SERVICE_LEVEL, 0);
+ }
+
+ public PolicyResult apply(IRequest req) {
+ PolicyResult res = PolicyResult.ACCEPTED;
+
+ /*
+ PresenceServerExtension ext = new PresenceServerExtension(mCritical,
+ mOID, mVersion, mStreetAddress,
+ mTelephoneNumber, mRFC822Name, mID,
+ mHostName, mPortNumber, mMaxUsers, mServiceLevel);
+ */
+
+ return res;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> params = new Vector<String>();
+
+ params.addElement(PROP_IS_CRITICAL + "=" + mCritical);
+ params.addElement(PROP_OID + "=" + mOID);
+ params.addElement(PROP_VERSION + "=" + mVersion);
+ params.addElement(PROP_STREET_ADDRESS + "=" + mStreetAddress);
+ params.addElement(PROP_TELEPHONE_NUMBER + "=" + mTelephoneNumber);
+ params.addElement(PROP_RFC822_NAME + "=" + mRFC822Name);
+ params.addElement(PROP_ID + "=" + mID);
+ params.addElement(PROP_HOSTNAME + "=" + mHostName);
+ params.addElement(PROP_PORT_NUMBER + "=" + mPortNumber);
+ params.addElement(PROP_MAX_USERS + "=" + mMaxUsers);
+ params.addElement(PROP_SERVICE_LEVEL + "=" + mServiceLevel);
+ return params;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_IS_CRITICAL + ";boolean;Criticality",
+ PROP_OID + ";string; Object identifier of this extension",
+ PROP_VERSION + ";string; version",
+ PROP_STREET_ADDRESS + ";string; street address",
+ PROP_TELEPHONE_NUMBER + ";string; telephone number",
+ PROP_RFC822_NAME + ";string; rfc822 name",
+ PROP_ID + ";string; identifier",
+ PROP_HOSTNAME + ";string; host name",
+ PROP_PORT_NUMBER + ";string; port number",
+ PROP_MAX_USERS + ";string; max users",
+ PROP_SERVICE_LEVEL + ";string; service level",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-presenceext",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Adds Presence Server Extension;"
+
+ };
+
+ return params;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return mDefParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/PrivateKeyUsagePeriodExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/PrivateKeyUsagePeriodExt.java
new file mode 100644
index 000000000..fd52e9bb1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/PrivateKeyUsagePeriodExt.java
@@ -0,0 +1,252 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.PrivateKeyUsageExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * PrivateKeyUsagePeriod Identifier Extension policy.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class PrivateKeyUsagePeriodExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+
+ private final static String PROP_NOT_BEFORE = "notBefore";
+ private final static String PROP_NOT_AFTER = "notAfter";
+ protected static final String PROP_IS_CRITICAL = "critical";
+
+ // 6 months roughly
+ private final static long defDuration = 60L * 60 * 24 * 180 * 1000;
+
+ private static final String DATE_PATTERN = "MM/dd/yyyy";
+ static SimpleDateFormat formatter = new SimpleDateFormat(DATE_PATTERN);
+ private static Date now = CMS.getCurrentDate();
+ private static Date six_months = new Date(now.getTime() + defDuration);
+
+ public static final String DEFAULT_NOT_BEFORE = formatter.format(now);
+ public static final String DEFAULT_NOT_AFTER = formatter.format(six_months);
+
+ // PKIX specifies the that the extension SHOULD NOT be critical
+ public static final boolean DEFAULT_CRITICALITY = false;
+
+ protected String mNotBefore;
+ protected String mNotAfter;
+ protected boolean mCritical;
+
+ private static Vector<String> defaultParams;
+
+ static {
+
+ formatter.setLenient(false);
+
+ defaultParams = new Vector<String>();
+ defaultParams.addElement(PROP_IS_CRITICAL + "=" + DEFAULT_CRITICALITY);
+ defaultParams.addElement(PROP_NOT_BEFORE + "=" + DEFAULT_NOT_BEFORE);
+ defaultParams.addElement(PROP_NOT_AFTER + "=" + DEFAULT_NOT_AFTER);
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_IS_CRITICAL + ";boolean;RFC 2459 recommendation: The profile " +
+ "recommends against the use of this extension. CAs " +
+ "conforming to the profile MUST NOT generate certs with " +
+ "critical private key usage period extensions.",
+ PROP_NOT_BEFORE + ";string; Date before which the Private Key is invalid.",
+ PROP_NOT_AFTER + ";string; Date after which the Private Key is invalid.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-privatekeyusageperiod",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Adds (deprecated) Private Key Usage Period Extension. " +
+ "Defined in RFC 2459 (4.2.1.4)"
+ };
+
+ return params;
+ }
+
+ /**
+ * Adds the private key usage extension to all certs.
+ */
+ public PrivateKeyUsagePeriodExt() {
+ NAME = "PrivateKeyUsagePeriodExt";
+ DESC = "Sets Private Key Usage Extension for a certificate";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * ra.Policy.rule.<ruleName>.implName=PrivateKeyUsageExtension
+ * ra.Policy.rule.<ruleName>.enable=true
+ * ra.Policy.rule.<ruleName>.notBefore=30
+ * ra.Policy.rule.<ruleName>.notAfter=180
+ * ra.Policy.rule.<ruleName>.critical=false
+ * ra.Policy.rule.<ruleName>.predicate=ou==Sales
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+
+ try {
+ // Get params.
+ mNotBefore = config.getString(PROP_NOT_BEFORE, null);
+ mNotAfter = config.getString(PROP_NOT_AFTER, null);
+ mCritical = config.getBoolean(PROP_IS_CRITICAL, false);
+
+ // Check the parameter formats for errors
+ formatter.format(formatter.parse(mNotBefore.trim()));
+ formatter.format(formatter.parse(mNotAfter.trim()));
+ } catch (Exception e) {
+ // e.printStackTrace();
+ Object[] params = { getInstanceName(), e };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CONFIG"), params);
+ }
+
+ }
+
+ /**
+ * Adds a private key usage extension if none exists.
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+
+ // get cert info.
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certRes = applyCert(req, ci[i]);
+
+ if (certRes == PolicyResult.REJECTED)
+ return certRes;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+ // get private key usage extension from cert info if any.
+ CertificateExtensions extensions = null;
+ PrivateKeyUsageExtension ext = null;
+
+ try {
+ // get subject key id extension if any.
+ extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+ } catch (IOException e) {
+ // no extensions or subject key identifier extension.
+ } catch (CertificateException e) {
+ // no extensions or subject key identifier extension.
+ }
+
+ if (extensions == null) {
+ extensions = new CertificateExtensions();
+ } else {
+ // remove any previously computed version of the extension
+ try {
+ extensions.delete(PrivateKeyUsageExtension.NAME);
+
+ } catch (IOException e) {
+ }
+
+ }
+
+ try {
+ ext = new PrivateKeyUsageExtension(
+ formatter.parse(mNotBefore),
+ formatter.parse(mNotAfter));
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions.set(PrivateKeyUsageExtension.NAME, ext);
+ } catch (Exception e) {
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_CREATE_PRIVATE_KEY_EXT", e.toString()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_SUBJECT_KEY_ID_ERROR"), NAME);
+ return PolicyResult.REJECTED;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return Empty Vector since this policy has no configuration parameters.
+ * for this policy instance.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> params = new Vector<String>();
+
+ params.addElement(PROP_IS_CRITICAL + "=" + mCritical);
+ params.addElement(PROP_NOT_BEFORE + "=" + mNotBefore);
+ params.addElement(PROP_NOT_AFTER + "=" + mNotAfter);
+ return params;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return Empty Vector since this policy implementation has no
+ * configuration parameters.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> defParams = new Vector<String>();
+
+ defParams.addElement(PROP_IS_CRITICAL + "=" + DEFAULT_CRITICALITY);
+ defParams.addElement(PROP_NOT_BEFORE + "=" + DEFAULT_NOT_BEFORE);
+ defParams.addElement(PROP_NOT_AFTER + "=" + DEFAULT_NOT_AFTER);
+ return defParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/RemoveBasicConstraintsExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/RemoveBasicConstraintsExt.java
new file mode 100644
index 000000000..b5d6d8eec
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/RemoveBasicConstraintsExt.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Remove Basic Constraints policy.
+ * Adds the Basic constraints extension.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class RemoveBasicConstraintsExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ public RemoveBasicConstraintsExt() {
+ NAME = "RemoveBasicConstraintsExt";
+ DESC = "Remove Basic Constraints extension";
+ }
+
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ }
+
+ public PolicyResult apply(IRequest req) {
+
+ // get cert info.
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ X509CertInfo certInfo = null;
+
+ if (ci == null || (certInfo = ci[0]) == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certResult = applyCert(req, certInfo);
+
+ if (certResult == PolicyResult.REJECTED)
+ return certResult;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(
+ IRequest req, X509CertInfo certInfo) {
+ // get basic constraints extension from cert info if any.
+ CertificateExtensions extensions = null;
+
+ try {
+ // get basic constraints extension if any.
+ extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+ if (extensions != null) {
+ try {
+ extensions.delete(BasicConstraintsExtension.NAME);
+ CMS.debug("PolicyRule RemoveBasicConstraintsExt: removed the extension from request "
+ + req.getRequestId().toString());
+ } catch (IOException e) {
+ }
+ }
+ } catch (IOException e) {
+ // no extensions or basic constraints extension.
+ } catch (CertificateException e) {
+ // no extensions or basic constraints extension.
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> params = new Vector<String>();
+
+ return params;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> defParams = new Vector<String>();
+
+ return defParams;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-removebasicconstraints",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Removes the Basic Constraints extension."
+ };
+
+ return params;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/SubjAltNameExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/SubjAltNameExt.java
new file mode 100644
index 000000000..d6e626aa9
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/SubjAltNameExt.java
@@ -0,0 +1,356 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.RFC822Name;
+import netscape.security.x509.SubjectAlternativeNameExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ *
+ * THIS POLICY HAS BEEN DEPRECATED SINCE CMS 4.2.
+ * New Policy is com.netscape.certsrv.policy.SubjectAltNameExt.
+ * <p>
+ *
+ * Subject Alternative Name extension policy in CMS 4.1.
+ *
+ * Adds the subject alternative name extension depending on the certificate type requested.
+ *
+ * Two forms are supported. 1) For S/MIME certificates, email addresses are copied from data stored in the request by
+ * the authentication component. Both 'e' and 'altEmail' are supported so that both the primary address and alternative
+ * forms may be certified. Only the primary goes in the subjectName position (which should be phased out).
+ *
+ * e mailAlternateAddress
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class SubjAltNameExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ // for future use. currently always allow.
+ protected static final String PROP_AGENT_OVERR = "allowAgentOverride";
+ protected static final String PROP_EE_OVERR = "AllowEEOverride";
+ protected static final String PROP_ENABLE_MANUAL_VALUES =
+ "enableManualValues";
+
+ // for future use. currently always non-critical
+ // (standard says SHOULD be marked critical if included.)
+ protected static final String PROP_CRITICAL = "critical";
+
+ // for future use to allow overrides from forms.
+ // request must be agent approved or authenticated.
+ protected boolean mAllowAgentOverride = false;
+ protected boolean mAllowEEOverride = false;
+ protected boolean mEnableManualValues = false;
+
+ // for future use. currently always critical
+ // (standard says SHOULD be marked critical if included.)
+ protected boolean mCritical = false;
+
+ public SubjAltNameExt() {
+ NAME = "SubjAltNameExt";
+ DESC = "Sets alternative subject names for certificates";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_CRITICAL
+ + ";boolean;RFC 2459 recommendation: If the certificate subject field contains an empty sequence, the subjectAltName extension MUST be marked critical.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-subjaltname",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";This policy inserts the Subject Alternative Name " +
+ "Extension into the certificate. See RFC 2459 (4.2.1.7). " +
+ "* Note: you probably want to use this policy in " +
+ "conjunction with an authentication manager which sets " +
+ "the 'mail' or 'mailalternateaddress' values in the authToken. " +
+ "See the 'ldapStringAttrs' parameter in the Directory-based " +
+ "authentication plugin"
+ };
+
+ return params;
+
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ra.Policy.rule.<ruleName>.implName=SubjAltNameExt ra.Policy.rule.<ruleName>.enable=true
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ // future use.
+ mAllowAgentOverride = config.getBoolean(PROP_AGENT_OVERR, false);
+ mAllowEEOverride = config.getBoolean(PROP_EE_OVERR, false);
+ mCritical = config.getBoolean(PROP_CRITICAL, false);
+ // mEnableManualValues = config.getBoolean(PROP_ENABLE_MANUAL_VALUES, false);
+ }
+
+ /**
+ * Adds the subject alternative names extension if not set already.
+ *
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ PolicyResult res = PolicyResult.ACCEPTED;
+
+ // Find the X509CertInfo object in the request
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certRes = applyCert(req, ci[i]);
+
+ if (certRes == PolicyResult.REJECTED)
+ return certRes;
+ }
+ return res;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+ PolicyResult res = PolicyResult.ACCEPTED;
+
+ //
+ // General error handling block
+ //
+ apply: try {
+
+ // Find the extensions in the certInfo
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+
+ if (extensions != null) {
+ //
+ // Remove any previously computed version of the extension
+ //
+ try {
+ extensions.delete(SubjectAlternativeNameExtension.NAME);
+ } catch (IOException e) {
+ // extension isn't there
+ }
+ }
+
+ //
+ // Determine the type of the request. For future expansion
+ // this test should dispatch to a specialized object to
+ // handle each particular type. For now just return for
+ // non-client certs, and implement client certs directly here.
+ //
+ String certType =
+ req.getExtDataInString(IRequest.HTTP_PARAMS, IRequest.CERT_TYPE);
+
+ if (certType == null ||
+ !certType.equals(IRequest.CLIENT_CERT) ||
+ !req.getExtDataInBoolean(IRequest.SMIME, false)) {
+ break apply;
+ }
+
+ // Create a list of email addresses that should be added
+ // to the certificate
+
+ IAuthToken tok = findAuthToken(req, null);
+
+ if (tok == null)
+ break apply;
+
+ Vector<String> emails = getEmailList(tok);
+
+ if (emails == null)
+ break apply;
+
+ // Create the extension
+ SubjectAlternativeNameExtension subjAltNameExt = mkExt(emails);
+
+ if (extensions == null)
+ extensions = createCertificateExtensions(certInfo);
+
+ extensions.set(SubjectAlternativeNameExtension.NAME,
+ subjAltNameExt);
+
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_IO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, e.getMessage());
+ return PolicyResult.REJECTED; // unrecoverable error.
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR", e.toString()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Certificate Info Error");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ return res;
+ }
+
+ /**
+ * Find a particular authentication token by manager name.
+ * If the token is not present return null
+ */
+ protected IAuthToken
+ findAuthToken(IRequest req, String authMgrName) {
+
+ return req.getExtDataInAuthToken(IRequest.AUTH_TOKEN);
+ }
+
+ /**
+ * Generate a String Vector containing all the email addresses
+ * found in this Authentication token
+ * @throws IOException
+ */
+ protected Vector<String> getEmailList(IAuthToken tok) throws IOException {
+
+ Vector<String> v = new Vector<String>();
+
+ addValues(tok, "mail", v);
+ addValues(tok, "mailalternateaddress", v);
+
+ if (v.size() == 0)
+ return null;
+
+ return v;
+ }
+
+ /**
+ * Add attribute values from an LDAP attribute to a vector
+ * @throws IOException
+ */
+ protected void
+ addValues(IAuthToken tok, String attrName, Vector<String> v) throws IOException {
+ String attr[] = tok.getInStringArray(attrName);
+
+ if (attr == null)
+ return;
+
+ for (int i = 0; i < attr.length; i++) {
+ v.addElement(attr[i]);
+ }
+ }
+
+ /**
+ * Make a Subject name extension given a list of email addresses
+ */
+ protected SubjectAlternativeNameExtension
+ mkExt(Vector<String> emails)
+ throws IOException {
+ SubjectAlternativeNameExtension sa;
+ GeneralNames gns = new GeneralNames();
+
+ for (int i = 0; i < emails.size(); i++) {
+ String email = emails.elementAt(i);
+
+ gns.addElement(new RFC822Name(email));
+ }
+
+ sa = new SubjectAlternativeNameExtension(gns);
+
+ return sa;
+ }
+
+ /**
+ * Create a new SET of extensions in the certificate info
+ * object.
+ *
+ * This should be a method in the X509CertInfo object
+ */
+ protected CertificateExtensions
+ createCertificateExtensions(X509CertInfo certInfo)
+ throws IOException, CertificateException {
+ CertificateExtensions extensions;
+
+ // Force version to V3
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+
+ return extensions;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> params = new Vector<String>();
+
+ //params.addElement("PROP_AGENT_OVERR = " + mAllowAgentOverride);
+ //params.addElement("PROP_EE_OVERR = " + mAllowEEOverride);
+ params.addElement(PROP_CRITICAL + "=" + mCritical);
+ // params.addElement(PROP_ENABLE_MANUAL_VALUES + " = " +
+ // mEnableManualValues);
+ return params;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> defParams = new Vector<String>();
+
+ //defParams.addElement("PROP_AGENT_OVERR = " + DEF_AGENT_OVERR);
+ //defParams.addElement("PROP_EE_OVERR = " + DEF_EE_OVERR);
+ defParams.addElement(PROP_CRITICAL + "=false");
+ // defParams.addElement(PROP_ENABLE_MANUAL_VALUES + "= false");
+
+ return defParams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/SubjectAltNameExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/SubjectAltNameExt.java
new file mode 100644
index 000000000..0d89d8876
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/SubjectAltNameExt.java
@@ -0,0 +1,331 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.SubjectAlternativeNameExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IGeneralNameUtil;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.policy.ISubjAltNameConfig;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Subject Alternative Name extension policy.
+ *
+ * Adds the subject alternative name extension as configured.
+ *
+ * Two forms are supported. 1) For S/MIME certificates, email
+ * addresses are copied from data stored in the request by the
+ * authentication component. Both 'e' and 'altEmail' are supported
+ * so that both the primary address and alternative forms may be
+ * certified. Only the primary goes in the subjectName position (which
+ * should be phased out).
+ *
+ * e
+ * mailAlternateAddress
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class SubjectAltNameExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ // (standard says SHOULD be marked critical if included.)
+ protected static final String PROP_CRITICAL = "critical";
+ protected static final boolean DEF_CRITICAL = false;
+
+ protected IConfigStore mConfig = null;
+ protected boolean mEnabled = false;
+ protected boolean mCritical = DEF_CRITICAL;
+ protected int mNumGNs = 0;
+ protected ISubjAltNameConfig[] mGNs = null;
+
+ Vector<String> mInstanceParams = new Vector<String>();
+
+ // init default params and extended plugin info.
+ private static Vector<String> mDefParams = new Vector<String>();
+ static {
+ // default params.
+ mDefParams.addElement(PROP_CRITICAL + "=" + DEF_CRITICAL);
+ mDefParams.addElement(
+ IGeneralNameUtil.PROP_NUM_GENERALNAMES + "=" +
+ IGeneralNameUtil.DEF_NUM_GENERALNAMES);
+ for (int i = 0; i < IGeneralNameUtil.DEF_NUM_GENERALNAMES; i++) {
+ CMS.getSubjAltNameConfigDefaultParams(
+ IGeneralNameUtil.PROP_GENERALNAME + i, mDefParams);
+ }
+ }
+
+ private String[] mExtendedPluginInfo = null;
+
+ public SubjectAltNameExt() {
+ NAME = "SubjectAltNameExt";
+ DESC = "Sets alternative subject names for certificates";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ra.Policy.rule.<ruleName>.implName=SubjectAltNameExt ra.Policy.rule.<ruleName>.enable=true
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+
+ // get criticality
+ mCritical = mConfig.getBoolean(PROP_CRITICAL, DEF_CRITICAL);
+
+ // get enabled
+ mEnabled = mConfig.getBoolean(
+ IPolicyProcessor.PROP_ENABLE, false);
+
+ // get general names configuration.
+ mNumGNs = mConfig.getInteger(IGeneralNameUtil.PROP_NUM_GENERALNAMES);
+ if (mNumGNs <= 0) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_MUST_BE_POSITIVE_NUMBER",
+ IGeneralNameUtil.PROP_NUM_GENERALNAMES));
+ }
+ mGNs = new ISubjAltNameConfig[mNumGNs];
+ for (int i = 0; i < mNumGNs; i++) {
+ String name = IGeneralNameUtil.PROP_GENERALNAME + i;
+ IConfigStore substore = mConfig.getSubStore(name);
+
+ mGNs[i] = CMS.createSubjAltNameConfig(name, substore, mEnabled);
+ }
+
+ // init instance params.
+ mInstanceParams.addElement(PROP_CRITICAL + "=" + mCritical);
+ mInstanceParams.addElement(
+ IGeneralNameUtil.PROP_NUM_GENERALNAMES + "=" + mNumGNs);
+ for (int j = 0; j < mGNs.length; j++) {
+ mGNs[j].getInstanceParams(mInstanceParams);
+ }
+ }
+
+ /**
+ * Adds the subject alternative names extension if not set already.
+ *
+ * <P>
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ PolicyResult res = PolicyResult.ACCEPTED;
+
+ // Find the X509CertInfo object in the request
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certRes = applyCert(req, ci[i]);
+
+ if (certRes == PolicyResult.REJECTED)
+ return certRes;
+ }
+ return res;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+ PolicyResult res = PolicyResult.ACCEPTED;
+
+ try {
+ // Find the extensions in the certInfo
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+
+ // Remove any previously computed version of the extension
+ // unless it is from RA. If from RA, accept what RA put in
+ // request and don't add our own.
+ if (extensions != null) {
+ String sourceId = req.getSourceId();
+
+ if (sourceId != null && sourceId.length() > 0)
+ return res; // accepted
+ try {
+ extensions.delete(SubjectAlternativeNameExtension.NAME);
+ } catch (IOException e) {
+ // extension isn't there
+ }
+ }
+
+ // form list of general names for the extension.
+ GeneralNames gns = new GeneralNames();
+
+ for (int i = 0; i < mNumGNs; i++) {
+ Object value = null;
+
+ value = req.getExtDataInString(mGNs[i].getPfx(), mGNs[i].getAttr());
+ if (value == null) {
+ continue;
+ }
+ Vector<GeneralName> gn = mGNs[i].formGeneralNames(value);
+
+ if (gn.size() == 0)
+ continue;
+ for (Enumeration<GeneralName> n = gn.elements(); n.hasMoreElements();) {
+ gns.addElement(n.nextElement());
+ }
+ }
+
+ // nothing was found in request to put into extension
+ if (gns.size() == 0)
+ return res; // accepted
+
+ String subject = certInfo.get(X509CertInfo.SUBJECT).toString();
+
+ boolean curCritical = mCritical;
+
+ if (subject.equals("")) {
+ curCritical = true;
+ }
+
+ // make the extension
+ SubjectAlternativeNameExtension sa = new SubjectAlternativeNameExtension(curCritical, gns);
+
+ // add it to certInfo.
+ if (extensions == null)
+ extensions = createCertificateExtensions(certInfo);
+
+ extensions.set(SubjectAlternativeNameExtension.NAME, sa);
+
+ return res; // accepted.
+
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_IO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, e.getMessage());
+ return PolicyResult.REJECTED; // unrecoverable error.
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Certificate Info Error");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("BASE_INTERNAL_ERROR_1", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Internal Error");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+ }
+
+ /**
+ * Create a new SET of extensions in the certificate info
+ * object.
+ *
+ * This should be a method in the X509CertInfo object
+ */
+ protected CertificateExtensions
+ createCertificateExtensions(X509CertInfo certInfo)
+ throws IOException, CertificateException {
+ CertificateExtensions extensions;
+
+ // Force version to V3
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+
+ return extensions;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ return mInstanceParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return mDefParams;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+
+ // extended plugin info.
+ Vector<String> info = new Vector<String>();
+
+ info.addElement(PROP_CRITICAL
+ + ";boolean;RFC2459 recommendation: If the certificate subject field contains an empty sequence, the extension MUST be marked critical.");
+ info.addElement(IGeneralNameUtil.PROP_NUM_GENERALNAMES_INFO);
+ for (int i = 0; i < IGeneralNameUtil.DEF_NUM_GENERALNAMES; i++) {
+ CMS.getSubjAltNameConfigExtendedPluginInfo(
+ IGeneralNameUtil.PROP_GENERALNAME + i, info);
+ }
+ info.addElement(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-subjaltname");
+ info.addElement(IExtendedPluginInfo.HELP_TEXT +
+ ";This policy inserts the Subject Alternative Name " +
+ "Extension into the certificate. See RFC 2459 (4.2.1.7). " +
+ "* Note: you probably want to use this policy in " +
+ "conjunction with an authentication manager which sets " +
+ "the 'mail' or 'mailalternateaddress' values in the authToken. " +
+ "See the 'ldapStringAttrs' parameter in the Directory-based " +
+ "authentication plugin");
+ mExtendedPluginInfo = new String[info.size()];
+ info.copyInto(mExtendedPluginInfo);
+ return mExtendedPluginInfo;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/SubjectDirectoryAttributesExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/SubjectDirectoryAttributesExt.java
new file mode 100644
index 000000000..bcd9c9885
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/SubjectDirectoryAttributesExt.java
@@ -0,0 +1,428 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.util.DerValue;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AVAValueConverter;
+import netscape.security.x509.Attribute;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.SubjectDirAttributesExtension;
+import netscape.security.x509.X500NameAttrMap;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Policy to add the subject directory attributes extension.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class SubjectDirectoryAttributesExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ protected static final String PROP_CRITICAL = "critical";
+ protected static final String PROP_ATTRIBUTE = "attribute";
+ protected static final String PROP_NUM_ATTRIBUTES = "numAttributes";
+
+ protected static final boolean DEF_CRITICAL = false;
+ protected static final int DEF_NUM_ATTRIBUTES = 3;
+ protected static final int MAX_NUM_ATTRIBUTES = 10;
+
+ protected boolean mCritical;
+ protected int mNumAttributes;
+ protected AttributeConfig[] mAttributes = null;
+
+ protected IConfigStore mConfig;
+ protected SubjectDirAttributesExtension mExt = null;
+
+ protected Vector<String> mParams = new Vector<String>();
+ private String[] mEPI = null; // extended plugin info
+ protected static Vector<String> mDefParams = new Vector<String>();
+
+ static {
+ setDefaultParams();
+ }
+
+ public SubjectDirectoryAttributesExt() {
+ NAME = "SubjectDirectoryAttributesExtPolicy";
+ DESC = "Sets Subject Directory Attributes Extension in certificates.";
+ setExtendedPluginInfo();
+ }
+
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ boolean enabled = config.getBoolean("enabled", false);
+
+ mConfig = config;
+
+ mCritical = mConfig.getBoolean(PROP_CRITICAL, false);
+ mNumAttributes = mConfig.getInteger(PROP_NUM_ATTRIBUTES, DEF_NUM_ATTRIBUTES);
+ if (mNumAttributes < 1) {
+ EBaseException ex = new EBaseException(
+ CMS.getUserMessage("CMS_BASE_MUST_BE_POSITIVE_NUMBER", PROP_NUM_ATTRIBUTES));
+
+ log(ILogger.LL_FAILURE, NAME + " Error: " + ex.toString());
+ throw ex;
+ }
+ mAttributes = new AttributeConfig[mNumAttributes];
+ for (int i = 0; i < mNumAttributes; i++) {
+ String name = PROP_ATTRIBUTE + i;
+ IConfigStore c = mConfig.getSubStore(name);
+
+ mAttributes[i] = new AttributeConfig(name, c, enabled);
+ }
+ if (enabled) {
+ try {
+ mExt = formExt(null);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, NAME + " Error: " + e.getMessage());
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Error forming Subject Directory Attributes Extension. " +
+ "See log file for details."));
+ }
+ }
+ setInstanceParams();
+ }
+
+ public PolicyResult apply(IRequest req) {
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED; // unrecoverable error.
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult r = applyCert(req, ci[i]);
+
+ if (r == PolicyResult.REJECTED)
+ return r;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+ CertificateExtensions extensions = null;
+
+ try {
+ // get extension and remove if exists.
+ extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+ if (extensions == null) {
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ } else {
+ try {
+ extensions.delete(SubjectDirAttributesExtension.NAME);
+ } catch (IOException ee) {
+ // if name is not found, try deleting the extension using the OID
+ try {
+ extensions.delete("2.5.29.9");
+ } catch (IOException eee) {
+ }
+ }
+ }
+
+ // form extension and set.
+ if (mExt != null) {
+ extensions.set(SubjectDirAttributesExtension.NAME, mExt);
+ } else {
+ SubjectDirAttributesExtension ext = formExt(req);
+
+ if (ext != null)
+ extensions.set(SubjectDirAttributesExtension.NAME, formExt(req));
+ }
+ return PolicyResult.ACCEPTED;
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR", e.getMessage()));
+
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Certificate Info Error");
+ return PolicyResult.REJECTED; // unrecoverable error.
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_IO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "IOException Error");
+ return PolicyResult.REJECTED;
+ }
+ }
+
+ public Vector<String> getInstanceParams() {
+ return mParams; // inited in init()
+ }
+
+ public Vector<String> getDefaultParams() {
+ return mDefParams;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ return mEPI; // inited in the constructor.
+ }
+
+ private void setInstanceParams() {
+ mParams.addElement(PROP_CRITICAL + "=" + mCritical);
+ mParams.addElement(PROP_NUM_ATTRIBUTES + "=" + mNumAttributes);
+ for (int i = 0; i < mNumAttributes; i++) {
+ mAttributes[i].getInstanceParams(mParams);
+ }
+ // clean up others if exists. expensive.
+ for (int j = mNumAttributes; j < MAX_NUM_ATTRIBUTES; j++) {
+ mConfig.removeSubStore(PROP_ATTRIBUTE + j);
+ }
+ }
+
+ private static void setDefaultParams() {
+ mDefParams.addElement(PROP_CRITICAL + "=" + DEF_CRITICAL);
+ mDefParams.addElement(PROP_NUM_ATTRIBUTES + "=" + DEF_NUM_ATTRIBUTES);
+ for (int i = 0; i < DEF_NUM_ATTRIBUTES; i++) {
+ AttributeConfig.getDefaultParams(PROP_ATTRIBUTE + i, mDefParams);
+ }
+ }
+
+ private void setExtendedPluginInfo() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(PROP_CRITICAL + ";boolean;" +
+ "RFC 2459 recommendation: MUST be non-critical.");
+ v.addElement(PROP_NUM_ATTRIBUTES + ";number;" +
+ "Number of Attributes in the extension.");
+
+ for (int i = 0; i < MAX_NUM_ATTRIBUTES; i++) {
+ AttributeConfig.getExtendedPluginInfo(PROP_ATTRIBUTE + i, v);
+ }
+
+ v.addElement(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-subjectdirectoryattributes");
+ v.addElement(IExtendedPluginInfo.HELP_TEXT
+ +
+ ";Adds Subject Directory Attributes extension. See RFC 2459 (4.2.1.9). It's not recommended as an essential part of the profile, but may be used in local environments.");
+
+ mEPI = com.netscape.cmsutil.util.Utils.getStringArrayFromVector(v);
+ }
+
+ private SubjectDirAttributesExtension formExt(IRequest req)
+ throws IOException {
+ Vector<Attribute> attrs = new Vector<Attribute>();
+
+ // if we're called from init and one attribute is from request attribute
+ // the ext can't be formed yet.
+ if (req == null) {
+ for (int i = 0; i < mNumAttributes; i++) {
+ if (mAttributes[i].mWhereToGetValue == AttributeConfig.USE_REQUEST_ATTR)
+ return null;
+ }
+ }
+ // either we're called from apply or all values are fixed.
+ for (int i = 0; i < mNumAttributes; i++) {
+ if (mAttributes[i].mAttribute != null) {
+ attrs.addElement(mAttributes[i].mAttribute);
+ } else {
+ // skip attribute if request attribute doesn't exist.
+ Attribute a = mAttributes[i].formAttr(req);
+
+ if (a == null)
+ continue;
+ attrs.addElement(a);
+ }
+ }
+ if (attrs.size() == 0)
+ return null;
+ Attribute[] attrList = new Attribute[attrs.size()];
+
+ attrs.copyInto(attrList);
+ SubjectDirAttributesExtension ext =
+ new SubjectDirAttributesExtension(attrList);
+
+ return ext;
+ }
+}
+
+class AttributeConfig {
+
+ protected static final String PROP_ATTRIBUTE_NAME = "attributeName";
+ protected static final String PROP_WTG_VALUE = "whereToGetValue";
+ protected static final String PROP_VALUE = "value";
+
+ protected static final String USE_REQUEST_ATTR = "Request Attribute";
+ protected static final String USE_FIXED = "Fixed Value";
+
+ protected String mAttributeName = null;
+ protected String mWhereToGetValue = null;
+ protected String mValue = null;
+
+ protected String mPrefix = null;
+ protected String mReqAttr = null;
+ protected ObjectIdentifier mAttributeOID = null;
+
+ protected String mName = null;
+ protected IConfigStore mConfig = null;
+ protected Attribute mAttribute = null;
+
+ protected static final String ATTRIBUTE_NAME_INFO = "Attribute name.";
+ protected static final String WTG_VALUE_INFO =
+ PROP_WTG_VALUE + ";choice(" + USE_REQUEST_ATTR + "," + USE_FIXED + ");" +
+ "Get value from a request attribute or use a fixed value specified below.";
+ protected static final String VALUE_INFO =
+ PROP_VALUE + ";string;" +
+ "Request attribute name or a fixed value to put into the extension.";
+
+ public AttributeConfig(String name, IConfigStore config, boolean enabled)
+ throws EBaseException {
+ X500NameAttrMap map = X500NameAttrMap.getDefault();
+
+ mName = name;
+ mConfig = config;
+ if (enabled) {
+ mAttributeName = mConfig.getString(PROP_ATTRIBUTE_NAME);
+ mWhereToGetValue = mConfig.getString(PROP_WTG_VALUE);
+ mValue = mConfig.getString(PROP_VALUE);
+ } else {
+ mAttributeName = mConfig.getString(PROP_ATTRIBUTE_NAME, "");
+ mWhereToGetValue = mConfig.getString(PROP_WTG_VALUE, USE_REQUEST_ATTR);
+ mValue = mConfig.getString(PROP_VALUE, "");
+ }
+
+ if (mAttributeName.length() > 0) {
+ mAttributeOID = map.getOid(mAttributeName);
+ if (mAttributeOID == null)
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", mAttributeName));
+ }
+
+ if (mWhereToGetValue.equalsIgnoreCase(USE_REQUEST_ATTR)) {
+ mWhereToGetValue = USE_REQUEST_ATTR;
+ if (enabled && mValue.length() == 0) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", PROP_VALUE));
+ }
+ int dot = mValue.indexOf('.');
+
+ if (dot != -1) {
+ mPrefix = mValue.substring(0, dot);
+ mReqAttr = mValue.substring(dot + 1);
+ if (mPrefix == null || mPrefix.length() == 0 ||
+ mReqAttr == null || mReqAttr.length() == 0) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", mValue));
+ }
+ } else {
+ mPrefix = null;
+ mReqAttr = mValue;
+ }
+ } else if (mWhereToGetValue.equalsIgnoreCase(USE_FIXED)) {
+ mWhereToGetValue = USE_FIXED;
+ if (mAttributeOID != null) {
+ try {
+ checkValue(mAttributeOID, mValue);
+ mAttribute = new Attribute(mAttributeOID, mValue);
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ mAttributeName, e.getMessage()));
+ }
+ }
+ } else if (enabled || mWhereToGetValue.length() > 0) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_VALUE_FOR_TYPE", PROP_WTG_VALUE,
+ "Must be either '" + USE_REQUEST_ATTR + "' or '" + USE_FIXED + "'."));
+ }
+ }
+
+ public static void getDefaultParams(String name, Vector<String> v) {
+ String nameDot = name + ".";
+
+ v.addElement(nameDot + PROP_ATTRIBUTE_NAME + "=");
+ v.addElement(nameDot + PROP_WTG_VALUE + "=" + USE_REQUEST_ATTR);
+ v.addElement(nameDot + PROP_VALUE + "=");
+ }
+
+ public static void getExtendedPluginInfo(String name, Vector<String> v) {
+ String nameDot = name + ".";
+ String attrChoices = getAllNames();
+
+ v.addElement(nameDot + PROP_ATTRIBUTE_NAME + ";choice(" + attrChoices + ");" +
+ ATTRIBUTE_NAME_INFO);
+ v.addElement(nameDot + WTG_VALUE_INFO);
+ v.addElement(nameDot + VALUE_INFO);
+ }
+
+ public void getInstanceParams(Vector<String> v) {
+ String nameDot = mName + ".";
+
+ v.addElement(nameDot + PROP_ATTRIBUTE_NAME + "=" + mAttributeName);
+ v.addElement(nameDot + PROP_WTG_VALUE + "=" + mWhereToGetValue);
+ v.addElement(nameDot + PROP_VALUE + "=" + mValue);
+ }
+
+ public Attribute formAttr(IRequest req)
+ throws IOException {
+ String val = req.getExtDataInString(mPrefix, mReqAttr);
+
+ if (val == null || val.length() == 0) {
+ return null;
+ }
+ checkValue(mAttributeOID, val);
+ return new Attribute(mAttributeOID, val);
+ }
+
+ static private String getAllNames() {
+ Enumeration<String> n = X500NameAttrMap.getDefault().getAllNames();
+ StringBuffer sb = new StringBuffer();
+ sb.append(n.nextElement());
+
+ while (n.hasMoreElements()) {
+ sb.append(",");
+ sb.append(n.nextElement());
+ }
+ return sb.toString();
+ }
+
+ private static void checkValue(ObjectIdentifier oid, String val)
+ throws IOException {
+ AVAValueConverter c = X500NameAttrMap.getDefault().getValueConverter(oid);
+
+ @SuppressWarnings("unused")
+ DerValue derval = c.getValue(val); // check for errors
+ return;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/policy/extensions/SubjectKeyIdentifierExt.java b/base/server/cms/src/com/netscape/cms/policy/extensions/SubjectKeyIdentifierExt.java
new file mode 100644
index 000000000..16fc73347
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/policy/extensions/SubjectKeyIdentifierExt.java
@@ -0,0 +1,377 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.policy.extensions;
+
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.KeyIdentifier;
+import netscape.security.x509.SubjectKeyIdentifierExtension;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cms.policy.APolicyRule;
+
+/**
+ * Subject Public Key Extension Policy
+ * Adds the subject public key id extension to certificates.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: The Policy Framework has been replaced by the Profile Framework.
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class SubjectKeyIdentifierExt extends APolicyRule
+ implements IEnrollmentPolicy, IExtendedPluginInfo {
+ protected static final String PROP_CRITICAL = "critical";
+ protected static final String PROP_KEYID_TYPE = "keyIdentifierType";
+ protected static final String PROP_REQATTR_NAME = "requestAttrName";
+
+ protected static final String KEYID_TYPE_SHA1 = "SHA1";
+ protected static final String KEYID_TYPE_TYPEFIELD = "TypeField";
+ protected static final String KEYID_TYPE_SPKISHA1 = "SpkiSHA1";
+ protected static final String KEYID_TYPE_REQATTR = "RequestAttribute";
+
+ protected static final boolean DEF_CRITICAL = false;
+ protected static final String DEF_KEYID_TYPE = KEYID_TYPE_SHA1;
+ protected static final String DEF_REQATTR_NAME = "KeyIdentifier";
+
+ protected boolean mEnabled = false;
+ protected IConfigStore mConfig = null;
+
+ protected boolean mCritical = DEF_CRITICAL;
+ protected String mKeyIdType = DEF_KEYID_TYPE;;
+ protected String mReqAttrName = DEF_REQATTR_NAME;
+
+ protected Vector<String> mInstanceParams = new Vector<String>();
+
+ protected static Vector<String> mDefaultParams = new Vector<String>();
+ static {
+ // form static default params.
+ mDefaultParams.addElement(PROP_CRITICAL + "=" + DEF_CRITICAL);
+ mDefaultParams.addElement(PROP_KEYID_TYPE + "=" + DEF_KEYID_TYPE);
+
+ /*
+ mDefaultParams.addElement(PROP_REQATTR_NAME+"="+DEF_REQATTR_NAME);
+ */
+ }
+
+ public SubjectKeyIdentifierExt() {
+ NAME = "SubjectKeyIdentifierExt";
+ DESC = "Adds Subject Key Idenifier Extension to certs";
+ }
+
+ /**
+ * Initializes this policy rule.
+ * <P>
+ *
+ * The entries may be of the form:
+ *
+ * ca.Policy.rule.<ruleName>.predicate= ca.Policy.rule.<ruleName>.implName= ca.Policy.rule.<ruleName>.enable=true
+ *
+ * @param config The config store reference
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+
+ mEnabled = mConfig.getBoolean(
+ IPolicyProcessor.PROP_ENABLE, false);
+ mCritical = mConfig.getBoolean(PROP_CRITICAL, DEF_CRITICAL);
+
+ mKeyIdType = mConfig.getString(PROP_KEYID_TYPE, DEF_KEYID_TYPE);
+
+ /*
+ mReqAttrName = mConfig.getString(PROP_REQATTR_NAME, DEF_REQATTR_NAME);
+ */
+
+ // parse key id type
+ if (mKeyIdType.equalsIgnoreCase(KEYID_TYPE_SHA1))
+ mKeyIdType = KEYID_TYPE_SHA1;
+ else if (mKeyIdType.equalsIgnoreCase(KEYID_TYPE_TYPEFIELD))
+ mKeyIdType = KEYID_TYPE_TYPEFIELD;
+
+ /*
+ else if (mKeyIdType.equalsIgnoreCase(KEYID_TYPE_REQATTR)
+ mKeyIdType = KEYID_TYPE_REQATTR;
+ */
+ else if (mKeyIdType.equalsIgnoreCase(KEYID_TYPE_SPKISHA1))
+ mKeyIdType = KEYID_TYPE_SPKISHA1;
+ else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("KRA_UNKNOWN_KEY_ID_TYPE", mKeyIdType));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ PROP_KEYID_TYPE,
+ "value must be one of " +
+ KEYID_TYPE_SHA1 + ", " +
+ KEYID_TYPE_TYPEFIELD + ", " +
+ KEYID_TYPE_SPKISHA1));
+ }
+
+ // form instance params
+ mInstanceParams.addElement(PROP_CRITICAL + "=" + mCritical);
+ mInstanceParams.addElement(PROP_KEYID_TYPE + "=" + mKeyIdType);
+
+ /*
+ mInstanceParams.addElement(PROP_REQATTR_NAME+"="+mReqAttrName);
+ */
+ }
+
+ /**
+ * Adds Subject Key identifier Extension to a certificate.
+ * If the extension is already there, accept it.
+ *
+ * @param req The request on which to apply policy.
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ // get certInfo from request.
+ X509CertInfo[] ci =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (ci == null || ci[0] == null) {
+ setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME);
+ return PolicyResult.REJECTED;
+ }
+
+ for (int i = 0; i < ci.length; i++) {
+ PolicyResult certRes = applyCert(req, ci[i]);
+
+ if (certRes == PolicyResult.REJECTED)
+ return certRes;
+ }
+ return PolicyResult.ACCEPTED;
+ }
+
+ public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) {
+
+ try {
+ // if subject key id extension already exists, leave it if approved.
+ SubjectKeyIdentifierExtension subjectKeyIdExt = null;
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+
+ try {
+ if (extensions != null) {
+ subjectKeyIdExt = (SubjectKeyIdentifierExtension)
+ extensions.get(SubjectKeyIdentifierExtension.NAME);
+ }
+ } catch (IOException e) {
+ // extension isn't there.
+ }
+ if (subjectKeyIdExt != null) {
+ if (agentApproved(req)) {
+ CMS.debug(
+ "SubjectKeyIdentifierExt: agent approved request id " + req.getRequestId() +
+ " already has subject key id extension with value " +
+ subjectKeyIdExt);
+ return PolicyResult.ACCEPTED;
+ } else {
+ CMS.debug(
+ "SubjectKeyIdentifierExt: request id from user " + req.getRequestId() +
+ " had subject key identifier - deleted to be replaced");
+ extensions.delete(SubjectKeyIdentifierExtension.NAME);
+ }
+ }
+
+ // create subject key id extension.
+ KeyIdentifier keyId = null;
+
+ try {
+ keyId = formKeyIdentifier(certInfo, req);
+ } catch (EBaseException e) {
+ setPolicyException(req, e);
+ return PolicyResult.REJECTED;
+ }
+ subjectKeyIdExt =
+ new SubjectKeyIdentifierExtension(
+ mCritical, keyId.getIdentifier());
+
+ // add subject key id extension.
+ if (extensions == null) {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ extensions = new CertificateExtensions();
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ }
+ extensions.set(
+ SubjectKeyIdentifierExtension.NAME, subjectKeyIdExt);
+ CMS.debug(
+ "SubjectKeyIdentifierExt: added subject key id ext to request " + req.getRequestId());
+ return PolicyResult.ACCEPTED;
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_UNEXPECTED_POLICY_ERROR,NAME", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, e.getMessage());
+ return PolicyResult.REJECTED;
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR", e.getMessage()));
+ setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"),
+ NAME, "Certificate Info Error");
+ return PolicyResult.REJECTED;
+ }
+ }
+
+ /**
+ * Form the Key Identifier in the Subject Key Identifier extension.
+ * <p>
+ *
+ * @param certInfo Certificate Info
+ * @param req request
+ * @return A Key Identifier.
+ */
+ protected KeyIdentifier formKeyIdentifier(
+ X509CertInfo certInfo, IRequest req) throws EBaseException {
+ KeyIdentifier keyId = null;
+
+ if (mKeyIdType == KEYID_TYPE_SHA1) {
+ keyId = formSHA1KeyId(certInfo);
+ } else if (mKeyIdType == KEYID_TYPE_TYPEFIELD) {
+ keyId = formTypeFieldKeyId(certInfo);
+ } /*
+ else if (mKeyIdType == KEYID_TYPE_REQATTR) {
+ keyId = formReqAttrKeyId(certInfo, req);
+ }
+ */else if (mKeyIdType == KEYID_TYPE_SPKISHA1) {
+ keyId = formSpkiSHA1KeyId(certInfo);
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ mKeyIdType, "Unknown Key Identifier type."));
+ }
+ return keyId;
+ }
+
+ /**
+ * Form key identifier from a type field value of 0100 followed by
+ * the least significate 60 bits of the sha-1 hash of the subject
+ * public key BIT STRING in accordance with RFC 2459.
+ * <p>
+ *
+ * @param certInfo - certificate info
+ * @return A Key Identifier with value formulatd as described.
+ */
+
+ protected KeyIdentifier formTypeFieldKeyId(X509CertInfo certInfo)
+ throws EBaseException {
+ KeyIdentifier keyId = null;
+ X509Key key = null;
+
+ try {
+ CertificateX509Key certKey =
+ (CertificateX509Key) certInfo.get(X509CertInfo.KEY);
+
+ if (certKey == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_MISSING_KEY_1", NAME));
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_MISSING_KEY", NAME));
+ }
+ key = (X509Key) certKey.get(CertificateX509Key.KEY);
+ if (key == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_MISSING_KEY_1", NAME));
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_MISSING_KEY", NAME));
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_GET_KEY_FROM_CERT", e.toString()));
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_SUBJECT_KEY_ID_ERROR", NAME));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_GET_KEY_FROM_CERT", e.toString()));
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_SUBJECT_KEY_ID_ERROR", NAME));
+ }
+ try {
+ byte[] octetString = new byte[8];
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+
+ md.update(key.getKey());
+ byte[] hash = md.digest();
+
+ System.arraycopy(hash, hash.length - 8, octetString, 0, 8);
+ octetString[0] &= (0x08f & octetString[0]);
+ keyId = new KeyIdentifier(octetString);
+ } catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("POLICY_ERROR_SUBJECT_KEY_ID_1", NAME));
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_SUBJECT_KEY_ID_ERROR", NAME));
+ }
+ return keyId;
+ }
+
+ /**
+ * Return configured parameters for a policy rule instance.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getInstanceParams() {
+ return mInstanceParams;
+ }
+
+ /**
+ * Return default parameters for a policy implementation.
+ *
+ * @return nvPairs A Vector of name/value pairs.
+ */
+ public Vector<String> getDefaultParams() {
+ return mDefaultParams;
+ }
+
+ /**
+ * Gets extended plugin info for pretty Console displays.
+ */
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_CRITICAL + ";boolean;RFC 2459 recommendation: MUST NOT be marked critical.",
+ PROP_KEYID_TYPE + ";" +
+ "choice(" + KEYID_TYPE_SHA1 + "," +
+ KEYID_TYPE_TYPEFIELD + "," +
+ KEYID_TYPE_SPKISHA1 + ");" +
+ "Method to derive the Key Identifier.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-policyrules-subjectkeyidentifier",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Adds the Subject Key Identifier extension. See RFC 2459 (4.2.1.2)"
+ };
+
+ return params;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/BasicProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/BasicProfile.java
new file mode 100644
index 000000000..ea5108445
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/common/BasicProfile.java
@@ -0,0 +1,1213 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.common;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyConstraint;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.IProfileOutput;
+import com.netscape.certsrv.profile.IProfilePolicy;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.profile.IProfileUpdater;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.registry.IPluginInfo;
+import com.netscape.certsrv.registry.IPluginRegistry;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestStatus;
+
+/**
+ * This class implements a basic profile.
+ *
+ * @version $Revision$, $Date$
+ */
+public abstract class BasicProfile implements IProfile {
+
+ public static final String PROP_ENABLE = "enable";
+ public static final String PROP_ENABLE_BY = "enableBy";
+ public static final String PROP_IS_RENEWAL = "renewal";
+ public static final String PROP_XML_OUTPUT = "xmlOutput";
+ public static final String PROP_VISIBLE = "visible";
+ public static final String PROP_INPUT_LIST = "list";
+ public static final String PROP_OUTPUT_LIST = "list";
+ public static final String PROP_UPDATER_LIST = "list";
+ public static final String PROP_POLICY_LIST = "list";
+ public static final String PROP_DEFAULT = "default";
+ public static final String PROP_CONSTRAINT = "constraint";
+ public static final String PROP_INPUT = "input";
+ public static final String PROP_OUTPUT = "output";
+ public static final String PROP_CLASS_ID = "class_id";
+ public static final String PROP_INSTANCE_ID = "instance_id";
+ public static final String PROP_PARAMS = "params";
+ public static final String PROP_NAME = "name";
+ public static final String PROP_DESC = "desc";
+ public static final String PROP_NO_DEFAULT = "noDefaultImpl";
+ public static final String PROP_NO_CONSTRAINT = "noConstraintImpl";
+ public static final String PROP_GENERIC_EXT_DEFAULT = "genericExtDefaultImpl";
+
+ protected IProfileSubsystem mOwner = null;
+ protected IConfigStore mConfig = null;
+ protected IPluginRegistry mRegistry = null;
+
+ protected Vector<String> mInputNames = new Vector<String>();
+ protected Hashtable<String, IProfileInput> mInputs = new Hashtable<String, IProfileInput>();
+ protected Vector<String> mInputIds = new Vector<String>();
+ protected Hashtable<String, IProfileOutput> mOutputs = new Hashtable<String, IProfileOutput>();
+ protected Vector<String> mOutputIds = new Vector<String>();
+ protected Hashtable<String, IProfileUpdater> mUpdaters = new Hashtable<String, IProfileUpdater>();
+ protected Vector<String> mUpdaterIds = new Vector<String>();
+ protected IProfileAuthenticator mAuthenticator = null;
+ protected String mAuthInstanceId = null;
+ protected String mId = null;
+ protected String mAuthzAcl = "";
+
+ protected Hashtable<String, Vector<IProfilePolicy>> mPolicySet = new Hashtable<String, Vector<IProfilePolicy>>();
+
+ protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+
+ public BasicProfile() {
+ }
+
+ public boolean isEnable() {
+ try {
+ return mConfig.getBoolean(PROP_ENABLE, false);
+ } catch (EBaseException e) {
+ return false;
+ }
+ }
+
+ public String isRenewal() {
+ try {
+ return mConfig.getString(PROP_IS_RENEWAL, "false");
+ } catch (EBaseException e) {
+ return "false";
+ }
+ }
+
+ public void setRenewal(boolean renewal) {
+ mConfig.putBoolean(PROP_IS_RENEWAL, renewal);
+ }
+
+ public String isXmlOutput() {
+ try {
+ return mConfig.getString(PROP_XML_OUTPUT, "false");
+ } catch (EBaseException e) {
+ return "false";
+ }
+ }
+
+ public void setXMLOutput(boolean xmlOutput) {
+ mConfig.putBoolean(PROP_XML_OUTPUT, xmlOutput);
+ }
+
+ public String getApprovedBy() {
+ try {
+ return mConfig.getString(PROP_ENABLE_BY, "");
+ } catch (EBaseException e) {
+ return "";
+ }
+ }
+
+ public void setId(String id) {
+ mId = id;
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ public IProfileAuthenticator getAuthenticator() throws EProfileException {
+ try {
+ IAuthSubsystem authSub = (IAuthSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ IProfileAuthenticator auth = (IProfileAuthenticator)
+ authSub.get(mAuthInstanceId);
+
+ if (mAuthInstanceId != null && mAuthInstanceId.length() > 0
+ && auth == null) {
+ throw new EProfileException("Cannot load " +
+ mAuthInstanceId);
+ }
+ return auth;
+ } catch (Exception e) {
+ if (mAuthInstanceId != null) {
+ throw new EProfileException("Cannot load " +
+ mAuthInstanceId);
+ }
+ return null;
+ }
+ }
+
+ public String getRequestorDN(IRequest request) {
+ return null;
+ }
+
+ public String getAuthenticatorId() {
+ return mAuthInstanceId;
+ }
+
+ public void setAuthenticatorId(String id) {
+ mAuthInstanceId = id;
+ mConfig.putString("auth." + PROP_INSTANCE_ID, id);
+ }
+
+ public void setAuthzAcl(String id) {
+ mAuthzAcl = id;
+ mConfig.putString("authz.acl", id);
+ }
+
+ public String getAuthzAcl() {
+ return mAuthzAcl;
+ }
+
+ /**
+ * Initializes this profile.
+ */
+ public void init(IProfileSubsystem owner, IConfigStore config)
+ throws EBaseException {
+ CMS.debug("BasicProfile: start init");
+ mOwner = owner;
+ mConfig = config;
+
+ mRegistry = (IPluginRegistry) CMS.getSubsystem(CMS.SUBSYSTEM_REGISTRY);
+
+ // Configure File Formats:
+ // visible
+ // auth.class_id=NoAuthImpl
+ // auth.params.x1=x1
+ // input.list=i1,i2,...
+ // input.i1.class=com.netscape.cms.profile.input.CertReqInput
+ // input.i1.params.x1=x1
+ // policy.list=p1,p2,...
+ // policy.p1.enable=true
+ // policy.p1.default.class=com.netscape.cms.profile.defaults.SubjectName
+ // policy.p1.default.params.x1=x1
+ // policy.p1.default.params.x2=x2
+ // policy.p1.constraint.class= ... .cms.profile.constraints.ValidityRange
+ // policy.p1.constraint.params.x1=x1
+ // policy.p1.constraint.params.x2=x2
+
+ // handle profile authentication plugins
+ try {
+ mAuthInstanceId = config.getString("auth." + PROP_INSTANCE_ID, null);
+ mAuthzAcl = config.getString("authz.acl", "");
+ } catch (EBaseException e) {
+ CMS.debug("BasicProfile: authentication class not found " +
+ e.toString());
+ }
+
+ // handle profile input plugins
+ IConfigStore inputStore = config.getSubStore("input");
+ String input_list = inputStore.getString(PROP_INPUT_LIST, "");
+ StringTokenizer input_st = new StringTokenizer(input_list, ",");
+
+ while (input_st.hasMoreTokens()) {
+ String input_id = input_st.nextToken();
+ String inputClassId = inputStore.getString(input_id + "." +
+ PROP_CLASS_ID);
+ IPluginInfo inputInfo = mRegistry.getPluginInfo("profileInput",
+ inputClassId);
+ String inputClass = inputInfo.getClassName();
+
+ IProfileInput input = null;
+
+ try {
+ input = (IProfileInput)
+ Class.forName(inputClass).newInstance();
+ } catch (Exception e) {
+ // throw Exception
+ CMS.debug("BasicProfile: input plugin Class.forName " +
+ inputClass + " " + e.toString());
+ throw new EBaseException(e.toString());
+ }
+ IConfigStore inputConfig = inputStore.getSubStore(input_id);
+ input.init(this, inputConfig);
+ mInputs.put(input_id, input);
+ mInputIds.addElement(input_id);
+ }
+
+ // handle profile output plugins
+ IConfigStore outputStore = config.getSubStore("output");
+ String output_list = outputStore.getString(PROP_OUTPUT_LIST, "");
+ StringTokenizer output_st = new StringTokenizer(output_list, ",");
+
+ while (output_st.hasMoreTokens()) {
+ String output_id = output_st.nextToken();
+
+ String outputClassId = outputStore.getString(output_id + "." +
+ PROP_CLASS_ID);
+ IPluginInfo outputInfo = mRegistry.getPluginInfo("profileOutput",
+ outputClassId);
+ String outputClass = outputInfo.getClassName();
+
+ IProfileOutput output = null;
+
+ try {
+ output = (IProfileOutput)
+ Class.forName(outputClass).newInstance();
+ } catch (Exception e) {
+ // throw Exception
+ CMS.debug("BasicProfile: output plugin Class.forName " +
+ outputClass + " " + e.toString());
+ throw new EBaseException(e.toString());
+ }
+ IConfigStore outputConfig = outputStore.getSubStore(output_id);
+ output.init(this, outputConfig);
+ mOutputs.put(output_id, output);
+ mOutputIds.addElement(output_id);
+ }
+
+ // handle profile output plugins
+ IConfigStore updaterStore = config.getSubStore("updater");
+ String updater_list = updaterStore.getString(PROP_UPDATER_LIST, "");
+ StringTokenizer updater_st = new StringTokenizer(updater_list, ",");
+
+ while (updater_st.hasMoreTokens()) {
+ String updater_id = updater_st.nextToken();
+
+ String updaterClassId = updaterStore.getString(updater_id + "." +
+ PROP_CLASS_ID);
+ IPluginInfo updaterInfo = mRegistry.getPluginInfo("profileUpdater",
+ updaterClassId);
+ String updaterClass = updaterInfo.getClassName();
+
+ IProfileUpdater updater = null;
+
+ try {
+ updater = (IProfileUpdater)
+ Class.forName(updaterClass).newInstance();
+ } catch (Exception e) {
+ // throw Exception
+ CMS.debug("BasicProfile: updater plugin Class.forName " +
+ updaterClass + " " + e.toString());
+ throw new EBaseException(e.toString());
+ }
+ IConfigStore updaterConfig = updaterStore.getSubStore(updater_id);
+ updater.init(this, updaterConfig);
+ mUpdaters.put(updater_id, updater);
+ mUpdaterIds.addElement(updater_id);
+ }
+
+ // handle profile policy plugins
+ IConfigStore policySetStore = config.getSubStore("policyset");
+ String setlist = policySetStore.getString("list", "");
+ StringTokenizer st = new StringTokenizer(setlist, ",");
+
+ while (st.hasMoreTokens()) {
+ String setId = st.nextToken();
+
+ IConfigStore policyStore = policySetStore.getSubStore(setId);
+ String list = policyStore.getString(PROP_POLICY_LIST, "");
+ StringTokenizer st1 = new StringTokenizer(list, ",");
+
+ while (st1.hasMoreTokens()) {
+ String id = st1.nextToken();
+
+ String defaultRoot = id + "." + PROP_DEFAULT;
+ String defaultClassId = policyStore.getString(defaultRoot + "." +
+ PROP_CLASS_ID);
+
+ String constraintRoot = id + "." + PROP_CONSTRAINT;
+ String constraintClassId =
+ policyStore.getString(constraintRoot + "." + PROP_CLASS_ID);
+
+ createProfilePolicy(setId, id, defaultClassId,
+ constraintClassId, false);
+ }
+ }
+ CMS.debug("BasicProfile: done init");
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public Enumeration<String> getInputNames() {
+ return mInputNames.elements();
+ }
+
+ public Enumeration<String> getProfileUpdaterIds() {
+ return mUpdaterIds.elements(); // ordered list
+ }
+
+ public IProfileUpdater getProfileUpdater(String name) {
+ return mUpdaters.get(name);
+ }
+
+ public Enumeration<String> getProfileOutputIds() {
+ return mOutputIds.elements(); // ordered list
+ }
+
+ public IProfileOutput getProfileOutput(String name) {
+ return mOutputs.get(name);
+ }
+
+ public Enumeration<String> getProfileInputIds() {
+ return mInputIds.elements(); // ordered list
+ }
+
+ public IProfileInput getProfileInput(String name) {
+ return mInputs.get(name);
+ }
+
+ public void addInputName(String name) {
+ mInputNames.addElement(name);
+ }
+
+ public IDescriptor getInputDescriptor(String name) {
+ return null;
+ }
+
+ public String getInput(String name, Locale locale, IRequest request)
+ throws EProfileException {
+ return null;
+ }
+
+ public void setInput(String name, Locale locale, IRequest request,
+ String value) throws EProfileException {
+ }
+
+ public Enumeration<String> getProfilePolicySetIds() {
+ return mPolicySet.keys();
+ }
+
+ public void deleteProfilePolicy(String setId, String policyId)
+ throws EProfileException {
+ Vector<IProfilePolicy> policies = mPolicySet.get(setId);
+
+ if (policies == null) {
+ return;
+ }
+ try {
+ IConfigStore policySetSubStore = mConfig.getSubStore("policyset");
+ IConfigStore policySubStore = policySetSubStore.getSubStore(setId);
+
+ policySubStore.removeSubStore(policyId);
+ String list = policySubStore.getString(PROP_POLICY_LIST, null);
+ StringTokenizer st = new StringTokenizer(list, ",");
+ String newlist = "";
+ StringBuffer sb = new StringBuffer();
+
+ while (st.hasMoreTokens()) {
+ String e = st.nextToken();
+
+ if (!e.equals(policyId)) {
+ sb.append(e);
+ sb.append(",");
+ }
+ }
+ newlist = sb.toString();
+ if (!newlist.equals("")) {
+ newlist = newlist.substring(0, newlist.length() - 1);
+ policySubStore.putString(PROP_POLICY_LIST, newlist);
+ } else {
+ policySetSubStore.removeSubStore(setId);
+ }
+
+ int size = policies.size();
+
+ for (int i = 0; i < size; i++) {
+ IProfilePolicy policy = policies.elementAt(i);
+ String id = policy.getId();
+
+ if (id.equals(policyId)) {
+ policies.removeElementAt(i);
+ if (size == 1) {
+ mPolicySet.remove(setId);
+ String setlist = policySetSubStore.getString(PROP_POLICY_LIST, null);
+ StringTokenizer st1 = new StringTokenizer(setlist, ",");
+ String newlist1 = "";
+
+ while (st1.hasMoreTokens()) {
+ String e = st1.nextToken();
+
+ if (!e.equals(setId))
+ newlist1 = newlist1 + e + ",";
+ }
+ if (!newlist1.equals(""))
+ newlist1 = newlist1.substring(0, newlist1.length() - 1);
+ policySetSubStore.putString(PROP_POLICY_LIST, newlist1);
+ }
+ break;
+ }
+ }
+
+ mConfig.putString("lastModified",
+ Long.toString(CMS.getCurrentDate().getTime()));
+ mConfig.commit(false);
+ } catch (Exception e) {
+ }
+
+ }
+
+ public void deleteAllProfilePolicies() throws EProfileException {
+ for (Map.Entry<String, Vector<IProfilePolicy>> entry : mPolicySet.entrySet()) {
+ String setId = entry.getKey();
+ Vector<IProfilePolicy> pList = new Vector<IProfilePolicy>(entry.getValue());
+ for (IProfilePolicy policy: pList) {
+ deleteProfilePolicy(setId, policy.getId());
+ }
+ }
+
+ mPolicySet.clear();
+ }
+
+ public void deleteProfileInput(String inputId) throws EProfileException {
+ try {
+ mConfig.removeSubStore("input." + inputId);
+ String list = mConfig.getString("input." + PROP_INPUT_LIST, null);
+ StringTokenizer st = new StringTokenizer(list, ",");
+ String newlist = "";
+ StringBuffer sb = new StringBuffer();
+
+ while (st.hasMoreTokens()) {
+ String e = st.nextToken();
+
+ if (!e.equals(inputId)) {
+ sb.append(e);
+ sb.append(",");
+ }
+ }
+ newlist = sb.toString();
+ if (!newlist.equals(""))
+ newlist = newlist.substring(0, newlist.length() - 1);
+
+ int size = mInputIds.size();
+
+ for (int i = 0; i < size; i++) {
+ String id = mInputIds.elementAt(i);
+
+ if (id.equals(inputId)) {
+ mInputIds.removeElementAt(i);
+ break;
+ }
+ }
+
+ mInputs.remove(inputId);
+ mConfig.putString("input." + PROP_INPUT_LIST, newlist);
+ mConfig.putString("lastModified",
+ Long.toString(CMS.getCurrentDate().getTime()));
+ mConfig.commit(false);
+ } catch (Exception e) {
+ }
+ }
+
+ public void deleteAllProfileInputs() throws EProfileException {
+ // need to use a copy here because we are removing elements from the vector
+ Vector<String> inputs = new Vector<String>(mInputIds);
+ for (String id: inputs) {
+ deleteProfileInput(id);
+ }
+ }
+
+ public void deleteProfileOutput(String outputId) throws EProfileException {
+ try {
+ mConfig.removeSubStore("output." + outputId);
+ String list = mConfig.getString("output." + PROP_OUTPUT_LIST, null);
+ StringTokenizer st = new StringTokenizer(list, ",");
+ String newlist = "";
+ StringBuffer sb = new StringBuffer();
+
+ while (st.hasMoreTokens()) {
+ String e = st.nextToken();
+
+ if (!e.equals(outputId)) {
+ sb.append(e);
+ sb.append(",");
+ }
+ }
+ newlist = sb.toString();
+ if (!newlist.equals(""))
+ newlist = newlist.substring(0, newlist.length() - 1);
+
+ int size = mOutputIds.size();
+
+ for (int i = 0; i < size; i++) {
+ String id = mOutputIds.elementAt(i);
+
+ if (id.equals(outputId)) {
+ mOutputIds.removeElementAt(i);
+ break;
+ }
+ }
+
+ mOutputs.remove(outputId);
+ mConfig.putString("output." + PROP_OUTPUT_LIST, newlist);
+ mConfig.putString("lastModified",
+ Long.toString(CMS.getCurrentDate().getTime()));
+ mConfig.commit(false);
+ } catch (Exception e) {
+ }
+ }
+
+ public void deleteAllProfileOutputs() throws EProfileException {
+ // need to use a copy here because we are removing elements from the vector
+ Vector<String> outputs = new Vector<String>(mOutputIds);
+ for (String id: outputs) {
+ deleteProfileOutput(id);
+ }
+ }
+
+ public IProfileOutput createProfileOutput(String id, String outputId,
+ NameValuePairs nvps)
+ throws EProfileException {
+ return createProfileOutput(id, outputId, nvps, true);
+ }
+
+ public IProfileOutput createProfileOutput(String id, String outputId,
+ NameValuePairs nvps, boolean createConfig)
+
+ throws EProfileException {
+ IConfigStore outputStore = mConfig.getSubStore("output");
+
+ IPluginInfo outputInfo = mRegistry.getPluginInfo("profileOutput",
+ outputId);
+
+ if (outputInfo == null) {
+ CMS.debug("Cannot find " + outputId);
+ throw new EProfileException("Cannot find " + outputId);
+ }
+ String outputClass = outputInfo.getClassName();
+
+ CMS.debug("BasicProfile: loading output class " + outputClass);
+ IProfileOutput output = null;
+
+ try {
+ output = (IProfileOutput)
+ Class.forName(outputClass).newInstance();
+ } catch (Exception e) {
+ // throw Exception
+ CMS.debug(e.toString());
+ }
+ if (output == null) {
+ CMS.debug("BasicProfile: failed to create " + outputClass);
+ } else {
+ CMS.debug("BasicProfile: initing " + id + " output");
+
+ CMS.debug("BasicProfile: outputStore " + outputStore);
+ output.init(this, outputStore);
+
+ mOutputs.put(id, output);
+ mOutputIds.addElement(id);
+ }
+
+ if (createConfig) {
+ String list = null;
+
+ try {
+ list = outputStore.getString(PROP_OUTPUT_LIST, null);
+ } catch (EBaseException e) {
+ }
+ if (list == null || list.equals("")) {
+ outputStore.putString(PROP_OUTPUT_LIST, id);
+ } else {
+ StringTokenizer st1 = new StringTokenizer(list, ",");
+
+ while (st1.hasMoreTokens()) {
+ String pid = st1.nextToken();
+
+ if (pid.equals(id)) {
+ throw new EProfileException("Duplicate output id: " + id);
+ }
+ }
+ outputStore.putString(PROP_OUTPUT_LIST, list + "," + id);
+ }
+ String prefix = id + ".";
+
+ outputStore.putString(prefix + "name",
+ outputInfo.getName(Locale.getDefault()));
+ outputStore.putString(prefix + "class_id", outputId);
+
+ for (String name : nvps.keySet()) {
+
+ outputStore.putString(prefix + "params." + name, nvps.get(name));
+ try {
+ if (output != null) {
+ output.setConfig(name, nvps.get(name));
+ }
+ } catch (EBaseException e) {
+ CMS.debug(e.toString());
+ }
+ }
+
+ try {
+ mConfig.putString("lastModified",
+ Long.toString(CMS.getCurrentDate().getTime()));
+ mConfig.commit(false);
+ } catch (EBaseException e) {
+ CMS.debug(e.toString());
+ }
+ }
+
+ return output;
+ }
+
+ public IProfileInput createProfileInput(String id, String inputId,
+ NameValuePairs nvps)
+ throws EProfileException {
+ return createProfileInput(id, inputId, nvps, true);
+ }
+
+ public IProfileInput createProfileInput(String id, String inputId,
+ NameValuePairs nvps, boolean createConfig)
+ throws EProfileException {
+ IConfigStore inputStore = mConfig.getSubStore("input");
+
+ IPluginInfo inputInfo = mRegistry.getPluginInfo("profileInput",
+ inputId);
+
+ if (inputInfo == null) {
+ CMS.debug("Cannot find " + inputId);
+ throw new EProfileException("Cannot find " + inputId);
+ }
+ String inputClass = inputInfo.getClassName();
+
+ CMS.debug("BasicProfile: loading input class " + inputClass);
+ IProfileInput input = null;
+
+ try {
+ input = (IProfileInput)
+ Class.forName(inputClass).newInstance();
+ } catch (Exception e) {
+ // throw Exception
+ CMS.debug(e.toString());
+ }
+ if (input == null) {
+ CMS.debug("BasicProfile: failed to create " + inputClass);
+ } else {
+ CMS.debug("BasicProfile: initing " + id + " input");
+
+ CMS.debug("BasicProfile: inputStore " + inputStore);
+ input.init(this, inputStore);
+
+ mInputs.put(id, input);
+ mInputIds.addElement(id);
+ }
+
+ if (createConfig) {
+ String list = null;
+
+ try {
+ list = inputStore.getString(PROP_INPUT_LIST, null);
+ } catch (EBaseException e) {
+ }
+ if (list == null || list.equals("")) {
+ inputStore.putString(PROP_INPUT_LIST, id);
+ } else {
+ StringTokenizer st1 = new StringTokenizer(list, ",");
+
+ while (st1.hasMoreTokens()) {
+ String pid = st1.nextToken();
+
+ if (pid.equals(id)) {
+ throw new EProfileException("Duplicate input id: " + id);
+ }
+ }
+ inputStore.putString(PROP_INPUT_LIST, list + "," + id);
+ }
+ String prefix = id + ".";
+
+ inputStore.putString(prefix + "name",
+ inputInfo.getName(Locale.getDefault()));
+ inputStore.putString(prefix + "class_id", inputId);
+
+ for (String name : nvps.keySet()) {
+
+ inputStore.putString(prefix + "params." + name, nvps.get(name));
+ try {
+ if (input != null) {
+ input.setConfig(name, nvps.get(name));
+ }
+ } catch (EBaseException e) {
+ CMS.debug(e.toString());
+ }
+ }
+
+ try {
+ mConfig.putString("lastModified",
+ Long.toString(CMS.getCurrentDate().getTime()));
+ mConfig.commit(false);
+ } catch (EBaseException e) {
+ CMS.debug(e.toString());
+ }
+ }
+
+ return input;
+ }
+
+ /**
+ * Creates a profile policy
+ */
+ public IProfilePolicy createProfilePolicy(String setId, String id,
+ String defaultClassId, String constraintClassId)
+ throws EProfileException {
+ return createProfilePolicy(setId, id, defaultClassId,
+ constraintClassId, true);
+ }
+
+ public IProfilePolicy createProfilePolicy(String setId, String id,
+ String defaultClassId, String constraintClassId,
+ boolean createConfig)
+ throws EProfileException {
+
+ // String setId ex: policyset.set1
+ // String id Id of policy : examples: p1,p2,p3
+ // String defaultClassId : id of the default plugin ex: validityDefaultImpl
+ // String constraintClassId : if of the constraint plugin ex: basicConstraintsExtConstraintImpl
+ // boolean createConfig : true : being called from the console. false: being called from server startup code
+
+ Vector<IProfilePolicy> policies = mPolicySet.get(setId);
+
+ IConfigStore policyStore = mConfig.getSubStore("policyset." + setId);
+ if (policies == null) {
+ policies = new Vector<IProfilePolicy>();
+ mPolicySet.put(setId, policies);
+ if (createConfig) {
+ // re-create policyset.list
+ StringBuffer setlist = new StringBuffer();
+ Enumeration<String> keys = mPolicySet.keys();
+
+ while (keys.hasMoreElements()) {
+ String k = keys.nextElement();
+
+ if (!(setlist.toString()).equals("")) {
+ setlist.append(",");
+ }
+ setlist.append(k);
+ }
+ mConfig.putString("policyset.list", setlist.toString());
+ }
+ } else {
+ String ids = null;
+
+ try {
+ ids = policyStore.getString(PROP_POLICY_LIST, "");
+ } catch (Exception ee) {
+ }
+
+ if (ids == null) {
+ CMS.debug("BasicProfile::createProfilePolicy() - ids is null!");
+ return null;
+ }
+
+ StringTokenizer st1 = new StringTokenizer(ids, ",");
+ int appearances = 0;
+ int appearancesTooMany = 0;
+ if (createConfig)
+ appearancesTooMany = 1;
+ else
+ appearancesTooMany = 2;
+
+ while (st1.hasMoreTokens()) {
+ String pid = st1.nextToken();
+ if (pid.equals(id)) {
+ appearances++;
+ if (appearances >= appearancesTooMany) {
+ CMS.debug("WARNING detected duplicate policy id: " + id + " Profile: " + mId);
+ if (createConfig) {
+ throw new EProfileException("Duplicate policy id: " + id);
+ }
+ }
+ }
+ }
+ }
+
+ // Now make sure we aren't trying to add a policy that already exists
+ IConfigStore policySetStore = mConfig.getSubStore("policyset");
+ String setlist = null;
+ try {
+ setlist = policySetStore.getString("list", "");
+ } catch (Exception e) {
+ }
+ StringTokenizer st = new StringTokenizer(setlist, ",");
+
+ int matches = 0;
+ while (st.hasMoreTokens()) {
+ String sId = st.nextToken();
+
+ //Only search the setId set. Ex: encryptionCertSet
+ if (!sId.equals(setId)) {
+ continue;
+ }
+ IConfigStore pStore = policySetStore.getSubStore(sId);
+
+ String list = null;
+ try {
+ list = pStore.getString(PROP_POLICY_LIST, "");
+ } catch (Exception e) {
+ CMS.debug("WARNING, can't get policy id list!");
+ }
+
+ StringTokenizer st1 = new StringTokenizer(list, ",");
+
+ while (st1.hasMoreTokens()) {
+ String curId = st1.nextToken();
+
+ String defaultRoot = curId + "." + PROP_DEFAULT;
+ String curDefaultClassId = null;
+ try {
+ curDefaultClassId = pStore.getString(defaultRoot + "." +
+ PROP_CLASS_ID);
+ } catch (Exception e) {
+ CMS.debug("WARNING, can't get default plugin id!");
+ }
+
+ //Disallow duplicate defaults with the following exceptions:
+ // noDefaultImpl, genericExtDefaultImpl
+
+ if ((curDefaultClassId.equals(defaultClassId) &&
+ !curDefaultClassId.equals(PROP_NO_DEFAULT) &&
+ !curDefaultClassId.equals(PROP_GENERIC_EXT_DEFAULT))) {
+
+ matches++;
+ if (createConfig) {
+ if (matches == 1) {
+ CMS.debug("WARNING attempt to add duplicate Policy "
+ + defaultClassId + ":" + constraintClassId +
+ " Contact System Administrator.");
+ throw new EProfileException("Attempt to add duplicate Policy : "
+ + defaultClassId + ":" + constraintClassId);
+ }
+ } else {
+ if (matches > 1) {
+ CMS.debug("WARNING attempt to add duplicate Policy "
+ + defaultClassId + ":" + constraintClassId +
+ " Contact System Administrator.");
+ }
+ }
+ }
+ }
+ }
+
+ String defaultRoot = id + "." + PROP_DEFAULT;
+ String constraintRoot = id + "." + PROP_CONSTRAINT;
+ IPluginInfo defInfo = mRegistry.getPluginInfo("defaultPolicy",
+ defaultClassId);
+
+ if (defInfo == null) {
+ CMS.debug("BasicProfile: Cannot find " + defaultClassId);
+ throw new EProfileException("Cannot find " + defaultClassId);
+ }
+ String defaultClass = defInfo.getClassName();
+
+ CMS.debug("BasicProfile: loading default class " + defaultClass);
+ IPolicyDefault def = null;
+
+ try {
+ def = (IPolicyDefault)
+ Class.forName(defaultClass).newInstance();
+ } catch (Exception e) {
+ // throw Exception
+ CMS.debug("BasicProfile: default policy " +
+ defaultClass + " " + e.toString());
+ }
+ if (def == null) {
+ CMS.debug("BasicProfile: failed to create " + defaultClass);
+ } else {
+ IConfigStore defStore = null;
+
+ defStore = policyStore.getSubStore(defaultRoot);
+ def.init(this, defStore);
+ }
+
+ IPluginInfo conInfo = mRegistry.getPluginInfo("constraintPolicy",
+ constraintClassId);
+ String constraintClass = conInfo.getClassName();
+ IPolicyConstraint constraint = null;
+
+ try {
+ constraint = (IPolicyConstraint)
+ Class.forName(constraintClass).newInstance();
+ } catch (Exception e) {
+ // throw Exception
+ CMS.debug("BasicProfile: constraint policy " +
+ constraintClass + " " + e.toString());
+ }
+ ProfilePolicy policy = null;
+ if (constraint == null) {
+ CMS.debug("BasicProfile: failed to create " + constraintClass);
+ } else {
+ IConfigStore conStore = null;
+
+ conStore = policyStore.getSubStore(constraintRoot);
+ constraint.init(this, conStore);
+ policy = new ProfilePolicy(id, def, constraint);
+ policies.addElement(policy);
+ }
+
+ if (createConfig) {
+ String list = null;
+
+ try {
+ list = policyStore.getString(PROP_POLICY_LIST, null);
+ } catch (EBaseException e) {
+ }
+ if (list == null || list.equals("")) {
+ policyStore.putString(PROP_POLICY_LIST, id);
+ } else {
+ policyStore.putString(PROP_POLICY_LIST, list + "," + id);
+ }
+ policyStore.putString(id + ".default.name",
+ defInfo.getName(Locale.getDefault()));
+ policyStore.putString(id + ".default.class_id",
+ defaultClassId);
+ policyStore.putString(id + ".constraint.name",
+ conInfo.getName(Locale.getDefault()));
+ policyStore.putString(id + ".constraint.class_id",
+ constraintClassId);
+ try {
+ mConfig.putString("lastModified",
+ Long.toString(CMS.getCurrentDate().getTime()));
+ policyStore.commit(false);
+ } catch (EBaseException e) {
+ CMS.debug("BasicProfile: commiting config store " +
+ e.toString());
+ }
+ }
+
+ return policy;
+ }
+
+ public IProfilePolicy getProfilePolicy(String setId, String id) {
+ Vector<IProfilePolicy> policies = mPolicySet.get(setId);
+
+ if (policies == null)
+ return null;
+
+ for (int i = 0; i < policies.size(); i++) {
+ IProfilePolicy policy = policies.elementAt(i);
+
+ if (policy.getId().equals(id)) {
+ return policy;
+ }
+ }
+ return null;
+ }
+
+ public boolean isVisible() {
+ try {
+ return mConfig.getBoolean(PROP_VISIBLE, false);
+ } catch (EBaseException e) {
+ return false;
+ }
+ }
+
+ public void setVisible(boolean v) {
+ mConfig.putBoolean(PROP_VISIBLE, v);
+ }
+
+ /**
+ * Returns the profile name.
+ */
+ public String getName(Locale locale) {
+ try {
+ return mConfig.getString(PROP_NAME, "");
+ } catch (EBaseException e) {
+ return "";
+ }
+ }
+
+ public void setName(Locale locale, String name) {
+ mConfig.putString(PROP_NAME, name);
+ }
+
+ public abstract IProfileContext createContext();
+
+ /**
+ * Creates request.
+ */
+ public abstract IRequest[] createRequests(IProfileContext ctx, Locale locale)
+ throws EProfileException;
+
+ /**
+ * Returns the profile description.
+ */
+ public String getDescription(Locale locale) {
+ try {
+ return mConfig.getString(PROP_DESC, "");
+ } catch (EBaseException e) {
+ return "";
+ }
+ }
+
+ public void setDescription(Locale locale, String desc) {
+ mConfig.putString(PROP_DESC, desc);
+ }
+
+ public void populateInput(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ Enumeration<String> ids = getProfileInputIds();
+
+ while (ids.hasMoreElements()) {
+ String id = ids.nextElement();
+ IProfileInput input = getProfileInput(id);
+
+ input.populate(ctx, request);
+ }
+ }
+
+ public Vector<IProfilePolicy> getPolicies(String setId) {
+ Vector<IProfilePolicy> policies = mPolicySet.get(setId);
+
+ return policies;
+ }
+
+ /**
+ * Passes the request to the set of default policies that
+ * populate the profile information against the profile.
+ */
+ public void populate(IRequest request)
+ throws EProfileException {
+ String setId = getPolicySetId(request);
+ Vector<IProfilePolicy> policies = getPolicies(setId);
+ CMS.debug("BasicProfile: populate() policy setid =" + setId);
+
+ for (int i = 0; i < policies.size(); i++) {
+ IProfilePolicy policy = policies.elementAt(i);
+
+ policy.getDefault().populate(request);
+ }
+ }
+
+ /**
+ * Passes the request to the set of constraint policies
+ * that validate the request against the profile.
+ */
+ public void validate(IRequest request)
+ throws ERejectException {
+ String setId = getPolicySetId(request);
+ CMS.debug("BasicProfile: validate start on setId=" + setId);
+ Vector<IProfilePolicy> policies = getPolicies(setId);
+
+ for (int i = 0; i < policies.size(); i++) {
+ IProfilePolicy policy = policies.elementAt(i);
+
+ policy.getConstraint().validate(request);
+ }
+ CMS.debug("BasicProfile: change to pending state");
+ request.setRequestStatus(RequestStatus.PENDING);
+ CMS.debug("BasicProfile: validate end");
+ }
+
+ public Enumeration<IProfilePolicy> getProfilePolicies(String setId) {
+ Vector<IProfilePolicy> policies = mPolicySet.get(setId);
+
+ if (policies == null)
+ return null;
+ return policies.elements();
+ }
+
+ public Enumeration<String> getProfilePolicyIds(String setId) {
+ Vector<IProfilePolicy> policies = mPolicySet.get(setId);
+
+ if (policies == null)
+ return null;
+
+ Vector<String> v = new Vector<String>();
+
+ for (int i = 0; i < policies.size(); i++) {
+ IProfilePolicy policy = policies.elementAt(i);
+
+ v.addElement(policy.getId());
+ }
+ return v.elements();
+ }
+
+ public void execute(IRequest request)
+ throws EProfileException {
+ }
+
+ /**
+ * Signed Audit Log
+ *
+ * This method is inherited by all extended "BasicProfile"s,
+ * and is called to store messages to the signed audit log.
+ * <P>
+ *
+ * @param msg signed audit log message
+ */
+ protected void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+
+ if (mSignedAuditLogger == null) {
+ return;
+ }
+
+ mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+
+ /**
+ * Signed Audit Log Subject ID
+ *
+ * This method is inherited by all extended "BasicProfile"s,
+ * and is called to obtain the "SubjectID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @return id string containing the signed audit log message SubjectID
+ */
+ protected String auditSubjectID() {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String subjectID = null;
+
+ // Initialize subjectID
+ SessionContext auditContext = SessionContext.getExistingContext();
+
+ if (auditContext != null) {
+ subjectID = (String)
+ auditContext.get(SessionContext.USER_ID);
+
+ if (subjectID != null) {
+ subjectID = subjectID.trim();
+ } else {
+ subjectID = ILogger.NONROLEUSER;
+ }
+ } else {
+ subjectID = ILogger.UNIDENTIFIED;
+ }
+
+ return subjectID;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/CACertCAEnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/CACertCAEnrollProfile.java
new file mode 100644
index 000000000..1ae2f0853
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/common/CACertCAEnrollProfile.java
@@ -0,0 +1,107 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.common;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfileEx;
+import com.netscape.certsrv.profile.IProfilePolicy;
+
+/**
+ * This class implements a Certificate Manager enrollment
+ * profile for CA Certificates.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CACertCAEnrollProfile extends CAEnrollProfile
+ implements IProfileEx {
+
+ /**
+ * Called after initialization. It populates default
+ * policies, inputs, and outputs.
+ */
+ public void populate() throws EBaseException {
+ // create inputs
+ NameValuePairs inputParams1 = new NameValuePairs();
+ createProfileInput("i1", "certReqInputImpl", inputParams1);
+ NameValuePairs inputParams2 = new NameValuePairs();
+ createProfileInput("i2", "submitterInfoInputImpl", inputParams2);
+
+ // create outputs
+ NameValuePairs outputParams1 = new NameValuePairs();
+ createProfileOutput("o1", "certOutputImpl", outputParams1);
+
+ // create policies
+ createProfilePolicy("set1", "p1",
+ "userSubjectNameDefaultImpl", "noConstraintImpl");
+
+ IProfilePolicy policy2 =
+ createProfilePolicy("set1", "p2",
+ "validityDefaultImpl", "noConstraintImpl");
+ IPolicyDefault def2 = policy2.getDefault();
+ IConfigStore defConfig2 = def2.getConfigStore();
+ defConfig2.putString("params.range", "180");
+ defConfig2.putString("params.startTime", "0");
+
+ IProfilePolicy policy3 =
+ createProfilePolicy("set1", "p3",
+ "userKeyDefaultImpl", "noConstraintImpl");
+ IPolicyDefault def3 = policy3.getDefault();
+ IConfigStore defConfig3 = def3.getConfigStore();
+ defConfig3.putString("params.keyType", "RSA");
+ defConfig3.putString("params.keyMinLength", "512");
+ defConfig3.putString("params.keyMaxLength", "4096");
+
+ IProfilePolicy policy4 =
+ createProfilePolicy("set1", "p4",
+ "signingAlgDefaultImpl", "noConstraintImpl");
+ IPolicyDefault def4 = policy4.getDefault();
+ IConfigStore defConfig4 = def4.getConfigStore();
+ defConfig4.putString("params.signingAlg", "-");
+ defConfig4.putString("params.signingAlgsAllowed",
+ "SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA256withEC,SHA384withEC,SHA512withEC");
+
+ // extensions
+ IProfilePolicy policy5 =
+ createProfilePolicy("set1", "p5",
+ "keyUsageExtDefaultImpl", "noConstraintImpl");
+ IPolicyDefault def5 = policy5.getDefault();
+ IConfigStore defConfig5 = def5.getConfigStore();
+ defConfig5.putString("params.keyUsageCritical", "true");
+ defConfig5.putString("params.keyUsageCrlSign", "true");
+ defConfig5.putString("params.keyUsageDataEncipherment", "false");
+ defConfig5.putString("params.keyUsageDecipherOnly", "false");
+ defConfig5.putString("params.keyUsageDigitalSignature", "true");
+ defConfig5.putString("params.keyUsageEncipherOnly", "false");
+ defConfig5.putString("params.keyUsageKeyAgreement", "false");
+ defConfig5.putString("params.keyUsageKeyCertSign", "true");
+ defConfig5.putString("params.keyUsageKeyEncipherment", "false");
+ defConfig5.putString("params.keyUsageNonRepudiation", "true");
+
+ IProfilePolicy policy6 =
+ createProfilePolicy("set1", "p6",
+ "basicConstraintsExtDefaultImpl", "noConstraintImpl");
+ IPolicyDefault def6 = policy6.getDefault();
+ IConfigStore defConfig6 = def6.getConfigStore();
+ defConfig6.putString("params.basicConstraintsPathLen", "-1");
+ defConfig6.putString("params.basicConstraintsIsCA", "true");
+ defConfig6.putString("params.basicConstraintsPathLen", "-1");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java
new file mode 100644
index 000000000..d0bfdb8a6
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java
@@ -0,0 +1,243 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.common;
+
+import java.util.Enumeration;
+
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import org.mozilla.jss.pkix.crmf.PKIArchiveOptions;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ca.ICAService;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.connector.IConnector;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IProfileUpdater;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestStatus;
+
+/**
+ * This class implements a Certificate Manager enrollment
+ * profile.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CAEnrollProfile extends EnrollProfile {
+
+ private final static String LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST =
+ "LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST_4";
+
+ public CAEnrollProfile() {
+ super();
+ }
+
+ public IAuthority getAuthority() {
+ IAuthority authority = (IAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+
+ if (authority == null)
+ return null;
+ return authority;
+ }
+
+ public X500Name getIssuerName() {
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ X500Name issuerName = ca.getX500Name();
+
+ return issuerName;
+ }
+
+ public void execute(IRequest request)
+ throws EProfileException {
+
+ long startTime = CMS.getCurrentDate().getTime();
+
+ if (!isEnable()) {
+ CMS.debug("CAEnrollProfile: Profile Not Enabled");
+ throw new EProfileException("Profile Not Enabled");
+ }
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRequesterID = auditRequesterID(request);
+ String auditArchiveID = ILogger.UNIDENTIFIED;
+
+ String id = request.getRequestId().toString();
+ if (id != null) {
+ auditArchiveID = id.trim();
+ }
+
+ CMS.debug("CAEnrollProfile: execute reqId=" +
+ request.getRequestId().toString());
+ ICertificateAuthority ca = (ICertificateAuthority) getAuthority();
+ ICAService caService = (ICAService) ca.getCAService();
+
+ if (caService == null) {
+ throw new EProfileException("No CA Service");
+ }
+
+ // if PKI Archive Option present, send this request
+ // to DRM
+ byte optionsData[] = request.getExtDataInByteArray(REQUEST_ARCHIVE_OPTIONS);
+ // do not archive keys for renewal requests
+ if ((optionsData != null) && (!request.getRequestType().equals(IRequest.RENEWAL_REQUEST))) {
+ PKIArchiveOptions options = toPKIArchiveOptions(optionsData);
+
+ if (options != null) {
+ CMS.debug("CAEnrollProfile: execute found " +
+ "PKIArchiveOptions");
+ try {
+ IConnector kraConnector = caService.getKRAConnector();
+
+ if (kraConnector == null) {
+ CMS.debug("CAEnrollProfile: KRA connector " +
+ "not configured");
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditArchiveID);
+
+ audit(auditMessage);
+
+ } else {
+ CMS.debug("CAEnrollProfile: execute send request");
+ kraConnector.send(request);
+
+ // check response
+ if (!request.isSuccess()) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditArchiveID);
+
+ audit(auditMessage);
+ if (request.getError(getLocale(request)) != null &&
+ (request.getError(getLocale(request))).equals(CMS.getUserMessage("CMS_KRA_INVALID_TRANSPORT_CERT"))) {
+ CMS.debug("CAEnrollProfile: execute set request status: REJECTED");
+ request.setRequestStatus(RequestStatus.REJECTED);
+ ca.getRequestQueue().updateRequest(request);
+ }
+ throw new ERejectException(
+ request.getError(getLocale(request)));
+ }
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditArchiveID);
+
+ audit(auditMessage);
+ }
+ } catch (Exception e) {
+
+ if (e instanceof ERejectException) {
+ throw (ERejectException) e;
+ }
+ CMS.debug("CAEnrollProfile: " + e.toString());
+ CMS.debug(e);
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditArchiveID);
+
+ audit(auditMessage);
+ throw new EProfileException(e.toString());
+ }
+ }
+ }
+ // process certificate issuance
+ X509CertInfo info = request.getExtDataInCertInfo(REQUEST_CERTINFO);
+ X509CertImpl theCert = null;
+ // #615460 - added audit log (transaction)
+ SessionContext sc = SessionContext.getExistingContext();
+ sc.put("profileId", getId());
+ String setId = request.getExtDataInString("profileSetId");
+ if (setId != null) {
+ sc.put("profileSetId", setId);
+ }
+ try {
+ theCert = caService.issueX509Cert(info, getId() /* profileId */,
+ id /* requestId */);
+ } catch (EBaseException e) {
+ CMS.debug(e.toString());
+
+ throw new EProfileException(e.toString());
+ }
+ request.setExtData(REQUEST_ISSUED_CERT, theCert);
+
+ long endTime = CMS.getCurrentDate().getTime();
+
+ String initiative = AuditFormat.FROMAGENT
+ + " userID: "
+ + (String) sc.get(SessionContext.USER_ID);
+ String authMgr = (String) sc.get(SessionContext.AUTH_MANAGER_ID);
+
+ ILogger logger = CMS.getLogger();
+ if (logger != null) {
+ logger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER, AuditFormat.LEVEL, AuditFormat.FORMAT,
+ new Object[] {
+ request.getRequestType(),
+ request.getRequestId(),
+ initiative,
+ authMgr,
+ "completed",
+ theCert.getSubjectDN(),
+ "cert issued serial number: 0x" +
+ theCert.getSerialNumber().toString(16) +
+ " time: " + (endTime - startTime) }
+ );
+ }
+
+ request.setRequestStatus(RequestStatus.COMPLETE);
+ // notifies updater plugins
+ Enumeration<String> updaterIds = getProfileUpdaterIds();
+ while (updaterIds.hasMoreElements()) {
+ String updaterId = updaterIds.nextElement();
+ IProfileUpdater updater = getProfileUpdater(updaterId);
+ updater.update(request, RequestStatus.COMPLETE);
+ }
+
+ // set value for predicate value - checking in getRule
+ if (CMS.isEncryptionCert(theCert))
+ request.setExtData("isEncryptionCert", "true");
+ else
+ request.setExtData("isEncryptionCert", "false");
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
new file mode 100644
index 000000000..ca665baf1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
@@ -0,0 +1,1506 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.common;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import netscape.security.pkcs.PKCS10;
+import netscape.security.pkcs.PKCS10Attribute;
+import netscape.security.pkcs.PKCS10Attributes;
+import netscape.security.pkcs.PKCS9Attribute;
+import netscape.security.util.DerInputStream;
+import netscape.security.util.DerOutputStream;
+import netscape.security.util.DerValue;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateIssuerName;
+import netscape.security.x509.CertificateSerialNumber;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.Extension;
+import netscape.security.x509.Extensions;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.ASN1Value;
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
+import org.mozilla.jss.asn1.OCTET_STRING;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.asn1.SET;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.pkcs10.CertificationRequest;
+import org.mozilla.jss.pkcs10.CertificationRequestInfo;
+import org.mozilla.jss.pkix.cmc.LraPopWitness;
+import org.mozilla.jss.pkix.cmc.OtherMsg;
+import org.mozilla.jss.pkix.cmc.PKIData;
+import org.mozilla.jss.pkix.cmc.TaggedAttribute;
+import org.mozilla.jss.pkix.cmc.TaggedCertificationRequest;
+import org.mozilla.jss.pkix.cmc.TaggedRequest;
+import org.mozilla.jss.pkix.crmf.CertReqMsg;
+import org.mozilla.jss.pkix.crmf.CertRequest;
+import org.mozilla.jss.pkix.crmf.CertTemplate;
+import org.mozilla.jss.pkix.crmf.PKIArchiveOptions;
+import org.mozilla.jss.pkix.crmf.ProofOfPossession;
+import org.mozilla.jss.pkix.primitive.AVA;
+import org.mozilla.jss.pkix.primitive.Attribute;
+import org.mozilla.jss.pkix.primitive.Name;
+import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authentication.ISharedToken;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EDeferException;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.cmsutil.util.HMACDigest;
+
+/**
+ * This class implements a generic enrollment profile.
+ *
+ * @version $Revision$, $Date$
+ */
+public abstract class EnrollProfile extends BasicProfile
+ implements IEnrollProfile {
+
+ private final static String LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST =
+ "LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST_5";
+ private final static String LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION =
+ "LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION_2";
+
+ private PKIData mCMCData;
+
+ public EnrollProfile() {
+ super();
+ }
+
+ public abstract IAuthority getAuthority();
+
+ public IRequestQueue getRequestQueue() {
+ IAuthority authority = getAuthority();
+
+ return authority.getRequestQueue();
+ }
+
+ public IProfileContext createContext() {
+ return new EnrollProfileContext();
+ }
+
+ /**
+ * Creates request.
+ */
+ public IRequest[] createRequests(IProfileContext context, Locale locale)
+ throws EProfileException {
+ EnrollProfileContext ctx = (EnrollProfileContext) context;
+
+ // determine how many requests should be created
+ String cert_request_type = ctx.get(CTX_CERT_REQUEST_TYPE);
+ String cert_request = ctx.get(CTX_CERT_REQUEST);
+ String is_renewal = ctx.get(CTX_RENEWAL);
+ Integer renewal_seq_num = 0;
+
+ /* cert_request_type can be null for the case of CMC */
+ if (cert_request_type == null) {
+ CMS.debug("EnrollProfile: request type is null");
+ }
+
+ int num_requests = 1; // default to 1 request
+
+ if (cert_request_type != null && cert_request_type.startsWith("pkcs10")) {
+ // catch for invalid request
+ parsePKCS10(locale, cert_request);
+ }
+ if (cert_request_type != null && cert_request_type.startsWith("crmf")) {
+ CertReqMsg msgs[] = parseCRMF(locale, cert_request);
+
+ num_requests = msgs.length;
+ }
+ if (cert_request_type != null && cert_request_type.startsWith("cmc")) {
+ // catch for invalid request
+ TaggedRequest[] msgs = parseCMC(locale, cert_request);
+ if (msgs == null)
+ return null;
+ else
+ num_requests = msgs.length;
+ }
+
+ // only 1 request for renewal
+ if ((is_renewal != null) && (is_renewal.equals("true"))) {
+ num_requests = 1;
+ String renewal_seq_num_str = ctx.get(CTX_RENEWAL_SEQ_NUM);
+ if (renewal_seq_num_str != null) {
+ renewal_seq_num = Integer.parseInt(renewal_seq_num_str);
+ } else {
+ renewal_seq_num = 0;
+ }
+ }
+
+ // populate requests with appropriate content
+ IRequest result[] = new IRequest[num_requests];
+
+ for (int i = 0; i < num_requests; i++) {
+ result[i] = createEnrollmentRequest();
+ if ((is_renewal != null) && (is_renewal.equals("true"))) {
+ result[i].setExtData(REQUEST_SEQ_NUM, renewal_seq_num);
+ } else {
+ result[i].setExtData(REQUEST_SEQ_NUM, Integer.valueOf(i));
+ }
+ if (locale != null) {
+ result[i].setExtData(REQUEST_LOCALE, locale.getLanguage());
+ }
+ }
+ return result;
+ }
+
+ public abstract X500Name getIssuerName();
+
+ public void setDefaultCertInfo(IRequest req) throws EProfileException {
+ // create an empty certificate template so that
+ // default plugins that store stuff
+ X509CertInfo info = new X509CertInfo();
+
+ // retrieve issuer name
+ X500Name issuerName = getIssuerName();
+
+ byte[] dummykey = new byte[] {
+ 48, 92, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5,
+ 0, 3, 75, 0, 48, 72, 2, 65, 0, -65, 121, -119, -59, 105, 66,
+ -122, -78, -30, -64, 63, -47, 44, -48, -104, 103, -47, -108,
+ 42, -38, 46, -8, 32, 49, -29, -26, -112, -29, -86, 71, 24,
+ -104, 78, -31, -75, -128, 90, -92, -34, -51, -125, -13, 80, 101,
+ -78, 39, -119, -38, 117, 28, 67, -19, -71, -124, -85, 105, -53,
+ -103, -59, -67, -38, -83, 118, 65, 2, 3, 1, 0, 1 };
+ // default values into x509 certinfo. This thing is
+ // not serializable by default
+ try {
+ info.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ info.set(X509CertInfo.SERIAL_NUMBER,
+ new CertificateSerialNumber(new BigInteger("0")));
+ info.set(X509CertInfo.ISSUER,
+ new CertificateIssuerName(issuerName));
+ info.set(X509CertInfo.KEY,
+ new CertificateX509Key(X509Key.parse(new DerValue(dummykey))));
+ info.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(issuerName));
+ info.set(X509CertInfo.VALIDITY,
+ new CertificateValidity(new Date(), new Date()));
+ info.set(X509CertInfo.ALGORITHM_ID,
+ new CertificateAlgorithmId(AlgorithmId.get("MD5withRSA")));
+
+ // add default extension container
+ info.set(X509CertInfo.EXTENSIONS,
+ new CertificateExtensions());
+ } catch (Exception e) {
+ // throw exception - add key to template
+ CMS.debug("EnrollProfile: Building X509CertInfo - " + e.toString());
+ throw new EProfileException(e.toString());
+ }
+ req.setExtData(REQUEST_CERTINFO, info);
+ }
+
+ public IRequest createEnrollmentRequest()
+ throws EProfileException {
+ IRequest req = null;
+
+ try {
+ req = getRequestQueue().newRequest("enrollment");
+
+ setDefaultCertInfo(req);
+
+ // put the certificate info into request
+ req.setExtData(REQUEST_EXTENSIONS,
+ new CertificateExtensions());
+
+ CMS.debug("EnrollProfile: createRequest " +
+ req.getRequestId().toString());
+ } catch (EBaseException e) {
+ // raise exception
+ CMS.debug("EnrollProfile: create new enroll request " +
+ e.toString());
+ }
+
+ return req;
+ }
+
+ public abstract void execute(IRequest request)
+ throws EProfileException;
+
+ /**
+ * Perform simple policy set assignment.
+ */
+ public String getPolicySetId(IRequest req) {
+ Integer seq = req.getExtDataInInteger(REQUEST_SEQ_NUM);
+ int seq_no = seq.intValue(); // start from 0
+
+ int count = 0;
+ Enumeration<String> setIds = getProfilePolicySetIds();
+
+ while (setIds.hasMoreElements()) {
+ String setId = setIds.nextElement();
+
+ if (count == seq_no) {
+ return setId;
+ }
+ count++;
+ }
+ return null;
+ }
+
+ public String getRequestorDN(IRequest request) {
+ X509CertInfo info = request.getExtDataInCertInfo(REQUEST_CERTINFO);
+
+ try {
+ CertificateSubjectName sn = (CertificateSubjectName)
+ info.get(X509CertInfo.SUBJECT);
+
+ return sn.toString();
+ } catch (Exception e) {
+ CMS.debug("EnrollProfile: getRequestDN " + e.toString());
+ }
+ return null;
+ }
+
+ /**
+ * This method is called after the user submits the
+ * request from the end-entity page.
+ */
+ public void submit(IAuthToken token, IRequest request)
+ throws EDeferException, EProfileException {
+ // Request Submission Logic:
+ //
+ // if (Authentication Failed) {
+ // return Error
+ // } else {
+ // if (No Auth Token) {
+ // queue request
+ // } else {
+ // process request
+ // }
+ // }
+
+ IAuthority authority = getAuthority();
+ IRequestQueue queue = authority.getRequestQueue();
+
+ // this profile queues request that is authenticated
+ // by NoAuth
+ try {
+ queue.updateRequest(request);
+ } catch (EBaseException e) {
+ // save request to disk
+ CMS.debug("EnrollProfile: Update request " + e.toString());
+ }
+
+ if (token == null) {
+ CMS.debug("EnrollProfile: auth token is null");
+ CMS.debug("EnrollProfile: validating request");
+ validate(request);
+ try {
+ queue.updateRequest(request);
+ } catch (EBaseException e) {
+ CMS.debug("EnrollProfile: Update request (after validation) " + e.toString());
+ }
+
+ throw new EDeferException("defer request");
+ } else {
+ // this profile executes request that is authenticated
+ // by non NoAuth
+ CMS.debug("EnrollProfile: auth token is not null");
+ validate(request);
+ execute(request);
+ }
+ }
+
+ public TaggedRequest[] parseCMC(Locale locale, String certreq)
+ throws EProfileException {
+ /* cert request must not be null */
+ if (certreq == null) {
+ CMS.debug("EnrollProfile: parseCMC() certreq null");
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ }
+ CMS.debug("EnrollProfile: Start parseCMC(): " + certreq);
+
+ TaggedRequest msgs[] = null;
+
+ String creq = normalizeCertReq(certreq);
+ try {
+ byte data[] = CMS.AtoB(creq);
+ ByteArrayInputStream cmcBlobIn =
+ new ByteArrayInputStream(data);
+
+ org.mozilla.jss.pkix.cms.ContentInfo cmcReq = (org.mozilla.jss.pkix.cms.ContentInfo)
+ org.mozilla.jss.pkix.cms.ContentInfo.getTemplate().decode(cmcBlobIn);
+ org.mozilla.jss.pkix.cms.SignedData cmcFullReq =
+ (org.mozilla.jss.pkix.cms.SignedData) cmcReq.getInterpretedContent();
+ org.mozilla.jss.pkix.cms.EncapsulatedContentInfo ci = cmcFullReq.getContentInfo();
+ OCTET_STRING content = ci.getContent();
+
+ ByteArrayInputStream s = new ByteArrayInputStream(content.toByteArray());
+ PKIData pkiData = (PKIData) (new PKIData.Template()).decode(s);
+
+ mCMCData = pkiData;
+ //PKIData pkiData = (PKIData)
+ // (new PKIData.Template()).decode(cmcBlobIn);
+ SEQUENCE controlSeq = pkiData.getControlSequence();
+ int numcontrols = controlSeq.size();
+ SEQUENCE reqSeq = pkiData.getReqSequence();
+ byte randomSeed[] = null;
+ SessionContext context = SessionContext.getContext();
+ if (!context.containsKey("numOfControls")) {
+ if (numcontrols > 0) {
+ context.put("numOfControls", Integer.valueOf(numcontrols));
+ TaggedAttribute[] attributes = new TaggedAttribute[numcontrols];
+ for (int i = 0; i < numcontrols; i++) {
+ attributes[i] = (TaggedAttribute) controlSeq.elementAt(i);
+ OBJECT_IDENTIFIER oid = attributes[i].getType();
+ if (oid.equals(OBJECT_IDENTIFIER.id_cmc_identityProof)) {
+ boolean valid = verifyIdentityProof(attributes[i],
+ reqSeq);
+ if (!valid) {
+ SEQUENCE bpids = getRequestBpids(reqSeq);
+ context.put("identityProof", bpids);
+ return null;
+ }
+ } else if (oid.equals(OBJECT_IDENTIFIER.id_cmc_idPOPLinkRandom)) {
+ SET vals = attributes[i].getValues();
+ OCTET_STRING ostr =
+ (OCTET_STRING) (ASN1Util.decode(OCTET_STRING.getTemplate(),
+ ASN1Util.encode(vals.elementAt(0))));
+ randomSeed = ostr.toByteArray();
+ } else {
+ context.put(attributes[i].getType(), attributes[i]);
+ }
+ }
+ }
+ }
+
+ SEQUENCE otherMsgSeq = pkiData.getOtherMsgSequence();
+ int numOtherMsgs = otherMsgSeq.size();
+ if (!context.containsKey("numOfOtherMsgs")) {
+ context.put("numOfOtherMsgs", Integer.valueOf(numOtherMsgs));
+ for (int i = 0; i < numOtherMsgs; i++) {
+ OtherMsg omsg = (OtherMsg) (ASN1Util.decode(OtherMsg.getTemplate(),
+ ASN1Util.encode(otherMsgSeq.elementAt(i))));
+ context.put("otherMsg" + i, omsg);
+ }
+ }
+
+ int nummsgs = reqSeq.size();
+ if (nummsgs > 0) {
+ msgs = new TaggedRequest[reqSeq.size()];
+ SEQUENCE bpids = new SEQUENCE();
+ boolean valid = true;
+ for (int i = 0; i < nummsgs; i++) {
+ msgs[i] = (TaggedRequest) reqSeq.elementAt(i);
+ if (!context.containsKey("POPLinkWitness")) {
+ if (randomSeed != null) {
+ valid = verifyPOPLinkWitness(randomSeed, msgs[i], bpids);
+ if (!valid || bpids.size() > 0) {
+ context.put("POPLinkWitness", bpids);
+ return null;
+ }
+ }
+ }
+ }
+ } else
+ return null;
+
+ return msgs;
+ } catch (Exception e) {
+ CMS.debug("EnrollProfile: parseCMC " + e.toString());
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ }
+ }
+
+ private boolean verifyPOPLinkWitness(byte[] randomSeed, TaggedRequest req,
+ SEQUENCE bpids) {
+ ISharedToken tokenClass = null;
+ boolean sharedSecretFound = true;
+ String name = null;
+ try {
+ name = CMS.getConfigStore().getString("cmc.sharedSecret.class");
+ } catch (EPropertyNotFound e) {
+ CMS.debug("EnrollProfile: Failed to find the token class in the configuration file.");
+ sharedSecretFound = false;
+ } catch (EBaseException e) {
+ CMS.debug("EnrollProfile: Failed to find the token class in the configuration file.");
+ sharedSecretFound = false;
+ }
+
+ try {
+ tokenClass = (ISharedToken) Class.forName(name).newInstance();
+ } catch (ClassNotFoundException e) {
+ CMS.debug("EnrollProfile: Failed to find class name: " + name);
+ sharedSecretFound = false;
+ } catch (InstantiationException e) {
+ CMS.debug("EnrollProfile: Failed to instantiate class: " + name);
+ sharedSecretFound = false;
+ } catch (IllegalAccessException e) {
+ CMS.debug("EnrollProfile: Illegal access: " + name);
+ sharedSecretFound = false;
+ }
+
+ INTEGER reqId = null;
+ byte[] bv = null;
+ String sharedSecret = null;
+ if (tokenClass != null)
+ sharedSecret = tokenClass.getSharedToken(mCMCData);
+ if (req.getType().equals(TaggedRequest.PKCS10)) {
+ TaggedCertificationRequest tcr = req.getTcr();
+ if (!sharedSecretFound) {
+ bpids.addElement(tcr.getBodyPartID());
+ return false;
+ } else {
+ CertificationRequest creq = tcr.getCertificationRequest();
+ CertificationRequestInfo cinfo = creq.getInfo();
+ SET attrs = cinfo.getAttributes();
+ for (int j = 0; j < attrs.size(); j++) {
+ Attribute pkcs10Attr = (Attribute) attrs.elementAt(j);
+ if (pkcs10Attr.getType().equals(OBJECT_IDENTIFIER.id_cmc_idPOPLinkWitness)) {
+ SET witnessVal = pkcs10Attr.getValues();
+ if (witnessVal.size() > 0) {
+ try {
+ OCTET_STRING str =
+ (OCTET_STRING) (ASN1Util.decode(OCTET_STRING.getTemplate(),
+ ASN1Util.encode(witnessVal.elementAt(0))));
+ bv = str.toByteArray();
+ return verifyDigest(sharedSecret.getBytes(),
+ randomSeed, bv);
+ } catch (InvalidBERException ex) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+ } else if (req.getType().equals(TaggedRequest.CRMF)) {
+ CertReqMsg crm = req.getCrm();
+ CertRequest certReq = crm.getCertReq();
+ reqId = certReq.getCertReqId();
+ if (!sharedSecretFound) {
+ bpids.addElement(reqId);
+ return false;
+ } else {
+ for (int i = 0; i < certReq.numControls(); i++) {
+ AVA ava = certReq.controlAt(i);
+
+ if (ava.getOID().equals(OBJECT_IDENTIFIER.id_cmc_idPOPLinkWitness)) {
+ ASN1Value value = ava.getValue();
+ ByteArrayInputStream bis = new ByteArrayInputStream(
+ ASN1Util.encode(value));
+ OCTET_STRING ostr = null;
+ try {
+ ostr = (OCTET_STRING)
+ (new OCTET_STRING.Template()).decode(bis);
+ bv = ostr.toByteArray();
+ } catch (Exception e) {
+ bpids.addElement(reqId);
+ return false;
+ }
+
+ boolean valid = verifyDigest(sharedSecret.getBytes(),
+ randomSeed, bv);
+ if (!valid) {
+ bpids.addElement(reqId);
+ return valid;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private boolean verifyDigest(byte[] sharedSecret, byte[] text, byte[] bv) {
+ byte[] key = null;
+ try {
+ MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+ key = SHA1Digest.digest(sharedSecret);
+ } catch (NoSuchAlgorithmException ex) {
+ CMS.debug("EnrollProfile: No such algorithm for this message digest.");
+ return false;
+ }
+
+ byte[] finalDigest = null;
+ try {
+ MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+ HMACDigest hmacDigest = new HMACDigest(SHA1Digest, key);
+ hmacDigest.update(text);
+ finalDigest = hmacDigest.digest();
+ } catch (NoSuchAlgorithmException ex) {
+ CMS.debug("EnrollProfile: No such algorithm for this message digest.");
+ return false;
+ }
+
+ if (finalDigest.length != bv.length) {
+ CMS.debug("EnrollProfile: The length of two HMAC digest are not the same.");
+ return false;
+ }
+
+ for (int j = 0; j < bv.length; j++) {
+ if (bv[j] != finalDigest[j]) {
+ CMS.debug("EnrollProfile: The content of two HMAC digest are not the same.");
+ return false;
+ }
+ }
+
+ CMS.debug("EnrollProfile: The content of two HMAC digest are the same.");
+ return true;
+ }
+
+ private SEQUENCE getRequestBpids(SEQUENCE reqSeq) {
+ SEQUENCE bpids = new SEQUENCE();
+ for (int i = 0; i < reqSeq.size(); i++) {
+ TaggedRequest req = (TaggedRequest) reqSeq.elementAt(i);
+ if (req.getType().equals(TaggedRequest.PKCS10)) {
+ TaggedCertificationRequest tcr = req.getTcr();
+ bpids.addElement(tcr.getBodyPartID());
+ } else if (req.getType().equals(TaggedRequest.CRMF)) {
+ CertReqMsg crm = req.getCrm();
+ CertRequest request = crm.getCertReq();
+ bpids.addElement(request.getCertReqId());
+ }
+ }
+
+ return bpids;
+ }
+
+ private boolean verifyIdentityProof(TaggedAttribute attr, SEQUENCE reqSeq) {
+ SET vals = attr.getValues();
+ if (vals.size() < 1)
+ return false;
+ String name = null;
+ try {
+ name = CMS.getConfigStore().getString("cmc.sharedSecret.class");
+ } catch (EPropertyNotFound e) {
+ } catch (EBaseException e) {
+ }
+
+ if (name == null)
+ return false;
+ else {
+ ISharedToken tokenClass = null;
+ try {
+ tokenClass = (ISharedToken) Class.forName(name).newInstance();
+ } catch (ClassNotFoundException e) {
+ CMS.debug("EnrollProfile: Failed to find class name: " + name);
+ return false;
+ } catch (InstantiationException e) {
+ CMS.debug("EnrollProfile: Failed to instantiate class: " + name);
+ return false;
+ } catch (IllegalAccessException e) {
+ CMS.debug("EnrollProfile: Illegal access: " + name);
+ return false;
+ }
+
+ String token = tokenClass.getSharedToken(mCMCData);
+ OCTET_STRING ostr = null;
+ try {
+ ostr = (OCTET_STRING) (ASN1Util.decode(OCTET_STRING.getTemplate(),
+ ASN1Util.encode(vals.elementAt(0))));
+ } catch (InvalidBERException e) {
+ CMS.debug("EnrollProfile: Failed to decode the byte value.");
+ return false;
+ }
+ byte[] b = ostr.toByteArray();
+ byte[] text = ASN1Util.encode(reqSeq);
+
+ return verifyDigest(token.getBytes(), text, b);
+ }
+ }
+
+ public void fillTaggedRequest(Locale locale, TaggedRequest tagreq, X509CertInfo info,
+ IRequest req)
+ throws EProfileException {
+ TaggedRequest.Type type = tagreq.getType();
+ if (type == null) {
+ CMS.debug("EnrollProfile: fillTaggedRequest: TaggedRequest type == null");
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST")+
+ "TaggedRequest type null");
+ }
+
+ if (type.equals(TaggedRequest.PKCS10)) {
+ CMS.debug("EnrollProfile: fillTaggedRequest: TaggedRequest type == pkcs10");
+ boolean sigver = true;
+ boolean tokenSwitched = false;
+ CryptoManager cm = null;
+ CryptoToken signToken = null;
+ CryptoToken savedToken = null;
+ try {
+ sigver = CMS.getConfigStore().getBoolean("ca.requestVerify.enabled", true);
+ cm = CryptoManager.getInstance();
+ if (sigver == true) {
+ String tokenName =
+ CMS.getConfigStore().getString("ca.requestVerify.token", "internal");
+ savedToken = cm.getThreadToken();
+ if (tokenName.equals("internal")) {
+ signToken = cm.getInternalCryptoToken();
+ } else {
+ signToken = cm.getTokenByName(tokenName);
+ }
+ if (!savedToken.getName().equals(signToken.getName())) {
+ cm.setThreadToken(signToken);
+ tokenSwitched = true;
+ }
+ }
+
+ TaggedCertificationRequest tcr = tagreq.getTcr();
+ CertificationRequest p10 = tcr.getCertificationRequest();
+ ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+
+ p10.encode(ostream);
+ PKCS10 pkcs10 = new PKCS10(ostream.toByteArray(), sigver);
+
+ req.setExtData("bodyPartId", tcr.getBodyPartID());
+ fillPKCS10(locale, pkcs10, info, req);
+ } catch (Exception e) {
+ CMS.debug("EnrollProfile: fillTaggedRequest " +
+ e.toString());
+ } finally {
+ if ((sigver == true) && (tokenSwitched == true)){
+ cm.setThreadToken(savedToken);
+ }
+ }
+ } else if (type.equals(TaggedRequest.CRMF)) {
+ CMS.debug("EnrollProfile: fillTaggedRequest: TaggedRequest type == crmf");
+ CertReqMsg crm = tagreq.getCrm();
+ SessionContext context = SessionContext.getContext();
+ Integer nums = (Integer) (context.get("numOfControls"));
+
+ // check if the LRA POP Witness Control attribute exists
+ if (nums != null && nums.intValue() > 0) {
+ TaggedAttribute attr =
+ (TaggedAttribute) (context.get(OBJECT_IDENTIFIER.id_cmc_lraPOPWitness));
+ if (attr != null) {
+ parseLRAPopWitness(locale, crm, attr);
+ } else {
+ CMS.debug("EnrollProfile: verify POP in CMC because LRA POP Witness control attribute doesnt exist in the CMC request.");
+ verifyPOP(locale, crm);
+ }
+ } else {
+ CMS.debug("EnrollProfile: verify POP in CMC because LRA POP Witness control attribute doesnt exist in the CMC request.");
+ verifyPOP(locale, crm);
+ }
+
+ fillCertReqMsg(locale, crm, info, req);
+ } else {
+ CMS.debug("EnrollProfile: fillTaggedRequest: unsupported type (not CRMF or PKCS10)");
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ }
+ }
+
+ private void parseLRAPopWitness(Locale locale, CertReqMsg crm,
+ TaggedAttribute attr) throws EProfileException {
+ SET vals = attr.getValues();
+ boolean donePOP = false;
+ INTEGER reqId = null;
+ if (vals.size() > 0) {
+ LraPopWitness lraPop = null;
+ try {
+ lraPop = (LraPopWitness) (ASN1Util.decode(LraPopWitness.getTemplate(),
+ ASN1Util.encode(vals.elementAt(0))));
+ } catch (InvalidBERException e) {
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_ENCODING_ERROR"));
+ }
+
+ SEQUENCE bodyIds = lraPop.getBodyIds();
+ reqId = crm.getCertReq().getCertReqId();
+
+ for (int i = 0; i < bodyIds.size(); i++) {
+ INTEGER num = (INTEGER) (bodyIds.elementAt(i));
+ if (num.toString().equals(reqId.toString())) {
+ donePOP = true;
+ CMS.debug("EnrollProfile: skip POP for request: "
+ + reqId.toString() + " because LRA POP Witness control is found.");
+ break;
+ }
+ }
+ }
+
+ if (!donePOP) {
+ CMS.debug("EnrollProfile: not skip POP for request: "
+ + reqId.toString()
+ + " because this request id is not part of the body list in LRA Pop witness control.");
+ verifyPOP(locale, crm);
+ }
+ }
+
+ public CertReqMsg[] parseCRMF(Locale locale, String certreq)
+ throws EProfileException {
+
+ /* cert request must not be null */
+ if (certreq == null) {
+ CMS.debug("EnrollProfile: parseCRMF() certreq null");
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ }
+ CMS.debug("EnrollProfile: Start parseCRMF(): " + certreq);
+
+ CertReqMsg msgs[] = null;
+ String creq = normalizeCertReq(certreq);
+ try {
+ byte data[] = CMS.AtoB(creq);
+ ByteArrayInputStream crmfBlobIn =
+ new ByteArrayInputStream(data);
+ SEQUENCE crmfMsgs = (SEQUENCE)
+ new SEQUENCE.OF_Template(new
+ CertReqMsg.Template()).decode(crmfBlobIn);
+ int nummsgs = crmfMsgs.size();
+
+ if (nummsgs <= 0)
+ return null;
+ msgs = new CertReqMsg[crmfMsgs.size()];
+ for (int i = 0; i < nummsgs; i++) {
+ msgs[i] = (CertReqMsg) crmfMsgs.elementAt(i);
+ }
+ return msgs;
+ } catch (Exception e) {
+ CMS.debug("EnrollProfile: parseCRMF " + e.toString());
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ }
+ }
+
+ private static final OBJECT_IDENTIFIER PKIARCHIVEOPTIONS_OID =
+ new OBJECT_IDENTIFIER(new long[] { 1, 3, 6, 1, 5, 5, 7, 5, 1, 4 }
+ );
+
+ protected PKIArchiveOptions getPKIArchiveOptions(AVA ava) {
+ ASN1Value archVal = ava.getValue();
+ ByteArrayInputStream bis = new ByteArrayInputStream(
+ ASN1Util.encode(archVal));
+ PKIArchiveOptions archOpts = null;
+
+ try {
+ archOpts = (PKIArchiveOptions)
+ (new PKIArchiveOptions.Template()).decode(bis);
+ } catch (Exception e) {
+ CMS.debug("EnrollProfile: getPKIArchiveOptions " + e.toString());
+ }
+ return archOpts;
+ }
+
+ public PKIArchiveOptions toPKIArchiveOptions(byte options[]) {
+ ByteArrayInputStream bis = new ByteArrayInputStream(options);
+ PKIArchiveOptions archOpts = null;
+
+ try {
+ archOpts = (PKIArchiveOptions)
+ (new PKIArchiveOptions.Template()).decode(bis);
+ } catch (Exception e) {
+ CMS.debug("EnrollProfile: toPKIArchiveOptions " + e.toString());
+ }
+ return archOpts;
+ }
+
+ public byte[] toByteArray(PKIArchiveOptions options) {
+ return ASN1Util.encode(options);
+ }
+
+ public void fillCertReqMsg(Locale locale, CertReqMsg certReqMsg, X509CertInfo info,
+ IRequest req)
+ throws EProfileException {
+ try {
+ CMS.debug("Start parseCertReqMsg ");
+ CertRequest certReq = certReqMsg.getCertReq();
+ req.setExtData("bodyPartId", certReq.getCertReqId());
+ // handle PKIArchiveOption (key archival)
+ for (int i = 0; i < certReq.numControls(); i++) {
+ AVA ava = certReq.controlAt(i);
+
+ if (ava.getOID().equals(PKIARCHIVEOPTIONS_OID)) {
+ PKIArchiveOptions opt = getPKIArchiveOptions(ava);
+
+ //req.set(REQUEST_ARCHIVE_OPTIONS, opt);
+ req.setExtData(REQUEST_ARCHIVE_OPTIONS,
+ toByteArray(opt));
+ try {
+ String transportCert = CMS.getConfigStore().getString("ca.connector.KRA.transportCert", "");
+ req.setExtData(IEnrollProfile.REQUEST_TRANSPORT_CERT, transportCert);
+ } catch (EBaseException ee) {
+ CMS.debug("EnrollProfile: fillCertReqMsg - Exception reading transportCert: "+ ee);
+ }
+ }
+ }
+
+ CertTemplate certTemplate = certReq.getCertTemplate();
+
+ // parse key
+ SubjectPublicKeyInfo spki = certTemplate.getPublicKey();
+ ByteArrayOutputStream keyout = new ByteArrayOutputStream();
+
+ spki.encode(keyout);
+ byte[] keybytes = keyout.toByteArray();
+ X509Key key = new X509Key();
+
+ key.decode(keybytes);
+
+ // XXX - kmccarth - this may simply undo the decoding above
+ // but for now it's unclear whether X509Key
+ // changest the format when decoding.
+ CertificateX509Key certKey = new CertificateX509Key(key);
+ ByteArrayOutputStream certKeyOut = new ByteArrayOutputStream();
+ certKey.encode(certKeyOut);
+ req.setExtData(REQUEST_KEY, certKeyOut.toByteArray());
+
+ // parse validity
+ if (certTemplate.getNotBefore() != null ||
+ certTemplate.getNotAfter() != null) {
+ CMS.debug("EnrollProfile: requested notBefore: " + certTemplate.getNotBefore());
+ CMS.debug("EnrollProfile: requested notAfter: " + certTemplate.getNotAfter());
+ CMS.debug("EnrollProfile: current CA time: " + new Date());
+ CertificateValidity certValidity = new CertificateValidity(
+ certTemplate.getNotBefore(), certTemplate.getNotAfter());
+ ByteArrayOutputStream certValidityOut =
+ new ByteArrayOutputStream();
+ certValidity.encode(certValidityOut);
+ req.setExtData(REQUEST_VALIDITY, certValidityOut.toByteArray());
+ } else {
+ CMS.debug("EnrollProfile: validity not supplied");
+ }
+
+ // parse subject
+ if (certTemplate.hasSubject()) {
+ Name subjectdn = certTemplate.getSubject();
+ ByteArrayOutputStream subjectEncStream =
+ new ByteArrayOutputStream();
+
+ subjectdn.encode(subjectEncStream);
+ byte[] subjectEnc = subjectEncStream.toByteArray();
+ X500Name subject = new X500Name(subjectEnc);
+
+ //info.set(X509CertInfo.SUBJECT,
+ // new CertificateSubjectName(subject));
+
+ req.setExtData(REQUEST_SUBJECT_NAME,
+ new CertificateSubjectName(subject));
+ try {
+ String subjectCN = subject.getCommonName();
+ if (subjectCN == null)
+ subjectCN = "";
+ req.setExtData(REQUEST_SUBJECT_NAME + ".cn", subjectCN);
+ } catch (Exception ee) {
+ req.setExtData(REQUEST_SUBJECT_NAME + ".cn", "");
+ }
+ try {
+ String subjectUID = subject.getUserID();
+ if (subjectUID == null)
+ subjectUID = "";
+ req.setExtData(REQUEST_SUBJECT_NAME + ".uid", subjectUID);
+ } catch (Exception ee) {
+ req.setExtData(REQUEST_SUBJECT_NAME + ".uid", "");
+ }
+ }
+
+ // parse extensions
+ CertificateExtensions extensions = null;
+
+ // try {
+ extensions = req.getExtDataInCertExts(REQUEST_EXTENSIONS);
+ // } catch (CertificateException e) {
+ // extensions = null;
+ // } catch (IOException e) {
+ // extensions = null;
+ // }
+ if (certTemplate.hasExtensions()) {
+ // put each extension from CRMF into CertInfo.
+ // index by extension name, consistent with
+ // CertificateExtensions.parseExtension() method.
+ if (extensions == null)
+ extensions = new CertificateExtensions();
+ int numexts = certTemplate.numExtensions();
+
+ for (int j = 0; j < numexts; j++) {
+ org.mozilla.jss.pkix.cert.Extension jssext =
+ certTemplate.extensionAt(j);
+ boolean isCritical = jssext.getCritical();
+ org.mozilla.jss.asn1.OBJECT_IDENTIFIER jssoid =
+ jssext.getExtnId();
+ long[] numbers = jssoid.getNumbers();
+ int[] oidNumbers = new int[numbers.length];
+
+ for (int k = numbers.length - 1; k >= 0; k--) {
+ oidNumbers[k] = (int) numbers[k];
+ }
+ ObjectIdentifier oid =
+ new ObjectIdentifier(oidNumbers);
+ org.mozilla.jss.asn1.OCTET_STRING jssvalue =
+ jssext.getExtnValue();
+ ByteArrayOutputStream jssvalueout =
+ new ByteArrayOutputStream();
+
+ jssvalue.encode(jssvalueout);
+ byte[] extValue = jssvalueout.toByteArray();
+
+ Extension ext =
+ new Extension(oid, isCritical, extValue);
+
+ extensions.parseExtension(ext);
+ }
+ // info.set(X509CertInfo.EXTENSIONS, extensions);
+ req.setExtData(REQUEST_EXTENSIONS, extensions);
+
+ }
+ } catch (IOException e) {
+ CMS.debug("EnrollProfile: fillCertReqMsg " + e.toString());
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ } catch (InvalidKeyException e) {
+ CMS.debug("EnrollProfile: fillCertReqMsg " + e.toString());
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ // } catch (CertificateException e) {
+ // CMS.debug("EnrollProfile: fillCertReqMsg " + e.toString());
+ // throw new EProfileException(e.toString());
+ }
+ }
+
+ public PKCS10 parsePKCS10(Locale locale, String certreq)
+ throws EProfileException {
+ /* cert request must not be null */
+ if (certreq == null) {
+ CMS.debug("EnrollProfile:parsePKCS10() certreq null");
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ }
+ CMS.debug("Start parsePKCS10(): " + certreq);
+
+ // trim header and footer
+ String creq = normalizeCertReq(certreq);
+
+ // parse certificate into object
+ byte data[] = CMS.AtoB(creq);
+ PKCS10 pkcs10 = null;
+ CryptoManager cm = null;
+ CryptoToken savedToken = null;
+ boolean sigver = true;
+
+ try {
+ cm = CryptoManager.getInstance();
+ sigver = CMS.getConfigStore().getBoolean("ca.requestVerify.enabled", true);
+ if (sigver) {
+ CMS.debug("EnrollProfile: parsePKCS10: signature verification enabled");
+ String tokenName = CMS.getConfigStore().getString("ca.requestVerify.token", "internal");
+ savedToken = cm.getThreadToken();
+ CryptoToken signToken = null;
+ if (tokenName.equals("internal")) {
+ CMS.debug("EnrollProfile: parsePKCS10: use internal token");
+ signToken = cm.getInternalCryptoToken();
+ } else {
+ CMS.debug("EnrollProfile: parsePKCS10: tokenName=" + tokenName);
+ signToken = cm.getTokenByName(tokenName);
+ }
+ CMS.debug("EnrollProfile: parsePKCS10 setting thread token");
+ cm.setThreadToken(signToken);
+ pkcs10 = new PKCS10(data);
+ } else {
+ CMS.debug("EnrollProfile: parsePKCS10: signature verification disabled");
+ pkcs10 = new PKCS10(data, sigver);
+ }
+ } catch (Exception e) {
+ CMS.debug("EnrollProfile: parsePKCS10 " + e.toString());
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ } finally {
+ if (sigver) {
+ CMS.debug("EnrollProfile: parsePKCS10 restoring thread token");
+ cm.setThreadToken(savedToken);
+ }
+ }
+
+ return pkcs10;
+ }
+
+ public void fillPKCS10(Locale locale, PKCS10 pkcs10, X509CertInfo info, IRequest req)
+ throws EProfileException {
+ X509Key key = pkcs10.getSubjectPublicKeyInfo();
+
+ try {
+ CertificateX509Key certKey = new CertificateX509Key(key);
+ ByteArrayOutputStream certKeyOut = new ByteArrayOutputStream();
+ certKey.encode(certKeyOut);
+ req.setExtData(IEnrollProfile.REQUEST_KEY, certKeyOut.toByteArray());
+
+ req.setExtData(EnrollProfile.REQUEST_SUBJECT_NAME,
+ new CertificateSubjectName(pkcs10.getSubjectName()));
+ try {
+ String subjectCN = pkcs10.getSubjectName().getCommonName();
+ if (subjectCN == null)
+ subjectCN = "";
+ req.setExtData(REQUEST_SUBJECT_NAME + ".cn", subjectCN);
+ } catch (Exception ee) {
+ req.setExtData(REQUEST_SUBJECT_NAME + ".cn", "");
+ }
+ try {
+ String subjectUID = pkcs10.getSubjectName().getUserID();
+ if (subjectUID == null)
+ subjectUID = "";
+ req.setExtData(REQUEST_SUBJECT_NAME + ".uid", subjectUID);
+ } catch (Exception ee) {
+ req.setExtData(REQUEST_SUBJECT_NAME + ".uid", "");
+ }
+
+ info.set(X509CertInfo.KEY, certKey);
+
+ PKCS10Attributes p10Attrs = pkcs10.getAttributes();
+ if (p10Attrs != null) {
+ PKCS10Attribute p10Attr = p10Attrs.getAttribute(CertificateExtensions.NAME);
+ if (p10Attr != null && p10Attr.getAttributeId().equals(
+ PKCS9Attribute.EXTENSION_REQUEST_OID)) {
+ CMS.debug("Found PKCS10 extension");
+ Extensions exts0 = (Extensions)
+ (p10Attr.getAttributeValue());
+ DerOutputStream extOut = new DerOutputStream();
+
+ exts0.encode(extOut);
+ byte[] extB = extOut.toByteArray();
+ DerInputStream extIn = new DerInputStream(extB);
+ CertificateExtensions exts = new CertificateExtensions(extIn);
+ if (exts != null) {
+ CMS.debug("Set extensions " + exts);
+ // info.set(X509CertInfo.EXTENSIONS, exts);
+ req.setExtData(REQUEST_EXTENSIONS, exts);
+ }
+ } else {
+ CMS.debug("PKCS10 extension Not Found");
+ }
+ }
+
+ CMS.debug("Finish parsePKCS10 - " + pkcs10.getSubjectName());
+ } catch (IOException e) {
+ CMS.debug("EnrollProfile: fillPKCS10 " + e.toString());
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ } catch (CertificateException e) {
+ CMS.debug("EnrollProfile: fillPKCS10 " + e.toString());
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ }
+ }
+
+ // for netkey
+ public void fillNSNKEY(Locale locale, String sn, String skey, X509CertInfo info, IRequest req)
+ throws EProfileException {
+
+ try {
+ //cfu - is the algorithm going to be replaced by the policy?
+ X509Key key = new X509Key();
+ key.decode(CMS.AtoB(skey));
+
+ info.set(X509CertInfo.KEY, new CertificateX509Key(key));
+ // req.set(EnrollProfile.REQUEST_SUBJECT_NAME,
+ // new CertificateSubjectName(new
+ // X500Name("CN="+sn)));
+ req.setExtData("screenname", sn);
+ // keeping "aoluid" to be backward compatible
+ req.setExtData("aoluid", sn);
+ req.setExtData("uid", sn);
+ CMS.debug("EnrollPrifile: fillNSNKEY(): uid=" + sn);
+
+ } catch (Exception e) {
+ CMS.debug("EnrollProfile: fillNSNKEY(): " + e.toString());
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ }
+ }
+
+ // for house key
+ public void fillNSHKEY(Locale locale, String tcuid, String skey, X509CertInfo info, IRequest req)
+ throws EProfileException {
+
+ try {
+ //cfu - is the algorithm going to be replaced by the policy?
+ X509Key key = new X509Key();
+ key.decode(CMS.AtoB(skey));
+
+ info.set(X509CertInfo.KEY, new CertificateX509Key(key));
+ // req.set(EnrollProfile.REQUEST_SUBJECT_NAME,
+ // new CertificateSubjectName(new
+ // X500Name("CN="+sn)));
+ req.setExtData("tokencuid", tcuid);
+
+ CMS.debug("EnrollPrifile: fillNSNKEY(): tokencuid=" + tcuid);
+
+ } catch (Exception e) {
+ CMS.debug("EnrollProfile: fillNSHKEY(): " + e.toString());
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ }
+ }
+
+ public DerInputStream parseKeyGen(Locale locale, String certreq)
+ throws EProfileException {
+ byte data[] = CMS.AtoB(certreq);
+
+ DerInputStream derIn = new DerInputStream(data);
+
+ return derIn;
+ }
+
+ public void fillKeyGen(Locale locale, DerInputStream derIn, X509CertInfo info, IRequest req
+ )
+ throws EProfileException {
+ try {
+
+ /* get SPKAC Algorithm & Signature */
+ DerValue derSPKACContent[] = derIn.getSequence(3);
+ @SuppressWarnings("unused")
+ AlgorithmId mAlgId = AlgorithmId.parse(derSPKACContent[1]);
+ @SuppressWarnings("unused")
+ byte mSignature[] = derSPKACContent[2].getBitString();
+
+ /* get PKAC SPKI & Challenge */
+ byte mPKAC[] = derSPKACContent[0].toByteArray();
+
+ derIn = new DerInputStream(mPKAC);
+ DerValue derPKACContent[] = derIn.getSequence(2);
+
+ @SuppressWarnings("unused")
+ DerValue mDerSPKI = derPKACContent[0];
+ X509Key mSPKI = X509Key.parse(derPKACContent[0]);
+
+ @SuppressWarnings("unused")
+ String mChallenge;
+ DerValue mDerChallenge = derPKACContent[1];
+
+ if (mDerChallenge.length() != 0)
+ mChallenge = derPKACContent[1].getIA5String();
+
+ CertificateX509Key certKey = new CertificateX509Key(mSPKI);
+ ByteArrayOutputStream certKeyOut = new ByteArrayOutputStream();
+ certKey.encode(certKeyOut);
+ req.setExtData(IEnrollProfile.REQUEST_KEY, certKeyOut.toByteArray());
+ info.set(X509CertInfo.KEY, certKey);
+ } catch (IOException e) {
+ CMS.debug("EnrollProfile: fillKeyGen " + e.toString());
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ } catch (CertificateException e) {
+ CMS.debug("EnrollProfile: fillKeyGen " + e.toString());
+ throw new EProfileException(
+ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"));
+ }
+ }
+
+ public String normalizeCertReq(String s) {
+ if (s == null) {
+ return s;
+ }
+ s = s.replaceAll("-----BEGIN CERTIFICATE REQUEST-----", "");
+ s = s.replaceAll("-----BEGIN NEW CERTIFICATE REQUEST-----", "");
+ s = s.replaceAll("-----END CERTIFICATE REQUEST-----", "");
+ s = s.replaceAll("-----END NEW CERTIFICATE REQUEST-----", "");
+
+ StringBuffer sb = new StringBuffer();
+ StringTokenizer st = new StringTokenizer(s, "\r\n ");
+
+ while (st.hasMoreTokens()) {
+ String nextLine = st.nextToken();
+
+ nextLine = nextLine.trim();
+ if (nextLine.equals("-----BEGIN CERTIFICATE REQUEST-----"))
+ continue;
+ if (nextLine.equals("-----BEGIN NEW CERTIFICATE REQUEST-----"))
+ continue;
+ if (nextLine.equals("-----END CERTIFICATE REQUEST-----"))
+ continue;
+ if (nextLine.equals("-----END NEW CERTIFICATE REQUEST-----"))
+ continue;
+ sb.append(nextLine);
+ }
+ return sb.toString();
+ }
+
+ public Locale getLocale(IRequest request) {
+ Locale locale = null;
+ String language = request.getExtDataInString(
+ EnrollProfile.REQUEST_LOCALE);
+ if (language != null) {
+ locale = new Locale(language);
+ }
+ return locale;
+ }
+
+ /**
+ * Populate input
+ * <P>
+ *
+ * (either all "agent" profile cert requests NOT made through a connector, or all "EE" profile cert requests NOT
+ * made through a connector)
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST used when a profile cert request is made (before
+ * approval process)
+ * </ul>
+ *
+ * @param ctx profile context
+ * @param request the certificate request
+ * @exception EProfileException an error related to this profile has
+ * occurred
+ */
+ public void populateInput(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ super.populateInput(ctx, request);
+ }
+
+ public void populate(IRequest request)
+ throws EProfileException {
+ super.populate(request);
+
+ }
+
+ /**
+ * Passes the request to the set of constraint policies
+ * that validate the request against the profile.
+ */
+ public void validate(IRequest request)
+ throws ERejectException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRequesterID = auditRequesterID(request);
+ String auditProfileID = auditProfileID();
+ String auditCertificateSubjectName = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ String subject = null;
+
+ // try {
+ X509CertInfo info = request.getExtDataInCertInfo(REQUEST_CERTINFO);
+
+ try {
+ CertificateSubjectName sn = (CertificateSubjectName)
+ info.get(X509CertInfo.SUBJECT);
+
+ // if the cert subject name is NOT MISSING, retrieve the
+ // actual "auditCertificateSubjectName" and "normalize" it
+ if (sn != null) {
+ subject = sn.toString();
+ if (subject != null) {
+ // NOTE: This is ok even if the cert subject name
+ // is "" (empty)!
+ auditCertificateSubjectName = subject.trim();
+ }
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditProfileID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+ } catch (CertificateException e) {
+ CMS.debug("EnrollProfile: populate " + e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditProfileID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+ } catch (IOException e) {
+ CMS.debug("EnrollProfile: populate " + e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditProfileID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+ }
+
+ super.validate(request);
+ Object key = null;
+
+ try {
+ key = info.get(X509CertInfo.KEY);
+ } catch (CertificateException e) {
+ } catch (IOException e) {
+ }
+
+ if (key == null) {
+ Locale locale = getLocale(request);
+
+ throw new ERejectException(CMS.getUserMessage(
+ locale, "CMS_PROFILE_EMPTY_KEY"));
+ }
+
+ try {
+ CMS.debug("EnrollProfile certInfo : " + info);
+ } catch (NullPointerException e) {
+ // do nothing
+ }
+ }
+
+ /**
+ * Signed Audit Log Requester ID
+ *
+ * This method is inherited by all extended "EnrollProfile"s,
+ * and is called to obtain the "RequesterID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param request the actual request
+ * @return id string containing the signed audit log message RequesterID
+ */
+ protected String auditRequesterID(IRequest request) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String requesterID = ILogger.UNIDENTIFIED;
+
+ if (request != null) {
+ // overwrite "requesterID" if and only if "id" != null
+ String id = request.getRequestId().toString();
+
+ if (id != null) {
+ requesterID = id.trim();
+ }
+ }
+
+ return requesterID;
+ }
+
+ /**
+ * Signed Audit Log Profile ID
+ *
+ * This method is inherited by all extended "EnrollProfile"s,
+ * and is called to obtain the "ProfileID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @return id string containing the signed audit log message ProfileID
+ */
+ protected String auditProfileID() {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String profileID = getId();
+
+ if (profileID != null) {
+ profileID = profileID.trim();
+ } else {
+ profileID = ILogger.UNIDENTIFIED;
+ }
+
+ return profileID;
+ }
+
+ public void verifyPOP(Locale locale, CertReqMsg certReqMsg)
+ throws EProfileException {
+ CMS.debug("EnrollProfile ::in verifyPOP");
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ if (!certReqMsg.hasPop()) {
+ return;
+ }
+ ProofOfPossession pop = certReqMsg.getPop();
+ ProofOfPossession.Type popType = pop.getType();
+
+ if (popType != ProofOfPossession.SIGNATURE) {
+ return;
+ }
+
+ try {
+ CryptoManager cm = CryptoManager.getInstance();
+ CryptoToken verifyToken = null;
+ String tokenName = CMS.getConfigStore().getString("ca.requestVerify.token", "internal");
+ if (tokenName.equals("internal")) {
+ CMS.debug("POP verification using internal token");
+ certReqMsg.verify();
+ } else {
+ CMS.debug("POP verification using token:" + tokenName);
+ verifyToken = cm.getTokenByName(tokenName);
+ certReqMsg.verify(verifyToken);
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION,
+ auditSubjectID,
+ ILogger.SUCCESS);
+ audit(auditMessage);
+ } catch (Exception e) {
+
+ CMS.debug("Failed POP verify! " + e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ throw new EProfileException(CMS.getUserMessage(locale,
+ "CMS_POP_VERIFICATION_ERROR"));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfileContext.java b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfileContext.java
new file mode 100644
index 000000000..444024b94
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfileContext.java
@@ -0,0 +1,31 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.common;
+
+import com.netscape.certsrv.profile.IProfileContext;
+
+/**
+ * This class implements an enrollment profile context
+ * that carries information for request creation.
+ *
+ * @version $Revision$, $Date$
+ */
+public class EnrollProfileContext extends ProfileContext
+ implements IProfileContext {
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/ProfileContext.java b/base/server/cms/src/com/netscape/cms/profile/common/ProfileContext.java
new file mode 100644
index 000000000..d07cdfc27
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/common/ProfileContext.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.common;
+
+import java.util.Hashtable;
+
+import com.netscape.certsrv.profile.IProfileContext;
+
+/**
+ * This class implements the profile context.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ProfileContext implements IProfileContext {
+ private Hashtable<String, String> m_Attrs = new Hashtable<String, String>();
+
+ public void set(String name, String value) {
+ m_Attrs.put(name, value);
+ }
+
+ public String get(String name) {
+ return m_Attrs.get(name);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/ProfilePolicy.java b/base/server/cms/src/com/netscape/cms/profile/common/ProfilePolicy.java
new file mode 100644
index 000000000..157914927
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/common/ProfilePolicy.java
@@ -0,0 +1,53 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.common;
+
+import com.netscape.certsrv.profile.IPolicyConstraint;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfilePolicy;
+
+/**
+ * This class implements a profile policy that
+ * contains a default policy and a constraint
+ * policy.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ProfilePolicy implements IProfilePolicy {
+ private String mId = null;
+ private IPolicyDefault mDefault = null;
+ private IPolicyConstraint mConstraint = null;
+
+ public ProfilePolicy(String id, IPolicyDefault def, IPolicyConstraint constraint) {
+ mId = id;
+ mDefault = def;
+ mConstraint = constraint;
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ public IPolicyDefault getDefault() {
+ return mDefault;
+ }
+
+ public IPolicyConstraint getConstraint() {
+ return mConstraint;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/RAEnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/RAEnrollProfile.java
new file mode 100644
index 000000000..1fe2fa514
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/common/RAEnrollProfile.java
@@ -0,0 +1,128 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.common;
+
+import java.util.Enumeration;
+
+import netscape.security.x509.X500Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.connector.IConnector;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.ra.IRAService;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestListener;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestStatus;
+
+/**
+ * This class implements a Registration Manager
+ * enrollment profile.
+ *
+ * @version $Revision$, $Date$
+ */
+public class RAEnrollProfile extends EnrollProfile {
+
+ public RAEnrollProfile() {
+ super();
+ }
+
+ public IAuthority getAuthority() {
+ IAuthority authority = (IAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_RA);
+
+ if (authority == null)
+ return null;
+ return authority;
+ }
+
+ public X500Name getIssuerName() {
+ IRegistrationAuthority ra = (IRegistrationAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_RA);
+ X500Name issuerName = ra.getX500Name();
+
+ return issuerName;
+ }
+
+ public void execute(IRequest request)
+ throws EProfileException {
+
+ if (!isEnable()) {
+ CMS.debug("CAEnrollProfile: Profile Not Enabled");
+ throw new EProfileException("Profile Not Enabled");
+ }
+
+ IRegistrationAuthority ra =
+ (IRegistrationAuthority) getAuthority();
+ IRAService raService = ra.getRAService();
+
+ if (raService == null) {
+ throw new EProfileException("No RA Service");
+ }
+
+ IRequestQueue queue = ra.getRequestQueue();
+
+ // send request to CA
+ try {
+ IConnector caConnector = raService.getCAConnector();
+
+ if (caConnector == null) {
+ CMS.debug("RAEnrollProfile: CA connector not configured");
+ } else {
+ caConnector.send(request);
+ // check response
+ if (!request.isSuccess()) {
+ CMS.debug("RAEnrollProfile error talking to CA setting req status to SVC_PENDING");
+
+ request.setRequestStatus(RequestStatus.SVC_PENDING);
+
+ try {
+ queue.updateRequest(request);
+ } catch (EBaseException e) {
+ CMS.debug("RAEnrollProfile: Update request " + e.toString());
+ }
+ throw new ERejectException(
+ request.getError(getLocale(request)));
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("RAEnrollProfile: " + e.toString());
+ throw new EProfileException(e.toString());
+ }
+
+ // request handling
+ Enumeration<String> names = ra.getRequestListenerNames();
+
+ if (names != null) {
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+
+ CMS.debug("CAEnrollProfile: listener " + name);
+ IRequestListener listener = ra.getRequestListener(name);
+
+ if (listener != null) {
+ listener.accept(request);
+ }
+ }
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/ServerCertCAEnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/ServerCertCAEnrollProfile.java
new file mode 100644
index 000000000..a1a83a49f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/common/ServerCertCAEnrollProfile.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.common;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfileEx;
+import com.netscape.certsrv.profile.IProfilePolicy;
+
+/**
+ * This class implements a Certificate Manager enrollment
+ * profile for Server Certificates.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ServerCertCAEnrollProfile extends CAEnrollProfile
+ implements IProfileEx {
+
+ /**
+ * Called after initialization. It populates default
+ * policies, inputs, and outputs.
+ */
+ public void populate() throws EBaseException {
+ // create inputs
+ NameValuePairs inputParams1 = new NameValuePairs();
+ createProfileInput("i1", "certReqInputImpl", inputParams1);
+ NameValuePairs inputParams2 = new NameValuePairs();
+ createProfileInput("i2", "submitterInfoInputImpl", inputParams2);
+
+ // create outputs
+ NameValuePairs outputParams1 = new NameValuePairs();
+ createProfileOutput("o1", "certOutputImpl", outputParams1);
+
+ createProfilePolicy("set1", "p1",
+ "userSubjectNameDefaultImpl", "noConstraintImpl");
+
+ IProfilePolicy policy2 =
+ createProfilePolicy("set1", "p2",
+ "validityDefaultImpl", "noConstraintImpl");
+ IPolicyDefault def2 = policy2.getDefault();
+ IConfigStore defConfig2 = def2.getConfigStore();
+ defConfig2.putString("params.range", "180");
+ defConfig2.putString("params.startTime", "0");
+
+ IProfilePolicy policy3 =
+ createProfilePolicy("set1", "p3",
+ "userKeyDefaultImpl", "noConstraintImpl");
+ IPolicyDefault def3 = policy3.getDefault();
+ IConfigStore defConfig3 = def3.getConfigStore();
+ defConfig3.putString("params.keyType", "RSA");
+ defConfig3.putString("params.keyMinLength", "512");
+ defConfig3.putString("params.keyMaxLength", "4096");
+
+ IProfilePolicy policy4 =
+ createProfilePolicy("set1", "p4",
+ "signingAlgDefaultImpl", "noConstraintImpl");
+ IPolicyDefault def4 = policy4.getDefault();
+ IConfigStore defConfig4 = def4.getConfigStore();
+ defConfig4.putString("params.signingAlg", "-");
+ defConfig4
+ .putString(
+ "params.signingAlgsAllowed",
+ "SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withEC,SHA256withEC,SHA384withEC,SHA512withEC");
+
+ IProfilePolicy policy5 =
+ createProfilePolicy("set1", "p5",
+ "keyUsageExtDefaultImpl", "noConstraintImpl");
+ IPolicyDefault def5 = policy5.getDefault();
+ IConfigStore defConfig5 = def5.getConfigStore();
+ defConfig5.putString("params.keyUsageCritical", "true");
+ defConfig5.putString("params.keyUsageCrlSign", "false");
+ defConfig5.putString("params.keyUsageDataEncipherment", "true");
+ defConfig5.putString("params.keyUsageDecipherOnly", "false");
+ defConfig5.putString("params.keyUsageDigitalSignature", "true");
+ defConfig5.putString("params.keyUsageEncipherOnly", "false");
+ defConfig5.putString("params.keyUsageKeyAgreement", "false");
+ defConfig5.putString("params.keyUsageKeyCertSign", "false");
+ defConfig5.putString("params.keyUsageKeyEncipherment", "true");
+ defConfig5.putString("params.keyUsageNonRepudiation", "true");
+
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/UserCertCAEnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/UserCertCAEnrollProfile.java
new file mode 100644
index 000000000..710a4616d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/common/UserCertCAEnrollProfile.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.common;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfileEx;
+import com.netscape.certsrv.profile.IProfilePolicy;
+
+/**
+ * This class implements a Certificate Manager enrollment
+ * profile for User Certificates.
+ *
+ * @version $Revision$, $Date$
+ */
+public class UserCertCAEnrollProfile extends CAEnrollProfile
+ implements IProfileEx {
+
+ /**
+ * Called after initialization. It populates default
+ * policies, inputs, and outputs.
+ */
+ public void populate() throws EBaseException {
+ // create inputs
+ NameValuePairs inputParams1 = new NameValuePairs();
+ createProfileInput("i1", "keyGenInputImpl", inputParams1);
+ NameValuePairs inputParams2 = new NameValuePairs();
+ createProfileInput("i2", "subjectNameInputImpl", inputParams2);
+ createProfileInput("i3", "submitterInfoInputImpl", inputParams2);
+
+ // create outputs
+ NameValuePairs outputParams1 = new NameValuePairs();
+ createProfileOutput("o1", "certOutputImpl", outputParams1);
+
+ // create policies
+ createProfilePolicy("set1", "p1",
+ "userSubjectNameDefaultImpl", "noConstraintImpl");
+
+ IProfilePolicy policy2 =
+ createProfilePolicy("set1", "p2",
+ "validityDefaultImpl", "noConstraintImpl");
+ IPolicyDefault def2 = policy2.getDefault();
+ IConfigStore defConfig2 = def2.getConfigStore();
+ defConfig2.putString("params.range", "180");
+ defConfig2.putString("params.startTime", "0");
+
+ IProfilePolicy policy3 =
+ createProfilePolicy("set1", "p3",
+ "userKeyDefaultImpl", "noConstraintImpl");
+ IPolicyDefault def3 = policy3.getDefault();
+ IConfigStore defConfig3 = def3.getConfigStore();
+ defConfig3.putString("params.keyType", "RSA");
+ defConfig3.putString("params.keyMinLength", "512");
+ defConfig3.putString("params.keyMaxLength", "4096");
+
+ IProfilePolicy policy4 =
+ createProfilePolicy("set1", "p4",
+ "signingAlgDefaultImpl", "noConstraintImpl");
+ IPolicyDefault def4 = policy4.getDefault();
+ IConfigStore defConfig4 = def4.getConfigStore();
+ defConfig4.putString("params.signingAlg", "-");
+ defConfig4
+ .putString(
+ "params.signingAlgsAllowed",
+ "SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withEC,SHA256withEC,SHA384withEC,SHA512withEC");
+
+ IProfilePolicy policy5 =
+ createProfilePolicy("set1", "p5",
+ "keyUsageExtDefaultImpl", "noConstraintImpl");
+ IPolicyDefault def5 = policy5.getDefault();
+ IConfigStore defConfig5 = def5.getConfigStore();
+ defConfig5.putString("params.keyUsageCritical", "true");
+ defConfig5.putString("params.keyUsageCrlSign", "false");
+ defConfig5.putString("params.keyUsageDataEncipherment", "false");
+ defConfig5.putString("params.keyUsageDecipherOnly", "false");
+ defConfig5.putString("params.keyUsageDigitalSignature", "true");
+ defConfig5.putString("params.keyUsageEncipherOnly", "false");
+ defConfig5.putString("params.keyUsageKeyAgreement", "false");
+ defConfig5.putString("params.keyUsageKeyCertSign", "false");
+ defConfig5.putString("params.keyUsageKeyEncipherment", "true");
+ defConfig5.putString("params.keyUsageNonRepudiation", "true");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/BasicConstraintsExtConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/BasicConstraintsExtConstraint.java
new file mode 100644
index 000000000..ca2668f7d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/BasicConstraintsExtConstraint.java
@@ -0,0 +1,224 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.def.BasicConstraintsExtDefault;
+import com.netscape.cms.profile.def.NoDefault;
+import com.netscape.cms.profile.def.UserExtensionDefault;
+
+/**
+ * This class implements the basic constraints extension constraint.
+ * It checks if the basic constraint in the certificate
+ * template satisfies the criteria.
+ *
+ * @version $Revision$, $Date$
+ */
+public class BasicConstraintsExtConstraint extends EnrollConstraint {
+
+ public static final String CONFIG_CRITICAL =
+ "basicConstraintsCritical";
+ public static final String CONFIG_IS_CA =
+ "basicConstraintsIsCA";
+ public static final String CONFIG_MIN_PATH_LEN =
+ "basicConstraintsMinPathLen";
+ public static final String CONFIG_MAX_PATH_LEN =
+ "basicConstraintsMaxPathLen";
+
+ public BasicConstraintsExtConstraint() {
+ super();
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_IS_CA);
+ addConfigName(CONFIG_MIN_PATH_LEN);
+ addConfigName(CONFIG_MAX_PATH_LEN);
+ }
+
+ /**
+ * Initializes this constraint plugin.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(CONFIG_IS_CA)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_IS_CA"));
+ } else if (name.equals(CONFIG_MIN_PATH_LEN)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "-1",
+ CMS.getUserMessage(locale, "CMS_PROFILE_MIN_PATH_LEN"));
+ } else if (name.equals(CONFIG_MAX_PATH_LEN)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "100",
+ CMS.getUserMessage(locale, "CMS_PROFILE_MAX_PATH_LEN"));
+ }
+ return null;
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ */
+ public void validate(IRequest request, X509CertInfo info)
+ throws ERejectException {
+
+ try {
+ BasicConstraintsExtension ext = (BasicConstraintsExtension)
+ getExtension(PKIXExtensions.BasicConstraints_Id.toString(),
+ info);
+
+ if (ext == null) {
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_EXTENSION_NOT_FOUND",
+ PKIXExtensions.BasicConstraints_Id.toString()));
+ }
+
+ // check criticality
+ String value = getConfig(CONFIG_CRITICAL);
+
+ if (!isOptional(value)) {
+ boolean critical = getBoolean(value);
+
+ if (critical != ext.isCritical()) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_CRITICAL_NOT_MATCHED"));
+ }
+ }
+ value = getConfig(CONFIG_IS_CA);
+ if (!isOptional(value)) {
+ boolean isCA = getBoolean(value);
+ Boolean extIsCA = (Boolean) ext.get(BasicConstraintsExtension.IS_CA);
+
+ if (isCA != extIsCA.booleanValue()) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_CONSTRAINT_BASIC_CONSTRAINTS_EXT_IS_CA"));
+ }
+ }
+ value = getConfig(CONFIG_MIN_PATH_LEN);
+ if (!isOptional(value)) {
+ int pathLen = getInt(value);
+ Integer extPathLen = (Integer) ext.get(BasicConstraintsExtension.PATH_LEN);
+
+ if (pathLen > extPathLen.intValue()) {
+ CMS.debug("BasicCOnstraintsExtConstraint: pathLen=" + pathLen + " > extPathLen=" + extPathLen);
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_CONSTRAINT_BASIC_CONSTRAINTS_EXT_MIN_PATH"));
+ }
+ }
+ value = getConfig(CONFIG_MAX_PATH_LEN);
+ if (!isOptional(value)) {
+ int pathLen = getInt(value);
+ Integer extPathLen = (Integer) ext.get(BasicConstraintsExtension.PATH_LEN);
+
+ if (pathLen < extPathLen.intValue()) {
+ CMS.debug("BasicCOnstraintsExtConstraint: pathLen=" + pathLen + " < extPathLen=" + extPathLen);
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_CONSTRAINT_BASIC_CONSTRAINTS_EXT_MAX_PATH"));
+ }
+ }
+ } catch (IOException e) {
+ CMS.debug("BasicConstraintsExt: validate " + e.toString());
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_EXTENSION_NOT_FOUND",
+ PKIXExtensions.BasicConstraints_Id.toString()));
+ }
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_CRITICAL),
+ getConfig(CONFIG_IS_CA),
+ getConfig(CONFIG_MIN_PATH_LEN),
+ getConfig(CONFIG_MAX_PATH_LEN)
+ };
+
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_CONSTRAINT_BASIC_CONSTRAINTS_EXT_TEXT",
+ params);
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ if (def instanceof NoDefault)
+ return true;
+ if (def instanceof BasicConstraintsExtDefault)
+ return true;
+ if (def instanceof UserExtensionDefault)
+ return true;
+ return false;
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+
+ if (mConfig.getSubStore("params") == null) {
+ CMS.debug("BasicConstraintsExt: mConfig.getSubStore is null");
+ //
+ } else {
+
+ CMS.debug("BasicConstraintsExt: setConfig name " + name + " value " + value);
+
+ if (name.equals(CONFIG_MAX_PATH_LEN)) {
+
+ String minPathLen = getConfig(CONFIG_MIN_PATH_LEN);
+
+ int minLen = getInt(minPathLen);
+
+ int maxLen = getInt(value);
+
+ if (minLen >= maxLen) {
+ CMS.debug("BasicConstraintExt: minPathLen >= maxPathLen!");
+
+ throw new EPropertyException("bad value");
+ }
+
+ }
+ mConfig.getSubStore("params").putString(name, value);
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/CAEnrollConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/CAEnrollConstraint.java
new file mode 100644
index 000000000..c0a9758da
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/CAEnrollConstraint.java
@@ -0,0 +1,48 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+
+/**
+ * This class represents an abstract class for CA enrollment
+ * constraint.
+ */
+public abstract class CAEnrollConstraint extends EnrollConstraint {
+
+ /**
+ * Constructs a CA enrollment constraint.
+ */
+ public CAEnrollConstraint() {
+ super();
+ }
+
+ /**
+ * Retrieves the CA certificate.
+ */
+ public X509CertImpl getCACert() {
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ X509CertImpl caCert = ca.getCACert();
+
+ return caCert;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/CAValidityConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/CAValidityConstraint.java
new file mode 100644
index 000000000..a7a159de3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/CAValidityConstraint.java
@@ -0,0 +1,139 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.def.CAValidityDefault;
+import com.netscape.cms.profile.def.NoDefault;
+import com.netscape.cms.profile.def.UserValidityDefault;
+import com.netscape.cms.profile.def.ValidityDefault;
+
+/**
+ * This class implements the validity constraint.
+ * It checks if the validity in the certificate
+ * template is within the CA's validity.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CAValidityConstraint extends CAEnrollConstraint {
+
+ private Date mDefNotBefore = null;
+ private Date mDefNotAfter = null;
+
+ public CAValidityConstraint() {
+ super();
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ X509CertImpl caCert = getCACert();
+
+ mDefNotBefore = caCert.getNotBefore();
+ mDefNotAfter = caCert.getNotAfter();
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ */
+ public void validate(IRequest request, X509CertInfo info)
+ throws ERejectException {
+ CMS.debug("CAValidityConstraint: validate start");
+ CertificateValidity v = null;
+
+ try {
+ v = (CertificateValidity) info.get(X509CertInfo.VALIDITY);
+ } catch (Exception e) {
+ throw new ERejectException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_VALIDITY_NOT_FOUND"));
+ }
+ Date notBefore = null;
+
+ try {
+ notBefore = (Date) v.get(CertificateValidity.NOT_BEFORE);
+ } catch (IOException e) {
+ CMS.debug("CAValidity: not before " + e.toString());
+ throw new ERejectException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_INVALID_NOT_BEFORE"));
+ }
+ Date notAfter = null;
+
+ try {
+ notAfter = (Date) v.get(CertificateValidity.NOT_AFTER);
+ } catch (IOException e) {
+ CMS.debug("CAValidity: not after " + e.toString());
+ throw new ERejectException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_INVALID_NOT_AFTER"));
+ }
+
+ if (mDefNotBefore != null) {
+ CMS.debug("ValidtyConstraint: notBefore=" + notBefore +
+ " defNotBefore=" + mDefNotBefore);
+ if (notBefore.before(mDefNotBefore)) {
+ throw new ERejectException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_INVALID_NOT_BEFORE"));
+ }
+ }
+ CMS.debug("ValidtyConstraint: notAfter=" + notAfter +
+ " defNotAfter=" + mDefNotAfter);
+ if (notAfter.after(mDefNotAfter)) {
+ throw new ERejectException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_INVALID_NOT_AFTER"));
+ }
+
+ CMS.debug("CAValidtyConstraint: validate end");
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ mDefNotBefore.toString(),
+ mDefNotAfter.toString()
+ };
+
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_CONSTRAINT_CA_VALIDITY_CONSTRAINT_TEXT",
+ params);
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ if (def instanceof NoDefault)
+ return true;
+ if (def instanceof UserValidityDefault)
+ return true;
+ if (def instanceof ValidityDefault)
+ return true;
+ if (def instanceof CAValidityDefault)
+ return true;
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/EnrollConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/EnrollConstraint.java
new file mode 100644
index 000000000..eb3eb14f6
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/EnrollConstraint.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.Extension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyConstraint;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the generic enrollment constraint.
+ *
+ * @version $Revision$, $Date$
+ */
+public abstract class EnrollConstraint implements IPolicyConstraint {
+ public static final String CONFIG_NAME = "name";
+
+ protected IConfigStore mConfig = null;
+ protected Vector<String> mConfigNames = new Vector<String>();
+
+ public EnrollConstraint() {
+ }
+
+ public Enumeration<String> getConfigNames() {
+ return mConfigNames.elements();
+ }
+
+ public void addConfigName(String name) {
+ mConfigNames.addElement(name);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public Locale getLocale(IRequest request) {
+ Locale locale = null;
+ String language = request.getExtDataInString(
+ EnrollProfile.REQUEST_LOCALE);
+ if (language != null) {
+ locale = new Locale(language);
+ }
+ return locale;
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ if (mConfig.getSubStore("params") == null) {
+ //
+ } else {
+ mConfig.getSubStore("params").putString(name, value);
+ }
+ }
+
+ public String getConfig(String name) {
+ try {
+ if (mConfig == null)
+ return null;
+ if (mConfig.getSubStore("params") != null) {
+ String val = mConfig.getSubStore("params").getString(name);
+
+ return val;
+ }
+ } catch (EBaseException e) {
+ CMS.debug(e.toString());
+ }
+ return "";
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ mConfig = config;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ *
+ * @param request enrollment request
+ * @param info certificate template
+ * @exception ERejectException request is rejected due
+ * to violation of constraint
+ */
+ public abstract void validate(IRequest request, X509CertInfo info)
+ throws ERejectException;
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ *
+ * The current implementation of this method calls
+ * into the subclass's validate(request, info)
+ * method for validation checking.
+ *
+ * @param request request
+ * @exception ERejectException request is rejected due
+ * to violation of constraint
+ */
+ public void validate(IRequest request)
+ throws ERejectException {
+ String name = getClass().getName();
+
+ name = name.substring(name.lastIndexOf('.') + 1);
+ CMS.debug(name + ": validate start");
+ X509CertInfo info =
+ request.getExtDataInCertInfo(EnrollProfile.REQUEST_CERTINFO);
+
+ validate(request, info);
+
+ request.setExtData(EnrollProfile.REQUEST_CERTINFO, info);
+ CMS.debug(name + ": validate end");
+ }
+
+ public String getText(Locale locale) {
+ return "Enroll Constraint";
+ }
+
+ public String getName(Locale locale) {
+ try {
+ return mConfig.getString(CONFIG_NAME);
+ } catch (EBaseException e) {
+ return null;
+ }
+ }
+
+ protected Extension getExtension(String name, X509CertInfo info) {
+ CertificateExtensions exts = null;
+
+ try {
+ exts = (CertificateExtensions)
+ info.get(X509CertInfo.EXTENSIONS);
+ } catch (Exception e) {
+ CMS.debug("EnrollConstraint: getExtension " + e.toString());
+ }
+ if (exts == null)
+ return null;
+ Enumeration<Extension> e = exts.getAttributes();
+
+ while (e.hasMoreElements()) {
+ Extension ext = e.nextElement();
+
+ if (ext.getExtensionId().toString().equals(name)) {
+ return ext;
+ }
+ }
+ return null;
+ }
+
+ protected boolean isOptional(String value) {
+ if (value.equals("") || value.equals("-"))
+ return true;
+ else
+ return false;
+ }
+
+ protected boolean getBoolean(String value) {
+ return Boolean.valueOf(value).booleanValue();
+ }
+
+ protected int getInt(String value) {
+ return Integer.valueOf(value).intValue();
+ }
+
+ protected boolean getConfigBoolean(String value) {
+ return getBoolean(getConfig(value));
+ }
+
+ protected int getConfigInt(String value) {
+ return getInt(getConfig(value));
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ return true;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/ExtendedKeyUsageExtConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/ExtendedKeyUsageExtConstraint.java
new file mode 100644
index 000000000..7821964b9
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/ExtendedKeyUsageExtConstraint.java
@@ -0,0 +1,156 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.security.extensions.ExtendedKeyUsageExtension;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.def.ExtendedKeyUsageExtDefault;
+import com.netscape.cms.profile.def.NoDefault;
+import com.netscape.cms.profile.def.UserExtensionDefault;
+
+/**
+ * This class implements the extended key usage extension constraint.
+ * It checks if the extended key usage extension in the certificate
+ * template satisfies the criteria.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ExtendedKeyUsageExtConstraint extends EnrollConstraint {
+
+ public static final String CONFIG_CRITICAL = "exKeyUsageCritical";
+ public static final String CONFIG_OIDS =
+ "exKeyUsageOIDs";
+
+ public ExtendedKeyUsageExtConstraint() {
+ super();
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_OIDS);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(CONFIG_OIDS)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_OIDS"));
+ }
+ return null;
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ */
+ public void validate(IRequest request, X509CertInfo info)
+ throws ERejectException {
+ ExtendedKeyUsageExtension ext = (ExtendedKeyUsageExtension)
+ getExtension(ExtendedKeyUsageExtension.OID, info);
+
+ if (ext == null) {
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_EXTENSION_NOT_FOUND",
+ ExtendedKeyUsageExtension.OID));
+ }
+
+ // check criticality
+ String value = getConfig(CONFIG_CRITICAL);
+
+ if (!isOptional(value)) {
+ boolean critical = getBoolean(value);
+
+ if (critical != ext.isCritical()) {
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_CRITICAL_NOT_MATCHED"));
+ }
+ }
+
+ // Build local cache of configured OIDs
+ Vector<String> mCache = new Vector<String>();
+ StringTokenizer st = new StringTokenizer(getConfig(CONFIG_OIDS), ",");
+
+ while (st.hasMoreTokens()) {
+ String oid = st.nextToken();
+
+ mCache.addElement(oid);
+ }
+
+ // check OIDs
+ Enumeration<ObjectIdentifier> e = ext.getOIDs();
+
+ while (e.hasMoreElements()) {
+ ObjectIdentifier oid = e.nextElement();
+
+ if (!mCache.contains(oid.toString())) {
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_OID_NOT_MATCHED",
+ oid.toString()));
+ }
+ }
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_CRITICAL),
+ getConfig(CONFIG_OIDS)
+ };
+
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_CONSTRAINT_EXTENDED_KEY_EXT_TEXT",
+ params);
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ if (def instanceof NoDefault)
+ return true;
+ if (def instanceof ExtendedKeyUsageExtDefault)
+ return true;
+ if (def instanceof UserExtensionDefault)
+ return true;
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/ExtensionConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/ExtensionConstraint.java
new file mode 100644
index 000000000..97dc358e3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/ExtensionConstraint.java
@@ -0,0 +1,146 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.util.Locale;
+
+import netscape.security.x509.Extension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.def.EnrollExtDefault;
+import com.netscape.cms.profile.def.NoDefault;
+import com.netscape.cms.profile.def.UserExtensionDefault;
+
+/**
+ * This class implements the general extension constraint.
+ * It checks if the extension in the certificate
+ * template satisfies the criteria.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ExtensionConstraint extends EnrollConstraint {
+
+ public static final String CONFIG_CRITICAL = "extCritical";
+ public static final String CONFIG_OID = "extOID";
+
+ public ExtensionConstraint() {
+ super();
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_OID);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+
+ if (mConfig.getSubStore("params") == null) {
+ CMS.debug("ExtensionConstraint: mConfig.getSubStore is null");
+ } else {
+ CMS.debug("ExtensionConstraint: setConfig name=" + name +
+ " value=" + value);
+
+ if (name.equals(CONFIG_OID)) {
+ try {
+ CMS.checkOID("", value);
+ } catch (Exception e) {
+ throw new EPropertyException(
+ CMS.getUserMessage("CMS_PROFILE_PROPERTY_ERROR", value));
+ }
+ }
+ mConfig.getSubStore("params").putString(name, value);
+ }
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(CONFIG_OID)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_OID"));
+ }
+ return null;
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ */
+ public void validate(IRequest request, X509CertInfo info)
+ throws ERejectException {
+
+ Extension ext = getExtension(getConfig(CONFIG_OID), info);
+
+ if (ext == null) {
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_EXTENSION_NOT_FOUND",
+ getConfig(CONFIG_OID)));
+ }
+
+ // check criticality
+ String value = getConfig(CONFIG_CRITICAL);
+
+ if (!isOptional(value)) {
+ boolean critical = getBoolean(value);
+
+ if (critical != ext.isCritical()) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_CRITICAL_NOT_MATCHED"));
+ }
+ }
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_CRITICAL),
+ getConfig(CONFIG_OID)
+ };
+
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_CONSTRAINT_EXTENSION_TEXT", params);
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ if (def instanceof NoDefault)
+ return true;
+ if (def instanceof UserExtensionDefault)
+ return true;
+ if (def instanceof EnrollExtDefault)
+ return true;
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/KeyConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/KeyConstraint.java
new file mode 100644
index 000000000..3a7d09d5f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/KeyConstraint.java
@@ -0,0 +1,328 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.math.BigInteger;
+import java.security.interfaces.DSAParams;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.provider.DSAPublicKey;
+import netscape.security.provider.RSAPublicKey;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.def.NoDefault;
+import com.netscape.cms.profile.def.UserKeyDefault;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+
+/**
+ * This constraint is to check the key type and
+ * key length.
+ *
+ * @version $Revision$, $Date$
+ */
+
+public class KeyConstraint extends EnrollConstraint {
+
+ public static final String CONFIG_KEY_TYPE = "keyType"; // (EC, RSA)
+ public static final String CONFIG_KEY_PARAMETERS = "keyParameters";
+
+ private static String[] cfgECCurves = null;
+ private static String keyType = "";
+ private static String keyParams = "";
+
+ public KeyConstraint() {
+ super();
+ addConfigName(CONFIG_KEY_TYPE);
+ addConfigName(CONFIG_KEY_PARAMETERS);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+
+ String ecNames = "";
+ try {
+ ecNames = CMS.getConfigStore().getString("keys.ecc.curve.list");
+ } catch (Exception e) {
+ }
+
+ CMS.debug("KeyConstraint.init ecNames: " + ecNames);
+ if (ecNames != null && ecNames.length() != 0) {
+ cfgECCurves = ecNames.split(",");
+ }
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_KEY_TYPE)) {
+ return new Descriptor(IDescriptor.CHOICE, "-,RSA,EC",
+ "RSA",
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_TYPE"));
+ } else if (name.equals(CONFIG_KEY_PARAMETERS)) {
+ return new Descriptor(IDescriptor.STRING, null, "",
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_PARAMETERS"));
+ }
+
+ return null;
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ */
+ public void validate(IRequest request, X509CertInfo info)
+ throws ERejectException {
+ try {
+ CertificateX509Key infokey = (CertificateX509Key)
+ info.get(X509CertInfo.KEY);
+ X509Key key = (X509Key) infokey.get(CertificateX509Key.KEY);
+
+ String alg = key.getAlgorithmId().getName().toUpperCase();
+ String value = getConfig(CONFIG_KEY_TYPE);
+ String keyType = value;
+
+ if (!isOptional(value)) {
+ if (!alg.equals(value)) {
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_KEY_TYPE_NOT_MATCHED",
+ value));
+ }
+ }
+
+ int keySize = 0;
+
+ if (alg.equals("RSA")) {
+ keySize = getRSAKeyLen(key);
+ } else if (alg.equals("DSA")) {
+ keySize = getDSAKeyLen(key);
+ } else if (alg.equals("EC")) {
+ //EC key case.
+ } else {
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_INVALID_KEY_TYPE",
+ alg));
+ }
+
+ value = getConfig(CONFIG_KEY_PARAMETERS);
+
+ String[] keyParams = value.split(",");
+
+ if (alg.equals("EC")) {
+ if (!alg.equals(keyType) && !isOptional(keyType)) {
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_KEY_PARAMS_NOT_MATCHED",
+ value));
+ }
+
+ Vector<?> vect = CryptoUtil.getECKeyCurve(key);
+
+ boolean curveFound = false;
+
+ if (vect != null) {
+ CMS.debug("vect: " + vect.toString());
+
+ if (!isOptional(keyType)) {
+ //Check the curve parameters only if explicit ECC or not optional
+ for (int i = 0; i < keyParams.length; i++) {
+ String ecParam = keyParams[i];
+ CMS.debug("keyParams[i]: " + i + " param: " + ecParam);
+ if (vect.contains(ecParam)) {
+ curveFound = true;
+ CMS.debug("KeyConstraint.validate: EC key constrainst passed.");
+ break;
+ }
+ }
+ } else {
+ curveFound = true;
+ }
+ }
+
+ if (!curveFound) {
+ CMS.debug("KeyConstraint.validate: EC key constrainst failed.");
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_KEY_PARAMS_NOT_MATCHED",
+ value));
+ }
+
+ } else {
+ if (!arrayContainsString(keyParams, Integer.toString(keySize))) {
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_KEY_PARAMS_NOT_MATCHED",
+ value));
+ }
+ CMS.debug("KeyConstraint.validate: RSA key contraints passed.");
+ }
+ } catch (Exception e) {
+ if (e instanceof ERejectException) {
+ throw (ERejectException) e;
+ }
+ CMS.debug("KeyConstraint: " + e.toString());
+ throw new ERejectException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_KEY_NOT_FOUND"));
+ }
+ }
+
+ public int getRSAKeyLen(X509Key key) throws Exception {
+ X509Key newkey = null;
+
+ try {
+ newkey = new X509Key(AlgorithmId.get("RSA"),
+ key.getKey());
+ } catch (Exception e) {
+ CMS.debug("KeyConstraint: getRSAKey Len " + e.toString());
+ return -1;
+ }
+ RSAPublicKey rsaKey = new RSAPublicKey(newkey.getEncoded());
+
+ return rsaKey.getKeySize();
+ }
+
+ public int getDSAKeyLen(X509Key key) throws Exception {
+ // Check DSAKey parameters.
+ // size refers to the p parameter.
+ DSAPublicKey dsaKey = new DSAPublicKey(key.getEncoded());
+ DSAParams keyParams = dsaKey.getParams();
+ BigInteger p = keyParams.getP();
+ int len = p.bitLength();
+
+ return len;
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_KEY_TYPE),
+ getConfig(CONFIG_KEY_PARAMETERS)
+ };
+
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_CONSTRAINT_KEY_TEXT", params);
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ if (def instanceof NoDefault)
+ return true;
+ if (def instanceof UserKeyDefault)
+ return true;
+ return false;
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+
+ CMS.debug("KeyConstraint.setConfig name: " + name + " value: " + value);
+ //establish keyType, we don't know which order these params will arrive
+ if (name.equals(CONFIG_KEY_TYPE)) {
+ keyType = value;
+ if (keyParams.equals(""))
+ return;
+ }
+
+ //establish keyParams
+ if (name.equals(CONFIG_KEY_PARAMETERS)) {
+ CMS.debug("establish keyParams: " + value);
+ keyParams = value;
+
+ if (keyType.equals(""))
+ return;
+ }
+ // All the params we need for validation have been collected,
+ // we don't know which order they will show up
+ if (keyType.length() > 0 && keyParams.length() > 0) {
+ String[] params = keyParams.split(",");
+ boolean isECCurve = false;
+ int keySize = 0;
+
+ for (int i = 0; i < params.length; i++) {
+ if (keyType.equals("EC")) {
+ if (cfgECCurves == null) {
+ //Use the static array as a backup if the config values are not present.
+ isECCurve = arrayContainsString(CryptoUtil.getECcurves(), params[i]);
+ } else {
+ isECCurve = arrayContainsString(cfgECCurves, params[i]);
+ }
+ if (isECCurve == false) { //Not a valid EC curve throw exception.
+ keyType = "";
+ keyParams = "";
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", name));
+ }
+ } else {
+ try {
+ keySize = Integer.parseInt(params[i]);
+ } catch (Exception e) {
+ if (isOptional(keyType)) {
+ isECCurve = arrayContainsString(CryptoUtil.getECcurves(), params[i]);
+ }
+ keySize = 0;
+ }
+ if ((keySize <= 0) && (isECCurve == false)) {
+ keyType = "";
+ keyParams = "";
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", name));
+ }
+ }
+ }
+ }
+ //Actually set the configuration in the profile
+ super.setConfig(CONFIG_KEY_TYPE, keyType);
+ super.setConfig(CONFIG_KEY_PARAMETERS, keyParams);
+
+ //Reset the vars for next round.
+ keyType = "";
+ keyParams = "";
+ }
+
+ private boolean arrayContainsString(String[] array, String value) {
+
+ if (array == null || value == null) {
+ return false;
+ }
+
+ for (int i = 0; i < array.length; i++) {
+ if (array[i].equals(value)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/KeyUsageExtConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/KeyUsageExtConstraint.java
new file mode 100644
index 000000000..f7ec42215
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/KeyUsageExtConstraint.java
@@ -0,0 +1,291 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.util.Locale;
+
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.def.KeyUsageExtDefault;
+import com.netscape.cms.profile.def.NoDefault;
+import com.netscape.cms.profile.def.UserExtensionDefault;
+
+/**
+ * This class implements the key usage extension constraint.
+ * It checks if the key usage constraint in the certificate
+ * template satisfies the criteria.
+ *
+ * @version $Revision$, $Date$
+ */
+public class KeyUsageExtConstraint extends EnrollConstraint {
+
+ public static final String CONFIG_CRITICAL = "keyUsageCritical";
+ public static final String CONFIG_DIGITAL_SIGNATURE =
+ "keyUsageDigitalSignature";
+ public static final String CONFIG_NON_REPUDIATION =
+ "keyUsageNonRepudiation";
+ public static final String CONFIG_KEY_ENCIPHERMENT =
+ "keyUsageKeyEncipherment";
+ public static final String CONFIG_DATA_ENCIPHERMENT =
+ "keyUsageDataEncipherment";
+ public static final String CONFIG_KEY_AGREEMENT = "keyUsageKeyAgreement";
+ public static final String CONFIG_KEY_CERTSIGN = "keyUsageKeyCertSign";
+ public static final String CONFIG_CRL_SIGN = "keyUsageCrlSign";
+ public static final String CONFIG_ENCIPHER_ONLY = "keyUsageEncipherOnly";
+ public static final String CONFIG_DECIPHER_ONLY = "keyUsageDecipherOnly";
+
+ public KeyUsageExtConstraint() {
+ super();
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_DIGITAL_SIGNATURE);
+ addConfigName(CONFIG_NON_REPUDIATION);
+ addConfigName(CONFIG_KEY_ENCIPHERMENT);
+ addConfigName(CONFIG_DATA_ENCIPHERMENT);
+ addConfigName(CONFIG_KEY_AGREEMENT);
+ addConfigName(CONFIG_KEY_CERTSIGN);
+ addConfigName(CONFIG_CRL_SIGN);
+ addConfigName(CONFIG_ENCIPHER_ONLY);
+ addConfigName(CONFIG_DECIPHER_ONLY);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(CONFIG_DIGITAL_SIGNATURE)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_DIGITAL_SIGNATURE"));
+ } else if (name.equals(CONFIG_NON_REPUDIATION)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NON_REPUDIATION"));
+ } else if (name.equals(CONFIG_KEY_ENCIPHERMENT)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_ENCIPHERMENT"));
+ } else if (name.equals(CONFIG_DATA_ENCIPHERMENT)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_DATA_ENCIPHERMENT"));
+ } else if (name.equals(CONFIG_KEY_AGREEMENT)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_AGREEMENT"));
+ } else if (name.equals(CONFIG_KEY_CERTSIGN)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_CERTSIGN"));
+ } else if (name.equals(CONFIG_CRL_SIGN)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRL_SIGN"));
+ } else if (name.equals(CONFIG_ENCIPHER_ONLY)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_ENCIPHER_ONLY"));
+ } else if (name.equals(CONFIG_DECIPHER_ONLY)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_DECIPHER_ONLY"));
+ }
+ return null;
+ }
+
+ public boolean isSet(boolean bits[], int position) {
+ if (bits.length <= position)
+ return false;
+ return bits[position];
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ */
+ public void validate(IRequest request, X509CertInfo info)
+ throws ERejectException {
+ KeyUsageExtension ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+
+ if (ext == null) {
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_EXTENSION_NOT_FOUND",
+ PKIXExtensions.KeyUsage_Id.toString()));
+ }
+
+ boolean[] bits = ext.getBits();
+ String value = getConfig(CONFIG_CRITICAL);
+
+ if (!isOptional(value)) {
+ boolean critical = getBoolean(value);
+
+ if (critical != ext.isCritical()) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_CRITICAL_NOT_MATCHED"));
+ }
+ }
+ value = getConfig(CONFIG_DIGITAL_SIGNATURE);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != isSet(bits, 0)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_DIGITAL_SIGNATURE_NOT_MATCHED",
+ value));
+ }
+ }
+ value = getConfig(CONFIG_NON_REPUDIATION);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != isSet(bits, 1)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_NON_REPUDIATION_NOT_MATCHED",
+ value));
+ }
+ }
+ value = getConfig(CONFIG_KEY_ENCIPHERMENT);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != isSet(bits, 2)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_KEY_ENCIPHERMENT_NOT_MATCHED",
+ value));
+ }
+ }
+ value = getConfig(CONFIG_DATA_ENCIPHERMENT);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != isSet(bits, 3)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_DATA_ENCIPHERMENT_NOT_MATCHED",
+ value));
+ }
+ }
+ value = getConfig(CONFIG_KEY_AGREEMENT);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != isSet(bits, 4)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_KEY_AGREEMENT_NOT_MATCHED",
+ value));
+ }
+ }
+ value = getConfig(CONFIG_KEY_CERTSIGN);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != isSet(bits, 5)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_KEY_CERTSIGN_NOT_MATCHED",
+ value));
+ }
+ }
+ value = getConfig(CONFIG_CRL_SIGN);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != isSet(bits, 6)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_CRL_SIGN_NOT_MATCHED",
+ value));
+ }
+ }
+ value = getConfig(CONFIG_ENCIPHER_ONLY);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != isSet(bits, 7)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_ENCIPHER_ONLY_NOT_MATCHED",
+ value));
+ }
+ }
+ value = getConfig(CONFIG_DECIPHER_ONLY);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != isSet(bits, 8)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_DECIPHER_ONLY_NOT_MATCHED",
+ value));
+ }
+ }
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_CRITICAL),
+ getConfig(CONFIG_DIGITAL_SIGNATURE),
+ getConfig(CONFIG_NON_REPUDIATION),
+ getConfig(CONFIG_KEY_ENCIPHERMENT),
+ getConfig(CONFIG_DATA_ENCIPHERMENT),
+ getConfig(CONFIG_KEY_AGREEMENT),
+ getConfig(CONFIG_KEY_CERTSIGN),
+ getConfig(CONFIG_CRL_SIGN),
+ getConfig(CONFIG_ENCIPHER_ONLY),
+ getConfig(CONFIG_DECIPHER_ONLY)
+ };
+
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_CONSTRAINT_KEY_USAGE_EXT_TEXT", params);
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ if (def instanceof NoDefault)
+ return true;
+ if (def instanceof KeyUsageExtDefault)
+ return true;
+ if (def instanceof UserExtensionDefault)
+ return true;
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/NSCertTypeExtConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/NSCertTypeExtConstraint.java
new file mode 100644
index 000000000..066553275
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/NSCertTypeExtConstraint.java
@@ -0,0 +1,243 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.util.Locale;
+
+import netscape.security.extensions.NSCertTypeExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.def.NSCertTypeExtDefault;
+import com.netscape.cms.profile.def.NoDefault;
+import com.netscape.cms.profile.def.UserExtensionDefault;
+
+/**
+ * This class implements the Netscape certificate type extension constraint.
+ * It checks if the Netscape certificate type extension in the certificate
+ * template satisfies the criteria.
+ *
+ * @version $Revision$, $Date$
+ */
+public class NSCertTypeExtConstraint extends EnrollConstraint {
+
+ public static final String CONFIG_CRITICAL = "nsCertCritical";
+ public static final String CONFIG_SSL_CLIENT = "nsCertSSLClient";
+ public static final String CONFIG_SSL_SERVER = "nsCertSSLServer";
+ public static final String CONFIG_EMAIL = "nsCertEmail";
+ public static final String CONFIG_OBJECT_SIGNING = "nsCertObjectSigning";
+ public static final String CONFIG_SSL_CA = "nsCertSSLCA";
+ public static final String CONFIG_EMAIL_CA = "nsCertEmailCA";
+ public static final String CONFIG_OBJECT_SIGNING_CA = "nsCertObjectSigningCA";
+
+ public NSCertTypeExtConstraint() {
+ super();
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_SSL_CLIENT);
+ addConfigName(CONFIG_SSL_SERVER);
+ addConfigName(CONFIG_EMAIL);
+ addConfigName(CONFIG_OBJECT_SIGNING);
+ addConfigName(CONFIG_SSL_CA);
+ addConfigName(CONFIG_EMAIL_CA);
+ addConfigName(CONFIG_OBJECT_SIGNING_CA);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(CONFIG_SSL_CLIENT)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SSL_CLIENT"));
+ } else if (name.equals(CONFIG_SSL_SERVER)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SSL_SERVER"));
+ } else if (name.equals(CONFIG_EMAIL)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_EMAIL"));
+ } else if (name.equals(CONFIG_OBJECT_SIGNING)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_OBJECT_SIGNING"));
+ } else if (name.equals(CONFIG_SSL_CA)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SSL_CA"));
+ } else if (name.equals(CONFIG_EMAIL_CA)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale, "CMS_PROFILE_EMAIL_CA"));
+ } else if (name.equals(CONFIG_OBJECT_SIGNING_CA)) {
+ return new Descriptor(IDescriptor.CHOICE, "true,false,-",
+ "-",
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_OBJECT_SIGNING_CA"));
+ }
+ return null;
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ */
+ public void validate(IRequest request, X509CertInfo info)
+ throws ERejectException {
+ NSCertTypeExtension ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+
+ if (ext == null) {
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_EXTENSION_NOT_FOUND",
+ NSCertTypeExtension.CertType_Id.toString()));
+ }
+
+ String value = getConfig(CONFIG_CRITICAL);
+
+ if (!isOptional(value)) {
+ boolean critical = getBoolean(value);
+
+ if (critical != ext.isCritical()) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_CRITICAL_NOT_MATCHED"));
+ }
+ }
+ value = getConfig(CONFIG_SSL_CLIENT);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != ext.isSet(0)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_SSL_CLIENT_NOT_MATCHED",
+ value));
+ }
+ }
+ value = getConfig(CONFIG_SSL_SERVER);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != ext.isSet(1)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_SSL_SERVER_NOT_MATCHED",
+ value));
+ }
+ }
+ value = getConfig(CONFIG_EMAIL);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != ext.isSet(2)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_EMAIL_NOT_MATCHED",
+ value));
+ }
+ }
+ value = getConfig(CONFIG_OBJECT_SIGNING);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != ext.isSet(3)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_OBJECT_SIGNING_NOT_MATCHED",
+ value));
+ }
+ }
+ value = getConfig(CONFIG_SSL_CA);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != ext.isSet(4)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_SSL_CA_NOT_MATCHED",
+ value));
+ }
+ }
+ value = getConfig(CONFIG_EMAIL_CA);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != ext.isSet(5)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_EMAIL_CA_NOT_MATCHED",
+ value));
+ }
+ }
+ value = getConfig(CONFIG_OBJECT_SIGNING_CA);
+ if (!isOptional(value)) {
+ boolean bit = getBoolean(value);
+
+ if (bit != ext.isSet(6)) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_OBJECT_SIGNING_CA_NOT_MATCHED",
+ value));
+ }
+ }
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_CRITICAL),
+ getConfig(CONFIG_SSL_CLIENT),
+ getConfig(CONFIG_SSL_SERVER),
+ getConfig(CONFIG_EMAIL),
+ getConfig(CONFIG_OBJECT_SIGNING),
+ getConfig(CONFIG_SSL_CA),
+ getConfig(CONFIG_EMAIL_CA),
+ getConfig(CONFIG_OBJECT_SIGNING_CA)
+ };
+
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_CONSTRAINT_NS_CERT_EXT_TEXT", params);
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ if (def instanceof NoDefault)
+ return true;
+ if (def instanceof NSCertTypeExtDefault)
+ return true;
+ if (def instanceof UserExtensionDefault)
+ return true;
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/NoConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/NoConstraint.java
new file mode 100644
index 000000000..17f6e0b37
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/NoConstraint.java
@@ -0,0 +1,101 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyConstraint;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements no constraint.
+ *
+ * @version $Revision$, $Date$
+ */
+public class NoConstraint implements IPolicyConstraint {
+
+ public static final String CONFIG_NAME = "name";
+
+ private IConfigStore mConfig = null;
+ private Vector<String> mNames = new Vector<String>();
+
+ public Enumeration<String> getConfigNames() {
+ return mNames.elements();
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ }
+
+ public String getConfig(String name) {
+ return null;
+ }
+
+ public String getDefaultConfig(String name) {
+ return null;
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ mConfig = config;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ */
+ public void validate(IRequest request)
+ throws ERejectException {
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_CONSTRAINT_NO_CONSTRAINT_TEXT");
+ }
+
+ public String getName(Locale locale) {
+ try {
+ return mConfig.getString(CONFIG_NAME);
+ } catch (EBaseException e) {
+ return null;
+ }
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ return true;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/RenewGracePeriodConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/RenewGracePeriodConstraint.java
new file mode 100644
index 000000000..d1403962e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/RenewGracePeriodConstraint.java
@@ -0,0 +1,165 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Locale;
+
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.def.NoDefault;
+
+/**
+ * This class supports renewal grace period, which has two
+ * parameters: graceBefore and graceAfter
+ *
+ * @author Christina Fu
+ * @version $Revision$, $Date$
+ */
+public class RenewGracePeriodConstraint extends EnrollConstraint {
+
+ // for renewal: # of days before the orig cert expiration date
+ public static final String CONFIG_RENEW_GRACE_BEFORE = "renewal.graceBefore";
+ // for renewal: # of days after the orig cert expiration date
+ public static final String CONFIG_RENEW_GRACE_AFTER = "renewal.graceAfter";
+
+ public RenewGracePeriodConstraint() {
+ super();
+ addConfigName(CONFIG_RENEW_GRACE_BEFORE);
+ addConfigName(CONFIG_RENEW_GRACE_AFTER);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ if (name.equals(CONFIG_RENEW_GRACE_BEFORE) ||
+ name.equals(CONFIG_RENEW_GRACE_AFTER)) {
+ try {
+ Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_RENEW_GRACE_BEFORE + " or " + CONFIG_RENEW_GRACE_AFTER));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_RENEW_GRACE_BEFORE)) {
+ return new Descriptor(IDescriptor.INTEGER, null, "30",
+ CMS.getUserMessage(locale, "CMS_PROFILE_RENEW_GRACE_BEFORE"));
+ } else if (name.equals(CONFIG_RENEW_GRACE_AFTER)) {
+ return new Descriptor(IDescriptor.INTEGER, null, "30",
+ CMS.getUserMessage(locale, "CMS_PROFILE_RENEW_GRACE_AFTER"));
+ }
+ return null;
+ }
+
+ public void validate(IRequest req, X509CertInfo info)
+ throws ERejectException {
+ String origExpDate_s = req.getExtDataInString("origNotAfter");
+ // probably not for renewal
+ if (origExpDate_s == null) {
+ return;
+ } else {
+ CMS.debug("validate RenewGracePeriod: original cert expiration date found... renewing");
+ }
+ CMS.debug("ValidilityConstraint: validateRenewGraceperiod begins");
+ BigInteger origExpDate_BI = new BigInteger(origExpDate_s);
+ Date origExpDate = new Date(origExpDate_BI.longValue());
+ String renew_grace_before_s = getConfig(CONFIG_RENEW_GRACE_BEFORE);
+ String renew_grace_after_s = getConfig(CONFIG_RENEW_GRACE_AFTER);
+ int renew_grace_before = 0;
+ int renew_grace_after = 0;
+ BigInteger renew_grace_before_BI = new BigInteger(renew_grace_before_s);
+ BigInteger renew_grace_after_BI = new BigInteger(renew_grace_after_s);
+
+ // -1 means no limit
+ if (renew_grace_before_s == "")
+ renew_grace_before = -1;
+ else
+ renew_grace_before = Integer.parseInt(renew_grace_before_s);
+
+ if (renew_grace_after_s == "")
+ renew_grace_after = -1;
+ else
+ renew_grace_after = Integer.parseInt(renew_grace_after_s);
+
+ if (renew_grace_before > 0)
+ renew_grace_before_BI = renew_grace_before_BI.multiply(BigInteger.valueOf(1000 * 86400));
+ if (renew_grace_after > 0)
+ renew_grace_after_BI = renew_grace_after_BI.multiply(BigInteger.valueOf(1000 * 86400));
+
+ Date current = CMS.getCurrentDate();
+ long millisDiff = origExpDate.getTime() - current.getTime();
+ CMS.debug("validateRenewGracePeriod: 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 ((renew_grace_before > 0) && (millisDiff > renew_grace_before_BI.longValue())) {
+ throw new ERejectException(CMS.getUserMessage(getLocale(req),
+ "CMS_PROFILE_RENEW_OUTSIDE_GRACE_PERIOD",
+ renew_grace_before + " days before and " +
+ renew_grace_after + " days after original cert expiration date"));
+ }
+ } else {
+ if ((renew_grace_after > 0) && ((0 - millisDiff) > renew_grace_after_BI.longValue())) {
+ throw new ERejectException(CMS.getUserMessage(getLocale(req),
+ "CMS_PROFILE_RENEW_OUTSIDE_GRACE_PERIOD",
+ renew_grace_before + " days before and " +
+ renew_grace_after + " days after original cert expiration date"));
+ }
+ }
+ }
+
+ public String getText(Locale locale) {
+ String renew_grace_before_s = getConfig(CONFIG_RENEW_GRACE_BEFORE);
+ String renew_grace_after_s = getConfig(CONFIG_RENEW_GRACE_AFTER);
+ return CMS.getUserMessage(locale, "CMS_PROFILE_CONSTRAINT_VALIDITY_TEXT",
+ renew_grace_before_s + " days before and " +
+ renew_grace_after_s + " days after original cert expiration date");
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ if (def instanceof NoDefault)
+ return true;
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/SigningAlgConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/SigningAlgConstraint.java
new file mode 100644
index 000000000..4ccb9ad8f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/SigningAlgConstraint.java
@@ -0,0 +1,160 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.def.NoDefault;
+import com.netscape.cms.profile.def.SigningAlgDefault;
+import com.netscape.cms.profile.def.UserSigningAlgDefault;
+
+/**
+ * This class implements the signing algorithm constraint.
+ * It checks if the signing algorithm in the certificate
+ * template satisfies the criteria.
+ *
+ * @version $Revision$, $Date$
+ */
+public class SigningAlgConstraint extends EnrollConstraint {
+
+ public static final String CONFIG_ALGORITHMS_ALLOWED = "signingAlgsAllowed";
+
+ private static StringBuffer sb = new StringBuffer("");
+ static {
+ for (int i = 0; i < AlgorithmId.ALL_SIGNING_ALGORITHMS.length; i++) {
+ if (i > 0) {
+ sb.append(",");
+ }
+ sb.append(AlgorithmId.ALL_SIGNING_ALGORITHMS[i]);
+ }
+ }
+ public static final String DEF_CONFIG_ALGORITHMS = new String(sb);
+
+ public SigningAlgConstraint() {
+ super();
+ addConfigName(CONFIG_ALGORITHMS_ALLOWED);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+
+ if (mConfig.getSubStore("params") == null) {
+ CMS.debug("SigningAlgConstraint: mConfig.getSubStore is null");
+ } else {
+ CMS.debug("SigningAlgConstraint: setConfig name=" + name +
+ " value=" + value);
+
+ if (name.equals(CONFIG_ALGORITHMS_ALLOWED)) {
+ StringTokenizer st = new StringTokenizer(value, ",");
+ while (st.hasMoreTokens()) {
+ String v = st.nextToken();
+ if (DEF_CONFIG_ALGORITHMS.indexOf(v) == -1) {
+ throw new EPropertyException(
+ CMS.getUserMessage("CMS_PROFILE_PROPERTY_ERROR", v));
+ }
+ }
+ }
+ mConfig.getSubStore("params").putString(name, value);
+ }
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_ALGORITHMS_ALLOWED)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ DEF_CONFIG_ALGORITHMS,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_SIGNING_ALGORITHMS_ALLOWED"));
+ }
+ return null;
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ */
+ public void validate(IRequest request, X509CertInfo info)
+ throws ERejectException {
+ CertificateAlgorithmId algId = null;
+
+ try {
+ algId = (CertificateAlgorithmId) info.get(X509CertInfo.ALGORITHM_ID);
+ AlgorithmId id = (AlgorithmId)
+ algId.get(CertificateAlgorithmId.ALGORITHM);
+
+ Vector<String> mCache = new Vector<String>();
+ StringTokenizer st = new StringTokenizer(
+ getConfig(CONFIG_ALGORITHMS_ALLOWED), ",");
+
+ while (st.hasMoreTokens()) {
+ String token = st.nextToken();
+
+ mCache.addElement(token);
+ }
+
+ if (!mCache.contains(id.toString())) {
+ throw new ERejectException(CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_SIGNING_ALGORITHM_NOT_MATCHED", id.toString()));
+ }
+ } catch (Exception e) {
+ if (e instanceof ERejectException) {
+ throw (ERejectException) e;
+ }
+ CMS.debug("SigningAlgConstraint: " + e.toString());
+ throw new ERejectException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_SIGNING_ALGORITHM_NOT_FOUND"));
+ }
+
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_CONSTRAINT_SIGNING_ALG_TEXT",
+ getConfig(CONFIG_ALGORITHMS_ALLOWED));
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ if (def instanceof NoDefault)
+ return true;
+ if (def instanceof UserSigningAlgDefault)
+ return true;
+ if (def instanceof SigningAlgDefault)
+ return true;
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/SubjectNameConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/SubjectNameConstraint.java
new file mode 100644
index 000000000..027f29b1c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/SubjectNameConstraint.java
@@ -0,0 +1,244 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.def.NoDefault;
+import com.netscape.cms.profile.def.SubjectNameDefault;
+import com.netscape.cms.profile.def.UserSubjectNameDefault;
+
+/**
+ * This class implements the subject name constraint.
+ * It checks if the subject name in the certificate
+ * template satisfies the criteria.
+ *
+ * @version $Revision$, $Date$
+ */
+public class SubjectNameConstraint extends EnrollConstraint {
+
+ public static final String CONFIG_PATTERN = "pattern";
+
+
+ private static final int COMMON_NAME_MAX = 64;
+ private static final int LOCALITY_NAME_MAX = 128;
+ private static final int STATE_NAME_MAX = 128;
+ private static final int ORG_NAME_MAX = 64;
+ private static final int ORG_UNIT_NAME_MAX = 64;
+ private static final int EMAIL_NAME_MAX = 255;
+ private static final int COUNTRY_NAME_MAX = 3;
+ private static final int UID_NAME_MAX = 64;
+
+ public SubjectNameConstraint() {
+ // configuration names
+ addConfigName(CONFIG_PATTERN);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_PATTERN)) {
+ return new Descriptor(IDescriptor.STRING,
+ null, null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SUBJECT_NAME_PATTERN"));
+ } else {
+ return null;
+ }
+ }
+
+ public String getDefaultConfig(String name) {
+ return null;
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ */
+ public void validate(IRequest request, X509CertInfo info)
+ throws ERejectException {
+ CMS.debug("SubjectNameConstraint: validate start");
+ CertificateSubjectName sn = null;
+
+ try {
+ sn = (CertificateSubjectName) info.get(X509CertInfo.SUBJECT);
+ CMS.debug("SubjectNameConstraint: validate cert subject =" +
+ sn.toString());
+ } catch (Exception e) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_SUBJECT_NAME_NOT_FOUND"));
+ }
+ X500Name sn500 = null;
+
+ try {
+ sn500 = (X500Name) sn.get(CertificateSubjectName.DN_NAME);
+ } catch (IOException e) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_SUBJECT_NAME_NOT_FOUND"));
+ }
+ if (sn500 == null) {
+ CMS.debug("SubjectNameConstraint: validate() - sn500 is null");
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_SUBJECT_NAME_NOT_FOUND"));
+ } else {
+ CMS.debug("SubjectNameConstraint: validate() - sn500 " +
+ CertificateSubjectName.DN_NAME + " = " +
+ sn500.toString());
+ }
+ if (!sn500.toString().matches(getConfig(CONFIG_PATTERN))) {
+ CMS.debug("SubjectNameConstraint: validate() - sn500 not matching pattern " + getConfig(CONFIG_PATTERN));
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_SUBJECT_NAME_NOT_MATCHED",
+ sn500.toString()));
+ }
+
+ String incorrectFields = " [ Invalid fields: ";
+ String country = null;
+ boolean fieldError = false;
+
+ String commonName = null;
+ try {
+ commonName = sn500.getCommonName();
+ } catch (Exception e) {
+ }
+ if ( commonName != null && commonName.length() > COMMON_NAME_MAX ) {
+ fieldError = true;
+ incorrectFields += " Common Name ";
+
+ }
+
+ try {
+ country = sn500.getCountry();
+ } catch (Exception e) {
+ }
+
+ if ( country != null && country.length() > COUNTRY_NAME_MAX ) {
+ fieldError = true;
+ incorrectFields += " , Country ";
+ }
+
+ String ou = null ;
+ try {
+ ou = sn500.getOrganizationalUnit();
+ } catch (Exception e) {
+ }
+
+ if ( ou != null && ou.length() > ORG_UNIT_NAME_MAX) {
+ fieldError = true;
+ incorrectFields += " , Org Unit ";
+ }
+
+ String o = null;
+ try {
+ o = sn500.getOrganization();
+ } catch (Exception e) {
+ }
+
+ if ( o != null && o.length() > ORG_NAME_MAX) {
+ fieldError = true;
+ incorrectFields += " , Org ";
+ }
+
+ String locality = null;
+ try {
+ locality = sn500.getLocality();
+ } catch (Exception e) {
+ }
+
+ if ( locality != null && locality.length() > LOCALITY_NAME_MAX ) {
+ fieldError = true;
+ incorrectFields += " , Locality ";
+ }
+
+ String state = null;
+ try {
+ state = sn500.getState();
+ } catch (Exception e) {
+ }
+
+ if ( state != null && state.length() > STATE_NAME_MAX ) {
+ fieldError = true;
+ incorrectFields += " , State ";
+ }
+
+ String email = null;
+ try {
+ email = sn500.getEmail();
+ } catch (Exception e) {
+ }
+
+ if ( email != null && email.length() > EMAIL_NAME_MAX ) {
+ fieldError = true;
+ incorrectFields += " , Email ";
+ }
+
+ String UID = null;
+ try {
+ UID = sn500.getUserID();
+ } catch (Exception e) {
+ }
+
+ if ( UID != null && UID.length() > UID_NAME_MAX) {
+ fieldError = true;
+ incorrectFields += " , UID";
+ }
+
+ if ( fieldError == true ) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_INVALID_SUBJECT_NAME",sn500.toString() + incorrectFields + " ] "));
+
+ }
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_CONSTRAINT_SUBJECT_NAME_TEXT",
+ getConfig(CONFIG_PATTERN));
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ if (def instanceof NoDefault)
+ return true;
+ if (def instanceof SubjectNameDefault)
+ return true;
+ if (def instanceof UserSubjectNameDefault)
+ return true;
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/UniqueKeyConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/UniqueKeyConstraint.java
new file mode 100644
index 000000000..869f0e2cc
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/UniqueKeyConstraint.java
@@ -0,0 +1,294 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.util.Enumeration;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertRecordList;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.def.NoDefault;
+
+/**
+ * This constraint is to check for publickey uniqueness.
+ * The config param "allowSameKeyRenewal" enables the
+ * situation where if the publickey is not unique, and if
+ * the subject DN is the same, that is a "renewal".
+ *
+ * Another "feature" that is quoted out of this code is the
+ * "revokeDupKeyCert" option, which enables the revocation
+ * of certs that bear the same publickey as the enrolling
+ * request. Since this can potentially be abused, it is taken
+ * out and preserved in comments to allow future refinement.
+ *
+ * @version $Revision$, $Date$
+ */
+public class UniqueKeyConstraint extends EnrollConstraint {
+ /*
+ public static final String CONFIG_REVOKE_DUPKEY_CERT =
+ "revokeDupKeyCert";
+ boolean mRevokeDupKeyCert = false;
+ */
+ public static final String CONFIG_ALLOW_SAME_KEY_RENEWAL =
+ "allowSameKeyRenewal";
+ boolean mAllowSameKeyRenewal = false;
+ public ICertificateAuthority mCA = null;
+
+ public UniqueKeyConstraint() {
+ super();
+ /*
+ addConfigName(CONFIG_REVOKE_DUPKEY_CERT);
+ */
+ addConfigName(CONFIG_ALLOW_SAME_KEY_RENEWAL);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ mCA = (ICertificateAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ /*
+ if (name.equals(CONFIG_REVOKE_DUPKEY_CERT)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null, "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CONFIG_REVOKE_DUPKEY_CERT"));
+ }
+ */
+ if (name.equals(CONFIG_ALLOW_SAME_KEY_RENEWAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null, "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CONFIG_ALLOW_SAME_KEY_RENEWAL"));
+ }
+ return null;
+ }
+
+ public String getDefaultConfig(String name) {
+ return null;
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ */
+ public void validate(IRequest request, X509CertInfo info)
+ throws ERejectException {
+ boolean rejected = false;
+ int size = 0;
+ ICertRecordList list;
+
+ /*
+ mRevokeDupKeyCert =
+ getConfigBoolean(CONFIG_REVOKE_DUPKEY_CERT);
+ */
+ mAllowSameKeyRenewal = getConfigBoolean(CONFIG_ALLOW_SAME_KEY_RENEWAL);
+
+ try {
+ CertificateX509Key infokey = (CertificateX509Key)
+ info.get(X509CertInfo.KEY);
+ X509Key key = (X509Key)
+ infokey.get(CertificateX509Key.KEY);
+
+ // check for key uniqueness
+ byte pub[] = key.getEncoded();
+ String pub_s = escapeBinaryData(pub);
+ String filter = "(" + ICertRecord.ATTR_X509CERT_PUBLIC_KEY_DATA + "=" + pub_s + ")";
+ list =
+ mCA.getCertificateRepository().findCertRecordsInList(filter, null, 10);
+ size = list.getSize();
+
+ } catch (Exception e) {
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_INTERNAL_ERROR", e.toString()));
+ }
+
+ /*
+ * It does not matter if the corresponding cert's status
+ * is valid or not, we don't want a key that was once
+ * generated before
+ */
+ if (size > 0) {
+ CMS.debug("UniqueKeyConstraint: found existing cert with duplicate key.");
+
+ /*
+ The following code revokes the existing certs that have
+ the same public key as the one submitted for enrollment
+ request. However, it is not a good idea due to possible
+ abuse. It is therefore commented out. It is still
+ however still maintained for possible utilization at later
+ time
+
+ // if configured to revoke duplicated key
+ // revoke cert
+ if (mRevokeDupKeyCert) {
+ try {
+ Enumeration e = list.getCertRecords(0, size-1);
+ while (e != null && e.hasMoreElements()) {
+ ICertRecord rec = (ICertRecord) e.nextElement();
+ X509CertImpl cert = rec.getCertificate();
+
+ // revoke the cert
+ BigInteger serialNum = cert.getSerialNumber();
+ ICAService service = (ICAService) mCA.getCAService();
+
+ RevokedCertImpl crlEntry =
+ formCRLEntry(serialNum, RevocationReason.KEY_COMPROMISE);
+ service.revokeCert(crlEntry);
+ CMS.debug("UniqueKeyConstraint: certificate with duplicate publickey revoked successfully");
+ }
+ } catch (Exception ex) {
+ CMS.debug("UniqueKeyConstraint: error in revoke dupkey cert");
+ }
+ } // revoke dupkey cert turned on
+ */
+
+ if (mAllowSameKeyRenewal == true) {
+ X500Name sjname_in_db = null;
+ X500Name sjname_in_req = null;
+
+ try {
+ // get subject of request
+ CertificateSubjectName subName =
+ (CertificateSubjectName) info.get(X509CertInfo.SUBJECT);
+
+ if (subName != null) {
+
+ sjname_in_req =
+ (X500Name) subName.get(CertificateSubjectName.DN_NAME);
+ CMS.debug("UniqueKeyConstraint: cert request subject DN =" + sjname_in_req.toString());
+ Enumeration<ICertRecord> e = list.getCertRecords(0, size - 1);
+ while (e != null && e.hasMoreElements()) {
+ ICertRecord rec = e.nextElement();
+ X509CertImpl cert = rec.getCertificate();
+ String certDN =
+ cert.getSubjectDN().toString();
+ CMS.debug("UniqueKeyConstraint: cert retrieved from ldap has subject DN =" + certDN);
+
+ sjname_in_db = new X500Name(certDN);
+
+ if (sjname_in_db.equals(sjname_in_req) == false) {
+ rejected = true;
+ break;
+ } else {
+ rejected = false;
+ }
+ } // while
+ } else { //subName is null
+ rejected = true;
+ }
+ } catch (Exception ex1) {
+ CMS.debug("UniqueKeyConstraint: error in allowSameKeyRenewal: " + ex1.toString());
+ rejected = true;
+ } // try
+
+ } else {
+ rejected = true;
+ }// allowSameKeyRenewal
+ } // (size > 0)
+
+ if (rejected == true) {
+ CMS.debug("UniqueKeyConstraint: rejected");
+ throw new ERejectException(
+ CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_DUPLICATE_KEY"));
+ } else {
+ CMS.debug("UniqueKeyConstraint: approved");
+ }
+ }
+
+ /**
+ * make a CRL entry from a serial number and revocation reason.
+ *
+ * @return a RevokedCertImpl that can be entered in a CRL.
+ *
+ * protected RevokedCertImpl formCRLEntry(
+ * BigInteger serialNo, RevocationReason reason)
+ * throws EBaseException {
+ * CRLReasonExtension reasonExt = new CRLReasonExtension(reason);
+ * CRLExtensions crlentryexts = new CRLExtensions();
+ *
+ * try {
+ * crlentryexts.set(CRLReasonExtension.NAME, reasonExt);
+ * } catch (IOException e) {
+ * CMS.debug("CMSGW_ERR_CRL_REASON "+e.toString());
+ *
+ * // throw new ECMSGWException(
+ * // CMS.getLogMessage("CMSGW_ERROR_SETTING_CRLREASON"));
+ *
+ * }
+ * RevokedCertImpl crlentry =
+ * new RevokedCertImpl(serialNo, CMS.getCurrentDate(),
+ * crlentryexts);
+ *
+ * return crlentry;
+ * }
+ */
+
+ public String getText(Locale locale) {
+ String params[] = {
+ /*
+ getConfig(CONFIG_REVOKE_DUPKEY_CERT),
+ */
+ };
+
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_CONSTRAINT_ALLOW_SAME_KEY_RENEWAL_TEXT", params);
+ }
+
+ public static String escapeBinaryData(byte data[]) {
+ StringBuffer sb = new StringBuffer();
+
+ for (int i = 0; i < data.length; i++) {
+ int v = 0xff & data[i];
+ sb.append("\\");
+ sb.append((v < 16 ? "0" : ""));
+ sb.append(Integer.toHexString(v));
+ }
+ return sb.toString();
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ if (def instanceof NoDefault)
+ return true;
+ if (def instanceof UniqueKeyConstraint)
+ return true;
+
+ return false;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/UniqueSubjectNameConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/UniqueSubjectNameConstraint.java
new file mode 100644
index 000000000..6545b81fd
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/UniqueSubjectNameConstraint.java
@@ -0,0 +1,251 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.Extension;
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+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.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.dbs.certdb.IRevocationInfo;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.def.NoDefault;
+import com.netscape.cms.profile.def.SubjectNameDefault;
+import com.netscape.cms.profile.def.UserSubjectNameDefault;
+
+/**
+ * This class implements the unique subject name constraint.
+ * It checks if the subject name in the certificate is
+ * unique in the internal database, ie, no two certificates
+ * have the same subject name.
+ *
+ * @version $Revision$, $Date$
+ */
+public class UniqueSubjectNameConstraint extends EnrollConstraint {
+
+ public static final String CONFIG_KEY_USAGE_EXTENSION_CHECKING =
+ "enableKeyUsageExtensionChecking";
+ private boolean mKeyUsageExtensionChecking = true;
+
+ public UniqueSubjectNameConstraint() {
+ addConfigName(CONFIG_KEY_USAGE_EXTENSION_CHECKING);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_KEY_USAGE_EXTENSION_CHECKING)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null, "true",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CONFIG_KEY_USAGE_EXTENSION_CHECKING"));
+ }
+ return null;
+ }
+
+ public String getDefaultConfig(String name) {
+ return null;
+ }
+
+ /**
+ * Checks if the key extension in the issued certificate
+ * is the same as the one in the certificate template.
+ */
+ private boolean sameKeyUsageExtension(ICertRecord rec,
+ X509CertInfo certInfo) {
+ X509CertImpl impl = rec.getCertificate();
+ boolean bits[] = impl.getKeyUsage();
+
+ CertificateExtensions extensions = null;
+
+ try {
+ extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+ } catch (IOException e) {
+ } catch (java.security.cert.CertificateException e) {
+ }
+ KeyUsageExtension ext = null;
+
+ if (extensions == null) {
+ if (bits != null)
+ return false;
+ } else {
+ try {
+ ext = (KeyUsageExtension) extensions.get(
+ KeyUsageExtension.NAME);
+ } catch (IOException e) {
+ // extension isn't there.
+ }
+
+ if (ext == null) {
+ if (bits != null)
+ return false;
+ } else {
+ boolean[] InfoBits = ext.getBits();
+
+ if (InfoBits == null) {
+ if (bits != null)
+ return false;
+ } else {
+ if (bits == null)
+ return false;
+ if (InfoBits.length != bits.length) {
+ return false;
+ }
+ for (int i = 0; i < InfoBits.length; i++) {
+ if (InfoBits[i] != bits[i])
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ *
+ * Rules are as follows:
+ * If the subject name is not unique, then the request will be rejected unless:
+ * 1. the certificate is expired or expired_revoked
+ * 2. the certificate is revoked and the revocation reason is not "on hold"
+ * 3. the keyUsageExtension bits are different and enableKeyUsageExtensionChecking=true (default)
+ */
+ public void validate(IRequest request, X509CertInfo info)
+ throws ERejectException {
+ CMS.debug("UniqueSubjectNameConstraint: validate start");
+ CertificateSubjectName sn = null;
+ IAuthority authority = (IAuthority) CMS.getSubsystem("ca");
+
+ mKeyUsageExtensionChecking = getConfigBoolean(CONFIG_KEY_USAGE_EXTENSION_CHECKING);
+ ICertificateRepository certdb = null;
+ if (authority != null && authority instanceof ICertificateAuthority) {
+ ICertificateAuthority ca = (ICertificateAuthority) authority;
+ certdb = ca.getCertificateRepository();
+ }
+
+ try {
+ sn = (CertificateSubjectName) info.get(X509CertInfo.SUBJECT);
+ } catch (Exception e) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_SUBJECT_NAME_NOT_FOUND"));
+ }
+
+ String certsubjectname = null;
+ if (sn == null)
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_SUBJECT_NAME_NOT_FOUND"));
+ else {
+ certsubjectname = sn.toString();
+ String filter = "x509Cert.subject=" + certsubjectname;
+ Enumeration<ICertRecord> sameSubjRecords = null;
+ try {
+ sameSubjRecords = certdb.findCertRecords(filter);
+ } catch (EBaseException e) {
+ CMS.debug("UniqueSubjectNameConstraint exception: " + e.toString());
+ }
+ while (sameSubjRecords != null && sameSubjRecords.hasMoreElements()) {
+ ICertRecord rec = sameSubjRecords.nextElement();
+ String status = rec.getStatus();
+
+ IRevocationInfo revocationInfo = rec.getRevocationInfo();
+ RevocationReason reason = null;
+
+ if (revocationInfo != null) {
+ CRLExtensions crlExts = revocationInfo.getCRLEntryExtensions();
+
+ if (crlExts != null) {
+ Enumeration<Extension> enumx = crlExts.getElements();
+
+ while (enumx.hasMoreElements()) {
+ Extension ext = enumx.nextElement();
+
+ if (ext instanceof CRLReasonExtension) {
+ reason = ((CRLReasonExtension) ext).getReason();
+ }
+ }
+ }
+ }
+
+ if (status.equals(ICertRecord.STATUS_EXPIRED) || status.equals(ICertRecord.STATUS_REVOKED_EXPIRED)) {
+ continue;
+ }
+
+ if (status.equals(ICertRecord.STATUS_REVOKED) && reason != null &&
+ (!reason.equals(RevocationReason.CERTIFICATE_HOLD))) {
+ continue;
+ }
+
+ if (mKeyUsageExtensionChecking && !sameKeyUsageExtension(rec, info)) {
+ continue;
+ }
+
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_SUBJECT_NAME_NOT_UNIQUE",
+ certsubjectname));
+ }
+ }
+ CMS.debug("UniqueSubjectNameConstraint: validate end");
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_KEY_USAGE_EXTENSION_CHECKING)
+ };
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_CONSTRAINT_UNIQUE_SUBJECT_NAME_TEXT",
+ params);
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ if (def instanceof NoDefault)
+ return true;
+ if (def instanceof SubjectNameDefault)
+ return true;
+ if (def instanceof UserSubjectNameDefault)
+ return true;
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/UserSubjectNameConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/UserSubjectNameConstraint.java
new file mode 100644
index 000000000..30a034cb3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/UserSubjectNameConstraint.java
@@ -0,0 +1,93 @@
+// --- 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 com.netscape.cms.profile.constraint;
+
+import java.util.Locale;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.def.UserSubjectNameDefault;
+
+/**
+ * This class implements the user subject name constraint.
+ * It copies user encoded subject name into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class UserSubjectNameConstraint extends EnrollConstraint {
+
+ public UserSubjectNameConstraint() {
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public String getDefaultConfig(String name) {
+ return null;
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation. User encoded subject name
+ * is copied into the certificate template.
+ */
+ public void validate(IRequest request, X509CertInfo info)
+ throws ERejectException {
+ CMS.debug("UserSubjectNameConstraint: validate start");
+ CertificateSubjectName requestSN = null;
+
+ try {
+ requestSN = request.getExtDataInCertSubjectName(
+ IEnrollProfile.REQUEST_SUBJECT_NAME);
+ info.set(X509CertInfo.SUBJECT, requestSN);
+ CMS.debug("UserSubjectNameConstraint: validate user subject ="+
+ requestSN.toString());
+ } catch (Exception e) {
+ throw new ERejectException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_SUBJECT_NAME_NOT_FOUND"));
+ }
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_CONSTRAINT_USER_SUBJECT_NAME_TEXT");
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ if (def instanceof UserSubjectNameDefault)
+ return true;
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/ValidityConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/ValidityConstraint.java
new file mode 100644
index 000000000..accbd9d2d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/ValidityConstraint.java
@@ -0,0 +1,218 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.def.CAValidityDefault;
+import com.netscape.cms.profile.def.NoDefault;
+import com.netscape.cms.profile.def.RandomizedValidityDefault;
+import com.netscape.cms.profile.def.UserValidityDefault;
+import com.netscape.cms.profile.def.ValidityDefault;
+
+/**
+ * This class implements the validity constraint.
+ * It checks if the validity in the certificate
+ * template satisfies the criteria.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ValidityConstraint extends EnrollConstraint {
+
+ public static final String CONFIG_RANGE = "range";
+ public static final String CONFIG_NOT_BEFORE_GRACE_PERIOD = "notBeforeGracePeriod";
+ public static final String CONFIG_CHECK_NOT_BEFORE = "notBeforeCheck";
+ public static final String CONFIG_CHECK_NOT_AFTER = "notAfterCheck";
+ public final static long SECS_IN_MS = 1000L;
+
+ public ValidityConstraint() {
+ super();
+ addConfigName(CONFIG_RANGE);
+ addConfigName(CONFIG_NOT_BEFORE_GRACE_PERIOD);
+ addConfigName(CONFIG_CHECK_NOT_BEFORE);
+ addConfigName(CONFIG_CHECK_NOT_AFTER);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ if (name.equals(CONFIG_RANGE) ||
+ name.equals(CONFIG_NOT_BEFORE_GRACE_PERIOD)) {
+ try {
+ Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", name));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_RANGE)) {
+ return new Descriptor(IDescriptor.INTEGER, null, "365",
+ CMS.getUserMessage(locale, "CMS_PROFILE_VALIDITY_RANGE"));
+ } else if (name.equals(CONFIG_NOT_BEFORE_GRACE_PERIOD)) {
+ return new Descriptor(IDescriptor.INTEGER, null, "0",
+ CMS.getUserMessage(locale, "CMS_PROFILE_VALIDITY_NOT_BEFORE_GRACE_PERIOD"));
+ } else if (name.equals(CONFIG_CHECK_NOT_BEFORE)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null, "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_VALIDITY_CHECK_NOT_BEFORE"));
+ } else if (name.equals(CONFIG_CHECK_NOT_AFTER)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null, "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_VALIDITY_CHECK_NOT_AFTER"));
+ }
+ return null;
+ }
+
+ /**
+ * Validates the request. The request is not modified
+ * during the validation.
+ */
+ public void validate(IRequest request, X509CertInfo info)
+ throws ERejectException {
+ CertificateValidity v = null;
+
+ try {
+ v = (CertificateValidity) info.get(X509CertInfo.VALIDITY);
+ } catch (Exception e) {
+ throw new ERejectException(CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_VALIDITY_NOT_FOUND"));
+ }
+ Date notBefore = null;
+
+ try {
+ notBefore = (Date) v.get(CertificateValidity.NOT_BEFORE);
+ } catch (IOException e) {
+ CMS.debug("ValidityConstraint: not before not found");
+ throw new ERejectException(CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_VALIDITY_NOT_FOUND"));
+ }
+ Date notAfter = null;
+
+ try {
+ notAfter = (Date) v.get(CertificateValidity.NOT_AFTER);
+ } catch (IOException e) {
+ CMS.debug("ValidityConstraint: not after not found");
+ throw new ERejectException(CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_VALIDITY_NOT_FOUND"));
+ }
+
+ if (notAfter.getTime() < notBefore.getTime()) {
+ CMS.debug("ValidityConstraint: notAfter (" + notAfter + ") < notBefore (" + notBefore + ")");
+ throw new ERejectException(CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_NOT_AFTER_BEFORE_NOT_BEFORE"));
+ }
+
+ long millisDiff = notAfter.getTime() - notBefore.getTime();
+ CMS.debug("ValidityConstraint: millisDiff="
+ + millisDiff + " notAfter=" + notAfter.getTime() + " notBefore=" + notBefore.getTime());
+ long long_days = (millisDiff / 1000) / 86400;
+ CMS.debug("ValidityConstraint: long_days: " + long_days);
+ int days = (int) long_days;
+ CMS.debug("ValidityConstraint: days: " + days);
+
+ if (days > Integer.parseInt(getConfig(CONFIG_RANGE))) {
+ throw new ERejectException(CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_VALIDITY_OUT_OF_RANGE",
+ Integer.toString(days)));
+ }
+
+ // 613828
+ // The validity field shall specify a notBefore value
+ // that does not precede the current time and a notAfter
+ // value that does not precede the value specified in
+ // notBefore (test can be automated; try entering violating
+ // time values and check result).
+ String notBeforeCheckStr = getConfig(CONFIG_CHECK_NOT_BEFORE);
+ boolean notBeforeCheck;
+
+ if (notBeforeCheckStr == null || notBeforeCheckStr.equals("")) {
+ notBeforeCheckStr = "false";
+ }
+ notBeforeCheck = Boolean.valueOf(notBeforeCheckStr).booleanValue();
+
+ String notAfterCheckStr = getConfig(CONFIG_CHECK_NOT_AFTER);
+ boolean notAfterCheck;
+
+ if (notAfterCheckStr == null || notAfterCheckStr.equals("")) {
+ notAfterCheckStr = "false";
+ }
+ notAfterCheck = Boolean.valueOf(notAfterCheckStr).booleanValue();
+
+ String notBeforeGracePeriodStr = getConfig(CONFIG_NOT_BEFORE_GRACE_PERIOD);
+ if (notBeforeGracePeriodStr == null || notBeforeGracePeriodStr.equals("")) {
+ notBeforeGracePeriodStr = "0";
+ }
+ long notBeforeGracePeriod = Long.parseLong(notBeforeGracePeriodStr) * SECS_IN_MS;
+
+ Date current = CMS.getCurrentDate();
+ if (notBeforeCheck) {
+ if (notBefore.getTime() > (current.getTime() + notBeforeGracePeriod)) {
+ CMS.debug("ValidityConstraint: notBefore (" + notBefore + ") > current + " +
+ "gracePeriod (" + new Date(current.getTime() + notBeforeGracePeriod) + ")");
+ throw new ERejectException(CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_NOT_BEFORE_AFTER_CURRENT"));
+ }
+ }
+ if (notAfterCheck) {
+ if (notAfter.getTime() < current.getTime()) {
+ CMS.debug("ValidityConstraint: notAfter (" + notAfter + ") < current + (" + current + ")");
+ throw new ERejectException(CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_NOT_AFTER_BEFORE_CURRENT"));
+ }
+ }
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_CONSTRAINT_VALIDITY_TEXT", getConfig(CONFIG_RANGE));
+ }
+
+ public boolean isApplicable(IPolicyDefault def) {
+ if (def instanceof NoDefault)
+ return true;
+ if (def instanceof UserValidityDefault)
+ return true;
+ if (def instanceof ValidityDefault)
+ return true;
+ if (def instanceof CAValidityDefault)
+ return true;
+ if (def instanceof RandomizedValidityDefault)
+ return true;
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/AuthInfoAccessExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/AuthInfoAccessExtDefault.java
new file mode 100644
index 000000000..36818a907
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/AuthInfoAccessExtDefault.java
@@ -0,0 +1,454 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.extensions.AccessDescription;
+import netscape.security.extensions.AuthInfoAccessExtension;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNameInterface;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates Authuority Info Access extension.
+ *
+ * @version $Revision$, $Date$
+ */
+public class AuthInfoAccessExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "authInfoAccessCritical";
+ public static final String CONFIG_NUM_ADS = "authInfoAccessNumADs";
+ public static final String CONFIG_AD_ENABLE = "authInfoAccessADEnable_";
+ public static final String CONFIG_AD_METHOD = "authInfoAccessADMethod_";
+ public static final String CONFIG_AD_LOCATIONTYPE = "authInfoAccessADLocationType_";
+ public static final String CONFIG_AD_LOCATION = "authInfoAccessADLocation_";
+
+ public static final String VAL_CRITICAL = "authInfoAccessCritical";
+ public static final String VAL_GENERAL_NAMES = "authInfoAccessGeneralNames";
+
+ private static final String AD_METHOD = "Method";
+ private static final String AD_LOCATION_TYPE = "Location Type";
+ private static final String AD_LOCATION = "Location";
+ private static final String AD_ENABLE = "Enable";
+
+ private static final int DEF_NUM_AD = 1;
+ private static final int MAX_NUM_AD = 100;
+
+ public AuthInfoAccessExtDefault() {
+ super();
+ }
+
+ protected int getNumAds() {
+ int num = DEF_NUM_AD;
+ String numAds = getConfig(CONFIG_NUM_ADS);
+
+ if (numAds != null) {
+ try {
+ num = Integer.parseInt(numAds);
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ }
+
+ if (num > MAX_NUM_AD) {
+ num = DEF_NUM_AD;
+ }
+
+ return num;
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ refreshConfigAndValueNames();
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ int num = 0;
+ if (name.equals(CONFIG_NUM_ADS)) {
+ try {
+ num = Integer.parseInt(value);
+
+ if (num >= MAX_NUM_AD || num < 0) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_ADS));
+ }
+
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_ADS));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public Enumeration<String> getConfigNames() {
+ refreshConfigAndValueNames();
+ return super.getConfigNames();
+ }
+
+ protected void refreshConfigAndValueNames() {
+ //refesh our config name list
+
+ super.refreshConfigAndValueNames();
+ mConfigNames.removeAllElements();
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_GENERAL_NAMES);
+
+ // register configuration names bases on num ads
+ addConfigName(CONFIG_CRITICAL);
+ int num = getNumAds();
+
+ addConfigName(CONFIG_NUM_ADS);
+ for (int i = 0; i < num; i++) {
+ addConfigName(CONFIG_AD_METHOD + i);
+ addConfigName(CONFIG_AD_LOCATIONTYPE + i);
+ addConfigName(CONFIG_AD_LOCATION + i);
+ addConfigName(CONFIG_AD_ENABLE + i);
+ }
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.startsWith(CONFIG_AD_METHOD)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_AD_METHOD"));
+ } else if (name.startsWith(CONFIG_AD_LOCATIONTYPE)) {
+ return new Descriptor(IDescriptor.CHOICE,
+ "RFC822Name,DNSName,DirectoryName,EDIPartyName,URIName,IPAddress,OIDName",
+ "URIName",
+ CMS.getUserMessage(locale, "CMS_PROFILE_AD_LOCATIONTYPE"));
+ } else if (name.startsWith(CONFIG_AD_LOCATION)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_AD_LOCATION"));
+ } else if (name.startsWith(CONFIG_AD_ENABLE)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_AD_ENABLE"));
+ } else if (name.startsWith(CONFIG_NUM_ADS)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "1",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NUM_ADS"));
+ }
+ return null;
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_GENERAL_NAMES)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_GENERAL_NAMES"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ AuthInfoAccessExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ AuthInfoAccessExtension a = new AuthInfoAccessExtension(false);
+ ObjectIdentifier oid = a.getExtensionId();
+
+ ext = (AuthInfoAccessExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ populate(null, info);
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+
+ ext = (AuthInfoAccessExtension)
+ getExtension(oid.toString(), info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ if (ext == null) {
+ return;
+ }
+ ext.setCritical(val);
+ } else if (name.equals(VAL_GENERAL_NAMES)) {
+
+ ext = (AuthInfoAccessExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ return;
+ }
+ boolean critical = ext.isCritical();
+
+ Vector<NameValuePairs> v = parseRecords(value);
+ int size = v.size();
+
+ ext = new AuthInfoAccessExtension(critical);
+ String method = null;
+ String locationType = null;
+ String location = null;
+ String enable = null;
+
+ for (int i = 0; i < size; i++) {
+ NameValuePairs nvps = v.elementAt(i);
+
+ for (String name1 : nvps.keySet()) {
+
+ if (name1.equals(AD_METHOD)) {
+ method = nvps.get(name1);
+ } else if (name1.equals(AD_LOCATION_TYPE)) {
+ locationType = nvps.get(name1);
+ } else if (name1.equals(AD_LOCATION)) {
+ location = nvps.get(name1);
+ } else if (name1.equals(AD_ENABLE)) {
+ enable = nvps.get(name1);
+ }
+ }
+
+ if (enable != null && enable.equals("true")) {
+ GeneralName gn = null;
+
+ if (locationType != null || location != null) {
+ GeneralNameInterface interface1 = parseGeneralName(locationType + ":" + location);
+ if (interface1 == null)
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", locationType));
+ gn = new GeneralName(interface1);
+ }
+
+ if (method != null) {
+ try {
+ ext.addAccessDescription(new ObjectIdentifier(method), gn);
+ } catch (NumberFormatException ee) {
+ CMS.debug("AuthInfoAccessExtDefault: " + ee.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_PROFILE_DEF_AIA_OID", method));
+ }
+ }
+ }
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ replaceExtension(ext.getExtensionId().toString(), ext, info);
+ } catch (IOException e) {
+ CMS.debug("AuthInfoAccessExtDefault: " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } catch (EProfileException e) {
+ CMS.debug("AuthInfoAccessExtDefault: " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ AuthInfoAccessExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ AuthInfoAccessExtension a = new AuthInfoAccessExtension(false);
+ ObjectIdentifier oid = a.getExtensionId();
+
+ ext = (AuthInfoAccessExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ CMS.debug("AuthInfoAccessExtDefault: getValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+ if (name.equals(VAL_CRITICAL)) {
+
+ ext = (AuthInfoAccessExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_GENERAL_NAMES)) {
+
+ ext = (AuthInfoAccessExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null)
+ return "";
+
+ int num = getNumAds();
+
+ CMS.debug("AuthInfoAccess num=" + num);
+ Vector<NameValuePairs> recs = new Vector<NameValuePairs>();
+
+ for (int i = 0; i < num; i++) {
+ NameValuePairs np = new NameValuePairs();
+ AccessDescription des = null;
+
+ if (i < ext.numberOfAccessDescription()) {
+ des = ext.getAccessDescription(i);
+ }
+ if (des == null) {
+ np.put(AD_METHOD, "");
+ np.put(AD_LOCATION_TYPE, "");
+ np.put(AD_LOCATION, "");
+ np.put(AD_ENABLE, "false");
+ } else {
+ ObjectIdentifier methodOid = des.getMethod();
+ GeneralName gn = des.getLocation();
+
+ np.put(AD_METHOD, methodOid.toString());
+ np.put(AD_LOCATION_TYPE, getGeneralNameType(gn));
+ np.put(AD_LOCATION, getGeneralNameValue(gn));
+ np.put(AD_ENABLE, "true");
+ }
+ recs.addElement(np);
+ }
+
+ return buildRecords(recs);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ StringBuffer ads = new StringBuffer();
+ int num = getNumAds();
+
+ for (int i = 0; i < num; i++) {
+ ads.append("Record #");
+ ads.append(i);
+ ads.append("{");
+ ads.append(AD_METHOD + ":");
+ ads.append(getConfig(CONFIG_AD_METHOD + i));
+ ads.append(",");
+ ads.append(AD_LOCATION_TYPE + ":");
+ ads.append(getConfig(CONFIG_AD_LOCATIONTYPE + i));
+ ads.append(",");
+ ads.append(AD_LOCATION + ":");
+ ads.append(getConfig(CONFIG_AD_LOCATION + i));
+ ads.append(",");
+ ads.append(AD_ENABLE + ":");
+ ads.append(getConfig(CONFIG_AD_ENABLE + i));
+ ads.append("}");
+ }
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_AIA_TEXT",
+ getConfig(CONFIG_CRITICAL), ads.toString());
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ AuthInfoAccessExtension ext = createExtension();
+
+ addExtension(ext.getExtensionId().toString(), ext, info);
+ }
+
+ public AuthInfoAccessExtension createExtension() {
+ AuthInfoAccessExtension ext = null;
+ int num = getNumAds();
+
+ try {
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+
+ ext = new AuthInfoAccessExtension(critical);
+ for (int i = 0; i < num; i++) {
+ String enable = getConfig(CONFIG_AD_ENABLE + i);
+ if (enable != null && enable.equals("true")) {
+ CMS.debug("AuthInfoAccess: createExtension i=" + i);
+ String method = getConfig(CONFIG_AD_METHOD + i);
+ String locationType = getConfig(CONFIG_AD_LOCATIONTYPE + i);
+ if (locationType == null || locationType.length() == 0)
+ locationType = "URIName";
+ String location = getConfig(CONFIG_AD_LOCATION + i);
+
+ if (location == null || location.equals("")) {
+ if (method.equals("1.3.6.1.5.5.7.48.1")) {
+ String hostname = CMS.getEENonSSLHost();
+ String port = CMS.getEENonSSLPort();
+ if (hostname != null && port != null)
+ // location = "http://"+hostname+":"+port+"/ocsp/ee/ocsp";
+ location = "http://" + hostname + ":" + port + "/ca/ocsp";
+ }
+ }
+
+ String s = locationType + ":" + location;
+ GeneralNameInterface gn = parseGeneralName(s);
+ if (gn != null) {
+ ext.addAccessDescription(new ObjectIdentifier(method),
+ new GeneralName(gn));
+ }
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("AuthInfoAccessExtDefault: createExtension " +
+ e.toString());
+ }
+
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/AuthTokenSubjectNameDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/AuthTokenSubjectNameDefault.java
new file mode 100644
index 000000000..e789625e4
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/AuthTokenSubjectNameDefault.java
@@ -0,0 +1,152 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy that
+ * populates subject name based on the attribute values
+ * in the authentication token (AuthToken) object.
+ *
+ * @version $Revision$, $Date$
+ */
+public class AuthTokenSubjectNameDefault extends EnrollDefault {
+
+ public static final String VAL_NAME = "name";
+
+ public AuthTokenSubjectNameDefault() {
+ super();
+ addValueName(VAL_NAME);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_NAME)) {
+ return new Descriptor(IDescriptor.STRING, null, null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SUBJECT_NAME"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ CMS.debug("AuthTokenSubjectNameDefault: begins");
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(locale,
+ "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NAME)) {
+ X500Name x500name = null;
+
+ try {
+ x500name = new X500Name(value);
+ CMS.debug("AuthTokenSubjectNameDefault: setValue x500name=" + x500name.toString());
+ } catch (IOException e) {
+ CMS.debug("AuthTokenSubjectNameDefault: setValue " +
+ e.toString());
+ // failed to build x500 name
+ }
+ CMS.debug("AuthTokenSubjectNameDefault: setValue name=" + x500name.toString());
+ try {
+ info.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(x500name));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("AuthTokenSubjectNameDefault: setValue " +
+ e.toString());
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(locale,
+ "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ if (name == null)
+ throw new EPropertyException("Invalid name " + name);
+ if (name.equals(VAL_NAME)) {
+ CertificateSubjectName sn = null;
+
+ try {
+ sn = (CertificateSubjectName)
+ info.get(X509CertInfo.SUBJECT);
+ return sn.toString();
+ } catch (Exception e) {
+ // nothing
+ CMS.debug("AuthTokenSubjectNameDefault: getValue " +
+ e.toString());
+ }
+ throw new EPropertyException(CMS.getUserMessage(locale,
+ "CMS_INVALID_PROPERTY", name));
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(locale,
+ "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_DEF_AUTHTOKEN_SUBJECT_NAME");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+
+ // authenticate the subject name and populate it
+ // to the certinfo
+ try {
+ X500Name name = new X500Name(
+ request.getExtDataInString(IProfileAuthenticator.AUTHENTICATED_NAME));
+
+ CMS.debug("AuthTokenSubjectNameDefault: X500Name=" + name.toString());
+ info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(name));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("AuthTokenSubjectNameDefault: " + e.toString());
+ throw new EProfileException(CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_SUBJECT_NAME_NOT_FOUND"));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java
new file mode 100644
index 000000000..77fd0a5fd
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java
@@ -0,0 +1,190 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.x509.AuthorityKeyIdentifierExtension;
+import netscape.security.x509.KeyIdentifier;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates Authority Key Identifier extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class AuthorityKeyIdentifierExtDefault extends CAEnrollDefault {
+
+ public static final String VAL_CRITICAL = "critical";
+ public static final String VAL_KEY_ID = "keyid";
+
+ public AuthorityKeyIdentifierExtDefault() {
+ super();
+
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_KEY_ID);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.STRING,
+ IDescriptor.READONLY, null, CMS.getUserMessage(locale,
+ "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_KEY_ID)) {
+ return new Descriptor(IDescriptor.STRING,
+ IDescriptor.READONLY, null, CMS.getUserMessage(locale,
+ "CMS_PROFILE_KEY_ID"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_CRITICAL)) {
+ // do nothing for read only value
+ } else if (name.equals(VAL_KEY_ID)) {
+ // do nothing for read only value
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ AuthorityKeyIdentifierExtension ext =
+ (AuthorityKeyIdentifierExtension) getExtension(
+ PKIXExtensions.AuthorityKey_Id.toString(), info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ CMS.debug("BasicConstraintsExtDefault: getValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+ if (name.equals(VAL_CRITICAL)) {
+ ext =
+ (AuthorityKeyIdentifierExtension) getExtension(
+ PKIXExtensions.AuthorityKey_Id.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_KEY_ID)) {
+ ext =
+ (AuthorityKeyIdentifierExtension) getExtension(
+ PKIXExtensions.AuthorityKey_Id.toString(), info);
+
+ if (ext == null) {
+ // do something here
+ return "";
+ }
+ KeyIdentifier kid = null;
+
+ try {
+ kid = (KeyIdentifier)
+ ext.get(AuthorityKeyIdentifierExtension.KEY_ID);
+ } catch (IOException e) {
+ //
+ CMS.debug(e.toString());
+ }
+ if (kid == null)
+ return "";
+ return toHexString(kid.getIdentifier());
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_AKI_EXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ AuthorityKeyIdentifierExtension ext = createExtension(info);
+
+ addExtension(PKIXExtensions.AuthorityKey_Id.toString(), ext, info);
+ }
+
+ public AuthorityKeyIdentifierExtension createExtension(X509CertInfo info) {
+ KeyIdentifier kid = null;
+ String localKey = getConfig("localKey");
+ if (localKey != null && localKey.equals("true")) {
+ kid = getKeyIdentifier(info);
+ } else {
+ kid = getCAKeyIdentifier();
+ }
+
+ if (kid == null)
+ return null;
+ AuthorityKeyIdentifierExtension ext = null;
+
+ try {
+ ext = new AuthorityKeyIdentifierExtension(false, kid, null, null);
+ } catch (IOException e) {
+ CMS.debug("AuthorityKeyIdentifierExtDefault: createExtension " +
+ e.toString());
+ }
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/AutoAssignDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/AutoAssignDefault.java
new file mode 100644
index 000000000..f685a4f59
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/AutoAssignDefault.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.util.Locale;
+
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that automatically assign request to agent.
+ *
+ * @version $Revision$, $Date$
+ */
+public class AutoAssignDefault extends EnrollDefault {
+
+ public static final String CONFIG_ASSIGN_TO = "assignTo";
+
+ public AutoAssignDefault() {
+ super();
+ addConfigName(CONFIG_ASSIGN_TO);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_ASSIGN_TO)) {
+ return new Descriptor(IDescriptor.STRING,
+ null, "admin", CMS.getUserMessage(locale,
+ "CMS_PROFILE_AUTO_ASSIGN"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ return null;
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_AUTO_ASSIGN",
+ getConfig(CONFIG_ASSIGN_TO));
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ try {
+ request.setRequestOwner(
+ mapPattern(request, getConfig(CONFIG_ASSIGN_TO)));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("AutoAssignDefault: populate " + e.toString());
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/BasicConstraintsExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/BasicConstraintsExtDefault.java
new file mode 100644
index 000000000..a827b7eaf
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/BasicConstraintsExtDefault.java
@@ -0,0 +1,297 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates Basic Constraint extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class BasicConstraintsExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "basicConstraintsCritical";
+ public static final String CONFIG_IS_CA = "basicConstraintsIsCA";
+ public static final String CONFIG_PATH_LEN = "basicConstraintsPathLen";
+
+ public static final String VAL_CRITICAL = "basicConstraintsCritical";
+ public static final String VAL_IS_CA = "basicConstraintsIsCA";
+ public static final String VAL_PATH_LEN = "basicConstraintsPathLen";
+
+ public BasicConstraintsExtDefault() {
+ super();
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_IS_CA);
+ addValueName(VAL_PATH_LEN);
+
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_IS_CA);
+ addConfigName(CONFIG_PATH_LEN);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(CONFIG_IS_CA)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "true",
+ CMS.getUserMessage(locale, "CMS_PROFILE_IS_CA"));
+ } else if (name.equals(CONFIG_PATH_LEN)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "-1",
+ CMS.getUserMessage(locale, "CMS_PROFILE_PATH_LEN"));
+ }
+ return null;
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_IS_CA)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "true",
+ CMS.getUserMessage(locale, "CMS_PROFILE_IS_CA"));
+ } else if (name.equals(VAL_PATH_LEN)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "-1",
+ CMS.getUserMessage(locale, "CMS_PROFILE_PATH_LEN"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ BasicConstraintsExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (BasicConstraintsExtension)
+ getExtension(PKIXExtensions.BasicConstraints_Id.toString(), info);
+
+ if (ext == null) {
+ populate(null, info);
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+
+ ext = (BasicConstraintsExtension)
+ getExtension(PKIXExtensions.BasicConstraints_Id.toString(), info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ if (ext == null) {
+ return;
+ }
+ ext.setCritical(val);
+ } else if (name.equals(VAL_IS_CA)) {
+ ext = (BasicConstraintsExtension)
+ getExtension(PKIXExtensions.BasicConstraints_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean isCA = Boolean.valueOf(value);
+
+ ext.set(BasicConstraintsExtension.IS_CA, isCA);
+ } else if (name.equals(VAL_PATH_LEN)) {
+ ext = (BasicConstraintsExtension)
+ getExtension(PKIXExtensions.BasicConstraints_Id.toString(), info);
+
+ if (ext == null) {
+ return;
+ }
+ Integer pathLen = Integer.valueOf(value);
+
+ ext.set(BasicConstraintsExtension.PATH_LEN, pathLen);
+ } else {
+ throw new EPropertyException("Invalid name " + name);
+ }
+ replaceExtension(PKIXExtensions.BasicConstraints_Id.toString(),
+ ext, info);
+ } catch (IOException e) {
+ CMS.debug("BasicConstraintsExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } catch (EProfileException e) {
+ CMS.debug("BasicConstraintsExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ try {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ BasicConstraintsExtension ext = (BasicConstraintsExtension)
+ getExtension(PKIXExtensions.BasicConstraints_Id.toString(), info);
+
+ if (ext == null) {
+ CMS.debug("BasicConstraintsExtDefault: getValue ext is null, populating a new one ");
+
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ CMS.debug("BasicConstraintsExtDefault: getValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (BasicConstraintsExtension)
+ getExtension(PKIXExtensions.BasicConstraints_Id.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_IS_CA)) {
+ ext = (BasicConstraintsExtension)
+ getExtension(PKIXExtensions.BasicConstraints_Id.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ Boolean isCA = (Boolean) ext.get(BasicConstraintsExtension.IS_CA);
+
+ return isCA.toString();
+ } else if (name.equals(VAL_PATH_LEN)) {
+ ext = (BasicConstraintsExtension)
+ getExtension(PKIXExtensions.BasicConstraints_Id.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ Integer pathLen = (Integer)
+ ext.get(BasicConstraintsExtension.PATH_LEN);
+
+ String pLen = null;
+
+ pLen = pathLen.toString();
+ if (pLen.equals("-2")) {
+ //This is done for bug 621700. Profile constraints actually checks for -1
+ //The low level security class for some reason sets this to -2
+ //This will allow the request to be approved successfuly by the agent.
+
+ pLen = "-1";
+
+ }
+
+ CMS.debug("BasicConstriantsExtDefault getValue(pLen) " + pLen);
+
+ return pLen;
+
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } catch (IOException e) {
+ CMS.debug("BasicConstraintsExtDefault: getValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_CRITICAL),
+ getConfig(CONFIG_IS_CA),
+ getConfig(CONFIG_PATH_LEN)
+ };
+
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_BASIC_CONSTRAINTS_EXT", params);
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ BasicConstraintsExtension ext = createExtension();
+
+ addExtension(PKIXExtensions.BasicConstraints_Id.toString(), ext,
+ info);
+ }
+
+ public BasicConstraintsExtension createExtension() {
+ BasicConstraintsExtension ext = null;
+
+ boolean critical = Boolean.valueOf(getConfig(CONFIG_CRITICAL)).booleanValue();
+ boolean isCA = Boolean.valueOf(getConfig(CONFIG_IS_CA)).booleanValue();
+ String pathLenStr = getConfig(CONFIG_PATH_LEN);
+
+ int pathLen = -2;
+
+ if (!pathLenStr.equals("")) {
+
+ pathLen = Integer.valueOf(pathLenStr).intValue();
+ }
+
+ try {
+ ext = new BasicConstraintsExtension(isCA, critical, pathLen);
+ } catch (Exception e) {
+ CMS.debug("BasicConstraintsExtDefault: createExtension " +
+ e.toString());
+ return null;
+ }
+ ext.setCritical(critical);
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/CAEnrollDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/CAEnrollDefault.java
new file mode 100644
index 000000000..1d1d05ed5
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/CAEnrollDefault.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.KeyIdentifier;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.SubjectKeyIdentifierExtension;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+
+/**
+ * This class implements an abstract CA specific
+ * Enrollment default. This policy can only be
+ * used with CA subsystem.
+ *
+ * @version $Revision$, $Date$
+ */
+public abstract class CAEnrollDefault extends EnrollDefault {
+ public CAEnrollDefault() {
+ }
+
+ public KeyIdentifier getKeyIdentifier(X509CertInfo info) {
+ try {
+ CertificateX509Key ckey = (CertificateX509Key)
+ info.get(X509CertInfo.KEY);
+ X509Key key = (X509Key) ckey.get(CertificateX509Key.KEY);
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+
+ md.update(key.getKey());
+ byte[] hash = md.digest();
+
+ return new KeyIdentifier(hash);
+ } catch (IOException e) {
+ CMS.debug("AuthorityKeyIdentifierExtDefault: getKeyId " +
+ e.toString());
+ } catch (CertificateException e) {
+ CMS.debug("AuthorityKeyIdentifierExtDefault: getKeyId " +
+ e.toString());
+ } catch (NoSuchAlgorithmException e) {
+ CMS.debug("AuthorityKeyIdentifierExtDefault: getKeyId " +
+ e.toString());
+ }
+ return null;
+ }
+
+ public KeyIdentifier getCAKeyIdentifier() {
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ X509CertImpl caCert = ca.getCACert();
+ if (caCert == null) {
+ // during configuration, we dont have the CA certificate
+ return null;
+ }
+ X509Key key = (X509Key) caCert.getPublicKey();
+
+ SubjectKeyIdentifierExtension subjKeyIdExt =
+ (SubjectKeyIdentifierExtension)
+ caCert.getExtension(PKIXExtensions.SubjectKey_Id.toString());
+ if (subjKeyIdExt != null) {
+ try {
+ KeyIdentifier keyId = (KeyIdentifier) subjKeyIdExt.get(
+ SubjectKeyIdentifierExtension.KEY_ID);
+ return keyId;
+ } catch (IOException e) {
+ }
+ }
+
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+
+ md.update(key.getKey());
+ byte[] hash = md.digest();
+
+ return new KeyIdentifier(hash);
+ } catch (NoSuchAlgorithmException e) {
+ CMS.debug("AuthorityKeyIdentifierExtDefault: getKeyId " +
+ e.toString());
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/CAValidityDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/CAValidityDefault.java
new file mode 100644
index 000000000..44ffd474f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/CAValidityDefault.java
@@ -0,0 +1,348 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements a CA signing cert enrollment default policy
+ * that populates a server-side configurable validity
+ * into the certificate template.
+ * It allows an agent to bypass the CA's signing cert's expiration constraint
+ */
+public class CAValidityDefault extends EnrollDefault {
+ public static final String CONFIG_RANGE = "range";
+ public static final String CONFIG_START_TIME = "startTime";
+ public static final String CONFIG_BYPASS_CA_NOTAFTER = "bypassCAnotafter";
+
+ public static final String VAL_NOT_BEFORE = "notBefore";
+ public static final String VAL_NOT_AFTER = "notAfter";
+ public static final String VAL_BYPASS_CA_NOTAFTER = "bypassCAnotafter";
+
+ public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
+
+ private long mDefault = 86400000; // 1 days
+ public ICertificateAuthority mCA = null;
+
+ public CAValidityDefault() {
+ super();
+ addConfigName(CONFIG_RANGE);
+ addConfigName(CONFIG_START_TIME);
+ addConfigName(CONFIG_BYPASS_CA_NOTAFTER);
+
+ addValueName(VAL_NOT_BEFORE);
+ addValueName(VAL_NOT_AFTER);
+ addValueName(VAL_BYPASS_CA_NOTAFTER);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ mCA = (ICertificateAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ if (name.equals(CONFIG_RANGE)) {
+ try {
+ Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_RANGE));
+ }
+ } else if (name.equals(CONFIG_START_TIME)) {
+ try {
+ Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_START_TIME));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_RANGE)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ "7305", /* 20 years */
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_VALIDITY_RANGE"));
+ } else if (name.equals(CONFIG_START_TIME)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ "60", /* 1 minute */
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_VALIDITY_START_TIME"));
+ } else if (name.equals(CONFIG_BYPASS_CA_NOTAFTER)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_BYPASS_CA_NOTAFTER"));
+
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_NOT_BEFORE)) {
+ return new Descriptor(IDescriptor.STRING, null, null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NOT_BEFORE"));
+ } else if (name.equals(VAL_NOT_AFTER)) {
+ return new Descriptor(IDescriptor.STRING, null, null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NOT_AFTER"));
+ } else if (name.equals(VAL_BYPASS_CA_NOTAFTER)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_BYPASS_CA_NOTAFTER"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (value == null || value.equals("")) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ CMS.debug("CAValidityDefault: setValue name= " + name);
+
+ if (name.equals(VAL_NOT_BEFORE)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+ ParsePosition pos = new ParsePosition(0);
+ Date date = formatter.parse(value, pos);
+ CertificateValidity validity = null;
+
+ try {
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ validity.set(CertificateValidity.NOT_BEFORE,
+ date);
+ } catch (Exception e) {
+ CMS.debug("CAValidityDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else if (name.equals(VAL_NOT_AFTER)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+ ParsePosition pos = new ParsePosition(0);
+ Date date = formatter.parse(value, pos);
+ CertificateValidity validity = null;
+
+ try {
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ validity.set(CertificateValidity.NOT_AFTER,
+ date);
+ } catch (Exception e) {
+ CMS.debug("CAValidityDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else if (name.equals(VAL_BYPASS_CA_NOTAFTER)) {
+ boolean bypassCAvalidity = Boolean.valueOf(value).booleanValue();
+ CMS.debug("CAValidityDefault: setValue: bypassCAvalidity=" + bypassCAvalidity);
+
+ BasicConstraintsExtension ext = (BasicConstraintsExtension)
+ getExtension(PKIXExtensions.BasicConstraints_Id.toString(), info);
+
+ if (ext == null) {
+ CMS.debug("CAValidityDefault: setValue: this default cannot be applied to non-CA cert.");
+ return;
+ }
+ try {
+ Boolean isCA = (Boolean) ext.get(BasicConstraintsExtension.IS_CA);
+ if (isCA.booleanValue() != true) {
+ CMS.debug("CAValidityDefault: setValue: this default cannot be aplied to non-CA cert.");
+ return;
+ }
+ } catch (Exception e) {
+ CMS.debug("CAValidityDefault: setValue: this default cannot be aplied to non-CA cert." + e.toString());
+ return;
+ }
+
+ CertificateValidity validity = null;
+ Date notAfter = null;
+ try {
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ notAfter = (Date) validity.get(CertificateValidity.NOT_AFTER);
+ } catch (Exception e) {
+ CMS.debug("CAValidityDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ // not to exceed CA's expiration
+ Date caNotAfter =
+ mCA.getSigningUnit().getCertImpl().getNotAfter();
+
+ if (notAfter.after(caNotAfter)) {
+ if (bypassCAvalidity == false) {
+ notAfter = caNotAfter;
+ CMS.debug("CAValidityDefault: setValue: bypassCAvalidity off. reset notAfter to caNotAfter. reset ");
+ } else {
+ CMS.debug("CAValidityDefault: setValue: bypassCAvalidity on. notAfter is after caNotAfter. no reset");
+ }
+ }
+ try {
+ validity.set(CertificateValidity.NOT_AFTER,
+ notAfter);
+ } catch (Exception e) {
+ CMS.debug("CAValidityDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+
+ if (name == null)
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+
+ CMS.debug("CAValidityDefault: getValue: name= " + name);
+ if (name.equals(VAL_NOT_BEFORE)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+ CertificateValidity validity = null;
+
+ try {
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ return formatter.format((Date)
+ validity.get(CertificateValidity.NOT_BEFORE));
+ } catch (Exception e) {
+ CMS.debug("CAValidityDefault: getValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else if (name.equals(VAL_NOT_AFTER)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+ CertificateValidity validity = null;
+
+ try {
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ return formatter.format((Date)
+ validity.get(CertificateValidity.NOT_AFTER));
+ } catch (Exception e) {
+ CMS.debug("CAValidityDefault: getValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else if (name.equals(VAL_BYPASS_CA_NOTAFTER)) {
+ return "false";
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_RANGE),
+ getConfig(CONFIG_BYPASS_CA_NOTAFTER)
+ };
+
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_VALIDITY", params);
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+
+ // always + 60 seconds
+ String startTimeStr = getConfig(CONFIG_START_TIME);
+ try {
+ startTimeStr = mapPattern(request, startTimeStr);
+ } catch (IOException e) {
+ CMS.debug("CAValidityDefault: populate " + e.toString());
+ }
+
+ if (startTimeStr == null || startTimeStr.equals("")) {
+ startTimeStr = "60";
+ }
+ int startTime = Integer.parseInt(startTimeStr);
+ Date notBefore = new Date(CMS.getCurrentDate().getTime() + (1000 * startTime));
+ long notAfterVal = 0;
+
+ try {
+ String rangeStr = getConfig(CONFIG_RANGE);
+ rangeStr = mapPattern(request, rangeStr);
+ notAfterVal = notBefore.getTime() +
+ (mDefault * Integer.parseInt(rangeStr));
+ } catch (Exception e) {
+ // configured value is not correct
+ CMS.debug("CAValidityDefault: populate " + e.toString());
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_INVALID_PROPERTY", CONFIG_RANGE));
+ }
+ Date notAfter = new Date(notAfterVal);
+
+ CertificateValidity validity =
+ new CertificateValidity(notBefore, notAfter);
+
+ try {
+ info.set(X509CertInfo.VALIDITY, validity);
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("CAValidityDefault: populate " + e.toString());
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_INVALID_PROPERTY", X509CertInfo.VALIDITY));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/CRLDistributionPointsExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/CRLDistributionPointsExtDefault.java
new file mode 100644
index 000000000..4bbd215a2
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/CRLDistributionPointsExtDefault.java
@@ -0,0 +1,696 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.security.util.BitArray;
+import netscape.security.x509.CRLDistributionPoint;
+import netscape.security.x509.CRLDistributionPointsExtension;
+import netscape.security.x509.CRLDistributionPointsExtension.Reason;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.GeneralNamesException;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.RDN;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a CRL Distribution points extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CRLDistributionPointsExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "crlDistPointsCritical";
+ public static final String CONFIG_NUM_POINTS = "crlDistPointsNum";
+ public static final String CONFIG_POINT_TYPE = "crlDistPointsPointType_";
+ public static final String CONFIG_POINT_NAME = "crlDistPointsPointName_";
+ public static final String CONFIG_REASONS = "crlDistPointsReasons_";
+ public static final String CONFIG_ISSUER_TYPE = "crlDistPointsIssuerType_";
+ public static final String CONFIG_ISSUER_NAME = "crlDistPointsIssuerName_";
+ public static final String CONFIG_ENABLE = "crlDistPointsEnable_";
+
+ public static final String VAL_CRITICAL = "crlDistPointsCritical";
+ public static final String VAL_CRL_DISTRIBUTION_POINTS = "crlDistPointsValue";
+
+ private static final String REASONS = "Reasons";
+ private static final String POINT_TYPE = "Point Type";
+ private static final String POINT_NAME = "Point Name";
+ private static final String ISSUER_TYPE = "Issuer Type";
+ private static final String ISSUER_NAME = "Issuer Name";
+ private static final String ENABLE = "Enable";
+
+ private static final String RELATIVETOISSUER = "RelativeToIssuer";
+
+ private static final int DEF_NUM_POINTS = 1;
+ private static final int MAX_NUM_POINTS = 100;
+
+ public CRLDistributionPointsExtDefault() {
+ super();
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ refreshConfigAndValueNames();
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ int num = 0;
+ if (name.equals(CONFIG_NUM_POINTS)) {
+ try {
+ num = Integer.parseInt(value);
+
+ if (num >= MAX_NUM_POINTS || num < 0) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_POINTS));
+ }
+
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_POINTS));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public Enumeration<String> getConfigNames() {
+ refreshConfigAndValueNames();
+ return super.getConfigNames();
+ }
+
+ protected void refreshConfigAndValueNames() {
+ super.refreshConfigAndValueNames();
+
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_CRL_DISTRIBUTION_POINTS);
+
+ addConfigName(CONFIG_CRITICAL);
+ int num = getNumPoints();
+
+ addConfigName(CONFIG_NUM_POINTS);
+ for (int i = 0; i < num; i++) {
+ addConfigName(CONFIG_POINT_TYPE + i);
+ addConfigName(CONFIG_POINT_NAME + i);
+ addConfigName(CONFIG_REASONS + i);
+ addConfigName(CONFIG_ISSUER_TYPE + i);
+ addConfigName(CONFIG_ISSUER_NAME + i);
+ addConfigName(CONFIG_ENABLE + i);
+ }
+ }
+
+ protected int getNumPoints() {
+ int num = DEF_NUM_POINTS;
+ String val = getConfig(CONFIG_NUM_POINTS);
+
+ if (val != null) {
+ try {
+ num = Integer.parseInt(val);
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ }
+
+ if (num >= MAX_NUM_POINTS)
+ num = DEF_NUM_POINTS;
+
+ return num;
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.startsWith(CONFIG_POINT_TYPE)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_POINT_TYPE"));
+ } else if (name.startsWith(CONFIG_POINT_NAME)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_POINT_NAME"));
+ } else if (name.startsWith(CONFIG_REASONS)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_REASONS"));
+ } else if (name.startsWith(CONFIG_ISSUER_TYPE)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_ISSUER_TYPE"));
+ } else if (name.startsWith(CONFIG_ISSUER_NAME)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_ISSUER_NAME"));
+ } else if (name.startsWith(CONFIG_ENABLE)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_ENABLE"));
+ } else if (name.startsWith(CONFIG_NUM_POINTS)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "1",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NUM_DIST_POINTS"));
+
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_CRL_DISTRIBUTION_POINTS)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRL_DISTRIBUTION_POINTS"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ CRLDistributionPointsExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (CRLDistributionPointsExtension)
+ getExtension(PKIXExtensions.CRLDistributionPoints_Id.toString(),
+ info);
+
+ if (ext == null) {
+ populate(locale, info);
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (CRLDistributionPointsExtension)
+ getExtension(PKIXExtensions.CRLDistributionPoints_Id.toString(),
+ info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ if (ext == null) {
+ return;
+ }
+ ext.setCritical(val);
+ } else if (name.equals(VAL_CRL_DISTRIBUTION_POINTS)) {
+ ext = (CRLDistributionPointsExtension)
+ getExtension(PKIXExtensions.CRLDistributionPoints_Id.toString(),
+ info);
+
+ if (ext == null) {
+ return;
+ }
+ Vector<NameValuePairs> v = parseRecords(value);
+ int size = v.size();
+
+ boolean critical = ext.isCritical();
+ int i = 0;
+
+ for (; i < size; i++) {
+ NameValuePairs nvps = v.elementAt(i);
+ String pointType = null;
+ String pointValue = null;
+ String issuerType = null;
+ String issuerValue = null;
+ String enable = null;
+ CRLDistributionPoint cdp = new CRLDistributionPoint();
+
+ for (String name1 : nvps.keySet()) {
+
+ if (name1.equals(REASONS)) {
+ addReasons(locale, cdp, REASONS, nvps.get(name1));
+ } else if (name1.equals(POINT_TYPE)) {
+ pointType = nvps.get(name1);
+ } else if (name1.equals(POINT_NAME)) {
+ pointValue = nvps.get(name1);
+ } else if (name1.equals(ISSUER_TYPE)) {
+ issuerType = nvps.get(name1);
+ } else if (name1.equals(ISSUER_NAME)) {
+ issuerValue = nvps.get(name1);
+ } else if (name1.equals(ENABLE)) {
+ enable = nvps.get(name1);
+ }
+ }
+
+ if (enable != null && enable.equals("true")) {
+ if (pointType != null)
+ addCRLPoint(locale, cdp, pointType, pointValue);
+ if (issuerType != null)
+ addIssuer(locale, cdp, issuerType, issuerValue);
+
+ // this is the first distribution point
+ if (i == 0) {
+ ext = new CRLDistributionPointsExtension(cdp);
+ ext.setCritical(critical);
+ } else {
+ ext.addPoint(cdp);
+ }
+ }
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ replaceExtension(PKIXExtensions.CRLDistributionPoints_Id.toString(),
+ ext, info);
+ } catch (EProfileException e) {
+ CMS.debug("CRLDistributionPointsExtDefault: setValue " +
+ e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ private void addCRLPoint(Locale locale, CRLDistributionPoint cdp, String type,
+ String value) throws EPropertyException {
+ try {
+ if (value == null || value.length() == 0)
+ return;
+
+ if (type.equals(RELATIVETOISSUER)) {
+ cdp.setRelativeName(new RDN(value));
+ } else if (isGeneralNameType(type)) {
+ GeneralNames gen = new GeneralNames();
+ gen.addElement(parseGeneralName(type, value));
+ cdp.setFullName(gen);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", type));
+ }
+ } catch (IOException e) {
+ CMS.debug("CRLDistributionPointsExtDefault: addCRLPoint " +
+ e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", type));
+ } catch (GeneralNamesException e) {
+ CMS.debug("CRLDistributionPointsExtDefault: addCRLPoint " +
+ e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", type));
+ }
+ }
+
+ private void addIssuer(Locale locale, CRLDistributionPoint cdp, String type,
+ String value) throws EPropertyException {
+ if (value == null || value.length() == 0)
+ return;
+ try {
+ if (isGeneralNameType(type)) {
+ GeneralNames gen = new GeneralNames();
+
+ gen.addElement(parseGeneralName(type, value));
+ cdp.setCRLIssuer(gen);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", type));
+ }
+ } catch (IOException e) {
+ CMS.debug("CRLDistributionPointsExtDefault: addIssuer " +
+ e.toString());
+ } catch (GeneralNamesException e) {
+ CMS.debug("CRLDistributionPointsExtDefault: addIssuer " +
+ e.toString());
+ }
+ }
+
+ private void addReasons(Locale locale, CRLDistributionPoint cdp, String type,
+ String value) throws EPropertyException {
+ if (value == null || value.length() == 0)
+ return;
+ if (type.equals(REASONS)) {
+ if (value != null && !value.equals("")) {
+ StringTokenizer st = new StringTokenizer(value, ", \t");
+ byte reasonBits = 0;
+
+ while (st.hasMoreTokens()) {
+ String s = st.nextToken();
+ Reason r = Reason.fromString(s);
+
+ if (r == null) {
+ CMS.debug("CRLDistributeionPointsExtDefault: addReasons Unknown reason: " + s);
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", s));
+ } else {
+ reasonBits |= r.getBitMask();
+ }
+ }
+
+ if (reasonBits != 0) {
+ BitArray ba = new BitArray(8, new byte[] { reasonBits }
+ );
+
+ cdp.setReasons(ba);
+ }
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", type));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ CRLDistributionPointsExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (CRLDistributionPointsExtension)
+ getExtension(PKIXExtensions.CRLDistributionPoints_Id.toString(),
+ info);
+
+ if (ext == null) {
+ try {
+ populate(locale, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (CRLDistributionPointsExtension)
+ getExtension(PKIXExtensions.CRLDistributionPoints_Id.toString(),
+ info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_CRL_DISTRIBUTION_POINTS)) {
+ ext = (CRLDistributionPointsExtension)
+ getExtension(PKIXExtensions.CRLDistributionPoints_Id.toString(),
+ info);
+
+ if (ext == null)
+ return "";
+
+ Vector<NameValuePairs> recs = new Vector<NameValuePairs>();
+ int num = getNumPoints();
+
+ for (int i = 0; i < num; i++) {
+ NameValuePairs pairs = null;
+
+ if (i < ext.getNumPoints()) {
+ CRLDistributionPoint p = ext.getPointAt(i);
+ GeneralNames gns = p.getFullName();
+
+ pairs = buildGeneralNames(gns, p);
+ recs.addElement(pairs);
+ } else {
+ pairs = buildEmptyGeneralNames();
+ recs.addElement(pairs);
+ }
+ }
+
+ return buildRecords(recs);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ protected NameValuePairs buildEmptyGeneralNames() {
+ NameValuePairs pairs = new NameValuePairs();
+
+ pairs.put(POINT_TYPE, "");
+ pairs.put(POINT_NAME, "");
+ pairs.put(REASONS, "");
+ pairs.put(ISSUER_TYPE, "");
+ pairs.put(ISSUER_NAME, "");
+ pairs.put(ENABLE, "false");
+ return pairs;
+ }
+
+ protected NameValuePairs buildGeneralNames(GeneralNames gns, CRLDistributionPoint p)
+ throws EPropertyException {
+
+ NameValuePairs pairs = new NameValuePairs();
+
+ RDN rdn = null;
+ boolean hasFullName = false;
+
+ pairs.put(ENABLE, "true");
+ if (gns == null) {
+ rdn = p.getRelativeName();
+ if (rdn != null) {
+ hasFullName = true;
+ pairs.put(POINT_TYPE, RELATIVETOISSUER);
+ pairs.put(POINT_NAME, rdn.toString());
+ } else {
+ pairs.put(POINT_TYPE, "");
+ pairs.put(POINT_NAME, "");
+ }
+ } else {
+ GeneralName gn = (GeneralName) gns.elementAt(0);
+
+ if (gn != null) {
+ hasFullName = true;
+
+ pairs.put(POINT_TYPE, getGeneralNameType(gn));
+ pairs.put(POINT_NAME, getGeneralNameValue(gn));
+ }
+ }
+
+ if (!hasFullName) {
+ pairs.put(POINT_TYPE, GN_DIRECTORY_NAME);
+ pairs.put(POINT_NAME, "");
+ }
+
+ BitArray reasons = p.getReasons();
+ String s = convertBitArrayToReasonNames(reasons);
+
+ if (s.length() > 0) {
+ pairs.put(REASONS, s);
+ } else {
+ pairs.put(REASONS, "");
+ }
+
+ gns = p.getCRLIssuer();
+
+ if (gns == null) {
+ pairs.put(ISSUER_TYPE, GN_DIRECTORY_NAME);
+ pairs.put(ISSUER_NAME, "");
+ } else {
+ GeneralName gn = (GeneralName) gns.elementAt(0);
+
+ if (gn != null) {
+ hasFullName = true;
+
+ pairs.put(ISSUER_TYPE, getGeneralNameType(gn));
+ pairs.put(ISSUER_NAME, getGeneralNameValue(gn));
+ }
+ }
+ return pairs;
+ }
+
+ private String convertBitArrayToReasonNames(BitArray reasons) {
+ StringBuffer sb = new StringBuffer();
+
+ if (reasons != null) {
+ byte[] b = reasons.toByteArray();
+ Reason[] reasonArray = Reason.bitArrayToReasonArray(b);
+
+ for (int i = 0; i < reasonArray.length; i++) {
+ if (sb.length() > 0)
+ sb.append(",");
+ sb.append(reasonArray[i].getName());
+ }
+ }
+
+ return sb.toString();
+ }
+
+ public String getText(Locale locale) {
+ StringBuffer sb = new StringBuffer();
+ int num = getNumPoints();
+
+ for (int i = 0; i < num; i++) {
+ sb.append("Record #");
+ sb.append(i);
+ sb.append("{");
+ sb.append(POINT_TYPE + ":");
+ sb.append(getConfig(CONFIG_POINT_TYPE + i));
+ sb.append(",");
+ sb.append(POINT_NAME + ":");
+ sb.append(getConfig(CONFIG_POINT_NAME + i));
+ sb.append(",");
+ sb.append(REASONS + ":");
+ sb.append(getConfig(CONFIG_REASONS + i));
+ sb.append(",");
+ sb.append(ISSUER_TYPE + ":");
+ sb.append(getConfig(CONFIG_ISSUER_TYPE + i));
+ sb.append(",");
+ sb.append(ISSUER_NAME + ":");
+ sb.append(getConfig(CONFIG_ISSUER_NAME + i));
+ sb.append(",");
+ sb.append(ENABLE + ":");
+ sb.append(getConfig(CONFIG_ENABLE + i));
+ sb.append("}");
+ }
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_DEF_CRL_DIST_POINTS_EXT",
+ getConfig(CONFIG_CRITICAL),
+ sb.toString());
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ private void populate(Locale locale, X509CertInfo info)
+ throws EProfileException {
+ CRLDistributionPointsExtension ext = createExtension(locale);
+
+ if (ext == null)
+ return;
+ addExtension(PKIXExtensions.CRLDistributionPoints_Id.toString(),
+ ext, info);
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ CRLDistributionPointsExtension ext = createExtension(request);
+
+ if (ext == null)
+ return;
+ addExtension(PKIXExtensions.CRLDistributionPoints_Id.toString(),
+ ext, info);
+ }
+
+ public CRLDistributionPointsExtension createExtension(IRequest request) {
+ CRLDistributionPointsExtension ext = null;
+ int num = 0;
+
+ try {
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+
+ num = getNumPoints();
+ for (int i = 0; i < num; i++) {
+ CRLDistributionPoint cdp = new CRLDistributionPoint();
+
+ String enable = getConfig(CONFIG_ENABLE + i);
+ String pointType = getConfig(CONFIG_POINT_TYPE + i);
+ String pointName = getConfig(CONFIG_POINT_NAME + i);
+ String reasons = getConfig(CONFIG_REASONS + i);
+ String issuerType = getConfig(CONFIG_ISSUER_TYPE + i);
+ String issuerName = getConfig(CONFIG_ISSUER_NAME + i);
+
+ if (enable != null && enable.equals("true")) {
+ if (pointType != null)
+ addCRLPoint(getLocale(request), cdp, pointType, pointName);
+ if (issuerType != null)
+ addIssuer(getLocale(request), cdp, issuerType, issuerName);
+ if (reasons != null)
+ addReasons(getLocale(request), cdp, REASONS, reasons);
+
+ if (i == 0) {
+ ext = new CRLDistributionPointsExtension(cdp);
+ ext.setCritical(critical);
+ } else {
+ ext.addPoint(cdp);
+ }
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("CRLDistribtionPointsExtDefault: createExtension " +
+ e.toString());
+ CMS.debug(e);
+ }
+
+ return ext;
+ }
+
+ private CRLDistributionPointsExtension createExtension(Locale locale) {
+ CRLDistributionPointsExtension ext = null;
+ int num = 0;
+
+ try {
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+
+ num = getNumPoints();
+ for (int i = 0; i < num; i++) {
+ CRLDistributionPoint cdp = new CRLDistributionPoint();
+
+ String enable = getConfig(CONFIG_ENABLE + i);
+ String pointType = getConfig(CONFIG_POINT_TYPE + i);
+ String pointName = getConfig(CONFIG_POINT_NAME + i);
+ String reasons = getConfig(CONFIG_REASONS + i);
+ String issuerType = getConfig(CONFIG_ISSUER_TYPE + i);
+ String issuerName = getConfig(CONFIG_ISSUER_NAME + i);
+
+ if (enable != null && enable.equals("true")) {
+ if (pointType != null)
+ addCRLPoint(locale, cdp, pointType, pointName);
+ if (issuerType != null)
+ addIssuer(locale, cdp, issuerType, issuerName);
+ addReasons(locale, cdp, REASONS, reasons);
+
+ if (i == 0) {
+ ext = new CRLDistributionPointsExtension(cdp);
+ ext.setCritical(critical);
+ } else {
+ ext.addPoint(cdp);
+ }
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("CRLDistribtionPointsExtDefault: createExtension " +
+ e.toString());
+ CMS.debug(e);
+ }
+
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/CertificatePoliciesExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/CertificatePoliciesExtDefault.java
new file mode 100644
index 000000000..9629e4990
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/CertificatePoliciesExtDefault.java
@@ -0,0 +1,793 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.CPSuri;
+import netscape.security.x509.CertificatePoliciesExtension;
+import netscape.security.x509.CertificatePolicyId;
+import netscape.security.x509.CertificatePolicyInfo;
+import netscape.security.x509.DisplayText;
+import netscape.security.x509.NoticeReference;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.PolicyQualifiers;
+import netscape.security.x509.Qualifier;
+import netscape.security.x509.UserNotice;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a policy mappings extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CertificatePoliciesExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "Critical";
+ public static final String CONFIG_PREFIX = "PoliciesExt.certPolicy";
+ public static final String CONFIG_PREFIX1 = "PolicyQualifiers";
+ public static final String CONFIG_POLICY_ENABLE = "enable";
+ public static final String CONFIG_POLICY_NUM = "PoliciesExt.num";
+ public static final String CONFIG_POLICY_ID = "policyId";
+ public static final String CONFIG_POLICY_QUALIFIERS_NUM = "PolicyQualifiers.num";
+ public static final String CONFIG_CPSURI_ENABLE = "CPSURI.enable";
+ public static final String CONFIG_USERNOTICE_ENABLE = "usernotice.enable";
+ public static final String CONFIG_CPSURI_VALUE = "CPSURI.value";
+ public static final String CONFIG_USERNOTICE_ORG = "usernotice.noticeReference.organization";
+ public static final String CONFIG_USERNOTICE_NUMBERS = "usernotice.noticeReference.noticeNumbers";
+ public static final String CONFIG_USERNOTICE_TEXT = "usernotice.explicitText.value";
+
+ public static final String VAL_CRITICAL = "Critical";
+ public static final String VAL_POLICY_QUALIFIERS = "policyQualifiers";
+
+ private static final String SEPARATOR = ".";
+ private static final int DEF_NUM_POLICIES = 5;
+ private static final int DEF_NUM_QUALIFIERS = 1;
+ private static final int MAX_NUM_POLICIES = 20;
+ private static final String POLICY_ID_ENABLE = "Enable";
+ private static final String POLICY_ID = "Policy Id";
+ private static final String POLICY_QUALIFIER_CPSURI_ENABLE = "CPSuri Enable";
+ private static final String POLICY_QUALIFIER_USERNOTICE_ENABLE = "UserNotice Enable";
+ private static final String USERNOTICE_REF_ORG = "UserNoticeReference Organization";
+ private static final String USERNOTICE_REF_NUMBERS = "UserNoticeReference Numbers";
+ private static final String USERNOTICE_EXPLICIT_TEXT = "UserNoticeReference Explicit Text";
+ private static final String CPSURI = "CPS uri";
+
+ public CertificatePoliciesExtDefault() {
+ super();
+ }
+
+ protected int getNumPolicies() {
+ int num = DEF_NUM_POLICIES;
+ String numPolicies = getConfig(CONFIG_POLICY_NUM);
+
+ if (numPolicies != null) {
+ try {
+ num = Integer.parseInt(numPolicies);
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ }
+
+ if (num >= MAX_NUM_POLICIES)
+ num = DEF_NUM_POLICIES;
+ return num;
+ }
+
+ protected int getNumQualifiers() {
+ int num = DEF_NUM_QUALIFIERS;
+ String numQualifiers = getConfig(CONFIG_POLICY_QUALIFIERS_NUM);
+ if (numQualifiers != null) {
+ try {
+ num = Integer.parseInt(numQualifiers);
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ }
+ return num;
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+
+ refreshConfigAndValueNames();
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ int num = 0;
+ if (name.equals(CONFIG_POLICY_NUM)) {
+ try {
+ num = Integer.parseInt(value);
+
+ if (num >= MAX_NUM_POLICIES || num < 0) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_POLICY_NUM));
+ }
+
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_POLICY_NUM));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public Enumeration<String> getConfigNames() {
+ refreshConfigAndValueNames();
+ return super.getConfigNames();
+ }
+
+ protected void refreshConfigAndValueNames() {
+
+ super.refreshConfigAndValueNames();
+
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_POLICY_QUALIFIERS);
+
+ addConfigName(CONFIG_CRITICAL);
+ int num = getNumPolicies();
+ int numQualifiers = getNumQualifiers();
+
+ addConfigName(CONFIG_POLICY_NUM);
+
+ for (int i = 0; i < num; i++) {
+ addConfigName(CONFIG_PREFIX + i + SEPARATOR + CONFIG_POLICY_ID);
+ addConfigName(CONFIG_PREFIX + i + SEPARATOR + CONFIG_POLICY_ENABLE);
+ for (int j = 0; j < numQualifiers; j++) {
+ addConfigName(CONFIG_PREFIX + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR + CONFIG_CPSURI_ENABLE);
+ addConfigName(CONFIG_PREFIX + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR + CONFIG_USERNOTICE_ENABLE);
+ addConfigName(CONFIG_PREFIX + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR + CONFIG_CPSURI_VALUE);
+ addConfigName(CONFIG_PREFIX + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR + CONFIG_USERNOTICE_ORG);
+ addConfigName(CONFIG_PREFIX
+ + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR + CONFIG_USERNOTICE_NUMBERS);
+ addConfigName(CONFIG_PREFIX + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR + CONFIG_USERNOTICE_TEXT);
+ }
+ }
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.indexOf(CONFIG_POLICY_ID) >= 0) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_POLICY_ID"));
+ } else if (name.indexOf(CONFIG_CPSURI_ENABLE) >= 0) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_POLICY_QUALIFIER_CPSURI_ENABLE"));
+ } else if (name.indexOf(CONFIG_USERNOTICE_ENABLE) >= 0) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_POLICY_QUALIFIER_USERNOTICE_ENABLE"));
+ } else if (name.indexOf(CONFIG_POLICY_ENABLE) >= 0) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CERTIFICATE_POLICY_ENABLE"));
+ } else if (name.indexOf(CONFIG_POLICY_QUALIFIERS_NUM) >= 0) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "1",
+ CMS.getUserMessage(locale, "CMS_PROFILE_POLICY_QUALIFIER_NUM"));
+ } else if (name.indexOf(CONFIG_USERNOTICE_ORG) >= 0) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_POLICY_USERNOTICE_REF_ORG"));
+ } else if (name.indexOf(CONFIG_USERNOTICE_NUMBERS) >= 0) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_POLICY_USERNOTICE_REF_NUMBERS"));
+ } else if (name.indexOf(CONFIG_USERNOTICE_TEXT) >= 0) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_POLICY_USERNOTICE_EXPLICIT_TEXT"));
+ } else if (name.indexOf(CONFIG_CPSURI_VALUE) >= 0) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_POLICY_CPSURI"));
+ } else if (name.indexOf(CONFIG_POLICY_NUM) >= 0) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "5",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NUM_POLICIES"));
+ }
+ return null;
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_POLICY_QUALIFIERS)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_POLICY_QUALIFIERS"));
+ }
+ return null;
+ }
+
+ private Hashtable<String, String> buildRecords(String value) throws EPropertyException {
+ StringTokenizer st = new StringTokenizer(value, "\r\n");
+ Hashtable<String, String> table = new Hashtable<String, String>();
+ while (st.hasMoreTokens()) {
+ String token = st.nextToken();
+ int index = token.indexOf(":");
+ if (index <= 0)
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", token));
+ String name = token.substring(0, index);
+ String val = "";
+ if ((token.length() - 1) > index) {
+ val = token.substring(index + 1);
+ }
+ table.put(name, val);
+ }
+
+ return table;
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ CertificatePoliciesExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (CertificatePoliciesExtension)
+ getExtension(PKIXExtensions.CertificatePolicies_Id.toString(),
+ info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ ext.setCritical(val);
+ } else if (name.equals(VAL_POLICY_QUALIFIERS)) {
+ ext = (CertificatePoliciesExtension)
+ getExtension(PKIXExtensions.CertificatePolicies_Id.toString(),
+ info);
+
+ Hashtable<String, String> h = buildRecords(value);
+
+ String numStr = h.get(CONFIG_POLICY_NUM);
+ int size = Integer.parseInt(numStr);
+
+ Vector<CertificatePolicyInfo> certificatePolicies = new Vector<CertificatePolicyInfo>();
+ for (int i = 0; i < size; i++) {
+ String enable = h.get(CONFIG_PREFIX + i + SEPARATOR + CONFIG_POLICY_ENABLE);
+ CertificatePolicyInfo cinfo = null;
+ if (enable != null && enable.equals("true")) {
+ String policyId = h.get(CONFIG_PREFIX + i + SEPARATOR + CONFIG_POLICY_ID);
+
+ if (policyId == null || policyId.length() == 0)
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_PROFILE_CERTIFICATE_POLICIES_EMPTY_POLICYID"));
+ CertificatePolicyId cpolicyId = getPolicyId(policyId);
+
+ String qualifersNum =
+ h.get(CONFIG_PREFIX + i + SEPARATOR + CONFIG_POLICY_QUALIFIERS_NUM);
+ PolicyQualifiers policyQualifiers = new PolicyQualifiers();
+ int num = 0;
+ if (qualifersNum != null && qualifersNum.length() > 0)
+ num = Integer.parseInt(qualifersNum);
+ for (int j = 0; j < num; j++) {
+ String cpsuriEnable =
+ h.get(CONFIG_PREFIX
+ + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR + CONFIG_CPSURI_ENABLE);
+ String usernoticeEnable =
+ h.get(CONFIG_PREFIX
+ + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR
+ + CONFIG_USERNOTICE_ENABLE);
+ if (cpsuriEnable != null && cpsuriEnable.equals("true")) {
+ String cpsuri =
+ h.get(CONFIG_PREFIX
+ + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR + CONFIG_CPSURI_VALUE);
+ netscape.security.x509.PolicyQualifierInfo qualifierInfo = createCPSuri(cpsuri);
+ if (qualifierInfo != null)
+ policyQualifiers.add(qualifierInfo);
+ } else if (usernoticeEnable != null && enable.equals("true")) {
+ String org =
+ h.get(CONFIG_PREFIX
+ + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR
+ + CONFIG_USERNOTICE_ORG);
+ String noticenumbers =
+ h.get(CONFIG_PREFIX
+ + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR
+ + CONFIG_USERNOTICE_NUMBERS);
+ String explicitText =
+ h.get(CONFIG_PREFIX
+ + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR
+ + CONFIG_USERNOTICE_TEXT);
+ netscape.security.x509.PolicyQualifierInfo qualifierInfo = createUserNotice(org,
+ noticenumbers, explicitText);
+ if (qualifierInfo != null)
+ policyQualifiers.add(qualifierInfo);
+ }
+ }
+
+ if (policyQualifiers.size() <= 0) {
+ cinfo = new CertificatePolicyInfo(cpolicyId);
+ } else {
+ cinfo = new CertificatePolicyInfo(cpolicyId, policyQualifiers);
+ }
+ if (cinfo != null)
+ certificatePolicies.addElement(cinfo);
+ }
+ }
+
+ ext.set(CertificatePoliciesExtension.INFOS, certificatePolicies);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ replaceExtension(PKIXExtensions.CertificatePolicies_Id.toString(),
+ ext, info);
+ } catch (EProfileException e) {
+ CMS.debug("CertificatePoliciesExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } catch (IOException e) {
+ CMS.debug("CertificatePoliciesExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ CertificatePoliciesExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (CertificatePoliciesExtension)
+ getExtension(PKIXExtensions.CertificatePolicies_Id.toString(),
+ info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_POLICY_QUALIFIERS)) {
+ ext = (CertificatePoliciesExtension)
+ getExtension(PKIXExtensions.CertificatePolicies_Id.toString(),
+ info);
+
+ if (ext == null)
+ return "";
+
+ StringBuffer sb = new StringBuffer();
+ int num_policies = getNumPolicies();
+ sb.append(CONFIG_POLICY_NUM);
+ sb.append(":");
+ sb.append(num_policies);
+ sb.append("\n");
+ Vector<CertificatePolicyInfo> infos;
+
+ try {
+ infos = (Vector<CertificatePolicyInfo>) ext.get(CertificatePoliciesExtension.INFOS);
+ } catch (IOException ee) {
+ infos = null;
+ }
+
+ for (int i = 0; i < num_policies; i++) {
+ int qSize = 0;
+ String policyId = "";
+ String policyEnable = "false";
+ PolicyQualifiers qualifiers = null;
+ if (infos.size() > 0) {
+ CertificatePolicyInfo cinfo =
+ infos.elementAt(0);
+
+ CertificatePolicyId id1 = cinfo.getPolicyIdentifier();
+ policyId = id1.getIdentifier().toString();
+ policyEnable = "true";
+ qualifiers = cinfo.getPolicyQualifiers();
+ if (qualifiers != null)
+ qSize = qualifiers.size();
+ infos.removeElementAt(0);
+ }
+ sb.append(CONFIG_PREFIX + i + SEPARATOR + CONFIG_POLICY_ENABLE);
+ sb.append(":");
+ sb.append(policyEnable);
+ sb.append("\n");
+ sb.append(CONFIG_PREFIX + i + SEPARATOR + CONFIG_POLICY_ID);
+ sb.append(":");
+ sb.append(policyId);
+ sb.append("\n");
+
+ if (qSize == 0) {
+ sb.append(CONFIG_PREFIX + i + SEPARATOR + CONFIG_POLICY_QUALIFIERS_NUM);
+ sb.append(":");
+ sb.append(DEF_NUM_QUALIFIERS);
+ sb.append("\n");
+ } else {
+ sb.append(CONFIG_PREFIX + i + SEPARATOR + CONFIG_POLICY_QUALIFIERS_NUM);
+ sb.append(":");
+ sb.append(qSize);
+ sb.append("\n");
+ }
+ if (qSize == 0) {
+ sb.append(CONFIG_PREFIX + i + SEPARATOR + CONFIG_PREFIX1 + "0" + SEPARATOR + CONFIG_CPSURI_ENABLE);
+ sb.append(":");
+ sb.append("false");
+ sb.append("\n");
+ sb.append(CONFIG_PREFIX + i + SEPARATOR + CONFIG_PREFIX1 + "0" + SEPARATOR + CONFIG_CPSURI_VALUE);
+ sb.append(":");
+ sb.append("");
+ sb.append("\n");
+ sb.append(CONFIG_PREFIX
+ + i + SEPARATOR + CONFIG_PREFIX1 + "0" + SEPARATOR + CONFIG_USERNOTICE_ENABLE);
+ sb.append(":");
+ sb.append("false");
+ sb.append("\n");
+ sb.append(CONFIG_PREFIX + i + SEPARATOR + CONFIG_PREFIX1 + "0" + SEPARATOR + CONFIG_USERNOTICE_ORG);
+ sb.append(":");
+ sb.append("");
+ sb.append("\n");
+ sb.append(CONFIG_PREFIX
+ + i + SEPARATOR + CONFIG_PREFIX1 + "0" + SEPARATOR + CONFIG_USERNOTICE_NUMBERS);
+ sb.append(":");
+ sb.append("");
+ sb.append("\n");
+ sb.append(CONFIG_PREFIX + i + SEPARATOR + CONFIG_PREFIX1 + "0" + SEPARATOR + CONFIG_USERNOTICE_TEXT);
+ sb.append(":");
+ sb.append("");
+ sb.append("\n");
+ }
+
+ for (int j = 0; j < qSize; j++) {
+ netscape.security.x509.PolicyQualifierInfo qinfo = qualifiers.getInfoAt(j);
+ ObjectIdentifier oid = qinfo.getId();
+ Qualifier qualifier = qinfo.getQualifier();
+
+ String cpsuriEnable = "false";
+ String usernoticeEnable = "false";
+ String cpsuri = "";
+ String org = "";
+ StringBuffer noticeNum = new StringBuffer();
+ String explicitText = "";
+
+ if (oid.toString().equals(netscape.security.x509.PolicyQualifierInfo.QT_CPS.toString())) {
+ cpsuriEnable = "true";
+ CPSuri content = (CPSuri) qualifier;
+ cpsuri = content.getURI();
+ } else if (oid.toString().equals(netscape.security.x509.PolicyQualifierInfo.QT_UNOTICE.toString())) {
+ usernoticeEnable = "true";
+ UserNotice content = (UserNotice) qualifier;
+ NoticeReference ref = content.getNoticeReference();
+ if (ref != null) {
+ org = ref.getOrganization().getText();
+ int[] nums = ref.getNumbers();
+ for (int k = 0; k < nums.length; k++) {
+ if (k != 0) {
+ noticeNum.append(",");
+ noticeNum.append(nums[k]);
+ } else
+ noticeNum.append(nums[k]);
+ }
+ }
+ DisplayText displayText = content.getDisplayText();
+ if (displayText != null)
+ explicitText = displayText.getText();
+ }
+
+ sb.append(CONFIG_PREFIX + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR + CONFIG_CPSURI_ENABLE);
+ sb.append(":");
+ sb.append(cpsuriEnable);
+ sb.append("\n");
+ sb.append(CONFIG_PREFIX + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR + CONFIG_CPSURI_VALUE);
+ sb.append(":");
+ sb.append(cpsuri);
+ sb.append("\n");
+ sb.append(CONFIG_PREFIX + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR + CONFIG_USERNOTICE_ENABLE);
+ sb.append(":");
+ sb.append(usernoticeEnable);
+ sb.append("\n");
+ sb.append(CONFIG_PREFIX + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR + CONFIG_USERNOTICE_ORG);
+ sb.append(":");
+ sb.append(org);
+ sb.append("\n");
+ sb.append(CONFIG_PREFIX
+ + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR + CONFIG_USERNOTICE_NUMBERS);
+ sb.append(":");
+ sb.append(noticeNum.toString());
+ sb.append("\n");
+ sb.append(CONFIG_PREFIX + i + SEPARATOR + CONFIG_PREFIX1 + j + SEPARATOR + CONFIG_USERNOTICE_TEXT);
+ sb.append(":");
+ sb.append(explicitText);
+ sb.append("\n");
+ }
+ } // end of for loop
+ return sb.toString();
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ StringBuffer sb = new StringBuffer();
+ int num = getNumPolicies();
+ int num1 = getNumQualifiers();
+
+ try {
+ IConfigStore basesubstore = getConfigStore().getSubStore("params");
+ sb.append("{");
+ sb.append(CONFIG_POLICY_NUM + ":");
+ sb.append(num);
+ sb.append(",");
+ for (int i = 0; i < num; i++) {
+ sb.append("{");
+ IConfigStore substore = basesubstore.getSubStore(CONFIG_PREFIX + i);
+ String enable = substore.getString(CONFIG_POLICY_ENABLE, "");
+ sb.append(POLICY_ID_ENABLE + ":");
+ sb.append(enable);
+ sb.append(",");
+ String policyId = substore.getString(CONFIG_POLICY_ID, "");
+ sb.append(POLICY_ID + ":");
+ sb.append(policyId);
+ sb.append(",");
+ String qualifiersNum = substore.getString(CONFIG_POLICY_QUALIFIERS_NUM, "");
+ sb.append(CONFIG_POLICY_QUALIFIERS_NUM + ":");
+ sb.append(qualifiersNum);
+ sb.append(",");
+ for (int j = 0; j < num1; j++) {
+ IConfigStore substore1 = substore.getSubStore(CONFIG_PREFIX1 + j);
+ sb.append("{");
+ String cpsuriEnable = substore1.getString(CONFIG_CPSURI_ENABLE, "");
+ sb.append(POLICY_QUALIFIER_CPSURI_ENABLE + ":");
+ sb.append(cpsuriEnable);
+ sb.append(",");
+ String usernoticeEnable = substore1.getString(CONFIG_USERNOTICE_ENABLE, "");
+ sb.append(POLICY_QUALIFIER_USERNOTICE_ENABLE + ":");
+ sb.append(usernoticeEnable);
+ sb.append(",");
+ String org = substore1.getString(CONFIG_USERNOTICE_ORG, "");
+ sb.append(USERNOTICE_REF_ORG + ":");
+ sb.append(org);
+ sb.append(",");
+ String refNums = substore1.getString(CONFIG_USERNOTICE_NUMBERS, "");
+ sb.append(USERNOTICE_REF_NUMBERS + ":");
+ sb.append(refNums);
+ sb.append(",");
+ String explicitText = substore1.getString(CONFIG_USERNOTICE_TEXT, "");
+ sb.append(USERNOTICE_EXPLICIT_TEXT + ":");
+ sb.append(explicitText);
+ sb.append(",");
+ String cpsuri = substore1.getString(CONFIG_CPSURI_VALUE, "");
+ sb.append(CPSURI + ":");
+ sb.append(cpsuri);
+ sb.append("}");
+ }
+ sb.append("}");
+ }
+ sb.append("}");
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_DEF_CERTIFICATE_POLICIES_EXT",
+ getConfig(CONFIG_CRITICAL), sb.toString());
+ } catch (Exception e) {
+ return "";
+ }
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ CertificatePoliciesExtension ext = createExtension();
+
+ if (ext == null)
+ return;
+ addExtension(PKIXExtensions.CertificatePolicies_Id.toString(),
+ ext, info);
+ }
+
+ public CertificatePoliciesExtension createExtension()
+ throws EProfileException {
+ CertificatePoliciesExtension ext = null;
+
+ try {
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+ Vector<CertificatePolicyInfo> certificatePolicies = new Vector<CertificatePolicyInfo>();
+ int num = getNumPolicies();
+ CMS.debug("CertificatePoliciesExtension: createExtension: number of policies=" + num);
+ IConfigStore config = getConfigStore();
+
+ for (int i = 0; i < num; i++) {
+ IConfigStore basesubstore = config.getSubStore("params");
+ IConfigStore substore = basesubstore.getSubStore(CONFIG_PREFIX + i);
+ String enable = substore.getString(CONFIG_POLICY_ENABLE);
+
+ CMS.debug("CertificatePoliciesExtension: createExtension: CertificatePolicy " + i + " enable=" + enable);
+ if (enable != null && enable.equals("true")) {
+ String policyId = substore.getString(CONFIG_POLICY_ID);
+ CertificatePolicyId cpolicyId = getPolicyId(policyId);
+ CMS.debug("CertificatePoliciesExtension: createExtension: CertificatePolicy "
+ + i + " policyId=" + policyId);
+ int qualifierNum = getNumQualifiers();
+ PolicyQualifiers policyQualifiers = new PolicyQualifiers();
+ for (int j = 0; j < qualifierNum; j++) {
+ IConfigStore substore1 = substore.getSubStore(CONFIG_PREFIX1 + j);
+ String cpsuriEnable = substore1.getString(CONFIG_CPSURI_ENABLE);
+ String usernoticeEnable = substore1.getString(CONFIG_USERNOTICE_ENABLE);
+
+ if (cpsuriEnable != null && cpsuriEnable.equals("true")) {
+ String cpsuri = substore1.getString(CONFIG_CPSURI_VALUE, "");
+ netscape.security.x509.PolicyQualifierInfo qualifierInfo = createCPSuri(cpsuri);
+ if (qualifierInfo != null)
+ policyQualifiers.add(qualifierInfo);
+ } else if (usernoticeEnable != null &&
+ usernoticeEnable.equals("true")) {
+
+ String org = substore1.getString(CONFIG_USERNOTICE_ORG);
+ String noticenumbers = substore1.getString(CONFIG_USERNOTICE_NUMBERS);
+ String explicitText = substore1.getString(CONFIG_USERNOTICE_TEXT);
+ netscape.security.x509.PolicyQualifierInfo qualifierInfo = createUserNotice(org,
+ noticenumbers, explicitText);
+ if (qualifierInfo != null)
+ policyQualifiers.add(qualifierInfo);
+ }
+ }
+
+ CertificatePolicyInfo info = null;
+ if (policyQualifiers.size() <= 0) {
+ info =
+ new CertificatePolicyInfo(cpolicyId);
+ } else {
+ info =
+ new CertificatePolicyInfo(cpolicyId, policyQualifiers);
+ }
+
+ if (info != null)
+ certificatePolicies.addElement(info);
+ }
+ }
+
+ ext = new CertificatePoliciesExtension(critical, certificatePolicies);
+ } catch (EPropertyException e) {
+ throw new EProfileException(e.toString());
+ } catch (EProfileException e) {
+ throw e;
+ } catch (Exception e) {
+ CMS.debug("CertificatePoliciesExtDefault: createExtension " +
+ e.toString());
+ }
+
+ return ext;
+ }
+
+ private CertificatePolicyId getPolicyId(String policyId) throws EPropertyException {
+ if (policyId == null || policyId.length() == 0)
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_PROFILE_CERTIFICATE_POLICIES_EMPTY_POLICYID"));
+
+ CertificatePolicyId cpolicyId = null;
+ try {
+ cpolicyId = new CertificatePolicyId(
+ ObjectIdentifier.getObjectIdentifier(policyId));
+ return cpolicyId;
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_PROFILE_CERTIFICATE_POLICIES_POLICYID_ERROR", policyId));
+ }
+ }
+
+ private netscape.security.x509.PolicyQualifierInfo createCPSuri(String uri) throws EPropertyException {
+ if (uri == null || uri.length() == 0)
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_PROFILE_CERTIFICATE_POLICIES_EMPTY_CPSURI"));
+
+ CPSuri cpsURI = new CPSuri(uri);
+ netscape.security.x509.PolicyQualifierInfo policyQualifierInfo2 =
+ new netscape.security.x509.PolicyQualifierInfo(netscape.security.x509.PolicyQualifierInfo.QT_CPS,
+ cpsURI);
+
+ return policyQualifierInfo2;
+ }
+
+ private netscape.security.x509.PolicyQualifierInfo createUserNotice(String organization,
+ String noticeText, String noticeNums) throws EPropertyException {
+
+ if ((organization == null || organization.length() == 0) &&
+ (noticeNums == null || noticeNums.length() == 0) &&
+ (noticeText == null || noticeText.length() == 0))
+ return null;
+
+ DisplayText explicitText = null;
+ if (noticeText != null && noticeText.length() > 0)
+ explicitText = new DisplayText(DisplayText.tag_VisibleString, noticeText);
+
+ int nums[] = null;
+ if (noticeNums != null && noticeNums.length() > 0) {
+ Vector<String> numsVector = new Vector<String>();
+ StringTokenizer tokens = new StringTokenizer(noticeNums, ";");
+ while (tokens.hasMoreTokens()) {
+ String num = tokens.nextToken().trim();
+ numsVector.addElement(num);
+ }
+
+ nums = new int[numsVector.size()];
+ try {
+ for (int i = 0; i < numsVector.size(); i++) {
+ Integer ii = new Integer(numsVector.elementAt(i));
+ nums[i] = ii.intValue();
+ }
+ } catch (Exception e) {
+ throw new EPropertyException("Wrong notice numbers");
+ }
+ }
+
+ DisplayText orgName = null;
+ if (organization != null && organization.length() > 0) {
+ orgName =
+ new DisplayText(DisplayText.tag_VisibleString, organization);
+ }
+
+ NoticeReference noticeReference = null;
+
+ if (orgName != null)
+ noticeReference = new NoticeReference(orgName, nums);
+
+ UserNotice userNotice = null;
+ if (explicitText != null || noticeReference != null) {
+ userNotice = new UserNotice(noticeReference, explicitText);
+
+ netscape.security.x509.PolicyQualifierInfo policyQualifierInfo1 =
+ new netscape.security.x509.PolicyQualifierInfo(
+ netscape.security.x509.PolicyQualifierInfo.QT_UNOTICE, userNotice);
+ return policyQualifierInfo1;
+ }
+
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/CertificateVersionDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/CertificateVersionDefault.java
new file mode 100644
index 000000000..752d99cbb
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/CertificateVersionDefault.java
@@ -0,0 +1,193 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a Netscape comment extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CertificateVersionDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_VERSION = "certVersionNum";
+
+ public static final String VAL_VERSION = "certVersionNum";
+
+ public CertificateVersionDefault() {
+ super();
+ addValueName(VAL_VERSION);
+
+ addConfigName(CONFIG_VERSION);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_VERSION)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "3",
+ CMS.getUserMessage(locale, "CMS_PROFILE_VERSION"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ if (name.equals(CONFIG_VERSION)) {
+ try {
+ Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_VERSION));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_VERSION)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "3",
+ CMS.getUserMessage(locale, "CMS_PROFILE_VERSION"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_VERSION)) {
+ if (value == null || value.equals(""))
+ throw new EPropertyException(name + " cannot be empty");
+ else {
+ int version = Integer.valueOf(value).intValue() - 1;
+
+ if (version == CertificateVersion.V1)
+ info.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V1));
+ else if (version == CertificateVersion.V2)
+ info.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V2));
+ else if (version == CertificateVersion.V3)
+ info.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } catch (IOException e) {
+ CMS.debug("CertificateVersionDefault: setValue " + e.toString());
+ } catch (CertificateException e) {
+ CMS.debug("CertificateVersionDefault: setValue " + e.toString());
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ if (name.equals(VAL_VERSION)) {
+ CertificateVersion v = null;
+ try {
+ v = (CertificateVersion) info.get(
+ X509CertInfo.VERSION);
+ } catch (Exception e) {
+ }
+
+ if (v == null)
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ int version = v.compare(0);
+
+ return "" + (version + 1);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_VERSION)
+ };
+
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_CERT_VERSION", params);
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ String v = getConfig(CONFIG_VERSION);
+ int version = Integer.valueOf(v).intValue() - 1;
+
+ try {
+ if (version == CertificateVersion.V1)
+ info.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V1));
+ else if (version == CertificateVersion.V2)
+ info.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V2));
+ else if (version == CertificateVersion.V3)
+ info.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ else {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_INVALID_PROPERTY", CONFIG_VERSION));
+ }
+ } catch (IOException e) {
+ } catch (CertificateException e) {
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/EnrollDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/EnrollDefault.java
new file mode 100644
index 000000000..7b4c3c74d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/EnrollDefault.java
@@ -0,0 +1,774 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.security.extensions.KerberosName;
+import netscape.security.util.DerInputStream;
+import netscape.security.util.DerOutputStream;
+import netscape.security.util.DerValue;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.DNSName;
+import netscape.security.x509.EDIPartyName;
+import netscape.security.x509.Extension;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNameInterface;
+import netscape.security.x509.IPAddressName;
+import netscape.security.x509.OIDName;
+import netscape.security.x509.OtherName;
+import netscape.security.x509.RFC822Name;
+import netscape.security.x509.URIName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IAttrSet;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IPrettyPrintFormat;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.pattern.Pattern;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ICertInfoPolicyDefault;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements an enrollment default policy.
+ *
+ * @version $Revision$, $Date$
+ */
+public abstract class EnrollDefault implements IPolicyDefault, ICertInfoPolicyDefault {
+
+ public static final String PROP_NAME = "name";
+
+ public static final String GN_RFC822_NAME = "RFC822Name";
+ public static final String GN_DNS_NAME = "DNSName";
+ public static final String GN_URI_NAME = "URIName";
+ public static final String GN_IP_NAME = "IPAddressName";
+ public static final String GN_DIRECTORY_NAME = "DirectoryName";
+ public static final String GN_EDI_NAME = "EDIPartyName";
+ public static final String GN_ANY_NAME = "OtherName";
+ public static final String GN_OID_NAME = "OIDName";
+
+ protected IConfigStore mConfig = null;
+ protected Vector<String> mConfigNames = new Vector<String>();
+ protected Vector<String> mValueNames = new Vector<String>();
+
+ public EnrollDefault() {
+ }
+
+ public Enumeration<String> getConfigNames() {
+ return mConfigNames.elements();
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public void addConfigName(String name) {
+ mConfigNames.addElement(name);
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ if (mConfig.getSubStore("params") == null) {
+ //
+ } else {
+ mConfig.getSubStore("params").putString(name, value);
+ }
+ }
+
+ public String getConfig(String name) {
+ try {
+ if (mConfig == null)
+ return null;
+ if (mConfig.getSubStore("params") != null) {
+ return mConfig.getSubStore("params").getString(name);
+ }
+ } catch (EBaseException e) {
+ }
+ return "";
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ mConfig = config;
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ *
+ * @param locale locale of the end user
+ * @return localized description of this default policy
+ */
+ public abstract String getText(Locale locale);
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public String getName(Locale locale) {
+ try {
+ return mConfig.getString(PROP_NAME);
+ } catch (EBaseException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Populates attributes into the certificate template.
+ *
+ * @param request enrollment request
+ * @param info certificate template
+ * @exception EProfileException failed to populate attributes
+ * into request
+ */
+ public abstract void populate(IRequest request, X509CertInfo info)
+ throws EProfileException;
+
+ /**
+ * Sets values from the approval page into certificate template.
+ *
+ * @param name name of the attribute
+ * @param locale user locale
+ * @param info certificate template
+ * @param value attribute value
+ * @exception EProfileException failed to set attributes
+ * into request
+ */
+ public abstract void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException;
+
+ /**
+ * Retrieves certificate template values and returns them to
+ * the approval page.
+ *
+ * @param name name of the attribute
+ * @param locale user locale
+ * @param info certificate template
+ * @exception EProfileException failed to get attributes
+ * from request
+ */
+ public abstract String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException;
+
+ /**
+ * Populates the request with this policy default.
+ *
+ * The current implementation extracts enrollment specific attributes
+ * and calls the populate() method of the subclass.
+ *
+ * @param request request to be populated
+ * @exception EProfileException failed to populate
+ */
+ public void populate(IRequest request)
+ throws EProfileException {
+ String name = getClass().getName();
+
+ name = name.substring(name.lastIndexOf('.') + 1);
+ CMS.debug(name + ": populate start");
+ X509CertInfo info =
+ request.getExtDataInCertInfo(IEnrollProfile.REQUEST_CERTINFO);
+
+ populate(request, info);
+
+ request.setExtData(IEnrollProfile.REQUEST_CERTINFO, info);
+ CMS.debug(name + ": populate end");
+ }
+
+ public void addValueName(String name) {
+ mValueNames.addElement(name);
+ }
+
+ public Enumeration<String> getValueNames() {
+ return mValueNames.elements();
+ }
+
+ public IDescriptor getValueDescriptor(String name) {
+ return null;
+ }
+
+ /**
+ * Sets the value of the given value property by name.
+ *
+ * The current implementation extracts enrollment specific attributes
+ * and calls the setValue() method of the subclass.
+ *
+ * @param name name of property
+ * @param locale locale of the end user
+ * @param request request
+ * @param value value to be set in the given request
+ * @exception EPropertyException failed to set property
+ */
+ public void setValue(String name, Locale locale, IRequest request,
+ String value)
+ throws EPropertyException {
+ X509CertInfo info =
+ request.getExtDataInCertInfo(IEnrollProfile.REQUEST_CERTINFO);
+
+ setValue(name, locale, info, value);
+
+ request.setExtData(IEnrollProfile.REQUEST_CERTINFO, info);
+ }
+
+ /**
+ * Retrieves the value of the given value
+ * property by name.
+ *
+ * The current implementation extracts enrollment specific attributes
+ * and calls the getValue() method of the subclass.
+ *
+ * @param name name of property
+ * @param locale locale of the end user
+ * @param request request
+ * @exception EPropertyException failed to get property
+ */
+ public String getValue(String name, Locale locale, IRequest request)
+ throws EPropertyException {
+ X509CertInfo info =
+ request.getExtDataInCertInfo(IEnrollProfile.REQUEST_CERTINFO);
+
+ String value = getValue(name, locale, info);
+ request.setExtData(IEnrollProfile.REQUEST_CERTINFO, info);
+ return value;
+ }
+
+ public String toHexString(byte data[]) {
+ IPrettyPrintFormat pp = CMS.getPrettyPrintFormat(":");
+ String s = pp.toHexString(data, 0, 16);
+ StringTokenizer st = new StringTokenizer(s, "\n");
+ StringBuffer buffer = new StringBuffer();
+
+ while (st.hasMoreTokens()) {
+ buffer.append(st.nextToken());
+ buffer.append("\\n");
+ }
+ return buffer.toString();
+ }
+
+ protected void refreshConfigAndValueNames() {
+ mConfigNames.removeAllElements();
+ mValueNames.removeAllElements();
+ }
+
+ protected void deleteExtension(String name, X509CertInfo info) {
+ CertificateExtensions exts = null;
+
+ try {
+ exts = (CertificateExtensions)
+ info.get(X509CertInfo.EXTENSIONS);
+ if (exts == null)
+ return;
+ Enumeration<String> e = exts.getNames();
+
+ while (e.hasMoreElements()) {
+ String n = e.nextElement();
+ Extension ext = (Extension) exts.get(n);
+
+ if (ext.getExtensionId().toString().equals(name)) {
+ exts.delete(n);
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug(e.toString());
+ }
+ }
+
+ protected Extension getExtension(String name, X509CertInfo info) {
+ CertificateExtensions exts = null;
+
+ try {
+ exts = (CertificateExtensions)
+ info.get(X509CertInfo.EXTENSIONS);
+ } catch (Exception e) {
+ CMS.debug("EnrollDefault: getExtension " + e.toString());
+ }
+ if (exts == null)
+ return null;
+ return getExtension(name, exts);
+ }
+
+ protected Extension getExtension(String name, CertificateExtensions exts) {
+ if (exts == null)
+ return null;
+ Enumeration<Extension> e = exts.getAttributes();
+
+ while (e.hasMoreElements()) {
+ Extension ext = e.nextElement();
+
+ if (ext.getExtensionId().toString().equals(name)) {
+ return ext;
+ }
+ }
+ return null;
+ }
+
+ protected void addExtension(String name, Extension ext, X509CertInfo info)
+ throws EProfileException {
+ if (ext == null) {
+ throw new EProfileException("extension not found");
+ }
+ CertificateExtensions exts = null;
+
+ Extension alreadyPresentExtension = getExtension(name, info);
+
+ if (alreadyPresentExtension != null) {
+ String eName = ext.toString();
+ CMS.debug("EnrollDefault.addExtension: duplicate extension attempted! Name: " + eName);
+ throw new EProfileException(CMS.getUserMessage("CMS_PROFILE_DUPLICATE_EXTENSION", eName));
+ }
+
+ try {
+ exts = (CertificateExtensions)
+ info.get(X509CertInfo.EXTENSIONS);
+ } catch (Exception e) {
+ CMS.debug("EnrollDefault: " + e.toString());
+ }
+ if (exts == null) {
+ throw new EProfileException("extensions not found");
+ }
+ try {
+ exts.set(name, ext);
+ } catch (IOException e) {
+ CMS.debug("EnrollDefault: " + e.toString());
+ }
+ }
+
+ protected void replaceExtension(String name, Extension ext, X509CertInfo info)
+ throws EProfileException {
+ deleteExtension(name, info);
+ addExtension(name, ext, info);
+ }
+
+ protected boolean isOptional(String value) {
+ return value.equals("");
+ }
+
+ protected boolean getBoolean(String value) {
+ return Boolean.valueOf(value).booleanValue();
+ }
+
+ protected int getInt(String value) {
+ return Integer.valueOf(value).intValue();
+ }
+
+ protected boolean getConfigBoolean(String value) {
+ return getBoolean(getConfig(value));
+ }
+
+ protected int getConfigInt(String value) {
+ return getInt(getConfig(value));
+ }
+
+ protected boolean isGeneralNameValid(String name) {
+ if (name == null)
+ return false;
+ int pos = name.indexOf(':');
+ if (pos == -1)
+ return false;
+ String nameValue = name.substring(pos + 1).trim();
+ if (nameValue.equals(""))
+ return false;
+ return true;
+ }
+
+ protected GeneralNameInterface parseGeneralName(String name)
+ throws IOException {
+ int pos = name.indexOf(':');
+ if (pos == -1)
+ return null;
+ String nameType = name.substring(0, pos).trim();
+ String nameValue = name.substring(pos + 1).trim();
+ return parseGeneralName(nameType, nameValue);
+ }
+
+ protected boolean isGeneralNameType(String nameType) {
+ if (nameType.equalsIgnoreCase("RFC822Name")) {
+ return true;
+ }
+ if (nameType.equalsIgnoreCase("DNSName")) {
+ return true;
+ }
+ if (nameType.equalsIgnoreCase("x400")) {
+ return true;
+ }
+ if (nameType.equalsIgnoreCase("DirectoryName")) {
+ return true;
+ }
+ if (nameType.equalsIgnoreCase("EDIPartyName")) {
+ return true;
+ }
+ if (nameType.equalsIgnoreCase("URIName")) {
+ return true;
+ }
+ if (nameType.equalsIgnoreCase("IPAddress")) {
+ return true;
+ }
+ if (nameType.equalsIgnoreCase("OIDName")) {
+ return true;
+ }
+ if (nameType.equalsIgnoreCase("OtherName")) {
+ return true;
+ }
+ return false;
+ }
+
+ protected GeneralNameInterface parseGeneralName(String nameType, String nameValue)
+ throws IOException {
+ if (nameType.equalsIgnoreCase("RFC822Name")) {
+ return new RFC822Name(nameValue);
+ }
+ if (nameType.equalsIgnoreCase("DNSName")) {
+ return new DNSName(nameValue);
+ }
+ if (nameType.equalsIgnoreCase("x400")) {
+ // XXX
+ }
+ if (nameType.equalsIgnoreCase("DirectoryName")) {
+ return new X500Name(nameValue);
+ }
+ if (nameType.equalsIgnoreCase("EDIPartyName")) {
+ return new EDIPartyName(nameValue);
+ }
+ if (nameType.equalsIgnoreCase("URIName")) {
+ return new URIName(nameValue);
+ }
+ if (nameType.equalsIgnoreCase("IPAddress")) {
+ CMS.debug("IP Value:" + nameValue);
+ if (nameValue.indexOf('/') != -1) {
+ // CIDR support for NameConstraintsExt
+ StringTokenizer st = new StringTokenizer(nameValue, "/");
+ String addr = st.nextToken();
+ String netmask = st.nextToken();
+ CMS.debug("addr:" + addr + " netmask: " + netmask);
+ return new IPAddressName(addr, netmask);
+ } else {
+ return new IPAddressName(nameValue);
+ }
+ }
+ if (nameType.equalsIgnoreCase("OIDName")) {
+ try {
+ // check if OID
+ new ObjectIdentifier(nameValue);
+ } catch (Exception e) {
+ return null;
+ }
+ return new OIDName(nameValue);
+ }
+ if (nameType.equals("OtherName")) {
+ if (nameValue == null || nameValue.length() == 0)
+ nameValue = " ";
+ if (nameValue.startsWith("(PrintableString)")) {
+ // format: OtherName: (PrintableString)oid,value
+ int pos0 = nameValue.indexOf(')');
+ int pos1 = nameValue.indexOf(',');
+ if (pos1 == -1)
+ return null;
+ String on_oid = nameValue.substring(pos0 + 1, pos1).trim();
+ String on_value = nameValue.substring(pos1 + 1).trim();
+ if (isValidOID(on_oid)) {
+ return new OtherName(new ObjectIdentifier(on_oid), DerValue.tag_PrintableString, on_value);
+ } else {
+ return null;
+ }
+ } else if (nameValue.startsWith("(KerberosName)")) {
+ // Syntax: (KerberosName)Realm|NameType|NameString(s)
+ int pos0 = nameValue.indexOf(')');
+ int pos1 = nameValue.indexOf('|');
+ int pos2 = nameValue.lastIndexOf('|');
+ String realm = nameValue.substring(pos0 + 1, pos1).trim();
+ String name_type = nameValue.substring(pos1 + 1, pos2).trim();
+ String name_strings = nameValue.substring(pos2 + 1).trim();
+ Vector<String> strings = new Vector<String>();
+ StringTokenizer st = new StringTokenizer(name_strings, ",");
+ while (st.hasMoreTokens()) {
+ strings.addElement(st.nextToken());
+ }
+ KerberosName name = new KerberosName(realm,
+ Integer.parseInt(name_type), strings);
+ // krb5 OBJECT IDENTIFIER ::= { iso (1)
+ // org (3)
+ // dod (6)
+ // internet (1)
+ // security (5)
+ // kerberosv5 (2) }
+ // krb5PrincipalName OBJECT IDENTIFIER ::= { krb5 2 }
+ return new OtherName(KerberosName.KRB5_PRINCIPAL_NAME,
+ name.toByteArray());
+ } else if (nameValue.startsWith("(IA5String)")) {
+ int pos0 = nameValue.indexOf(')');
+ int pos1 = nameValue.indexOf(',');
+ if (pos1 == -1)
+ return null;
+ String on_oid = nameValue.substring(pos0 + 1, pos1).trim();
+ String on_value = nameValue.substring(pos1 + 1).trim();
+ if (isValidOID(on_oid)) {
+ return new OtherName(new ObjectIdentifier(on_oid), DerValue.tag_IA5String, on_value);
+ } else {
+ return null;
+ }
+ } else if (nameValue.startsWith("(UTF8String)")) {
+ int pos0 = nameValue.indexOf(')');
+ int pos1 = nameValue.indexOf(',');
+ if (pos1 == -1)
+ return null;
+ String on_oid = nameValue.substring(pos0 + 1, pos1).trim();
+ String on_value = nameValue.substring(pos1 + 1).trim();
+ if (isValidOID(on_oid)) {
+ return new OtherName(new ObjectIdentifier(on_oid), DerValue.tag_UTF8String, on_value);
+ } else {
+ return null;
+ }
+ } else if (nameValue.startsWith("(BMPString)")) {
+ int pos0 = nameValue.indexOf(')');
+ int pos1 = nameValue.indexOf(',');
+ if (pos1 == -1)
+ return null;
+ String on_oid = nameValue.substring(pos0 + 1, pos1).trim();
+ String on_value = nameValue.substring(pos1 + 1).trim();
+ if (isValidOID(on_oid)) {
+ return new OtherName(new ObjectIdentifier(on_oid), DerValue.tag_BMPString, on_value);
+ } else {
+ return null;
+ }
+ } else if (nameValue.startsWith("(Any)")) {
+ int pos0 = nameValue.indexOf(')');
+ int pos1 = nameValue.indexOf(',');
+ if (pos1 == -1)
+ return null;
+ String on_oid = nameValue.substring(pos0 + 1, pos1).trim();
+ String on_value = nameValue.substring(pos1 + 1).trim();
+ if (isValidOID(on_oid)) {
+ CMS.debug("OID: " + on_oid + " Value:" + on_value);
+ return new OtherName(new ObjectIdentifier(on_oid), getBytes(on_value));
+ } else {
+ CMS.debug("Invalid OID " + on_oid);
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Converts string containing pairs of characters in the range of '0'
+ * to '9', 'a' to 'f' to an array of bytes such that each pair of
+ * characters in the string represents an individual byte
+ */
+ public byte[] getBytes(String string) {
+ if (string == null)
+ return null;
+ int stringLength = string.length();
+ if ((stringLength == 0) || ((stringLength % 2) != 0))
+ return null;
+ byte[] bytes = new byte[(stringLength / 2)];
+ for (int i = 0, b = 0; i < stringLength; i += 2, ++b) {
+ String nextByte = string.substring(i, (i + 2));
+ bytes[b] = (byte) Integer.parseInt(nextByte, 0x10);
+ }
+ return bytes;
+ }
+
+ /**
+ * Check if a object identifier in string form is valid,
+ * that is a string in the form n.n.n.n and der encode and decode-able.
+ *
+ * @param oid object identifier string.
+ * @return true if the oid is valid
+ */
+ public boolean isValidOID(String oid) {
+ ObjectIdentifier v = null;
+ try {
+ v = ObjectIdentifier.getObjectIdentifier(oid);
+ } catch (Exception e) {
+ return false;
+ }
+ if (v == null)
+ return false;
+
+ // if the OID isn't valid (ex. n.n) the error isn't caught til
+ // encoding time leaving a bad request in the request queue.
+ try (DerOutputStream derOut = new DerOutputStream()) {
+
+ derOut.putOID(v);
+ new ObjectIdentifier(new DerInputStream(derOut.toByteArray()));
+ } catch (Exception e) {
+ return false;
+ }
+ return true;
+ }
+
+ protected String buildRecords(Vector<NameValuePairs> recs) throws EPropertyException {
+ StringBuffer sb = new StringBuffer();
+
+ for (int i = 0; i < recs.size(); i++) {
+ NameValuePairs pairs = recs.elementAt(i);
+
+ sb.append("Record #");
+ sb.append(i);
+ sb.append("\r\n");
+
+ for (String key : pairs.keySet()) {
+ String val = pairs.get(key);
+
+ sb.append(key);
+ sb.append(":");
+ sb.append(val);
+ sb.append("\r\n");
+ }
+ sb.append("\r\n");
+
+ }
+ return sb.toString();
+ }
+
+ protected Vector<NameValuePairs> parseRecords(String value) throws EPropertyException {
+ StringTokenizer st = new StringTokenizer(value, "\r\n");
+ int num = 0;
+ Vector<NameValuePairs> v = new Vector<NameValuePairs>();
+ NameValuePairs nvps = null;
+
+ while (st.hasMoreTokens()) {
+ String token = st.nextToken();
+
+ if (token.equals("Record #" + num)) {
+ CMS.debug("parseRecords: Record" + num);
+ nvps = new NameValuePairs();
+ v.addElement(nvps);
+ try {
+ token = st.nextToken();
+ } catch (NoSuchElementException e) {
+ v.removeElementAt(num);
+ CMS.debug(e.toString());
+ return v;
+ }
+ num++;
+ }
+
+ if (nvps == null)
+ throw new EPropertyException("Bad Input Format");
+
+ int pos = token.indexOf(":");
+
+ if (pos <= 0) {
+ CMS.debug("parseRecords: No colon found in the input line");
+ throw new EPropertyException("Bad Input Format");
+ } else {
+ if (pos == (token.length() - 1)) {
+ nvps.put(token.substring(0, pos), "");
+ } else {
+ nvps.put(token.substring(0, pos), token.substring(pos + 1));
+ }
+ }
+ }
+
+ return v;
+ }
+
+ protected String getGeneralNameType(GeneralName gn)
+ throws EPropertyException {
+ int type = gn.getType();
+
+ if (type == GeneralNameInterface.NAME_RFC822)
+ return "RFC822Name";
+ else if (type == GeneralNameInterface.NAME_DNS)
+ return "DNSName";
+ else if (type == GeneralNameInterface.NAME_URI)
+ return "URIName";
+ else if (type == GeneralNameInterface.NAME_IP)
+ return "IPAddress";
+ else if (type == GeneralNameInterface.NAME_DIRECTORY)
+ return "DirectoryName";
+ else if (type == GeneralNameInterface.NAME_EDI)
+ return "EDIPartyName";
+ else if (type == GeneralNameInterface.NAME_ANY)
+ return "OtherName";
+ else if (type == GeneralNameInterface.NAME_OID)
+ return "OIDName";
+
+ throw new EPropertyException("Unsupported type: " + type);
+ }
+
+ protected String getGeneralNameValue(GeneralName gn) throws EPropertyException {
+ String s = gn.toString();
+ int type = gn.getType();
+
+ if (type == GeneralNameInterface.NAME_DIRECTORY)
+ return s;
+ else {
+ int pos = s.indexOf(":");
+
+ if (pos <= 0)
+ throw new EPropertyException("Badly formatted general name: " + s);
+ else {
+ return s.substring(pos + 1).trim();
+ }
+ }
+ }
+
+ public Locale getLocale(IRequest request) {
+ Locale locale = null;
+
+ if (request == null)
+ return null;
+
+ String language = request.getExtDataInString(
+ EnrollProfile.REQUEST_LOCALE);
+ if (language != null) {
+ locale = new Locale(language);
+ }
+ return locale;
+ }
+
+ public String toGeneralNameString(GeneralNameInterface gn) {
+ int type = gn.getType();
+ // Sun's General Name is not consistent, so we need
+ // to do a special case for directory string
+ if (type == GeneralNameInterface.NAME_DIRECTORY) {
+ return "DirectoryName: " + gn.toString();
+ }
+ return gn.toString();
+ }
+
+ protected String mapPattern(IRequest request, String pattern)
+ throws IOException {
+ Pattern p = new Pattern(pattern);
+ IAttrSet attrSet = null;
+ if (request != null) {
+ attrSet = request.asIAttrSet();
+ }
+ return p.substitute2("request", attrSet);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/EnrollExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/EnrollExtDefault.java
new file mode 100644
index 000000000..da395871b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/EnrollExtDefault.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+/**
+ * This class implements an enrollment extension
+ * default policy that extension into the certificate
+ * template.
+ *
+ * @version $Revision$, $Date$
+ */
+public abstract class EnrollExtDefault extends EnrollDefault {
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/ExtendedKeyUsageExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/ExtendedKeyUsageExtDefault.java
new file mode 100644
index 000000000..22f00eb94
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/ExtendedKeyUsageExtDefault.java
@@ -0,0 +1,250 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import netscape.security.extensions.ExtendedKeyUsageExtension;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates Extended Key Usage extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ExtendedKeyUsageExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "exKeyUsageCritical";
+ public static final String CONFIG_OIDS = "exKeyUsageOIDs";
+
+ public static final String VAL_CRITICAL = "exKeyUsageCritical";
+ public static final String VAL_OIDS = "exKeyUsageOIDs";
+
+ public ExtendedKeyUsageExtDefault() {
+ super();
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_OIDS);
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_OIDS);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(CONFIG_OIDS)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_OIDS"));
+ }
+ return null;
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_OIDS)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null, null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_OIDS"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ ExtendedKeyUsageExtension ext = null;
+
+ ext = (ExtendedKeyUsageExtension)
+ getExtension(ExtendedKeyUsageExtension.OID, info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (ExtendedKeyUsageExtension)
+ getExtension(ExtendedKeyUsageExtension.OID, info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ if (ext == null) {
+ return;
+ }
+ ext.setCritical(val);
+ } else if (name.equals(VAL_OIDS)) {
+ ext = (ExtendedKeyUsageExtension)
+ getExtension(ExtendedKeyUsageExtension.OID, info);
+ // ext.deleteAllOIDs();
+ StringTokenizer st = new StringTokenizer(value, ",");
+
+ if (ext == null) {
+ return;
+ }
+ while (st.hasMoreTokens()) {
+ String oid = st.nextToken();
+
+ ext.addOID(new ObjectIdentifier(oid));
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ try {
+ replaceExtension(ExtendedKeyUsageExtension.OID, ext, info);
+ } catch (EProfileException e) {
+ CMS.debug("ExtendedKeyUsageExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ExtendedKeyUsageExtension ext = (ExtendedKeyUsageExtension)
+ getExtension(ExtendedKeyUsageExtension.OID, info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (ExtendedKeyUsageExtension)
+ getExtension(ExtendedKeyUsageExtension.OID, info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_OIDS)) {
+ ext = (ExtendedKeyUsageExtension)
+ getExtension(ExtendedKeyUsageExtension.OID, info);
+ StringBuffer sb = new StringBuffer();
+ if (ext == null) {
+ return "";
+ }
+ Enumeration<ObjectIdentifier> e = ext.getOIDs();
+
+ while (e.hasMoreElements()) {
+ ObjectIdentifier oid = e.nextElement();
+
+ if (!sb.toString().equals("")) {
+ sb.append(",");
+ }
+ sb.append(oid.toString());
+ }
+ return sb.toString();
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_CRITICAL),
+ getConfig(CONFIG_OIDS)
+ };
+
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_DEF_EXTENDED_KEY_EXT", params);
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ ExtendedKeyUsageExtension ext = createExtension();
+
+ addExtension(ExtendedKeyUsageExtension.OID, ext, info);
+ }
+
+ public ExtendedKeyUsageExtension createExtension() {
+ ExtendedKeyUsageExtension ext = null;
+
+ try {
+ ext = new ExtendedKeyUsageExtension();
+ } catch (Exception e) {
+ CMS.debug("ExtendedKeyUsageExtDefault: createExtension " +
+ e.toString());
+ }
+ if (ext == null)
+ return null;
+ boolean critical = getBoolean(getConfig(CONFIG_CRITICAL));
+
+ ext.setCritical(critical);
+ StringTokenizer st = new StringTokenizer(getConfig(CONFIG_OIDS), ",");
+
+ while (st.hasMoreTokens()) {
+ String oid = st.nextToken();
+
+ ext.addOID(new ObjectIdentifier(oid));
+ }
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/FreshestCRLExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/FreshestCRLExtDefault.java
new file mode 100644
index 000000000..b78f0e6cf
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/FreshestCRLExtDefault.java
@@ -0,0 +1,584 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CRLDistributionPoint;
+import netscape.security.x509.FreshestCRLExtension;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.GeneralNamesException;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates Freshest CRL extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class FreshestCRLExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "freshestCRLCritical";
+ public static final String CONFIG_NUM_POINTS = "freshestCRLPointNum";
+ public static final String CONFIG_POINT_TYPE = "freshestCRLPointType_";
+ public static final String CONFIG_POINT_NAME = "freshestCRLPointName_";
+ public static final String CONFIG_ISSUER_TYPE = "freshestCRLPointIssuerType_";
+ public static final String CONFIG_ISSUER_NAME = "freshestCRLPointIssuerName_";
+ public static final String CONFIG_ENABLE = "freshestCRLPointEnable_";
+
+ public static final String VAL_CRITICAL = "freshestCRLCritical";
+ public static final String VAL_CRL_DISTRIBUTION_POINTS =
+ "freshestCRLPointsValue";
+
+ private static final String POINT_TYPE = "Point Type";
+ private static final String POINT_NAME = "Point Name";
+ private static final String ISSUER_TYPE = "Issuer Type";
+ private static final String ISSUER_NAME = "Issuer Name";
+ private static final String ENABLE = "Enable";
+
+ private static final int DEF_NUM_POINTS = 1;
+ private static final int MAX_NUM_POINTS = 100;
+
+ public FreshestCRLExtDefault() {
+ super();
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ refreshConfigAndValueNames();
+ }
+
+ protected int getNumPoints() {
+ int num = DEF_NUM_POINTS;
+ String val = getConfig(CONFIG_NUM_POINTS);
+
+ if (val != null) {
+ try {
+ num = Integer.parseInt(val);
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ }
+
+ if (num >= MAX_NUM_POINTS)
+ num = DEF_NUM_POINTS;
+
+ return num;
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ int num = 0;
+ if (name.equals(CONFIG_NUM_POINTS)) {
+ try {
+ num = Integer.parseInt(value);
+
+ if (num >= MAX_NUM_POINTS || num < 0) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_POINTS));
+ }
+
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_POINTS));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public Enumeration<String> getConfigNames() {
+ refreshConfigAndValueNames();
+ return super.getConfigNames();
+ }
+
+ protected void refreshConfigAndValueNames() {
+ //refesh our config name list
+
+ super.refreshConfigAndValueNames();
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_CRL_DISTRIBUTION_POINTS);
+
+ addConfigName(CONFIG_CRITICAL);
+ int num = getNumPoints();
+
+ addConfigName(CONFIG_NUM_POINTS);
+ for (int i = 0; i < num; i++) {
+ addConfigName(CONFIG_POINT_TYPE + i);
+ addConfigName(CONFIG_POINT_NAME + i);
+ addConfigName(CONFIG_ISSUER_TYPE + i);
+ addConfigName(CONFIG_ISSUER_NAME + i);
+ addConfigName(CONFIG_ENABLE + i);
+ }
+
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.startsWith(CONFIG_POINT_TYPE)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_POINT_TYPE"));
+ } else if (name.startsWith(CONFIG_POINT_NAME)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_POINT_NAME"));
+ } else if (name.startsWith(CONFIG_ISSUER_TYPE)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_ISSUER_TYPE"));
+ } else if (name.startsWith(CONFIG_ISSUER_NAME)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_ISSUER_NAME"));
+ } else if (name.startsWith(CONFIG_ENABLE)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_ENABLE"));
+ } else if (name.startsWith(CONFIG_NUM_POINTS)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "1",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NUM_DIST_POINTS"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_CRL_DISTRIBUTION_POINTS)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRL_DISTRIBUTION_POINTS"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ FreshestCRLExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (FreshestCRLExtension)
+ getExtension(FreshestCRLExtension.OID,
+ info);
+
+ if (ext == null) {
+ populate(locale, info);
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (FreshestCRLExtension)
+ getExtension(FreshestCRLExtension.OID,
+ info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ ext.setCritical(val);
+ } else if (name.equals(VAL_CRL_DISTRIBUTION_POINTS)) {
+ ext = (FreshestCRLExtension)
+ getExtension(FreshestCRLExtension.OID,
+ info);
+
+ Vector<NameValuePairs> v = parseRecords(value);
+ int size = v.size();
+
+ boolean critical = ext.isCritical();
+ int i = 0;
+
+ for (; i < size; i++) {
+ NameValuePairs nvps = v.elementAt(i);
+ String pointType = null;
+ String pointValue = null;
+ String issuerType = null;
+ String issuerValue = null;
+ String enable = null;
+ CRLDistributionPoint cdp = new CRLDistributionPoint();
+
+ for (String name1 : nvps.keySet()) {
+
+ if (name1.equals(POINT_TYPE)) {
+ pointType = nvps.get(name1);
+ } else if (name1.equals(POINT_NAME)) {
+ pointValue = nvps.get(name1);
+ } else if (name1.equals(ISSUER_TYPE)) {
+ issuerType = nvps.get(name1);
+ } else if (name1.equals(ISSUER_NAME)) {
+ issuerValue = nvps.get(name1);
+ } else if (name1.equals(ENABLE)) {
+ enable = nvps.get(name1);
+ }
+ }
+
+ if (enable != null && enable.equals("true")) {
+ if (pointType != null)
+ addCRLPoint(locale, cdp, pointType, pointValue);
+ if (issuerType != null)
+ addIssuer(locale, cdp, issuerType, issuerValue);
+
+ // this is the first distribution point
+ if (i == 0) {
+ ext = new FreshestCRLExtension(cdp);
+ ext.setCritical(critical);
+ } else {
+ ext.addPoint(cdp);
+ }
+ }
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ replaceExtension(PKIXExtensions.FreshestCRL_Id.toString(),
+ ext, info);
+ } catch (EProfileException e) {
+ CMS.debug("FreshestCRLExtDefault: setValue " +
+ e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ private void addCRLPoint(Locale locale, CRLDistributionPoint cdp, String type,
+ String value) throws EPropertyException {
+ try {
+ if (value == null || value.length() == 0)
+ return;
+
+ if (isGeneralNameType(type)) {
+ GeneralNames gen = new GeneralNames();
+
+ gen.addElement(parseGeneralName(type, value));
+ cdp.setFullName(gen);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", type));
+ }
+ } catch (IOException e) {
+ CMS.debug("FreshestCRLExtDefault: addCRLPoint " +
+ e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", type));
+ } catch (GeneralNamesException e) {
+ CMS.debug("FreshestCRLExtDefault: addCRLPoint " +
+ e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", type));
+ }
+ }
+
+ private void addIssuer(Locale locale, CRLDistributionPoint cdp, String type,
+ String value) throws EPropertyException {
+ if (value == null || value.length() == 0)
+ return;
+ try {
+ if (isGeneralNameType(type)) {
+ GeneralNames gen = new GeneralNames();
+
+ gen.addElement(parseGeneralName(type, value));
+ cdp.setCRLIssuer(gen);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", type));
+ }
+ } catch (IOException e) {
+ CMS.debug("FreshestCRLExtDefault: addIssuer " +
+ e.toString());
+ } catch (GeneralNamesException e) {
+ CMS.debug("FreshestCRLExtDefault: addIssuer " +
+ e.toString());
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ FreshestCRLExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (FreshestCRLExtension)
+ getExtension(FreshestCRLExtension.OID,
+ info);
+ if (ext == null) {
+ try {
+ populate(locale, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (FreshestCRLExtension)
+ getExtension(FreshestCRLExtension.OID,
+ info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_CRL_DISTRIBUTION_POINTS)) {
+ ext = (FreshestCRLExtension)
+ getExtension(FreshestCRLExtension.OID,
+ info);
+
+ if (ext == null)
+ return "";
+
+ Vector<NameValuePairs> recs = new Vector<NameValuePairs>();
+ int num = getNumPoints();
+ for (int i = 0; i < num; i++) {
+ NameValuePairs pairs = null;
+
+ if (i < ext.getNumPoints()) {
+ CRLDistributionPoint p = ext.getPointAt(i);
+ GeneralNames gns = p.getFullName();
+
+ pairs = buildGeneralNames(gns, p);
+ } else {
+ pairs = buildEmptyGeneralNames();
+ }
+ recs.addElement(pairs);
+ }
+
+ return buildRecords(recs);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ protected NameValuePairs buildEmptyGeneralNames() {
+ NameValuePairs pairs = new NameValuePairs();
+
+ pairs.put(POINT_TYPE, "");
+ pairs.put(POINT_NAME, "");
+ pairs.put(ISSUER_TYPE, "");
+ pairs.put(ISSUER_NAME, "");
+ pairs.put(ENABLE, "false");
+ return pairs;
+ }
+
+ protected NameValuePairs buildGeneralNames(GeneralNames gns, CRLDistributionPoint p)
+ throws EPropertyException {
+
+ NameValuePairs pairs = new NameValuePairs();
+
+ boolean hasFullName = false;
+
+ pairs.put(ENABLE, "true");
+ if (gns == null) {
+ pairs.put(POINT_TYPE, "");
+ pairs.put(POINT_NAME, "");
+ } else {
+ GeneralName gn = (GeneralName) gns.elementAt(0);
+
+ if (gn != null) {
+ hasFullName = true;
+
+ pairs.put(POINT_TYPE, getGeneralNameType(gn));
+ pairs.put(POINT_NAME, getGeneralNameValue(gn));
+ }
+ }
+
+ if (!hasFullName) {
+ pairs.put(POINT_TYPE, GN_DIRECTORY_NAME);
+ pairs.put(POINT_NAME, "");
+ }
+
+ gns = p.getCRLIssuer();
+
+ if (gns == null) {
+ pairs.put(ISSUER_TYPE, GN_DIRECTORY_NAME);
+ pairs.put(ISSUER_NAME, "");
+ } else {
+ GeneralName gn = (GeneralName) gns.elementAt(0);
+
+ if (gn != null) {
+ hasFullName = true;
+
+ pairs.put(ISSUER_TYPE, getGeneralNameType(gn));
+ pairs.put(ISSUER_NAME, getGeneralNameValue(gn));
+ }
+ }
+ return pairs;
+ }
+
+ public String getText(Locale locale) {
+ StringBuffer sb = new StringBuffer();
+ int num = getNumPoints();
+
+ for (int i = 0; i < num; i++) {
+ sb.append("Record #");
+ sb.append(i);
+ sb.append("{");
+ sb.append(POINT_TYPE + ":");
+ sb.append(getConfig(CONFIG_POINT_TYPE + i));
+ sb.append(",");
+ sb.append(POINT_NAME + ":");
+ sb.append(getConfig(CONFIG_POINT_NAME + i));
+ sb.append(",");
+ sb.append(ISSUER_TYPE + ":");
+ sb.append(getConfig(CONFIG_ISSUER_TYPE + i));
+ sb.append(",");
+ sb.append(ISSUER_NAME + ":");
+ sb.append(getConfig(CONFIG_ISSUER_NAME + i));
+ sb.append(",");
+ sb.append(ENABLE + ":");
+ sb.append(getConfig(CONFIG_ENABLE + i));
+ sb.append("}");
+ }
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_DEF_FRESHEST_CRL_EXT",
+ getConfig(CONFIG_CRITICAL),
+ sb.toString());
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ FreshestCRLExtension ext = createExtension(request);
+
+ if (ext == null)
+ return;
+ addExtension(FreshestCRLExtension.OID, ext, info);
+ }
+
+ public FreshestCRLExtension createExtension(IRequest request) {
+ FreshestCRLExtension ext = new FreshestCRLExtension();
+ int num = 0;
+
+ try {
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+ ext.setCritical(critical);
+
+ num = getNumPoints();
+ for (int i = 0; i < num; i++) {
+ CRLDistributionPoint cdp = new CRLDistributionPoint();
+
+ String enable = getConfig(CONFIG_ENABLE + i);
+ String pointType = getConfig(CONFIG_POINT_TYPE + i);
+ String pointName = getConfig(CONFIG_POINT_NAME + i);
+ String issuerType = getConfig(CONFIG_ISSUER_TYPE + i);
+ String issuerName = getConfig(CONFIG_ISSUER_NAME + i);
+
+ if (enable != null && enable.equals("true")) {
+ if (pointType != null)
+ addCRLPoint(getLocale(request), cdp, pointType, pointName);
+ if (issuerType != null)
+ addIssuer(getLocale(request), cdp, issuerType, issuerName);
+
+ ext.addPoint(cdp);
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("FreshestCRLExtDefault: createExtension " +
+ e.toString());
+ }
+
+ return ext;
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ private void populate(Locale locale, X509CertInfo info)
+ throws EProfileException {
+ FreshestCRLExtension ext = createExtension(locale);
+
+ if (ext == null)
+ return;
+ addExtension(FreshestCRLExtension.OID, ext, info);
+ }
+
+ public FreshestCRLExtension createExtension(Locale locale) {
+ FreshestCRLExtension ext = new FreshestCRLExtension();
+ int num = 0;
+
+ try {
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+ ext.setCritical(critical);
+
+ num = getNumPoints();
+ for (int i = 0; i < num; i++) {
+ CRLDistributionPoint cdp = new CRLDistributionPoint();
+
+ String enable = getConfig(CONFIG_ENABLE + i);
+ String pointType = getConfig(CONFIG_POINT_TYPE + i);
+ String pointName = getConfig(CONFIG_POINT_NAME + i);
+ String issuerType = getConfig(CONFIG_ISSUER_TYPE + i);
+ String issuerName = getConfig(CONFIG_ISSUER_NAME + i);
+
+ if (enable != null && enable.equals("true")) {
+ if (pointType != null)
+ addCRLPoint(locale, cdp, pointType, pointName);
+ if (issuerType != null)
+ addIssuer(locale, cdp, issuerType, issuerName);
+
+ ext.addPoint(cdp);
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("FreshestCRLExtDefault: createExtension " +
+ e.toString());
+ }
+
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/GenericExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/GenericExtDefault.java
new file mode 100644
index 000000000..f344648ab
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/GenericExtDefault.java
@@ -0,0 +1,253 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.util.Locale;
+
+import netscape.security.util.DerOutputStream;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.Extension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a Netscape comment extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class GenericExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "genericExtCritical";
+ public static final String CONFIG_OID = "genericExtOID";
+ public static final String CONFIG_DATA = "genericExtData";
+
+ public static final String VAL_CRITICAL = "genericExtCritical";
+ public static final String VAL_DATA = "genericExtData";
+
+ public GenericExtDefault() {
+ super();
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_DATA);
+
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_OID);
+ addConfigName(CONFIG_DATA);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(CONFIG_OID)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ "Comment Here...",
+ CMS.getUserMessage(locale, "CMS_PROFILE_OID"));
+ } else if (name.equals(CONFIG_DATA)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ "Comment Here...",
+ CMS.getUserMessage(locale, "CMS_PROFILE_EXT_VALUE"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_DATA)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_EXT_VALUE"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ Extension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ObjectIdentifier oid = new ObjectIdentifier(getConfig(CONFIG_OID));
+
+ ext = getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ populate(null, info);
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = getExtension(oid.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ boolean val = Boolean.valueOf(value).booleanValue();
+ ext.setCritical(val);
+ } else if (name.equals(VAL_DATA)) {
+ ext = getExtension(oid.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ byte data[] = getBytes(value);
+ ext.setExtensionValue(data);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ replaceExtension(ext.getExtensionId().toString(), ext, info);
+ } catch (EProfileException e) {
+ CMS.debug("GenericExtDefault: setValue " + e.toString());
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ Extension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ObjectIdentifier oid = new ObjectIdentifier(getConfig(CONFIG_OID));
+
+ ext = getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+
+ ext = getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_DATA)) {
+
+ ext = getExtension(oid.toString(), info);
+
+ if (ext == null)
+ return "";
+
+ byte data[] = ext.getExtensionValue();
+
+ if (data == null)
+ return "";
+
+ return toStr(data);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_CRITICAL),
+ getConfig(CONFIG_OID),
+ getConfig(CONFIG_DATA)
+ };
+
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_GENERIC_EXT", params);
+ }
+
+ public String toStr(byte data[]) {
+ StringBuffer b = new StringBuffer();
+ for (int i = 0; i < data.length; i++) {
+ if ((data[i] & 0xff) < 16) {
+ b.append("0");
+ }
+ b.append(Integer.toString((data[i] & 0xff), 0x10));
+ }
+ return b.toString();
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ Extension ext = createExtension(request);
+
+ addExtension(ext.getExtensionId().toString(), ext, info);
+ }
+
+ public Extension createExtension(IRequest request) {
+ Extension ext = null;
+
+ try (DerOutputStream out = new DerOutputStream()) {
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+ ObjectIdentifier oid = new ObjectIdentifier(getConfig(CONFIG_OID));
+ byte data[] = null;
+
+ if (request == null) {
+ data = getBytes(getConfig(CONFIG_DATA));
+ } else {
+ data = getBytes(mapPattern(request, getConfig(CONFIG_DATA)));
+ }
+
+ out.putOctetString(data);
+
+ ext = new Extension(oid, critical, out.toByteArray());
+ } catch (Exception e) {
+ CMS.debug("GenericExtDefault: createExtension " +
+ e.toString());
+ }
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/ImageDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/ImageDefault.java
new file mode 100644
index 000000000..c1e69c9f4
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/ImageDefault.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.util.Locale;
+
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that shows an image in the approval page.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ImageDefault extends EnrollDefault {
+
+ public static final String INPUT_IMAGE_URL = "image_url";
+
+ public static final String VAL_IMAGE_URL = "pd_image_url";
+
+ public ImageDefault() {
+ super();
+ addValueName(VAL_IMAGE_URL);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_IMAGE_URL)) {
+ return new Descriptor(IDescriptor.IMAGE_URL, null, null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_IMAGE"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ }
+
+ public String getValue(String name, Locale locale, IRequest request)
+ throws EPropertyException {
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ if (name.equals(VAL_IMAGE_URL)) {
+ return request.getExtDataInString(INPUT_IMAGE_URL);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ return null;
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_IMAGE");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/InhibitAnyPolicyExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/InhibitAnyPolicyExtDefault.java
new file mode 100644
index 000000000..2c176593a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/InhibitAnyPolicyExtDefault.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.math.BigInteger;
+import java.util.Locale;
+
+import netscape.security.extensions.InhibitAnyPolicyExtension;
+import netscape.security.util.BigInt;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an inhibit Any-Policy extension
+ *
+ * @version $Revision$, $Date$
+ */
+public class InhibitAnyPolicyExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "critical";
+ public static final String CONFIG_SKIP_CERTS = "skipCerts";
+
+ public static final String VAL_CRITICAL = "critical";
+ public static final String VAL_SKIP_CERTS = "skipCerts";
+
+ private static final String SKIP_CERTS = "Skip Certs";
+
+ public InhibitAnyPolicyExtDefault() {
+ super();
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_SKIP_CERTS);
+
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_SKIP_CERTS);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null, "true",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.startsWith(CONFIG_SKIP_CERTS)) {
+ return new Descriptor(IDescriptor.INTEGER, null, "0",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SKIP_CERTS"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ if (name.equals(CONFIG_SKIP_CERTS)) {
+ try {
+ Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_SKIP_CERTS));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null, "true",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_SKIP_CERTS)) {
+ return new Descriptor(IDescriptor.INTEGER, null, "0",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SKIP_CERTS"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ InhibitAnyPolicyExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (InhibitAnyPolicyExtension)
+ getExtension(InhibitAnyPolicyExtension.OID, info);
+
+ if (ext == null) {
+ populate(null, info);
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (InhibitAnyPolicyExtension)
+ getExtension(InhibitAnyPolicyExtension.OID, info);
+
+ if (ext == null) {
+ // it is ok, the extension is never populated or delted
+ return;
+ }
+ boolean critical = Boolean.valueOf(value).booleanValue();
+
+ ext.setCritical(critical);
+ } else if (name.equals(VAL_SKIP_CERTS)) {
+ ext = (InhibitAnyPolicyExtension)
+ getExtension(InhibitAnyPolicyExtension.OID, info);
+
+ if (ext == null) {
+ // it is ok, the extension is never populated or delted
+ return;
+ }
+ boolean critical = ext.isCritical();
+ if (value.equals("")) {
+ // if value is empty, do not add this extension
+ deleteExtension(InhibitAnyPolicyExtension.OID, info);
+ return;
+ }
+ BigInt num = null;
+ try {
+ BigInteger l = new BigInteger(value);
+ num = new BigInt(l);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ ext = new InhibitAnyPolicyExtension(critical,
+ num);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ replaceExtension(InhibitAnyPolicyExtension.OID, ext, info);
+ } catch (EProfileException e) {
+ CMS.debug("InhibitAnyPolicyExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ InhibitAnyPolicyExtension ext =
+ (InhibitAnyPolicyExtension)
+ getExtension(InhibitAnyPolicyExtension.OID, info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (InhibitAnyPolicyExtension)
+ getExtension(InhibitAnyPolicyExtension.OID, info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_SKIP_CERTS)) {
+ ext = (InhibitAnyPolicyExtension)
+ getExtension(InhibitAnyPolicyExtension.OID, info);
+ if (ext == null) {
+ return null;
+ }
+
+ BigInt n = ext.getSkipCerts();
+ return "" + n.toInt();
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ /*
+ * returns text that goes into description for this extension on
+ * a profile
+ */
+ public String getText(Locale locale) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(SKIP_CERTS + ":");
+ sb.append(getConfig(CONFIG_SKIP_CERTS));
+
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_DEF_INHIBIT_ANY_POLICY_EXT",
+ getConfig(CONFIG_CRITICAL), sb.toString());
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ InhibitAnyPolicyExtension ext = null;
+
+ ext = createExtension(request);
+ addExtension(InhibitAnyPolicyExtension.OID, ext, info);
+ }
+
+ public InhibitAnyPolicyExtension createExtension(IRequest request)
+ throws EProfileException {
+ InhibitAnyPolicyExtension ext = null;
+
+ boolean critical = Boolean.valueOf(
+ getConfig(CONFIG_CRITICAL)).booleanValue();
+
+ String str = getConfig(CONFIG_SKIP_CERTS);
+ if (str == null || str.equals("")) {
+ ext = new InhibitAnyPolicyExtension();
+ ext.setCritical(critical);
+ } else {
+ BigInt val = null;
+ try {
+ BigInteger b = new BigInteger(str);
+ val = new BigInt(b);
+ } catch (NumberFormatException e) {
+ throw new EProfileException(
+ CMS.getUserMessage("CMS_PROFILE_INHIBIT_ANY_POLICY_WRONG_SKIP_CERTS"));
+ }
+
+ try {
+ ext = new InhibitAnyPolicyExtension(critical, val);
+ } catch (Exception e) {
+ CMS.debug(e.toString());
+ }
+ }
+
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/IssuerAltNameExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/IssuerAltNameExtDefault.java
new file mode 100644
index 000000000..ec203713b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/IssuerAltNameExtDefault.java
@@ -0,0 +1,317 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNameInterface;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.IssuerAlternativeNameExtension;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a issuer alternative name extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class IssuerAltNameExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "issuerAltNameExtCritical";
+ public static final String CONFIG_TYPE = "issuerAltExtType";
+ public static final String CONFIG_PATTERN = "issuerAltExtPattern";
+
+ public static final String VAL_CRITICAL = "issuerAltNameExtCritical";
+ public static final String VAL_GENERAL_NAMES = "issuerAltNames";
+
+ public IssuerAltNameExtDefault() {
+ super();
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_GENERAL_NAMES);
+
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_TYPE);
+ addConfigName(CONFIG_PATTERN);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(CONFIG_TYPE)) {
+ return new Descriptor(IDescriptor.CHOICE,
+ "RFC822Name,DNSName,DirectoryName,EDIPartyName,URIName,IPAddress,OIDName",
+ "RFC822Name",
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_ISSUER_ALT_NAME_TYPE"));
+ } else if (name.equals(CONFIG_PATTERN)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_ISSUER_ALT_NAME_PATTERN"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_GENERAL_NAMES)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_GENERAL_NAMES"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ IssuerAlternativeNameExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext =
+ (IssuerAlternativeNameExtension)
+ getExtension(PKIXExtensions.IssuerAlternativeName_Id.toString(), info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext =
+ (IssuerAlternativeNameExtension)
+ getExtension(PKIXExtensions.IssuerAlternativeName_Id.toString(), info);
+
+ if (ext == null) {
+ // it is ok, the extension is never populated or delted
+ return;
+ }
+ boolean critical = Boolean.valueOf(value).booleanValue();
+
+ ext.setCritical(critical);
+ } else if (name.equals(VAL_GENERAL_NAMES)) {
+ ext =
+ (IssuerAlternativeNameExtension)
+ getExtension(PKIXExtensions.IssuerAlternativeName_Id.toString(), info);
+
+ if (ext == null) {
+ // it is ok, the extension is never populated or delted
+ return;
+ }
+ if (value.equals("")) {
+ // if value is empty, do not add this extension
+ deleteExtension(PKIXExtensions.IssuerAlternativeName_Id.toString(), info);
+ return;
+ }
+ GeneralNames gn = new GeneralNames();
+ StringTokenizer st = new StringTokenizer(value, "\r\n");
+
+ while (st.hasMoreTokens()) {
+ String gname = st.nextToken();
+
+ GeneralNameInterface n = parseGeneralName(gname);
+ if (n != null) {
+ gn.addElement(n);
+ }
+ }
+ ext.set(IssuerAlternativeNameExtension.ISSUER_NAME, gn);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ replaceExtension(
+ PKIXExtensions.IssuerAlternativeName_Id.toString(),
+ ext, info);
+ } catch (IOException e) {
+ CMS.debug("IssuerAltNameExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } catch (EProfileException e) {
+ CMS.debug("IssuerAltNameExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ try {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ IssuerAlternativeNameExtension ext =
+ (IssuerAlternativeNameExtension)
+ getExtension(PKIXExtensions.IssuerAlternativeName_Id.toString(), info);
+
+ if (ext == null) {
+
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext =
+ (IssuerAlternativeNameExtension)
+ getExtension(PKIXExtensions.IssuerAlternativeName_Id.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_GENERAL_NAMES)) {
+ ext =
+ (IssuerAlternativeNameExtension)
+ getExtension(PKIXExtensions.IssuerAlternativeName_Id.toString(), info);
+ if (ext == null) {
+ return "";
+ }
+
+ GeneralNames names = (GeneralNames)
+ ext.get(IssuerAlternativeNameExtension.ISSUER_NAME);
+ StringBuffer sb = new StringBuffer();
+ Enumeration<GeneralNameInterface> e = names.elements();
+
+ while (e.hasMoreElements()) {
+ GeneralName gn = (GeneralName) e.nextElement();
+
+ if (!sb.toString().equals("")) {
+ sb.append("\r\n");
+ }
+ sb.append(toGeneralNameString(gn));
+ }
+ return sb.toString();
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } catch (IOException e) {
+ CMS.debug("IssuerAltNameExtDefault: getValue " +
+ e.toString());
+ }
+ return null;
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_CRITICAL),
+ getConfig(CONFIG_PATTERN),
+ getConfig(CONFIG_TYPE)
+ };
+
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_ISSUER_ALT_NAME_EXT", params);
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ IssuerAlternativeNameExtension ext = null;
+
+ try {
+ ext = createExtension(request);
+
+ } catch (IOException e) {
+ CMS.debug("IssuerAltNameExtDefault: populate " + e.toString());
+ }
+ addExtension(PKIXExtensions.IssuerAlternativeName_Id.toString(),
+ ext, info);
+ }
+
+ public IssuerAlternativeNameExtension createExtension(IRequest request)
+ throws IOException {
+ IssuerAlternativeNameExtension ext = null;
+
+ try {
+ ext = new IssuerAlternativeNameExtension();
+ } catch (Exception e) {
+ CMS.debug(e.toString());
+ throw new IOException(e.toString());
+ }
+ boolean critical = Boolean.valueOf(
+ getConfig(CONFIG_CRITICAL)).booleanValue();
+ String pattern = getConfig(CONFIG_PATTERN);
+
+ if (!pattern.equals("")) {
+ GeneralNames gn = new GeneralNames();
+
+ String gname = "";
+
+ if (request != null) {
+ gname = mapPattern(request, pattern);
+ }
+
+ gn.addElement(parseGeneralName(
+ getConfig(CONFIG_TYPE) + ":" + gname));
+ ext.set(IssuerAlternativeNameExtension.ISSUER_NAME, gn);
+ }
+ ext.setCritical(critical);
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/KeyUsageExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/KeyUsageExtDefault.java
new file mode 100644
index 000000000..bbc4f5227
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/KeyUsageExtDefault.java
@@ -0,0 +1,511 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a Key Usage extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class KeyUsageExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "keyUsageCritical";
+ public static final String CONFIG_DIGITAL_SIGNATURE =
+ "keyUsageDigitalSignature";
+ public static final String CONFIG_NON_REPUDIATION =
+ "keyUsageNonRepudiation";
+ public static final String CONFIG_KEY_ENCIPHERMENT =
+ "keyUsageKeyEncipherment";
+ public static final String CONFIG_DATA_ENCIPHERMENT =
+ "keyUsageDataEncipherment";
+ public static final String CONFIG_KEY_AGREEMENT = "keyUsageKeyAgreement";
+ public static final String CONFIG_KEY_CERTSIGN = "keyUsageKeyCertSign";
+ public static final String CONFIG_CRL_SIGN = "keyUsageCrlSign";
+ public static final String CONFIG_ENCIPHER_ONLY = "keyUsageEncipherOnly";
+ public static final String CONFIG_DECIPHER_ONLY = "keyUsageDecipherOnly";
+
+ public static final String VAL_CRITICAL = "keyUsageCritical";
+ public static final String VAL_DIGITAL_SIGNATURE =
+ "keyUsageDigitalSignature";
+ public static final String VAL_NON_REPUDIATION =
+ "keyUsageNonRepudiation";
+ public static final String VAL_KEY_ENCIPHERMENT =
+ "keyUsageKeyEncipherment";
+ public static final String VAL_DATA_ENCIPHERMENT =
+ "keyUsageDataEncipherment";
+ public static final String VAL_KEY_AGREEMENT = "keyUsageKeyAgreement";
+ public static final String VAL_KEY_CERTSIGN = "keyUsageKeyCertSign";
+ public static final String VAL_CRL_SIGN = "keyUsageCrlSign";
+ public static final String VAL_ENCIPHER_ONLY = "keyUsageEncipherOnly";
+ public static final String VAL_DECIPHER_ONLY = "keyUsageDecipherOnly";
+
+ public KeyUsageExtDefault() {
+ super();
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_DIGITAL_SIGNATURE);
+ addValueName(VAL_NON_REPUDIATION);
+ addValueName(VAL_KEY_ENCIPHERMENT);
+ addValueName(VAL_DATA_ENCIPHERMENT);
+ addValueName(VAL_KEY_AGREEMENT);
+ addValueName(VAL_KEY_CERTSIGN);
+ addValueName(VAL_CRL_SIGN);
+ addValueName(VAL_ENCIPHER_ONLY);
+ addValueName(VAL_DECIPHER_ONLY);
+
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_DIGITAL_SIGNATURE);
+ addConfigName(CONFIG_NON_REPUDIATION);
+ addConfigName(CONFIG_KEY_ENCIPHERMENT);
+ addConfigName(CONFIG_DATA_ENCIPHERMENT);
+ addConfigName(CONFIG_KEY_AGREEMENT);
+ addConfigName(CONFIG_KEY_CERTSIGN);
+ addConfigName(CONFIG_CRL_SIGN);
+ addConfigName(CONFIG_ENCIPHER_ONLY);
+ addConfigName(CONFIG_DECIPHER_ONLY);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(CONFIG_DIGITAL_SIGNATURE)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_DIGITAL_SIGNATURE"));
+ } else if (name.equals(CONFIG_NON_REPUDIATION)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NON_REPUDIATION"));
+ } else if (name.equals(CONFIG_KEY_ENCIPHERMENT)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_ENCIPHERMENT"));
+ } else if (name.equals(CONFIG_DATA_ENCIPHERMENT)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_DATA_ENCIPHERMENT"));
+ } else if (name.equals(CONFIG_KEY_AGREEMENT)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_AGREEMENT"));
+ } else if (name.equals(CONFIG_KEY_CERTSIGN)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_CERTSIGN"));
+ } else if (name.equals(CONFIG_CRL_SIGN)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRL_SIGN"));
+ } else if (name.equals(CONFIG_ENCIPHER_ONLY)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_ENCIPHER_ONLY"));
+ } else if (name.equals(CONFIG_DECIPHER_ONLY)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_DECIPHER_ONLY"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_DIGITAL_SIGNATURE)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_DIGITAL_SIGNATURE"));
+ } else if (name.equals(VAL_NON_REPUDIATION)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NON_REPUDIATION"));
+ } else if (name.equals(VAL_KEY_ENCIPHERMENT)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_ENCIPHERMENT"));
+ } else if (name.equals(VAL_DATA_ENCIPHERMENT)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_DATA_ENCIPHERMENT"));
+ } else if (name.equals(VAL_KEY_AGREEMENT)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_AGREEMENT"));
+ } else if (name.equals(VAL_KEY_CERTSIGN)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_CERTSIGN"));
+ } else if (name.equals(VAL_CRL_SIGN)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRL_SIGN"));
+ } else if (name.equals(VAL_ENCIPHER_ONLY)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_ENCIPHER_ONLY"));
+ } else if (name.equals(VAL_DECIPHER_ONLY)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_DECIPHER_ONLY"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ KeyUsageExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+
+ if (ext == null) {
+ populate(null, info);
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ if (ext == null) {
+ return;
+ }
+ ext.setCritical(val);
+ } else if (name.equals(VAL_DIGITAL_SIGNATURE)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(KeyUsageExtension.DIGITAL_SIGNATURE, val);
+ } else if (name.equals(VAL_NON_REPUDIATION)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(KeyUsageExtension.NON_REPUDIATION, val);
+ } else if (name.equals(VAL_KEY_ENCIPHERMENT)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(KeyUsageExtension.KEY_ENCIPHERMENT, val);
+ } else if (name.equals(VAL_DATA_ENCIPHERMENT)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(KeyUsageExtension.DATA_ENCIPHERMENT, val);
+ } else if (name.equals(VAL_KEY_AGREEMENT)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(KeyUsageExtension.KEY_AGREEMENT, val);
+ } else if (name.equals(VAL_KEY_CERTSIGN)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(KeyUsageExtension.KEY_CERTSIGN, val);
+ } else if (name.equals(VAL_CRL_SIGN)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(KeyUsageExtension.CRL_SIGN, val);
+ } else if (name.equals(VAL_ENCIPHER_ONLY)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(KeyUsageExtension.ENCIPHER_ONLY, val);
+ } else if (name.equals(VAL_DECIPHER_ONLY)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(KeyUsageExtension.DECIPHER_ONLY, val);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ replaceExtension(PKIXExtensions.KeyUsage_Id.toString(), ext, info);
+ } catch (IOException e) {
+ CMS.debug("KeyUsageExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } catch (EProfileException e) {
+ CMS.debug("KeyUsageExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ try {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ KeyUsageExtension ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_DIGITAL_SIGNATURE)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+
+ Boolean val = (Boolean)
+ ext.get(KeyUsageExtension.DIGITAL_SIGNATURE);
+
+ return val.toString();
+ } else if (name.equals(VAL_NON_REPUDIATION)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean)
+ ext.get(KeyUsageExtension.NON_REPUDIATION);
+
+ return val.toString();
+ } else if (name.equals(VAL_KEY_ENCIPHERMENT)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean)
+ ext.get(KeyUsageExtension.KEY_ENCIPHERMENT);
+
+ return val.toString();
+ } else if (name.equals(VAL_DATA_ENCIPHERMENT)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean)
+ ext.get(KeyUsageExtension.DATA_ENCIPHERMENT);
+
+ return val.toString();
+ } else if (name.equals(VAL_KEY_AGREEMENT)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean)
+ ext.get(KeyUsageExtension.KEY_AGREEMENT);
+
+ return val.toString();
+ } else if (name.equals(VAL_KEY_CERTSIGN)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean)
+ ext.get(KeyUsageExtension.KEY_CERTSIGN);
+
+ return val.toString();
+ } else if (name.equals(VAL_CRL_SIGN)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean)
+ ext.get(KeyUsageExtension.CRL_SIGN);
+
+ return val.toString();
+ } else if (name.equals(VAL_ENCIPHER_ONLY)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean)
+ ext.get(KeyUsageExtension.ENCIPHER_ONLY);
+
+ return val.toString();
+ } else if (name.equals(VAL_DECIPHER_ONLY)) {
+ ext = (KeyUsageExtension)
+ getExtension(PKIXExtensions.KeyUsage_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean)
+ ext.get(KeyUsageExtension.DECIPHER_ONLY);
+
+ return val.toString();
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } catch (IOException e) {
+ CMS.debug("KeyUsageExtDefault: getValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_CRITICAL),
+ getConfig(CONFIG_DIGITAL_SIGNATURE),
+ getConfig(CONFIG_NON_REPUDIATION),
+ getConfig(CONFIG_KEY_ENCIPHERMENT),
+ getConfig(CONFIG_DATA_ENCIPHERMENT),
+ getConfig(CONFIG_KEY_AGREEMENT),
+ getConfig(CONFIG_KEY_CERTSIGN),
+ getConfig(CONFIG_CRL_SIGN),
+ getConfig(CONFIG_ENCIPHER_ONLY),
+ getConfig(CONFIG_DECIPHER_ONLY)
+ };
+
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_KEY_USAGE_EXT", params);
+
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ KeyUsageExtension ext = createKeyUsageExtension();
+
+ addExtension(PKIXExtensions.KeyUsage_Id.toString(), ext, info);
+ }
+
+ public KeyUsageExtension createKeyUsageExtension() {
+ KeyUsageExtension ext = null;
+ boolean[] bits = new boolean[KeyUsageExtension.NBITS];
+
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+
+ bits[0] = getConfigBoolean(CONFIG_DIGITAL_SIGNATURE);
+ bits[1] = getConfigBoolean(CONFIG_NON_REPUDIATION);
+ bits[2] = getConfigBoolean(CONFIG_KEY_ENCIPHERMENT);
+ bits[3] = getConfigBoolean(CONFIG_DATA_ENCIPHERMENT);
+ bits[4] = getConfigBoolean(CONFIG_KEY_AGREEMENT);
+ bits[5] = getConfigBoolean(CONFIG_KEY_CERTSIGN);
+ bits[6] = getConfigBoolean(CONFIG_CRL_SIGN);
+ bits[7] = getConfigBoolean(CONFIG_ENCIPHER_ONLY);
+ bits[8] = getConfigBoolean(CONFIG_DECIPHER_ONLY);
+ try {
+ ext = new KeyUsageExtension(critical, bits);
+ } catch (Exception e) {
+ CMS.debug("KeyUsageExtDefault: createKeyUsageExtension " +
+ e.toString());
+ }
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/NSCCommentExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/NSCCommentExtDefault.java
new file mode 100644
index 000000000..f6da8aede
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/NSCCommentExtDefault.java
@@ -0,0 +1,246 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.NSCCommentExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a Netscape comment extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class NSCCommentExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "nscCommentCritical";
+ public static final String CONFIG_COMMENT = "nscCommentContent";
+
+ public static final String VAL_CRITICAL = "nscCommentCritical";
+ public static final String VAL_COMMENT = "nscCommentContent";
+
+ public NSCCommentExtDefault() {
+ super();
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_COMMENT);
+
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_COMMENT);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(CONFIG_COMMENT)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ "Comment Here...",
+ CMS.getUserMessage(locale, "CMS_PROFILE_COMMENT"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_COMMENT)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_COMMENT"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ NSCCommentExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ObjectIdentifier oid = NSCCommentExtension.OID;
+
+ ext = (NSCCommentExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ populate(null, info);
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+
+ ext = (NSCCommentExtension)
+ getExtension(oid.toString(), info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ if (ext == null) {
+ return;
+ }
+ ext.setCritical(val);
+ } else if (name.equals(VAL_COMMENT)) {
+
+ ext = (NSCCommentExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ return;
+ }
+ boolean critical = ext.isCritical();
+
+ if (value == null || value.equals(""))
+ ext = new NSCCommentExtension(critical, "");
+ // throw new EPropertyException(name+" cannot be empty");
+ else
+ ext = new NSCCommentExtension(critical, value);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ replaceExtension(ext.getExtensionId().toString(), ext, info);
+ } catch (IOException e) {
+ CMS.debug("NSCCommentExtDefault: setValue " + e.toString());
+ } catch (EProfileException e) {
+ CMS.debug("NSCCommentExtDefault: setValue " + e.toString());
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ NSCCommentExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ObjectIdentifier oid = NSCCommentExtension.OID;
+
+ ext = (NSCCommentExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+
+ ext = (NSCCommentExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_COMMENT)) {
+
+ ext = (NSCCommentExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null)
+ return "";
+
+ String comment = ext.getComment();
+
+ if (comment == null)
+ comment = "";
+
+ return comment;
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_CRITICAL),
+ getConfig(CONFIG_COMMENT)
+ };
+
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_NS_COMMENT_EXT", params);
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ NSCCommentExtension ext = createExtension();
+
+ addExtension(ext.getExtensionId().toString(), ext, info);
+ }
+
+ public NSCCommentExtension createExtension() {
+ NSCCommentExtension ext = null;
+
+ try {
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+ String comment = getConfig(CONFIG_COMMENT);
+
+ if (comment == null || comment.equals(""))
+ ext = new NSCCommentExtension(critical, "");
+ else
+ ext = new NSCCommentExtension(critical, comment);
+ } catch (Exception e) {
+ CMS.debug("NSCCommentExtension: createExtension " +
+ e.toString());
+ }
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/NSCertTypeExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/NSCertTypeExtDefault.java
new file mode 100644
index 000000000..731581945
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/NSCertTypeExtDefault.java
@@ -0,0 +1,420 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.security.cert.CertificateException;
+import java.util.Locale;
+
+import netscape.security.extensions.NSCertTypeExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a Netscape Certificate Type extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class NSCertTypeExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "nsCertCritical";
+ public static final String CONFIG_SSL_CLIENT = "nsCertSSLClient";
+ public static final String CONFIG_SSL_SERVER = "nsCertSSLServer";
+ public static final String CONFIG_EMAIL = "nsCertEmail";
+ public static final String CONFIG_OBJECT_SIGNING = "nsCertObjectSigning";
+ public static final String CONFIG_SSL_CA = "nsCertSSLCA";
+ public static final String CONFIG_EMAIL_CA = "nsCertEmailCA";
+ public static final String CONFIG_OBJECT_SIGNING_CA = "nsCertObjectSigningCA";
+
+ public static final String VAL_CRITICAL = "nsCertCritical";
+ public static final String VAL_SSL_CLIENT = "nsCertSSLClient";
+ public static final String VAL_SSL_SERVER = "nsCertSSLServer";
+ public static final String VAL_EMAIL = "nsCertEmail";
+ public static final String VAL_OBJECT_SIGNING = "nsCertObjectSigning";
+ public static final String VAL_SSL_CA = "nsCertSSLCA";
+ public static final String VAL_EMAIL_CA = "nsCertEmailCA";
+ public static final String VAL_OBJECT_SIGNING_CA = "nsCertObjectSigningCA";
+
+ public NSCertTypeExtDefault() {
+ super();
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_SSL_CLIENT);
+ addValueName(VAL_SSL_SERVER);
+ addValueName(VAL_EMAIL);
+ addValueName(VAL_OBJECT_SIGNING);
+ addValueName(VAL_SSL_CA);
+ addValueName(VAL_EMAIL_CA);
+ addValueName(VAL_OBJECT_SIGNING_CA);
+
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_SSL_CLIENT);
+ addConfigName(CONFIG_SSL_SERVER);
+ addConfigName(CONFIG_EMAIL);
+ addConfigName(CONFIG_OBJECT_SIGNING);
+ addConfigName(CONFIG_SSL_CA);
+ addConfigName(CONFIG_EMAIL_CA);
+ addConfigName(CONFIG_OBJECT_SIGNING_CA);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(CONFIG_SSL_CLIENT)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SSL_CLIENT"));
+ } else if (name.equals(CONFIG_SSL_SERVER)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SSL_SERVER"));
+ } else if (name.equals(CONFIG_EMAIL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_EMAIL"));
+ } else if (name.equals(CONFIG_OBJECT_SIGNING)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_OBJECT_SIGNING"));
+ } else if (name.equals(CONFIG_SSL_CA)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SSL_CA"));
+ } else if (name.equals(CONFIG_EMAIL_CA)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_EMAIL_CA"));
+ } else if (name.equals(CONFIG_OBJECT_SIGNING_CA)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_OBJECT_SIGNING_CA"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_SSL_CLIENT)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SSL_CLIENT"));
+ } else if (name.equals(VAL_SSL_SERVER)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SSL_SERVER"));
+ } else if (name.equals(VAL_EMAIL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_EMAIL"));
+ } else if (name.equals(VAL_OBJECT_SIGNING)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_OBJECT_SIGNING"));
+ } else if (name.equals(VAL_SSL_CA)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SSL_CA"));
+ } else if (name.equals(VAL_EMAIL_CA)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_EMAIL_CA"));
+ } else if (name.equals(VAL_OBJECT_SIGNING_CA)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_OBJECT_SIGNING_CA"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ NSCertTypeExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+
+ if (ext == null) {
+ populate(null, info);
+
+ }
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ if (ext == null) {
+ return;
+ }
+ ext.setCritical(val);
+ } else if (name.equals(VAL_SSL_CLIENT)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(NSCertTypeExtension.SSL_CLIENT, val);
+ } else if (name.equals(VAL_SSL_SERVER)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(NSCertTypeExtension.SSL_SERVER, val);
+ } else if (name.equals(VAL_EMAIL)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(NSCertTypeExtension.EMAIL, val);
+ } else if (name.equals(VAL_OBJECT_SIGNING)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(NSCertTypeExtension.OBJECT_SIGNING, val);
+ } else if (name.equals(VAL_SSL_CA)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(NSCertTypeExtension.SSL_CA, val);
+ } else if (name.equals(VAL_EMAIL_CA)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(NSCertTypeExtension.EMAIL_CA, val);
+ } else if (name.equals(VAL_OBJECT_SIGNING_CA)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ if (ext == null) {
+ return;
+ }
+ Boolean val = Boolean.valueOf(value);
+
+ ext.set(NSCertTypeExtension.OBJECT_SIGNING_CA, val);
+ } else {
+ throw new EPropertyException("Invalid name " + name);
+ }
+ replaceExtension(NSCertTypeExtension.CertType_Id.toString(), ext, info);
+ } catch (CertificateException e) {
+ CMS.debug("NSCertTypeExtDefault: setValue " + e.toString());
+ } catch (EProfileException e) {
+ CMS.debug("NSCertTypeExtDefault: setValue " + e.toString());
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ try {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ NSCertTypeExtension ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_SSL_CLIENT)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean) ext.get(NSCertTypeExtension.SSL_CLIENT);
+
+ return val.toString();
+ } else if (name.equals(VAL_SSL_SERVER)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean) ext.get(NSCertTypeExtension.SSL_SERVER);
+
+ return val.toString();
+ } else if (name.equals(VAL_EMAIL)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean) ext.get(NSCertTypeExtension.EMAIL);
+
+ return val.toString();
+ } else if (name.equals(VAL_OBJECT_SIGNING)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean) ext.get(NSCertTypeExtension.OBJECT_SIGNING);
+
+ return val.toString();
+ } else if (name.equals(VAL_SSL_CA)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean) ext.get(NSCertTypeExtension.SSL_CA);
+
+ return val.toString();
+ } else if (name.equals(VAL_EMAIL_CA)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean) ext.get(NSCertTypeExtension.EMAIL_CA);
+
+ return val.toString();
+ } else if (name.equals(VAL_OBJECT_SIGNING_CA)) {
+ ext = (NSCertTypeExtension)
+ getExtension(NSCertTypeExtension.CertType_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+ Boolean val = (Boolean) ext.get(NSCertTypeExtension.OBJECT_SIGNING_CA);
+
+ return val.toString();
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } catch (CertificateException e) {
+ CMS.debug("NSCertTypeExtDefault: setValue " + e.toString());
+ }
+ return null;
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_CRITICAL),
+ getConfig(CONFIG_SSL_CLIENT),
+ getConfig(CONFIG_SSL_SERVER),
+ getConfig(CONFIG_EMAIL),
+ getConfig(CONFIG_OBJECT_SIGNING),
+ getConfig(CONFIG_SSL_CA),
+ getConfig(CONFIG_EMAIL_CA),
+ getConfig(CONFIG_OBJECT_SIGNING_CA)
+ };
+
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_NS_CERT_TYPE_EXT", params);
+
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ NSCertTypeExtension ext = createExtension();
+
+ addExtension(NSCertTypeExtension.CertType_Id.toString(), ext, info);
+ }
+
+ public NSCertTypeExtension createExtension() {
+ NSCertTypeExtension ext = null;
+ boolean[] bits = new boolean[NSCertTypeExtension.NBITS];
+
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+
+ bits[0] = getConfigBoolean(CONFIG_SSL_CLIENT);
+ bits[1] = getConfigBoolean(CONFIG_SSL_SERVER);
+ bits[2] = getConfigBoolean(CONFIG_EMAIL);
+ bits[3] = getConfigBoolean(CONFIG_OBJECT_SIGNING);
+ bits[4] = false;
+ bits[5] = getConfigBoolean(CONFIG_SSL_CA);
+ bits[6] = getConfigBoolean(CONFIG_EMAIL_CA);
+ bits[7] = getConfigBoolean(CONFIG_OBJECT_SIGNING_CA);
+ try {
+ ext = new NSCertTypeExtension(critical, bits);
+ } catch (Exception e) {
+ CMS.debug("NSCertTypeExtDefault: createExtension " +
+ e.toString());
+ }
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/NameConstraintsExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/NameConstraintsExtDefault.java
new file mode 100644
index 000000000..f010b6134
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/NameConstraintsExtDefault.java
@@ -0,0 +1,670 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNameInterface;
+import netscape.security.x509.GeneralSubtree;
+import netscape.security.x509.GeneralSubtrees;
+import netscape.security.x509.NameConstraintsExtension;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a name constraint extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class NameConstraintsExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "nameConstraintsCritical";
+ public static final String CONFIG_NUM_PERMITTED_SUBTREES =
+ "nameConstraintsNumPermittedSubtrees";
+ public static final String CONFIG_PERMITTED_MIN_VAL = "nameConstraintsPermittedSubtreeMinValue_";
+ public static final String CONFIG_PERMITTED_MAX_VAL = "nameConstraintsPermittedSubtreeMaxValue_";
+ public static final String CONFIG_PERMITTED_NAME_CHOICE = "nameConstraintsPermittedSubtreeNameChoice_";
+ public static final String CONFIG_PERMITTED_NAME_VAL = "nameConstraintsPermittedSubtreeNameValue_";
+ public static final String CONFIG_PERMITTED_ENABLE = "nameConstraintsPermittedSubtreeEnable_";
+
+ public static final String CONFIG_NUM_EXCLUDED_SUBTREES = "nameConstraintsNumExcludedSubtrees";
+ public static final String CONFIG_EXCLUDED_MIN_VAL = "nameConstraintsExcludedSubtreeMinValue_";
+ public static final String CONFIG_EXCLUDED_MAX_VAL = "nameConstraintsExcludedSubtreeMaxValue_";
+ public static final String CONFIG_EXCLUDED_NAME_CHOICE = "nameConstraintsExcludedSubtreeNameChoice_";
+ public static final String CONFIG_EXCLUDED_NAME_VAL = "nameConstraintsExcludedSubtreeNameValue_";
+ public static final String CONFIG_EXCLUDED_ENABLE = "nameConstraintsExcludedSubtreeEnable_";
+
+ public static final String VAL_CRITICAL = "nameConstraintsCritical";
+ public static final String VAL_PERMITTED_SUBTREES = "nameConstraintsPermittedSubtreesValue";
+ public static final String VAL_EXCLUDED_SUBTREES = "nameConstraintsExcludedSubtreesValue";
+
+ private static final String GENERAL_NAME_CHOICE = "GeneralNameChoice";
+ private static final String GENERAL_NAME_VALUE = "GeneralNameValue";
+ private static final String MIN_VALUE = "Min Value";
+ private static final String MAX_VALUE = "Max Value";
+ private static final String ENABLE = "Enable";
+
+ protected static final int DEF_NUM_PERMITTED_SUBTREES = 1;
+ protected static final int DEF_NUM_EXCLUDED_SUBTREES = 1;
+ protected static final int MAX_NUM_EXCLUDED_SUBTREES = 100;
+ protected static final int MAX_NUM_PERMITTED_SUBTREES = 100;
+
+ public NameConstraintsExtDefault() {
+ super();
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ refreshConfigAndValueNames();
+
+ }
+
+ protected int getNumPermitted() {
+ int num = DEF_NUM_PERMITTED_SUBTREES;
+ String val = getConfig(CONFIG_NUM_PERMITTED_SUBTREES);
+
+ if (val != null) {
+ try {
+ num = Integer.parseInt(val);
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ }
+
+ if (num >= MAX_NUM_PERMITTED_SUBTREES)
+ num = DEF_NUM_PERMITTED_SUBTREES;
+ return num;
+ }
+
+ protected int getNumExcluded() {
+ int num = DEF_NUM_EXCLUDED_SUBTREES;
+ String val = getConfig(CONFIG_NUM_EXCLUDED_SUBTREES);
+
+ if (val != null) {
+ try {
+ num = Integer.parseInt(val);
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ }
+
+ if (num >= MAX_NUM_EXCLUDED_SUBTREES)
+ num = DEF_NUM_EXCLUDED_SUBTREES;
+
+ return num;
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ int num = 0;
+ if (name.equals(CONFIG_NUM_PERMITTED_SUBTREES)) {
+ try {
+ num = Integer.parseInt(value);
+
+ if (num >= MAX_NUM_PERMITTED_SUBTREES || num < 0) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_PERMITTED_SUBTREES));
+ }
+
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_PERMITTED_SUBTREES));
+ }
+ } else if (name.equals(CONFIG_NUM_EXCLUDED_SUBTREES)) {
+
+ try {
+ num = Integer.parseInt(value);
+
+ if (num >= MAX_NUM_EXCLUDED_SUBTREES || num < 0) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_EXCLUDED_SUBTREES));
+ }
+
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_EXCLUDED_SUBTREES));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public Enumeration<String> getConfigNames() {
+ refreshConfigAndValueNames();
+ return super.getConfigNames();
+ }
+
+ protected void refreshConfigAndValueNames() {
+ //refesh our config name list
+
+ super.refreshConfigAndValueNames();
+
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_PERMITTED_SUBTREES);
+ addValueName(VAL_EXCLUDED_SUBTREES);
+
+ addConfigName(CONFIG_CRITICAL);
+ int num = getNumPermitted();
+
+ addConfigName(CONFIG_NUM_PERMITTED_SUBTREES);
+
+ for (int i = 0; i < num; i++) {
+ addConfigName(CONFIG_PERMITTED_MIN_VAL + i);
+ addConfigName(CONFIG_PERMITTED_MAX_VAL + i);
+ addConfigName(CONFIG_PERMITTED_NAME_CHOICE + i);
+ addConfigName(CONFIG_PERMITTED_NAME_VAL + i);
+ addConfigName(CONFIG_PERMITTED_ENABLE + i);
+ }
+
+ num = getNumExcluded();
+
+ addConfigName(CONFIG_NUM_EXCLUDED_SUBTREES);
+ for (int i = 0; i < num; i++) {
+ addConfigName(CONFIG_EXCLUDED_MIN_VAL + i);
+ addConfigName(CONFIG_EXCLUDED_MAX_VAL + i);
+ addConfigName(CONFIG_EXCLUDED_NAME_CHOICE + i);
+ addConfigName(CONFIG_EXCLUDED_NAME_VAL + i);
+ addConfigName(CONFIG_EXCLUDED_ENABLE + i);
+ }
+
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.startsWith(CONFIG_PERMITTED_MIN_VAL)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_PERMITTED_MIN_VAL"));
+ } else if (name.startsWith(CONFIG_PERMITTED_MAX_VAL)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_PERMITTED_MAX_VAL"));
+ } else if (name.startsWith(CONFIG_PERMITTED_NAME_CHOICE)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_PERMITTED_NAME_CHOICE"));
+ } else if (name.startsWith(CONFIG_PERMITTED_NAME_VAL)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_PERMITTED_NAME_VAL"));
+ } else if (name.startsWith(CONFIG_PERMITTED_ENABLE)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_ENABLE"));
+ } else if (name.startsWith(CONFIG_EXCLUDED_MIN_VAL)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_EXCLUDED_MIN_VAL"));
+ } else if (name.startsWith(CONFIG_EXCLUDED_MAX_VAL)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_EXCLUDED_MAX_VAL"));
+ } else if (name.startsWith(CONFIG_EXCLUDED_NAME_CHOICE)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_EXCLUDED_NAME_CHOICE"));
+ } else if (name.startsWith(CONFIG_EXCLUDED_NAME_VAL)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_EXCLUDED_NAME_VAL"));
+ } else if (name.startsWith(CONFIG_EXCLUDED_ENABLE)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_ENABLE"));
+ } else if (name.startsWith(CONFIG_NUM_EXCLUDED_SUBTREES)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "1",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NUM_EXCLUDED_SUBTREES"));
+ } else if (name.startsWith(CONFIG_NUM_PERMITTED_SUBTREES)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "1",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NUM_PERMITTED_SUBTREES"));
+ }
+ return null;
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_PERMITTED_SUBTREES)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_PERMITTED_SUBTREES"));
+ } else if (name.equals(VAL_EXCLUDED_SUBTREES)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_EXCLUDED_SUBTREES"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ NameConstraintsExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (NameConstraintsExtension)
+ getExtension(PKIXExtensions.NameConstraints_Id.toString(), info);
+
+ if (ext == null) {
+ populate(null, info);
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (NameConstraintsExtension)
+ getExtension(PKIXExtensions.NameConstraints_Id.toString(), info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ if (ext == null) {
+ return;
+ }
+ ext.setCritical(val);
+ } else if (name.equals(VAL_PERMITTED_SUBTREES)) {
+ ext = (NameConstraintsExtension)
+ getExtension(PKIXExtensions.NameConstraints_Id.toString(), info);
+
+ if (ext == null) {
+ return;
+ }
+ if ((value == null) || (value.equals("null")) || (value.equals(""))) {
+ CMS.debug("NameConstraintsExtDefault:setValue : " +
+ "blank value for permitted subtrees ... returning");
+ return;
+ }
+
+ Vector<NameValuePairs> v = parseRecords(value);
+
+ Vector<GeneralSubtree> permittedSubtrees = createSubtrees(locale, v);
+
+ ext.set(NameConstraintsExtension.PERMITTED_SUBTREES,
+ new GeneralSubtrees(permittedSubtrees));
+ } else if (name.equals(VAL_EXCLUDED_SUBTREES)) {
+ ext = (NameConstraintsExtension)
+ getExtension(PKIXExtensions.NameConstraints_Id.toString(), info);
+
+ if (ext == null) {
+ return;
+ }
+ if ((value == null) || (value.equals("null")) || (value.equals(""))) {
+ CMS.debug("NameConstraintsExtDefault:setValue : " +
+ "blank value for excluded subtrees ... returning");
+ return;
+ }
+ Vector<NameValuePairs> v = parseRecords(value);
+
+ Vector<GeneralSubtree> excludedSubtrees = createSubtrees(locale, v);
+
+ ext.set(NameConstraintsExtension.EXCLUDED_SUBTREES,
+ new GeneralSubtrees(excludedSubtrees));
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ replaceExtension(PKIXExtensions.NameConstraints_Id.toString(), ext, info);
+ } catch (IOException e) {
+ CMS.debug("NameConstraintsExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } catch (EProfileException e) {
+ CMS.debug("NameConstraintsExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ private Vector<GeneralSubtree> createSubtrees(Locale locale, Vector<NameValuePairs> v) throws EPropertyException {
+ int size = v.size();
+ String choice = null;
+ String val = "";
+ String minS = null;
+ String maxS = null;
+
+ Vector<GeneralSubtree> subtrees = new Vector<GeneralSubtree>();
+
+ for (int i = 0; i < size; i++) {
+ NameValuePairs nvps = v.elementAt(i);
+
+ for (String name1 : nvps.keySet()) {
+
+ if (name1.equals(GENERAL_NAME_CHOICE)) {
+ choice = nvps.get(name1);
+ } else if (name1.equals(GENERAL_NAME_VALUE)) {
+ val = nvps.get(name1);
+ } else if (name1.equals(MIN_VALUE)) {
+ minS = nvps.get(name1);
+ } else if (name1.equals(MAX_VALUE)) {
+ maxS = nvps.get(name1);
+ }
+ }
+
+ if (choice == null || choice.length() == 0) {
+ throw new EPropertyException(CMS.getUserMessage(locale,
+ "CMS_PROFILE_GENERAL_NAME_NOT_FOUND"));
+ }
+
+ if (val == null)
+ val = "";
+
+ int min = 0;
+ int max = -1;
+
+ if (minS != null && minS.length() > 0)
+ min = Integer.parseInt(minS);
+ if (maxS != null && maxS.length() > 0)
+ max = Integer.parseInt(maxS);
+
+ GeneralName gn = null;
+ GeneralNameInterface gnI = null;
+
+ try {
+ gnI = parseGeneralName(choice + ":" + val);
+ } catch (IOException e) {
+ CMS.debug("NameConstraintsExtDefault: createSubtress " +
+ e.toString());
+ }
+
+ if (gnI != null) {
+ gn = new GeneralName(gnI);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(locale,
+ "CMS_PROFILE_GENERAL_NAME_NOT_FOUND"));
+ }
+ GeneralSubtree subtree = new GeneralSubtree(
+ gn, min, max);
+
+ subtrees.addElement(subtree);
+ }
+
+ return subtrees;
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ NameConstraintsExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (NameConstraintsExtension)
+ getExtension(PKIXExtensions.NameConstraints_Id.toString(), info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (NameConstraintsExtension)
+ getExtension(PKIXExtensions.NameConstraints_Id.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_PERMITTED_SUBTREES)) {
+ ext = (NameConstraintsExtension)
+ getExtension(PKIXExtensions.NameConstraints_Id.toString(), info);
+
+ if (ext == null)
+ return "";
+
+ GeneralSubtrees subtrees = null;
+
+ try {
+ subtrees = (GeneralSubtrees)
+ ext.get(NameConstraintsExtension.PERMITTED_SUBTREES);
+ } catch (IOException e) {
+ CMS.debug("NameConstraintExtDefault: getValue " + e.toString());
+ }
+
+ if (subtrees == null) {
+ CMS.debug("NameConstraintsExtDefault::getValue() VAL_PERMITTED_SUBTREES is null!");
+ throw new EPropertyException("subtrees is null");
+ }
+
+ return getSubtreesInfo(ext, subtrees);
+ } else if (name.equals(VAL_EXCLUDED_SUBTREES)) {
+ ext = (NameConstraintsExtension)
+ getExtension(PKIXExtensions.NameConstraints_Id.toString(), info);
+
+ if (ext == null)
+ return "";
+
+ GeneralSubtrees subtrees = null;
+
+ try {
+ subtrees = (GeneralSubtrees)
+ ext.get(NameConstraintsExtension.EXCLUDED_SUBTREES);
+ } catch (IOException e) {
+ CMS.debug("NameConstraintExtDefault: getValue " + e.toString());
+ }
+
+ if (subtrees == null) {
+ CMS.debug("NameConstraintsExtDefault::getValue() VAL_EXCLUDED_SUBTREES is null!");
+ throw new EPropertyException("subtrees is null");
+ }
+
+ return getSubtreesInfo(ext, subtrees);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ private String getSubtreesInfo(NameConstraintsExtension ext,
+ GeneralSubtrees subtrees) throws EPropertyException {
+ Vector<GeneralSubtree> trees = subtrees.getSubtrees();
+ int size = trees.size();
+
+ Vector<NameValuePairs> recs = new Vector<NameValuePairs>();
+
+ for (int i = 0; i < size; i++) {
+ GeneralSubtree tree = trees.elementAt(i);
+
+ GeneralName gn = tree.getGeneralName();
+ String type = getGeneralNameType(gn);
+ int max = tree.getMaxValue();
+ int min = tree.getMinValue();
+
+ NameValuePairs pairs = new NameValuePairs();
+
+ pairs.put(GENERAL_NAME_CHOICE, type);
+ pairs.put(GENERAL_NAME_VALUE, getGeneralNameValue(gn));
+ pairs.put(MIN_VALUE, Integer.toString(min));
+ pairs.put(MAX_VALUE, Integer.toString(max));
+ pairs.put(ENABLE, "true");
+
+ recs.addElement(pairs);
+ }
+
+ return buildRecords(recs);
+ }
+
+ public String getText(Locale locale) {
+ StringBuffer sb = new StringBuffer();
+ int num = getNumPermitted();
+
+ for (int i = 0; i < num; i++) {
+ sb.append("Permitted #");
+ sb.append(i);
+ sb.append("{");
+ sb.append(GENERAL_NAME_CHOICE + ":");
+ sb.append(getConfig(CONFIG_PERMITTED_NAME_CHOICE + i));
+ sb.append(",");
+ sb.append(GENERAL_NAME_VALUE + ":");
+ sb.append(getConfig(CONFIG_PERMITTED_NAME_VAL + i));
+ sb.append(",");
+ sb.append(MIN_VALUE + ":");
+ sb.append(getConfig(CONFIG_PERMITTED_MIN_VAL + i));
+ sb.append(",");
+ sb.append(MAX_VALUE + ":");
+ sb.append(getConfig(CONFIG_PERMITTED_MAX_VAL + i));
+ sb.append("}");
+ }
+ num = getNumExcluded();
+ for (int i = 0; i < num; i++) {
+ sb.append("Exluded #");
+ sb.append(i);
+ sb.append("{");
+ sb.append(GENERAL_NAME_CHOICE + ":");
+ sb.append(getConfig(CONFIG_EXCLUDED_NAME_CHOICE + i));
+ sb.append(",");
+ sb.append(GENERAL_NAME_VALUE + ":");
+ sb.append(getConfig(CONFIG_EXCLUDED_NAME_VAL + i));
+ sb.append(",");
+ sb.append(MIN_VALUE + ":");
+ sb.append(getConfig(CONFIG_EXCLUDED_MIN_VAL + i));
+ sb.append(",");
+ sb.append(MAX_VALUE + ":");
+ sb.append(getConfig(CONFIG_EXCLUDED_MAX_VAL + i));
+ sb.append("}");
+ }
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_DEF_NAME_CONSTRAINTS_EXT",
+ getConfig(CONFIG_CRITICAL), sb.toString());
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ NameConstraintsExtension ext = createExtension();
+
+ addExtension(PKIXExtensions.NameConstraints_Id.toString(), ext, info);
+ }
+
+ public NameConstraintsExtension createExtension() {
+ NameConstraintsExtension ext = null;
+
+ try {
+ int num = getNumPermitted();
+
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+
+ Vector<GeneralSubtree> v = new Vector<GeneralSubtree>();
+
+ for (int i = 0; i < num; i++) {
+ String enable = getConfig(CONFIG_PERMITTED_ENABLE + i);
+
+ if (enable != null && enable.equals("true")) {
+ String choice = getConfig(CONFIG_PERMITTED_NAME_CHOICE + i);
+ String value = getConfig(CONFIG_PERMITTED_NAME_VAL + i);
+ String minS = getConfig(CONFIG_PERMITTED_MIN_VAL + i);
+ String maxS = getConfig(CONFIG_PERMITTED_MAX_VAL + i);
+
+ v.addElement(createSubtree(choice, value, minS, maxS));
+ }
+ }
+
+ Vector<GeneralSubtree> v1 = new Vector<GeneralSubtree>();
+
+ num = getNumExcluded();
+ for (int i = 0; i < num; i++) {
+ String enable = getConfig(CONFIG_EXCLUDED_ENABLE + i);
+
+ if (enable != null && enable.equals("true")) {
+ String choice = getConfig(CONFIG_EXCLUDED_NAME_CHOICE + i);
+ String value = getConfig(CONFIG_EXCLUDED_NAME_VAL + i);
+ String minS = getConfig(CONFIG_EXCLUDED_MIN_VAL + i);
+ String maxS = getConfig(CONFIG_EXCLUDED_MAX_VAL + i);
+
+ v1.addElement(createSubtree(choice, value, minS, maxS));
+ }
+ }
+
+ ext = new NameConstraintsExtension(critical,
+ new GeneralSubtrees(v), new GeneralSubtrees(v1));
+ } catch (Exception e) {
+ CMS.debug("NameConstraintsExtDefault: createExtension " +
+ e.toString());
+ }
+
+ return ext;
+ }
+
+ private GeneralSubtree createSubtree(String choice, String value,
+ String minS, String maxS) {
+ GeneralName gn = null;
+ GeneralNameInterface gnI = null;
+
+ try {
+ gnI = parseGeneralName(choice + ":" + value);
+ } catch (IOException e) {
+ CMS.debug(e.toString());
+ }
+ if (gnI != null)
+ gn = new GeneralName(gnI);
+ else
+ //throw new EPropertyException("GeneralName must not be null");
+ return null;
+
+ int min = 0;
+
+ if (minS != null && minS.length() > 0)
+ min = Integer.parseInt(minS);
+ int max = -1;
+
+ if (maxS != null && maxS.length() > 0)
+ max = Integer.parseInt(maxS);
+
+ return (new GeneralSubtree(gn, min, max));
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/NoDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/NoDefault.java
new file mode 100644
index 000000000..2e80aee2f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/NoDefault.java
@@ -0,0 +1,111 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements no default policy.
+ *
+ * @version $Revision$, $Date$
+ */
+public class NoDefault implements IPolicyDefault {
+
+ public static final String PROP_NAME = "name";
+
+ protected Vector<String> mValues = new Vector<String>();
+ protected Vector<String> mNames = new Vector<String>();
+ protected IConfigStore mConfig = null;
+
+ public Enumeration<String> getConfigNames() {
+ return mNames.elements();
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ }
+
+ public String getDefaultConfig(String name) {
+ return null;
+ }
+
+ public String getConfig(String name) {
+ return null;
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ mConfig = config;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request)
+ throws EProfileException {
+ }
+
+ public Enumeration<String> getValueNames() {
+ return mValues.elements();
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public void setValue(String name, Locale locale, IRequest request,
+ String value)
+ throws EPropertyException {
+ }
+
+ public String getValue(String name, Locale locale, IRequest request) {
+ return null;
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_NO_DEFAULT");
+ }
+
+ public String getName(Locale locale) {
+ try {
+ return mConfig.getString(PROP_NAME);
+ } catch (EBaseException e) {
+ return null;
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/OCSPNoCheckExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/OCSPNoCheckExtDefault.java
new file mode 100644
index 000000000..ab5b8c62b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/OCSPNoCheckExtDefault.java
@@ -0,0 +1,185 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.util.Locale;
+
+import netscape.security.extensions.OCSPNoCheckExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates an OCSP No Check extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class OCSPNoCheckExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "ocspNoCheckCritical";
+
+ public static final String VAL_CRITICAL = "ocspNoCheckCritical";
+
+ public OCSPNoCheckExtDefault() {
+ super();
+ addValueName(VAL_CRITICAL);
+ addConfigName(CONFIG_CRITICAL);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ OCSPNoCheckExtension ext = (OCSPNoCheckExtension)
+ getExtension(OCSPNoCheckExtension.OID, info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (OCSPNoCheckExtension)
+ getExtension(OCSPNoCheckExtension.OID, info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ if (ext == null) {
+ return;
+ }
+ ext.setCritical(val);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ OCSPNoCheckExtension ext = (OCSPNoCheckExtension)
+ getExtension(OCSPNoCheckExtension.OID, info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (OCSPNoCheckExtension)
+ getExtension(OCSPNoCheckExtension.OID, info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_OCSP_NO_CHECK_EXT",
+ getConfig(CONFIG_CRITICAL));
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ OCSPNoCheckExtension ext = createExtension();
+
+ addExtension(OCSPNoCheckExtension.OID, ext, info);
+ }
+
+ public OCSPNoCheckExtension createExtension() {
+ OCSPNoCheckExtension ext = null;
+
+ try {
+ ext = new OCSPNoCheckExtension();
+ } catch (Exception e) {
+ CMS.debug("OCSPNoCheckExtDefault: createExtension " +
+ e.toString());
+ return null;
+ }
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+
+ ext.setCritical(critical);
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/PolicyConstraintsExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/PolicyConstraintsExtDefault.java
new file mode 100644
index 000000000..ced6096a3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/PolicyConstraintsExtDefault.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.PolicyConstraintsExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a policy constraints extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class PolicyConstraintsExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "policyConstraintsCritical";
+ public static final String CONFIG_REQ_EXPLICIT_POLICY = "policyConstraintsReqExplicitPolicy";
+ public static final String CONFIG_INHIBIT_POLICY_MAPPING = "policyConstraintsInhibitPolicyMapping";
+
+ public static final String VAL_CRITICAL = "policyConstraintsCritical";
+ public static final String VAL_REQ_EXPLICIT_POLICY = "policyConstraintsReqExplicitPolicy";
+ public static final String VAL_INHIBIT_POLICY_MAPPING = "policyConstraintsInhibitPolicyMapping";
+
+ public PolicyConstraintsExtDefault() {
+ super();
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_REQ_EXPLICIT_POLICY);
+ addValueName(VAL_INHIBIT_POLICY_MAPPING);
+
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_REQ_EXPLICIT_POLICY);
+ addConfigName(CONFIG_INHIBIT_POLICY_MAPPING);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(CONFIG_REQ_EXPLICIT_POLICY)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_REQUIRED_EXPLICIT_POLICY"));
+ } else if (name.equals(CONFIG_INHIBIT_POLICY_MAPPING)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_INHIBIT_POLICY_MAPPING"));
+ }
+ return null;
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_REQ_EXPLICIT_POLICY)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_REQUIRED_EXPLICIT_POLICY"));
+ } else if (name.equals(VAL_INHIBIT_POLICY_MAPPING)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_INHIBIT_POLICY_MAPPING"));
+ }
+ return null;
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ PolicyConstraintsExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (PolicyConstraintsExtension)
+ getExtension(PKIXExtensions.PolicyConstraints_Id.toString(),
+ info);
+
+ if (ext == null) {
+ populate(null, info);
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (PolicyConstraintsExtension)
+ getExtension(PKIXExtensions.PolicyConstraints_Id.toString(),
+ info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ if (ext == null) {
+ return;
+ }
+ ext.setCritical(val);
+ } else if (name.equals(VAL_REQ_EXPLICIT_POLICY)) {
+ ext = (PolicyConstraintsExtension)
+ getExtension(PKIXExtensions.PolicyConstraints_Id.toString(),
+ info);
+
+ if (ext == null) {
+ return;
+ }
+ Integer num = new Integer(value);
+
+ ext.set(PolicyConstraintsExtension.REQUIRE, num);
+ } else if (name.equals(VAL_INHIBIT_POLICY_MAPPING)) {
+ ext = (PolicyConstraintsExtension)
+ getExtension(PKIXExtensions.PolicyConstraints_Id.toString(),
+ info);
+
+ if (ext == null) {
+ return;
+ }
+ Integer num = new Integer(value);
+
+ ext.set(PolicyConstraintsExtension.INHIBIT, num);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ replaceExtension(PKIXExtensions.PolicyConstraints_Id.toString(),
+ ext, info);
+ } catch (EProfileException e) {
+ CMS.debug("PolicyConstraintsExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } catch (IOException e) {
+ CMS.debug("PolicyConstraintsExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ PolicyConstraintsExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (PolicyConstraintsExtension)
+ getExtension(PKIXExtensions.PolicyConstraints_Id.toString(),
+ info);
+ if (ext == null) {
+
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (PolicyConstraintsExtension)
+ getExtension(PKIXExtensions.PolicyConstraints_Id.toString(),
+ info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_REQ_EXPLICIT_POLICY)) {
+ ext = (PolicyConstraintsExtension)
+ getExtension(PKIXExtensions.PolicyConstraints_Id.toString(),
+ info);
+
+ if (ext == null)
+ return "";
+
+ int num = ext.getRequireExplicitMapping();
+
+ return "" + num;
+ } else if (name.equals(VAL_INHIBIT_POLICY_MAPPING)) {
+ ext = (PolicyConstraintsExtension)
+ getExtension(PKIXExtensions.PolicyConstraints_Id.toString(),
+ info);
+
+ if (ext == null)
+ return "";
+
+ int num = ext.getInhibitPolicyMapping();
+
+ return "" + num;
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_CRITICAL),
+ getConfig(CONFIG_REQ_EXPLICIT_POLICY),
+ getConfig(CONFIG_INHIBIT_POLICY_MAPPING)
+ };
+
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_POLICY_CONSTRAINTS_EXT", params);
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ PolicyConstraintsExtension ext = createExtension();
+
+ if (ext == null)
+ return;
+ addExtension(PKIXExtensions.PolicyConstraints_Id.toString(),
+ ext, info);
+ }
+
+ public PolicyConstraintsExtension createExtension() {
+ PolicyConstraintsExtension ext = null;
+
+ try {
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+
+ int reqNum = -1;
+ int inhibitNum = -1;
+ String req = getConfig(CONFIG_REQ_EXPLICIT_POLICY);
+
+ if (req != null && req.length() > 0) {
+ reqNum = Integer.parseInt(req);
+ }
+ String inhibit = getConfig(CONFIG_INHIBIT_POLICY_MAPPING);
+
+ if (inhibit != null && inhibit.length() > 0) {
+ inhibitNum = Integer.parseInt(inhibit);
+ }
+ ext = new PolicyConstraintsExtension(critical, reqNum, inhibitNum);
+ } catch (Exception e) {
+ CMS.debug("PolicyConstraintsExtDefault: createExtension " +
+ e.toString());
+ }
+
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/PolicyMappingsExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/PolicyMappingsExtDefault.java
new file mode 100644
index 000000000..56d67a93e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/PolicyMappingsExtDefault.java
@@ -0,0 +1,419 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.CertificatePolicyId;
+import netscape.security.x509.CertificatePolicyMap;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.PolicyMappingsExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a policy mappings extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class PolicyMappingsExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "policyMappingsCritical";
+ public static final String CONFIG_NUM_POLICY_MAPPINGS = "policyMappingsNum";
+ public static final String CONFIG_ISSUER_DOMAIN_POLICY = "policyMappingsIssuerDomainPolicy_";
+ public static final String CONFIG_SUBJECT_DOMAIN_POLICY = "policyMappingsSubjectDomainPolicy_";
+ public static final String CONFIG_ENABLE = "policyMappingsEnable_";
+
+ public static final String VAL_CRITICAL = "policyMappingsCritical";
+ public static final String VAL_DOMAINS = "policyMappingsDomains";
+
+ private static final String ISSUER_POLICY_ID = "Issuer Policy Id";
+ private static final String SUBJECT_POLICY_ID = "Subject Policy Id";
+ private static final String POLICY_ID_ENABLE = "Enable";
+
+ private static final int DEF_NUM_MAPPINGS = 1;
+ private static final int MAX_NUM_MAPPINGS = 100;
+
+ public PolicyMappingsExtDefault() {
+ super();
+ }
+
+ protected int getNumMappings() {
+ int num = DEF_NUM_MAPPINGS;
+ String numMappings = getConfig(CONFIG_NUM_POLICY_MAPPINGS);
+
+ if (numMappings != null) {
+ try {
+ num = Integer.parseInt(numMappings);
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ }
+ return num;
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ refreshConfigAndValueNames();
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ int num = 0;
+ if (name.equals(CONFIG_NUM_POLICY_MAPPINGS)) {
+ try {
+ num = Integer.parseInt(value);
+
+ if (num >= MAX_NUM_MAPPINGS || num < 0) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_POLICY_MAPPINGS));
+ }
+
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_POLICY_MAPPINGS));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public Enumeration<String> getConfigNames() {
+ refreshConfigAndValueNames();
+ return super.getConfigNames();
+ }
+
+ protected void refreshConfigAndValueNames() {
+ super.refreshConfigAndValueNames();
+
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_DOMAINS);
+
+ addConfigName(CONFIG_CRITICAL);
+ int num = getNumMappings();
+
+ addConfigName(CONFIG_NUM_POLICY_MAPPINGS);
+ for (int i = 0; i < num; i++) {
+ addConfigName(CONFIG_ISSUER_DOMAIN_POLICY + i);
+ addConfigName(CONFIG_SUBJECT_DOMAIN_POLICY + i);
+ addConfigName(CONFIG_ENABLE + i);
+ }
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.startsWith(CONFIG_ISSUER_DOMAIN_POLICY)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_ISSUER_DOMAIN_POLICY"));
+ } else if (name.startsWith(CONFIG_SUBJECT_DOMAIN_POLICY)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SUBJECT_DOMAIN_POLICY"));
+ } else if (name.startsWith(CONFIG_ENABLE)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_ENABLE"));
+ } else if (name.startsWith(CONFIG_NUM_POLICY_MAPPINGS)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "1",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NUM_POLICY_MAPPINGS"));
+ }
+
+ return null;
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_DOMAINS)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_DOMAINS"));
+ }
+ return null;
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ PolicyMappingsExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (PolicyMappingsExtension)
+ getExtension(PKIXExtensions.PolicyMappings_Id.toString(),
+ info);
+
+ if (ext == null) {
+ populate(null, info);
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (PolicyMappingsExtension)
+ getExtension(PKIXExtensions.PolicyMappings_Id.toString(),
+ info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ if (ext == null) {
+ return;
+ }
+ ext.setCritical(val);
+ } else if (name.equals(VAL_DOMAINS)) {
+ ext = (PolicyMappingsExtension)
+ getExtension(PKIXExtensions.PolicyMappings_Id.toString(),
+ info);
+
+ if (ext == null) {
+ return;
+ }
+ Vector<NameValuePairs> v = parseRecords(value);
+ int size = v.size();
+
+ String issuerPolicyId = null;
+ String subjectPolicyId = null;
+ String enable = null;
+ Vector<CertificatePolicyMap> policyMaps = new Vector<CertificatePolicyMap>();
+
+ for (int i = 0; i < size; i++) {
+ NameValuePairs nvps = v.elementAt(i);
+
+ for (String name1 : nvps.keySet()) {
+
+ if (name1.equals(ISSUER_POLICY_ID)) {
+ issuerPolicyId = nvps.get(name1);
+ } else if (name1.equals(SUBJECT_POLICY_ID)) {
+ subjectPolicyId = nvps.get(name1);
+ } else if (name1.equals(POLICY_ID_ENABLE)) {
+ enable = nvps.get(name1);
+ }
+ }
+
+ if (enable != null && enable.equals("true")) {
+ if (issuerPolicyId == null ||
+ issuerPolicyId.length() == 0 || subjectPolicyId == null ||
+ subjectPolicyId.length() == 0)
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_PROFILE_POLICY_ID_NOT_FOUND"));
+ CertificatePolicyMap map = new CertificatePolicyMap(
+ new CertificatePolicyId(new ObjectIdentifier(issuerPolicyId)),
+ new CertificatePolicyId(new ObjectIdentifier(subjectPolicyId)));
+
+ policyMaps.addElement(map);
+ }
+ }
+ ext.set(PolicyMappingsExtension.MAP, policyMaps);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ replaceExtension(PKIXExtensions.PolicyMappings_Id.toString(),
+ ext, info);
+ } catch (EProfileException e) {
+ CMS.debug("PolicyMappingsExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } catch (IOException e) {
+ CMS.debug("PolicyMappingsExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ PolicyMappingsExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (PolicyMappingsExtension)
+ getExtension(PKIXExtensions.PolicyMappings_Id.toString(),
+ info);
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (PolicyMappingsExtension)
+ getExtension(PKIXExtensions.PolicyMappings_Id.toString(),
+ info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_DOMAINS)) {
+ ext = (PolicyMappingsExtension)
+ getExtension(PKIXExtensions.PolicyMappings_Id.toString(),
+ info);
+
+ if (ext == null)
+ return "";
+
+ int num_mappings = getNumMappings();
+
+ Enumeration<CertificatePolicyMap> maps = ext.getMappings();
+
+ Vector<NameValuePairs> recs = new Vector<NameValuePairs>();
+
+ for (int i = 0; i < num_mappings; i++) {
+ NameValuePairs pairs = new NameValuePairs();
+
+ if (maps.hasMoreElements()) {
+ CertificatePolicyMap map = maps.nextElement();
+
+ CertificatePolicyId i1 = map.getIssuerIdentifier();
+ CertificatePolicyId s1 = map.getSubjectIdentifier();
+
+ pairs.put(ISSUER_POLICY_ID, i1.getIdentifier().toString());
+ pairs.put(SUBJECT_POLICY_ID, s1.getIdentifier().toString());
+ pairs.put(POLICY_ID_ENABLE, "true");
+ } else {
+ pairs.put(ISSUER_POLICY_ID, "");
+ pairs.put(SUBJECT_POLICY_ID, "");
+ pairs.put(POLICY_ID_ENABLE, "false");
+
+ }
+ recs.addElement(pairs);
+ }
+
+ return buildRecords(recs);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ StringBuffer sb = new StringBuffer();
+ int num = getNumMappings();
+
+ for (int i = 0; i < num; i++) {
+ sb.append("Record #");
+ sb.append(i);
+ sb.append("{");
+ sb.append(ISSUER_POLICY_ID + ":");
+ sb.append(getConfig(CONFIG_ISSUER_DOMAIN_POLICY + i));
+ sb.append(",");
+ sb.append(SUBJECT_POLICY_ID + ":");
+ sb.append(getConfig(CONFIG_SUBJECT_DOMAIN_POLICY + i));
+ sb.append(",");
+ sb.append(POLICY_ID_ENABLE + ":");
+ sb.append(getConfig(CONFIG_ENABLE + i));
+ sb.append("}");
+ }
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_DEF_POLICY_MAPPINGS_EXT",
+ getConfig(CONFIG_CRITICAL), sb.toString());
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ PolicyMappingsExtension ext = createExtension();
+
+ if (ext == null)
+ return;
+ addExtension(PKIXExtensions.PolicyMappings_Id.toString(),
+ ext, info);
+ }
+
+ public PolicyMappingsExtension createExtension() {
+ PolicyMappingsExtension ext = null;
+
+ try {
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+ Vector<CertificatePolicyMap> policyMaps = new Vector<CertificatePolicyMap>();
+ int num = getNumMappings();
+
+ for (int i = 0; i < num; i++) {
+ String enable = getConfig(CONFIG_ENABLE + i);
+
+ if (enable != null && enable.equals("true")) {
+ String issuerID = getConfig(CONFIG_ISSUER_DOMAIN_POLICY + i);
+
+ if (issuerID == null || issuerID.length() == 0) {
+ return null;
+ }
+
+ String subjectID = getConfig(CONFIG_SUBJECT_DOMAIN_POLICY + i);
+
+ if (subjectID == null || subjectID.length() == 0) {
+ return null;
+ }
+
+ CertificatePolicyMap map = new CertificatePolicyMap(
+ new CertificatePolicyId(new ObjectIdentifier(issuerID)),
+ new CertificatePolicyId(new ObjectIdentifier(subjectID)));
+
+ policyMaps.addElement(map);
+ }
+ }
+
+ ext = new PolicyMappingsExtension(critical, policyMaps);
+ } catch (Exception e) {
+ CMS.debug("PolicyMappingsExtDefault: createExtension " +
+ e.toString());
+ }
+
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/PrivateKeyUsagePeriodExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/PrivateKeyUsagePeriodExtDefault.java
new file mode 100644
index 000000000..6532a13f0
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/PrivateKeyUsagePeriodExtDefault.java
@@ -0,0 +1,316 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.PrivateKeyUsageExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a Private Key Usage Period extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class PrivateKeyUsagePeriodExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "puCritical";
+ public static final String CONFIG_START_TIME = "puStartTime";
+ public static final String CONFIG_DURATION = "puDurationInDays"; // in days
+
+ public static final String VAL_CRITICAL = "puCritical";
+ public static final String VAL_NOT_BEFORE = "puNotBefore";
+ public static final String VAL_NOT_AFTER = "puNotAfter";
+
+ public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
+ private long mDefault = 86400000; // 1 days
+
+ public PrivateKeyUsagePeriodExtDefault() {
+ super();
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_NOT_BEFORE);
+ addValueName(VAL_NOT_AFTER);
+
+ addConfigName(CONFIG_CRITICAL);
+ addConfigName(CONFIG_START_TIME);
+ addConfigName(CONFIG_DURATION);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(CONFIG_START_TIME)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ "0",
+ CMS.getUserMessage(locale, "CMS_PROFILE_VALIDITY_START_TIME"));
+ } else if (name.equals(CONFIG_DURATION)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ "365",
+ CMS.getUserMessage(locale, "CMS_PROFILE_VALIDITY_RANGE"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ if (name.equals(CONFIG_START_TIME)) {
+ try {
+ Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_START_TIME));
+ }
+ } else if (name.equals(CONFIG_DURATION)) {
+ try {
+ Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_DURATION));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_NOT_BEFORE)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ "0",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NOT_BEFORE"));
+ } else if (name.equals(VAL_NOT_AFTER)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ "30",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NOT_AFTER"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ PrivateKeyUsageExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ObjectIdentifier oid = PKIXExtensions.PrivateKeyUsage_Id;
+
+ ext = (PrivateKeyUsageExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ populate(null, info);
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+
+ ext = (PrivateKeyUsageExtension)
+ getExtension(oid.toString(), info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ if (ext == null) {
+ return;
+ }
+ ext.setCritical(val);
+ } else if (name.equals(VAL_NOT_BEFORE)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+ ParsePosition pos = new ParsePosition(0);
+ Date date = formatter.parse(value, pos);
+
+ ext = (PrivateKeyUsageExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ return;
+ }
+ ext.set(PrivateKeyUsageExtension.NOT_BEFORE, date);
+ } else if (name.equals(VAL_NOT_AFTER)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+ ParsePosition pos = new ParsePosition(0);
+ Date date = formatter.parse(value, pos);
+
+ ext = (PrivateKeyUsageExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ return;
+ }
+ ext.set(PrivateKeyUsageExtension.NOT_AFTER, date);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ replaceExtension(ext.getExtensionId().toString(), ext, info);
+ } catch (EProfileException e) {
+ CMS.debug("PrivateKeyUsageExtension: setValue " + e.toString());
+ } catch (Exception e) {
+ CMS.debug("PrivateKeyUsageExtension: setValue " + e.toString());
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ PrivateKeyUsageExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ObjectIdentifier oid = PKIXExtensions.PrivateKeyUsage_Id;
+
+ ext = (PrivateKeyUsageExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+
+ ext = (PrivateKeyUsageExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_NOT_BEFORE)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+
+ ext = (PrivateKeyUsageExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null)
+ return "";
+
+ return formatter.format(ext.getNotBefore());
+ } else if (name.equals(VAL_NOT_AFTER)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+
+ ext = (PrivateKeyUsageExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null)
+ return "";
+
+ return formatter.format(ext.getNotAfter());
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ String params[] = {
+ getConfig(CONFIG_CRITICAL),
+ getConfig(CONFIG_START_TIME),
+ getConfig(CONFIG_DURATION)
+ };
+
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_PRIVATE_KEY_EXT", params);
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ PrivateKeyUsageExtension ext = createExtension();
+
+ addExtension(ext.getExtensionId().toString(), ext, info);
+ }
+
+ public PrivateKeyUsageExtension createExtension() {
+ PrivateKeyUsageExtension ext = null;
+
+ try {
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+
+ // always + 60 seconds
+ String startTimeStr = getConfig(CONFIG_START_TIME);
+
+ if (startTimeStr == null || startTimeStr.equals("")) {
+ startTimeStr = "60";
+ }
+ int startTime = Integer.parseInt(startTimeStr);
+ Date notBefore = new Date(CMS.getCurrentDate().getTime() +
+ (1000 * startTime));
+ long notAfterVal = 0;
+
+ notAfterVal = notBefore.getTime() +
+ (mDefault * Integer.parseInt(getConfig(CONFIG_DURATION)));
+ Date notAfter = new Date(notAfterVal);
+
+ ext = new PrivateKeyUsageExtension(notBefore, notAfter);
+ ext.setCritical(critical);
+ } catch (Exception e) {
+ CMS.debug("PrivateKeyUsagePeriodExt: createExtension " +
+ e.toString());
+ }
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/RandomizedValidityDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/RandomizedValidityDefault.java
new file mode 100644
index 000000000..b3b16448d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/RandomizedValidityDefault.java
@@ -0,0 +1,354 @@
+// --- 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 com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Random;
+
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a server-side configurable validity
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class RandomizedValidityDefault extends EnrollDefault {
+ public static final String CONFIG_RANGE = "range";
+ public static final String CONFIG_START_TIME = "startTime";
+ public static final String CONFIG_NOT_BEFORE_RANDOM_BITS = "notBeforeRandomBits";
+ public static final String CONFIG_NOT_AFTER_RANDOM_BITS = "startTimeRandomBits";
+
+ public static final String VAL_NOT_BEFORE = "notBefore";
+ public static final String VAL_NOT_AFTER = "notAfter";
+
+ public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
+
+ private long mDayInMS = 86400000; // 1 days
+ private Random mRandom = null;
+
+ public RandomizedValidityDefault() {
+ super();
+ addConfigName(CONFIG_RANGE);
+ addConfigName(CONFIG_START_TIME);
+ addConfigName(CONFIG_NOT_BEFORE_RANDOM_BITS);
+ addConfigName(CONFIG_NOT_AFTER_RANDOM_BITS);
+ addValueName(VAL_NOT_BEFORE);
+ addValueName(VAL_NOT_AFTER);
+ mRandom = new Random();
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ if (name.equals(CONFIG_RANGE)) {
+ try {
+ Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_RANGE));
+ }
+ } else if (name.equals(CONFIG_START_TIME)) {
+ try {
+ Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_START_TIME));
+ }
+ } else if (name.equals(CONFIG_NOT_BEFORE_RANDOM_BITS)) {
+ try {
+ Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NOT_BEFORE_RANDOM_BITS));
+ }
+ } else if (name.equals(CONFIG_NOT_AFTER_RANDOM_BITS)) {
+ try {
+ Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NOT_AFTER_RANDOM_BITS));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_RANGE)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ "365", /* 365 days */
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_VALIDITY_RANGE"));
+ } else if (name.equals(CONFIG_START_TIME)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ "0", /* 0 seconds */
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_VALIDITY_START_TIME"));
+ } else if (name.equals(CONFIG_NOT_BEFORE_RANDOM_BITS)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ "10", /* 10 bits */
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_NOT_BEFORE_RANDOM_BITS"));
+ } else if (name.equals(CONFIG_NOT_AFTER_RANDOM_BITS)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ "10", /* 10 bits */
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_NOT_AFTER_RANDOM_BITS"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_NOT_BEFORE)) {
+ return new Descriptor(IDescriptor.STRING, null, null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NOT_BEFORE"));
+ } else if (name.equals(VAL_NOT_AFTER)) {
+ return new Descriptor(IDescriptor.STRING, null, null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NOT_AFTER"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (value == null || value.equals("")) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NOT_BEFORE)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+ ParsePosition pos = new ParsePosition(0);
+ Date date = formatter.parse(value, pos);
+ CertificateValidity validity = null;
+
+ try {
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ validity.set(CertificateValidity.NOT_BEFORE,
+ date);
+ } catch (Exception e) {
+ CMS.debug("RandomizedValidityDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else if (name.equals(VAL_NOT_AFTER)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+ ParsePosition pos = new ParsePosition(0);
+ Date date = formatter.parse(value, pos);
+ CertificateValidity validity = null;
+
+ try {
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ validity.set(CertificateValidity.NOT_AFTER,
+ date);
+ } catch (Exception e) {
+ CMS.debug("RandomizedValidityDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+
+ if (name == null)
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+
+ if (name.equals(VAL_NOT_BEFORE)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+ CertificateValidity validity = null;
+
+ try {
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ return formatter.format((Date)
+ validity.get(CertificateValidity.NOT_BEFORE));
+ } catch (Exception e) {
+ CMS.debug("RandomizedValidityDefault: getValue " + e.toString());
+ }
+ throw new EPropertyException("Invalid valie");
+ } else if (name.equals(VAL_NOT_AFTER)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+ CertificateValidity validity = null;
+
+ try {
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ return formatter.format((Date)
+ validity.get(CertificateValidity.NOT_AFTER));
+ } catch (Exception e) {
+ CMS.debug("RandomizedValidityDefault: getValue " + e.toString());
+ }
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_VALIDITY",
+ getConfig(CONFIG_RANGE));
+ }
+
+ private int randomSecs(int numBits) {
+ int maxSecs = 0;
+ int secs = 0;
+
+ if (numBits > Integer.SIZE) {
+ numBits = Integer.SIZE;
+ CMS.debug("RandomizedValidityDefault randomSecs "+
+ "- number of bits limited to "+numBits);
+ }
+ if (numBits > 0) {
+ maxSecs = (1 << numBits) - 1;
+ int numBytes = (numBits+7)/8;
+ int byteSecs = (1 << (numBytes * 8)) - 1;
+ byte[] randomBits = new byte[numBytes];
+ mRandom.nextBytes(randomBits);
+ for (int i = 0; i < numBytes; i++) {
+ secs <<= 8;
+ secs |= (int)(randomBits[i]) & 0xFF;
+ }
+ secs &= maxSecs;
+ }
+ CMS.debug("RandomizedValidityDefault randomSecs numBits="+numBits+
+ " secs="+secs+" maxSecs="+maxSecs);
+ return secs;
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ // always + 60 seconds
+ String startTimeStr = getConfig(CONFIG_START_TIME);
+ try {
+ startTimeStr = mapPattern(request, startTimeStr);
+ } catch (IOException e) {
+ CMS.debug("RandomizedValidityDefault: populate " + e.toString());
+ }
+
+ if (startTimeStr == null || startTimeStr.equals("")) {
+ startTimeStr = "60";
+ }
+ int startTime = Integer.parseInt(startTimeStr);
+
+ String notBeforeRandomBitsStr = getConfig(CONFIG_NOT_BEFORE_RANDOM_BITS);
+ if (notBeforeRandomBitsStr == null || notBeforeRandomBitsStr.length() == 0) {
+ notBeforeRandomBitsStr = "0";
+ }
+ int notBeforeRandomBits = Integer.parseInt(notBeforeRandomBitsStr);
+
+ String notAfterRandomBitsStr = getConfig(CONFIG_NOT_AFTER_RANDOM_BITS);
+ if (notAfterRandomBitsStr == null || notAfterRandomBitsStr.length() == 0) {
+ notAfterRandomBitsStr = "0";
+ }
+ int notAfterRandomBits = Integer.parseInt(notAfterRandomBitsStr);
+ int randomSeconds = randomSecs(notBeforeRandomBits);
+ long currentTime = CMS.getCurrentDate().getTime();
+ Date notBefore = new Date(currentTime + (1000 * startTime));
+ CMS.debug("RandomizedValidityDefault populate notBefore = "+notBefore);
+ Date notBeforeRandomized = new Date(currentTime + (1000 * (startTime - randomSeconds)));
+ CMS.debug("RandomizedValidityDefault populate notBeforeRandomized = "+notBeforeRandomized);
+ int maxNotBeforeSecs = (1 << notBeforeRandomBits) - 1;
+ Date notBeforeMax = new Date(currentTime + (1000 * (startTime - maxNotBeforeSecs)));
+ CMS.debug("RandomizedValidityDefault populate notBeforeMax = "+notBeforeMax);
+
+ long notAfterValue = 0;
+ long notAfterValueRandomized = 0;
+ long notAfterValueMax = 0;
+
+ try {
+ String rangeStr = getConfig(CONFIG_RANGE);
+ rangeStr = mapPattern(request, rangeStr);
+ notAfterValue = notBefore.getTime() + (mDayInMS * Integer.parseInt(rangeStr));
+ notAfterValueRandomized = notBefore.getTime() + (mDayInMS * Integer.parseInt(rangeStr)) +
+ (1000 * randomSecs(notAfterRandomBits));
+ int maxNotAfterSecs = (1 << notAfterRandomBits) - 1;
+ notAfterValueMax = notBefore.getTime() + (mDayInMS * Integer.parseInt(rangeStr)) +
+ (1000 * maxNotAfterSecs);
+ } catch (Exception e) {
+ // configured value is not correct
+ CMS.debug("RandomizedValidityDefault: populate " + e.toString());
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_INVALID_PROPERTY", CONFIG_RANGE));
+ }
+ Date notAfter = new Date(notAfterValue);
+ CMS.debug("RandomizedValidityDefault populate notAfter = "+notAfter);
+ Date notAfterRandomized = new Date(notAfterValueRandomized);
+ CMS.debug("RandomizedValidityDefault populate notAfterRandomized = "+notAfterRandomized);
+ Date notAfterMax = new Date(notAfterValueMax);
+ CMS.debug("RandomizedValidityDefault populate notAfterMax = "+notAfterMax);
+ CertificateValidity validity =
+ new CertificateValidity(notBeforeRandomized, notAfterRandomized);
+
+ try {
+ info.set(X509CertInfo.VALIDITY, validity);
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("RandomizedValidityDefault: populate " + e.toString());
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_INVALID_PROPERTY", X509CertInfo.VALIDITY));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/SigningAlgDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/SigningAlgDefault.java
new file mode 100644
index 000000000..81ad58c73
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/SigningAlgDefault.java
@@ -0,0 +1,182 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.util.Locale;
+
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a signing algorithm
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class SigningAlgDefault extends EnrollDefault {
+
+ public static final String CONFIG_ALGORITHM = "signingAlg";
+
+ public static final String VAL_ALGORITHM = "signingAlg";
+ public static final String DEF_CONFIG_ALGORITHMS =
+ "-,MD5withRSA,MD2withRSA,SHA1withRSA,SHA256withRSA,SHA512withRSA";
+
+ public SigningAlgDefault() {
+ super();
+ addConfigName(CONFIG_ALGORITHM);
+ addValueName(VAL_ALGORITHM);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_ALGORITHM)) {
+ return new Descriptor(IDescriptor.CHOICE, DEF_CONFIG_ALGORITHMS,
+ "SHA256withRSA",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SIGNING_ALGORITHM"));
+ } else {
+ return null;
+ }
+ }
+
+ public String getSigningAlg() {
+ String signingAlg = getConfig(CONFIG_ALGORITHM);
+ // if specified, use the specified one. Otherwise, pick
+ // the best selection for the user
+ if (signingAlg == null || signingAlg.equals("") ||
+ signingAlg.equals("-")) {
+ // best pick for the user
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ return ca.getDefaultAlgorithm();
+ } else {
+ return signingAlg;
+ }
+ }
+
+ public String getDefSigningAlgorithms() {
+ StringBuffer allowed = new StringBuffer();
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ String algos[] = ca.getCASigningAlgorithms();
+ for (int i = 0; i < algos.length; i++) {
+ if (allowed.length() == 0) {
+ allowed.append(algos[i]);
+ } else {
+ allowed.append(",");
+ allowed.append(algos[i]);
+ }
+ }
+ return allowed.toString();
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_ALGORITHM)) {
+ String allowed = getDefSigningAlgorithms();
+ return new Descriptor(IDescriptor.CHOICE,
+ allowed, null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SIGNING_ALGORITHM"));
+ }
+ return null;
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_ALGORITHM)) {
+ try {
+ info.set(X509CertInfo.ALGORITHM_ID,
+ new CertificateAlgorithmId(
+ AlgorithmId.get(value)));
+ } catch (Exception e) {
+ CMS.debug("SigningAlgDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+
+ if (name == null)
+ throw new EPropertyException("Invalid name " + name);
+
+ if (name.equals(VAL_ALGORITHM)) {
+ CertificateAlgorithmId algId = null;
+
+ try {
+ algId = (CertificateAlgorithmId)
+ info.get(X509CertInfo.ALGORITHM_ID);
+ AlgorithmId id = (AlgorithmId)
+ algId.get(CertificateAlgorithmId.ALGORITHM);
+
+ return id.toString();
+ } catch (Exception e) {
+ CMS.debug("SigningAlgDefault: getValue " + e.toString());
+ }
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_SIGNING_ALGORITHM",
+ getSigningAlg());
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ try {
+ info.set(X509CertInfo.ALGORITHM_ID,
+ new CertificateAlgorithmId(AlgorithmId.get(getSigningAlg())));
+ } catch (Exception e) {
+ CMS.debug("SigningAlgDefault: populate " + e.toString());
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/SubjectAltNameExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/SubjectAltNameExtDefault.java
new file mode 100644
index 000000000..61c200a96
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/SubjectAltNameExtDefault.java
@@ -0,0 +1,544 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.UUID;
+
+import netscape.security.x509.GeneralNameInterface;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.SubjectAlternativeNameExtension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IAttrSet;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.pattern.Pattern;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a subject alternative name extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class SubjectAltNameExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "subjAltNameExtCritical";
+ public static final String CONFIG_NUM_GNS = "subjAltNameNumGNs";
+ public static final String CONFIG_GN_ENABLE = "subjAltExtGNEnable_";
+ public static final String CONFIG_TYPE = "subjAltExtType_";
+ public static final String CONFIG_PATTERN = "subjAltExtPattern_";
+ public static final String CONFIG_SOURCE = "subjAltExtSource_";
+ public static final String CONFIG_SOURCE_UUID4 = "UUID4";
+
+ public static final String CONFIG_OLD_TYPE = "subjAltExtType";
+ public static final String CONFIG_OLD_PATTERN = "subjAltExtPattern";
+
+ public static final String VAL_CRITICAL = "subjAltNameExtCritical";
+ public static final String VAL_GENERAL_NAMES = "subjAltNames";
+
+ private static final String GN_ENABLE = "Enable";
+ private static final String GN_TYPE = "Pattern Type";
+ private static final String GN_PATTERN = "Pattern";
+
+ private static final int DEF_NUM_GN = 1;
+ private static final int MAX_NUM_GN = 100;
+
+ public SubjectAltNameExtDefault() {
+ super();
+ }
+
+ protected int getNumGNs() {
+ int num = DEF_NUM_GN;
+ String numGNs = getConfig(CONFIG_NUM_GNS);
+
+ if (numGNs != null) {
+ try {
+ num = Integer.parseInt(numGNs);
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ }
+
+ if (num >= MAX_NUM_GN)
+ num = DEF_NUM_GN;
+ return num;
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+
+ super.init(profile, config);
+ refreshConfigAndValueNames();
+ // migrate old parameters to new parameters
+ String old_type = null;
+ String old_pattern = null;
+ IConfigStore paramConfig = config.getSubStore("params");
+ try {
+ if (paramConfig != null) {
+ old_type = paramConfig.getString(CONFIG_OLD_TYPE);
+ }
+ } catch (EBaseException e) {
+ // nothing to do here
+ }
+ CMS.debug("SubjectAltNameExtDefault: Upgrading old_type=" +
+ old_type);
+ try {
+ if (paramConfig != null) {
+ old_pattern = paramConfig.getString(CONFIG_OLD_PATTERN);
+ }
+ } catch (EBaseException e) {
+ // nothing to do here
+ }
+ CMS.debug("SubjectAltNameExtDefault: Upgrading old_pattern=" +
+ old_pattern);
+ if (old_type != null && old_pattern != null) {
+ CMS.debug("SubjectAltNameExtDefault: Upgrading");
+ try {
+ paramConfig.putString(CONFIG_NUM_GNS, "1");
+ paramConfig.putString(CONFIG_GN_ENABLE + "0", "true");
+ paramConfig.putString(CONFIG_TYPE + "0", old_type);
+ paramConfig.putString(CONFIG_PATTERN + "0", old_pattern);
+ paramConfig.remove(CONFIG_OLD_TYPE);
+ paramConfig.remove(CONFIG_OLD_PATTERN);
+ profile.getConfigStore().commit(true);
+ } catch (Exception e) {
+ CMS.debug("SubjectAltNameExtDefault: Failed to upgrade " + e);
+ }
+ }
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ int num = 0;
+ if (name.equals(CONFIG_NUM_GNS)) {
+ try {
+ num = Integer.parseInt(value);
+
+ if (num >= MAX_NUM_GN || num < 0) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_GNS));
+ }
+
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_GNS));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public Enumeration<String> getConfigNames() {
+ refreshConfigAndValueNames();
+ return super.getConfigNames();
+ }
+
+ protected void refreshConfigAndValueNames() {
+ super.refreshConfigAndValueNames();
+
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_GENERAL_NAMES);
+
+ addConfigName(CONFIG_CRITICAL);
+ int num = getNumGNs();
+ addConfigName(CONFIG_NUM_GNS);
+ for (int i = 0; i < num; i++) {
+ addConfigName(CONFIG_TYPE + i);
+ addConfigName(CONFIG_PATTERN + i);
+ addConfigName(CONFIG_GN_ENABLE + i);
+ }
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.startsWith(CONFIG_TYPE)) {
+ return new Descriptor(IDescriptor.CHOICE,
+ "RFC822Name,DNSName,DirectoryName,EDIPartyName,URIName,IPAddress,OIDName,OtherName",
+ "RFC822Name",
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_SUBJECT_ALT_NAME_TYPE"));
+ } else if (name.startsWith(CONFIG_PATTERN)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_SUBJECT_ALT_NAME_PATTERN"));
+ } else if (name.startsWith(CONFIG_GN_ENABLE)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_GN_ENABLE"));
+ } else if (name.startsWith(CONFIG_NUM_GNS)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "1",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NUM_GNS"));
+ }
+
+ return null;
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_GENERAL_NAMES)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_GENERAL_NAMES"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ SubjectAlternativeNameExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext =
+ (SubjectAlternativeNameExtension)
+ getExtension(PKIXExtensions.SubjectAlternativeName_Id.toString(), info);
+
+ if (ext == null) {
+ populate(null, info);
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext =
+ (SubjectAlternativeNameExtension)
+ getExtension(PKIXExtensions.SubjectAlternativeName_Id.toString(), info);
+
+ if (ext == null) {
+ // it is ok, the extension is never populated or delted
+ return;
+ }
+ boolean critical = Boolean.valueOf(value).booleanValue();
+
+ ext.setCritical(critical);
+ } else if (name.equals(VAL_GENERAL_NAMES)) {
+ ext =
+ (SubjectAlternativeNameExtension)
+ getExtension(PKIXExtensions.SubjectAlternativeName_Id.toString(), info);
+
+ if (ext == null) {
+ // it is ok, the extension is never populated or delted
+ return;
+ }
+ if (value.equals("")) {
+ // if value is empty, do not add this extension
+ deleteExtension(PKIXExtensions.SubjectAlternativeName_Id.toString(), info);
+ return;
+ }
+ GeneralNames gn = new GeneralNames();
+ StringTokenizer st = new StringTokenizer(value, "\r\n");
+
+ while (st.hasMoreTokens()) {
+ String gname = st.nextToken();
+ CMS.debug("SubjectAltNameExtDefault: setValue GN:" + gname);
+
+ if (!isGeneralNameValid(gname)) {
+ continue;
+ }
+ GeneralNameInterface n = parseGeneralName(gname);
+ if (n != null) {
+ gn.addElement(n);
+ }
+ }
+ if (gn.size() == 0) {
+ CMS.debug("GN size is zero");
+ deleteExtension(PKIXExtensions.SubjectAlternativeName_Id.toString(), info);
+ return;
+ } else {
+ CMS.debug("GN size is non zero (" + gn.size() + ")");
+ ext.set(SubjectAlternativeNameExtension.SUBJECT_NAME, gn);
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ replaceExtension(
+ PKIXExtensions.SubjectAlternativeName_Id.toString(),
+ ext, info);
+ } catch (IOException e) {
+ CMS.debug("SubjectAltNameExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } catch (EProfileException e) {
+ CMS.debug("SubjectAltNameExtDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ try {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ SubjectAlternativeNameExtension ext =
+ (SubjectAlternativeNameExtension)
+ getExtension(PKIXExtensions.SubjectAlternativeName_Id.toString(), info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext =
+ (SubjectAlternativeNameExtension)
+ getExtension(PKIXExtensions.SubjectAlternativeName_Id.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_GENERAL_NAMES)) {
+ ext =
+ (SubjectAlternativeNameExtension)
+ getExtension(PKIXExtensions.SubjectAlternativeName_Id.toString(), info);
+ if (ext == null) {
+ return null;
+ }
+
+ GeneralNames names = (GeneralNames)
+ ext.get(SubjectAlternativeNameExtension.SUBJECT_NAME);
+ StringBuffer sb = new StringBuffer();
+ Enumeration<GeneralNameInterface> e = names.elements();
+
+ while (e.hasMoreElements()) {
+ GeneralNameInterface gn = e.nextElement();
+
+ if (!sb.toString().equals("")) {
+ sb.append("\r\n");
+ }
+ sb.append(toGeneralNameString(gn));
+ CMS.debug("SubjectAltNameExtDefault: getValue append GN:" + toGeneralNameString(gn));
+ }
+ return sb.toString();
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } catch (IOException e) {
+ CMS.debug("SubjectAltNameExtDefault: getValue " +
+ e.toString());
+ }
+ return null;
+ }
+
+ /*
+ * returns text that goes into description for this extension on
+ * a profile
+ */
+ public String getText(Locale locale) {
+ StringBuffer sb = new StringBuffer();
+ int num = getNumGNs();
+
+ for (int i = 0; i < num; i++) {
+ sb.append("Record #");
+ sb.append(i);
+ sb.append("{");
+ sb.append(GN_PATTERN + ":");
+ sb.append(getConfig(CONFIG_PATTERN + i));
+ sb.append(",");
+ sb.append(GN_TYPE + ":");
+ sb.append(getConfig(CONFIG_TYPE + i));
+ sb.append(",");
+ sb.append(GN_ENABLE + ":");
+ sb.append(getConfig(CONFIG_GN_ENABLE + i));
+ sb.append("}");
+ }
+ ;
+
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_SUBJECT_ALT_NAME_EXT", getConfig(CONFIG_CRITICAL),
+ sb.toString());
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ SubjectAlternativeNameExtension ext = null;
+
+ try {
+ /* read from config file*/
+ ext = createExtension(request);
+
+ } catch (IOException e) {
+ CMS.debug("SubjectAltNameExtDefault: populate " + e.toString());
+ }
+ if (ext != null) {
+ addExtension(PKIXExtensions.SubjectAlternativeName_Id.toString(),
+ ext, info);
+ } else {
+ CMS.debug("SubjectAltNameExtDefault: populate sees no extension. get out");
+ }
+ }
+
+ public SubjectAlternativeNameExtension createExtension(IRequest request)
+ throws IOException {
+ SubjectAlternativeNameExtension ext = null;
+ int num = getNumGNs();
+
+ boolean critical = Boolean.valueOf(
+ getConfig(CONFIG_CRITICAL)).booleanValue();
+
+ GeneralNames gn = new GeneralNames();
+ int count = 0; // # of actual gnames
+ for (int i = 0; i < num; i++) {
+ String enable = getConfig(CONFIG_GN_ENABLE + i);
+ if (enable != null && enable.equals("true")) {
+ CMS.debug("SubjectAltNameExtDefault: createExtension i=" + i);
+
+ String pattern = getConfig(CONFIG_PATTERN + i);
+ if (pattern == null || pattern.equals("")) {
+ pattern = " ";
+ }
+
+ if (!pattern.equals("")) {
+ String gname = "";
+
+ // cfu - see if this is server-generated (e.g. UUID4)
+ // to use this feature, use $server.source$ in pattern
+ String source = getConfig(CONFIG_SOURCE + i);
+ String type = getConfig(CONFIG_TYPE + i);
+ if ((source != null) && (!source.equals(""))) {
+ if (type.equalsIgnoreCase("OtherName")) {
+ CMS.debug("SubjectAlternativeNameExtension: using " +
+ source + " as gn");
+ if (source.equals(CONFIG_SOURCE_UUID4)) {
+ UUID randUUID = UUID.randomUUID();
+ // call the mapPattern that does server-side gen
+ // request is not used, but needed for the substitute
+ // function
+ if (request != null) {
+ gname = mapPattern(randUUID.toString(), request, pattern);
+ }
+ } else { //expand more server-gen types here
+ CMS.debug("SubjectAltNameExtDefault: createExtension - unsupported server-generated type: "
+ + source + ". Supported: UUID4");
+ continue;
+ }
+ } else {
+ CMS.debug("SubjectAltNameExtDefault: createExtension - source is only supported for subjAltExtType OtherName");
+ continue;
+ }
+ } else {
+ if (request != null) {
+ gname = mapPattern(request, pattern);
+ }
+ }
+
+ if (gname.equals("")) {
+ CMS.debug("gname is empty, not added");
+ continue;
+ }
+ CMS.debug("SubjectAltNameExtDefault: createExtension got gname=" + gname);
+
+ GeneralNameInterface n = parseGeneralName(type + ":" + gname);
+
+ CMS.debug("adding gname: " + gname);
+ if (n != null) {
+ CMS.debug("SubjectAlternativeNameExtension: n not null");
+ gn.addElement(n);
+ count++;
+ } else {
+ CMS.debug("SubjectAlternativeNameExtension: n null");
+ }
+ }
+ }
+ } //for
+
+ if (count != 0) {
+ try {
+ ext = new SubjectAlternativeNameExtension();
+ } catch (Exception e) {
+ CMS.debug(e.toString());
+ throw new IOException(e.toString());
+ }
+ ext.set(SubjectAlternativeNameExtension.SUBJECT_NAME, gn);
+ ext.setCritical(critical);
+ } else {
+ CMS.debug("count is 0");
+ }
+ return ext;
+ }
+
+ public String mapPattern(IRequest request, String pattern)
+ throws IOException {
+ Pattern p = new Pattern(pattern);
+ IAttrSet attrSet = null;
+ if (request != null) {
+ attrSet = request.asIAttrSet();
+ }
+ return p.substitute("request", attrSet);
+ }
+
+ // for server-side generated values
+ public String mapPattern(String val, IRequest request, String pattern)
+ throws IOException {
+ Pattern p = new Pattern(pattern);
+ IAttrSet attrSet = null;
+ if (request != null) {
+ attrSet = request.asIAttrSet();
+ }
+ try {
+ attrSet.set("source", val);
+ } catch (Exception e) {
+ CMS.debug("SubjectAlternativeNameExtension: mapPattern source " + e.toString());
+ }
+
+ return p.substitute("server", attrSet);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/SubjectDirAttributesExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/SubjectDirAttributesExtDefault.java
new file mode 100644
index 000000000..a60721733
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/SubjectDirAttributesExtDefault.java
@@ -0,0 +1,527 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.security.util.DerValue;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AVAValueConverter;
+import netscape.security.x509.Attribute;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.SubjectDirAttributesExtension;
+import netscape.security.x509.X500NameAttrMap;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a subject directory attributes extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class SubjectDirAttributesExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "subjDirAttrsCritical";
+ public static final String CONFIG_NUM_ATTRS = "subjDirAttrsNum";
+ public static final String CONFIG_ATTR_NAME = "subjDirAttrName_";
+ public static final String CONFIG_PATTERN = "subjDirAttrPattern_";
+ public static final String CONFIG_ENABLE = "subjDirAttrEnable_";
+
+ public static final String VAL_CRITICAL = "subjDirAttrCritical";
+ public static final String VAL_ATTR = "subjDirAttrValue";
+
+ private static final int DEF_NUM_ATTRS = 1;
+ private static final int MAX_NUM_ATTRS = 100;
+ private static final String ENABLE = "Enable";
+ private static final String ATTR_NAME = "Attribute Name";
+ private static final String ATTR_VALUE = "Attribute Value";
+
+ public SubjectDirAttributesExtDefault() {
+ super();
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ refreshConfigAndValueNames();
+ }
+
+ protected int getNumAttrs() {
+ int num = DEF_NUM_ATTRS;
+ String val = getConfig(CONFIG_NUM_ATTRS);
+
+ if (val != null) {
+ try {
+ num = Integer.parseInt(val);
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ }
+
+ if (num >= MAX_NUM_ATTRS)
+ num = DEF_NUM_ATTRS;
+
+ return num;
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ int num = 0;
+ if (name.equals(DEF_NUM_ATTRS)) {
+ try {
+ num = Integer.parseInt(value);
+
+ if (num >= MAX_NUM_ATTRS || num < 0) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_ATTRS));
+ }
+
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_ATTRS));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public Enumeration<String> getConfigNames() {
+ refreshConfigAndValueNames();
+ return super.getConfigNames();
+ }
+
+ protected void refreshConfigAndValueNames() {
+ super.refreshConfigAndValueNames();
+
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_ATTR);
+
+ addConfigName(CONFIG_CRITICAL);
+ int num = getNumAttrs();
+ addConfigName(CONFIG_NUM_ATTRS);
+ for (int i = 0; i < num; i++) {
+ addConfigName(CONFIG_ATTR_NAME + i);
+ addConfigName(CONFIG_PATTERN + i);
+ addConfigName(CONFIG_ENABLE + i);
+ }
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.startsWith(CONFIG_ATTR_NAME)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NUM_ATTRS"));
+ } else if (name.startsWith(CONFIG_ATTR_NAME)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_ATTR_NAME"));
+ } else if (name.startsWith(CONFIG_PATTERN)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_ATTR_VALUE"));
+ } else if (name.startsWith(CONFIG_ENABLE)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_ENABLE"));
+ } else if (name.startsWith(CONFIG_NUM_ATTRS)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "1",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NUM_ATTRS"));
+ }
+
+ return null;
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_ATTR)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SUBJDIR_ATTRS"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ SubjectDirAttributesExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (SubjectDirAttributesExtension)
+ getExtension(PKIXExtensions.SubjectDirectoryAttributes_Id.toString(),
+ info);
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (SubjectDirAttributesExtension)
+ getExtension(PKIXExtensions.SubjectDirectoryAttributes_Id.toString(),
+ info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ if (ext == null) {
+ return;
+ }
+ ext.setCritical(val);
+ } else if (name.equals(VAL_ATTR)) {
+ ext = (SubjectDirAttributesExtension)
+ getExtension(PKIXExtensions.SubjectDirectoryAttributes_Id.toString(),
+ info);
+
+ if (ext == null) {
+ return;
+ }
+ Vector<NameValuePairs> v = parseRecords(value);
+ int size = v.size();
+
+ boolean critical = ext.isCritical();
+
+ Vector<Attribute> attrV = new Vector<Attribute>();
+ for (int i = 0; i < size; i++) {
+ NameValuePairs nvps = v.elementAt(i);
+ String attrName = null;
+ String attrValue = null;
+ String enable = "false";
+
+ for (String name1 : nvps.keySet()) {
+
+ if (name1.equals(ATTR_NAME)) {
+ attrName = nvps.get(name1);
+ } else if (name1.equals(ATTR_VALUE)) {
+ attrValue = nvps.get(name1);
+ } else if (name1.equals(ENABLE)) {
+ enable = nvps.get(name1);
+ }
+ }
+
+ if (enable.equals("true")) {
+ AttributeConfig attributeConfig =
+ new AttributeConfig(attrName, attrValue);
+ Attribute attr = attributeConfig.mAttribute;
+ if (attr != null)
+ attrV.addElement(attr);
+ }
+ }
+
+ if (attrV.size() > 0) {
+ Attribute[] attrList = new Attribute[attrV.size()];
+ attrV.copyInto(attrList);
+ ext = new SubjectDirAttributesExtension(attrList, critical);
+ } else
+ return;
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ replaceExtension(PKIXExtensions.SubjectDirectoryAttributes_Id.toString(),
+ ext, info);
+ } catch (EProfileException e) {
+ CMS.debug("SubjectDirAttributesExtDefault: setValue " +
+ e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } catch (IOException e) {
+ CMS.debug("SubjectDirAttributesExtDefault: setValue " +
+ e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ SubjectDirAttributesExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ ext = (SubjectDirAttributesExtension)
+ getExtension(PKIXExtensions.SubjectDirectoryAttributes_Id.toString(),
+ info);
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext = (SubjectDirAttributesExtension)
+ getExtension(PKIXExtensions.SubjectDirectoryAttributes_Id.toString(),
+ info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_ATTR)) {
+ ext = (SubjectDirAttributesExtension)
+ getExtension(PKIXExtensions.SubjectDirectoryAttributes_Id.toString(),
+ info);
+
+ if (ext == null)
+ return "";
+
+ X500NameAttrMap map = X500NameAttrMap.getDefault();
+
+ Vector<NameValuePairs> recs = new Vector<NameValuePairs>();
+ int num = getNumAttrs();
+ Enumeration<Attribute> e = ext.getAttributesList();
+ CMS.debug("SubjectDirAttributesExtDefault: getValue: attributesList=" + e);
+ int i = 0;
+
+ while (e.hasMoreElements()) {
+ NameValuePairs pairs = new NameValuePairs();
+ pairs.put(ENABLE, "true");
+ Attribute attr = e.nextElement();
+ CMS.debug("SubjectDirAttributesExtDefault: getValue: attribute=" + attr);
+ ObjectIdentifier oid = attr.getOid();
+ CMS.debug("SubjectDirAttributesExtDefault: getValue: oid=" + oid);
+
+ String vv = map.getName(oid);
+
+ if (vv != null)
+ pairs.put(ATTR_NAME, vv);
+ else
+ pairs.put(ATTR_NAME, oid.toString());
+ Enumeration<String> v = attr.getValues();
+
+ // just support single value for now
+ StringBuffer ss = new StringBuffer();
+ while (v.hasMoreElements()) {
+ if (ss.length() == 0)
+ ss.append(v.nextElement());
+ else {
+ ss.append(",");
+ ss.append(v.nextElement());
+ }
+ }
+
+ pairs.put(ATTR_VALUE, ss.toString());
+ recs.addElement(pairs);
+ i++;
+ }
+
+ for (; i < num; i++) {
+ NameValuePairs pairs = new NameValuePairs();
+ pairs.put(ENABLE, "false");
+ pairs.put(ATTR_NAME, "GENERATIONQUALIFIER");
+ pairs.put(ATTR_VALUE, "");
+ recs.addElement(pairs);
+ }
+
+ return buildRecords(recs);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ StringBuffer sb = new StringBuffer();
+ int num = getNumAttrs();
+
+ for (int i = 0; i < num; i++) {
+ sb.append("Record #");
+ sb.append(i);
+ sb.append("{");
+ sb.append(ATTR_NAME + ":");
+ sb.append(getConfig(CONFIG_ATTR_NAME + i));
+ sb.append(",");
+ sb.append(ATTR_VALUE + ":");
+ sb.append(getConfig(CONFIG_PATTERN + i));
+ sb.append(",");
+ sb.append(ENABLE + ":");
+ sb.append(getConfig(CONFIG_ENABLE + i));
+ sb.append("}");
+ }
+ return CMS.getUserMessage(locale,
+ "CMS_PROFILE_DEF_SUBJECT_DIR_ATTR_EXT",
+ getConfig(CONFIG_CRITICAL),
+ sb.toString());
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ SubjectDirAttributesExtension ext = createExtension(request);
+
+ if (ext == null)
+ return;
+
+ addExtension(PKIXExtensions.SubjectDirectoryAttributes_Id.toString(),
+ ext, info);
+ }
+
+ public SubjectDirAttributesExtension createExtension(IRequest request)
+ throws EProfileException {
+ SubjectDirAttributesExtension ext = null;
+ int num = 0;
+
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+
+ num = getNumAttrs();
+
+ AttributeConfig attributeConfig = null;
+ Vector<Attribute> attrs = new Vector<Attribute>();
+ for (int i = 0; i < num; i++) {
+ String enable = getConfig(CONFIG_ENABLE + i);
+ if (enable != null && enable.equals("true")) {
+ String attrName = getConfig(CONFIG_ATTR_NAME + i);
+ String pattern = getConfig(CONFIG_PATTERN + i);
+ if (pattern == null || pattern.equals(""))
+ pattern = " ";
+
+ //check pattern syntax
+ int startpos = pattern.indexOf("$");
+ int lastpos = pattern.lastIndexOf("$");
+ String attrValue = pattern;
+ if (!pattern.equals("") && startpos != -1 &&
+ startpos == 0 && lastpos != -1 &&
+ lastpos == (pattern.length() - 1)) {
+ if (request != null) {
+ try {
+ attrValue = mapPattern(request, pattern);
+ } catch (IOException e) {
+ throw new EProfileException(e.toString());
+ }
+ }
+ }
+ try {
+ attributeConfig = new AttributeConfig(attrName, attrValue);
+ } catch (EPropertyException e) {
+ throw new EProfileException(e.toString());
+ }
+ Attribute attr = attributeConfig.mAttribute;
+ if (attr != null) {
+ attrs.addElement(attr);
+ }
+ }
+ }
+
+ if (attrs.size() > 0) {
+ Attribute[] attrList = new Attribute[attrs.size()];
+ attrs.copyInto(attrList);
+ try {
+ ext =
+ new SubjectDirAttributesExtension(attrList, critical);
+ } catch (IOException e) {
+ throw new EProfileException(e.toString());
+ }
+ }
+
+ return ext;
+ }
+}
+
+class AttributeConfig {
+
+ protected ObjectIdentifier mAttributeOID = null;
+ protected Attribute mAttribute = null;
+
+ public AttributeConfig(String attrName, String attrValue)
+ throws EPropertyException {
+ X500NameAttrMap map = X500NameAttrMap.getDefault();
+
+ if (attrName == null || attrName.length() == 0) {
+ throw new EPropertyException(
+ CMS.getUserMessage("CMS_PROFILE_SUBJDIR_EMPTY_ATTRNAME", attrName));
+ }
+
+ if (attrValue == null || attrValue.length() == 0) {
+ throw new EPropertyException(
+ CMS.getUserMessage("CMS_PROFILE_SUBJDIR_EMPTY_ATTRVAL", attrValue));
+ }
+
+ try {
+ mAttributeOID = new ObjectIdentifier(attrName);
+ } catch (Exception e) {
+ CMS.debug("SubjectDirAttributesExtDefault: invalid OID syntax: " + attrName);
+ }
+
+ if (mAttributeOID == null) {
+ mAttributeOID = map.getOid(attrName);
+ if (mAttributeOID == null)
+ throw new EPropertyException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", attrName));
+ try {
+ checkValue(mAttributeOID, attrValue);
+ } catch (IOException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_BASE_INVALID_ATTR_VALUE", e.getMessage()));
+ }
+ }
+
+ try {
+ mAttribute = new Attribute(mAttributeOID,
+ str2MultiValues(attrValue));
+ } catch (IOException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_BASE_INVALID_ATTR_VALUE", e.getMessage()));
+ }
+ }
+
+ private static void checkValue(ObjectIdentifier oid, String val)
+ throws IOException {
+ AVAValueConverter c = X500NameAttrMap.getDefault().getValueConverter(oid);
+
+ @SuppressWarnings("unused")
+ DerValue derval = c.getValue(val); // check for errors
+ return;
+ }
+
+ private Vector<String> str2MultiValues(String attrValue) {
+ StringTokenizer tokenizer = new StringTokenizer(attrValue, ",");
+ Vector<String> v = new Vector<String>();
+ while (tokenizer.hasMoreTokens()) {
+ v.addElement(tokenizer.nextToken());
+ }
+
+ return v;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/SubjectInfoAccessExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/SubjectInfoAccessExtDefault.java
new file mode 100644
index 000000000..d850147a4
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/SubjectInfoAccessExtDefault.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.extensions.AccessDescription;
+import netscape.security.extensions.SubjectInfoAccessExtension;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNameInterface;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates Subject Info Access extension.
+ *
+ * @version $Revision$, $Date$
+ */
+public class SubjectInfoAccessExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "subjInfoAccessCritical";
+ public static final String CONFIG_NUM_ADS = "subjInfoAccessNumADs";
+ public static final String CONFIG_AD_ENABLE = "subjInfoAccessADEnable_";
+ public static final String CONFIG_AD_METHOD = "subjInfoAccessADMethod_";
+ public static final String CONFIG_AD_LOCATIONTYPE = "subjInfoAccessADLocationType_";
+ public static final String CONFIG_AD_LOCATION = "subjInfoAccessADLocation_";
+
+ public static final String VAL_CRITICAL = "subjInfoAccessCritical";
+ public static final String VAL_GENERAL_NAMES = "subjInfoAccessGeneralNames";
+
+ private static final String AD_METHOD = "Method";
+ private static final String AD_LOCATION_TYPE = "Location Type";
+ private static final String AD_LOCATION = "Location";
+ private static final String AD_ENABLE = "Enable";
+
+ private static final int DEF_NUM_AD = 1;
+ private static final int MAX_NUM_AD = 100;
+
+ public SubjectInfoAccessExtDefault() {
+ super();
+ }
+
+ protected int getNumAds() {
+ int num = DEF_NUM_AD;
+ String numAds = getConfig(CONFIG_NUM_ADS);
+
+ if (numAds != null) {
+ try {
+ num = Integer.parseInt(numAds);
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ }
+ if (num >= MAX_NUM_AD)
+ num = DEF_NUM_AD;
+
+ return num;
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ refreshConfigAndValueNames();
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ int num = 0;
+ if (name.equals(CONFIG_NUM_ADS)) {
+ try {
+ num = Integer.parseInt(value);
+
+ if (num >= MAX_NUM_AD || num < 0) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_ADS));
+ }
+
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_NUM_ADS));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public Enumeration<String> getConfigNames() {
+ refreshConfigAndValueNames();
+ return super.getConfigNames();
+ }
+
+ protected void refreshConfigAndValueNames() {
+ super.refreshConfigAndValueNames();
+
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_GENERAL_NAMES);
+
+ // register configuration names bases on num ads
+ addConfigName(CONFIG_CRITICAL);
+ int num = getNumAds();
+ addConfigName(CONFIG_NUM_ADS);
+ for (int i = 0; i < num; i++) {
+ addConfigName(CONFIG_AD_METHOD + i);
+ addConfigName(CONFIG_AD_LOCATIONTYPE + i);
+ addConfigName(CONFIG_AD_LOCATION + i);
+ addConfigName(CONFIG_AD_ENABLE + i);
+ }
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.startsWith(CONFIG_AD_METHOD)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_AD_METHOD"));
+ } else if (name.startsWith(CONFIG_AD_LOCATIONTYPE)) {
+ return new Descriptor(IDescriptor.CHOICE,
+ "RFC822Name,DNSName,DirectoryName,EDIPartyName,URIName,IPAddress,OIDName",
+ "URIName",
+ CMS.getUserMessage(locale, "CMS_PROFILE_AD_LOCATIONTYPE"));
+ } else if (name.startsWith(CONFIG_AD_LOCATION)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_AD_LOCATION"));
+ } else if (name.startsWith(CONFIG_AD_ENABLE)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_AD_ENABLE"));
+ } else if (name.startsWith(CONFIG_NUM_ADS)) {
+ return new Descriptor(IDescriptor.INTEGER, null,
+ "1",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NUM_ADS"));
+ }
+ return null;
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_GENERAL_NAMES)) {
+ return new Descriptor(IDescriptor.STRING_LIST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_GENERAL_NAMES"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ try {
+ SubjectInfoAccessExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ SubjectInfoAccessExtension a = new SubjectInfoAccessExtension(false);
+ ObjectIdentifier oid = a.getExtensionId();
+
+ ext = (SubjectInfoAccessExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ populate(null, info);
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+
+ ext = (SubjectInfoAccessExtension)
+ getExtension(oid.toString(), info);
+ boolean val = Boolean.valueOf(value).booleanValue();
+
+ if (ext == null) {
+ return;
+ }
+ ext.setCritical(val);
+ } else if (name.equals(VAL_GENERAL_NAMES)) {
+
+ ext = (SubjectInfoAccessExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ return;
+ }
+ boolean critical = ext.isCritical();
+
+ Vector<NameValuePairs> v = parseRecords(value);
+ int size = v.size();
+
+ ext = new SubjectInfoAccessExtension(critical);
+ String method = null;
+ String locationType = null;
+ String location = null;
+ String enable = null;
+
+ for (int i = 0; i < size; i++) {
+ NameValuePairs nvps = v.elementAt(i);
+
+ for (String name1 : nvps.keySet()) {
+
+ if (name1.equals(AD_METHOD)) {
+ method = nvps.get(name1);
+ } else if (name1.equals(AD_LOCATION_TYPE)) {
+ locationType = nvps.get(name1);
+ } else if (name1.equals(AD_LOCATION)) {
+ location = nvps.get(name1);
+ } else if (name1.equals(AD_ENABLE)) {
+ enable = nvps.get(name1);
+ }
+ }
+
+ if (enable != null && enable.equals("true")) {
+ GeneralName gn = null;
+
+ if (locationType != null || location != null) {
+ GeneralNameInterface interface1 = parseGeneralName(locationType + ":" + location);
+ if (interface1 == null)
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", locationType));
+ gn = new GeneralName(interface1);
+ }
+
+ if (method != null) {
+ try {
+ ext.addAccessDescription(new ObjectIdentifier(method), gn);
+ } catch (NumberFormatException ee) {
+ CMS.debug("SubjectInfoAccessExtDefault: " + ee.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_PROFILE_DEF_SIA_OID", method));
+ }
+ }
+ }
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ replaceExtension(ext.getExtensionId().toString(), ext, info);
+ } catch (IOException e) {
+ CMS.debug("SubjectInfoAccessExtDefault: " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } catch (EProfileException e) {
+ CMS.debug("SubjectInfoAccessExtDefault: " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ SubjectInfoAccessExtension ext = null;
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ SubjectInfoAccessExtension a = new SubjectInfoAccessExtension(false);
+ ObjectIdentifier oid = a.getExtensionId();
+
+ ext = (SubjectInfoAccessExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ CMS.debug("SubjectInfoAccessExtDefault: getValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+ if (name.equals(VAL_CRITICAL)) {
+
+ ext = (SubjectInfoAccessExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_GENERAL_NAMES)) {
+
+ ext = (SubjectInfoAccessExtension)
+ getExtension(oid.toString(), info);
+
+ if (ext == null)
+ return "";
+
+ int num = getNumAds();
+
+ CMS.debug("SubjectInfoAccess num=" + num);
+ Vector<NameValuePairs> recs = new Vector<NameValuePairs>();
+
+ for (int i = 0; i < num; i++) {
+ NameValuePairs np = new NameValuePairs();
+ AccessDescription des = null;
+
+ if (i < ext.numberOfAccessDescription()) {
+ des = ext.getAccessDescription(i);
+ }
+ if (des == null) {
+ np.put(AD_METHOD, "");
+ np.put(AD_LOCATION_TYPE, "");
+ np.put(AD_LOCATION, "");
+ np.put(AD_ENABLE, "false");
+ } else {
+ ObjectIdentifier methodOid = des.getMethod();
+ GeneralName gn = des.getLocation();
+
+ np.put(AD_METHOD, methodOid.toString());
+ np.put(AD_LOCATION_TYPE, getGeneralNameType(gn));
+ np.put(AD_LOCATION, getGeneralNameValue(gn));
+ np.put(AD_ENABLE, "true");
+ }
+ recs.addElement(np);
+ }
+
+ return buildRecords(recs);
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ StringBuffer ads = new StringBuffer();
+ int num = getNumAds();
+
+ for (int i = 0; i < num; i++) {
+ ads.append("Record #");
+ ads.append(i);
+ ads.append("{");
+ ads.append(AD_METHOD + ":");
+ ads.append(getConfig(CONFIG_AD_METHOD + i));
+ ads.append(",");
+ ads.append(AD_LOCATION_TYPE + ":");
+ ads.append(getConfig(CONFIG_AD_LOCATIONTYPE + i));
+ ads.append(",");
+ ads.append(AD_LOCATION + ":");
+ ads.append(getConfig(CONFIG_AD_LOCATION + i));
+ ads.append(",");
+ ads.append(AD_ENABLE + ":");
+ ads.append(getConfig(CONFIG_AD_ENABLE + i));
+ ads.append("}");
+ }
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_SIA_TEXT",
+ getConfig(CONFIG_CRITICAL), ads.toString());
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ SubjectInfoAccessExtension ext = createExtension();
+
+ addExtension(ext.getExtensionId().toString(), ext, info);
+ }
+
+ public SubjectInfoAccessExtension createExtension() {
+ SubjectInfoAccessExtension ext = null;
+ int num = getNumAds();
+
+ try {
+ boolean critical = getConfigBoolean(CONFIG_CRITICAL);
+
+ ext = new SubjectInfoAccessExtension(critical);
+ for (int i = 0; i < num; i++) {
+ String enable = getConfig(CONFIG_AD_ENABLE + i);
+ if (enable != null && enable.equals("true")) {
+ CMS.debug("SubjectInfoAccess: createExtension i=" + i);
+ String method = getConfig(CONFIG_AD_METHOD + i);
+ String locationType = getConfig(CONFIG_AD_LOCATIONTYPE + i);
+ if (locationType == null || locationType.length() == 0)
+ locationType = "URIName";
+ String location = getConfig(CONFIG_AD_LOCATION + i);
+
+ if (location == null || location.equals("")) {
+ if (method.equals("1.3.6.1.5.5.7.48.1")) {
+ String hostname = CMS.getEENonSSLHost();
+ String port = CMS.getEENonSSLPort();
+ if (hostname != null && port != null)
+ location = "http://" + hostname + ":" + port + "/ocsp";
+ }
+ }
+
+ String s = locationType + ":" + location;
+ GeneralNameInterface gn = parseGeneralName(s);
+ if (gn != null) {
+ ext.addAccessDescription(new ObjectIdentifier(method),
+ new GeneralName(gn));
+ }
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("SubjectInfoAccessExtDefault: createExtension " +
+ e.toString());
+ }
+
+ return ext;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/SubjectKeyIdentifierExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/SubjectKeyIdentifierExtDefault.java
new file mode 100644
index 000000000..a8f6a7415
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/SubjectKeyIdentifierExtDefault.java
@@ -0,0 +1,217 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.KeyIdentifier;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.SubjectKeyIdentifierExtension;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a subject key identifier extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class SubjectKeyIdentifierExtDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "critical";
+
+ public static final String VAL_CRITICAL = "critical";
+ public static final String VAL_KEY_ID = "keyid";
+
+ public SubjectKeyIdentifierExtDefault() {
+ super();
+ addValueName(VAL_CRITICAL);
+ addValueName(VAL_KEY_ID);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CRITICAL)) {
+ return new Descriptor(IDescriptor.STRING,
+ IDescriptor.READONLY,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_CRITICAL"));
+ } else if (name.equals(VAL_KEY_ID)) {
+ return new Descriptor(IDescriptor.STRING,
+ IDescriptor.READONLY,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_ID"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_CRITICAL)) {
+ // read-only; do nothing
+ } else if (name.equals(VAL_KEY_ID)) {
+ // read-only; do nothing
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ SubjectKeyIdentifierExtension ext =
+ (SubjectKeyIdentifierExtension) getExtension(
+ PKIXExtensions.SubjectKey_Id.toString(), info);
+
+ if (ext == null) {
+ try {
+ populate(null, info);
+
+ } catch (EProfileException e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ if (name.equals(VAL_CRITICAL)) {
+ ext =
+ (SubjectKeyIdentifierExtension) getExtension(
+ PKIXExtensions.SubjectKey_Id.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ if (ext.isCritical()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (name.equals(VAL_KEY_ID)) {
+ ext =
+ (SubjectKeyIdentifierExtension) getExtension(
+ PKIXExtensions.SubjectKey_Id.toString(), info);
+
+ if (ext == null) {
+ return null;
+ }
+ KeyIdentifier kid = null;
+
+ try {
+ kid = (KeyIdentifier)
+ ext.get(SubjectKeyIdentifierExtension.KEY_ID);
+ } catch (IOException e) {
+ CMS.debug("SubjectKeyIdentifierExtDefault::getValue() - " +
+ "kid is null!");
+ throw new EPropertyException(CMS.getUserMessage(locale,
+ "CMS_INVALID_PROPERTY",
+ name));
+ }
+ return toHexString(kid.getIdentifier());
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_SUBJECT_KEY_ID_EXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ SubjectKeyIdentifierExtension ext = createExtension(info);
+
+ addExtension(PKIXExtensions.SubjectKey_Id.toString(), ext, info);
+ }
+
+ public SubjectKeyIdentifierExtension createExtension(X509CertInfo info) {
+ KeyIdentifier kid = getKeyIdentifier(info);
+
+ if (kid == null) {
+ CMS.debug("SubjectKeyIdentifierExtDefault: KeyIdentifier not found");
+ return null;
+ }
+ SubjectKeyIdentifierExtension ext = null;
+
+ boolean critical = Boolean.valueOf(getConfig(CONFIG_CRITICAL)).booleanValue();
+
+ try {
+ ext = new SubjectKeyIdentifierExtension(critical, kid.getIdentifier());
+ } catch (IOException e) {
+ CMS.debug("SubjectKeyIdentifierExtDefault: createExtension " +
+ e.toString());
+ //
+ }
+ return ext;
+ }
+
+ public KeyIdentifier getKeyIdentifier(X509CertInfo info) {
+ try {
+ CertificateX509Key infokey = (CertificateX509Key)
+ info.get(X509CertInfo.KEY);
+ X509Key key = (X509Key) infokey.get(CertificateX509Key.KEY);
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+
+ md.update(key.getKey());
+ byte[] hash = md.digest();
+
+ return new KeyIdentifier(hash);
+ } catch (NoSuchAlgorithmException e) {
+ CMS.debug("SubjectKeyIdentifierExtDefault: getKeyIdentifier " +
+ e.toString());
+ } catch (Exception e) {
+ CMS.debug("SubjectKeyIdentifierExtDefault: getKeyIdentifier " +
+ e.toString());
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/SubjectNameDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/SubjectNameDefault.java
new file mode 100644
index 000000000..31aee6dd6
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/SubjectNameDefault.java
@@ -0,0 +1,184 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates server-side configurable subject name
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class SubjectNameDefault extends EnrollDefault {
+
+ public static final String CONFIG_NAME = "name";
+
+ public static final String VAL_NAME = "name";
+
+ public SubjectNameDefault() {
+ super();
+ addValueName(VAL_NAME);
+ addConfigName(CONFIG_NAME);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_NAME)) {
+ return new Descriptor(IDescriptor.STRING,
+ null, "CN=TEST", CMS.getUserMessage(locale,
+ "CMS_PROFILE_SUBJECT_NAME"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_NAME)) {
+ return new Descriptor(IDescriptor.STRING, null, null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_SUBJECT_NAME"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NAME)) {
+ X500Name x500name = null;
+
+ try {
+ x500name = new X500Name(value);
+ if (x500name != null) {
+ CMS.debug("SubjectNameDefault: setValue x500name=" + x500name.toString());
+ }
+ } catch (IOException e) {
+ CMS.debug("SubjectNameDefault: setValue " + e.toString());
+ // failed to build x500 name
+ }
+ CMS.debug("SubjectNameDefault: setValue name=" + x500name.toString());
+ try {
+ info.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(x500name));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("SubjectNameDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NAME)) {
+ CertificateSubjectName sn = null;
+
+ try {
+ CMS.debug("SubjectNameDefault: getValue info=" + info);
+ sn = (CertificateSubjectName)
+ info.get(X509CertInfo.SUBJECT);
+ CMS.debug("SubjectNameDefault: getValue name=" + sn);
+ return sn.toString();
+ } catch (Exception e) {
+ // nothing
+ CMS.debug("SubjectNameDefault: getValue " + e.toString());
+
+ }
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_SUBJECT_NAME",
+ getConfig(CONFIG_NAME));
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ X500Name name = null;
+
+ String subjectName = null;
+
+ try {
+ subjectName = mapPattern(request, getConfig(CONFIG_NAME));
+ } catch (IOException e) {
+ CMS.debug("SubjectNameDefault: mapPattern " + e.toString());
+ }
+
+ CMS.debug("subjectName=" + subjectName);
+ if (subjectName == null || subjectName.equals(""))
+ return;
+ try {
+ name = new X500Name(subjectName);
+ } catch (IOException e) {
+ // failed to build x500 name
+ CMS.debug("SubjectNameDefault: populate " + e.toString());
+ }
+ if (name == null) {
+ // failed to build x500 name
+ }
+ try {
+ info.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(name));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("SubjectNameDefault: populate " + e.toString());
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/UserExtensionDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/UserExtensionDefault.java
new file mode 100644
index 000000000..a78992a74
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/UserExtensionDefault.java
@@ -0,0 +1,136 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.util.Locale;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.Extension;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a user-supplied extension
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class UserExtensionDefault extends EnrollExtDefault {
+
+ public static final String CONFIG_CRITICAL = "userExtCritical";
+ public static final String CONFIG_OID = "userExtOID";
+
+ public static final String VAL_CRITICAL = "userExtCritical";
+ public static final String VAL_OID = "userExtOID";
+
+ public UserExtensionDefault() {
+ super();
+ addValueName(VAL_OID);
+ addConfigName(CONFIG_OID);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_OID)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ "Comment Here...",
+ CMS.getUserMessage(locale, "CMS_PROFILE_OID"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_OID)) {
+ return new Descriptor(IDescriptor.STRING,
+ IDescriptor.READONLY,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_OID"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ // Nothing to do for read-only values
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_OID)) {
+ Extension ext = getExtension(getConfig(CONFIG_OID), info);
+
+ if (ext == null) {
+ // do something here
+ return "";
+ }
+ return ext.getExtensionId().toString();
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_USER_EXT", getConfig(CONFIG_OID));
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ CertificateExtensions inExts = null;
+ String oid = getConfig(CONFIG_OID);
+
+ inExts = request.getExtDataInCertExts(IEnrollProfile.REQUEST_EXTENSIONS);
+ if (inExts == null)
+ return;
+ Extension ext = getExtension(getConfig(CONFIG_OID), inExts);
+ if (ext == null) {
+ CMS.debug("UserExtensionDefault: no user ext supplied for " + oid);
+ return;
+ }
+
+ // user supplied the ext that's allowed, replace the def set by system
+ deleteExtension(oid, info);
+ CMS.debug("UserExtensionDefault: using user supplied ext for " + oid);
+ addExtension(oid, ext, info);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/UserKeyDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/UserKeyDefault.java
new file mode 100644
index 000000000..4531e0fe5
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/UserKeyDefault.java
@@ -0,0 +1,241 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.ByteArrayInputStream;
+import java.math.BigInteger;
+import java.security.interfaces.DSAParams;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.provider.DSAPublicKey;
+import netscape.security.provider.RSAPublicKey;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a user supplied key
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class UserKeyDefault extends EnrollDefault {
+
+ public static final String VAL_KEY = "KEY";
+ public static final String VAL_LEN = "LEN";
+ public static final String VAL_TYPE = "TYPE";
+
+ public UserKeyDefault() {
+ super();
+ addValueName(VAL_TYPE);
+ addValueName(VAL_LEN);
+ addValueName(VAL_KEY);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_KEY)) {
+ return new Descriptor(IDescriptor.STRING,
+ IDescriptor.READONLY,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY"));
+ } else if (name.equals(VAL_LEN)) {
+ return new Descriptor(IDescriptor.STRING,
+ IDescriptor.READONLY,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_LEN"));
+ } else if (name.equals(VAL_TYPE)) {
+ return new Descriptor(IDescriptor.STRING,
+ IDescriptor.READONLY,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_TYPE"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ // this default rule is readonly
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_KEY)) {
+ CertificateX509Key ck = null;
+
+ try {
+ ck = (CertificateX509Key)
+ info.get(X509CertInfo.KEY);
+ } catch (Exception e) {
+ // nothing
+ }
+ X509Key k = null;
+
+ try {
+ k = (X509Key)
+ ck.get(CertificateX509Key.KEY);
+ } catch (Exception e) {
+ // nothing
+ }
+ if (k == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_PROFILE_KEY_NOT_FOUND"));
+ }
+ return toHexString(k.getKey());
+ } else if (name.equals(VAL_LEN)) {
+ CertificateX509Key ck = null;
+
+ try {
+ ck = (CertificateX509Key)
+ info.get(X509CertInfo.KEY);
+ } catch (Exception e) {
+ // nothing
+ }
+ X509Key k = null;
+
+ try {
+ k = (X509Key)
+ ck.get(CertificateX509Key.KEY);
+ } catch (Exception e) {
+ // nothing
+ }
+ if (k == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_PROFILE_KEY_NOT_FOUND"));
+ }
+ try {
+ if (k.getAlgorithm().equals("RSA")) {
+ return Integer.toString(getRSAKeyLen(k));
+ } else if (k.getAlgorithm().equals("EC")) {
+ Vector<String> vect = CryptoUtil.getECKeyCurve(k);
+ if (vect != null)
+ return vect.toString();
+ else
+ return null;
+ } else {
+ return Integer.toString(getDSAKeyLen(k));
+ }
+ } catch (Exception e) {
+ CMS.debug("UserKeyDefault: getValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else if (name.equals(VAL_TYPE)) {
+ CertificateX509Key ck = null;
+
+ try {
+ ck = (CertificateX509Key)
+ info.get(X509CertInfo.KEY);
+ } catch (Exception e) {
+ // nothing
+ }
+ X509Key k = null;
+
+ try {
+ k = (X509Key)
+ ck.get(CertificateX509Key.KEY);
+ } catch (Exception e) {
+ // nothing
+ }
+ if (k == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_PROFILE_KEY_NOT_FOUND"));
+ }
+ return k.getAlgorithm() + " - " +
+ k.getAlgorithmId().getOID().toString();
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_USER_KEY");
+ }
+
+ public int getRSAKeyLen(X509Key key) throws Exception {
+ X509Key newkey = null;
+
+ try {
+ newkey = new X509Key(AlgorithmId.get("RSA"),
+ key.getKey());
+ } catch (Exception e) {
+ CMS.debug("UserKeyDefault: getRSAKey " + e.toString());
+ throw e;
+ }
+ RSAPublicKey rsaKey = new RSAPublicKey(newkey.getEncoded());
+
+ return rsaKey.getKeySize();
+ }
+
+ public int getDSAKeyLen(X509Key key) throws Exception {
+ // Check DSAKey parameters.
+ // size refers to the p parameter.
+ DSAPublicKey dsaKey = new DSAPublicKey(key.getEncoded());
+ DSAParams keyParams = dsaKey.getParams();
+ BigInteger p = keyParams.getP();
+ int len = p.bitLength();
+
+ return len;
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ CertificateX509Key certKey = null;
+ // authenticate the certificate key, and move
+ // the key from request into x509 certinfo
+ try {
+ byte[] certKeyData = request.getExtDataInByteArray(IEnrollProfile.REQUEST_KEY);
+ if (certKeyData != null) {
+ certKey = new CertificateX509Key(
+ new ByteArrayInputStream(certKeyData));
+ }
+ info.set(X509CertInfo.KEY, certKey);
+ } catch (Exception e) {
+ CMS.debug("UserKeyDefault: populate " + e.toString());
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/UserSigningAlgDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/UserSigningAlgDefault.java
new file mode 100644
index 000000000..7625f9a34
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/UserSigningAlgDefault.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.ByteArrayInputStream;
+import java.util.Locale;
+
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a user-supplied signing algorithm
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class UserSigningAlgDefault extends EnrollDefault {
+
+ public static final String VAL_ALG_ID = "userSigningAlgID";
+
+ public UserSigningAlgDefault() {
+ super();
+ addValueName(VAL_ALG_ID);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_ALG_ID)) {
+ return new Descriptor(IDescriptor.STRING,
+ IDescriptor.READONLY, null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_SIGNING_ALGORITHM"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ // this default rule is readonly
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_ALG_ID)) {
+ CertificateAlgorithmId algID = null;
+
+ try {
+ algID = (CertificateAlgorithmId)
+ info.get(X509CertInfo.ALGORITHM_ID);
+ AlgorithmId id = (AlgorithmId)
+ algID.get(CertificateAlgorithmId.ALGORITHM);
+
+ return id.toString();
+ } catch (Exception e) {
+ CMS.debug("UserSigningAlgDefault: setValue " + e.toString());
+ return ""; //XXX
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_USER_SIGNING_ALGORITHM");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ CertificateAlgorithmId certAlg = null;
+ // authenticate the certificate key, and move
+ // the key from request into x509 certinfo
+ try {
+ byte[] certAlgData = request.getExtDataInByteArray(
+ IEnrollProfile.REQUEST_SIGNING_ALGORITHM);
+ if (certAlgData != null) {
+ certAlg = new CertificateAlgorithmId(
+ new ByteArrayInputStream(certAlgData));
+ }
+ info.set(X509CertInfo.ALGORITHM_ID, certAlg);
+ } catch (Exception e) {
+ CMS.debug("UserSigningAlgDefault: populate " + e.toString());
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/UserSubjectNameDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/UserSubjectNameDefault.java
new file mode 100644
index 000000000..77d743334
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/UserSubjectNameDefault.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a user-supplied subject name
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class UserSubjectNameDefault extends EnrollDefault {
+
+ public static final String VAL_NAME = "name";
+
+ public UserSubjectNameDefault() {
+ super();
+ addValueName(VAL_NAME);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_NAME)) {
+ return new Descriptor(IDescriptor.STRING, null, null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SUBJECT_NAME"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NAME)) {
+ X500Name x500name = null;
+
+ try {
+ x500name = new X500Name(value);
+ } catch (IOException e) {
+ CMS.debug(e.toString());
+ // failed to build x500 name
+ }
+ CMS.debug("SubjectNameDefault: setValue name=" + x500name);
+ try {
+ info.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(x500name));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("UserSubjectNameDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NAME)) {
+ CertificateSubjectName sn = null;
+
+ try {
+ sn = (CertificateSubjectName)
+ info.get(X509CertInfo.SUBJECT);
+ return sn.toString();
+ } catch (Exception e) {
+ // nothing
+ }
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_USER_SUBJECT_NAME");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ // authenticate the subject name and populate it
+ // to the certinfo
+ try {
+ info.set(X509CertInfo.SUBJECT, request.getExtDataInCertSubjectName(
+ IEnrollProfile.REQUEST_SUBJECT_NAME));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("UserSubjectNameDefault: populate " + e.toString());
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/UserValidityDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/UserValidityDefault.java
new file mode 100644
index 000000000..8d5ca7d55
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/UserValidityDefault.java
@@ -0,0 +1,149 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.ByteArrayInputStream;
+import java.util.Date;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a user-supplied validity
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class UserValidityDefault extends EnrollDefault {
+
+ public static final String VAL_NOT_BEFORE = "userValdityNotBefore";
+ public static final String VAL_NOT_AFTER = "userValdityNotAfter";
+
+ public UserValidityDefault() {
+ super();
+ addValueName(VAL_NOT_BEFORE);
+ addValueName(VAL_NOT_AFTER);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_NOT_BEFORE)) {
+ return new Descriptor(IDescriptor.STRING,
+ IDescriptor.READONLY,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NOT_BEFORE"));
+ } else if (name.equals(VAL_NOT_AFTER)) {
+ return new Descriptor(IDescriptor.STRING,
+ IDescriptor.READONLY,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NOT_AFTER"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ // this default rule is readonly
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NOT_BEFORE)) {
+ CertificateValidity validity = null;
+
+ try {
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ Date notBefore = (Date)
+ validity.get(CertificateValidity.NOT_BEFORE);
+
+ return notBefore.toString();
+ } catch (Exception e) {
+ CMS.debug("UserValidityDefault: getValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else if (name.equals(VAL_NOT_AFTER)) {
+ try {
+ CertificateValidity validity = null;
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ Date notAfter = (Date)
+ validity.get(CertificateValidity.NOT_AFTER);
+
+ return notAfter.toString();
+ } catch (Exception e) {
+ CMS.debug("UserValidityDefault: getValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_USER_VALIDITY");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ CertificateValidity certValidity = null;
+ // authenticate the certificate key, and move
+ // the key from request into x509 certinfo
+ try {
+ byte[] certValidityData = request.getExtDataInByteArray(
+ IEnrollProfile.REQUEST_VALIDITY);
+ if (certValidityData != null) {
+ certValidity = new CertificateValidity();
+ certValidity.decode(
+ new ByteArrayInputStream(certValidityData));
+ }
+ info.set(X509CertInfo.VALIDITY, certValidity);
+ } catch (Exception e) {
+ CMS.debug("UserValidityDefault: populate " + e.toString());
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/ValidityDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/ValidityDefault.java
new file mode 100644
index 000000000..b649c7076
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/ValidityDefault.java
@@ -0,0 +1,263 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a server-side configurable validity
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ValidityDefault extends EnrollDefault {
+ public static final String CONFIG_RANGE = "range";
+ public static final String CONFIG_START_TIME = "startTime";
+
+ public static final String VAL_NOT_BEFORE = "notBefore";
+ public static final String VAL_NOT_AFTER = "notAfter";
+
+ public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
+
+ private long mDefault = 86400000; // 1 days
+
+ public ValidityDefault() {
+ super();
+ addConfigName(CONFIG_RANGE);
+ addConfigName(CONFIG_START_TIME);
+ addValueName(VAL_NOT_BEFORE);
+ addValueName(VAL_NOT_AFTER);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ if (name.equals(CONFIG_RANGE)) {
+ try {
+ Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_RANGE));
+ }
+ } else if (name.equals(CONFIG_START_TIME)) {
+ try {
+ Integer.parseInt(value);
+ } catch (Exception e) {
+ throw new EPropertyException(CMS.getUserMessage(
+ "CMS_INVALID_PROPERTY", CONFIG_START_TIME));
+ }
+ }
+ super.setConfig(name, value);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_RANGE)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ "7305",
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_VALIDITY_RANGE"));
+ } else if (name.equals(CONFIG_START_TIME)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ "60", /* 1 minute */
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_VALIDITY_START_TIME"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_NOT_BEFORE)) {
+ return new Descriptor(IDescriptor.STRING, null, null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NOT_BEFORE"));
+ } else if (name.equals(VAL_NOT_AFTER)) {
+ return new Descriptor(IDescriptor.STRING, null, null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NOT_AFTER"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (value == null || value.equals("")) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NOT_BEFORE)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+ ParsePosition pos = new ParsePosition(0);
+ Date date = formatter.parse(value, pos);
+ CertificateValidity validity = null;
+
+ try {
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ validity.set(CertificateValidity.NOT_BEFORE,
+ date);
+ } catch (Exception e) {
+ CMS.debug("ValidityDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else if (name.equals(VAL_NOT_AFTER)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+ ParsePosition pos = new ParsePosition(0);
+ Date date = formatter.parse(value, pos);
+ CertificateValidity validity = null;
+
+ try {
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ validity.set(CertificateValidity.NOT_AFTER,
+ date);
+ } catch (Exception e) {
+ CMS.debug("ValidityDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+
+ if (name == null)
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+
+ if (name.equals(VAL_NOT_BEFORE)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+ CertificateValidity validity = null;
+
+ try {
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ return formatter.format((Date)
+ validity.get(CertificateValidity.NOT_BEFORE));
+ } catch (Exception e) {
+ CMS.debug("ValidityDefault: getValue " + e.toString());
+ }
+ throw new EPropertyException("Invalid valie");
+ } else if (name.equals(VAL_NOT_AFTER)) {
+ SimpleDateFormat formatter =
+ new SimpleDateFormat(DATE_FORMAT);
+ CertificateValidity validity = null;
+
+ try {
+ validity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ return formatter.format((Date)
+ validity.get(CertificateValidity.NOT_AFTER));
+ } catch (Exception e) {
+ CMS.debug("ValidityDefault: getValue " + e.toString());
+ }
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_VALIDITY",
+ getConfig(CONFIG_RANGE));
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ // always + 60 seconds
+ String startTimeStr = getConfig(CONFIG_START_TIME);
+ try {
+ startTimeStr = mapPattern(request, startTimeStr);
+ } catch (IOException e) {
+ CMS.debug("ValidityDefault: populate " + e.toString());
+ }
+
+ if (startTimeStr == null || startTimeStr.equals("")) {
+ startTimeStr = "60";
+ }
+ int startTime = Integer.parseInt(startTimeStr);
+ Date notBefore = new Date(CMS.getCurrentDate().getTime() + (1000 * startTime));
+ long notAfterVal = 0;
+
+ try {
+ String rangeStr = getConfig(CONFIG_RANGE);
+ rangeStr = mapPattern(request, rangeStr);
+ notAfterVal = notBefore.getTime() +
+ (mDefault * Integer.parseInt(rangeStr));
+ } catch (Exception e) {
+ // configured value is not correct
+ CMS.debug("ValidityDefault: populate " + e.toString());
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_INVALID_PROPERTY", CONFIG_RANGE));
+ }
+ Date notAfter = new Date(notAfterVal);
+ CertificateValidity validity =
+ new CertificateValidity(notBefore, notAfter);
+
+ try {
+ info.set(X509CertInfo.VALIDITY, validity);
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("ValidityDefault: populate " + e.toString());
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_INVALID_PROPERTY", X509CertInfo.VALIDITY));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/nsHKeySubjectNameDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/nsHKeySubjectNameDefault.java
new file mode 100644
index 000000000..bd935fb53
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/nsHKeySubjectNameDefault.java
@@ -0,0 +1,215 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates server-side configurable subject name
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class nsHKeySubjectNameDefault extends EnrollDefault {
+
+ public static final String PROP_PARAMS = "params";
+ public static final String CONFIG_DNPATTERN = "dnpattern";
+
+ public static final String VAL_NAME = "name";
+
+ /* default dn pattern if left blank or not set in the config */
+ protected static String DEFAULT_DNPATTERN =
+ "CN=SecureMember - $request.tokencuid$, OU=Subscriber, O=Red Hat, C=US";
+
+ protected IConfigStore mParamsConfig;
+
+ public nsHKeySubjectNameDefault() {
+ super();
+ addConfigName(CONFIG_DNPATTERN);
+
+ addValueName(CONFIG_DNPATTERN);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ CMS.debug("nsHKeySubjectNameDefault: in getConfigDescriptor, name=" + name);
+ if (name.equals(CONFIG_DNPATTERN)) {
+ return new Descriptor(IDescriptor.STRING,
+ null, null, CMS.getUserMessage(locale,
+ "CMS_PROFILE_SUBJECT_NAME"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ CMS.debug("nsHKeySubjectNameDefault: in getValueDescriptor name=" + name);
+
+ if (name.equals(VAL_NAME)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_SUBJECT_NAME"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+
+ CMS.debug("nsHKeySubjectNameDefault: in setValue, value=" + value);
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NAME)) {
+ X500Name x500name = null;
+
+ try {
+ x500name = new X500Name(value);
+ } catch (IOException e) {
+ CMS.debug("nsHKeySubjectNameDefault: setValue " + e.toString());
+ // failed to build x500 name
+ }
+ CMS.debug("nsHKeySubjectNameDefault: setValue name=" + x500name);
+ try {
+ info.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(x500name));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("nsHKeySubjectNameDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ CMS.debug("nsHKeySubjectNameDefault: in getValue, name=" + name);
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NAME)) {
+ CertificateSubjectName sn = null;
+
+ try {
+ CMS.debug("nsHKeySubjectNameDefault: getValue info=" + info);
+ sn = (CertificateSubjectName)
+ info.get(X509CertInfo.SUBJECT);
+ CMS.debug("nsHKeySubjectNameDefault: getValue name=" + sn);
+ return sn.toString();
+ } catch (Exception e) {
+ // nothing
+ CMS.debug("nsHKeySubjectNameDefault: getValue " + e.toString());
+
+ }
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ CMS.debug("nsHKeySubjectNameDefault: in getText");
+ return CMS.getUserMessage(locale, "CMS_PROFILE_SUBJECT_NAME",
+ getConfig(CONFIG_DNPATTERN));
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ X500Name name = null;
+ CMS.debug("nsHKeySubjectNameDefault: in populate");
+
+ try {
+ String subjectName = getSubjectName(request);
+ CMS.debug("subjectName=" + subjectName);
+ if (subjectName == null || subjectName.equals(""))
+ return;
+
+ name = new X500Name(subjectName);
+ } catch (IOException e) {
+ // failed to build x500 name
+ CMS.debug("nsHKeySubjectNameDefault: populate " + e.toString());
+ }
+ if (name == null) {
+ // failed to build x500 name
+ }
+ try {
+ info.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(name));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("nsHKeySubjectNameDefault: populate " + e.toString());
+ }
+ }
+
+ private String getSubjectName(IRequest request)
+ throws EProfileException, IOException {
+
+ CMS.debug("nsHKeySubjectNameDefault: in getSubjectName");
+
+ String pattern = getConfig(CONFIG_DNPATTERN);
+ if (pattern == null || pattern.equals("")) {
+ pattern = " ";
+ }
+
+ String sbjname = "";
+
+ if (request != null) {
+ CMS.debug("pattern = " + pattern);
+ sbjname = mapPattern(request, pattern);
+ CMS.debug("nsHKeySubjectNameDefault: getSubjectName(): subject name mapping done");
+ }
+
+ return sbjname;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/nsNKeySubjectNameDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/nsNKeySubjectNameDefault.java
new file mode 100644
index 000000000..c90b76c5d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/nsNKeySubjectNameDefault.java
@@ -0,0 +1,423 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+//ldap java sdk
+import java.io.IOException;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates server-side configurable subject name
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class nsNKeySubjectNameDefault extends EnrollDefault {
+
+ public static final String PROP_LDAP = "ldap";
+ public static final String PROP_PARAMS = "params";
+ public static final String CONFIG_DNPATTERN = "dnpattern";
+ public static final String CONFIG_LDAP_STRING_ATTRS = "ldapStringAttributes";
+ public static final String CONFIG_LDAP_HOST = "ldap.ldapconn.host";
+ public static final String CONFIG_LDAP_PORT = "ldap.ldapconn.port";
+ public static final String CONFIG_LDAP_SEC_CONN = "ldap.ldapconn.secureConn";
+ public static final String CONFIG_LDAP_VER = "ldap.ldapconn.Version";
+ public static final String CONFIG_LDAP_BASEDN = "ldap.basedn";
+ public static final String CONFIG_LDAP_MIN_CONN = "ldap.minConns";
+ public static final String CONFIG_LDAP_MAX_CONN = "ldap.maxConns";
+
+ public static final String VAL_NAME = "name";
+
+ public static final String CONFIG_LDAP_VERS =
+ "2,3";
+
+ /* default dn pattern if left blank or not set in the config */
+ protected static String DEFAULT_DNPATTERN =
+ "CN=$request.aoluid$, E=$request.mail$";
+
+ /* ldap configuration sub-store */
+ boolean mInitialized = false;
+ protected IConfigStore mInstConfig;
+ protected IConfigStore mLdapConfig;
+ protected IConfigStore mParamsConfig;
+
+ /* ldap base dn */
+ protected String mBaseDN = null;
+
+ /* factory of anonymous ldap connections */
+ protected ILdapConnFactory mConnFactory = null;
+
+ /* the list of LDAP attributes with string values to retrieve to
+ * form the subject dn. */
+ protected String[] mLdapStringAttrs = null;
+
+ public nsNKeySubjectNameDefault() {
+ super();
+ addConfigName(CONFIG_DNPATTERN);
+ addConfigName(CONFIG_LDAP_STRING_ATTRS);
+ addConfigName(CONFIG_LDAP_HOST);
+ addConfigName(CONFIG_LDAP_PORT);
+ addConfigName(CONFIG_LDAP_SEC_CONN);
+ addConfigName(CONFIG_LDAP_VER);
+ addConfigName(CONFIG_LDAP_BASEDN);
+ addConfigName(CONFIG_LDAP_MIN_CONN);
+ addConfigName(CONFIG_LDAP_MAX_CONN);
+
+ addValueName(CONFIG_DNPATTERN);
+ addValueName(CONFIG_LDAP_STRING_ATTRS);
+ addValueName(CONFIG_LDAP_HOST);
+ addValueName(CONFIG_LDAP_PORT);
+ addValueName(CONFIG_LDAP_SEC_CONN);
+ addValueName(CONFIG_LDAP_VER);
+ addValueName(CONFIG_LDAP_BASEDN);
+ addValueName(CONFIG_LDAP_MIN_CONN);
+ addValueName(CONFIG_LDAP_MAX_CONN);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ mInstConfig = config;
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ CMS.debug("nsNKeySubjectNameDefault: in getConfigDescriptor, name=" + name);
+ if (name.equals(CONFIG_DNPATTERN)) {
+ return new Descriptor(IDescriptor.STRING,
+ null, null, CMS.getUserMessage(locale,
+ "CMS_PROFILE_SUBJECT_NAME"));
+ } else if (name.equals(CONFIG_LDAP_STRING_ATTRS)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NSNKEY_LDAP_STRING_ATTRS"));
+ } else if (name.equals(CONFIG_LDAP_HOST)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NSNKEY_HOST_NAME"));
+ } else if (name.equals(CONFIG_LDAP_PORT)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NSNKEY_PORT_NUMBER"));
+ } else if (name.equals(CONFIG_LDAP_SEC_CONN)) {
+ return new Descriptor(IDescriptor.BOOLEAN,
+ null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NSNKEY_SECURE_CONN"));
+ } else if (name.equals(CONFIG_LDAP_VER)) {
+ return new Descriptor(IDescriptor.CHOICE, CONFIG_LDAP_VERS,
+ "3",
+ CMS.getUserMessage(locale, "CMS_PROFILE_NSNKEY_LDAP_VERSION"));
+ } else if (name.equals(CONFIG_LDAP_BASEDN)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NSNKEY_BASEDN"));
+ } else if (name.equals(CONFIG_LDAP_MIN_CONN)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NSNKEY_LDAP_MIN_CONN"));
+ } else if (name.equals(CONFIG_LDAP_MAX_CONN)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_NSNKEY_LDAP_MAX_CONN"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ CMS.debug("nsNKeySubjectNameDefault: in getValueDescriptor name=" + name);
+
+ if (name.equals(VAL_NAME)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_SUBJECT_NAME"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+
+ CMS.debug("nsNKeySubjectNameDefault: in setValue, value=" + value);
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NAME)) {
+ X500Name x500name = null;
+
+ try {
+ x500name = new X500Name(value);
+ } catch (IOException e) {
+ CMS.debug("nsNKeySubjectNameDefault: setValue " + e.toString());
+ // failed to build x500 name
+ }
+ CMS.debug("nsNKeySubjectNameDefault: setValue name=" + x500name);
+ try {
+ info.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(x500name));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("nsNKeySubjectNameDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ CMS.debug("nsNKeySubjectNameDefault: in getValue, name=" + name);
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NAME)) {
+ CertificateSubjectName sn = null;
+
+ try {
+ CMS.debug("nsNKeySubjectNameDefault: getValue info=" + info);
+ sn = (CertificateSubjectName)
+ info.get(X509CertInfo.SUBJECT);
+ CMS.debug("nsNKeySubjectNameDefault: getValue name=" + sn);
+ return sn.toString();
+ } catch (Exception e) {
+ // nothing
+ CMS.debug("nsNKeySubjectNameDefault: getValue " + e.toString());
+
+ }
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ CMS.debug("nsNKeySubjectNameDefault: in getText");
+ return CMS.getUserMessage(locale, "CMS_PROFILE_SUBJECT_NAME",
+ getConfig(CONFIG_DNPATTERN));
+ }
+
+ public void ldapInit()
+ throws EProfileException {
+ if (mInitialized == true)
+ return;
+
+ CMS.debug("nsNKeySubjectNameDefault: ldapInit(): begin");
+
+ try {
+ // cfu - XXX do more error handling here later
+ /* initialize ldap server configuration */
+ mParamsConfig = mInstConfig.getSubStore(PROP_PARAMS);
+ mLdapConfig = mParamsConfig.getSubStore(PROP_LDAP);
+ mBaseDN = mParamsConfig.getString(CONFIG_LDAP_BASEDN, null);
+ mConnFactory = CMS.getLdapAnonConnFactory();
+ mConnFactory.init(mLdapConfig);
+
+ /* initialize dn pattern */
+ String pattern = mParamsConfig.getString(CONFIG_DNPATTERN, null);
+
+ if (pattern == null || pattern.length() == 0)
+ pattern = DEFAULT_DNPATTERN;
+
+ /* initialize ldap string attribute list */
+ String ldapStringAttrs = mParamsConfig.getString(CONFIG_LDAP_STRING_ATTRS, null);
+
+ if ((ldapStringAttrs != null) && (ldapStringAttrs.length() != 0)) {
+ StringTokenizer pAttrs =
+ new StringTokenizer(ldapStringAttrs, ",", false);
+
+ mLdapStringAttrs = new String[pAttrs.countTokens()];
+
+ for (int i = 0; i < mLdapStringAttrs.length; i++) {
+ mLdapStringAttrs[i] = ((String) pAttrs.nextElement()).trim();
+ }
+ }
+ CMS.debug("nsNKeySubjectNameDefault: ldapInit(): done");
+ mInitialized = true;
+ } catch (Exception e) {
+ CMS.debug("nsNKeySubjectNameDefault: ldapInit(): " + e.toString());
+ // throw EProfileException...
+ throw new EProfileException("ldap init failure: " + e.toString());
+ }
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ X500Name name = null;
+ CMS.debug("nsNKeySubjectNameDefault: in populate");
+ ldapInit();
+ try {
+ // cfu - this goes to ldap
+ String subjectName = getSubjectName(request);
+ CMS.debug("subjectName=" + subjectName);
+ if (subjectName == null || subjectName.equals(""))
+ return;
+
+ name = new X500Name(subjectName);
+ } catch (IOException e) {
+ // failed to build x500 name
+ CMS.debug("nsNKeySubjectNameDefault: populate " + e.toString());
+ }
+ if (name == null) {
+ // failed to build x500 name
+ }
+ try {
+ info.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(name));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("nsNKeySubjectNameDefault: populate " + e.toString());
+ }
+ }
+
+ private String getSubjectName(IRequest request)
+ throws EProfileException, IOException {
+
+ CMS.debug("nsNKeySubjectNameDefault: in getSubjectName");
+
+ String pattern = getConfig(CONFIG_DNPATTERN);
+ if (pattern == null || pattern.equals("")) {
+ pattern = " ";
+ }
+
+ LDAPConnection conn = null;
+ String userdn = null;
+ String sbjname = "";
+ // get DN from ldap to fill request
+ try {
+ if (mConnFactory == null) {
+ conn = null;
+ CMS.debug("nsNKeySubjectNameDefault: getSubjectName(): no LDAP connection");
+ throw new EProfileException("no LDAP connection");
+ } else {
+ conn = mConnFactory.getConn();
+ if (conn == null) {
+ CMS.debug("nsNKeySubjectNameDefault::getSubjectName() - " +
+ "no LDAP connection");
+ throw new EProfileException("no LDAP connection");
+ }
+ CMS.debug("nsNKeySubjectNameDefault: getSubjectName(): got LDAP connection");
+ }
+
+ if (request != null) {
+ CMS.debug("pattern = " + pattern);
+ sbjname = mapPattern(request, pattern);
+ CMS.debug("nsNKeySubjectNameDefault: getSubjectName(): subject name mapping done");
+ } else {
+ CMS.debug("nsNKeySubjectNameDefault::getSubjectName() - " +
+ "request is null!");
+ throw new EProfileException("request is null");
+ }
+ // retrieve the attributes
+ // get user dn.
+ CMS.debug("nsNKeySubjectNameDefault: getSubjectName(): about to search with basedn = " + mBaseDN);
+ LDAPSearchResults res = conn.search(mBaseDN,
+ LDAPv2.SCOPE_SUB, "(aoluid=" + request.getExtDataInString("aoluid") + ")", null, false);
+
+ if (res.hasMoreElements()) {
+ LDAPEntry entry = res.next();
+
+ userdn = entry.getDN();
+ } else {// put into property file later - cfu
+ CMS.debug("nsNKeySubjectNameDefault: getSubjectName(): screen name does not exist");
+ throw new EProfileException("screenname does not exist");
+ }
+ CMS.debug("nsNKeySubjectNameDefault: getSubjectName(): retrieved entry for aoluid = "
+ + request.getExtDataInString("aoluid"));
+ ;
+
+ LDAPEntry entry = null;
+ CMS.debug("nsNKeySubjectNameDefault: getSubjectName(): about to search with "
+ + mLdapStringAttrs.length + " attributes");
+ LDAPSearchResults results =
+ conn.search(userdn, LDAPv2.SCOPE_BASE, "objectclass=*",
+ mLdapStringAttrs, false);
+
+ if (!results.hasMoreElements()) {
+ CMS.debug("nsNKeySubjectNameDefault: getSubjectName(): no attributes");
+ throw new EProfileException("no ldap attributes found");
+ }
+ entry = results.next();
+ // set attrs into request
+ for (int i = 0; i < mLdapStringAttrs.length; i++) {
+ LDAPAttribute la =
+ entry.getAttribute(mLdapStringAttrs[i]);
+ if (la != null) {
+ String[] sla = la.getStringValueArray();
+ CMS.debug("nsNKeySubjectNameDefault: getSubjectName(): got attribute: " + sla[0]);
+ request.setExtData(mLdapStringAttrs[i], sla[0]);
+ }
+ }
+ CMS.debug("nsNKeySubjectNameDefault: getSubjectName(): attributes set in request");
+ } catch (Exception e) {
+ CMS.debug("nsNKeySubjectNameDefault: getSubjectName(): " + e.toString());
+ throw new EProfileException("getSubjectName() failure: " + e.toString());
+ } finally {
+ try {
+ if (conn != null)
+ mConnFactory.returnConn(conn);
+ } catch (Exception e) {
+ throw new EProfileException("nsNKeySubjectNameDefault: getSubjectName(): connection return failure");
+ }
+ }
+ return sbjname;
+
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/nsTokenDeviceKeySubjectNameDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/nsTokenDeviceKeySubjectNameDefault.java
new file mode 100644
index 000000000..9dfda47b5
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/nsTokenDeviceKeySubjectNameDefault.java
@@ -0,0 +1,215 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates server-side configurable subject name
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class nsTokenDeviceKeySubjectNameDefault extends EnrollDefault {
+
+ public static final String PROP_PARAMS = "params";
+ public static final String CONFIG_DNPATTERN = "dnpattern";
+
+ public static final String VAL_NAME = "name";
+
+ /* default dn pattern if left blank or not set in the config */
+ protected static String DEFAULT_DNPATTERN =
+ "Token Key Device - $request.tokencuid$";
+
+ protected IConfigStore mParamsConfig;
+
+ public nsTokenDeviceKeySubjectNameDefault() {
+ super();
+ addConfigName(CONFIG_DNPATTERN);
+
+ addValueName(CONFIG_DNPATTERN);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: in getConfigDescriptor, name=" + name);
+ if (name.equals(CONFIG_DNPATTERN)) {
+ return new Descriptor(IDescriptor.STRING,
+ null, null, CMS.getUserMessage(locale,
+ "CMS_PROFILE_SUBJECT_NAME"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: in getValueDescriptor name=" + name);
+
+ if (name.equals(VAL_NAME)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_SUBJECT_NAME"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: in setValue, value=" + value);
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NAME)) {
+ X500Name x500name = null;
+
+ try {
+ x500name = new X500Name(value);
+ } catch (IOException e) {
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: setValue " + e.toString());
+ // failed to build x500 name
+ }
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: setValue name=" + x500name);
+ try {
+ info.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(x500name));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: in getValue, name=" + name);
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NAME)) {
+ CertificateSubjectName sn = null;
+
+ try {
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: getValue info=" + info);
+ sn = (CertificateSubjectName)
+ info.get(X509CertInfo.SUBJECT);
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: getValue name=" + sn);
+ return sn.toString();
+ } catch (Exception e) {
+ // nothing
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: getValue " + e.toString());
+
+ }
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: in getText");
+ return CMS.getUserMessage(locale, "CMS_PROFILE_SUBJECT_NAME",
+ getConfig(CONFIG_DNPATTERN));
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ X500Name name = null;
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: in populate");
+
+ try {
+ String subjectName = getSubjectName(request);
+ CMS.debug("subjectName=" + subjectName);
+ if (subjectName == null || subjectName.equals(""))
+ return;
+
+ name = new X500Name(subjectName);
+ } catch (IOException e) {
+ // failed to build x500 name
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: populate " + e.toString());
+ }
+ if (name == null) {
+ // failed to build x500 name
+ }
+ try {
+ info.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(name));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: populate " + e.toString());
+ }
+ }
+
+ private String getSubjectName(IRequest request)
+ throws EProfileException, IOException {
+
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: in getSubjectName");
+
+ String pattern = getConfig(CONFIG_DNPATTERN);
+ if (pattern == null || pattern.equals("")) {
+ pattern = " ";
+ }
+
+ String sbjname = "";
+
+ if (request != null) {
+ CMS.debug("pattern = " + pattern);
+ sbjname = mapPattern(request, pattern);
+ CMS.debug("nsTokenDeviceKeySubjectNameDefault: getSubjectName(): subject name mapping done");
+ }
+
+ return sbjname;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/nsTokenUserKeySubjectNameDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/nsTokenUserKeySubjectNameDefault.java
new file mode 100644
index 000000000..86a2a6961
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/nsTokenUserKeySubjectNameDefault.java
@@ -0,0 +1,457 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+//ldap java sdk
+import java.io.IOException;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates server-side configurable subject name
+ * into the certificate template.
+ *
+ * @version $Revision$, $Date$
+ */
+public class nsTokenUserKeySubjectNameDefault extends EnrollDefault {
+
+ public static final String PROP_LDAP = "ldap";
+ public static final String PROP_PARAMS = "params";
+ public static final String CONFIG_DNPATTERN = "dnpattern";
+ public static final String CONFIG_LDAP_ENABLE = "ldap.enable";
+ public static final String CONFIG_LDAP_SEARCH_NAME = "ldap.searchName";
+ public static final String CONFIG_LDAP_STRING_ATTRS = "ldapStringAttributes";
+ public static final String CONFIG_LDAP_HOST = "ldap.ldapconn.host";
+ public static final String CONFIG_LDAP_PORT = "ldap.ldapconn.port";
+ public static final String CONFIG_LDAP_SEC_CONN = "ldap.ldapconn.secureConn";
+ public static final String CONFIG_LDAP_VER = "ldap.ldapconn.Version";
+ public static final String CONFIG_LDAP_BASEDN = "ldap.basedn";
+ public static final String CONFIG_LDAP_MIN_CONN = "ldap.minConns";
+ public static final String CONFIG_LDAP_MAX_CONN = "ldap.maxConns";
+
+ public static final String VAL_NAME = "name";
+
+ public static final String CONFIG_LDAP_VERS =
+ "2,3";
+
+ /* default dn pattern if left blank or not set in the config */
+ protected static String DEFAULT_DNPATTERN =
+ "CN=$request.uid$, E=$request.mail$";
+
+ /* ldap configuration sub-store */
+ boolean mldapInitialized = false;
+ boolean mldapEnabled = false;
+ protected IConfigStore mInstConfig;
+ protected IConfigStore mLdapConfig;
+ protected IConfigStore mParamsConfig;
+
+ /* ldap base dn */
+ protected String mBaseDN = null;
+
+ /* factory of anonymous ldap connections */
+ protected ILdapConnFactory mConnFactory = null;
+
+ /* the list of LDAP attributes with string values to retrieve to
+ * form the subject dn. */
+ protected String[] mLdapStringAttrs = null;
+
+ public nsTokenUserKeySubjectNameDefault() {
+ super();
+ addConfigName(CONFIG_DNPATTERN);
+ addConfigName(CONFIG_LDAP_ENABLE);
+ addConfigName(CONFIG_LDAP_SEARCH_NAME);
+ addConfigName(CONFIG_LDAP_STRING_ATTRS);
+ addConfigName(CONFIG_LDAP_HOST);
+ addConfigName(CONFIG_LDAP_PORT);
+ addConfigName(CONFIG_LDAP_SEC_CONN);
+ addConfigName(CONFIG_LDAP_VER);
+ addConfigName(CONFIG_LDAP_BASEDN);
+ addConfigName(CONFIG_LDAP_MIN_CONN);
+ addConfigName(CONFIG_LDAP_MAX_CONN);
+
+ addValueName(CONFIG_DNPATTERN);
+ addValueName(CONFIG_LDAP_ENABLE);
+ addValueName(CONFIG_LDAP_SEARCH_NAME);
+ addValueName(CONFIG_LDAP_STRING_ATTRS);
+ addValueName(CONFIG_LDAP_HOST);
+ addValueName(CONFIG_LDAP_PORT);
+ addValueName(CONFIG_LDAP_SEC_CONN);
+ addValueName(CONFIG_LDAP_VER);
+ addValueName(CONFIG_LDAP_BASEDN);
+ addValueName(CONFIG_LDAP_MIN_CONN);
+ addValueName(CONFIG_LDAP_MAX_CONN);
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ mInstConfig = config;
+ super.init(profile, config);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ CMS.debug("nsTokenUserKeySubjectNameDefault: in getConfigDescriptor, name=" + name);
+ if (name.equals(CONFIG_DNPATTERN)) {
+ return new Descriptor(IDescriptor.STRING,
+ null, null, CMS.getUserMessage(locale,
+ "CMS_PROFILE_SUBJECT_NAME"));
+ } else if (name.equals(CONFIG_LDAP_STRING_ATTRS)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_TOKENKEY_LDAP_STRING_ATTRS"));
+ } else if (name.equals(CONFIG_LDAP_ENABLE)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_TOKENKEY_LDAP_ENABLE"));
+ } else if (name.equals(CONFIG_LDAP_SEARCH_NAME)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_TOKENKEY_LDAP_SEARCH_NAME"));
+ } else if (name.equals(CONFIG_LDAP_HOST)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_TOKENKEY_LDAP_HOST_NAME"));
+ } else if (name.equals(CONFIG_LDAP_PORT)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_TOKENKEY_LDAP_PORT_NUMBER"));
+ } else if (name.equals(CONFIG_LDAP_SEC_CONN)) {
+ return new Descriptor(IDescriptor.BOOLEAN,
+ null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_TOKENKEY_LDAP_SECURE_CONN"));
+ } else if (name.equals(CONFIG_LDAP_VER)) {
+ return new Descriptor(IDescriptor.CHOICE, CONFIG_LDAP_VERS,
+ "3",
+ CMS.getUserMessage(locale, "CMS_PROFILE_TOKENKEY_LDAP_VERSION"));
+ } else if (name.equals(CONFIG_LDAP_BASEDN)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_TOKENKEY_LDAP_BASEDN"));
+ } else if (name.equals(CONFIG_LDAP_MIN_CONN)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_TOKENKEY_LDAP_MIN_CONN"));
+ } else if (name.equals(CONFIG_LDAP_MAX_CONN)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_TOKENKEY_LDAP_MAX_CONN"));
+ } else {
+ return null;
+ }
+ }
+
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ CMS.debug("nsTokenUserKeySubjectNameDefault: in getValueDescriptor name=" + name);
+
+ if (name.equals(VAL_NAME)) {
+ return new Descriptor(IDescriptor.STRING,
+ null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_SUBJECT_NAME"));
+ } else {
+ return null;
+ }
+ }
+
+ public void setValue(String name, Locale locale,
+ X509CertInfo info, String value)
+ throws EPropertyException {
+
+ CMS.debug("nsTokenUserKeySubjectNameDefault: in setValue, value=" + value);
+
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NAME)) {
+ X500Name x500name = null;
+
+ try {
+ x500name = new X500Name(value);
+ } catch (IOException e) {
+ CMS.debug("nsTokenUserKeySubjectNameDefault: setValue " + e.toString());
+ // failed to build x500 name
+ }
+ CMS.debug("nsTokenUserKeySubjectNameDefault: setValue name=" + x500name);
+ try {
+ info.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(x500name));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("nsTokenUserKeySubjectNameDefault: setValue " + e.toString());
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getValue(String name, Locale locale,
+ X509CertInfo info)
+ throws EPropertyException {
+ CMS.debug("nsTokenUserKeySubjectNameDefault: in getValue, name=" + name);
+ if (name == null) {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ if (name.equals(VAL_NAME)) {
+ CertificateSubjectName sn = null;
+
+ try {
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getValue info=" + info);
+ sn = (CertificateSubjectName)
+ info.get(X509CertInfo.SUBJECT);
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getValue name=" + sn);
+ return sn.toString();
+ } catch (Exception e) {
+ // nothing
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getValue " + e.toString());
+
+ }
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ } else {
+ throw new EPropertyException(CMS.getUserMessage(
+ locale, "CMS_INVALID_PROPERTY", name));
+ }
+ }
+
+ public String getText(Locale locale) {
+ CMS.debug("nsTokenUserKeySubjectNameDefault: in getText");
+ return CMS.getUserMessage(locale, "CMS_PROFILE_SUBJECT_NAME",
+ getConfig(CONFIG_DNPATTERN));
+ }
+
+ public void ldapInit()
+ throws EProfileException {
+ if (mldapInitialized == true)
+ return;
+
+ CMS.debug("nsTokenUserKeySubjectNameDefault: ldapInit(): begin");
+
+ try {
+ // cfu - XXX do more error handling here later
+ /* initialize ldap server configuration */
+ mParamsConfig = mInstConfig.getSubStore(PROP_PARAMS);
+ mLdapConfig = mParamsConfig.getSubStore(PROP_LDAP);
+ mldapEnabled = mParamsConfig.getBoolean(CONFIG_LDAP_ENABLE,
+ false);
+ if (mldapEnabled == false)
+ return;
+
+ mBaseDN = mParamsConfig.getString(CONFIG_LDAP_BASEDN, null);
+ mConnFactory = CMS.getLdapAnonConnFactory();
+ mConnFactory.init(mLdapConfig);
+
+ /* initialize dn pattern */
+ String pattern = mParamsConfig.getString(CONFIG_DNPATTERN, null);
+
+ if (pattern == null || pattern.length() == 0)
+ pattern = DEFAULT_DNPATTERN;
+
+ /* initialize ldap string attribute list */
+ String ldapStringAttrs = mParamsConfig.getString(CONFIG_LDAP_STRING_ATTRS, null);
+
+ if ((ldapStringAttrs != null) && (ldapStringAttrs.length() != 0)) {
+ StringTokenizer pAttrs =
+ new StringTokenizer(ldapStringAttrs, ",", false);
+
+ mLdapStringAttrs = new String[pAttrs.countTokens()];
+
+ for (int i = 0; i < mLdapStringAttrs.length; i++) {
+ mLdapStringAttrs[i] = ((String) pAttrs.nextElement()).trim();
+ }
+ }
+ CMS.debug("nsTokenUserKeySubjectNameDefault: ldapInit(): done");
+ mldapInitialized = true;
+ } catch (Exception e) {
+ CMS.debug("nsTokenUserKeySubjectNameDefault: ldapInit(): " + e.toString());
+ // throw EProfileException...
+ throw new EProfileException("ldap init failure: " + e.toString());
+ }
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IRequest request, X509CertInfo info)
+ throws EProfileException {
+ X500Name name = null;
+ CMS.debug("nsTokenUserKeySubjectNameDefault: in populate");
+ ldapInit();
+ try {
+ // cfu - this goes to ldap
+ String subjectName = getSubjectName(request);
+ CMS.debug("subjectName=" + subjectName);
+ if (subjectName == null || subjectName.equals(""))
+ return;
+
+ name = new X500Name(subjectName);
+ } catch (IOException e) {
+ // failed to build x500 name
+ CMS.debug("nsTokenUserKeySubjectNameDefault: populate " + e.toString());
+ }
+ if (name == null) {
+ // failed to build x500 name
+ }
+ try {
+ info.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(name));
+ } catch (Exception e) {
+ // failed to insert subject name
+ CMS.debug("nsTokenUserKeySubjectNameDefault: populate " + e.toString());
+ }
+ }
+
+ private String getSubjectName(IRequest request)
+ throws EProfileException, IOException {
+
+ CMS.debug("nsTokenUserKeySubjectNameDefault: in getSubjectName");
+
+ String pattern = getConfig(CONFIG_DNPATTERN);
+ if (pattern == null || pattern.equals("")) {
+ pattern = " ";
+ }
+ String sbjname = "";
+
+ if (mldapInitialized == false) {
+ if (request != null) {
+ CMS.debug("pattern = " + pattern);
+ sbjname = mapPattern(request, pattern);
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getSubjectName(): subject name mapping done");
+ }
+ return sbjname;
+ }
+
+ // ldap is initialized, do more substitution
+ String searchName = getConfig(CONFIG_LDAP_SEARCH_NAME);
+ if (searchName == null || searchName.equals("")) {
+ searchName = "uid";
+ }
+
+ LDAPConnection conn = null;
+ String userdn = null;
+ // get DN from ldap to fill request
+ try {
+ if (mConnFactory == null) {
+ conn = null;
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getSubjectName(): no LDAP connection");
+ throw new EProfileException("no LDAP connection");
+ } else {
+ conn = mConnFactory.getConn();
+ if (conn == null) {
+ CMS.debug("nsTokenUserKeySubjectNameDefault::getSubjectName() - " +
+ "no LDAP connection");
+ throw new EProfileException("no LDAP connection");
+ }
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getSubjectName(): got LDAP connection");
+ }
+ // retrieve the attributes
+ // get user dn.
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getSubjectName(): about to search with basedn = " + mBaseDN);
+ LDAPSearchResults res = conn.search(mBaseDN,
+ LDAPv2.SCOPE_SUB, "(" + searchName + "=" + request.getExtDataInString("uid") + ")", null, false);
+
+ if (res.hasMoreElements()) {
+ LDAPEntry entry = res.next();
+
+ userdn = entry.getDN();
+ } else {// put into property file later - cfu
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getSubjectName(): " + searchName + " does not exist");
+ throw new EProfileException("id does not exist");
+ }
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getSubjectName(): retrieved entry for "
+ + searchName + " = " + request.getExtDataInString("uid"));
+
+ LDAPEntry entry = null;
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getSubjectName(): about to search with "
+ + mLdapStringAttrs.length + " attributes");
+ LDAPSearchResults results =
+ conn.search(userdn, LDAPv2.SCOPE_BASE, "objectclass=*",
+ mLdapStringAttrs, false);
+
+ if (!results.hasMoreElements()) {
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getSubjectName(): no attributes");
+ throw new EProfileException("no ldap attributes found");
+ }
+ entry = results.next();
+ // set attrs into request
+ for (int i = 0; i < mLdapStringAttrs.length; i++) {
+ LDAPAttribute la =
+ entry.getAttribute(mLdapStringAttrs[i]);
+ if (la != null) {
+ String[] sla = la.getStringValueArray();
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getSubjectName(): got attribute: "
+ + mLdapStringAttrs[i] +
+ "=" + LDAPUtil.escapeRDNValue(sla[0]));
+ request.setExtData(mLdapStringAttrs[i], LDAPUtil.escapeRDNValue(sla[0]));
+ }
+ }
+ CMS.debug("pattern = " + pattern);
+ sbjname = mapPattern(request, pattern);
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getSubjectName(): subject name mapping done");
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getSubjectName(): attributes set in request");
+
+ } catch (Exception e) {
+ CMS.debug("nsTokenUserKeySubjectNameDefault: getSubjectName(): " + e.toString());
+ throw new EProfileException("getSubjectName() failure: " + e.toString());
+ } finally {
+ try {
+ if (conn != null)
+ mConnFactory.returnConn(conn);
+ } catch (Exception e) {
+ throw new EProfileException(
+ "nsTokenUserKeySubjectNameDefault: getSubjectName(): connection return failure");
+ }
+ }
+ return sbjname;
+
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/CMCCertReqInput.java b/base/server/cms/src/com/netscape/cms/profile/input/CMCCertReqInput.java
new file mode 100644
index 000000000..a62d6e9f7
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/CMCCertReqInput.java
@@ -0,0 +1,128 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Locale;
+
+import netscape.security.x509.X509CertInfo;
+
+import org.mozilla.jss.pkix.cmc.TaggedRequest;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the certificate request input.
+ * This input populates 2 main fields to the enrollment page:
+ * 1/ Certificate Request Type, 2/ Certificate Request
+ * <p>
+ *
+ * This input usually is used by an enrollment profile for certificate requests.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMCCertReqInput extends EnrollInput implements IProfileInput {
+ public static final String VAL_CERT_REQUEST_TYPE =
+ EnrollProfile.CTX_CERT_REQUEST_TYPE;
+ public static final String VAL_CERT_REQUEST =
+ EnrollProfile.CTX_CERT_REQUEST;
+
+ public EnrollProfile mEnrollProfile = null;
+
+ public CMCCertReqInput() {
+ addValueName(VAL_CERT_REQUEST);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+
+ mEnrollProfile = (EnrollProfile) profile;
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_CERT_REQ_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_CERT_REQ_TEXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ String cert_request = ctx.get(VAL_CERT_REQUEST);
+ X509CertInfo info =
+ request.getExtDataInCertInfo(EnrollProfile.REQUEST_CERTINFO);
+
+ if (cert_request == null) {
+ CMS.debug("CMCCertReqInput: populate - invalid certificate request");
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+ TaggedRequest msgs[] = mEnrollProfile.parseCMC(getLocale(request), cert_request);
+
+ if (msgs == null) {
+ CMS.debug("CMCCertReqInput: populate - parseCMC returns null TaggedRequest msgs");
+ return;
+ }
+ // This profile only handle the first request in CRMF
+ Integer seqNum = request.getExtDataInInteger(EnrollProfile.REQUEST_SEQ_NUM);
+ if (seqNum == null) {
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_UNKNOWN_SEQ_NUM"));
+ }
+
+ mEnrollProfile.fillTaggedRequest(getLocale(request), msgs[seqNum.intValue()], info, request);
+ request.setExtData(EnrollProfile.REQUEST_CERTINFO, info);
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CERT_REQUEST)) {
+ return new Descriptor(IDescriptor.CERT_REQUEST, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_INPUT_CERT_REQ"));
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/CertReqInput.java b/base/server/cms/src/com/netscape/cms/profile/input/CertReqInput.java
new file mode 100644
index 000000000..e67f5b501
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/CertReqInput.java
@@ -0,0 +1,190 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Locale;
+
+import netscape.security.pkcs.PKCS10;
+import netscape.security.util.DerInputStream;
+import netscape.security.x509.X509CertInfo;
+
+import org.mozilla.jss.pkix.cmc.TaggedRequest;
+import org.mozilla.jss.pkix.crmf.CertReqMsg;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the certificate request input.
+ * This input populates 2 main fields to the enrollment page:
+ * 1/ Certificate Request Type, 2/ Certificate Request
+ * <p>
+ *
+ * This input usually is used by an enrollment profile for certificate requests.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CertReqInput extends EnrollInput implements IProfileInput {
+ public static final String VAL_CERT_REQUEST_TYPE =
+ EnrollProfile.CTX_CERT_REQUEST_TYPE;
+ public static final String VAL_CERT_REQUEST =
+ EnrollProfile.CTX_CERT_REQUEST;
+
+ public EnrollProfile mEnrollProfile = null;
+
+ public CertReqInput() {
+ addValueName(VAL_CERT_REQUEST_TYPE);
+ addValueName(VAL_CERT_REQUEST);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+
+ mEnrollProfile = (EnrollProfile) profile;
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_CERT_REQ_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_CERT_REQ_TEXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ String cert_request_type = ctx.get(VAL_CERT_REQUEST_TYPE);
+ String cert_request = ctx.get(VAL_CERT_REQUEST);
+ X509CertInfo info =
+ request.getExtDataInCertInfo(EnrollProfile.REQUEST_CERTINFO);
+
+ if (cert_request_type == null) {
+ CMS.debug("CertReqInput: populate - invalid cert request type " +
+ "");
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_UNKNOWN_CERT_REQ_TYPE",
+ ""));
+ }
+ if (cert_request == null) {
+ CMS.debug("CertReqInput: populate - invalid certificate request");
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+
+ if (cert_request_type.equals(EnrollProfile.REQ_TYPE_PKCS10)) {
+ PKCS10 pkcs10 = mEnrollProfile.parsePKCS10(getLocale(request), cert_request);
+
+ if (pkcs10 == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+
+ mEnrollProfile.fillPKCS10(getLocale(request), pkcs10, info, request);
+ } else if (cert_request_type.startsWith(EnrollProfile.REQ_TYPE_KEYGEN)) {
+ DerInputStream keygen = mEnrollProfile.parseKeyGen(getLocale(request), cert_request);
+
+ if (keygen == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+
+ mEnrollProfile.fillKeyGen(getLocale(request), keygen, info, request);
+ } else if (cert_request_type.startsWith(EnrollProfile.REQ_TYPE_CRMF)) {
+ CertReqMsg msgs[] = mEnrollProfile.parseCRMF(getLocale(request), cert_request);
+
+ if (msgs == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+ for (int x = 0; x < msgs.length; x++) {
+ verifyPOP(getLocale(request), msgs[x]);
+ }
+ // This profile only handle the first request in CRMF
+ Integer seqNum = request.getExtDataInInteger(EnrollProfile.REQUEST_SEQ_NUM);
+
+ mEnrollProfile.fillCertReqMsg(getLocale(request), msgs[seqNum.intValue()], info, request
+ );
+ } else if (cert_request_type.startsWith(EnrollProfile.REQ_TYPE_CMC)) {
+ TaggedRequest msgs[] = mEnrollProfile.parseCMC(getLocale(request), cert_request);
+
+ if (msgs == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+ // This profile only handle the first request in CRMF
+ Integer seqNum = request.getExtDataInInteger(EnrollProfile.REQUEST_SEQ_NUM);
+ if (seqNum == null) {
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_UNKNOWN_SEQ_NUM"));
+ }
+
+ mEnrollProfile.fillTaggedRequest(getLocale(request), msgs[seqNum.intValue()], info, request);
+ } else {
+ // error
+ CMS.debug("CertReqInput: populate - invalid cert request type " +
+ cert_request_type);
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_UNKNOWN_CERT_REQ_TYPE",
+ cert_request_type));
+ }
+ request.setExtData(EnrollProfile.REQUEST_CERTINFO, info);
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_CERT_REQUEST_TYPE)) {
+ return new Descriptor(IDescriptor.CERT_REQUEST_TYPE, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_INPUT_CERT_REQ_TYPE"));
+ } else if (name.equals(VAL_CERT_REQUEST)) {
+ return new Descriptor(IDescriptor.CERT_REQUEST, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_INPUT_CERT_REQ"));
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/DualKeyGenInput.java b/base/server/cms/src/com/netscape/cms/profile/input/DualKeyGenInput.java
new file mode 100644
index 000000000..8a2629667
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/DualKeyGenInput.java
@@ -0,0 +1,168 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Locale;
+
+import netscape.security.pkcs.PKCS10;
+import netscape.security.util.DerInputStream;
+import netscape.security.x509.X509CertInfo;
+
+import org.mozilla.jss.pkix.crmf.CertReqMsg;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the dual key generation input.
+ * This input populates parameters to the enrollment
+ * pages so that a CRMF request containing 2 certificate
+ * requests will be generated.
+ * <p>
+ *
+ * This input can only be used with Netscape 7.x or later clients.
+ * <p>
+ *
+ * @version $Revision$, $Date$
+ */
+public class DualKeyGenInput extends EnrollInput implements IProfileInput {
+
+ public static final String VAL_KEYGEN_REQUEST_TYPE =
+ EnrollProfile.CTX_CERT_REQUEST_TYPE;
+ public static final String VAL_KEYGEN_REQUEST =
+ EnrollProfile.CTX_CERT_REQUEST;
+
+ public EnrollProfile mEnrollProfile = null;
+
+ public DualKeyGenInput() {
+ addValueName(VAL_KEYGEN_REQUEST_TYPE);
+ addValueName(VAL_KEYGEN_REQUEST);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ mEnrollProfile = (EnrollProfile) profile;
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_DUAL_KEY_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_DUAL_KEY_TEXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ String keygen_request_type = ctx.get(VAL_KEYGEN_REQUEST_TYPE);
+ String keygen_request = ctx.get(VAL_KEYGEN_REQUEST);
+
+ X509CertInfo info =
+ request.getExtDataInCertInfo(EnrollProfile.REQUEST_CERTINFO);
+
+ if (keygen_request_type == null) {
+ CMS.debug("DualKeyGenInput: populate - invalid cert request type " +
+ "");
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_UNKNOWN_CERT_REQ_TYPE",
+ ""));
+ }
+ if (keygen_request == null) {
+ CMS.debug("DualKeyGenInput: populate - invalid certificate request");
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+ if (keygen_request_type.startsWith("pkcs10")) {
+ PKCS10 pkcs10 = mEnrollProfile.parsePKCS10(getLocale(request), keygen_request);
+
+ mEnrollProfile.fillPKCS10(getLocale(request), pkcs10, info, request);
+ } else if (keygen_request_type.startsWith("keygen")) {
+ DerInputStream keygen = mEnrollProfile.parseKeyGen(getLocale(request), keygen_request);
+
+ mEnrollProfile.fillKeyGen(getLocale(request), keygen, info, request);
+ } else if (keygen_request_type.startsWith("crmf")) {
+ CertReqMsg msgs[] = mEnrollProfile.parseCRMF(getLocale(request), keygen_request);
+
+ if (msgs == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+ for (int x = 0; x < msgs.length; x++) {
+ verifyPOP(getLocale(request), msgs[x]);
+ }
+ // This profile only handle the first request in CRMF
+ Integer seqNum = request.getExtDataInInteger(EnrollProfile.REQUEST_SEQ_NUM);
+
+ if (seqNum == null) {
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_UNKNOWN_SEQ_NUM"));
+ }
+
+ mEnrollProfile.fillCertReqMsg(getLocale(request), msgs[seqNum.intValue()], info, request);
+ } else {
+ // error
+ CMS.debug("DualKeyGenInput: populate - " +
+ "invalid cert request type " + keygen_request_type);
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_UNKNOWN_CERT_REQ_TYPE",
+ keygen_request_type));
+ }
+ request.setExtData(EnrollProfile.REQUEST_CERTINFO, info);
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_KEYGEN_REQUEST_TYPE)) {
+ return new Descriptor(IDescriptor.DUAL_KEYGEN_REQUEST_TYPE, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_KEYGEN_REQ_TYPE"));
+ } else if (name.equals(VAL_KEYGEN_REQUEST)) {
+ return new Descriptor(IDescriptor.DUAL_KEYGEN_REQUEST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_KEYGEN_REQ"));
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/EncryptionKeyGenInput.java b/base/server/cms/src/com/netscape/cms/profile/input/EncryptionKeyGenInput.java
new file mode 100644
index 000000000..dae8143ee
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/EncryptionKeyGenInput.java
@@ -0,0 +1,189 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Locale;
+
+import netscape.security.pkcs.PKCS10;
+import netscape.security.util.DerInputStream;
+import netscape.security.x509.X509CertInfo;
+
+import org.mozilla.jss.pkix.cmc.TaggedRequest;
+import org.mozilla.jss.pkix.crmf.CertReqMsg;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the key generation input that
+ * populates parameters to the enrollment page for
+ * key generation.
+ * <p>
+ *
+ * This input normally is used with user-based or non certificate request profile.
+ * <p>
+ *
+ * @version $Revision$, $Date$
+ */
+public class EncryptionKeyGenInput extends EnrollInput implements IProfileInput {
+
+ public static final String VAL_KEYGEN_REQUEST_TYPE =
+ EnrollProfile.CTX_CERT_REQUEST_TYPE;
+ public static final String VAL_KEYGEN_REQUEST =
+ EnrollProfile.CTX_CERT_REQUEST;
+
+ public EnrollProfile mEnrollProfile = null;
+
+ public EncryptionKeyGenInput() {
+ addValueName(VAL_KEYGEN_REQUEST_TYPE);
+ addValueName(VAL_KEYGEN_REQUEST);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ mEnrollProfile = (EnrollProfile) profile;
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_ENC_KEY_GEN_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_ENC_KEY_GEN_TEXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ String keygen_request_type = ctx.get(VAL_KEYGEN_REQUEST_TYPE);
+ String keygen_request = ctx.get(VAL_KEYGEN_REQUEST);
+
+ X509CertInfo info =
+ request.getExtDataInCertInfo(EnrollProfile.REQUEST_CERTINFO);
+
+ if (keygen_request_type == null) {
+ CMS.debug("EncryptionKeyGenInput: populate - invalid cert request type " +
+ "");
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_UNKNOWN_CERT_REQ_TYPE",
+ ""));
+ }
+ if (keygen_request == null) {
+ CMS.debug("EncryptionKeyGenInput: populate - invalid certificate request");
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+ if (keygen_request_type.startsWith(EnrollProfile.REQ_TYPE_PKCS10)) {
+ PKCS10 pkcs10 = mEnrollProfile.parsePKCS10(getLocale(request), keygen_request);
+
+ if (pkcs10 == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+
+ mEnrollProfile.fillPKCS10(getLocale(request), pkcs10, info, request);
+ } else if (keygen_request_type.startsWith(EnrollProfile.REQ_TYPE_KEYGEN)) {
+ DerInputStream keygen = mEnrollProfile.parseKeyGen(getLocale(request), keygen_request);
+
+ if (keygen == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+
+ mEnrollProfile.fillKeyGen(getLocale(request), keygen, info, request);
+ } else if (keygen_request_type.startsWith(EnrollProfile.REQ_TYPE_CRMF)) {
+ CertReqMsg msgs[] = mEnrollProfile.parseCRMF(getLocale(request), keygen_request);
+
+ if (msgs == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+ for (int x = 0; x < msgs.length; x++) {
+ verifyPOP(getLocale(request), msgs[x]);
+ }
+ // This profile only handle the first request in CRMF
+ Integer seqNum = request.getExtDataInInteger(EnrollProfile.REQUEST_SEQ_NUM);
+
+ mEnrollProfile.fillCertReqMsg(getLocale(request), msgs[seqNum.intValue()], info, request);
+ } else if (keygen_request_type.startsWith(EnrollProfile.REQ_TYPE_CMC)) {
+ TaggedRequest msgs[] = mEnrollProfile.parseCMC(getLocale(request), keygen_request);
+
+ if (msgs == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+ // This profile only handle the first request in CRMF
+ Integer seqNum = request.getExtDataInInteger(EnrollProfile.REQUEST_SEQ_NUM);
+
+ if (seqNum == null) {
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_UNKNOWN_SEQ_NUM"));
+ }
+
+ mEnrollProfile.fillTaggedRequest(getLocale(request), msgs[seqNum.intValue()], info, request);
+ } else {
+ // error
+ CMS.debug("EncryptionKeyGenInput: populate - " +
+ "invalid cert request type " + keygen_request_type);
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_UNKNOWN_CERT_REQ_TYPE",
+ keygen_request_type));
+ }
+ request.setExtData(EnrollProfile.REQUEST_CERTINFO, info);
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_KEYGEN_REQUEST_TYPE)) {
+ return new Descriptor(IDescriptor.ENC_KEYGEN_REQUEST_TYPE, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_KEYGEN_REQ_TYPE"));
+ } else if (name.equals(VAL_KEYGEN_REQUEST)) {
+ return new Descriptor(IDescriptor.ENC_KEYGEN_REQUEST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_KEYGEN_REQ"));
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/EnrollInput.java b/base/server/cms/src/com/netscape/cms/profile/input/EnrollInput.java
new file mode 100644
index 000000000..b4ed31223
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/EnrollInput.java
@@ -0,0 +1,303 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.pkix.crmf.CertReqMsg;
+import org.mozilla.jss.pkix.crmf.ProofOfPossession;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the base enrollment input.
+ *
+ * @version $Revision$, $Date$
+ */
+public abstract class EnrollInput implements IProfileInput {
+
+ private final static String LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION =
+ "LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION_2";
+
+ protected IConfigStore mConfig = null;
+ protected Vector<String> mValueNames = new Vector<String>();
+ protected Vector<String> mConfigNames = new Vector<String>();
+ protected IProfile mProfile = null;
+
+ protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ mConfig = config;
+ mProfile = profile;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Populates the request with this policy default.
+ *
+ * @param ctx profile context
+ * @param request request
+ * @exception EProfileException failed to populate
+ */
+ public abstract void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException;
+
+ /**
+ * Retrieves the localizable name of this policy.
+ *
+ * @param locale user locale
+ * @return localized input name
+ */
+ public abstract String getName(Locale locale);
+
+ /**
+ * Retrieves the localizable description of this policy.
+ *
+ * @param locale user locale
+ * @return localized input description
+ */
+ public abstract String getText(Locale locale);
+
+ /**
+ * Retrieves the descriptor of the given value
+ * property by name.
+ *
+ * @param locale user locale
+ * @param name property name
+ * @return descriptor of the property
+ */
+ public abstract IDescriptor getValueDescriptor(Locale locale, String name);
+
+ public void addValueName(String name) {
+ mValueNames.addElement(name);
+ }
+
+ /**
+ * Retrieves a list of names of the value parameter.
+ */
+ public Enumeration<String> getValueNames() {
+ return mValueNames.elements();
+ }
+
+ public void addConfigName(String name) {
+ mConfigNames.addElement(name);
+ }
+
+ public Enumeration<String> getConfigNames() {
+ return mConfigNames.elements();
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ if (mConfig.getSubStore("params") == null) {
+ //
+ } else {
+ mConfig.getSubStore("params").putString(name, value);
+ }
+ }
+
+ public String getConfig(String name) {
+ try {
+ if (mConfig == null) {
+ return null;
+ }
+ if (mConfig.getSubStore("params") != null) {
+ return mConfig.getSubStore("params").getString(name);
+ }
+ } catch (EBaseException e) {
+ }
+ return "";
+ }
+
+ public String getDefaultConfig(String name) {
+ return null;
+ }
+
+ public String getValue(String name, Locale locale, IRequest request)
+ throws EProfileException {
+ return request.getExtDataInString(name);
+ }
+
+ /**
+ * Sets the value of the given value parameter by name.
+ */
+ public void setValue(String name, Locale locale, IRequest request,
+ String value) throws EPropertyException {
+ request.setExtData(name, value);
+ }
+
+ public Locale getLocale(IRequest request) {
+ Locale locale = null;
+ String language = request.getExtDataInString(
+ EnrollProfile.REQUEST_LOCALE);
+ if (language != null) {
+ locale = new Locale(language);
+ }
+ return locale;
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public void verifyPOP(Locale locale, CertReqMsg certReqMsg)
+ throws EProfileException {
+ CMS.debug("EnrollInput ::in verifyPOP");
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ if (!certReqMsg.hasPop()) {
+ CMS.debug("CertReqMsg has not POP, return");
+ return;
+ }
+ ProofOfPossession pop = certReqMsg.getPop();
+ ProofOfPossession.Type popType = pop.getType();
+
+ if (popType != ProofOfPossession.SIGNATURE) {
+ CMS.debug("not POP SIGNATURE, return");
+ return;
+ }
+
+ try {
+ if (CMS.getConfigStore().getBoolean("cms.skipPOPVerify", false)) {
+ CMS.debug("skipPOPVerify on, return");
+ return;
+ }
+ CMS.debug("POP verification begins:");
+ CryptoManager cm = CryptoManager.getInstance();
+
+ CryptoToken verifyToken = null;
+ String tokenName = CMS.getConfigStore().getString("ca.requestVerify.token", "internal");
+ if (tokenName.equals("internal")) {
+ CMS.debug("POP verification using internal token");
+ certReqMsg.verify();
+ } else {
+ CMS.debug("POP verification using token:" + tokenName);
+ verifyToken = cm.getTokenByName(tokenName);
+ certReqMsg.verify(verifyToken);
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION,
+ auditSubjectID,
+ ILogger.SUCCESS);
+ audit(auditMessage);
+ } catch (Exception e) {
+
+ CMS.debug("Failed POP verify! " + e.toString());
+ CMS.debug(e);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ throw new EProfileException(CMS.getUserMessage(locale,
+ "CMS_POP_VERIFICATION_ERROR"));
+ }
+ }
+
+ /**
+ * Signed Audit Log
+ *
+ * This method is inherited by all extended "CMSServlet"s,
+ * and is called to store messages to the signed audit log.
+ * <P>
+ *
+ * @param msg signed audit log message
+ */
+ protected void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+
+ if (mSignedAuditLogger == null) {
+ return;
+ }
+
+ mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+
+ /**
+ * Signed Audit Log Subject ID
+ *
+ * This method is inherited by all extended "CMSServlet"s,
+ * and is called to obtain the "SubjectID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @return id string containing the signed audit log message SubjectID
+ */
+ protected String auditSubjectID() {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String subjectID = null;
+
+ // Initialize subjectID
+ SessionContext auditContext = SessionContext.getExistingContext();
+
+ if (auditContext != null) {
+ subjectID = (String)
+ auditContext.get(SessionContext.USER_ID);
+
+ if (subjectID != null) {
+ subjectID = subjectID.trim();
+ } else {
+ subjectID = ILogger.NONROLEUSER;
+ }
+ } else {
+ subjectID = ILogger.UNIDENTIFIED;
+ }
+
+ return subjectID;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/FileSigningInput.java b/base/server/cms/src/com/netscape/cms/profile/input/FileSigningInput.java
new file mode 100644
index 000000000..f62a5964c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/FileSigningInput.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.io.BufferedInputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.MessageDigest;
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements the image
+ * input that collects a picture.
+ * <p>
+ *
+ * @version $Revision$, $Date$
+ */
+public class FileSigningInput extends EnrollInput implements IProfileInput {
+
+ public static final String URL = "file_signing_url";
+ public static final String TEXT = "file_signing_text";
+ public static final String SIZE = "file_signing_size";
+ public static final String DIGEST = "file_signing_digest";
+ public static final String DIGEST_TYPE = "file_signing_digest_type";
+
+ public FileSigningInput() {
+ addValueName(URL);
+ addValueName(TEXT);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_FILE_SIGNING_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_FILE_SIGNING_TEXT");
+ }
+
+ public String toHexString(byte data[]) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < data.length; i++) {
+ int v = data[i] & 0xff;
+ if (v < 16) {
+ sb.append("0");
+ }
+ sb.append(Integer.toHexString(v));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ request.setExtData(TEXT, ctx.get(TEXT));
+ request.setExtData(URL, ctx.get(URL));
+ request.setExtData(DIGEST_TYPE, "SHA256");
+
+ try {
+ // retrieve file and calculate the hash
+ URL url = new URL(ctx.get(URL));
+ URLConnection c = url.openConnection();
+ c.setAllowUserInteraction(false);
+ c.setDoInput(true);
+ c.setDoOutput(false);
+ c.setUseCaches(false);
+ c.connect();
+ int len = c.getContentLength();
+ request.setExtData(SIZE, Integer.toString(len));
+ BufferedInputStream is = new BufferedInputStream(c.getInputStream());
+ byte data[] = new byte[len];
+ is.read(data, 0, len);
+ is.close();
+
+ // calculate digest
+ MessageDigest digester = MessageDigest.getInstance("SHA256");
+ byte digest[] = digester.digest(data);
+ request.setExtData(DIGEST, toHexString(digest));
+ } catch (Exception e) {
+ CMS.debug("FileSigningInput populate failure " + e);
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_FILE_NOT_FOUND"));
+ }
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(URL)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_FILE_SIGNING_URL"));
+ } else if (name.equals(TEXT)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_FILE_SIGNING_TEXT"));
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/GenericInput.java b/base/server/cms/src/com/netscape/cms/profile/input/GenericInput.java
new file mode 100644
index 000000000..e92fbe93e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/GenericInput.java
@@ -0,0 +1,160 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements a generic input.
+ * <p>
+ *
+ * @version $Revision$, $Date$
+ */
+public class GenericInput extends EnrollInput implements IProfileInput {
+
+ public static final String CONFIG_NUM = "gi_num";
+ public static final String CONFIG_DISPLAY_NAME = "gi_display_name";
+ public static final String CONFIG_PARAM_NAME = "gi_param_name";
+ public static final String CONFIG_ENABLE = "gi_param_enable";
+
+ public static final int DEF_NUM = 5;
+
+ public GenericInput() {
+ int num = getNum();
+ for (int i = 0; i < num; i++) {
+ addConfigName(CONFIG_PARAM_NAME + i);
+ addConfigName(CONFIG_DISPLAY_NAME + i);
+ addConfigName(CONFIG_ENABLE + i);
+ }
+ }
+
+ protected int getNum() {
+ int num = DEF_NUM;
+ String numC = getConfig(CONFIG_NUM);
+
+ if (numC != null) {
+ try {
+ num = Integer.parseInt(numC);
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ }
+ return num;
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_GENERIC_NAME_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_GENERIC_NAME_TEXT");
+ }
+
+ /**
+ * Returns selected value names based on the configuration.
+ */
+ public Enumeration<String> getValueNames() {
+ Vector<String> v = new Vector<String>();
+ int num = getNum();
+ for (int i = 0; i < num; i++) {
+ String enable = getConfig(CONFIG_ENABLE + i);
+ if (enable != null && enable.equals("true")) {
+ v.addElement(getConfig(CONFIG_PARAM_NAME + i));
+ }
+ }
+ return v.elements();
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ int num = getNum();
+ for (int i = 0; i < num; i++) {
+ String enable = getConfig(CONFIG_ENABLE + i);
+ if (enable != null && enable.equals("true")) {
+ String param = getConfig(CONFIG_PARAM_NAME + i);
+ request.setExtData(param, ctx.get(param));
+ }
+ }
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ int num = getNum();
+ for (int i = 0; i < num; i++) {
+ if (name.equals(CONFIG_PARAM_NAME + i)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_GI_PARAM_NAME") + i);
+ } else if (name.equals(CONFIG_DISPLAY_NAME + i)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_GI_DISPLAY_NAME") + i);
+ } else if (name.equals(CONFIG_ENABLE + i)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "false",
+ CMS.getUserMessage(locale, "CMS_PROFILE_GI_ENABLE") + i);
+ }
+ } // for
+ return null;
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ int num = getNum();
+ for (int i = 0; i < num; i++) {
+ String param = getConfig(CONFIG_PARAM_NAME + i);
+ if (param != null && param.equals(name)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ getConfig(CONFIG_DISPLAY_NAME + i));
+ }
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/ImageInput.java b/base/server/cms/src/com/netscape/cms/profile/input/ImageInput.java
new file mode 100644
index 000000000..5874cc07f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/ImageInput.java
@@ -0,0 +1,89 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements the image
+ * input that collects a picture.
+ * <p>
+ *
+ * @version $Revision$, $Date$
+ */
+public class ImageInput extends EnrollInput implements IProfileInput {
+
+ public static final String IMAGE_URL = "image_url";
+
+ public ImageInput() {
+ addValueName(IMAGE_URL);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_IMAGE_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_IMAGE_TEXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ request.setExtData(IMAGE_URL, ctx.get(IMAGE_URL));
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(IMAGE_URL)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_IMAGE_URL"));
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/KeyGenInput.java b/base/server/cms/src/com/netscape/cms/profile/input/KeyGenInput.java
new file mode 100644
index 000000000..1b3564ab7
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/KeyGenInput.java
@@ -0,0 +1,189 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Locale;
+
+import netscape.security.pkcs.PKCS10;
+import netscape.security.util.DerInputStream;
+import netscape.security.x509.X509CertInfo;
+
+import org.mozilla.jss.pkix.cmc.TaggedRequest;
+import org.mozilla.jss.pkix.crmf.CertReqMsg;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the key generation input that
+ * populates parameters to the enrollment page for
+ * key generation.
+ * <p>
+ *
+ * This input normally is used with user-based or non certificate request profile.
+ * <p>
+ *
+ * @version $Revision$, $Date$
+ */
+public class KeyGenInput extends EnrollInput implements IProfileInput {
+
+ public static final String VAL_KEYGEN_REQUEST_TYPE =
+ EnrollProfile.CTX_CERT_REQUEST_TYPE;
+ public static final String VAL_KEYGEN_REQUEST =
+ EnrollProfile.CTX_CERT_REQUEST;
+
+ public EnrollProfile mEnrollProfile = null;
+
+ public KeyGenInput() {
+ addValueName(VAL_KEYGEN_REQUEST_TYPE);
+ addValueName(VAL_KEYGEN_REQUEST);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ mEnrollProfile = (EnrollProfile) profile;
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_KEY_GEN_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_KEY_GEN_TEXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ String keygen_request_type = ctx.get(VAL_KEYGEN_REQUEST_TYPE);
+ String keygen_request = ctx.get(VAL_KEYGEN_REQUEST);
+
+ X509CertInfo info =
+ request.getExtDataInCertInfo(EnrollProfile.REQUEST_CERTINFO);
+
+ if (keygen_request_type == null) {
+ CMS.debug("KeyGenInput: populate - invalid cert request type " +
+ "");
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_UNKNOWN_CERT_REQ_TYPE",
+ ""));
+ }
+ if (keygen_request == null) {
+ CMS.debug("KeyGenInput: populate - invalid certificate request");
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+ if (keygen_request_type.startsWith(EnrollProfile.REQ_TYPE_PKCS10)) {
+ PKCS10 pkcs10 = mEnrollProfile.parsePKCS10(getLocale(request), keygen_request);
+
+ if (pkcs10 == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+
+ mEnrollProfile.fillPKCS10(getLocale(request), pkcs10, info, request);
+ } else if (keygen_request_type.startsWith(EnrollProfile.REQ_TYPE_KEYGEN)) {
+ DerInputStream keygen = mEnrollProfile.parseKeyGen(getLocale(request), keygen_request);
+
+ if (keygen == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+
+ mEnrollProfile.fillKeyGen(getLocale(request), keygen, info, request);
+ } else if (keygen_request_type.startsWith(EnrollProfile.REQ_TYPE_CRMF)) {
+ CertReqMsg msgs[] = mEnrollProfile.parseCRMF(getLocale(request), keygen_request);
+
+ if (msgs == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+ for (int x = 0; x < msgs.length; x++) {
+ verifyPOP(getLocale(request), msgs[x]);
+ }
+ // This profile only handle the first request in CRMF
+ Integer seqNum = request.getExtDataInInteger(EnrollProfile.REQUEST_SEQ_NUM);
+
+ mEnrollProfile.fillCertReqMsg(getLocale(request), msgs[seqNum.intValue()], info, request);
+ } else if (keygen_request_type.startsWith(EnrollProfile.REQ_TYPE_CMC)) {
+ TaggedRequest msgs[] = mEnrollProfile.parseCMC(getLocale(request), keygen_request);
+
+ if (msgs == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+ // This profile only handle the first request in CRMF
+ Integer seqNum = request.getExtDataInInteger(EnrollProfile.REQUEST_SEQ_NUM);
+
+ if (seqNum == null) {
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_UNKNOWN_SEQ_NUM"));
+ }
+
+ mEnrollProfile.fillTaggedRequest(getLocale(request), msgs[seqNum.intValue()], info, request);
+ } else {
+ // error
+ CMS.debug("DualKeyGenInput: populate - " +
+ "invalid cert request type " + keygen_request_type);
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_UNKNOWN_CERT_REQ_TYPE",
+ keygen_request_type));
+ }
+ request.setExtData(EnrollProfile.REQUEST_CERTINFO, info);
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_KEYGEN_REQUEST_TYPE)) {
+ return new Descriptor(IDescriptor.KEYGEN_REQUEST_TYPE, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_KEYGEN_REQ_TYPE"));
+ } else if (name.equals(VAL_KEYGEN_REQUEST)) {
+ return new Descriptor(IDescriptor.KEYGEN_REQUEST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_KEYGEN_REQ"));
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/SerialNumRenewInput.java b/base/server/cms/src/com/netscape/cms/profile/input/SerialNumRenewInput.java
new file mode 100644
index 000000000..c2566139a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/SerialNumRenewInput.java
@@ -0,0 +1,89 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements the serial number input
+ * for renewal
+ * <p>
+ *
+ * @author Christina Fu
+ */
+public class SerialNumRenewInput extends EnrollInput implements IProfileInput {
+
+ public static final String SERIAL_NUM = "serial_num";
+
+ public SerialNumRenewInput() {
+ addValueName(SERIAL_NUM);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SERIAL_NUM_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SERIAL_NUM_TEXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ //
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(SERIAL_NUM)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SERIAL_NUM_NAME"));
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/SigningKeyGenInput.java b/base/server/cms/src/com/netscape/cms/profile/input/SigningKeyGenInput.java
new file mode 100644
index 000000000..6ee2fd42e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/SigningKeyGenInput.java
@@ -0,0 +1,189 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Locale;
+
+import netscape.security.pkcs.PKCS10;
+import netscape.security.util.DerInputStream;
+import netscape.security.x509.X509CertInfo;
+
+import org.mozilla.jss.pkix.cmc.TaggedRequest;
+import org.mozilla.jss.pkix.crmf.CertReqMsg;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the key generation input that
+ * populates parameters to the enrollment page for
+ * key generation.
+ * <p>
+ *
+ * This input normally is used with user-based or non certificate request profile.
+ * <p>
+ *
+ * @version $Revision$, $Date$
+ */
+public class SigningKeyGenInput extends EnrollInput implements IProfileInput {
+
+ public static final String VAL_KEYGEN_REQUEST_TYPE =
+ EnrollProfile.CTX_CERT_REQUEST_TYPE;
+ public static final String VAL_KEYGEN_REQUEST =
+ EnrollProfile.CTX_CERT_REQUEST;
+
+ public EnrollProfile mEnrollProfile = null;
+
+ public SigningKeyGenInput() {
+ addValueName(VAL_KEYGEN_REQUEST_TYPE);
+ addValueName(VAL_KEYGEN_REQUEST);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ mEnrollProfile = (EnrollProfile) profile;
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SIGN_KEY_GEN_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SIGN_KEY_GEN_TEXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ String keygen_request_type = ctx.get(VAL_KEYGEN_REQUEST_TYPE);
+ String keygen_request = ctx.get(VAL_KEYGEN_REQUEST);
+
+ X509CertInfo info =
+ request.getExtDataInCertInfo(EnrollProfile.REQUEST_CERTINFO);
+
+ if (keygen_request_type == null) {
+ CMS.debug("SigningKeyGenInput: populate - invalid cert request type " +
+ "");
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_UNKNOWN_CERT_REQ_TYPE",
+ ""));
+ }
+ if (keygen_request == null) {
+ CMS.debug("SigningKeyGenInput: populate - invalid certificate request");
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+ if (keygen_request_type.startsWith(EnrollProfile.REQ_TYPE_PKCS10)) {
+ PKCS10 pkcs10 = mEnrollProfile.parsePKCS10(getLocale(request), keygen_request);
+
+ if (pkcs10 == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+
+ mEnrollProfile.fillPKCS10(getLocale(request), pkcs10, info, request);
+ } else if (keygen_request_type.startsWith(EnrollProfile.REQ_TYPE_KEYGEN)) {
+ DerInputStream keygen = mEnrollProfile.parseKeyGen(getLocale(request), keygen_request);
+
+ if (keygen == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+
+ mEnrollProfile.fillKeyGen(getLocale(request), keygen, info, request);
+ } else if (keygen_request_type.startsWith(EnrollProfile.REQ_TYPE_CRMF)) {
+ CertReqMsg msgs[] = mEnrollProfile.parseCRMF(getLocale(request), keygen_request);
+
+ if (msgs == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+ for (int x = 0; x < msgs.length; x++) {
+ verifyPOP(getLocale(request), msgs[x]);
+ }
+ // This profile only handle the first request in CRMF
+ Integer seqNum = request.getExtDataInInteger(EnrollProfile.REQUEST_SEQ_NUM);
+
+ mEnrollProfile.fillCertReqMsg(getLocale(request), msgs[seqNum.intValue()], info, request);
+ } else if (keygen_request_type.startsWith(EnrollProfile.REQ_TYPE_CMC)) {
+ TaggedRequest msgs[] = mEnrollProfile.parseCMC(getLocale(request), keygen_request);
+
+ if (msgs == null) {
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
+ }
+ // This profile only handle the first request in CRMF
+ Integer seqNum = request.getExtDataInInteger(EnrollProfile.REQUEST_SEQ_NUM);
+
+ if (seqNum == null) {
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_UNKNOWN_SEQ_NUM"));
+ }
+
+ mEnrollProfile.fillTaggedRequest(getLocale(request), msgs[seqNum.intValue()], info, request);
+ } else {
+ // error
+ CMS.debug("SigningKeyGenInput: populate - " +
+ "invalid cert request type " + keygen_request_type);
+ throw new EProfileException(CMS.getUserMessage(
+ getLocale(request),
+ "CMS_PROFILE_UNKNOWN_CERT_REQ_TYPE",
+ keygen_request_type));
+ }
+ request.setExtData(EnrollProfile.REQUEST_CERTINFO, info);
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_KEYGEN_REQUEST_TYPE)) {
+ return new Descriptor(IDescriptor.SIGN_KEYGEN_REQUEST_TYPE, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_KEYGEN_REQ_TYPE"));
+ } else if (name.equals(VAL_KEYGEN_REQUEST)) {
+ return new Descriptor(IDescriptor.SIGN_KEYGEN_REQUEST, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_KEYGEN_REQ"));
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/SubjectDNInput.java b/base/server/cms/src/com/netscape/cms/profile/input/SubjectDNInput.java
new file mode 100644
index 000000000..a12351f8a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/SubjectDNInput.java
@@ -0,0 +1,142 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This plugin accepts subject DN from end user.
+ */
+public class SubjectDNInput extends EnrollInput implements IProfileInput {
+
+ public static final String VAL_SUBJECT = "subject";
+
+ public SubjectDNInput() {
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SUBJECT_NAME_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SUBJECT_NAME_TEXT");
+ }
+
+ public String getConfig(String name) {
+ String config = super.getConfig(name);
+ if (config == null || config.equals(""))
+ return "true";
+ return config;
+ }
+
+ /**
+ * Returns selected value names based on the configuration.
+ */
+ public Enumeration<String> getValueNames() {
+ Vector<String> v = new Vector<String>();
+ v.addElement(VAL_SUBJECT);
+ return v.elements();
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ X509CertInfo info =
+ request.getExtDataInCertInfo(EnrollProfile.REQUEST_CERTINFO);
+ String subjectName = "";
+
+ subjectName = ctx.get(VAL_SUBJECT);
+ if (subjectName.equals("")) {
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_SUBJECT_NAME_NOT_FOUND"));
+ }
+ X500Name name = null;
+
+ try {
+ name = new X500Name(subjectName);
+ } catch (Exception e) {
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_INVALID_SUBJECT_NAME", subjectName));
+ }
+ parseSubjectName(name, info, request);
+ request.setExtData(EnrollProfile.REQUEST_CERTINFO, info);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_SUBJECT)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SUBJECT_NAME"));
+ }
+ return null;
+ }
+
+ protected void parseSubjectName(X500Name subj, X509CertInfo info, IRequest req)
+ throws EProfileException {
+ try {
+ req.setExtData(EnrollProfile.REQUEST_SUBJECT_NAME,
+ new CertificateSubjectName(subj));
+ } catch (Exception e) {
+ CMS.debug("SubjectNameInput: parseSubject Name " +
+ e.toString());
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/SubjectNameInput.java b/base/server/cms/src/com/netscape/cms/profile/input/SubjectNameInput.java
new file mode 100644
index 000000000..2c0de4486
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/SubjectNameInput.java
@@ -0,0 +1,382 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the subject name input
+ * that populates text fields to the enrollment
+ * page so that distinguished name parameters
+ * can be collected from the user.
+ * <p>
+ * The collected parameters could be used for fomulating the subject name in the certificate.
+ * <p>
+ *
+ * @version $Revision$, $Date$
+ */
+public class SubjectNameInput extends EnrollInput implements IProfileInput {
+
+ public static final String CONFIG_UID = "sn_uid";
+ public static final String CONFIG_EMAIL = "sn_e";
+ public static final String CONFIG_CN = "sn_cn";
+ public static final String CONFIG_OU3 = "sn_ou3";
+ public static final String CONFIG_OU2 = "sn_ou2";
+ public static final String CONFIG_OU1 = "sn_ou1";
+ public static final String CONFIG_OU = "sn_ou";
+ public static final String CONFIG_O = "sn_o";
+ public static final String CONFIG_C = "sn_c";
+
+ public static final String VAL_UID = "sn_uid";
+ public static final String VAL_EMAIL = "sn_e";
+ public static final String VAL_CN = "sn_cn";
+ public static final String VAL_OU3 = "sn_ou3";
+ public static final String VAL_OU2 = "sn_ou2";
+ public static final String VAL_OU1 = "sn_ou1";
+ public static final String VAL_OU = "sn_ou";
+ public static final String VAL_O = "sn_o";
+ public static final String VAL_C = "sn_c";
+
+ public SubjectNameInput() {
+ addConfigName(CONFIG_UID);
+ addConfigName(CONFIG_EMAIL);
+ addConfigName(CONFIG_CN);
+ addConfigName(CONFIG_OU3);
+ addConfigName(CONFIG_OU2);
+ addConfigName(CONFIG_OU1);
+ addConfigName(CONFIG_OU);
+ addConfigName(CONFIG_O);
+ addConfigName(CONFIG_C);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SUBJECT_NAME_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SUBJECT_NAME_TEXT");
+ }
+
+ public String getConfig(String name) {
+ String config = super.getConfig(name);
+ if (config == null || config.equals(""))
+ return "true";
+ return config;
+ }
+
+ /**
+ * Returns selected value names based on the configuration.
+ */
+ public Enumeration<String> getValueNames() {
+ Vector<String> v = new Vector<String>();
+ String c_uid = getConfig(CONFIG_UID);
+ if (c_uid == null || c_uid.equals("")) {
+ v.addElement(VAL_UID); // default case
+ } else {
+ if (c_uid.equals("true")) {
+ v.addElement(VAL_UID);
+ }
+ }
+ String c_email = getConfig(CONFIG_EMAIL);
+ if (c_email == null || c_email.equals("")) {
+ v.addElement(VAL_EMAIL);
+ } else {
+ if (c_email.equals("true")) {
+ v.addElement(VAL_EMAIL);
+ }
+ }
+ String c_cn = getConfig(CONFIG_CN);
+ if (c_cn == null || c_cn.equals("")) {
+ v.addElement(VAL_CN);
+ } else {
+ if (c_cn.equals("true")) {
+ v.addElement(VAL_CN);
+ }
+ }
+ String c_ou3 = getConfig(CONFIG_OU3);
+ if (c_ou3 == null || c_ou3.equals("")) {
+ v.addElement(VAL_OU3);
+ } else {
+ if (c_ou3.equals("true")) {
+ v.addElement(VAL_OU3);
+ }
+ }
+ String c_ou2 = getConfig(CONFIG_OU2);
+ if (c_ou2 == null || c_ou2.equals("")) {
+ v.addElement(VAL_OU2);
+ } else {
+ if (c_ou2.equals("true")) {
+ v.addElement(VAL_OU2);
+ }
+ }
+ String c_ou1 = getConfig(CONFIG_OU1);
+ if (c_ou1 == null || c_ou1.equals("")) {
+ v.addElement(VAL_OU1);
+ } else {
+ if (c_ou1.equals("true")) {
+ v.addElement(VAL_OU1);
+ }
+ }
+ String c_ou = getConfig(CONFIG_OU);
+ if (c_ou == null || c_ou.equals("")) {
+ v.addElement(VAL_OU);
+ } else {
+ if (c_ou.equals("true")) {
+ v.addElement(VAL_OU);
+ }
+ }
+ String c_o = getConfig(CONFIG_O);
+ if (c_o == null || c_o.equals("")) {
+ v.addElement(VAL_O);
+ } else {
+ if (c_o.equals("true")) {
+ v.addElement(VAL_O);
+ }
+ }
+ String c_c = getConfig(CONFIG_C);
+ if (c_c == null || c_c.equals("")) {
+ v.addElement(VAL_C);
+ } else {
+ if (c_c.equals("true")) {
+ v.addElement(VAL_C);
+ }
+ }
+ return v.elements();
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ X509CertInfo info =
+ request.getExtDataInCertInfo(EnrollProfile.REQUEST_CERTINFO);
+ String subjectName = "";
+
+ String uid = ctx.get(VAL_UID);
+
+ if (uid != null && !uid.equals("")) {
+ subjectName += "UID=" + uid;
+ }
+ String email = ctx.get(VAL_EMAIL);
+
+ if (email != null && !email.equals("")) {
+ if (!subjectName.equals("")) {
+ subjectName += ",";
+ }
+ subjectName += "E=" + email;
+ }
+ String cn = ctx.get(VAL_CN);
+
+ if (cn != null && !cn.equals("")) {
+ if (!subjectName.equals("")) {
+ subjectName += ",";
+ }
+ subjectName += "CN=" + cn;
+ }
+ String ou3 = ctx.get(VAL_OU3);
+ if (ou3 != null && !ou3.equals("")) {
+ if (!subjectName.equals("")) {
+ subjectName += ",";
+ }
+ subjectName += "OU=" + ou3;
+ }
+ String ou2 = ctx.get(VAL_OU2);
+ if (ou2 != null && !ou2.equals("")) {
+ if (!subjectName.equals("")) {
+ subjectName += ",";
+ }
+ subjectName += "OU=" + ou2;
+ }
+ String ou1 = ctx.get(VAL_OU1);
+ if (ou1 != null && !ou1.equals("")) {
+ if (!subjectName.equals("")) {
+ subjectName += ",";
+ }
+ subjectName += "OU=" + ou1;
+ }
+ String ou = ctx.get(VAL_OU);
+ if (ou != null && !ou.equals("")) {
+ if (!subjectName.equals("")) {
+ subjectName += ",";
+ }
+ subjectName += "OU=" + ou;
+ }
+ String o = ctx.get(VAL_O);
+
+ if (o != null && !o.equals("")) {
+ if (!subjectName.equals("")) {
+ subjectName += ",";
+ }
+ subjectName += "O=" + o;
+ }
+ String c = ctx.get(VAL_C);
+
+ if (c != null && !c.equals("")) {
+ if (!subjectName.equals("")) {
+ subjectName += ",";
+ }
+ subjectName += "C=" + c;
+ }
+ if (subjectName.equals("")) {
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_SUBJECT_NAME_NOT_FOUND"));
+ }
+ X500Name name = null;
+
+ try {
+ name = new X500Name(subjectName);
+ } catch (Exception e) {
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_INVALID_SUBJECT_NAME", subjectName));
+ }
+ parseSubjectName(name, info, request);
+ request.setExtData(EnrollProfile.REQUEST_CERTINFO, info);
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ if (name.equals(CONFIG_UID)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "true",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_UID"));
+ } else if (name.equals(CONFIG_EMAIL)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "true",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_UID"));
+ } else if (name.equals(CONFIG_CN)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "true",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_CN"));
+ } else if (name.equals(CONFIG_OU3)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "true",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_OU"));
+ } else if (name.equals(CONFIG_OU2)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "true",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_OU"));
+ } else if (name.equals(CONFIG_OU1)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "true",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_OU"));
+ } else if (name.equals(CONFIG_OU)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "true",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_OU"));
+ } else if (name.equals(CONFIG_O)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "true",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_O"));
+ } else if (name.equals(CONFIG_C)) {
+ return new Descriptor(IDescriptor.BOOLEAN, null,
+ "true",
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_C"));
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_UID)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_UID"));
+ } else if (name.equals(VAL_EMAIL)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_EMAIL"));
+ } else if (name.equals(VAL_CN)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_CN"));
+ } else if (name.equals(VAL_OU3)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_OU") + " 3");
+ } else if (name.equals(VAL_OU2)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_OU") + " 2");
+ } else if (name.equals(VAL_OU1)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_OU") + " 1");
+ } else if (name.equals(VAL_OU)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_OU"));
+ } else if (name.equals(VAL_O)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_O"));
+ } else if (name.equals(VAL_C)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_SN_C"));
+ }
+ return null;
+ }
+
+ protected void parseSubjectName(X500Name subj, X509CertInfo info, IRequest req)
+ throws EProfileException {
+ try {
+ req.setExtData(EnrollProfile.REQUEST_SUBJECT_NAME,
+ new CertificateSubjectName(subj));
+ } catch (Exception e) {
+ CMS.debug("SubjectNameInput: parseSubject Name " +
+ e.toString());
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/SubmitterInfoInput.java b/base/server/cms/src/com/netscape/cms/profile/input/SubmitterInfoInput.java
new file mode 100644
index 000000000..e15e13e91
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/SubmitterInfoInput.java
@@ -0,0 +1,102 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements the submitter information
+ * input that collects certificate requestor's
+ * information such as name, email and phone.
+ * <p>
+ *
+ * @version $Revision$, $Date$
+ */
+public class SubmitterInfoInput extends EnrollInput implements IProfileInput {
+
+ public static final String NAME = "requestor_name";
+ public static final String EMAIL = "requestor_email";
+ public static final String PHONE = "requestor_phone";
+
+ public SubmitterInfoInput() {
+ addValueName(NAME);
+ addValueName(EMAIL);
+ addValueName(PHONE);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SUBMITTER_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SUBMITTER_TEXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ //
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(NAME)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_REQUESTOR_NAME"));
+ } else if (name.equals(EMAIL)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_REQUESTOR_EMAIL"));
+ } else if (name.equals(PHONE)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale, "CMS_PROFILE_REQUESTOR_PHONE"));
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/nsHKeyCertReqInput.java b/base/server/cms/src/com/netscape/cms/profile/input/nsHKeyCertReqInput.java
new file mode 100644
index 000000000..15f296a9e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/nsHKeyCertReqInput.java
@@ -0,0 +1,160 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Locale;
+
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the certificate request input from TPS.
+ * This input populates 2 main fields to the enrollment "page":
+ * 1/ token cuid, 2/ publickey
+ * <p>
+ *
+ * This input usually is used by an enrollment profile for certificate requests coming from TPS.
+ *
+ * @version $Revision$, $Date$
+ */
+public class nsHKeyCertReqInput extends EnrollInput implements IProfileInput {
+ public static final String VAL_TOKEN_CUID = "tokencuid";
+ public static final String VAL_PUBLIC_KEY = "publickey";
+
+ public EnrollProfile mEnrollProfile = null;
+
+ public nsHKeyCertReqInput() {
+ addValueName(VAL_TOKEN_CUID);
+ addValueName(VAL_PUBLIC_KEY);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+
+ mEnrollProfile = (EnrollProfile) profile;
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_TOKENKEY_CERT_REQ_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_TOKENKEY_CERT_REQ_TEXT");
+ }
+
+ /*
+ * Pretty print token cuid
+ */
+ public String toPrettyPrint(String cuid) {
+ if (cuid == null)
+ return null;
+
+ if (cuid.length() != 20)
+ return null;
+
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < cuid.length(); i++) {
+ if (i == 4 || i == 8 || i == 12 || i == 16) {
+ sb.append("-");
+ }
+ sb.append(cuid.charAt(i));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ String tcuid = ctx.get(VAL_TOKEN_CUID);
+ // pretty print tcuid
+ String prettyPrintCuid = toPrettyPrint(tcuid);
+ if (prettyPrintCuid == null) {
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_TOKENKEY_NO_TOKENCUID",
+ ""));
+ }
+
+ request.setExtData("pretty_print_tokencuid", prettyPrintCuid);
+
+ String pk = ctx.get(VAL_PUBLIC_KEY);
+ X509CertInfo info =
+ request.getExtDataInCertInfo(EnrollProfile.REQUEST_CERTINFO);
+
+ if (tcuid == null) {
+ CMS.debug("nsHKeyCertReqInput: populate - tokencuid not found " +
+ "");
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_TOKENKEY_NO_TOKENCUID",
+ ""));
+ }
+ if (pk == null) {
+ CMS.debug("nsHKeyCertReqInput: populate - public key not found " +
+ "");
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_TOKENKEY_NO_PUBLIC_KEY",
+ ""));
+ }
+
+ mEnrollProfile.fillNSHKEY(getLocale(request), tcuid, pk, info, request);
+ request.setExtData(EnrollProfile.REQUEST_CERTINFO, info);
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_TOKEN_CUID)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_INPUT_TOKENKEY_CERT_REQ_TOKEN_CUID"));
+ } else if (name.equals(VAL_PUBLIC_KEY)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_INPUT_TOKENKEY_CERT_REQ_PK"));
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/nsNKeyCertReqInput.java b/base/server/cms/src/com/netscape/cms/profile/input/nsNKeyCertReqInput.java
new file mode 100644
index 000000000..f14df1a80
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/input/nsNKeyCertReqInput.java
@@ -0,0 +1,129 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.input;
+
+import java.util.Locale;
+
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the certificate request input from TPS.
+ * This input populates 2 main fields to the enrollment "page":
+ * 1/ id, 2/ publickey
+ * <p>
+ *
+ * This input usually is used by an enrollment profile for certificate requests coming from TPS.
+ *
+ * @version $Revision$, $Date$
+ */
+public class nsNKeyCertReqInput extends EnrollInput implements IProfileInput {
+ public static final String VAL_SN = "screenname";
+ public static final String VAL_PUBLIC_KEY = "publickey";
+
+ public EnrollProfile mEnrollProfile = null;
+
+ public nsNKeyCertReqInput() {
+ addValueName(VAL_SN);
+ addValueName(VAL_PUBLIC_KEY);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+
+ mEnrollProfile = (EnrollProfile) profile;
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_TOKENKEY_CERT_REQ_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_TOKENKEY_CERT_REQ_TEXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ String sn = ctx.get(VAL_SN);
+ String pk = ctx.get(VAL_PUBLIC_KEY);
+ X509CertInfo info =
+ request.getExtDataInCertInfo(EnrollProfile.REQUEST_CERTINFO);
+
+ if (sn == null) {
+ CMS.debug("nsNKeyCertReqInput: populate - id not found " +
+ "");
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_TOKENKEY_NO_ID",
+ ""));
+ }
+ if (pk == null) {
+ CMS.debug("nsNKeyCertReqInput: populate - public key not found " +
+ "");
+ throw new EProfileException(
+ CMS.getUserMessage(getLocale(request),
+ "CMS_PROFILE_TOKENKEY_NO_PUBLIC_KEY",
+ ""));
+ }
+
+ mEnrollProfile.fillNSNKEY(getLocale(request), sn, pk, info, request);
+ request.setExtData(EnrollProfile.REQUEST_CERTINFO, info);
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_SN)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_INPUT_TOKENKEY_CERT_REQ_UID"));
+ } else if (name.equals(VAL_PUBLIC_KEY)) {
+ return new Descriptor(IDescriptor.STRING, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_INPUT_TOKENKEY_CERT_REQ_PK"));
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/output/CMMFOutput.java b/base/server/cms/src/com/netscape/cms/profile/output/CMMFOutput.java
new file mode 100644
index 000000000..9c04e6962
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/output/CMMFOutput.java
@@ -0,0 +1,161 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.output;
+
+import java.io.ByteArrayOutputStream;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.X509CertImpl;
+
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.pkix.cmmf.CertOrEncCert;
+import org.mozilla.jss.pkix.cmmf.CertRepContent;
+import org.mozilla.jss.pkix.cmmf.CertResponse;
+import org.mozilla.jss.pkix.cmmf.CertifiedKeyPair;
+import org.mozilla.jss.pkix.cmmf.PKIStatusInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.ICertPrettyPrint;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileOutput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the output plugin that outputs
+ * CMMF response for the issued certificate.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMMFOutput extends EnrollOutput implements IProfileOutput {
+
+ public static final String VAL_PRETTY_CERT = "pretty_cert";
+ public static final String VAL_CMMF_RESPONSE = "cmmf_response";
+
+ public CMMFOutput() {
+ addValueName(VAL_PRETTY_CERT);
+ addValueName(VAL_CMMF_RESPONSE);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_OUTPUT_CERT_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_OUTPUT_CERT_TEXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_PRETTY_CERT)) {
+ return new Descriptor(IDescriptor.PRETTY_PRINT, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_OUTPUT_CERT_PP"));
+ } else if (name.equals(VAL_CMMF_RESPONSE)) {
+ return new Descriptor(IDescriptor.PRETTY_PRINT, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_OUTPUT_CMMF_B64"));
+ }
+ return null;
+ }
+
+ public String getValue(String name, Locale locale, IRequest request)
+ throws EProfileException {
+ if (name.equals(VAL_PRETTY_CERT)) {
+ X509CertImpl cert = request.getExtDataInCert(
+ EnrollProfile.REQUEST_ISSUED_CERT);
+ ICertPrettyPrint prettyCert = CMS.getCertPrettyPrint(cert);
+
+ return prettyCert.toString(locale);
+ } else if (name.equals(VAL_CMMF_RESPONSE)) {
+ try {
+ X509CertImpl cert = request.getExtDataInCert(
+ EnrollProfile.REQUEST_ISSUED_CERT);
+ if (cert == null)
+ return null;
+
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem("ca");
+ CertificateChain cachain = ca.getCACertChain();
+ X509Certificate[] cacerts = cachain.getChain();
+
+ byte[][] caPubs = new byte[cacerts.length][];
+
+ for (int j = 0; j < cacerts.length; j++) {
+ caPubs[j] = ((X509CertImpl) cacerts[j]).getEncoded();
+ }
+
+ CertRepContent certRepContent = null;
+ certRepContent = new CertRepContent(caPubs);
+
+ PKIStatusInfo status = new PKIStatusInfo(PKIStatusInfo.granted);
+ CertifiedKeyPair certifiedKP =
+ new CertifiedKeyPair(new CertOrEncCert(cert.getEncoded()));
+ CertResponse resp =
+ new CertResponse(new INTEGER(request.getRequestId().toString()),
+ status, certifiedKP);
+ certRepContent.addCertResponse(resp);
+
+ ByteArrayOutputStream certRepOut = new ByteArrayOutputStream();
+ certRepContent.encode(certRepOut);
+ byte[] certRepBytes = certRepOut.toByteArray();
+
+ return CMS.BtoA(certRepBytes);
+ } catch (Exception e) {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/output/CertOutput.java b/base/server/cms/src/com/netscape/cms/profile/output/CertOutput.java
new file mode 100644
index 000000000..a556d4a44
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/output/CertOutput.java
@@ -0,0 +1,120 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.output;
+
+import java.util.Locale;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.ICertPrettyPrint;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileOutput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the pretty print certificate output
+ * that displays the issued certificate in a pretty print format.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CertOutput extends EnrollOutput implements IProfileOutput {
+ public static final String VAL_PRETTY_CERT = "pretty_cert";
+ public static final String VAL_B64_CERT = "b64_cert";
+
+ public CertOutput() {
+ addValueName(VAL_PRETTY_CERT);
+ addValueName(VAL_B64_CERT);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_OUTPUT_CERT_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_OUTPUT_CERT_TEXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_PRETTY_CERT)) {
+ return new Descriptor(IDescriptor.PRETTY_PRINT, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_OUTPUT_CERT_PP"));
+ } else if (name.equals(VAL_B64_CERT)) {
+ return new Descriptor(IDescriptor.PRETTY_PRINT, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_OUTPUT_CERT_B64"));
+ }
+ return null;
+ }
+
+ public String getValue(String name, Locale locale, IRequest request)
+ throws EProfileException {
+ if (name.equals(VAL_PRETTY_CERT)) {
+ X509CertImpl cert = request.getExtDataInCert(
+ EnrollProfile.REQUEST_ISSUED_CERT);
+ if (cert == null)
+ return null;
+ ICertPrettyPrint prettyCert = CMS.getCertPrettyPrint(cert);
+
+ return prettyCert.toString(locale);
+ } else if (name.equals(VAL_B64_CERT)) {
+ X509CertImpl cert = request.getExtDataInCert(
+ EnrollProfile.REQUEST_ISSUED_CERT);
+ if (cert == null)
+ return null;
+ return CMS.getEncodedCert(cert);
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/output/EnrollOutput.java b/base/server/cms/src/com/netscape/cms/profile/output/EnrollOutput.java
new file mode 100644
index 000000000..06c940e8c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/output/EnrollOutput.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.output;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileOutput;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class implements the basic enrollment output.
+ *
+ * @version $Revision$, $Date$
+ */
+public abstract class EnrollOutput implements IProfileOutput {
+ private IConfigStore mConfig = null;
+ private Vector<String> mValueNames = new Vector<String>();
+ protected Vector<String> mConfigNames = new Vector<String>();
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ mConfig = config;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void addValueName(String name) {
+ mValueNames.addElement(name);
+ }
+
+ /**
+ * Populates the request with this policy default.
+ *
+ * @param ctx profile context
+ * @param request request
+ * @exception EProfileException failed to populate
+ */
+ public abstract void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException;
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ *
+ * @param locale user locale
+ * @param name property name
+ * @return property descriptor
+ */
+ public abstract IDescriptor getValueDescriptor(Locale locale, String name);
+
+ /**
+ * Retrieves the localizable name of this policy.
+ *
+ * @param locale user locale
+ * @return output policy name
+ */
+ public abstract String getName(Locale locale);
+
+ /**
+ * Retrieves the localizable description of this policy.
+ *
+ * @param locale user locale
+ * @return output policy description
+ */
+ public abstract String getText(Locale locale);
+
+ /**
+ * Retrieves a list of names of the value parameter.
+ */
+ public Enumeration<String> getValueNames() {
+ return mValueNames.elements();
+ }
+
+ public String getValue(String name, Locale locale, IRequest request)
+ throws EProfileException {
+ return request.getExtDataInString(name);
+ }
+
+ /**
+ * Sets the value of the given value parameter by name.
+ */
+ public void setValue(String name, Locale locale, IRequest request,
+ String value) throws EPropertyException {
+ request.setExtData(name, value);
+ }
+
+ public Enumeration<String> getConfigNames() {
+ return mConfigNames.elements();
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ }
+
+ public String getConfig(String name) {
+ return null;
+ }
+
+ public String getDefaultConfig(String name) {
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/output/PKCS7Output.java b/base/server/cms/src/com/netscape/cms/profile/output/PKCS7Output.java
new file mode 100644
index 000000000..c412eb2fd
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/output/PKCS7Output.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.output;
+
+import java.io.ByteArrayOutputStream;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+
+import netscape.security.pkcs.ContentInfo;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.pkcs.SignerInfo;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.ICertPrettyPrint;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileOutput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the output plugin that outputs
+ * PKCS7 for the issued certificate.
+ *
+ * @version $Revision$, $Date$
+ */
+public class PKCS7Output extends EnrollOutput implements IProfileOutput {
+
+ public static final String VAL_PRETTY_CERT = "pretty_cert";
+ public static final String VAL_PKCS7 = "pkcs7";
+
+ public PKCS7Output() {
+ addValueName(VAL_PRETTY_CERT);
+ addValueName(VAL_PKCS7);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_OUTPUT_CERT_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_OUTPUT_CERT_TEXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_PRETTY_CERT)) {
+ return new Descriptor(IDescriptor.PRETTY_PRINT, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_OUTPUT_CERT_PP"));
+ } else if (name.equals(VAL_PKCS7)) {
+ return new Descriptor(IDescriptor.PRETTY_PRINT, null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_OUTPUT_PKCS7_B64"));
+ }
+ return null;
+ }
+
+ public String getValue(String name, Locale locale, IRequest request)
+ throws EProfileException {
+ if (name.equals(VAL_PRETTY_CERT)) {
+ X509CertImpl cert = request.getExtDataInCert(
+ EnrollProfile.REQUEST_ISSUED_CERT);
+ if (cert == null)
+ return null;
+ ICertPrettyPrint prettyCert = CMS.getCertPrettyPrint(cert);
+
+ return prettyCert.toString(locale);
+ } else if (name.equals(VAL_PKCS7)) {
+
+ try {
+ X509CertImpl cert = request.getExtDataInCert(
+ EnrollProfile.REQUEST_ISSUED_CERT);
+ if (cert == null)
+ return null;
+
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem("ca");
+ CertificateChain cachain = ca.getCACertChain();
+ X509Certificate[] cacerts = cachain.getChain();
+
+ X509CertImpl[] userChain = new X509CertImpl[cacerts.length + 1];
+ int m = 1, n = 0;
+
+ for (; n < cacerts.length; m++, n++) {
+ userChain[m] = (X509CertImpl) cacerts[n];
+ }
+
+ userChain[0] = cert;
+ PKCS7 p7 = new PKCS7(new AlgorithmId[0],
+ new ContentInfo(new byte[0]),
+ userChain,
+ new SignerInfo[0]);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ p7.encodeSignedData(bos);
+ byte[] p7Bytes = bos.toByteArray();
+ String p7Str = CMS.BtoA(p7Bytes);
+
+ return p7Str;
+ } catch (Exception e) {
+ return "";
+ }
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/output/nsNKeyOutput.java b/base/server/cms/src/com/netscape/cms/profile/output/nsNKeyOutput.java
new file mode 100644
index 000000000..571022ad8
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/output/nsNKeyOutput.java
@@ -0,0 +1,110 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.output;
+
+import java.util.Locale;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileOutput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+/**
+ * This class implements the output plugin that outputs
+ * DER for the issued certificate for token keys
+ *
+ * @version $Revision$, $Date$
+ */
+public class nsNKeyOutput extends EnrollOutput implements IProfileOutput {
+
+ public static final String VAL_DER = "der";
+
+ public nsNKeyOutput() {
+ addValueName(VAL_DER);
+ }
+
+ /**
+ * Initializes this default policy.
+ */
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ super.init(profile, config);
+ }
+
+ /**
+ * Retrieves the localizable name of this policy.
+ */
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_OUTPUT_CERT_TOKENKEY_NAME");
+ }
+
+ /**
+ * Retrieves the localizable description of this policy.
+ */
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_OUTPUT_CERT_TOKENKEY_TEXT");
+ }
+
+ /**
+ * Populates the request with this policy default.
+ */
+ public void populate(IProfileContext ctx, IRequest request)
+ throws EProfileException {
+ }
+
+ /**
+ * Retrieves the descriptor of the given value
+ * parameter by name.
+ */
+ public IDescriptor getValueDescriptor(Locale locale, String name) {
+ if (name.equals(VAL_DER)) {
+ return new Descriptor("der_b64", null,
+ null,
+ CMS.getUserMessage(locale,
+ "CMS_PROFILE_OUTPUT_DER_B64"));
+ }
+ return null;
+ }
+
+ public String getValue(String name, Locale locale, IRequest request)
+ throws EProfileException {
+ if (name.equals(VAL_DER)) {
+
+ try {
+ X509CertImpl cert = request.getExtDataInCert(
+ EnrollProfile.REQUEST_ISSUED_CERT);
+ if (cert == null)
+ return null;
+ return CMS.BtoA(cert.getEncoded());
+ } catch (Exception e) {
+ return "";
+ }
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/updater/SubsystemGroupUpdater.java b/base/server/cms/src/com/netscape/cms/profile/updater/SubsystemGroupUpdater.java
new file mode 100644
index 000000000..b703f5b47
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/updater/SubsystemGroupUpdater.java
@@ -0,0 +1,314 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.updater;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPException;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileUpdater;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+
+/**
+ * This updater class will create the new user to the subsystem group and
+ * then add the subsystem certificate to the user.
+ *
+ * @version $Revision$, $Date$
+ */
+public class SubsystemGroupUpdater implements IProfileUpdater {
+
+ @SuppressWarnings("unused")
+ private IProfile mProfile;
+ private IConfigStore mConfig = null;
+ private ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+ private Vector<String> mConfigNames = new Vector<String>();
+
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_ROLE =
+ "LOGGING_SIGNED_AUDIT_CONFIG_ROLE_3";
+
+ public SubsystemGroupUpdater() {
+ }
+
+ public void init(IProfile profile, IConfigStore config)
+ throws EProfileException {
+ mConfig = config;
+ mProfile = profile;
+ }
+
+ public Enumeration<String> getConfigNames() {
+ return mConfigNames.elements();
+ }
+
+ public IDescriptor getConfigDescriptor(Locale locale, String name) {
+ return null;
+ }
+
+ public void setConfig(String name, String value)
+ throws EPropertyException {
+ if (mConfig.getSubStore("params") == null) {
+ //
+ } else {
+ mConfig.getSubStore("params").putString(name, value);
+ }
+ }
+
+ public String getConfig(String name) {
+ try {
+ if (mConfig == null) {
+ return null;
+ }
+ if (mConfig.getSubStore("params") != null) {
+ return mConfig.getSubStore("params").getString(name);
+ }
+ } catch (EBaseException e) {
+ }
+ return "";
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void update(IRequest req, RequestStatus status)
+ throws EProfileException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ CMS.debug("SubsystemGroupUpdater update starts");
+ if (status != req.getRequestStatus()) {
+ return;
+ }
+
+ X509CertImpl cert = req.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
+ if (cert == null)
+ return;
+
+ IConfigStore mainConfig = CMS.getConfigStore();
+
+ int num = 0;
+ try {
+ num = mainConfig.getInteger("subsystem.count", 0);
+ } catch (Exception e) {
+ }
+
+ IUGSubsystem system = (IUGSubsystem) (CMS.getSubsystem(IUGSubsystem.ID));
+
+ String requestor_name = "subsystem";
+ try {
+ requestor_name = req.getExtDataInString("requestor_name");
+ } catch (Exception e1) {
+ // ignore
+ }
+
+ // i.e. tps-1.2.3.4-4
+ String id = requestor_name;
+
+ num++;
+ mainConfig.putInteger("subsystem.count", num);
+
+ try {
+ mainConfig.commit(false);
+ } catch (Exception e) {
+ }
+ String auditParams = "Scope;;users+Operation;;OP_ADD+source;;SubsystemGroupUpdater" +
+ "+Resource;;" + id +
+ "+fullname;;" + id +
+ "+state;;1" +
+ "+userType;;agentType+email;;<null>+password;;<null>+phone;;<null>";
+
+ IUser user = null;
+ CMS.debug("SubsystemGroupUpdater adduser");
+ try {
+ user = system.createUser(id);
+ user.setFullName(id);
+ user.setEmail("");
+ user.setPassword("");
+ user.setUserType("agentType");
+ user.setState("1");
+ user.setPhone("");
+ X509CertImpl[] certs = new X509CertImpl[1];
+ certs[0] = cert;
+ user.setX509Certificates(certs);
+
+ system.addUser(user);
+ CMS.debug("SubsystemGroupUpdater update: successfully add the user");
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams);
+ audit(auditMessage);
+
+ String b64 = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ try {
+ byte[] certEncoded = cert.getEncoded();
+ b64 = CMS.BtoA(certEncoded).trim();
+
+ // extract all line separators
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < b64.length(); i++) {
+ if (!Character.isWhitespace(b64.charAt(i))) {
+ sb.append(b64.charAt(i));
+ }
+ }
+ b64 = sb.toString();
+ } catch (Exception ence) {
+ CMS.debug("SubsystemGroupUpdater update: user cert encoding failed: " + ence);
+ }
+
+ auditParams = "Scope;;certs+Operation;;OP_ADD+source;;SubsystemGroupUpdater" +
+ "+Resource;;" + id +
+ "+cert;;" + b64;
+
+ system.addUserCert(user);
+ CMS.debug("SubsystemGroupUpdater update: successfully add the user certificate");
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams);
+ audit(auditMessage);
+ } catch (LDAPException e) {
+ CMS.debug("UpdateSubsystemGroup: update " + e.toString());
+ if (e.getLDAPResultCode() != LDAPException.ENTRY_ALREADY_EXISTS) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams);
+ audit(auditMessage);
+ throw new EProfileException(e.toString());
+ }
+ } catch (Exception e) {
+ CMS.debug("UpdateSubsystemGroup: update addUser " + e.toString());
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams);
+ audit(auditMessage);
+ throw new EProfileException(e.toString());
+ }
+
+ IGroup group = null;
+ String groupName = "Subsystem Group";
+ auditParams = "Scope;;groups+Operation;;OP_MODIFY+source;;SubsystemGroupUpdater" +
+ "+Resource;;" + groupName;
+
+ try {
+ group = system.getGroupFromName(groupName);
+
+ auditParams += "+user;;";
+ Enumeration<String> members = group.getMemberNames();
+ while (members.hasMoreElements()) {
+ auditParams += members.nextElement();
+ if (members.hasMoreElements()) {
+ auditParams += ",";
+ }
+ }
+
+ if (!group.isMember(id)) {
+ auditParams += "," + id;
+ group.addMemberName(id);
+ system.modifyGroup(group);
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams);
+ audit(auditMessage);
+
+ CMS.debug("UpdateSubsystemGroup: update: successfully added the user to the group.");
+ } else {
+ CMS.debug("UpdateSubsystemGroup: update: user already a member of the group");
+ }
+ } catch (Exception e) {
+ CMS.debug("UpdateSubsystemGroup update: modifyGroup " + e.toString());
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams);
+ audit(auditMessage);
+ }
+ }
+
+ public String getName(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_UPDATER_SUBSYSTEM_NAME");
+ }
+
+ public String getText(Locale locale) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_UPDATER_SUBSYSTEM_TEXT");
+ }
+
+ private void audit(String msg) {
+ if (mSignedAuditLogger == null) {
+ return;
+ }
+
+ mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+
+ private String auditSubjectID() {
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String subjectID = null;
+
+ // Initialize subjectID
+ SessionContext auditContext = SessionContext.getExistingContext();
+
+ if (auditContext != null) {
+ subjectID = (String)
+ auditContext.get(SessionContext.USER_ID);
+
+ if (subjectID != null) {
+ subjectID = subjectID.trim();
+ } else {
+ subjectID = ILogger.NONROLEUSER;
+ }
+ } else {
+ subjectID = ILogger.UNIDENTIFIED;
+ }
+ return subjectID;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/mappers/AVAPattern.java b/base/server/cms/src/com/netscape/cms/publish/mappers/AVAPattern.java
new file mode 100644
index 000000000..e612c339a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/mappers/AVAPattern.java
@@ -0,0 +1,587 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cms.publish.mappers;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+/* cert server imports */
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.StringReader;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.ldap.LDAPDN;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.Extension;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNameInterface;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.OIDMap;
+import netscape.security.x509.SubjectAlternativeNameExtension;
+import netscape.security.x509.X500Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.publish.ECompSyntaxErr;
+import com.netscape.certsrv.request.IRequest;
+
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * avaPattern is a string representing an ldap
+ * attribute formulated from the certificate
+ * subject name, extension or request attributes.
+ * <p>
+ *
+ * The syntax is
+ *
+ * <pre>
+ * avaPattern := constant-value |
+ * "$subj" "." attrName [ "." attrNumber ] |
+ * "$req" "." [ prefix .] attrName [ "." attrNumber ] |
+ * "$ext" "." extName [ "." nameType ] [ "." attrNumber ]
+ * </pre>
+ *
+ * <pre>
+ * Example: <i>$ext.SubjectAlternativeName.RFC822Name.1</i>
+ * cert subjectAltName is rfc822Name: jjames@mcom.com
+ * <p>
+ * The ldap attribute formulated will be : <br>
+ * jjames@mcom.com
+ * <p>
+ * The first rfc822name value in the subjAltName extension. <br>
+ * <p>
+ * </pre>
+ *
+ * If a request attribute or subject DN component does not exist, the attribute is skipped.
+ *
+ * @version $Revision$, $Date$
+ */
+class AVAPattern {
+ ////////////////
+ // parameters //
+ ////////////////
+
+ /* the value type of the dn component */
+ public static final String TYPE_REQ = "$req";
+ public static final String TYPE_SUBJ = "$subj";
+ public static final String TYPE_EXT = "$ext";
+ public static final String TYPE_CONSTANT = "constant";
+
+ public static final String[] GENERAL_NAME_TYPE = { "ANY",
+ "RFC822Name",
+ "DNSName",
+ "X400Name",
+ "DIRECTORYName",
+ "EDIName",
+ "URIName",
+ "IPAddress",
+ "OIDName" };
+
+ /* the list of request attributes needed by this AVA */
+ protected String[] mReqAttrs = null;
+
+ /* the list of cert attributes needed by this AVA*/
+ protected String[] mCertAttrs = null;
+
+ /* value type */
+ protected String mType = null;
+
+ /* value - could be name of a request attribute or
+ * cert subject attribute or extension name.
+ */
+ protected String mValue = null;
+
+ /* value type - general name type of an
+ * extension attribute if any.
+ */
+ protected String mGNType = null;
+
+ /* prefix - prefix of a request attribute if any. */
+ protected String mPrefix = null;
+
+ /* nth value of the ldap or dn attribute */
+ protected int mElement = 0;
+
+ protected String mTestDN = null;
+
+ /////////////
+ // methods //
+ /////////////
+
+ public AVAPattern(String component)
+ throws ELdapException {
+ if (component == null || component.length() == 0) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX", component));
+ }
+
+ parse(new PushbackReader(new StringReader(component)));
+ }
+
+ public AVAPattern(PushbackReader in)
+ throws ELdapException {
+ parse(in);
+ }
+
+ private void parse(PushbackReader in)
+ throws ELdapException {
+ int c;
+
+ // skip spaces
+ //System.out.println("============ AVAPattern Begin ===========");
+ //System.out.println("skip spaces");
+
+ try {
+ while ((c = in.read()) == ' ' || c == '\t') {//System.out.println("spaces read "+(char)c);
+ ;
+ }
+ } catch (IOException e) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX", "All blank"));
+ }
+
+ if (c == -1) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX", "All blank"));
+ }
+
+ if (c == '$') {
+ // check for $subj $ext or $req
+ try {
+ c = in.read();
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+
+ if (c == -1) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "expecting $subj $ext or $req in ava pattern"));
+ }
+
+ if (c == 'r') {
+ try {
+ if (in.read() != 'e' ||
+ in.read() != 'q' ||
+ in.read() != '.') {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "expecting $req in ava pattern"));
+ }
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+
+ mType = TYPE_REQ;
+ //System.out.println("---- mtype $req");
+ } else if (c == 's') {
+ try {
+ if (in.read() != 'u' ||
+ in.read() != 'b' ||
+ in.read() != 'j' ||
+ in.read() != '.') {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "expecting $subj in ava pattern"));
+ }
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+
+ mType = TYPE_SUBJ;
+ //System.out.println("----- mtype $subj");
+ } else if (c == 'e') {
+ try {
+ if (in.read() != 'x' ||
+ in.read() != 't' ||
+ in.read() != '.') {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "expecting $ext in ava pattern"));
+ }
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+
+ mType = TYPE_EXT;
+ //System.out.println("----- mtype $ext");
+ } else {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "unknown keyword. expecting $subj $ext or $req."));
+ }
+
+ // get request attribute or
+ // cert subject or
+ // extension attribute
+
+ StringBuffer valueBuf = new StringBuffer();
+
+ try {
+ while ((c = in.read()) != ',' &&
+ c != -1 && c != '.' && c != '+') {
+ //System.out.println("mValue read "+(char)c);
+ valueBuf.append((char) c);
+ }
+
+ if (c == '+' || c == ',') { // either ',' or '+'
+ in.unread(c); // pushback last , or +
+ }
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+
+ mValue = valueBuf.toString().trim();
+ if (mValue.length() == 0) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "$subj $ext or $req attribute name expected"));
+ }
+ //System.out.println("----- mValue "+mValue);
+
+ // get nth dn xxx not nth request attribute .
+ if (c == '.') {
+ StringBuffer attrNumberBuf = new StringBuffer();
+
+ try {
+ while ((c = in.read()) != ',' && c != -1 && c != '.'
+ && c != '+') {
+ //System.out.println("mElement read "+(char)c);
+ attrNumberBuf.append((char) c);
+ }
+
+ if (c == ',' || c == '+') { // either ',' or '+'
+ in.unread(c); // pushback last , or +
+ }
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+
+ String attrNumber = attrNumberBuf.toString().trim();
+
+ if (attrNumber.length() == 0) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "nth element $req $ext or $subj expected"));
+ }
+
+ try {
+ mElement = Integer.parseInt(attrNumber) - 1;
+ } catch (NumberFormatException e) {
+
+ if (TYPE_REQ.equals(mType)) {
+ mPrefix = mValue;
+ mValue = attrNumber;
+ } else if (TYPE_EXT.equals(mType)) {
+ mGNType = attrNumber;
+ } else {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "Invalid format in nth element " +
+ "$req $ext or $subj"));
+ }
+
+ // get nth request attribute .
+ if (c == '.') {
+ StringBuffer attrNumberBuf1 = new StringBuffer();
+
+ try {
+ while ((c = in.read()) != ',' &&
+ c != -1 && c != '+') {
+ //System.out.println("mElement read "+
+ // (char)c);
+ attrNumberBuf1.append((char) c);
+ }
+
+ if (c != -1) { // either ',' or '+'
+ in.unread(c); // pushback last , or +
+ }
+ } catch (IOException ex) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", ex.toString()));
+ }
+
+ String attrNumber1 =
+ attrNumberBuf1.toString().trim();
+
+ if (attrNumber1.length() == 0) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "nth element $req or $ext expected"));
+ }
+
+ try {
+ mElement = Integer.parseInt(attrNumber1) - 1;
+ } catch (NumberFormatException ex) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "Invalid format in nth element " +
+ "$req or $ext."));
+ }
+ }
+ }
+ }
+ //System.out.println("----- mElement "+mElement);
+ } else {
+ // value is constant. treat as regular ava.
+ mType = TYPE_CONSTANT;
+
+ // parse ava value.
+ StringBuffer valueBuf = new StringBuffer();
+
+ valueBuf.append((char) c);
+
+ // read forward to get attribute value
+ try {
+ while ((c = in.read()) != ',' && c != -1) {
+ valueBuf.append((char) c);
+ }
+
+ if (c == '+' || c == ',') { // either ',' or '+'
+ in.unread(c); // pushback last , or +
+ }
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+
+ mValue = valueBuf.toString().trim();
+
+ /* try {
+ * AVA ava = mLdapDNStrConverter.parseAVA(
+ * valueBuf.toString());
+ * mValue = ava.toLdapDNString();
+ * //System.out.println("----- mValue "+mValue);
+ * } catch (IOException e) {
+ * throw new ECompSyntaxErr(e.toString());
+ * }
+ */
+ }
+ }
+
+ public String formAVA(IRequest req,
+ X500Name subject,
+ CertificateExtensions extensions)
+ throws ELdapException {
+ if (TYPE_CONSTANT.equals(mType)) {
+ return mValue;
+ }
+
+ if (TYPE_SUBJ.equals(mType)) {
+ String dn = subject.toString();
+
+ if (mTestDN != null) {
+ dn = mTestDN;
+ }
+
+ //System.out.println("AVAPattern Using dn "+mTestDN);
+ String[] rdns = LDAPDN.explodeDN(dn, false);
+
+ String value = null;
+
+ int nFound = -1;
+
+ for (int i = 0; i < rdns.length; i++) {
+ String[] avas = explodeRDN(rdns[i]);
+
+ for (int j = 0; j < avas.length; j++) {
+ String[] exploded = explodeAVA(avas[j]);
+
+ if (exploded[0].equalsIgnoreCase(mValue) &&
+ ++nFound == mElement) {
+ value = exploded[1];
+ break;
+ }
+ }
+ }
+
+ if (value == null) {
+ return null;
+ }
+
+ return value;
+ }
+
+ if (TYPE_EXT.equals(mType)) {
+
+ if (extensions != null) {
+
+ for (int i = 0; i < extensions.size(); i++) {
+ Extension ext = extensions.elementAt(i);
+
+ String extName =
+ OIDMap.getName(ext.getExtensionId());
+
+ int index = extName.lastIndexOf(".");
+
+ if (index != -1) {
+ extName = extName.substring(index + 1);
+ }
+
+ if (extName.equals(mValue)) {
+ // Check the extensions one by one.
+ // For now, just give subjectAltName
+ // as an example.
+ if (mValue.equalsIgnoreCase(
+ SubjectAlternativeNameExtension.NAME)) {
+ try {
+ GeneralNames subjectNames = (GeneralNames)
+ ((SubjectAlternativeNameExtension)
+ ext).get(
+ SubjectAlternativeNameExtension.SUBJECT_NAME);
+
+ if (subjectNames.size() == 0) {
+ break;
+ }
+
+ int j = 0;
+
+ for (Enumeration<GeneralNameInterface> n =
+ subjectNames.elements(); n.hasMoreElements();) {
+
+ GeneralName gn = (GeneralName)
+ n.nextElement();
+
+ String gname = gn.toString();
+
+ index = gname.indexOf(":");
+
+ if (index == -1) {
+ break;
+ }
+
+ String gType =
+ gname.substring(0, index);
+
+ if (mGNType != null) {
+ if (mGNType.equalsIgnoreCase(gType)) {
+ if (mElement == j) {
+ gname =
+ gname.substring(index + 2);
+ return gname;
+ } else {
+ j++;
+ }
+ }
+ } else {
+ if (mElement == j) {
+ gname =
+ gname.substring(index + 2);
+ return gname;
+ }
+ j++;
+ }
+ }
+ } catch (IOException e) {
+ CMS.debug(
+ "AVAPattern: Publishing attr not formed " +
+ "from extension " +
+ "-- no attr : " +
+ mValue);
+ }
+ }
+ }
+ }
+ }
+
+ CMS.debug(
+ "AVAPattern: Publishing:attr not formed " +
+ "from extension " +
+ "-- no attr : " +
+ mValue);
+
+ return null;
+ }
+
+ if (TYPE_REQ.equals(mType)) {
+ // mPrefix and mValue are looked up case-insensitive
+ String reqAttr = req.getExtDataInString(mPrefix, mValue);
+ if (reqAttr == null) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_NO_REQUEST", mValue, ""));
+ }
+
+ return reqAttr;
+ }
+
+ return null;
+ }
+
+ public String getReqAttr() {
+ if (TYPE_REQ.equals(mType)) {
+ return mValue;
+ } else {
+ return null;
+ }
+ }
+
+ public String getCertAttr() {
+ if (TYPE_SUBJ.equals(mType)) {
+ return mValue;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Explode RDN into AVAs.
+ * Does not handle escaped '+'
+ * Java ldap library does not yet support multiple avas per rdn.
+ * If RDN is malformed returns empty array.
+ */
+ public static String[] explodeRDN(String rdn) {
+ int plus = rdn.indexOf('+');
+
+ if (plus == -1) {
+ return new String[] { rdn };
+ }
+
+ Vector<String> avas = new Vector<String>();
+
+ StringTokenizer token = new StringTokenizer(rdn, "+");
+
+ while (token.hasMoreTokens()) {
+ avas.addElement(token.nextToken());
+ }
+
+ String[] theAvas = new String[avas.size()];
+
+ avas.copyInto(theAvas);
+
+ return theAvas;
+ }
+
+ /**
+ * Explode AVA into name and value.
+ * Does not handle escaped '='
+ * If AVA is malformed empty array is returned.
+ */
+ public static String[] explodeAVA(String ava) {
+ int equals = ava.indexOf('=');
+
+ if (equals == -1) {
+ return null;
+ }
+
+ return new String[] { ava.substring(0, equals).trim(),
+ ava.substring(equals + 1).trim() };
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCaSimpleMap.java b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCaSimpleMap.java
new file mode 100644
index 000000000..1b1531000
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCaSimpleMap.java
@@ -0,0 +1,368 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.mappers;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+import netscape.ldap.LDAPv3;
+import netscape.ldap.util.DN;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CRLImpl;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapMapper;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * Maps a request to an entry in the LDAP server.
+ * Takes a dnPattern to form the baseDN from the request attributes
+ * and certificate subject name.Do a base search for the entry
+ * in the directory to publish the cert or crl.
+ * The restriction of this mapper is that the ldap dn components must
+ * be part of certificate subject name or request attributes or constant.
+ *
+ * @version $Revision$, $Date$
+ */
+public class LdapCaSimpleMap implements ILdapMapper, IExtendedPluginInfo {
+ protected static final String PROP_DNPATTERN = "dnPattern";
+ protected static final String PROP_CREATECA = "createCAEntry";
+ protected String mDnPattern = null;
+ protected boolean mCreateCAEntry = true;
+
+ private ILogger mLogger = CMS.getLogger();
+ private boolean mInited = false;
+ protected IConfigStore mConfig = null;
+
+ /* the subject DN pattern */
+ protected MapDNPattern mPattern = null;
+
+ /* the list of request attriubutes to retrieve*/
+ protected String[] mReqAttrs = null;
+
+ /* the list of cert attriubutes to retrieve*/
+ protected String[] mCertAttrs = null;
+
+ /* default dn pattern if left blank or not set in the config */
+ public static final String DEFAULT_DNPATTERN =
+ "UID=$req.HTTP_PARAMS.UID, OU=people, O=$subj.o, C=$subj.c";
+
+ /**
+ * Constructor.
+ *
+ * @param dnPattern The base DN.
+ */
+ public LdapCaSimpleMap(String dnPattern) {
+ try {
+ init(dnPattern);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+
+ }
+
+ /**
+ * constructor if initializing from config store.
+ */
+ public LdapCaSimpleMap() {
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String params[] = {
+ "dnPattern;string;Describes how to form the Ldap Subject name in" +
+ " the directory. Example 1: 'uid=CertMgr, o=Fedora'. Example 2:" +
+ " 'uid=$req.HTTP_PARAMS.uid, E=$ext.SubjectAlternativeName.RFC822Name, ou=$subj.ou'. " +
+ "$req means: take the attribute from the request. " +
+ "$subj means: take the attribute from the certificate subject name. " +
+ "$ext means: take the attribute from the certificate extension",
+ "createCAEntry;boolean;If checked, CA entry will be created automatically",
+ IExtendedPluginInfo.HELP_TOKEN + ";configuration-ldappublish-mapper-casimplemapper",
+ IExtendedPluginInfo.HELP_TEXT + ";Describes how to form the LDAP DN of the entry to publish to"
+ };
+
+ return params;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * for initializing from config store.
+ */
+ public void init(IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+ String dnPattern = mConfig.getString(PROP_DNPATTERN);
+
+ mCreateCAEntry = mConfig.getBoolean(PROP_CREATECA, true);
+ init(dnPattern);
+ }
+
+ /**
+ * common initialization routine.
+ */
+ protected void init(String dnPattern)
+ throws EBaseException {
+ if (mInited)
+ return;
+
+ mDnPattern = dnPattern;
+ if (mDnPattern == null || mDnPattern.length() == 0)
+ mDnPattern = DEFAULT_DNPATTERN;
+ try {
+ mPattern = new MapDNPattern(mDnPattern);
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_DN_PATTERN_INIT", dnPattern, e.toString()));
+ throw new EBaseException("falied to init with pattern " +
+ dnPattern + " " + e);
+ }
+
+ mInited = true;
+ }
+
+ /**
+ * Maps a X500 subject name to LDAP entry.
+ * Uses DN pattern to form a DN for a LDAP base search.
+ *
+ * @param conn the LDAP connection.
+ * @param obj the object to map.
+ * @exception ELdapException if any LDAP exceptions occured.
+ */
+ public String map(LDAPConnection conn, Object obj)
+ throws ELdapException {
+ return map(conn, null, obj);
+ }
+
+ /**
+ * Maps a X500 subject name to LDAP entry.
+ * Uses DN pattern to form a DN for a LDAP base search.
+ *
+ * @param conn the LDAP connection.
+ * @param req the request to map.
+ * @param obj the object to map.
+ * @exception ELdapException if any LDAP exceptions occured.
+ */
+ public String map(LDAPConnection conn, IRequest req, Object obj)
+ throws ELdapException {
+ if (conn == null)
+ return null;
+ String dn = null;
+
+ try {
+ dn = formDN(req, obj);
+ if (dn == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_DN_NOT_FORMED"));
+ String s1 = "";
+
+ if (req != null)
+ s1 = req.getRequestId().toString();
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_NO_DN_MATCH", s1));
+ }
+ int scope = LDAPv2.SCOPE_BASE;
+ String filter = "(objectclass=*)";
+
+ // search for entry
+ String[] attrs = new String[] { LDAPv3.NO_ATTRS };
+
+ log(ILogger.LL_INFO, "searching for dn: " + dn + " filter:"
+ + filter + " scope: base");
+
+ LDAPSearchResults results =
+ conn.search(dn, scope, filter, attrs, false);
+ LDAPEntry entry = results.next();
+
+ if (results.hasMoreElements()) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_MORE_THAN_ONE_ENTRY", dn,
+ ((req == null) ? "" : req.getRequestId().toString())));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_MORE_THAN_ONE_ENTRY",
+ ((req == null) ? "" : req.getRequestId().toString())));
+ }
+ if (entry != null)
+ return entry.getDN();
+ else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_ENTRY_NOT_FOUND", dn,
+ ((req == null) ? "" : req.getRequestId().toString())));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH_FOUND",
+ "null entry"));
+ }
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else if (e.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT && mCreateCAEntry) {
+ try {
+ createCAEntry(conn, dn);
+ log(ILogger.LL_INFO, "CA Entry " + dn + " Created");
+ return dn;
+ } catch (LDAPException e1) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_DN_MAP_EXCEPTION", dn, e1.toString()));
+ if (e1.getLDAPResultCode() == LDAPException.CONSTRAINT_VIOLATION) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_CA_ENTRY_NOT_CREATED"));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_CA_ENTRY_NOT_CREATED1"));
+ }
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_CREATE_CA_FAILED", dn));
+ }
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_DN_MAP_EXCEPTION", dn, e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH_FOUND", e.toString()));
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_EXCEPTION_CAUGHT", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH_FOUND", e.toString()));
+ }
+ }
+
+ private void createCAEntry(LDAPConnection conn, String dn)
+ throws LDAPException {
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+ // OID 2.5.6.16
+ String caOc[] = new String[] { "top",
+ "person",
+ "organizationalPerson",
+ "inetOrgPerson" };
+
+ DN dnobj = new DN(dn);
+ String attrval[] = dnobj.explodeDN(true);
+
+ attrs.add(new LDAPAttribute("cn", attrval[0]));
+ attrs.add(new LDAPAttribute("sn", attrval[0]));
+ attrs.add(new LDAPAttribute("objectclass", caOc));
+ LDAPEntry entry = new LDAPEntry(dn, attrs);
+
+ conn.add(entry);
+ }
+
+ /**
+ * form a dn from component in the request and cert subject name
+ *
+ * @param req The request
+ * @param obj The certificate or crl
+ */
+ private String formDN(IRequest req, Object obj) throws EBaseException {
+ X500Name subjectDN = null;
+ CertificateExtensions certExt = null;
+
+ try {
+ X509Certificate cert = (X509Certificate) obj;
+ subjectDN = (X500Name) cert.getSubjectDN();
+
+ CMS.debug("LdapCaSimpleMap: cert subject dn:" + subjectDN.toString());
+ X509CertInfo info = (X509CertInfo)
+ ((X509CertImpl) cert).get(
+ X509CertImpl.NAME + "." + X509CertImpl.INFO);
+
+ certExt = (CertificateExtensions) info.get(
+ CertificateExtensions.NAME);
+ } catch (java.security.cert.CertificateParsingException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_CANT_GET_EXT", e.toString()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_CANT_GET_EXT", e.toString()));
+ } catch (java.security.cert.CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_CANT_GET_EXT", e.toString()));
+ } catch (ClassCastException e) {
+ try {
+ X509CRLImpl crl = (X509CRLImpl) obj;
+ subjectDN = (X500Name) crl.getIssuerDN();
+
+ CMS.debug("LdapCaSimpleMap: crl issuer dn: " +
+ subjectDN.toString());
+ } catch (ClassCastException ex) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_PUBLISH_OBJ_NOT_SUPPORTED",
+ ((req == null) ? "" : req.getRequestId().toString())));
+ return null;
+ }
+ }
+ try {
+ String dn = mPattern.formDN(req, subjectDN, certExt);
+
+ return dn;
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_CANT_FORM_DN",
+ ((req == null) ? "" : req.getRequestId().toString()), e.toString()));
+ throw new EBaseException("falied to form dn for request: " +
+ ((req == null) ? "" : req.getRequestId().toString()) + " " + e);
+ }
+ }
+
+ public String getImplName() {
+ return "LdapCaSimpleMap";
+ }
+
+ public String getDescription() {
+ return "LdapCaSimpleMap";
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(PROP_DNPATTERN + "=");
+ v.addElement(PROP_CREATECA + "=true");
+ return v;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ try {
+ if (mDnPattern == null) {
+ v.addElement(PROP_DNPATTERN + "=");
+ } else {
+ v.addElement(PROP_DNPATTERN + "=" +
+ mConfig.getString(PROP_DNPATTERN));
+ }
+ v.addElement(PROP_CREATECA + "=" + mConfig.getBoolean(PROP_CREATECA, true));
+ } catch (Exception e) {
+ }
+ return v;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "LdapCaSimpleMapper: " + msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCertCompsMap.java b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCertCompsMap.java
new file mode 100644
index 000000000..8ed702f50
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCertCompsMap.java
@@ -0,0 +1,176 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.mappers;
+
+import java.security.cert.CRLException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Vector;
+
+import netscape.ldap.LDAPConnection;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CRLImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapMapper;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * Maps a X509 certificate to a LDAP entry using AVAs in the certificate's
+ * subject name to form the ldap search dn and filter.
+ * Takes a optional root search dn.
+ * The DN comps are used to form a LDAP entry to begin a subtree search.
+ * The filter comps are used to form a search filter for the subtree.
+ * If none of the DN comps matched, baseDN is used for the subtree.
+ * If the baseDN is null and none of the DN comps matched, it is an error.
+ * If none of the DN comps and filter comps matched, it is an error.
+ * If just the filter comps is null, a base search is performed.
+ *
+ * @version $Revision$, $Date$
+ */
+public class LdapCertCompsMap
+ extends LdapDNCompsMap implements ILdapMapper {
+ ILogger mLogger = CMS.getLogger();
+
+ public LdapCertCompsMap() {
+ // need to support baseDN, dnComps, and filterComps
+ // via configuration
+ }
+
+ /**
+ * Constructor.
+ *
+ * The DN comps are used to form a LDAP entry to begin a subtree search.
+ * The filter comps are used to form a search filter for the subtree.
+ * If none of the DN comps matched, baseDN is used for the subtree.
+ * If the baseDN is null and none of the DN comps matched, it is an error.
+ * If none of the DN comps and filter comps matched, it is an error.
+ * If just the filter comps is null, a base search is performed.
+ *
+ * @param baseDN The base DN.
+ * @param dnComps Components to form the LDAP base dn for search.
+ * @param filterComps Components to form the LDAP search filter.
+ */
+ public LdapCertCompsMap(String baseDN, ObjectIdentifier[] dnComps,
+ ObjectIdentifier[] filterComps) {
+ init(baseDN, dnComps, filterComps);
+ }
+
+ public String getImplName() {
+ return "LdapCertCompsMap";
+ }
+
+ public String getDescription() {
+ return "LdapCertCompsMap";
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = super.getDefaultParams();
+
+ return v;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = super.getInstanceParams();
+
+ return v;
+ }
+
+ /**
+ * constructor using non-standard certificate attribute.
+ */
+ public LdapCertCompsMap(String certAttr, String baseDN,
+ ObjectIdentifier[] dnComps,
+ ObjectIdentifier[] filterComps) {
+ super(certAttr, baseDN, dnComps, filterComps);
+ }
+
+ protected void init(String baseDN, ObjectIdentifier[] dnComps,
+ ObjectIdentifier[] filterComps) {
+ super.init(baseDN, dnComps, filterComps);
+ }
+
+ /**
+ * Maps a certificate to LDAP entry.
+ * Uses DN components and filter components to form a DN and
+ * filter for a LDAP search.
+ * If the formed DN is null the baseDN will be used.
+ * If the formed DN is null and baseDN is null an error is thrown.
+ * If the filter is null a base search is performed.
+ * If both are null an error is thrown.
+ *
+ * @param conn - the LDAP connection.
+ * @param obj - the X509Certificate.
+ */
+ public String
+ map(LDAPConnection conn, Object obj)
+ throws ELdapException {
+ if (conn == null)
+ return null;
+ try {
+ X509Certificate cert = (X509Certificate) obj;
+ String result = null;
+ // form dn and filter for search.
+ X500Name subjectDN = (X500Name) cert.getSubjectDN();
+
+ CMS.debug("LdapCertCompsMap: " + subjectDN.toString());
+
+ byte[] certbytes = cert.getEncoded();
+
+ result = super.map(conn, subjectDN, certbytes);
+ return result;
+ } catch (CertificateEncodingException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_CANT_DECODE_CERT", e.toString()));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_GET_DER_ENCODED_CERT_FAILED", e.toString()));
+ } catch (ClassCastException e) {
+ try {
+ X509CRLImpl crl = (X509CRLImpl) obj;
+ String result = null;
+ X500Name issuerDN = (X500Name) crl.getIssuerDN();
+
+ CMS.debug("LdapCertCompsMap: " + issuerDN.toString());
+
+ byte[] crlbytes = crl.getEncoded();
+
+ result = super.map(conn, issuerDN, crlbytes);
+ return result;
+ } catch (CRLException ex) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_CANT_DECODE_CRL", ex.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_GET_DER_ENCODED_CRL_FAILED", ex.toString()));
+ } catch (ClassCastException ex) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_NOT_SUPPORTED_OBJECT"));
+ return null;
+ }
+ }
+ }
+
+ public String map(LDAPConnection conn, IRequest req, Object obj)
+ throws ELdapException {
+ return map(conn, obj);
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "LdapCertCompsMap: " + msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCertExactMap.java b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCertExactMap.java
new file mode 100644
index 000000000..21a3a0794
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCertExactMap.java
@@ -0,0 +1,195 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.mappers;
+
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+import netscape.ldap.LDAPv3;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CRLImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapMapper;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * Maps a X509 certificate to a LDAP entry by using the subject name
+ * of the certificate as the LDAP entry DN.
+ *
+ * @version $Revision$, $Date$
+ */
+public class LdapCertExactMap implements ILdapMapper, IExtendedPluginInfo {
+ private ILogger mLogger = CMS.getLogger();
+ protected IConfigStore mConfig = null;
+ boolean mInited = false;
+
+ /**
+ * constructs a certificate subject name mapper with search base.
+ */
+ public LdapCertExactMap() {
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void init(IConfigStore config)
+ throws EBaseException {
+ if (mInited == true)
+ return;
+ mConfig = config;
+ mInited = true;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ldappublish-mapper-certexactmapper",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Literally uses the subject name of the certificate as the DN to publish to"
+ };
+
+ return params;
+ }
+
+ public String getImplName() {
+ return "LdapCertExactMap";
+ }
+
+ public String getDescription() {
+ return "LdapCertExactMap";
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ return v;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ return v;
+ }
+
+ /**
+ * Finds the entry for the certificate by looking for the cert
+ * subject name in the subject name attribute.
+ *
+ * @param conn - the LDAP connection.
+ * @param obj - the X509Certificate.
+ */
+ public String
+ map(LDAPConnection conn, Object obj)
+ throws ELdapException {
+ if (conn == null)
+ return null;
+
+ X500Name subjectDN = null;
+
+ try {
+ X509Certificate cert = (X509Certificate) obj;
+ subjectDN = (X500Name) cert.getSubjectDN();
+
+ CMS.debug("LdapCertExactMap: cert subject dn:" + subjectDN.toString());
+ } catch (ClassCastException e) {
+ try {
+ X509CRLImpl crl = (X509CRLImpl) obj;
+ subjectDN = (X500Name) crl.getIssuerDN();
+
+ CMS.debug("LdapCertExactMap: crl issuer dn: " +
+ subjectDN.toString());
+ } catch (ClassCastException ex) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_NOT_SUPPORTED_OBJECT"));
+ return null;
+ }
+ }
+ try {
+ String[] attrs = new String[] { LDAPv3.NO_ATTRS };
+
+ log(ILogger.LL_INFO, "Searching for " + subjectDN.toString());
+
+ LDAPSearchResults results =
+ conn.search(subjectDN.toString(), LDAPv2.SCOPE_BASE,
+ "(objectclass=*)", attrs, false);
+
+ LDAPEntry entry = results.next();
+
+ if (results.hasMoreElements()) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_MORE_THAN_ONE_ENTRY", "", subjectDN.toString()));
+ }
+ if (entry != null) {
+ log(ILogger.LL_INFO, "entry found");
+ return entry.getDN();
+ }
+ return null;
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_DN_MAP_EXCEPTION", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH_FOUND", e.toString()));
+ }
+ }
+
+ /*
+ catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_CANT_GET_SUBJECT", e.toString()));
+ throw new ELdapException(
+ LdapResources.GET_CERT_SUBJECT_DN_FAILED, e);
+ }
+ catch (CertificateEncodingException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_CANT_DECODE_CERT", e.toString()));
+ throw new ELdapException(
+ LdapResources.GET_DER_ENCODED_CERT_FAILED, e);
+ }
+ */
+ }
+
+ public String map(LDAPConnection conn, IRequest req, Object obj)
+ throws ELdapException {
+ return map(conn, obj);
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "LdapCertExactMap: " + msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCertSubjMap.java b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCertSubjMap.java
new file mode 100644
index 000000000..a1f7207f6
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCertSubjMap.java
@@ -0,0 +1,339 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.mappers;
+
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+import netscape.ldap.LDAPv3;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CRLImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapMapper;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * Maps a X509 certificate to a LDAP entry by finding an LDAP entry
+ * which has an attribute whose contents are equal to the cert subject name.
+ *
+ * @version $Revision$, $Date$
+ */
+public class LdapCertSubjMap implements ILdapMapper, IExtendedPluginInfo {
+ public static final String LDAP_CERTSUBJNAME_ATTR = "certSubjectName";
+ protected String mSearchBase = null;
+ protected String mCertSubjNameAttr = LDAP_CERTSUBJNAME_ATTR;
+ protected boolean mUseAllEntries = false;
+
+ private ILogger mLogger = CMS.getLogger();
+ protected IConfigStore mConfig = null;
+ boolean mInited = false;
+
+ public LdapCertSubjMap() {
+ // need to setup the mSearchBase via configuration
+ }
+
+ /**
+ * constructs a certificate subject name mapper with search base.
+ *
+ * @param searchBase the dn to start searching for the certificate
+ * subject name.
+ */
+ public LdapCertSubjMap(String searchBase) {
+ if (searchBase == null)
+ throw new IllegalArgumentException(
+ "a null argument to constructor " + this.getClass().getName());
+ mSearchBase = searchBase;
+ mInited = true;
+ }
+
+ /**
+ * Constructor using non-ES cert map attribute name.
+ *
+ * @param searchBase entry to start search.
+ * @param certSubjNameAttr attribute for certificate subject names.
+ * @param certAttr attribute to find certificate.
+ */
+ public LdapCertSubjMap(String searchBase,
+ String certSubjNameAttr, String certAttr) {
+ if (searchBase == null ||
+ certSubjNameAttr == null || certAttr == null)
+ throw new IllegalArgumentException(
+ "a null argument to constructor " + this.getClass().getName());
+ mCertSubjNameAttr = certSubjNameAttr;
+ mSearchBase = searchBase;
+ mInited = true;
+ }
+
+ public LdapCertSubjMap(String searchBase,
+ String certSubjNameAttr, String certAttr, boolean useAllEntries) {
+ if (searchBase == null ||
+ certSubjNameAttr == null || certAttr == null)
+ throw new IllegalArgumentException(
+ "a null argument to constructor " + this.getClass().getName());
+ mCertSubjNameAttr = certSubjNameAttr;
+ mSearchBase = searchBase;
+ mUseAllEntries = useAllEntries;
+ mInited = true;
+ }
+
+ public String getImplName() {
+ return "LdapCertSubjMap";
+ }
+
+ public String getDescription() {
+ return "LdapCertSubjMap";
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement("certSubjNameAttr=" + mCertSubjNameAttr);
+ v.addElement("searchBase=");
+ v.addElement("useAllEntries=" + mUseAllEntries);
+ return v;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ "certSubjNameAttr;string;Name of Ldap attribute containing cert subject name",
+ "searchBase;string;Base DN to search from",
+ "useAllEntries;boolean;Use all entries for publishing",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ldappublish-mapper-certsubjmapper",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";This plugin assumes you want to publish to an LDAP entry which has " +
+ "an attribute whose contents are equal to the cert subject name"
+ };
+
+ return params;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ if (mCertSubjNameAttr == null) {
+ v.addElement("certSubjNameAttr=");
+ } else {
+ v.addElement("certSubjNameAttr=" + mCertSubjNameAttr);
+ }
+ if (mSearchBase == null) {
+ v.addElement("searchBase=");
+ } else {
+ v.addElement("searchBase=" + mSearchBase);
+ }
+ v.addElement("useAllEntries=" + mUseAllEntries);
+ return v;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void init(IConfigStore config)
+ throws EBaseException {
+ if (mInited == true)
+ return;
+ mConfig = config;
+ mCertSubjNameAttr = config.getString("certSubjNameAttr",
+ LDAP_CERTSUBJNAME_ATTR);
+ mSearchBase = config.getString("searchBase");
+ mUseAllEntries = config.getBoolean("useAllEntries", false);
+ mInited = true;
+ }
+
+ /**
+ * Finds the entry for the certificate by looking for the cert
+ * subject name in the subject name attribute.
+ *
+ * @param conn - the LDAP connection.
+ * @param obj - the X509Certificate.
+ */
+ public String
+ map(LDAPConnection conn, Object obj)
+ throws ELdapException {
+ if (conn == null)
+ return null;
+ X500Name subjectDN = null;
+
+ try {
+ X509Certificate cert = (X509Certificate) obj;
+ subjectDN = (X500Name) cert.getSubjectDN();
+
+ CMS.debug("LdapCertSubjMap: cert subject dn:" + subjectDN.toString());
+ } catch (ClassCastException e) {
+ try {
+ X509CRLImpl crl = (X509CRLImpl) obj;
+ subjectDN = (X500Name) crl.getIssuerDN();
+
+ CMS.debug("LdapCertSubjMap: crl issuer dn: " +
+ subjectDN.toString());
+ } catch (ClassCastException ex) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_NOT_SUPPORTED_OBJECT"));
+ return null;
+ }
+ }
+ try {
+ String[] attrs = new String[] { LDAPv3.NO_ATTRS };
+
+ log(ILogger.LL_INFO, "search " + mSearchBase +
+ " (" + mCertSubjNameAttr + "=" + subjectDN + ") " + mCertSubjNameAttr);
+
+ LDAPSearchResults results =
+ conn.search(mSearchBase, LDAPv2.SCOPE_SUB,
+ "(" + mCertSubjNameAttr + "=" + subjectDN + ")", attrs, false);
+
+ LDAPEntry entry = results.next();
+
+ if (results.hasMoreElements()) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_MORE_THAN_ONE_ENTRY", "", subjectDN.toString()));
+ }
+ if (entry != null) {
+ log(ILogger.LL_INFO, "entry found");
+ return entry.getDN();
+ }
+ return null;
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_DN_MAP_EXCEPTION", "LDAPException", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH_FOUND", e.toString()));
+ }
+ }
+
+ /*
+ catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_CANT_GET_SUBJECT", e.toString()));
+ throw new ELdapException(
+ LdapResources.GET_CERT_SUBJECT_DN_FAILED, e);
+ }
+ catch (CertificateEncodingException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_CANT_DECODE_CERT", e.toString()));
+ throw new ELdapException(
+ LdapResources.GET_DER_ENCODED_CERT_FAILED, e);
+ }
+ */
+ }
+
+ public String map(LDAPConnection conn, IRequest req, Object obj)
+ throws ELdapException {
+ return map(conn, obj);
+ }
+
+ public Vector<String> mapAll(LDAPConnection conn, Object obj)
+ throws ELdapException {
+ Vector<String> v = new Vector<String>();
+
+ if (conn == null)
+ return null;
+ X500Name subjectDN = null;
+
+ try {
+ X509Certificate cert = (X509Certificate) obj;
+ subjectDN = (X500Name) cert.getSubjectDN();
+ CMS.debug("LdapCertSubjMap: cert subject dn:" + subjectDN.toString());
+ } catch (ClassCastException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_NOT_SUPPORTED_OBJECT"));
+ return v;
+ }
+ try {
+ String[] attrs = new String[] { LDAPv3.NO_ATTRS };
+
+ log(ILogger.LL_INFO, "search " + mSearchBase +
+ " (" + mCertSubjNameAttr + "=" + subjectDN + ") " + mCertSubjNameAttr);
+
+ LDAPSearchResults results =
+ conn.search(mSearchBase, LDAPv2.SCOPE_SUB,
+ "(" + mCertSubjNameAttr + "=" + subjectDN + ")", attrs, false);
+
+ while (results.hasMoreElements()) {
+ LDAPEntry entry = results.next();
+ String dn = entry.getDN();
+ v.addElement(dn);
+ CMS.debug("LdapCertSubjMap: dn=" + dn);
+ }
+ CMS.debug("LdapCertSubjMap: Number of entries: " + v.size());
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_DN_MAP_EXCEPTION", "LDAPException", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH_FOUND", e.toString()));
+ }
+ }
+
+ return v;
+ }
+
+ public Vector<String> mapAll(LDAPConnection conn, IRequest req, Object obj)
+ throws ELdapException {
+ return mapAll(conn, obj);
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "LdapCertSubjMap: " + msg);
+ }
+
+ /**
+ * return search base
+ */
+ public String getSearchBase() {
+ return mSearchBase;
+ }
+
+ /**
+ * return certificate subject attribute
+ */
+ public String getCertSubjNameAttr() {
+ return mCertSubjNameAttr;
+ }
+
+ public boolean useAllEntries() {
+ return mUseAllEntries;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCrlIssuerCompsMap.java b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCrlIssuerCompsMap.java
new file mode 100644
index 000000000..ca5903ee0
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapCrlIssuerCompsMap.java
@@ -0,0 +1,155 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.mappers;
+
+import java.security.cert.CRLException;
+import java.util.Vector;
+
+import netscape.ldap.LDAPConnection;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CRLImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapMapper;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * Default crl mapper.
+ * maps the crl to a ldap entry by using components in the issuer name
+ * to find the CA's entry.
+ *
+ * @version $Revision$, $Date$
+ */
+public class LdapCrlIssuerCompsMap
+ extends LdapDNCompsMap implements ILdapMapper {
+ ILogger mLogger = CMS.getLogger();
+
+ public LdapCrlIssuerCompsMap() {
+ // need to support baseDN, dnComps, and filterComps
+ // via configuration
+ }
+
+ /**
+ * Constructor.
+ *
+ * The DN comps are used to form a LDAP entry to begin a subtree search.
+ * The filter comps are used to form a search filter for the subtree.
+ * If none of the DN comps matched, baseDN is used for the subtree.
+ * If the baseDN is null and none of the DN comps matched, it is an error.
+ * If none of the DN comps and filter comps matched, it is an error.
+ * If just the filter comps is null, a base search is performed.
+ *
+ * @param baseDN The base DN.
+ * @param dnComps Components to form the LDAP base dn for search.
+ * @param filterComps Components to form the LDAP search filter.
+ */
+ public LdapCrlIssuerCompsMap(String baseDN, ObjectIdentifier[] dnComps,
+ ObjectIdentifier[] filterComps) {
+ init(baseDN, dnComps, filterComps);
+ }
+
+ /**
+ * constructor using non-standard certificate attribute.
+ */
+ public LdapCrlIssuerCompsMap(String crlAttr, String baseDN,
+ ObjectIdentifier[] dnComps,
+ ObjectIdentifier[] filterComps) {
+ super(crlAttr, baseDN, dnComps, filterComps);
+ }
+
+ public String getImplName() {
+ return "LdapCrlIssuerCompsMap";
+ }
+
+ public String getDescription() {
+ return "LdapCrlIssuerCompsMap";
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = super.getDefaultParams();
+
+ //v.addElement("crlAttr=" + LdapCrlPublisher.LDAP_CRL_ATTR);
+ return v;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = super.getInstanceParams();
+
+ return v;
+ }
+
+ protected void init(String baseDN, ObjectIdentifier[] dnComps,
+ ObjectIdentifier[] filterComps) {
+ //mLdapAttr = LdapCrlPublisher.LDAP_CRL_ATTR;
+ super.init(baseDN, dnComps, filterComps);
+ }
+
+ /**
+ * Maps a crl to LDAP entry.
+ * Uses issuer DN components and filter components to form a DN and
+ * filter for a LDAP search.
+ * If the formed DN is null the baseDN will be used.
+ * If the formed DN is null and baseDN is null an error is thrown.
+ * If the filter is null a base search is performed.
+ * If both are null an error is thrown.
+ *
+ * @param conn - the LDAP connection.
+ * @param obj - the X509Certificate.
+ * @return the result. LdapCertMapResult is also used for CRL.
+ */
+ public String
+ map(LDAPConnection conn, Object obj)
+ throws ELdapException {
+ if (conn == null)
+ return null;
+ X509CRLImpl crl = (X509CRLImpl) obj;
+
+ try {
+ String result = null;
+ X500Name issuerDN = (X500Name) crl.getIssuerDN();
+
+ CMS.debug("LdapCrlIssuerCompsMap: " + issuerDN.toString());
+
+ byte[] crlbytes = crl.getEncoded();
+
+ result = super.map(conn, issuerDN, crlbytes);
+ return result;
+ } catch (CRLException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_CANT_DECODE_CRL", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_GET_DER_ENCODED_CRL_FAILED", e.toString()));
+ }
+ }
+
+ public String map(LDAPConnection conn, IRequest req, Object obj)
+ throws ELdapException {
+ return map(conn, obj);
+ }
+
+ /**
+ * overrides super's log().
+ */
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "LdapCrlCompsMap: " + msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/mappers/LdapDNCompsMap.java b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapDNCompsMap.java
new file mode 100644
index 000000000..96ff2a11e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapDNCompsMap.java
@@ -0,0 +1,457 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.mappers;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+import netscape.ldap.LDAPv3;
+import netscape.security.util.DerValue;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AVA;
+import netscape.security.x509.RDN;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X500NameAttrMap;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapPlugin;
+
+/**
+ * Maps a Subject name to an entry in the LDAP server.
+ * subject name to form the ldap search dn and filter.
+ * Takes a optional root search dn.
+ * The DN comps are used to form a LDAP entry to begin a subtree search.
+ * The filter comps are used to form a search filter for the subtree.
+ * If none of the DN comps matched, baseDN is used for the subtree.
+ * If the baseDN is null and none of the DN comps matched, it is an error.
+ * If none of the DN comps and filter comps matched, it is an error.
+ * If just the filter comps is null, a base search is performed.
+ *
+ * @version $Revision$, $Date$
+ */
+public class LdapDNCompsMap
+ implements ILdapPlugin, IExtendedPluginInfo {
+ //protected String mLdapAttr = null;
+ protected String mBaseDN = null;
+ protected ObjectIdentifier[] mDnComps = null;
+ protected ObjectIdentifier[] mFilterComps = null;
+
+ private ILogger mLogger = CMS.getLogger();
+ private boolean mInited = false;
+ protected IConfigStore mConfig = null;
+
+ /**
+ * Constructor.
+ *
+ * The DN comps are used to form a LDAP entry to begin a subtree search.
+ * The filter comps are used to form a search filter for the subtree.
+ * If none of the DN comps matched, baseDN is used for the subtree.
+ * If the baseDN is null and none of the DN comps matched, it is an error.
+ * If none of the DN comps and filter comps matched, it is an error.
+ * If just the filter comps is null, a base search is performed.
+ *
+ * @param baseDN The base DN.
+ * @param dnComps Components to form the LDAP base dn for search.
+ * @param filterComps Components to form the LDAP search filter.
+ */
+ public LdapDNCompsMap(String ldapAttr, String baseDN,
+ ObjectIdentifier[] dnComps,
+ ObjectIdentifier[] filterComps) {
+ //mLdapAttr = ldapAttr;
+ init(baseDN, dnComps, filterComps);
+ }
+
+ /**
+ * constructor if initializing from config store.
+ */
+ public LdapDNCompsMap() {
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * for initializing from config store.
+ */
+ public void init(IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+ String baseDN = mConfig.getString("baseDN");
+ ObjectIdentifier[] dnComps =
+ getCompsFromString(mConfig.getString("dnComps"));
+ ObjectIdentifier[] filterComps =
+ getCompsFromString(mConfig.getString("filterComps"));
+
+ init(baseDN, dnComps, filterComps);
+ }
+
+ public String getImplName() {
+ return "LdapDNCompsMap";
+ }
+
+ public String getDescription() {
+ return "LdapDNCompsMap";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] s = {
+ "baseDN;string;Base to search from. E.g ou=Engineering,o=Fedora",
+ "dnComps;string;Comma-separated list of attributes to put in the DN",
+ "filterComps;string;Comma-separated list of attributes to form the filter",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ldappublish-mapper-dncompsmapper",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";More complex mapper. Used when there is not enough information " +
+ "in the cert request to form the complete LDAP DN. Using this " +
+ "plugin, you can specify additional LDAP filters to narrow down the " +
+ "search"
+ };
+
+ return s;
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement("baseDN=");
+ v.addElement("dnComps=");
+ v.addElement("filterComps=");
+ return v;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ try {
+ if (mBaseDN == null) {
+ v.addElement("baseDN=");
+ } else {
+ v.addElement("baseDN=" + mConfig.getString("baseDN"));
+ }
+ if (mDnComps == null) {
+ v.addElement("dnComps=");
+ } else {
+ v.addElement("dnComps=" +
+ mConfig.getString("dnComps"));
+ }
+ if (mFilterComps == null) {
+ v.addElement("filterComps=");
+ } else {
+ v.addElement("filterComps=" +
+ mConfig.getString("filterComps"));
+ }
+ } catch (Exception e) {
+ }
+ return v;
+ }
+
+ /**
+ * common initialization routine.
+ */
+ protected void init(String baseDN, ObjectIdentifier[] dnComps,
+ ObjectIdentifier[] filterComps) {
+ if (mInited)
+ return;
+
+ mBaseDN = baseDN;
+ if (dnComps != null)
+ mDnComps = dnComps.clone();
+ if (filterComps != null)
+ mFilterComps = filterComps.clone();
+
+ // log debug info.
+ for (int i = 0; i < mDnComps.length; i++) {
+ CMS.debug(
+ "LdapDNCompsMap: dnComp " + X500NameAttrMap.getDefault().getName(mDnComps[i]));
+ }
+ for (int i = 0; i < mFilterComps.length; i++) {
+ CMS.debug("LdapDNCompsMap: filterComp " +
+ X500NameAttrMap.getDefault().getName(mFilterComps[i]));
+ }
+ mInited = true;
+ }
+
+ /**
+ * Maps a X500 subject name to LDAP entry.
+ * Uses DN components and filter components to form a DN and
+ * filter for a LDAP search.
+ * If the formed DN is null the baseDN will be used.
+ * If the formed DN is null and baseDN is null an error is thrown.
+ * If the filter is null a base search is performed.
+ * If both are null an error is thrown.
+ *
+ * @param conn the LDAP connection.
+ * @param x500name the dn to map.
+ * @param obj the object
+ * @exception ELdapException if any LDAP exceptions occured.
+ * @return the DN of the entry.
+ */
+ public String map(LDAPConnection conn, X500Name x500name,
+ byte[] obj)
+ throws ELdapException {
+ try {
+ if (conn == null)
+ return null;
+
+ CMS.debug("LdapDNCompsMap: " + x500name.toString());
+
+ String[] dnAndFilter = formDNandFilter(x500name);
+ String dn = dnAndFilter[0];
+ String filter = dnAndFilter[1];
+
+ if (dn == null) {
+ // #362332
+ // if (filter == null) {
+ // log(ILogger.LL_FAILURE, "No dn and filter formed");
+ // throw new ELdapException(
+ // LdapResources.NO_DN_AND_FILTER_COMPS,
+ // x500name.toString());
+ // }
+ if (mBaseDN == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_BASE"));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_NO_DN_COMPS_AND_BASEDN",
+ x500name.toString()));
+ }
+ dn = mBaseDN;
+ }
+ int scope = LDAPv2.SCOPE_SUB;
+
+ if (filter == null) {
+ scope = LDAPv2.SCOPE_BASE;
+ filter = "(objectclass=*)";
+ }
+
+ // search for entry
+ String[] attrs;
+
+ attrs = new String[] { LDAPv3.NO_ATTRS };
+
+ log(ILogger.LL_INFO, "searching for " + dn + " " + filter + " " +
+ ((scope == LDAPv2.SCOPE_SUB) ? "sub" : "base"));
+
+ LDAPSearchResults results =
+ conn.search(dn, scope, filter, attrs, false);
+ LDAPEntry entry = results.next();
+
+ if (results.hasMoreElements()) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_MORE_THAN_ONE_ENTRY", "", x500name.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_MORE_THAN_ONE_ENTRY",
+ x500name.toString()));
+ }
+ if (entry != null) {
+ return entry.getDN();
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_ENTRY_NOT_FOUND", "", x500name.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH_FOUND",
+ "null entry"));
+ }
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_DN_MAP_EXCEPTION", "LDAPException", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH_FOUND", e.toString()));
+ }
+ }
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "LdapDNCompsMap: " + msg);
+ }
+
+ /**
+ * form a dn and filter from component in the cert subject name
+ *
+ * @param subjName subject name
+ */
+ public String[] formDNandFilter(X500Name subjName)
+ throws ELdapException {
+ Vector<RDN> dnRdns = new Vector<RDN>();
+ SearchFilter filter = new SearchFilter();
+ X500NameAttrMap attrMap = X500NameAttrMap.getDefault();
+ String dnStr = null, filterStr = null;
+ ObjectIdentifier EOid = attrMap.getOid("E");
+ ObjectIdentifier mailOid = attrMap.getOid("MAIL");
+
+ try {
+ // get the base DN & filter.
+ for (Enumeration<RDN> n = subjName.getRDNs(); n.hasMoreElements();) {
+ RDN rdn = n.nextElement();
+ // NOTE assumes one AVA per RDN.
+ AVA ava = rdn.getAssertion()[0];
+ ObjectIdentifier oid = ava.getOid();
+
+ for (int i = 0; i < mDnComps.length; i++) {
+ if (mDnComps[i].equals(oid)) {
+ if (oid == EOid) {
+ DerValue val = ava.getValue();
+ AVA newAVA = new AVA(mailOid, val);
+ RDN newRDN = new RDN(new AVA[] { newAVA }
+ );
+
+ CMS.debug(
+ "LdapDNCompsMap: Converted " + rdn.toLdapDNString() + " to " +
+ newRDN.toLdapDNString() + " in DN");
+ rdn = newRDN;
+ }
+ dnRdns.addElement(rdn);
+ CMS.debug(
+ "LdapDNCompsMap: adding dn comp " + rdn.toLdapDNString());
+ break;
+ }
+ }
+ for (int i = 0; i < mFilterComps.length; i++) {
+ if (mFilterComps[i].equals(oid)) {
+ if (oid == EOid) {
+ DerValue val = ava.getValue();
+ AVA newAVA = new AVA(mailOid, val);
+
+ CMS.debug(
+ "LdapDNCompsMap: Converted " + ava.toLdapDNString() + " to " +
+ newAVA.toLdapDNString() + " in filter");
+ ava = newAVA;
+ }
+ filter.addElement(ava.toLdapDNString());
+ CMS.debug(
+ "LdapDNCompsMap: adding filter comp " + ava.toLdapDNString());
+ break;
+ }
+ }
+
+ // XXX should be an error when string is null?
+ // return to caller to decide.
+ if (dnRdns.size() != 0) {
+ dnStr = new X500Name(dnRdns).toLdapDNString();
+ }
+ if (filter.size() != 0) {
+ filterStr = filter.toFilterString();
+ }
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_FROM_SUBJ_TO_DN", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FORM_DN_COMPS_FAILED", e.toString()));
+ }
+
+ return new String[] { dnStr, filterStr };
+ }
+
+ public ObjectIdentifier[] getDnComps() {
+ return mDnComps.clone();
+ }
+
+ public ObjectIdentifier[] getFilterComps() {
+ return mFilterComps.clone();
+ }
+
+ /**
+ * class for forming search filters for ldap searching from
+ * name=value components. components are anded.
+ */
+
+ public static class SearchFilter extends Vector<Object> {
+ private static final long serialVersionUID = 4210302171279891828L;
+
+ public String toFilterString() {
+ StringBuffer buf = new StringBuffer();
+
+ if (elementCount == 0) {
+ return null;
+ }
+ if (elementCount == 1) {
+ buf.append("(" + (String) elementData[0] + ")");
+ return buf.toString();
+ }
+ buf.append("(&");
+ for (int i = 0; i < elementCount; i++) {
+ buf.append("(" + (String) elementData[i] + ")");
+ }
+ buf.append(")");
+ return buf.toString();
+ }
+ }
+
+ /**
+ * useful routine for parsing components given as string to
+ * arrays of objectidentifiers.
+ * The string is expected to be comma separated AVA attribute names.
+ * For example, "uid,cn,o,ou". Attribute names are case insensitive.
+ *
+ * @param val the string specifying the comps
+ * @exception ELdapException if any error occurs.
+ */
+ public static ObjectIdentifier[] getCompsFromString(String val)
+ throws ELdapException {
+ StringTokenizer tokens;
+ ObjectIdentifier[] comps;
+ String attr;
+ ObjectIdentifier oid;
+
+ if (val == null || val.length() == 0)
+ return new ObjectIdentifier[0];
+
+ tokens = new StringTokenizer(val, ", \t\n\r");
+ comps = new ObjectIdentifier[tokens.countTokens()];
+ if (comps.length == 0) {
+ return new ObjectIdentifier[0];
+ }
+ int i = 0;
+
+ while (tokens.hasMoreTokens()) {
+ attr = tokens.nextToken().trim();
+ // mail -> E hack to look for E in subject names.
+ if (attr.equalsIgnoreCase("mail"))
+ attr = "E";
+ oid = X500NameAttrMap.getDefault().getOid(attr);
+ if (oid != null) {
+ comps[i++] = oid;
+ } else {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_UNKNOWN_ATTR_IN_DN_FILTER_COMPS", attr));
+ }
+ }
+ return comps;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/mappers/LdapEnhancedMap.java b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapEnhancedMap.java
new file mode 100644
index 000000000..a970602bd
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapEnhancedMap.java
@@ -0,0 +1,635 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cms.publish.mappers;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+/* cert server imports */
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+import netscape.ldap.LDAPv3;
+import netscape.ldap.util.DN;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CRLImpl;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapMapper;
+import com.netscape.certsrv.request.IRequest;
+
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * Maps a request to an entry in the LDAP server.
+ * Takes a dnPattern to form the baseDN from the
+ * request attributes and certificate subject name.
+ * Does a base search for the entry in the directory
+ * to publish the cert or crl. The restriction of
+ * this mapper is that the ldap dn components must
+ * be part of certificate subject name or request
+ * attributes or constant. The difference of this
+ * mapper and LdapSimpleMap is that if the ldap
+ * entry is not found, it has the option to create
+ * the ldap entry given the dn and attributes
+ * formulated.
+ *
+ * @version $Revision$, $Date$
+ */
+public class LdapEnhancedMap
+ implements ILdapMapper, IExtendedPluginInfo {
+ ////////////////////////
+ // default parameters //
+ ////////////////////////
+
+ //////////////////////////////////////
+ // local LdapEnhancedMap parameters //
+ //////////////////////////////////////
+
+ private boolean mInited = false;
+
+ // the subject DN pattern
+ protected MapDNPattern mPattern = null;
+
+ // the list of request attriubutes to retrieve
+ protected String[] mReqAttrs = null;
+
+ // the list of cert attributes to retrieve
+ protected String[] mCertAttrs = null;
+
+ protected String[] mLdapValues = null;
+
+ ////////////////////////////
+ // ILdapMapper parameters //
+ ////////////////////////////
+
+ /* mapper plug-in fields */
+ protected static final String PROP_DNPATTERN = "dnPattern";
+ protected static final String PROP_CREATE = "createEntry";
+ // the object class of the entry to be created. xxxx not done yet
+ protected static final String PROP_OBJCLASS = "objectClass";
+ // req/cert/ext attribute --> directory attribute table
+ protected static final String PROP_ATTRNUM = "attrNum";
+ protected static final String PROP_ATTR_NAME = "attrName";
+ protected static final String PROP_ATTR_PATTERN = "attrPattern";
+
+ /* mapper plug-in fields initialization values */
+ private static final int DEFAULT_NUM_ATTRS = 1;
+
+ /* Holds mapper plug-in fields accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ private static Vector<String> defaultParams = new Vector<String>();
+
+ static {
+ defaultParams.addElement(PROP_DNPATTERN + "=");
+ defaultParams.addElement(PROP_CREATE + "=true");
+ defaultParams.addElement(PROP_ATTRNUM + "=" + DEFAULT_NUM_ATTRS);
+ for (int i = 0; i < DEFAULT_NUM_ATTRS; i++) {
+ defaultParams.addElement(PROP_ATTR_NAME + i + "=");
+ defaultParams.addElement(PROP_ATTR_PATTERN + i + "=");
+ }
+ }
+
+ /* mapper plug-in values */
+ protected String mDnPattern = null;
+ protected boolean mCreateEntry = true;
+ private int mNumAttrs = DEFAULT_NUM_ATTRS;
+ protected String[] mLdapNames = null;
+ protected String[] mLdapPatterns = null;
+
+ /* miscellaneous constants local to this mapper plug-in */
+ // default dn pattern if left blank or not set in the config
+ public static final String DEFAULT_DNPATTERN =
+ "UID=$req.HTTP_PARAMS.UID, " +
+ "OU=people, O=$subj.o, C=$subj.c";
+ private static final int MAX_ATTRS = 10;
+ protected static final int DEFAULT_ATTRNUM = 1;
+
+ /* miscellaneous variables local to this mapper plug-in */
+ protected IConfigStore mConfig = null;
+ protected AVAPattern[] mPatterns = null;
+
+ ////////////////////////////////////
+ // IExtendedPluginInfo parameters //
+ ////////////////////////////////////
+
+ ///////////////////////
+ // Logger parameters //
+ ///////////////////////
+
+ private ILogger mLogger = CMS.getLogger();
+
+ /////////////////////
+ // default methods //
+ /////////////////////
+
+ /**
+ * Default constructor, initialization must follow.
+ */
+ public LdapEnhancedMap() {
+ }
+
+ ///////////////////////////////////
+ // local LdapEnhancedMap methods //
+ ///////////////////////////////////
+
+ /**
+ * common initialization routine.
+ */
+ protected void init(String dnPattern)
+ throws EBaseException {
+ if (mInited) {
+ return;
+ }
+
+ mDnPattern = dnPattern;
+ if (mDnPattern == null ||
+ mDnPattern.length() == 0) {
+ mDnPattern = DEFAULT_DNPATTERN;
+ }
+
+ try {
+ mPattern = new MapDNPattern(mDnPattern);
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_DN_PATTERN_INIT",
+ dnPattern, e.toString()));
+ throw new EBaseException(
+ "falied to init with pattern " +
+ dnPattern + " " + e);
+ }
+
+ mInited = true;
+ }
+
+ /**
+ * form a dn from component in the request and cert subject name
+ *
+ * @param req The request
+ * @param obj The certificate or crl
+ */
+ private String formDN(IRequest req, Object obj)
+ throws EBaseException {
+ CertificateExtensions certExt = null;
+ X500Name subjectDN = null;
+
+ try {
+ X509Certificate cert = (X509Certificate) obj;
+ subjectDN = (X500Name) cert.getSubjectDN();
+ CMS.debug(
+ "LdapEnhancedMap: cert subject dn:" +
+ subjectDN.toString());
+
+ //certExt = (CertificateExtensions)
+ // ((X509CertImpl)cert).get(
+ // X509CertInfo.EXTENSIONS);
+ X509CertInfo info = (X509CertInfo)
+ ((X509CertImpl) cert).get(
+ X509CertImpl.NAME +
+ "." +
+ X509CertImpl.INFO);
+
+ certExt = (CertificateExtensions)
+ info.get(CertificateExtensions.NAME);
+ } catch (java.security.cert.CertificateParsingException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_CANT_GET_EXT", e.toString()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_CANT_GET_EXT", e.toString()));
+ } catch (java.security.cert.CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_CANT_GET_EXT", e.toString()));
+ } catch (ClassCastException e) {
+
+ try {
+ X509CRLImpl crl = (X509CRLImpl) obj;
+ subjectDN = (X500Name) crl.getIssuerDN();
+
+ CMS.debug(
+ "LdapEnhancedMap: crl issuer dn: " +
+ subjectDN.toString());
+ } catch (ClassCastException ex) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_PUBLISH_OBJ_NOT_SUPPORTED",
+ ((req == null) ? ""
+ : req.getRequestId().toString())));
+ return null;
+ }
+ }
+
+ try {
+ mLdapValues = new String[mNumAttrs];
+
+ for (int i = 0; i < mNumAttrs; i++) {
+ if (mPatterns[i] != null) {
+ mLdapValues[i] = mPatterns[i].formAVA(
+ req,
+ subjectDN,
+ certExt);
+ }
+ }
+
+ String dn = mPattern.formDN(req, subjectDN, certExt);
+
+ return dn;
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_CANT_FORM_DN",
+ ((req == null) ? ""
+ : req.getRequestId().toString()), e.toString()));
+
+ throw new EBaseException(
+ "failed to form dn for request: " +
+ ((req == null) ? ""
+ : req.getRequestId().toString()) +
+ " " + e);
+ }
+ }
+
+ private void createEntry(LDAPConnection conn, String dn)
+ throws LDAPException {
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+
+ // OID 2.5.6.16
+ String caOc[] = { "top",
+ "person",
+ "organizationalPerson",
+ "inetOrgPerson" };
+
+ DN dnobj = new DN(dn);
+ String attrval[] = dnobj.explodeDN(true);
+
+ attrs.add(new LDAPAttribute("cn", attrval[0]));
+ attrs.add(new LDAPAttribute("sn", attrval[0]));
+ attrs.add(new LDAPAttribute("objectclass", caOc));
+
+ for (int i = 0; i < mNumAttrs; i++) {
+ if (mLdapNames[i] != null &&
+ !mLdapNames[i].trim().equals("") &&
+ mLdapValues[i] != null &&
+ !mLdapValues[i].trim().equals("")) {
+ attrs.add(new LDAPAttribute(mLdapNames[i],
+ mLdapValues[i]));
+ }
+ }
+
+ LDAPEntry entry = new LDAPEntry(dn, attrs);
+
+ conn.add(entry);
+ }
+
+ /////////////////////////
+ // ILdapMapper methods //
+ /////////////////////////
+
+ /**
+ * for initializing from config store.
+ *
+ * implementation for extended
+ * ILdapPlugin interface method
+ */
+ public void init(IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+
+ mDnPattern = mConfig.getString(PROP_DNPATTERN,
+ DEFAULT_DNPATTERN);
+
+ mCreateEntry = mConfig.getBoolean(PROP_CREATE,
+ true);
+
+ mNumAttrs = mConfig.getInteger(PROP_ATTRNUM,
+ 0);
+
+ mLdapNames = new String[mNumAttrs];
+
+ mLdapPatterns = new String[mNumAttrs];
+
+ mPatterns = new AVAPattern[mNumAttrs];
+ for (int i = 0; i < mNumAttrs; i++) {
+ mLdapNames[i] =
+ mConfig.getString(PROP_ATTR_NAME +
+ Integer.toString(i),
+ "");
+
+ mLdapPatterns[i] =
+ mConfig.getString(PROP_ATTR_PATTERN +
+ Integer.toString(i),
+ "");
+
+ if (mLdapPatterns[i] != null &&
+ !mLdapPatterns[i].trim().equals("")) {
+ mPatterns[i] = new AVAPattern(mLdapPatterns[i]);
+ }
+ }
+
+ init(mDnPattern);
+ }
+
+ /**
+ * implementation for extended
+ * ILdapPlugin interface method
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public String getImplName() {
+ return "LdapEnhancedMap";
+ }
+
+ public String getDescription() {
+ return "LdapEnhancedMap";
+ }
+
+ public Vector<String> getDefaultParams() {
+ return defaultParams;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ try {
+ if (mDnPattern == null) {
+ v.addElement(PROP_DNPATTERN + "=");
+ } else {
+ v.addElement(PROP_DNPATTERN + "=" +
+ mConfig.getString(PROP_DNPATTERN));
+ }
+
+ v.addElement(PROP_CREATE + "=" +
+ mConfig.getBoolean(PROP_CREATE,
+ true));
+
+ v.addElement(PROP_ATTRNUM + "=" +
+ mConfig.getInteger(PROP_ATTRNUM,
+ DEFAULT_NUM_ATTRS));
+
+ for (int i = 0; i < mNumAttrs; i++) {
+ if (mLdapNames[i] != null) {
+ v.addElement(PROP_ATTR_NAME + i +
+ "=" + mLdapNames[i]);
+ } else {
+ v.addElement(PROP_ATTR_NAME + i +
+ "=");
+ }
+
+ if (mLdapPatterns[i] != null) {
+ v.addElement(PROP_ATTR_PATTERN + i +
+ "=" + mLdapPatterns[i]);
+ } else {
+ v.addElement(PROP_ATTR_PATTERN + i +
+ "=");
+ }
+ }
+ } catch (Exception e) {
+ }
+
+ return v;
+ }
+
+ /**
+ * Maps an X500 subject name to an LDAP entry.
+ * Uses DN pattern to form a DN for an LDAP base search.
+ *
+ * @param conn the LDAP connection.
+ * @param obj the object to map.
+ * @exception ELdapException if any LDAP exceptions occurred.
+ */
+ public String map(LDAPConnection conn, Object obj)
+ throws ELdapException {
+ return map(conn, null, obj);
+ }
+
+ /**
+ * Maps an X500 subject name to an LDAP entry.
+ * Uses DN pattern to form a DN for an LDAP base search.
+ *
+ * @param conn the LDAP connection.
+ * @param req the request to map.
+ * @param obj the object to map.
+ * @exception ELdapException if any LDAP exceptions occurred.
+ */
+ public String map(LDAPConnection conn, IRequest req, Object obj)
+ throws ELdapException {
+ if (conn == null) {
+ return null;
+ }
+
+ String dn = null;
+
+ try {
+ dn = formDN(req, obj);
+ if (dn == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_DN_NOT_FORMED"));
+
+ String s1 = "";
+
+ if (req != null)
+ s1 = req.getRequestId().toString();
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_NO_DN_MATCH", s1));
+ }
+
+ int scope = LDAPv2.SCOPE_BASE;
+ String filter = "(objectclass=*)";
+
+ // search for entry
+ String[] attrs = new String[] { LDAPv3.NO_ATTRS };
+
+ log(ILogger.LL_INFO,
+ "searching for dn: " +
+ dn + " filter:" +
+ filter + " scope: base");
+
+ LDAPSearchResults results = conn.search(dn,
+ scope,
+ filter,
+ attrs,
+ false);
+
+ LDAPEntry entry = results.next();
+
+ if (results.hasMoreElements()) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_MORE_THAN_ONE_ENTRY",
+ dn +
+ ((req == null) ? ""
+ : req.getRequestId().toString())));
+
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_MORE_THAN_ONE_ENTRY",
+ ((req == null) ? ""
+ : req.getRequestId().toString())));
+ }
+
+ if (entry != null) {
+ return entry.getDN();
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_ENTRY_NOT_FOUND",
+ dn +
+ ((req == null) ? ""
+ : req.getRequestId().toString())));
+
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH_FOUND",
+ "null entry"));
+ }
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else if (e.getLDAPResultCode() ==
+ LDAPException.NO_SUCH_OBJECT && mCreateEntry) {
+
+ try {
+ createEntry(conn, dn);
+
+ log(ILogger.LL_INFO,
+ "Entry " +
+ dn +
+ " Created");
+
+ return dn;
+ } catch (LDAPException e1) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_DN_MAP_EXCEPTION",
+ dn,
+ e.toString()));
+
+ log(ILogger.LL_FAILURE,
+ "Entry is not created. " +
+ "This may because there are " +
+ "entries in the directory " +
+ "hierachy not exit.");
+
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_CREATE_ENTRY", dn));
+ }
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_DN_MAP_EXCEPTION",
+ dn,
+ e.toString()));
+
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH_FOUND", e.toString()));
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_EXCEPTION_CAUGHT",
+ e.toString()));
+
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH_FOUND", e.toString()));
+ }
+ }
+
+ /////////////////////////////////
+ // IExtendedPluginInfo methods //
+ /////////////////////////////////
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(PROP_DNPATTERN +
+ ";string;Describes how to form the Ldap " +
+ "Subject name in the directory. " +
+ "Example 1: 'uid=CertMgr, o=Fedora'. " +
+ "Example 2: 'uid=$req.HTTP_PARAMS.uid, " +
+ "E=$ext.SubjectAlternativeName.RFC822Name, " +
+ "ou=$subj.ou'. " +
+ "$req means: take the attribute from the " +
+ "request. " +
+ "$subj means: take the attribute from the " +
+ "certificate subject name. " +
+ "$ext means: take the attribute from the " +
+ "certificate extension");
+ v.addElement(PROP_CREATE +
+ ";boolean;If checked, An entry will be " +
+ "created automatically");
+ v.addElement(PROP_ATTRNUM +
+ ";string;How many attributes to add.");
+ v.addElement(IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ldappublish-mapper-enhancedmapper");
+ v.addElement(IExtendedPluginInfo.HELP_TEXT +
+ ";Describes how to form the LDAP DN of the " +
+ "entry to publish to");
+
+ for (int i = 0; i < MAX_ATTRS; i++) {
+ v.addElement(PROP_ATTR_NAME +
+ Integer.toString(i) +
+ ";string;" +
+ "The name of LDAP attribute " +
+ "to be added. e.g. mail");
+ v.addElement(PROP_ATTR_PATTERN +
+ Integer.toString(i) +
+ ";string;" +
+ "How to create the LDAP attribute value. " +
+ "e.g. $req.HTTP_PARAMS.csrRequestorEmail, " +
+ "$subj.E or " +
+ "$ext.SubjectAlternativeName.RFC822Name");
+ }
+
+ String params[] =
+ com.netscape.cmsutil.util.Utils.getStringArrayFromVector(v);
+
+ return params;
+ }
+
+ ////////////////////
+ // Logger methods //
+ ////////////////////
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "LdapEnhancedMapper: " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/mappers/LdapSimpleMap.java b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapSimpleMap.java
new file mode 100644
index 000000000..8f88ffaba
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/mappers/LdapSimpleMap.java
@@ -0,0 +1,328 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.mappers;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+import netscape.ldap.LDAPv3;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CRLImpl;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapMapper;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * Maps a request to an entry in the LDAP server.
+ * Takes a dnPattern to form the baseDN from the request attributes
+ * and certificate subject name.Do a base search for the entry
+ * in the directory to publish the cert or crl.
+ * The restriction of this mapper is that the ldap dn components must
+ * be part of certificate subject name or request attributes or constant.
+ *
+ * @version $Revision$, $Date$
+ */
+public class LdapSimpleMap implements ILdapMapper, IExtendedPluginInfo {
+ protected static final String PROP_DNPATTERN = "dnPattern";
+ protected String mDnPattern = null;
+
+ private ILogger mLogger = CMS.getLogger();
+ private boolean mInited = false;
+ protected IConfigStore mConfig = null;
+
+ /* the subject DN pattern */
+ protected MapDNPattern mPattern = null;
+
+ /* the list of request attriubutes to retrieve*/
+ protected String[] mReqAttrs = null;
+
+ /* the list of cert attriubutes to retrieve*/
+ protected String[] mCertAttrs = null;
+
+ /* default dn pattern if left blank or not set in the config */
+ public static final String DEFAULT_DNPATTERN =
+ "UID=$req.HTTP_PARAMS.UID, OU=people, O=$subj.o, C=$subj.c";
+
+ /**
+ * Constructor.
+ *
+ * @param dnPattern The base DN.
+ */
+ public LdapSimpleMap(String dnPattern) {
+ try {
+ init(dnPattern);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+
+ }
+
+ /**
+ * constructor if initializing from config store.
+ */
+ public LdapSimpleMap() {
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String params[] = {
+ "dnPattern;string;Describes how to form the Ldap Subject name in" +
+ " the directory. Example 1: 'uid=CertMgr, o=Fedora'. Example 2:" +
+ " 'uid=$req.HTTP_PARAMS.uid, E=$ext.SubjectAlternativeName.RFC822Name, ou=$subj.ou'. " +
+ "$req means: take the attribute from the request. " +
+ "$subj means: take the attribute from the certificate subject name. " +
+ "$ext means: take the attribute from the certificate extension",
+ IExtendedPluginInfo.HELP_TOKEN + ";configuration-ldappublish-mapper-simplemapper",
+ IExtendedPluginInfo.HELP_TEXT + ";Describes how to form the LDAP DN of the entry to publish to"
+ };
+
+ return params;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * for initializing from config store.
+ */
+ public void init(IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+ String dnPattern = mConfig.getString(PROP_DNPATTERN);
+
+ init(dnPattern);
+ }
+
+ /**
+ * common initialization routine.
+ */
+ protected void init(String dnPattern)
+ throws EBaseException {
+ if (mInited)
+ return;
+
+ mDnPattern = dnPattern;
+ if (mDnPattern == null || mDnPattern.length() == 0)
+ mDnPattern = DEFAULT_DNPATTERN;
+ try {
+ mPattern = new MapDNPattern(mDnPattern);
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_DN_PATTERN_INIT",
+ dnPattern, e.toString()));
+ throw new EBaseException("falied to init with pattern " +
+ dnPattern + " " + e);
+ }
+
+ mInited = true;
+ }
+
+ /**
+ * Maps a X500 subject name to LDAP entry.
+ * Uses DN pattern to form a DN for a LDAP base search.
+ *
+ * @param conn the LDAP connection.
+ * @param obj the object to map.
+ * @exception ELdapException if any LDAP exceptions occured.
+ */
+ public String map(LDAPConnection conn, Object obj)
+ throws ELdapException {
+ return map(conn, null, obj);
+ }
+
+ /**
+ * Maps a X500 subject name to LDAP entry.
+ * Uses DN pattern to form a DN for a LDAP base search.
+ *
+ * @param conn the LDAP connection.
+ * @param req the request to map.
+ * @param obj the object to map.
+ * @exception ELdapException if any LDAP exceptions occured.
+ */
+ public String map(LDAPConnection conn, IRequest req, Object obj)
+ throws ELdapException {
+ if (conn == null)
+ return null;
+ String dn = null;
+
+ try {
+ dn = formDN(req, obj);
+ if (dn == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_DN_NOT_FORMED"));
+ String s1 = "";
+
+ if (req != null)
+ s1 = req.getRequestId().toString();
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_NO_DN_MATCH", s1));
+ }
+ int scope = LDAPv2.SCOPE_BASE;
+ String filter = "(objectclass=*)";
+
+ // search for entry
+ String[] attrs = new String[] { LDAPv3.NO_ATTRS };
+
+ log(ILogger.LL_INFO, "searching for dn: " + dn + " filter:"
+ + filter + " scope: base");
+
+ LDAPSearchResults results =
+ conn.search(dn, scope, filter, attrs, false);
+ LDAPEntry entry = results.next();
+
+ if (results.hasMoreElements()) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_MORE_THAN_ONE_ENTRY", dn, ((req == null) ? "" :
+ req.getRequestId().toString())));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_MORE_THAN_ONE_ENTRY",
+ ((req == null) ? "" : req.getRequestId().toString())));
+ }
+ if (entry != null)
+ return entry.getDN();
+ else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_ENTRY_NOT_FOUND", dn, ((req == null) ? "" : req.getRequestId()
+ .toString())));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH_FOUND",
+ "null entry"));
+ }
+ } catch (ELdapException e) {
+ throw e;
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_DN_MAP_EXCEPTION", "", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH_FOUND", e.toString()));
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_EXCEPTION_CAUGHT", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH_FOUND", e.toString()));
+ }
+ }
+
+ /**
+ * form a dn from component in the request and cert subject name
+ *
+ * @param req The request
+ * @param obj The certificate or crl
+ */
+ private String formDN(IRequest req, Object obj) throws
+ EBaseException, ELdapException {
+ X500Name subjectDN = null;
+ CertificateExtensions certExt = null;
+
+ try {
+ X509Certificate cert = (X509Certificate) obj;
+ subjectDN = (X500Name) cert.getSubjectDN();
+
+ CMS.debug("LdapSimpleMap: cert subject dn:" + subjectDN.toString());
+ //certExt = (CertificateExtensions)
+ // ((X509CertImpl)cert).get(X509CertInfo.EXTENSIONS);
+ X509CertInfo info = (X509CertInfo)
+ ((X509CertImpl) cert).get(
+ X509CertImpl.NAME + "." + X509CertImpl.INFO);
+
+ certExt = (CertificateExtensions) info.get(
+ CertificateExtensions.NAME);
+ } catch (java.security.cert.CertificateParsingException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_CANT_GET_EXT", e.toString()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_CANT_GET_EXT", e.toString()));
+ } catch (java.security.cert.CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_CANT_GET_EXT", e.toString()));
+ } catch (ClassCastException e) {
+ try {
+ X509CRLImpl crl = (X509CRLImpl) obj;
+ subjectDN = (X500Name) crl.getIssuerDN();
+
+ CMS.debug("LdapSimpleMap: crl issuer dn: " +
+ subjectDN.toString());
+ } catch (ClassCastException ex) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_PUBLISH_OBJ_NOT_SUPPORTED",
+ ((req == null) ? "" : req.getRequestId().toString())));
+ return null;
+ }
+ }
+ try {
+ String dn = mPattern.formDN(req, subjectDN, certExt);
+
+ return dn;
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_CANT_FORM_DN",
+ ((req == null) ? "" : req.getRequestId().toString()), e.toString()));
+ throw e;
+ }
+ }
+
+ public String getImplName() {
+ return "LdapSimpleMap";
+ }
+
+ public String getDescription() {
+ return "LdapSimpleMap";
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(PROP_DNPATTERN + "=");
+ return v;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ try {
+ if (mDnPattern == null) {
+ v.addElement(PROP_DNPATTERN + "=");
+ } else {
+ v.addElement(PROP_DNPATTERN + "=" +
+ mConfig.getString(PROP_DNPATTERN));
+ }
+ } catch (Exception e) {
+ }
+ return v;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "LdapSimpleMapper: " + msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/mappers/MapAVAPattern.java b/base/server/cms/src/com/netscape/cms/publish/mappers/MapAVAPattern.java
new file mode 100644
index 000000000..ea69cc5a1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/mappers/MapAVAPattern.java
@@ -0,0 +1,650 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.mappers;
+
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.StringReader;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.ldap.LDAPDN;
+import netscape.security.x509.AVA;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.Extension;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNameInterface;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.LdapV3DNStrConverter;
+import netscape.security.x509.OIDMap;
+import netscape.security.x509.SubjectAlternativeNameExtension;
+import netscape.security.x509.X500Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.publish.ECompSyntaxErr;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * class for parsing a DN pattern used to construct a ldap dn from
+ * request attributes and cert subject name.
+ * <p>
+ *
+ * dnpattern is a string representing a ldap dn pattern to formulate from the certificate subject name attributes and
+ * request attributes . If empty or not set, the certificate subject name will be used as the ldap dn.
+ * <p>
+ *
+ * The syntax is
+ *
+ * <pre>
+ * dnPattern := rdnPattern *[ "," rdnPattern ]
+ * rdnPattern := avaPattern *[ "+" avaPattern ]
+ * avaPattern := name "=" value |
+ * name "=" "$subj" "." attrName [ "." attrNumber ] |
+ * name "=" "$ext" "." extName [ "." nameType ] [ "." attrNumber ]
+ * name "=" "$req" "." attrName [ "." attrNumber ] |
+ * "$rdn" "." number
+ * </pre>
+ *
+ * <pre>
+ * Example1: <i>cn=Certificate Manager,ou=people,o=mcom.com</i>
+ * cert subject name: dn: CN=Certificate Manager, OU=people, O=mcom.com
+ * request attributes: uid: cmanager
+ * <p>
+ * The dn formulated will be : <br>
+ * CN=Certificate Manager, OU=people, O=mcom.com
+ * <p>
+ * note: Subordinate ca enrollment will use ca mapper. Use predicate
+ * to distinguish the ca itself and the subordinates.
+ *
+ * Example2: <i>UID=$req.HTTP_PARAMS.uid, OU=$subj.ou, OU=people, , O=mcom.com</i>
+ * cert subject name: dn: UID=jjames, OU=IS, OU=people, , O=mcom.com
+ * request attributes: uid: cmanager
+ * <p>
+ * The dn formulated will be : <br>
+ * UID=jjames, OU=IS, OU=people, O=mcom.com
+ * <p>
+ * UID = the 'uid' attribute value in the request. <br>
+ * OU = the 'ou' value in the cert subject name. <br>
+ * O = the string mcom.com. <br>
+ * <p>
+ * Example3: <i>UID=$req.HTTP_PARAMS.uid, E=$ext.SubjectAlternativeName.RFC822Name.1, O=mcom.com</i>
+ * cert subject name: dn: UID=jjames, OU=IS, OU=people, O=mcom.com
+ * cert subjectAltName is rfc822Name: jjames@mcom.com
+ * request attributes: uid: cmanager
+ * <p>
+ * The dn formulated will be : <br>
+ * UID=jjames, E=jjames@mcom.com, O=mcom.com
+ * <p>
+ * UID = the 'uid' attribute value in the request. <br>
+ * E = The first rfc822name value in the subjAltName extension. <br>
+ * O = the string mcom.com. <br>
+ * <p>
+ * </pre>
+ *
+ * If an request attribute or subject DN component does not exist, the attribute is skipped. There is potential risk
+ * that a wrong dn will be mapped into.
+ *
+ * @version $Revision$, $Date$
+ */
+class MapAVAPattern {
+
+ /* the value type of the dn component */
+ public static final String TYPE_REQ = "$req";
+ public static final String TYPE_SUBJ = "$subj";
+ public static final String TYPE_EXT = "$ext";
+ public static final String TYPE_RDN = "$rdn";
+ public static final String TYPE_CONSTANT = "constant";
+
+ public static final String[] GENERAL_NAME_TYPE = { "ANY",
+ "RFC822Name",
+ "DNSName",
+ "X400Name",
+ "DIRECTORYName",
+ "EDIName",
+ "URIName",
+ "IPAddress",
+ "OIDName" };
+
+ private static final LdapV3DNStrConverter mLdapDNStrConverter =
+ new LdapV3DNStrConverter();
+
+ /* the list of request attributes needed by this AVA */
+ protected String[] mReqAttrs = null;
+
+ /* the list of cert attributes needed by this AVA*/
+ protected String[] mCertAttrs = null;
+
+ /* value type */
+ protected String mType = null;
+
+ /* the attribute in the AVA pair */
+ protected String mAttr = null;
+
+ /* value - could be name of a request attribute or
+ * cert subject dn attribute. */
+ protected String mValue = null;
+
+ /* value type - general name type of an extension attribute if any. */
+ protected String mGNType = null;
+
+ /* prefix - prefix of a request attribute if any. */
+ protected String mPrefix = null;
+
+ /* nth value of the ldap or dn attribute */
+ protected int mElement = 0;
+
+ protected String mTestDN = null;
+
+ public MapAVAPattern(String component)
+ throws ELdapException {
+ if (component == null || component.length() == 0)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX", component));
+ parse(new PushbackReader(new StringReader(component)));
+ }
+
+ public MapAVAPattern(PushbackReader in)
+ throws ELdapException {
+ parse(in);
+ }
+
+ private void parse(PushbackReader in)
+ throws ELdapException {
+ int c;
+
+ // mark ava beginning.
+
+ // skip spaces
+ //System.out.println("============ AVAPattern Begin ===========");
+ //System.out.println("skip spaces");
+
+ try {
+ while ((c = in.read()) == ' ' || c == '\t') {//System.out.println("spaces read "+(char)c);
+ ;
+ }
+ } catch (IOException e) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX", "All blank"));
+ }
+ if (c == -1)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX", "All blank"));
+
+ // $rdn "." number syntax.
+
+ if (c == '$') {
+ //System.out.println("$rdn syntax");
+ mType = TYPE_RDN;
+ try {
+ if (in.read() != 'r' ||
+ in.read() != 'd' ||
+ in.read() != 'n' ||
+ in.read() != '.')
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "Invalid $ syntax, expecting $rdn"));
+ } catch (IOException e) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "Invalid $ syntax, expecting $rdn"));
+ }
+
+ StringBuffer rdnNumberBuf = new StringBuffer();
+
+ try {
+ while ((c = in.read()) != ',' && c != -1 && c != '+') {
+ //System.out.println("rdnNumber read "+(char)c);
+ rdnNumberBuf.append((char) c);
+ }
+ if (c != -1) // either ',' or '+'
+ in.unread(c);
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+
+ String rdnNumber = rdnNumberBuf.toString().trim();
+
+ if (rdnNumber.length() == 0)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "$rdn number not set in ava pattern"));
+ try {
+ mElement = Integer.parseInt(rdnNumber) - 1;
+ } catch (NumberFormatException e) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "Invalid $rdn number in ava pattern"));
+ }
+ return;
+ }
+
+ // name "=" ... syntax.
+
+ // read name
+ //System.out.println("reading name");
+
+ StringBuffer attrBuf = new StringBuffer();
+
+ try {
+ while (c != '=' && c != -1 && c != ',' && c != '+') {
+ attrBuf.append((char) c);
+ c = in.read();
+ //System.out.println("name read "+(char)c);
+ }
+ if (c == ',' || c == '+')
+ in.unread(c);
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+ if (c != '=')
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "Missing \"=\" in ava pattern"));
+
+ // read value
+ //System.out.println("reading value");
+
+ // skip spaces
+ //System.out.println("skip spaces for value");
+ try {
+ while ((c = in.read()) == ' ' || c == '\t') {//System.out.println("spaces2 read "+(char)c);
+ ;
+ }
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+ if (c == -1)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "no value after = in ava pattern"));
+
+ if (c == '$') {
+ // check for $subj $ext or $req
+ try {
+ c = in.read();
+ //System.out.println("check $dn or $attr read "+(char)c);
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+ if (c == -1)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "expecting $subj or $req in ava pattern"));
+ if (c == 'r') {
+ try {
+ if (in.read() != 'e' ||
+ in.read() != 'q' ||
+ in.read() != '.')
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "expecting $req in ava pattern"));
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+ mType = TYPE_REQ;
+ //System.out.println("---- mtype $req");
+ } else if (c == 's') {
+ try {
+ if (in.read() != 'u' ||
+ in.read() != 'b' ||
+ in.read() != 'j' ||
+ in.read() != '.')
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "expecting $subj in ava pattern"));
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+ mType = TYPE_SUBJ;
+ //System.out.println("----- mtype $subj");
+ } else if (c == 'e') {
+ try {
+ if (in.read() != 'x' ||
+ in.read() != 't' ||
+ in.read() != '.')
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "expecting $ext in ava pattern"));
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+ mType = TYPE_EXT;
+ //System.out.println("----- mtype $ext");
+ } else {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "unknown keyword. expecting $subj $ext or $req."));
+ }
+
+ // get request attr name of subject dn pattern from above.
+ String attrName = attrBuf.toString().trim();
+
+ //System.out.println("----- attrName "+attrName);
+ if (attrName.length() == 0)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "attribute name expected"));
+ mAttr = attrName;
+
+ /*
+ try {
+ ObjectIdentifier attrOid =
+ mLdapDNStrConverter.parseAVAKeyword(attrName);
+ mAttr = mLdapDNStrConverter.encodeOID(attrOid);
+ //System.out.println("----- mAttr "+mAttr);
+ }
+ catch (IOException e) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX", e.toString()));
+ }
+ */
+
+ // get request attribute or cert subject dn attribute
+
+ StringBuffer valueBuf = new StringBuffer();
+
+ try {
+ while ((c = in.read()) != ',' &&
+ c != -1 && c != '.' && c != '+') {
+ //System.out.println("mValue read "+(char)c);
+ valueBuf.append((char) c);
+ }
+ if (c == '+' || c == ',') // either ',' or '+'
+ in.unread(c); // pushback last , or +
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+
+ mValue = valueBuf.toString().trim();
+ if (mValue.length() == 0)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "$subj or $req attribute name expected"));
+ //System.out.println("----- mValue "+mValue);
+
+ // get nth dn xxx not nth request attribute .
+ if (c == '.') {
+ StringBuffer attrNumberBuf = new StringBuffer();
+
+ try {
+ while ((c = in.read()) != ',' && c != -1 && c != '.'
+ && c != '+') {
+ //System.out.println("mElement read "+(char)c);
+ attrNumberBuf.append((char) c);
+ }
+ if (c == ',' || c == '+') // either ',' or '+'
+ in.unread(c); // pushback last , or +
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+ String attrNumber = attrNumberBuf.toString().trim();
+
+ if (attrNumber.length() == 0)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "nth element $req $ext or $subj expected"));
+ try {
+ mElement = Integer.parseInt(attrNumber) - 1;
+ } catch (NumberFormatException e) {
+ if (TYPE_REQ.equals(mType)) {
+ mPrefix = mValue;
+ mValue = attrNumber;
+ } else if (TYPE_EXT.equals(mType)) {
+ mGNType = attrNumber;
+ } else
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "Invalid format in nth element $req $ext or $subj"));
+
+ // get nth request attribute .
+ if (c == '.') {
+ StringBuffer attrNumberBuf1 = new StringBuffer();
+
+ try {
+ while ((c = in.read()) != ',' && c != -1 && c != '+') {
+ //System.out.println("mElement read "+(char)c);
+ attrNumberBuf1.append((char) c);
+ }
+ if (c != -1) // either ',' or '+'
+ in.unread(c); // pushback last , or +
+ } catch (IOException ex) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", ex.toString()));
+ }
+ String attrNumber1 = attrNumberBuf1.toString().trim();
+
+ if (attrNumber1.length() == 0)
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "nth element $req expected"));
+ try {
+ mElement = Integer.parseInt(attrNumber1) - 1;
+ } catch (NumberFormatException ex) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX",
+ "Invalid format in nth element $req."));
+
+ }
+ }
+ }
+ }
+ //System.out.println("----- mElement "+mElement);
+ } else {
+ // value is constant. treat as regular ava.
+ mType = TYPE_CONSTANT;
+ //System.out.println("----- mType constant");
+ // parse ava value.
+ StringBuffer valueBuf = new StringBuffer();
+
+ valueBuf.append((char) c);
+ // read forward to get attribute value
+ try {
+ while ((c = in.read()) != ',' &&
+ c != -1) {
+ valueBuf.append((char) c);
+ }
+ if (c == '+' || c == ',') { // either ',' or '+'
+ in.unread(c); // pushback last , or +
+ }
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+ try {
+ AVA ava = mLdapDNStrConverter.parseAVA(attrBuf + "=" + valueBuf);
+
+ mValue = ava.toLdapDNString();
+ //System.out.println("----- mValue "+mValue);
+ } catch (IOException e) {
+ throw new ECompSyntaxErr(CMS.getUserMessage("CMS_AUTHENTICATION_COMPONENT_SYNTAX", e.toString()));
+ }
+ }
+ }
+
+ public String formAVA(IRequest req, X500Name subject, CertificateExtensions extensions)
+ throws ELdapException {
+ if (TYPE_CONSTANT.equals(mType))
+ return mValue;
+
+ if (TYPE_RDN.equals(mType)) {
+ String dn = subject.toString();
+
+ if (mTestDN != null)
+ dn = mTestDN;
+ //System.out.println("AVAPattern Using dn "+mTestDN);
+ String[] rdns = LDAPDN.explodeDN(dn, false);
+
+ if (mElement >= rdns.length)
+ return null;
+ return rdns[mElement];
+ }
+
+ if (TYPE_SUBJ.equals(mType)) {
+ String dn = subject.toString();
+
+ if (mTestDN != null)
+ dn = mTestDN;
+ //System.out.println("AVAPattern Using dn "+mTestDN);
+ String[] rdns = LDAPDN.explodeDN(dn, false);
+ String value = null;
+ int nFound = -1;
+
+ for (int i = 0; i < rdns.length; i++) {
+ String[] avas = explodeRDN(rdns[i]);
+
+ for (int j = 0; j < avas.length; j++) {
+ String[] exploded = explodeAVA(avas[j]);
+
+ if (exploded[0].equalsIgnoreCase(mValue) &&
+ ++nFound == mElement) {
+ value = exploded[1];
+ break;
+ }
+ }
+ }
+ if (value == null) {
+ CMS.debug(
+ "MapAVAPattern: attr " + mAttr +
+ " not formed from: cert subject " +
+ dn +
+ "-- no subject component : " + mValue);
+ return null;
+ }
+ return mAttr + "=" + value;
+ }
+
+ if (TYPE_EXT.equals(mType)) {
+ if (extensions != null) {
+ for (int i = 0; i < extensions.size(); i++) {
+ Extension ext = extensions.elementAt(i);
+ String extName = OIDMap.getName(ext.getExtensionId());
+ int index = extName.lastIndexOf(".");
+
+ if (index != -1)
+ extName = extName.substring(index + 1);
+ if (extName.equals(mValue)) {
+ // Check the extensions one by one.
+ // For now, just give subjectAltName as an example.
+ if (mValue.equalsIgnoreCase(SubjectAlternativeNameExtension.NAME)) {
+ try {
+ GeneralNames subjectNames =
+ (GeneralNames)
+ ((SubjectAlternativeNameExtension) ext)
+ .get(SubjectAlternativeNameExtension.SUBJECT_NAME);
+
+ if (subjectNames.size() == 0)
+ break;
+ int j = 0;
+
+ for (Enumeration<GeneralNameInterface> n = subjectNames.elements(); n.hasMoreElements();) {
+ GeneralName gn = (GeneralName) n.nextElement();
+ String gname = gn.toString();
+
+ index = gname.indexOf(":");
+ if (index == -1)
+ break;
+ String gType = gname.substring(0, index);
+
+ if (mGNType != null) {
+ if (mGNType.equalsIgnoreCase(gType)) {
+ if (mElement == j) {
+ gname =
+ gname.substring(index + 2);
+ return mAttr + "=" + gname;
+ } else {
+ j++;
+ }
+ }
+ } else {
+ if (mElement == j) {
+ gname =
+ gname.substring(index + 2);
+ return mAttr + "=" + gname;
+ }
+ j++;
+ }
+ }
+ } catch (IOException e) {
+ CMS.debug(
+ "MapAVAPattern: Publishing attr not formed from extension." +
+ "-- no attr : " + mValue);
+ }
+ }
+ }
+ }
+ }
+ CMS.debug(
+ "MapAVAPattern: Publishing:attr not formed from extension " +
+ "-- no attr : " + mValue);
+
+ return null;
+ }
+
+ if (TYPE_REQ.equals(mType)) {
+ // mPrefix and mValue are looked up case-insensitive
+ String reqAttr = req.getExtDataInString(mPrefix, mValue);
+ if (reqAttr == null) {
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_REQUEST",
+ mValue, mAttr));
+ }
+ return mAttr + "=" + reqAttr;
+ }
+
+ return null;
+ }
+
+ public String getReqAttr() {
+ if (TYPE_REQ.equals(mType))
+ return mValue;
+ else
+ return null;
+ }
+
+ public String getCertAttr() {
+ if (TYPE_SUBJ.equals(mType))
+ return mValue;
+ else
+ return null;
+ }
+
+ /**
+ * Explode RDN into AVAs.
+ * Does not handle escaped '+'
+ * Java ldap library does not yet support multiple avas per rdn.
+ * If RDN is malformed returns empty array.
+ */
+ public static String[] explodeRDN(String rdn) {
+ int plus = rdn.indexOf('+');
+
+ if (plus == -1)
+ return new String[] { rdn };
+ Vector<String> avas = new Vector<String>();
+ StringTokenizer token = new StringTokenizer(rdn, "+");
+
+ while (token.hasMoreTokens())
+ avas.addElement(token.nextToken());
+ String[] theAvas = new String[avas.size()];
+
+ avas.copyInto(theAvas);
+ return theAvas;
+ }
+
+ /**
+ * Explode AVA into name and value.
+ * Does not handle escaped '='
+ * If AVA is malformed empty array is returned.
+ */
+ public static String[] explodeAVA(String ava) {
+ int equals = ava.indexOf('=');
+
+ if (equals == -1)
+ return null;
+ return new String[] {
+ ava.substring(0, equals).trim(), ava.substring(equals + 1).trim() };
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/mappers/MapDNPattern.java b/base/server/cms/src/com/netscape/cms/publish/mappers/MapDNPattern.java
new file mode 100644
index 000000000..6656f4a1f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/mappers/MapDNPattern.java
@@ -0,0 +1,201 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.mappers;
+
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.StringReader;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.X500Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * class for parsing a DN pattern used to construct a ldap dn from
+ * request attributes and cert subject name.
+ * <p>
+ *
+ * dnpattern is a string representing a ldap dn pattern to formulate from the certificate subject name attributes and
+ * request attributes . If empty or not set, the certificate subject name will be used as the ldap dn.
+ * <p>
+ *
+ * The syntax is
+ *
+ * <pre>
+ * dnPattern := rdnPattern *[ "," rdnPattern ]
+ * rdnPattern := avaPattern *[ "+" avaPattern ]
+ * avaPattern := name "=" value |
+ * name "=" "$subj" "." attrName [ "." attrNumber ] |
+ * name "=" "$req" "." attrName [ "." attrNumber ] |
+ * "$rdn" "." number
+ * </pre>
+ *
+ * <pre>
+ * Example1: <i>cn=Certificate Manager,ou=people,o=mcom.com</i>
+ * cert subject name: dn: CN=Certificate Manager, OU=people, O=mcom.com
+ * request attributes: uid: cmanager
+ * <p>
+ * The dn formulated will be : <br>
+ * CN=Certificate Manager, OU=people, O=mcom.com
+ * <p>
+ * note: Subordinate ca enrollment will use ca mapper. Use predicate
+ * to distinguish the ca itself and the subordinates.
+ *
+ * Example2: <i>UID=$req.HTTP_PARAMS.uid, OU=$subj.ou, O=people, , O=mcom.com</i>
+ * cert subject name: dn: UID=jjames, OU=IS, O=people, , O=mcom.com
+ * request attributes: uid: cmanager
+ * <p>
+ * The dn formulated will be : <br>
+ * UID=jjames, OU=IS, OU=people, O=mcom.com
+ * <p>
+ * UID = the 'uid' attribute value in the request. <br>
+ * OU = the 'ou' value in the cert subject name. <br>
+ * O = the string people, mcom.com. <br>
+ * <p>
+ * </pre>
+ *
+ * If an request attribute or subject DN component does not exist, the attribute is skipped. There is potential risk
+ * that a wrong dn will be mapped into.
+ *
+ * @version $Revision$, $Date$
+ */
+public class MapDNPattern {
+
+ /* the list of request attriubutes to retrieve*/
+ protected String[] mReqAttrs = null;
+
+ /* the list of cert attriubutes to retrieve*/
+ protected String[] mCertAttrs = null;
+
+ /* rdn patterns */
+ protected MapRDNPattern[] mRDNPatterns = null;
+
+ /* original pattern string */
+ protected String mPatternString = null;
+
+ protected String mTestDN = null;
+
+ /**
+ * Construct a DN pattern by parsing a pattern string.
+ *
+ * @param pattern the DN pattern
+ * @exception EBaseException If parsing error occurs.
+ */
+ public MapDNPattern(String pattern)
+ throws ELdapException {
+ if (pattern == null || pattern.equals("")) {
+ CMS.debug(
+ "MapDNPattern: null pattern");
+ } else {
+ mPatternString = pattern;
+ PushbackReader in = new PushbackReader(new StringReader(pattern));
+
+ parse(in);
+ }
+ }
+
+ public MapDNPattern(PushbackReader in)
+ throws ELdapException {
+ parse(in);
+ }
+
+ private void parse(PushbackReader in)
+ throws ELdapException {
+ Vector<MapRDNPattern> rdnPatterns = new Vector<MapRDNPattern>();
+ MapRDNPattern rdnPattern = null;
+ int lastChar = -1;
+
+ do {
+ rdnPattern = new MapRDNPattern(in);
+ rdnPatterns.addElement(rdnPattern);
+ try {
+ lastChar = in.read();
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+ } while (lastChar == ',');
+
+ mRDNPatterns = new MapRDNPattern[rdnPatterns.size()];
+ rdnPatterns.copyInto(mRDNPatterns);
+
+ Vector<String> reqAttrs = new Vector<String>();
+
+ for (int i = 0; i < mRDNPatterns.length; i++) {
+ String[] rdnAttrs = mRDNPatterns[i].getReqAttrs();
+
+ if (rdnAttrs != null && rdnAttrs.length > 0)
+ for (int j = 0; j < rdnAttrs.length; j++)
+ reqAttrs.addElement(rdnAttrs[j]);
+ }
+ mReqAttrs = new String[reqAttrs.size()];
+ reqAttrs.copyInto(mReqAttrs);
+
+ Vector<String> certAttrs = new Vector<String>();
+
+ for (int i = 0; i < mRDNPatterns.length; i++) {
+ String[] rdnAttrs = mRDNPatterns[i].getCertAttrs();
+
+ if (rdnAttrs != null && rdnAttrs.length > 0)
+ for (int j = 0; j < rdnAttrs.length; j++)
+ certAttrs.addElement(rdnAttrs[j]);
+ }
+ mCertAttrs = new String[certAttrs.size()];
+ certAttrs.copyInto(mCertAttrs);
+ }
+
+ /**
+ * Form a Ldap v3 DN string from a request and a cert subject name.
+ *
+ * @param req the request for (un)publish
+ * @param subject the subjectDN of the certificate
+ * @return Ldap v3 DN string to use for base ldap search.
+ */
+ public String formDN(IRequest req, X500Name subject, CertificateExtensions ext)
+ throws ELdapException {
+ StringBuffer formedDN = new StringBuffer();
+
+ for (int i = 0; i < mRDNPatterns.length; i++) {
+ if (mTestDN != null)
+ mRDNPatterns[i].mTestDN = mTestDN;
+ String rdn = mRDNPatterns[i].formRDN(req, subject, ext);
+
+ if (rdn != null && rdn.length() != 0) {
+ if (formedDN.length() != 0)
+ formedDN.append(",");
+ formedDN.append(rdn);
+ } else {
+ throw new ELdapException("pattern not matched");
+ }
+ }
+ return formedDN.toString();
+ }
+
+ public String[] getReqAttrs() {
+ return mReqAttrs.clone();
+ }
+
+ public String[] getCertAttrs() {
+ return mCertAttrs.clone();
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/mappers/MapRDNPattern.java b/base/server/cms/src/com/netscape/cms/publish/mappers/MapRDNPattern.java
new file mode 100644
index 000000000..058294d7c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/mappers/MapRDNPattern.java
@@ -0,0 +1,217 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.mappers;
+
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.StringReader;
+import java.util.Vector;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.X500Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * class for parsing a DN pattern used to construct a ldap dn from
+ * request attributes and cert subject name.
+ * <p>
+ *
+ * dnpattern is a string representing a ldap dn pattern to formulate from the certificate subject name attributes and
+ * request attributes . If empty or not set, the certificate subject name will be used as the ldap dn.
+ * <p>
+ *
+ * The syntax is
+ *
+ * <pre>
+ * dnPattern := rdnPattern *[ "," rdnPattern ]
+ * rdnPattern := avaPattern *[ "+" avaPattern ]
+ * avaPattern := name "=" value |
+ * name "=" "$subj" "." attrName [ "." attrNumber ] |
+ * name "=" "$req" "." attrName [ "." attrNumber ] |
+ * "$rdn" "." number
+ * </pre>
+ *
+ * <pre>
+ * Example1: <i>cn=Certificate Manager,ou=people,o=mcom.com</i>
+ * cert subject name: dn: CN=Certificate Manager, OU=people, O=mcom.com
+ * request attributes: uid: cmanager
+ * <p>
+ * The dn formulated will be : <br>
+ * CN=Certificate Manager, OU=people, O=mcom.com
+ * <p>
+ * note: Subordinate ca enrollment will use ca mapper. Use predicate
+ * to distinguish the ca itself and the subordinates.
+ *
+ * Example2: <i>UID=$req.HTTP_PARAMS.uid, OU=$subj.ou, O=people, , O=mcom.com</i>
+ * cert subject name: dn: UID=jjames, OU=IS, O=people, , O=mcom.com
+ * request attributes: uid: cmanager
+ * <p>
+ * The dn formulated will be : <br>
+ * UID=jjames, OU=IS, OU=people, O=mcom.com
+ * <p>
+ * UID = the 'uid' attribute value in the request. <br>
+ * OU = the 'ou' value in the cert subject name. <br>
+ * O = the string people, mcom.com. <br>
+ * <p>
+ * </pre>
+ *
+ * If an request attribute or subject DN component does not exist, the attribute is skipped.There is potential risk that
+ * a wrong dn will be mapped into.
+ *
+ * @version $Revision$, $Date$
+ */
+class MapRDNPattern {
+
+ /* the list of request attributes needed by this RDN */
+ protected String[] mReqAttrs = null;
+
+ /* the list of cert attributes needed by this RDN */
+ protected String[] mCertAttrs = null;
+
+ /* AVA patterns */
+ protected MapAVAPattern[] mAVAPatterns = null;
+
+ /* original pattern string */
+ protected String mPatternString = null;
+
+ protected String mTestDN = null;
+
+ /**
+ * Construct a DN pattern by parsing a pattern string.
+ *
+ * @param pattenr the DN pattern
+ * @exception ELdapException If parsing error occurs.
+ */
+ public MapRDNPattern(String pattern)
+ throws ELdapException {
+ if (pattern == null || pattern.equals("")) {
+ CMS.debug(
+ "MapDNPattern: null pattern");
+ } else {
+ mPatternString = pattern;
+ PushbackReader in = new PushbackReader(new StringReader(pattern));
+
+ parse(in);
+ }
+ }
+
+ /**
+ * Construct a DN pattern from a input stream of pattern
+ */
+ public MapRDNPattern(PushbackReader in)
+ throws ELdapException {
+ parse(in);
+ }
+
+ private void parse(PushbackReader in)
+ throws ELdapException {
+ //System.out.println("_________ begin rdn _________");
+ Vector<MapAVAPattern> avaPatterns = new Vector<MapAVAPattern>();
+ MapAVAPattern avaPattern = null;
+ int lastChar;
+
+ do {
+ avaPattern = new MapAVAPattern(in);
+ avaPatterns.addElement(avaPattern);
+ //System.out.println("added AVAPattern"+
+ //" mType "+avaPattern.mType+
+ //" mAttr "+avaPattern.mAttr+
+ //" mValue "+avaPattern.mValue+
+ //" mElement "+avaPattern.mElement);
+ try {
+ lastChar = in.read();
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+ } while (lastChar == '+');
+
+ if (lastChar != -1) {
+ try {
+ in.unread(lastChar); // pushback last ,
+ } catch (IOException e) {
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+ }
+
+ mAVAPatterns = new MapAVAPattern[avaPatterns.size()];
+ avaPatterns.copyInto(mAVAPatterns);
+
+ Vector<String> reqAttrs = new Vector<String>();
+
+ for (int i = 0; i < mAVAPatterns.length; i++) {
+ String avaAttr = mAVAPatterns[i].getReqAttr();
+
+ if (avaAttr == null || avaAttr.length() == 0)
+ continue;
+ reqAttrs.addElement(avaAttr);
+ }
+ mReqAttrs = new String[reqAttrs.size()];
+ reqAttrs.copyInto(mReqAttrs);
+
+ Vector<String> certAttrs = new Vector<String>();
+
+ for (int i = 0; i < mAVAPatterns.length; i++) {
+ String avaAttr = mAVAPatterns[i].getCertAttr();
+
+ if (avaAttr == null || avaAttr.length() == 0)
+ continue;
+ certAttrs.addElement(avaAttr);
+ }
+ mCertAttrs = new String[certAttrs.size()];
+ certAttrs.copyInto(mCertAttrs);
+ }
+
+ /**
+ * Form a Ldap v3 DN string from a request and a cert subject name.
+ *
+ * @param req the request for (un)publish
+ * @param subject the subjectDN of the certificate
+ * @return Ldap v3 DN string to use for base ldap search.
+ */
+ public String formRDN(IRequest req, X500Name subject, CertificateExtensions ext)
+ throws ELdapException {
+ StringBuffer formedRDN = new StringBuffer();
+
+ for (int i = 0; i < mAVAPatterns.length; i++) {
+ if (mTestDN != null)
+ mAVAPatterns[i].mTestDN = mTestDN;
+ String ava = mAVAPatterns[i].formAVA(req, subject, ext);
+
+ if (ava != null && ava.length() > 0) {
+ if (formedRDN.length() != 0)
+ formedRDN.append("+");
+ formedRDN.append(ava);
+ }
+ }
+ //System.out.println("formed RDN "+formedRDN.toString());
+ return formedRDN.toString();
+ }
+
+ public String[] getReqAttrs() {
+ return mReqAttrs.clone();
+ }
+
+ public String[] getCertAttrs() {
+ return mCertAttrs.clone();
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/mappers/NoMap.java b/base/server/cms/src/com/netscape/cms/publish/mappers/NoMap.java
new file mode 100644
index 000000000..cc12714e2
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/mappers/NoMap.java
@@ -0,0 +1,104 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.mappers;
+
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPConnection;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.publish.ILdapMapper;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * No Map
+ *
+ * @version $Revision$, $Date$
+ */
+public class NoMap implements ILdapMapper, IExtendedPluginInfo {
+
+ public IConfigStore mConfig = null;
+
+ /**
+ * constructor if initializing from config store.
+ */
+ public NoMap() {
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String params[] = {
+ IExtendedPluginInfo.HELP_TOKEN + ";configuration-ldappublish-mapper-simplemapper",
+ IExtendedPluginInfo.HELP_TEXT + ";Describes how to form the name of the entry to publish to"
+ };
+
+ return params;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * for initializing from config store.
+ */
+ public void init(IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+ }
+
+ /**
+ * Maps a X500 subject name to LDAP entry.
+ * Uses DN pattern to form a DN for a LDAP base search.
+ *
+ * @param conn the LDAP connection.
+ * @param obj the object to map.
+ * @exception ELdapException if any LDAP exceptions occured.
+ */
+ public String map(LDAPConnection conn, Object obj)
+ throws ELdapException {
+ return null;
+ }
+
+ public String map(LDAPConnection conn, IRequest req, Object obj)
+ throws ELdapException {
+ return null;
+ }
+
+ public String getImplName() {
+ return "NoMap";
+ }
+
+ public String getDescription() {
+ return "NoMap";
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+ return v;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+ return v;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/publishers/FileBasedPublisher.java b/base/server/cms/src/com/netscape/cms/publish/publishers/FileBasedPublisher.java
new file mode 100644
index 000000000..c48aa2db4
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/publishers/FileBasedPublisher.java
@@ -0,0 +1,476 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.publishers;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.math.BigInteger;
+import java.security.cert.CRLException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+import java.util.TimeZone;
+import java.util.Vector;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import netscape.ldap.LDAPConnection;
+
+import org.mozilla.jss.util.Base64OutputStream;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapPublisher;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * This publisher writes certificate and CRL into
+ * a directory.
+ *
+ * @version $Revision$, $Date$
+ */
+public class FileBasedPublisher implements ILdapPublisher, IExtendedPluginInfo {
+ private static final String PROP_DIR = "directory";
+ private static final String PROP_DER = "Filename.der";
+ private static final String PROP_B64 = "Filename.b64";
+ private static final String PROP_LNK = "latestCrlLink";
+ private static final String PROP_GMT = "timeStamp";
+ private static final String PROP_EXT = "crlLinkExt";
+ private static final String PROP_ZIP = "zipCRLs";
+ private static final String PROP_LEV = "zipLevel";
+ private IConfigStore mConfig = null;
+ private String mDir = null;
+ private ILogger mLogger = CMS.getLogger();
+ private String mCrlIssuingPointId;
+ protected boolean mDerAttr = true;
+ protected boolean mB64Attr = false;
+ protected boolean mLatestCRL = false;
+ protected boolean mZipCRL = false;
+ protected String mTimeStamp = null;
+ protected String mLinkExt = null;
+ protected int mZipLevel = 9;
+
+ public void setIssuingPointId(String crlIssuingPointId) {
+ mCrlIssuingPointId = crlIssuingPointId;
+ }
+
+ /**
+ * Returns the implementation name.
+ */
+ public String getImplName() {
+ return "FileBasedPublisher";
+ }
+
+ /**
+ * Returns the description of the ldap publisher.
+ */
+
+ public String getDescription() {
+ return "This publisher writes the Certificates and CRLs into files.";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_DIR
+ + ";string;Directory in which to put the files (absolute path or relative path to cert-* instance directory).",
+ PROP_DER + ";boolean;Store certificates or CRLs into *.der files.",
+ PROP_B64 + ";boolean;Store certificates or CRLs into *.b64 files.",
+ PROP_GMT
+ + ";choice(LocalTime,GMT);Use local time or GMT to time stamp CRL file name with CRL's 'thisUpdate' field.",
+ PROP_LNK
+ + ";boolean;Generate link to the latest binary CRL. It requires '" + PROP_DER
+ + "' to be enabled.",
+ PROP_EXT
+ + ";string;Name extension used by link to the latest CRL. Default name extension is 'der'.",
+ PROP_ZIP + ";boolean;Generate compressed CRLs.",
+ PROP_LEV + ";choice(0,1,2,3,4,5,6,7,8,9);Set compression level from 0 to 9.",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ldappublish-publisher-filepublisher",
+ IExtendedPluginInfo.HELP_TEXT
+ +
+ ";Stores the certificates or CRLs into files. Certificate is named as cert-<serialno>.der or *.b64, and CRL is named as <IssuingPoint>-<thisUpdate-time>.der or *.b64."
+ };
+
+ return params;
+ }
+
+ /**
+ * Returns the current instance parameters.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+ String dir = "";
+ String ext = "";
+
+ try {
+ dir = mConfig.getString(PROP_DIR);
+ } catch (EBaseException e) {
+ }
+ try {
+ ext = mConfig.getString(PROP_EXT);
+ } catch (EBaseException e) {
+ }
+ try {
+ mTimeStamp = mConfig.getString(PROP_GMT);
+ } catch (EBaseException e) {
+ }
+ try {
+ mZipLevel = mConfig.getInteger(PROP_LEV, 9);
+ } catch (EBaseException e) {
+ }
+ try {
+ if (mTimeStamp == null || (!mTimeStamp.equals("GMT")))
+ mTimeStamp = "LocalTime";
+ v.addElement(PROP_DIR + "=" + dir);
+ v.addElement(PROP_DER + "=" + mConfig.getBoolean(PROP_DER, true));
+ v.addElement(PROP_B64 + "=" + mConfig.getBoolean(PROP_B64, false));
+ v.addElement(PROP_GMT + "=" + mTimeStamp);
+ v.addElement(PROP_LNK + "=" + mConfig.getBoolean(PROP_LNK, false));
+ v.addElement(PROP_EXT + "=" + ext);
+ v.addElement(PROP_ZIP + "=" + mConfig.getBoolean(PROP_ZIP, false));
+ v.addElement(PROP_LEV + "=" + mZipLevel);
+ } catch (Exception e) {
+ }
+ return v;
+ }
+
+ /**
+ * Returns the initial default parameters.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(PROP_DIR + "=");
+ v.addElement(PROP_DER + "=true");
+ v.addElement(PROP_B64 + "=false");
+ v.addElement(PROP_GMT + "=LocalTime");
+ v.addElement(PROP_LNK + "=false");
+ v.addElement(PROP_EXT + "=");
+ v.addElement(PROP_ZIP + "=false");
+ v.addElement(PROP_LEV + "=9");
+ return v;
+ }
+
+ /**
+ * Initializes this plugin.
+ */
+ public void init(IConfigStore config) {
+ mConfig = config;
+ String dir = null;
+
+ try {
+ dir = mConfig.getString(PROP_DIR, null);
+ mDerAttr = mConfig.getBoolean(PROP_DER, true);
+ mB64Attr = mConfig.getBoolean(PROP_B64, false);
+ mTimeStamp = mConfig.getString(PROP_GMT, "LocalTime");
+ mLatestCRL = mConfig.getBoolean(PROP_LNK, false);
+ mLinkExt = mConfig.getString(PROP_EXT, null);
+ mZipCRL = mConfig.getBoolean(PROP_ZIP, false);
+ mZipLevel = mConfig.getInteger(PROP_LEV, 9);
+ } catch (EBaseException e) {
+ }
+ if (dir == null) {
+ throw new RuntimeException("No Directory Specified");
+ }
+
+ // convert to forward slash
+ dir = dir.replace('\\', '/');
+ config.putString(PROP_DIR, dir);
+
+ File dirCheck = new File(dir);
+
+ if (dirCheck.isDirectory()) {
+ mDir = dir;
+ } else {
+ // maybe it is relative path
+ String mInstanceRoot = null;
+
+ try {
+ mInstanceRoot = CMS.getConfigStore().getString("instanceRoot");
+ } catch (Exception e) {
+ throw new RuntimeException("Invalid Instance Dir " + e);
+ }
+ dirCheck = new File(mInstanceRoot +
+ File.separator + dir);
+ if (dirCheck.isDirectory()) {
+ mDir = mInstanceRoot + File.separator + dir;
+ } else {
+ throw new RuntimeException("Invalid Directory " + dir);
+ }
+ }
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ private String[] getCrlNamePrefix(X509CRL crl, boolean useGMT) {
+ String[] namePrefix = { "crl", "crl" };
+
+ if (mCrlIssuingPointId != null && mCrlIssuingPointId.length() != 0) {
+ namePrefix[0] = mCrlIssuingPointId;
+ namePrefix[1] = mCrlIssuingPointId;
+ }
+ java.text.SimpleDateFormat format = new java.text.SimpleDateFormat("yyyyMMdd-HHmmss");
+ TimeZone tz = TimeZone.getTimeZone("GMT");
+ if (useGMT)
+ format.setTimeZone(tz);
+ String timeStamp = format.format(crl.getThisUpdate()).toString();
+ namePrefix[0] += "-" + timeStamp;
+ if (((netscape.security.x509.X509CRLImpl) crl).isDeltaCRL()) {
+ namePrefix[0] += "-delta";
+ namePrefix[1] += "-delta";
+ }
+
+ return namePrefix;
+ }
+
+ private void createLink(String linkName, String fileName) {
+ String cmd = "ln -s " + fileName + " " + linkName + ".new";
+ if (com.netscape.cmsutil.util.Utils.exec(cmd)) {
+ File oldLink = new File(linkName + ".old");
+ if (oldLink.exists()) { // remove old link if exists
+ oldLink.delete();
+ }
+ File link = new File(linkName);
+ if (link.exists()) { // current link becomes an old link
+ link.renameTo(new File(linkName + ".old"));
+ }
+ File newLink = new File(linkName + ".new");
+ if (newLink.exists()) { // new link becomes current link
+ newLink.renameTo(new File(linkName));
+ }
+ oldLink = new File(linkName + ".old");
+ if (oldLink.exists()) { // remove a new old link
+ oldLink.delete();
+ }
+ } else {
+ CMS.debug("FileBasedPublisher: createLink: '" + cmd + "' --- failed");
+ }
+ }
+
+ /**
+ * Publishs a object to the ldap directory.
+ *
+ * @param conn a Ldap connection
+ * (null if LDAP publishing is not enabled)
+ * @param dn dn of the ldap entry to publish cert
+ * (null if LDAP publishing is not enabled)
+ * @param object object to publish
+ * (java.security.cert.X509Certificate or,
+ * java.security.cert.X509CRL)
+ */
+ public void publish(LDAPConnection conn, String dn, Object object)
+ throws ELdapException {
+ CMS.debug("FileBasedPublisher: publish");
+
+ try {
+ if (object instanceof X509Certificate) {
+ X509Certificate cert = (X509Certificate) object;
+ BigInteger sno = cert.getSerialNumber();
+ String name = mDir +
+ File.separator + "cert-" +
+ sno.toString();
+ if (mDerAttr) {
+ FileOutputStream fos = null;
+ try {
+ String fileName = name + ".der";
+ fos = new FileOutputStream(fileName);
+ fos.write(cert.getEncoded());
+ } finally {
+ if (fos != null)
+ fos.close();
+ }
+ }
+ if (mB64Attr) {
+ String fileName = name + ".b64";
+ PrintStream ps = null;
+ Base64OutputStream b64 = null;
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(fileName);
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ b64 = new Base64OutputStream(new PrintStream(new FilterOutputStream(output)));
+ b64.write(cert.getEncoded());
+ b64.flush();
+ ps = new PrintStream(fos);
+ ps.print(output.toString("8859_1"));
+ } finally {
+ if (ps != null) {
+ ps.close();
+ }
+ if (b64 != null) {
+ b64.close();
+ }
+ if (fos != null)
+ fos.close();
+ }
+ }
+ } else if (object instanceof X509CRL) {
+ X509CRL crl = (X509CRL) object;
+ String[] namePrefix = getCrlNamePrefix(crl, mTimeStamp.equals("GMT"));
+ String baseName = mDir + File.separator + namePrefix[0];
+ String tempFile = baseName + ".temp";
+ ZipOutputStream zos = null;
+ byte[] encodedArray = null;
+ File destFile = null;
+ String destName = null;
+ File renameFile = null;
+
+ if (mDerAttr) {
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(tempFile);
+ encodedArray = crl.getEncoded();
+ fos.write(encodedArray);
+ } finally {
+ if (fos != null)
+ fos.close();
+ }
+ if (mZipCRL) {
+ try {
+ zos = new ZipOutputStream(new FileOutputStream(baseName + ".zip"));
+ zos.setLevel(mZipLevel);
+ zos.putNextEntry(new ZipEntry(baseName + ".der"));
+ zos.write(encodedArray, 0, encodedArray.length);
+ zos.closeEntry();
+ } finally {
+ if (zos != null)
+ zos.close();
+ }
+ }
+ destName = baseName + ".der";
+ destFile = new File(destName);
+
+ if (destFile.exists()) {
+ destFile.delete();
+ }
+ renameFile = new File(tempFile);
+ renameFile.renameTo(destFile);
+
+ if (mLatestCRL) {
+ String linkExt = ".";
+ if (mLinkExt != null && mLinkExt.length() > 0) {
+ linkExt += mLinkExt;
+ } else {
+ linkExt += "der";
+ }
+ String linkName = mDir + File.separator + namePrefix[1] + linkExt;
+ createLink(linkName, destName);
+ if (mZipCRL) {
+ linkName = mDir + File.separator + namePrefix[1] + ".zip";
+ createLink(linkName, baseName + ".zip");
+ }
+ }
+ }
+
+ // output base64 file
+ if (mB64Attr == true) {
+ if (encodedArray == null)
+ encodedArray = crl.getEncoded();
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(tempFile);
+ fos.write(Utils.base64encode(encodedArray).getBytes());
+ } finally {
+ if (fos != null)
+ fos.close();
+ }
+ destName = baseName + ".b64";
+ destFile = new File(destName);
+
+ if (destFile.exists()) {
+ destFile.delete();
+ }
+ renameFile = new File(tempFile);
+ renameFile.renameTo(destFile);
+ }
+ }
+ } catch (IOException e) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_FILE_PUBLISHER_ERROR", e.toString()));
+ } catch (CertificateEncodingException e) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_FILE_PUBLISHER_ERROR", e.toString()));
+ } catch (CRLException e) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_FILE_PUBLISHER_ERROR", e.toString()));
+ }
+ }
+
+ /**
+ * Unpublishs a object to the ldap directory.
+ *
+ * @param conn the Ldap connection
+ * (null if LDAP publishing is not enabled)
+ * @param dn dn of the ldap entry to unpublish cert
+ * (null if LDAP publishing is not enabled)
+ * @param object object to unpublish
+ * (java.security.cert.X509Certificate)
+ */
+ public void unpublish(LDAPConnection conn, String dn, Object object)
+ throws ELdapException {
+ CMS.debug("FileBasedPublisher: unpublish");
+ String name = mDir + File.separator;
+ String fileName;
+
+ if (object instanceof X509Certificate) {
+ X509Certificate cert = (X509Certificate) object;
+ BigInteger sno = cert.getSerialNumber();
+ name += "cert-" + sno.toString();
+ } else if (object instanceof X509CRL) {
+ X509CRL crl = (X509CRL) object;
+ String[] namePrefix = getCrlNamePrefix(crl, mTimeStamp.equals("GMT"));
+ name += namePrefix[0];
+
+ fileName = name + ".zip";
+ File f = new File(fileName);
+ f.delete();
+ }
+ fileName = name + ".der";
+ File f = new File(fileName);
+ f.delete();
+
+ fileName = name + ".b64";
+ f = new File(fileName);
+ f.delete();
+ }
+
+ /**
+ * returns the Der attribute where it'll be published.
+ */
+ public boolean getDerAttr() {
+ return mDerAttr;
+ }
+
+ /**
+ * returns the B64 attribute where it'll be published.
+ */
+ public boolean getB64Attr() {
+ return mB64Attr;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCaCertPublisher.java b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCaCertPublisher.java
new file mode 100644
index 000000000..06050480e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCaCertPublisher.java
@@ -0,0 +1,420 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.publishers;
+
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPModificationSet;
+import netscape.ldap.LDAPSSLSocketFactoryExt;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapPublisher;
+
+/**
+ * Interface for publishing a CA certificate to
+ *
+ * @version $Revision$, $Date$
+ */
+public class LdapCaCertPublisher
+ implements ILdapPublisher, IExtendedPluginInfo {
+ public static final String LDAP_CACERT_ATTR = "caCertificate;binary";
+ public static final String LDAP_CA_OBJECTCLASS = "pkiCA";
+ public static final String LDAP_ARL_ATTR = "authorityRevocationList;binary";
+ public static final String LDAP_CRL_ATTR = "certificateRevocationList;binary";
+
+ protected String mCaCertAttr = LDAP_CACERT_ATTR;
+ protected String mCaObjectclass = LDAP_CA_OBJECTCLASS;
+ protected String mObjAdded = "";
+ protected String mObjDeleted = "";
+
+ private ILogger mLogger = CMS.getLogger();
+ private boolean mInited = false;
+ protected IConfigStore mConfig = null;
+
+ /**
+ * constructor constructs default values.
+ */
+ public LdapCaCertPublisher() {
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String s[] = {
+ "caCertAttr;string;Name of Ldap attribute in which to store certificate",
+ "caObjectClass;string;The name of the objectclasses which should be " +
+ "added to this entry, if they do not already exist. This can be " +
+ "'certificationAuthority' (if using RFC 2256) or 'pkiCA' (if using RFC 4523)",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ldappublish-publisher-cacertpublisher",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";This plugin knows how to publish the CA cert to " +
+ "'certificateAuthority' and 'pkiCA' -type entries"
+ };
+
+ return s;
+ }
+
+ public String getImplName() {
+ return "LdapCaCertPublisher";
+ }
+
+ public String getDescription() {
+ return "LdapCaCertPublisher";
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement("caCertAttr=" + mCaCertAttr);
+ v.addElement("caObjectClass=" + mCaObjectclass);
+ return v;
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement("caCertAttr=" + mCaCertAttr);
+ v.addElement("caObjectClass=" + mCaObjectclass);
+ return v;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void init(IConfigStore config)
+ throws EBaseException {
+ if (mInited)
+ return;
+ mConfig = config;
+ mCaCertAttr = mConfig.getString("caCertAttr", LDAP_CACERT_ATTR);
+ mCaObjectclass = mConfig.getString("caObjectClass",
+ LDAP_CA_OBJECTCLASS);
+ mObjAdded = mConfig.getString("caObjectClassAdded", "");
+ mObjDeleted = mConfig.getString("caObjectClassDeleted", "");
+ mInited = true;
+ }
+
+ // don't think anyone would ever use this but just in case.
+ public LdapCaCertPublisher(String caCertAttr, String caObjectclass) {
+ mCaCertAttr = caCertAttr;
+ mCaObjectclass = caObjectclass;
+ mInited = true;
+ }
+
+ /**
+ * Gets the CA object class to convert to.
+ */
+ public String getCAObjectclass() {
+ return mCaObjectclass;
+ }
+
+ /**
+ * returns the ca cert attribute where it'll be published.
+ */
+ public String getCaCertAttrName() {
+ return mCaCertAttr;
+ }
+
+ /**
+ * publish a CA certificate
+ * Adds the cert to the multi-valued certificate attribute as a
+ * DER encoded binary blob. Does not check if cert already exists.
+ * Converts the class to certificateAuthority.
+ *
+ * @param conn the LDAP connection
+ * @param dn dn of the entry to publish the certificate
+ * @param certObj the certificate object.
+ */
+ public void publish(LDAPConnection conn, String dn, Object certObj)
+ throws ELdapException {
+ if (conn == null) {
+ log(ILogger.LL_INFO, "LdapCaCertPublisher: no LDAP connection");
+ return;
+ }
+
+ try {
+ mCaCertAttr = mConfig.getString("caCertAttr", LDAP_CACERT_ATTR);
+ mCaObjectclass = mConfig.getString("caObjectClass", LDAP_CA_OBJECTCLASS);
+ } catch (EBaseException e) {
+ }
+
+ // Bugscape #56124 - support multiple publishing directory
+ // see if we should create local connection
+ LDAPConnection altConn = null;
+ try {
+ String host = mConfig.getString("host", null);
+ String port = mConfig.getString("port", null);
+ if (host != null && port != null) {
+ int portVal = Integer.parseInt(port);
+ int version = Integer.parseInt(mConfig.getString("version", "2"));
+ String cert_nick = mConfig.getString("clientCertNickname", null);
+ LDAPSSLSocketFactoryExt sslSocket = null;
+ if (cert_nick != null) {
+ sslSocket = CMS.getLdapJssSSLSocketFactory(cert_nick);
+ }
+ String mgr_dn = mConfig.getString("bindDN", null);
+ String mgr_pwd = mConfig.getString("bindPWD", null);
+
+ altConn = CMS.getBoundConnection(host, portVal,
+ version,
+ sslSocket, mgr_dn, mgr_pwd);
+ conn = altConn;
+ }
+ } catch (LDAPException e) {
+ CMS.debug("Failed to create alt connection " + e);
+ } catch (EBaseException e) {
+ CMS.debug("Failed to create alt connection " + e);
+ }
+
+ if (!(certObj instanceof X509Certificate))
+ throw new IllegalArgumentException("Illegal arg to publish");
+
+ X509Certificate cert = (X509Certificate) certObj;
+
+ try {
+ byte[] certEnc = cert.getEncoded();
+
+ /* search for attribute names to determine existence of attributes */
+ LDAPSearchResults res =
+ conn.search(dn, LDAPv2.SCOPE_BASE, "(objectclass=*)",
+ new String[] { LDAP_CRL_ATTR, LDAP_ARL_ATTR }, true);
+ LDAPEntry entry = res.next();
+ LDAPAttribute arls = entry.getAttribute(LDAP_ARL_ATTR);
+ LDAPAttribute crls = entry.getAttribute(LDAP_CRL_ATTR);
+
+ /* search for objectclass and caCert values */
+ LDAPSearchResults res1 =
+ conn.search(dn, LDAPv2.SCOPE_BASE, "(objectclass=*)",
+ new String[] { "objectclass", mCaCertAttr }, false);
+ LDAPEntry entry1 = res1.next();
+ LDAPAttribute ocs = entry1.getAttribute("objectclass");
+ LDAPAttribute certs = entry1.getAttribute(mCaCertAttr);
+
+ boolean hasCert =
+ LdapUserCertPublisher.ByteValueExists(certs, certEnc);
+
+ LDAPModificationSet modSet = new LDAPModificationSet();
+
+ if (hasCert) {
+ log(ILogger.LL_INFO, "publish: CA " + dn + " already has Cert");
+ } else {
+ /*
+ fix for 360458 - if no cert, use add, if has cert but
+ not equal, use replace
+ */
+ if (certs == null) {
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(mCaCertAttr, certEnc));
+ log(ILogger.LL_INFO, "CA cert added");
+ } else {
+ modSet.add(LDAPModification.REPLACE,
+ new LDAPAttribute(mCaCertAttr, certEnc));
+ log(ILogger.LL_INFO, "CA cert replaced");
+ }
+ }
+
+ String[] oclist = mCaObjectclass.split(",");
+
+ boolean attrsAdded = false;
+ for (int i = 0; i < oclist.length; i++) {
+ String oc = oclist[i].trim();
+ boolean hasoc = LdapUserCertPublisher.StringValueExists(ocs, oc);
+ if (!hasoc) {
+ log(ILogger.LL_INFO, "adding CA objectclass " + oc + " to " + dn);
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute("objectclass", oc));
+
+ if ((!attrsAdded) && oc.equalsIgnoreCase("certificationAuthority")) {
+ // add MUST attributes
+ if (arls == null)
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(LDAP_ARL_ATTR, ""));
+ if (crls == null)
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(LDAP_CRL_ATTR, ""));
+ attrsAdded = true;
+ }
+ }
+ }
+
+ // delete objectclasses that have been deleted from config
+ String[] delList = mObjDeleted.split(",");
+ if (delList.length > 0) {
+ for (int i = 0; i < delList.length; i++) {
+ String deloc = delList[i].trim();
+ boolean hasoc = LdapUserCertPublisher.StringValueExists(ocs, deloc);
+ boolean match = false;
+ for (int j = 0; j < oclist.length; j++) {
+ if ((oclist[j].trim()).equals(deloc)) {
+ match = true;
+ break;
+ }
+ }
+ if (!match && hasoc) {
+ log(ILogger.LL_INFO, "deleting CA objectclass " + deloc + " from " + dn);
+ modSet.add(LDAPModification.DELETE,
+ new LDAPAttribute("objectclass", deloc));
+ }
+ }
+ }
+
+ // reset mObjAdded and mObjDeleted, if needed
+ if ((!mObjAdded.equals("")) || (!mObjDeleted.equals(""))) {
+ mObjAdded = "";
+ mObjDeleted = "";
+ mConfig.putString("caObjectClassAdded", "");
+ mConfig.putString("caObjectClassDeleted", "");
+ try {
+ mConfig.commit(false);
+ } catch (Exception e) {
+ log(ILogger.LL_INFO, "Failure in updating mObjAdded and mObjDeleted");
+ }
+ }
+
+ if (modSet.size() > 0)
+ conn.modify(dn, modSet);
+ } catch (CertificateEncodingException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_CANT_DECODE_CERT", dn));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_GET_DER_ENCODED_CERT_FAILED", e.toString()));
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_PUBLISHER_EXCEPTION", "", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_CACERT_ERROR", e.toString()));
+ }
+ } finally {
+ if (altConn != null) {
+ try {
+ altConn.disconnect();
+ } catch (LDAPException e) {
+ // safely ignored
+ }
+ }
+ }
+
+ return;
+ }
+
+ /**
+ * deletes the certificate from CA's certificate attribute.
+ * if it's the last cert will also remove the certificateAuthority
+ * objectclass.
+ */
+ public void unpublish(LDAPConnection conn, String dn, Object certObj)
+ throws ELdapException {
+ if (!(certObj instanceof X509Certificate))
+ throw new IllegalArgumentException("Illegal arg to publish");
+
+ X509Certificate cert = (X509Certificate) certObj;
+
+ try {
+ mCaCertAttr = mConfig.getString("caCertAttr", LDAP_CACERT_ATTR);
+ mCaObjectclass = mConfig.getString("caObjectClass", LDAP_CA_OBJECTCLASS);
+ } catch (EBaseException e) {
+ }
+
+ try {
+ byte[] certEnc = cert.getEncoded();
+
+ LDAPSearchResults res =
+ conn.search(dn, LDAPv2.SCOPE_BASE, "(objectclass=*)",
+ new String[] { mCaCertAttr, "objectclass" }, false);
+
+ LDAPEntry entry = res.next();
+ LDAPAttribute certs = entry.getAttribute(mCaCertAttr);
+ LDAPAttribute ocs = entry.getAttribute("objectclass");
+
+ boolean hasCert =
+ LdapUserCertPublisher.ByteValueExists(certs, certEnc);
+
+ if (!hasCert) {
+ log(ILogger.LL_INFO, "unpublish: " + dn + " has not cert already");
+ //throw new ELdapException(
+ // LdapResources.ALREADY_UNPUBLISHED_1, dn);
+ return;
+ }
+
+ LDAPModificationSet modSet = new LDAPModificationSet();
+
+ modSet.add(LDAPModification.DELETE,
+ new LDAPAttribute(mCaCertAttr, certEnc));
+ if (certs.size() == 1) {
+ // if last ca cert, remove oc also.
+
+ String[] oclist = mCaObjectclass.split(",");
+ for (int i = 0; i < oclist.length; i++) {
+ String oc = oclist[i].trim();
+ boolean hasOC = LdapUserCertPublisher.StringValueExists(ocs, oc);
+ if (hasOC) {
+ log(ILogger.LL_INFO, "unpublish: deleting CA oc" + oc + " from " + dn);
+ modSet.add(LDAPModification.DELETE,
+ new LDAPAttribute("objectclass", oc));
+ }
+ }
+ }
+ conn.modify(dn, modSet);
+ } catch (CertificateEncodingException e) {
+ CMS.debug("LdapCaCertPublisher: unpublish: Cannot decode cert for " + dn);
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_GET_DER_ENCODED_CERT_FAILED", e.toString()));
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_UNPUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_UNPUBLISH_CACERT_ERROR", e.toString()));
+ }
+ }
+ return;
+ }
+
+ /**
+ * handy routine for logging in this class.
+ */
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "LdapCaPublisher: " + msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCertSubjPublisher.java b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCertSubjPublisher.java
new file mode 100644
index 000000000..ac2b64973
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCertSubjPublisher.java
@@ -0,0 +1,345 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.publishers;
+
+import java.io.IOException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPModificationSet;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapPublisher;
+
+/**
+ * Interface for mapping a X509 certificate to a LDAP entry
+ * Publishes a certificate as binary and its subject name.
+ * there is one subject name value for each certificate.
+ *
+ * @version $Revision$, $Date$
+ */
+public class LdapCertSubjPublisher implements ILdapPublisher {
+ public static final String LDAP_CERTSUBJNAME_ATTR = "certSubjectName";
+ protected String mCertAttr = LdapUserCertPublisher.LDAP_USERCERT_ATTR;
+ protected String mSubjNameAttr = LDAP_CERTSUBJNAME_ATTR;
+
+ private ILogger mLogger = CMS.getLogger();
+ private boolean mInited = false;
+ protected IConfigStore mConfig = null;
+
+ /**
+ * constructor using default certificate subject name and attribute for
+ * publishing subject name.
+ */
+ public LdapCertSubjPublisher() {
+ }
+
+ public String getImplName() {
+ return "LdapCertSubjPublisher";
+ }
+
+ public String getDescription() {
+ return "LdapCertSubjPublisher";
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement("certAttr=" + mCertAttr);
+ v.addElement("subjectNameAttr=" + mSubjNameAttr);
+ return v;
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement("certAttr=" + mCertAttr);
+ v.addElement("subjectNameAttr=" + mSubjNameAttr);
+ return v;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void init(IConfigStore config)
+ throws EBaseException {
+ if (mInited)
+ return;
+ mConfig = config;
+ mCertAttr = mConfig.getString("certAttr",
+ LdapUserCertPublisher.LDAP_USERCERT_ATTR);
+ mSubjNameAttr = mConfig.getString("certSubjectName",
+ LDAP_CERTSUBJNAME_ATTR);
+ mInited = true;
+ }
+
+ /**
+ * constrcutor using specified certificate attribute and
+ * certificate subject name attribute.
+ */
+ public LdapCertSubjPublisher(String certAttr, String subjNameAttr) {
+ mCertAttr = certAttr;
+ mSubjNameAttr = subjNameAttr;
+ }
+
+ public String getCertAttr() {
+ return mCertAttr;
+ }
+
+ public String getSubjNameAttr() {
+ return mSubjNameAttr;
+ }
+
+ public void setSubjNameAttr(String subjNameAttr) {
+ mSubjNameAttr = subjNameAttr;
+ }
+
+ public void setCertAttr(String certAttr) {
+ mCertAttr = certAttr;
+ }
+
+ /**
+ * publish a user certificate
+ * Adds the cert to the multi-valued certificate attribute as a
+ * DER encoded binary blob. Does not check if cert already exists.
+ * Then adds the subject name of the cert to the subject name attribute.
+ *
+ * @param conn the LDAP connection
+ * @param dn dn of the entry to publish the certificate
+ * @param certObj the certificate object.
+ * @exception ELdapException if cert or subject name already exists,
+ * if cert encoding fails, if getting cert subject name fails.
+ * Use ELdapException.getException() to find underlying exception.
+ */
+ public void publish(LDAPConnection conn, String dn, Object certObj)
+ throws ELdapException {
+ if (conn == null) {
+ log(ILogger.LL_INFO, "LdapCertSubjPublisher: no LDAP connection");
+ return;
+ }
+
+ if (!(certObj instanceof X509Certificate))
+ throw new IllegalArgumentException("Illegal arg to publish");
+
+ X509Certificate cert = (X509Certificate) certObj;
+
+ try {
+ boolean hasCert = false, hasSubjname = false;
+ byte[] certEnc = cert.getEncoded();
+ String subjName = ((X500Name) cert.getSubjectDN()).toLdapDNString();
+
+ LDAPSearchResults res =
+ conn.search(dn, LDAPv2.SCOPE_BASE, "(objectclass=*)",
+ new String[] { mCertAttr, mSubjNameAttr }, false);
+
+ LDAPEntry entry = res.next();
+ LDAPAttribute certs = entry.getAttribute(mCertAttr);
+ LDAPAttribute subjnames = entry.getAttribute(mSubjNameAttr);
+
+ // check if has cert already.
+ if (certs != null) {
+ hasCert = LdapUserCertPublisher.ByteValueExists(certs, certEnc);
+ }
+
+ // check if has subject name already.
+ if (subjnames != null) {
+ hasSubjname =
+ LdapUserCertPublisher.StringValueExists(subjnames, subjName);
+ }
+
+ // if has both, done.
+ if (hasCert && hasSubjname) {
+ log(ILogger.LL_INFO,
+ "publish: " + subjName + " already has cert & subject name");
+ return;
+ }
+
+ // add cert if not already there.
+ LDAPModificationSet modSet = new LDAPModificationSet();
+
+ if (!hasCert) {
+ log(ILogger.LL_INFO, "publish: adding cert to " + subjName);
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(mCertAttr, certEnc));
+ }
+ // add subject name if not already there.
+ if (!hasSubjname) {
+ log(ILogger.LL_INFO, "publish: adding " + subjName + " to " + dn);
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(mSubjNameAttr, subjName));
+ }
+ conn.modify(dn, modSet);
+ } catch (CertificateEncodingException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_PUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_GET_DER_ENCODED_CERT_FAILED", e.toString()));
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_PUBLISHER_EXCEPTION", "", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_USERCERT_ERROR", e.toString()));
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_PUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_USERCERT_ERROR", e.toString()));
+ }
+ }
+
+ /**
+ * deletes the certificate from the list of certificates.
+ * does not check if certificate is already there.
+ * also takes out the subject name if no other certificate remain
+ * with the same subject name.
+ */
+ public void unpublish(LDAPConnection conn, String dn, Object certObj)
+ throws ELdapException {
+ if (!(certObj instanceof X509Certificate))
+ throw new IllegalArgumentException("Illegal arg to publish");
+
+ try {
+ boolean hasCert = false, hasSubjname = false;
+ boolean hasAnotherCert = false;
+ X509Certificate cert = (X509Certificate) certObj;
+ String subjName = ((X500Name) cert.getSubjectDN()).toLdapDNString();
+
+ byte[] certEnc = cert.getEncoded();
+
+ LDAPSearchResults res =
+ conn.search(dn, LDAPv2.SCOPE_BASE, "(objectclass=*)",
+ new String[] { mCertAttr, mSubjNameAttr }, false);
+
+ LDAPEntry entry = res.next();
+ LDAPAttribute certs = entry.getAttribute(mCertAttr);
+ LDAPAttribute subjnames = entry.getAttribute(mSubjNameAttr);
+
+ // check for cert and other certs with same subject name.
+ if (certs != null) {
+ hasCert = LdapUserCertPublisher.ByteValueExists(certs, certEnc);
+ // check for other certs with the same subject name
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> vals = certs.getByteValues();
+ byte[] val = null;
+
+ while (vals.hasMoreElements()) {
+ val = vals.nextElement();
+ if (PublisherUtils.byteArraysAreEqual(certEnc, val)) {
+ hasCert = true;
+ continue;
+ }
+ try {
+ X509CertImpl certval = new X509CertImpl(val);
+ // XXX use some sort of X500name equals function here.
+ String subjnam =
+ ((X500Name) certval.getSubjectDN()).toLdapDNString();
+
+ if (subjnam.equalsIgnoreCase(subjName)) {
+ hasAnotherCert = true;
+ }
+ } catch (CertificateEncodingException e) {
+ // ignore this certificate.
+ CMS.debug(
+ "LdapCertSubjPublisher: unpublish: an invalid cert in dn entry encountered");
+ } catch (CertificateException e) {
+ // ignore this certificate.
+ CMS.debug(
+ "LdapCertSubjPublisher: unpublish: an invalid cert in dn entry encountered");
+ }
+ }
+ }
+
+ // check if doesn't have subject name already.
+ if (subjnames != null) {
+ hasSubjname =
+ LdapUserCertPublisher.StringValueExists(subjnames, subjName);
+ }
+
+ // if doesn't have both, done.
+ if (!hasCert && !hasSubjname) {
+ log(ILogger.LL_INFO,
+ "unpublish: " + subjName + " already has not cert & subjname");
+ return;
+ }
+
+ // delete cert if there.
+ LDAPModificationSet modSet = new LDAPModificationSet();
+
+ if (hasCert) {
+ log(ILogger.LL_INFO,
+ "unpublish: deleting cert " + subjName + " from " + dn);
+ modSet.add(LDAPModification.DELETE,
+ new LDAPAttribute(mCertAttr, certEnc));
+ }
+ // delete subject name if no other cert has the same name.
+ if (hasSubjname && !hasAnotherCert) {
+ log(ILogger.LL_INFO,
+ "unpublish: deleting subject name " + subjName + " from " + dn);
+ modSet.add(LDAPModification.DELETE,
+ new LDAPAttribute(mSubjNameAttr, subjName));
+ }
+ conn.modify(dn, modSet);
+ } catch (CertificateEncodingException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_UNPUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_GET_DER_ENCODED_CERT_FAILED", e.toString()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_UNPUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_GET_LDAP_DN_STRING_FAILED", e.toString()));
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_UNPUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_UNPUBLISH_USERCERT_ERROR", e.toString()));
+ }
+ }
+ return;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "LdapCertSubjPublisher: " + msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCertificatePairPublisher.java b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCertificatePairPublisher.java
new file mode 100644
index 000000000..014cc0e5e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCertificatePairPublisher.java
@@ -0,0 +1,318 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.publishers;
+
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPModificationSet;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapPublisher;
+
+/**
+ * module for publishing a cross certificate pair to ldap
+ * crossCertificatePair attribute
+ *
+ * @version $Revision$, $Date$
+ */
+public class LdapCertificatePairPublisher
+ implements ILdapPublisher, IExtendedPluginInfo {
+ public static final String LDAP_CROSS_CERT_PAIR_ATTR = "crossCertificatePair;binary";
+ public static final String LDAP_CA_OBJECTCLASS = "pkiCA";
+ public static final String LDAP_ARL_ATTR = "authorityRevocationList;binary";
+ public static final String LDAP_CRL_ATTR = "certificateRevocationList;binary";
+ public static final String LDAP_CACERT_ATTR = "caCertificate;binary";
+
+ protected String mCrossCertPairAttr = LDAP_CROSS_CERT_PAIR_ATTR;
+ protected String mCaObjectclass = LDAP_CA_OBJECTCLASS;
+ protected String mObjAdded = "";
+ protected String mObjDeleted = "";
+
+ private ILogger mLogger = CMS.getLogger();
+ private boolean mInited = false;
+ protected IConfigStore mConfig = null;
+
+ /**
+ * constructor constructs default values.
+ */
+ public LdapCertificatePairPublisher() {
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String s[] = {
+ "crossCertPairAttr;string;Name of Ldap attribute in which to store cross certificates",
+ "caObjectClass;string;The name of the objectclasses which should be " +
+ "added to this entry, if they do not already exist. This can be " +
+ "'certificationAuthority' (if using RFC 2256) or 'pkiCA' (if using RFC 4523)",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ldappublish-publisher-crosscertpairpublisher",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";This plugin knows how to publish the CA cert to " +
+ "'certificateAuthority' and 'pkiCA' -type entries"
+ };
+
+ return s;
+ }
+
+ public String getImplName() {
+ return "LdapCertificatePairPublisher";
+ }
+
+ public String getDescription() {
+ return "LdapCertificatePairPublisher";
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement("crossCertPairAttr=" + mCrossCertPairAttr);
+ v.addElement("caObjectClass=" + mCaObjectclass);
+ return v;
+ }
+
+ public Vector<String> getInstanceParamsWithExtras() {
+ return getInstanceParams();
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement("crossCertPairAttr=" + mCrossCertPairAttr);
+ v.addElement("caObjectClass=" + mCaObjectclass);
+ return v;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void init(IConfigStore config)
+ throws EBaseException {
+ if (mInited)
+ return;
+ mConfig = config;
+ mCrossCertPairAttr = mConfig.getString("crossCertPairAttr", LDAP_CROSS_CERT_PAIR_ATTR);
+ mCaObjectclass = mConfig.getString("caObjectClass",
+ LDAP_CA_OBJECTCLASS);
+ mObjAdded = mConfig.getString("caObjectClassAdded", "");
+ mObjDeleted = mConfig.getString("caObjectClassDeleted", "");
+
+ mInited = true;
+ }
+
+ // don't think anyone would ever use this but just in case.
+ public LdapCertificatePairPublisher(String crossCertPairAttr, String caObjectclass) {
+ mCrossCertPairAttr = crossCertPairAttr;
+ mCaObjectclass = caObjectclass;
+ mInited = true;
+ }
+
+ /**
+ * Gets the Certificate Authority object class to convert to.
+ */
+ public String getCAObjectclass() {
+ return mCaObjectclass;
+ }
+
+ /**
+ * returns the cross cert pair attribute where it'll be published.
+ */
+ public String getXCertAttrName() {
+ return mCrossCertPairAttr;
+ }
+
+ /**
+ * publish a certificatePair
+ * -should not be called from listeners.
+ *
+ * @param conn the LDAP connection
+ * @param dn dn of the entry to publish the XcertificatePair
+ * @param pair the Xcertificate bytes object.
+ */
+ public synchronized void publish(LDAPConnection conn, String dn, Object pair)
+ throws ELdapException {
+ publish(conn, dn, (byte[]) pair);
+ }
+
+ /**
+ * publish a certificatePair
+ * -should not be called from listeners.
+ *
+ * @param conn the LDAP connection
+ * @param dn dn of the entry to publish the XcertificatePair
+ * @param pair the cross cert bytes
+ */
+ public synchronized void publish(LDAPConnection conn, String dn,
+ byte[] pair)
+ throws ELdapException {
+
+ if (conn == null) {
+ log(ILogger.LL_INFO, "LdapCertificatePairPublisher: no LDAP connection");
+ return;
+ }
+
+ try {
+ mCrossCertPairAttr = mConfig.getString("crossCertPairAttr", LDAP_CROSS_CERT_PAIR_ATTR);
+ mCaObjectclass = mConfig.getString("caObjectClass", LDAP_CA_OBJECTCLASS);
+ } catch (EBaseException e) {
+ }
+
+ try {
+ // search for attributes to determine if they exist
+ LDAPSearchResults res =
+ conn.search(dn, LDAPv2.SCOPE_BASE, "(objectclass=*)",
+ new String[] { LDAP_CACERT_ATTR, LDAP_CRL_ATTR, LDAP_ARL_ATTR }, true);
+ LDAPEntry entry = res.next();
+ LDAPAttribute certs = entry.getAttribute(LDAP_CACERT_ATTR);
+ LDAPAttribute arls = entry.getAttribute(LDAP_ARL_ATTR);
+ LDAPAttribute crls = entry.getAttribute(LDAP_CRL_ATTR);
+
+ // search for objectclass and crosscertpair attributes and values
+ LDAPSearchResults res1 =
+ conn.search(dn, LDAPv2.SCOPE_BASE, "(objectclass=*)",
+ new String[] { "objectclass", mCrossCertPairAttr }, false);
+ LDAPEntry entry1 = res1.next();
+ LDAPAttribute ocs = entry1.getAttribute("objectclass");
+ LDAPAttribute certPairs = entry1.getAttribute("crosscertificatepair;binary");
+
+ LDAPModificationSet modSet = new LDAPModificationSet();
+
+ boolean hasCert = LdapUserCertPublisher.ByteValueExists(certPairs, pair);
+ if (LdapUserCertPublisher.ByteValueExists(certPairs, pair)) {
+ CMS.debug("LdapCertificatePairPublisher: cross cert pair bytes exist in publishing directory, do not publish again.");
+ return;
+ }
+ if (hasCert) {
+ log(ILogger.LL_INFO, "publish: CA " + dn + " already has cross cert pair bytes");
+ } else {
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(mCrossCertPairAttr, pair));
+ log(ILogger.LL_INFO, "cross cert pair published with dn=" + dn);
+ }
+
+ String[] oclist = mCaObjectclass.split(",");
+
+ boolean attrsAdded = false;
+ for (int i = 0; i < oclist.length; i++) {
+ String oc = oclist[i].trim();
+ boolean hasoc = LdapUserCertPublisher.StringValueExists(ocs, oc);
+ if (!hasoc) {
+ log(ILogger.LL_INFO, "adding CA objectclass " + oc + " to " + dn);
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute("objectclass", oc));
+
+ if ((!attrsAdded) && oc.equalsIgnoreCase("certificationAuthority")) {
+ // add MUST attributes
+ if (arls == null)
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(LDAP_ARL_ATTR, ""));
+ if (crls == null)
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(LDAP_CRL_ATTR, ""));
+ if (certs == null)
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(LDAP_CACERT_ATTR, ""));
+ attrsAdded = true;
+ }
+ }
+ }
+
+ // delete objectclasses that have been deleted from config
+ String[] delList = mObjDeleted.split(",");
+ if (delList.length > 0) {
+ for (int i = 0; i < delList.length; i++) {
+ String deloc = delList[i].trim();
+ boolean hasoc = LdapUserCertPublisher.StringValueExists(ocs, deloc);
+ boolean match = false;
+ for (int j = 0; j < oclist.length; j++) {
+ if ((oclist[j].trim()).equals(deloc)) {
+ match = true;
+ break;
+ }
+ }
+ if (!match && hasoc) {
+ log(ILogger.LL_INFO, "deleting CRL objectclass " + deloc + " from " + dn);
+ modSet.add(LDAPModification.DELETE,
+ new LDAPAttribute("objectclass", deloc));
+ }
+ }
+ }
+
+ // reset mObjAdded and mObjDeleted, if needed
+ if ((!mObjAdded.equals("")) || (!mObjDeleted.equals(""))) {
+ mObjAdded = "";
+ mObjDeleted = "";
+ mConfig.putString("caObjectClassAdded", "");
+ mConfig.putString("caObjectClassDeleted", "");
+ try {
+ mConfig.commit(false);
+ } catch (Exception e) {
+ log(ILogger.LL_INFO, "Failure in updating mObjAdded and mObjDeleted");
+ }
+ }
+
+ if (modSet.size() > 0)
+ conn.modify(dn, modSet);
+ CMS.debug("LdapCertificatePairPublisher: in publish() just published");
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_PUBLISHER_EXCEPTION", "", e.toString()));
+ throw new ELdapException("error publishing cross cert pair:" + e.toString());
+ }
+ }
+ return;
+ }
+
+ /**
+ * unsupported
+ */
+ public void unpublish(LDAPConnection conn, String dn, Object certObj)
+ throws ELdapException {
+ CMS.debug("LdapCertificatePairPublisher: unpublish() is unsupported in this revision");
+ }
+
+ /**
+ * handy routine for logging in this class.
+ */
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "LdapCertificatePairPublisher: " + msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCrlPublisher.java b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCrlPublisher.java
new file mode 100644
index 000000000..51bebe236
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCrlPublisher.java
@@ -0,0 +1,379 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.publishers;
+
+import java.security.cert.CRLException;
+import java.security.cert.X509CRL;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPModificationSet;
+import netscape.ldap.LDAPSSLSocketFactoryExt;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapPublisher;
+
+/**
+ * For publishing master or global CRL.
+ * Publishes (replaces) the CRL in the CA's LDAP entry.
+ *
+ * @version $Revision$, $Date$
+ */
+public class LdapCrlPublisher implements ILdapPublisher, IExtendedPluginInfo {
+ private ILogger mLogger = CMS.getLogger();
+ protected IConfigStore mConfig = null;
+ boolean mInited = false;
+
+ public static final String LDAP_CACERT_ATTR = "caCertificate;binary";
+ public static final String LDAP_ARL_ATTR = "authorityRevocationList;binary";
+ public static final String LDAP_CRL_ATTR = "certificateRevocationList;binary";
+ public static final String LDAP_CRL_OBJECTCLASS = "pkiCA,deltaCRL";
+
+ protected String mCrlAttr = LDAP_CRL_ATTR;
+ protected String mCrlObjectClass = LDAP_CRL_OBJECTCLASS;
+ protected String mObjAdded = "";
+ protected String mObjDeleted = "";
+
+ /**
+ * constructs ldap crl publisher with default values
+ */
+ public LdapCrlPublisher() {
+ }
+
+ public String getImplName() {
+ return "LdapCrlPublisher";
+ }
+
+ public String getDescription() {
+ return "LdapCrlPublisher";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ "crlAttr;string;Name of Ldap attribute in which to store the CRL",
+ "crlObjectClass;string;The name of the objectclasses which should be " +
+ "added to this entry, if they do not already exist. This can be a comma-" +
+ "separated list such as 'certificationAuthority,certificationAuthority-V2' " +
+ "(if using RFC 2256) or 'pkiCA, deltaCRL' (if using RFC 4523)",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ldappublish-publisher-crlpublisher",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";This plugin knows how to publish CRL's to " +
+ "'certificateAuthority' and 'pkiCA' -type entries"
+ };
+
+ return params;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement("crlAttr=" + mCrlAttr);
+ v.addElement("crlObjectClass=" + mCrlObjectClass);
+ return v;
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement("crlAttr=" + mCrlAttr);
+ v.addElement("crlObjectClass=" + mCrlObjectClass);
+ return v;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void init(IConfigStore config)
+ throws EBaseException {
+ if (mInited)
+ return;
+ mConfig = config;
+ mCrlAttr = mConfig.getString("crlAttr", LDAP_CRL_ATTR);
+ mCrlObjectClass = mConfig.getString("crlObjectClass",
+ LDAP_CRL_OBJECTCLASS);
+ mObjAdded = mConfig.getString("crlObjectClassAdded", "");
+ mObjDeleted = mConfig.getString("crlObjectClassDeleted", "");
+
+ mInited = true;
+ }
+
+ public LdapCrlPublisher(String crlAttr, String crlObjectClass) {
+ mCrlAttr = crlAttr;
+ mCrlObjectClass = crlObjectClass;
+ }
+
+ /**
+ * Gets the CA object class to convert to.
+ */
+ public String getCRLObjectclass() {
+ return mCrlObjectClass;
+ }
+
+ /**
+ * Replaces the CRL in the certificateRevocationList attribute.
+ * CRL's are published as a DER encoded blob.
+ */
+ public void publish(LDAPConnection conn, String dn, Object crlObj)
+ throws ELdapException {
+ if (conn == null) {
+ log(ILogger.LL_INFO, "publish CRL: no LDAP connection");
+ return;
+ }
+
+ try {
+ mCrlAttr = mConfig.getString("crlAttr", LDAP_CRL_ATTR);
+ mCrlObjectClass = mConfig.getString("crlObjectClass", LDAP_CRL_OBJECTCLASS);
+ } catch (EBaseException e) {
+ }
+
+ // Bugscape #56124 - support multiple publishing directory
+ // see if we should create local connection
+ LDAPConnection altConn = null;
+ try {
+ String host = mConfig.getString("host", null);
+ String port = mConfig.getString("port", null);
+ if (host != null && port != null) {
+ int portVal = Integer.parseInt(port);
+ int version = Integer.parseInt(mConfig.getString("version", "2"));
+ String cert_nick = mConfig.getString("clientCertNickname", null);
+ LDAPSSLSocketFactoryExt sslSocket = null;
+ if (cert_nick != null) {
+ sslSocket = CMS.getLdapJssSSLSocketFactory(cert_nick);
+ }
+ String mgr_dn = mConfig.getString("bindDN", null);
+ String mgr_pwd = mConfig.getString("bindPWD", null);
+
+ altConn = CMS.getBoundConnection(host, portVal,
+ version,
+ sslSocket, mgr_dn, mgr_pwd);
+ conn = altConn;
+ }
+ } catch (LDAPException e) {
+ CMS.debug("Failed to create alt connection " + e);
+ } catch (EBaseException e) {
+ CMS.debug("Failed to create alt connection " + e);
+ }
+
+ try {
+ byte[] crlEnc = ((X509CRL) crlObj).getEncoded();
+ log(ILogger.LL_INFO, "publish CRL: " + dn);
+
+ /* search for attribute names to determine existence of attributes */
+ LDAPSearchResults res = null;
+ if (mCrlAttr.equals(LDAP_CRL_ATTR)) {
+ res = conn.search(dn, LDAPv2.SCOPE_BASE, "(objectclass=*)",
+ new String[] { LDAP_CACERT_ATTR, LDAP_ARL_ATTR }, true);
+ } else {
+ res = conn.search(dn, LDAPv2.SCOPE_BASE, "(objectclass=*)",
+ new String[] { LDAP_CRL_ATTR, LDAP_CACERT_ATTR, LDAP_ARL_ATTR }, true);
+ }
+
+ LDAPEntry entry = res.next();
+ LDAPAttribute crls = entry.getAttribute(LDAP_CRL_ATTR);
+ LDAPAttribute certs = entry.getAttribute(LDAP_CACERT_ATTR);
+ LDAPAttribute arls = entry.getAttribute(LDAP_ARL_ATTR);
+
+ /* get object class values */
+ LDAPSearchResults res1 = null;
+ res1 = conn.search(dn, LDAPv2.SCOPE_BASE, "(objectclass=*)",
+ new String[] { "objectclass" }, false);
+ LDAPEntry entry1 = res1.next();
+ LDAPAttribute ocs = entry1.getAttribute("objectclass");
+
+ LDAPModificationSet modSet = new LDAPModificationSet();
+
+ String[] oclist = mCrlObjectClass.split(",");
+ boolean attrsAdded = false;
+ for (int i = 0; i < oclist.length; i++) {
+ String oc = oclist[i].trim();
+ boolean hasoc = LdapUserCertPublisher.StringValueExists(ocs, oc);
+ if (!hasoc) {
+ log(ILogger.LL_INFO, "adding CRL objectclass " + oc + " to " + dn);
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute("objectclass", oc));
+
+ if ((!attrsAdded) && oc.equalsIgnoreCase("certificationAuthority")) {
+ // add MUST attributes
+ if (arls == null)
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(LDAP_ARL_ATTR, ""));
+ if (certs == null)
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(LDAP_CACERT_ATTR, ""));
+
+ if ((crls == null) && (!mCrlAttr.equals(LDAP_CRL_ATTR)))
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(LDAP_CRL_ATTR, ""));
+ attrsAdded = true;
+ }
+ }
+ }
+
+ modSet.add(LDAPModification.REPLACE, new LDAPAttribute(mCrlAttr, crlEnc));
+
+ // delete objectclasses that have been deleted from config
+ String[] delList = mObjDeleted.split(",");
+ if (delList.length > 0) {
+ for (int i = 0; i < delList.length; i++) {
+ String deloc = delList[i].trim();
+ boolean hasoc = LdapUserCertPublisher.StringValueExists(ocs, deloc);
+ boolean match = false;
+ for (int j = 0; j < oclist.length; j++) {
+ if ((oclist[j].trim()).equals(deloc)) {
+ match = true;
+ break;
+ }
+ }
+ if (!match && hasoc) {
+ log(ILogger.LL_INFO, "deleting CRL objectclass " + deloc + " from " + dn);
+ modSet.add(LDAPModification.DELETE,
+ new LDAPAttribute("objectclass", deloc));
+ }
+ }
+ }
+
+ // reset mObjAdded and mObjDeleted, if needed
+ if ((!mObjAdded.equals("")) || (!mObjDeleted.equals(""))) {
+ mObjAdded = "";
+ mObjDeleted = "";
+ mConfig.putString("crlObjectClassAdded", "");
+ mConfig.putString("crlObjectClassDeleted", "");
+ try {
+ mConfig.commit(false);
+ } catch (Exception e) {
+ log(ILogger.LL_INFO, "Failure in updating mObjAdded and mObjDeleted");
+ }
+ }
+
+ conn.modify(dn, modSet);
+ } catch (CRLException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_PUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_CRL_ERROR", e.toString()));
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_PUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_CRL_ERROR", e.toString()));
+ }
+ } finally {
+ if (altConn != null) {
+ try {
+ altConn.disconnect();
+ } catch (LDAPException e) {
+ // safely ignored
+ }
+ }
+ }
+
+ }
+
+ /**
+ * There shouldn't be a need to call this.
+ * CRLs are always replaced but this is implemented anyway in case
+ * there is ever a reason to remove a global CRL.
+ */
+ public void unpublish(LDAPConnection conn, String dn, Object crlObj)
+ throws ELdapException {
+ try {
+ byte[] crlEnc = ((X509CRL) crlObj).getEncoded();
+
+ try {
+ mCrlAttr = mConfig.getString("crlAttr", LDAP_CRL_ATTR);
+ mCrlObjectClass = mConfig.getString("crlObjectClass", LDAP_CRL_OBJECTCLASS);
+ } catch (EBaseException e) {
+ }
+
+ LDAPSearchResults res = conn.search(dn, LDAPv2.SCOPE_BASE,
+ "(objectclass=*)", new String[] { mCrlAttr, "objectclass" }, false);
+ LDAPEntry e = res.next();
+ LDAPAttribute crls = e.getAttribute(mCrlAttr);
+ LDAPAttribute ocs = e.getAttribute("objectclass");
+
+ LDAPModificationSet modSet = new LDAPModificationSet();
+
+ boolean hasOC = false;
+ boolean hasCRL =
+ LdapUserCertPublisher.ByteValueExists(crls, crlEnc);
+
+ if (hasCRL) {
+ modSet.add(LDAPModification.DELETE,
+ new LDAPAttribute(mCrlAttr, crlEnc));
+ }
+
+ String[] oclist = mCrlObjectClass.split(",");
+ for (int i = 0; i < oclist.length; i++) {
+ String oc = oclist[i].trim();
+ if (LdapUserCertPublisher.StringValueExists(ocs, oc)) {
+ log(ILogger.LL_INFO, "unpublish: deleting CRL object class " + oc + " from " + dn);
+ modSet.add(LDAPModification.DELETE,
+ new LDAPAttribute("objectClass", oc));
+ hasOC = true;
+ }
+ }
+
+ if (hasCRL || hasOC) {
+ conn.modify(dn, modSet);
+ } else {
+ log(ILogger.LL_INFO,
+ "unpublish: " + dn + " already has not CRL");
+ }
+ } catch (CRLException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_UNPUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_CRL_ERROR", e.toString()));
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_UNPUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_UNPUBLISH_CRL_ERROR", e.toString()));
+ }
+ }
+ return;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "LdapCrlPublisher: " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/publishers/LdapEncryptCertPublisher.java b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapEncryptCertPublisher.java
new file mode 100644
index 000000000..41a15f93a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapEncryptCertPublisher.java
@@ -0,0 +1,357 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.publishers;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ca.ICAService;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapPublisher;
+
+/**
+ * Interface for mapping a X509 certificate to a LDAP entry
+ *
+ * @version $Revision$, $Date$
+ */
+public class LdapEncryptCertPublisher implements ILdapPublisher, IExtendedPluginInfo {
+ public static final String LDAP_USERCERT_ATTR = "userCertificate;binary";
+ public static final String PROP_REVOKE_CERT = "revokeCert";
+
+ protected String mCertAttr = LDAP_USERCERT_ATTR;
+ private ILogger mLogger = CMS.getLogger();
+ private IConfigStore mConfig = null;
+ private boolean mInited = false;
+
+ public LdapEncryptCertPublisher() {
+ }
+
+ public String getImplName() {
+ return "LdapEncryptCertPublisher";
+ }
+
+ public String getDescription() {
+ return "LdapEncryptCertPublisher";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ "certAttr;string;LDAP attribute in which to store the certificate",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ldappublish-publisher-usercertpublisher",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";This plugin knows how to publish user certificates"
+ };
+
+ return params;
+
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement("certAttr=" + mCertAttr);
+ return v;
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement("certAttr=" + mCertAttr);
+ return v;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void init(IConfigStore config)
+ throws EBaseException {
+ if (mInited)
+ return;
+ mConfig = config;
+ mCertAttr = mConfig.getString("certAttr", LDAP_USERCERT_ATTR);
+ mInited = true;
+ }
+
+ public LdapEncryptCertPublisher(String certAttr) {
+ mCertAttr = certAttr;
+ }
+
+ /**
+ * publish a user certificate
+ * Adds the cert to the multi-valued certificate attribute as a
+ * DER encoded binary blob. Does not check if cert already exists.
+ *
+ * @param conn the LDAP connection
+ * @param dn dn of the entry to publish the certificate
+ * @param certObj the certificate object.
+ */
+ public void publish(LDAPConnection conn, String dn, Object certObj)
+ throws ELdapException {
+ if (conn == null)
+ return;
+
+ if (!(certObj instanceof X509Certificate))
+ throw new IllegalArgumentException("Illegal arg to publish");
+
+ X509Certificate cert = (X509Certificate) certObj;
+
+ log(ILogger.LL_INFO, "Publishing " + cert);
+ try {
+ byte[] certEnc = cert.getEncoded();
+
+ // check if cert already exists.
+ LDAPSearchResults res = conn.search(dn, LDAPv2.SCOPE_BASE,
+ "(objectclass=*)", new String[] { mCertAttr }, false);
+ LDAPEntry entry = res.next();
+ LDAPAttribute attr = getModificationAttribute(entry.getAttribute(mCertAttr), certEnc);
+
+ if (attr == null) {
+ log(ILogger.LL_INFO, "publish: " + dn + " already has cert.");
+ return;
+ }
+
+ // publish
+ LDAPModification mod = new LDAPModification(LDAPModification.REPLACE, attr);
+
+ conn.modify(dn, mod);
+ } catch (CertificateEncodingException e) {
+ CMS.debug("LdapEncryptCertPublisher: error in publish: " + e.toString());
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_GET_DER_ENCODED_CERT_FAILED", e.toString()));
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_PUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_USERCERT_ERROR", e.toString()));
+ }
+ }
+ return;
+ }
+
+ /**
+ * unpublish a user certificate
+ * deletes the certificate from the list of certificates.
+ * does not check if certificate is already there.
+ */
+ public void unpublish(LDAPConnection conn, String dn, Object certObj)
+ throws ELdapException {
+ if (!(certObj instanceof X509Certificate))
+ throw new IllegalArgumentException("Illegal arg to publish");
+
+ X509Certificate cert = (X509Certificate) certObj;
+
+ try {
+ byte[] certEnc = cert.getEncoded();
+
+ // check if cert already deleted.
+ LDAPSearchResults res = conn.search(dn, LDAPv2.SCOPE_BASE,
+ "(objectclass=*)", new String[] { mCertAttr }, false);
+ LDAPEntry entry = res.next();
+
+ if (!ByteValueExists(entry.getAttribute(mCertAttr), certEnc)) {
+ log(ILogger.LL_INFO, dn + " already has not cert");
+ return;
+ }
+
+ LDAPModification mod = new LDAPModification(LDAPModification.DELETE,
+ new LDAPAttribute(mCertAttr, certEnc));
+
+ conn.modify(dn, mod);
+ } catch (CertificateEncodingException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_UNPUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_GET_DER_ENCODED_CERT_FAILED", e.toString()));
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_UNPUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_UNPUBLISH_USERCERT_ERROR", e.toString()));
+ }
+ }
+ return;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "LdapUserCertPublisher: " + msg);
+ }
+
+ public LDAPAttribute getModificationAttribute(
+ LDAPAttribute attr, byte[] bval) {
+
+ LDAPAttribute at = new LDAPAttribute(attr.getName(), bval);
+ // determine if the given cert is a signing or an encryption
+ // certificate
+ X509CertImpl thisCert = null;
+
+ try {
+ thisCert = new X509CertImpl(bval);
+ } catch (Exception e) {
+ }
+ if (thisCert == null) {
+ return at;
+ }
+
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> vals = attr.getByteValues();
+ byte[] val = null;
+
+ while (vals.hasMoreElements()) {
+ val = vals.nextElement();
+ try {
+ X509CertImpl cert = new X509CertImpl(val);
+
+ log(ILogger.LL_INFO, "Checking " + cert);
+ if (CMS.isEncryptionCert(thisCert) &&
+ CMS.isEncryptionCert(cert)) {
+ // skip
+ log(ILogger.LL_INFO, "SKIP ENCRYPTION " + cert);
+ revokeCert(cert);
+ } else if (CMS.isSigningCert(thisCert) &&
+ CMS.isSigningCert(cert)) {
+ // skip
+ log(ILogger.LL_INFO, "SKIP SIGNING " + cert);
+ revokeCert(cert);
+ } else {
+ at.addValue(val);
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_CHECK_FAILED", e.toString()));
+ }
+ }
+ return at;
+ }
+
+ private RevokedCertImpl formCRLEntry(
+ BigInteger serialNo, RevocationReason reason)
+ throws EBaseException {
+ CRLReasonExtension reasonExt = new CRLReasonExtension(reason);
+ CRLExtensions crlentryexts = new CRLExtensions();
+
+ try {
+ crlentryexts.set(CRLReasonExtension.NAME, reasonExt);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_SET_CRL_REASON", reason.toString(), e.toString()));
+
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_INTERNAL_ERROR", e.toString()));
+ }
+ RevokedCertImpl crlentry =
+ new RevokedCertImpl(serialNo, new Date(), crlentryexts);
+
+ return crlentry;
+ }
+
+ private void revokeCert(X509CertImpl cert)
+ throws EBaseException {
+ try {
+ if (mConfig.getBoolean(PROP_REVOKE_CERT, true) == false) {
+ return;
+ }
+ } catch (EBaseException e) {
+ return;
+ }
+ BigInteger serialNum = cert.getSerialNumber();
+ // need to revoke certificate also
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem("ca");
+ ICAService service = (ICAService) ca.getCAService();
+ RevokedCertImpl crlEntry = formCRLEntry(
+ serialNum, RevocationReason.KEY_COMPROMISE);
+
+ service.revokeCert(crlEntry);
+ }
+
+ /**
+ * checks if a byte attribute has a certain value.
+ */
+ public static boolean ByteValueExists(LDAPAttribute attr, byte[] bval) {
+ if (attr == null) {
+ return false;
+ }
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> vals = attr.getByteValues();
+ byte[] val = null;
+
+ while (vals.hasMoreElements()) {
+ val = vals.nextElement();
+ if (PublisherUtils.byteArraysAreEqual(val, bval)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * checks if a attribute has a string value.
+ */
+ public static boolean StringValueExists(LDAPAttribute attr, String sval) {
+ if (attr == null) {
+ return false;
+ }
+ @SuppressWarnings("unchecked")
+ Enumeration<String> vals = attr.getStringValues();
+ String val = null;
+
+ while (vals.hasMoreElements()) {
+ val = vals.nextElement();
+ if (val.equalsIgnoreCase(sval)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/publishers/LdapUserCertPublisher.java b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapUserCertPublisher.java
new file mode 100644
index 000000000..020c25552
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapUserCertPublisher.java
@@ -0,0 +1,333 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.publishers;
+
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPSSLSocketFactoryExt;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapPublisher;
+
+/**
+ * Interface for mapping a X509 certificate to a LDAP entry
+ *
+ * @version $Revision$, $Date$
+ */
+public class LdapUserCertPublisher implements ILdapPublisher, IExtendedPluginInfo {
+ public static final String LDAP_USERCERT_ATTR = "userCertificate;binary";
+
+ protected String mCertAttr = LDAP_USERCERT_ATTR;
+ private ILogger mLogger = CMS.getLogger();
+ private IConfigStore mConfig = null;
+ private boolean mInited = false;
+
+ public LdapUserCertPublisher() {
+ }
+
+ public String getImplName() {
+ return "LdapUserCertPublisher";
+ }
+
+ public String getDescription() {
+ return "LdapUserCertPublisher";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ "certAttr;string;LDAP attribute in which to store the certificate",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ldappublish-publisher-usercertpublisher",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";This plugin knows how to publish user certificates"
+ };
+
+ return params;
+
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement("certAttr=" + mCertAttr);
+ return v;
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement("certAttr=" + mCertAttr);
+ return v;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void init(IConfigStore config)
+ throws EBaseException {
+ if (mInited)
+ return;
+ mConfig = config;
+ mCertAttr = mConfig.getString("certAttr", LDAP_USERCERT_ATTR);
+ mInited = true;
+ }
+
+ public LdapUserCertPublisher(String certAttr) {
+ mCertAttr = certAttr;
+ }
+
+ /**
+ * publish a user certificate
+ * Adds the cert to the multi-valued certificate attribute as a
+ * DER encoded binary blob. Does not check if cert already exists.
+ *
+ * @param conn the LDAP connection
+ * @param dn dn of the entry to publish the certificate
+ * @param certObj the certificate object.
+ */
+ public void publish(LDAPConnection conn, String dn, Object certObj)
+ throws ELdapException {
+ if (conn == null)
+ return;
+
+ // Bugscape #56124 - support multiple publishing directory
+ // see if we should create local connection
+ LDAPConnection altConn = null;
+ try {
+ String host = mConfig.getString("host", null);
+ String port = mConfig.getString("port", null);
+ if (host != null && port != null) {
+ int portVal = Integer.parseInt(port);
+ int version = Integer.parseInt(mConfig.getString("version", "2"));
+ String cert_nick = mConfig.getString("clientCertNickname", null);
+ LDAPSSLSocketFactoryExt sslSocket = null;
+ if (cert_nick != null) {
+ sslSocket = CMS.getLdapJssSSLSocketFactory(cert_nick);
+ }
+ String mgr_dn = mConfig.getString("bindDN", null);
+ String mgr_pwd = mConfig.getString("bindPWD", null);
+
+ altConn = CMS.getBoundConnection(host, portVal,
+ version,
+ sslSocket, mgr_dn, mgr_pwd);
+ conn = altConn;
+ }
+ } catch (LDAPException e) {
+ CMS.debug("Failed to create alt connection " + e);
+ } catch (EBaseException e) {
+ CMS.debug("Failed to create alt connection " + e);
+ }
+
+ if (!(certObj instanceof X509Certificate))
+ throw new IllegalArgumentException("Illegal arg to publish");
+
+ X509Certificate cert = (X509Certificate) certObj;
+
+ boolean deleteCert = false;
+ try {
+ deleteCert = mConfig.getBoolean("deleteCert", false);
+ } catch (Exception e) {
+ }
+
+ try {
+ byte[] certEnc = cert.getEncoded();
+
+ // check if cert already exists.
+ LDAPSearchResults res = conn.search(dn, LDAPv2.SCOPE_BASE,
+ "(objectclass=*)", new String[] { mCertAttr }, false);
+ LDAPEntry entry = res.next();
+
+ if (ByteValueExists(entry.getAttribute(mCertAttr), certEnc)) {
+ log(ILogger.LL_INFO, "publish: " + dn + " already has cert.");
+ return;
+ }
+
+ // publish
+ LDAPModification mod = null;
+ if (deleteCert) {
+ mod = new LDAPModification(LDAPModification.REPLACE,
+ new LDAPAttribute(mCertAttr, certEnc));
+ } else {
+ mod = new LDAPModification(LDAPModification.ADD,
+ new LDAPAttribute(mCertAttr, certEnc));
+ }
+
+ conn.modify(dn, mod);
+
+ // log a successful message to the "transactions" log
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_LDAP,
+ ILogger.LL_INFO,
+ AuditFormat.LDAP_PUBLISHED_FORMAT,
+ new Object[] { "LdapUserCertPublisher",
+ cert.getSerialNumber().toString(16),
+ cert.getSubjectDN() });
+ } catch (CertificateEncodingException e) {
+ CMS.debug("LdapUserCertPublisher: error in publish: " + e.toString());
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_GET_DER_ENCODED_CERT_FAILED", e.toString()));
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_PUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_USERCERT_ERROR", e.toString()));
+ }
+ } finally {
+ if (altConn != null) {
+ try {
+ altConn.disconnect();
+ } catch (LDAPException e) {
+ // safely ignored
+ }
+ }
+ }
+ return;
+ }
+
+ /**
+ * unpublish a user certificate
+ * deletes the certificate from the list of certificates.
+ * does not check if certificate is already there.
+ */
+ public void unpublish(LDAPConnection conn, String dn, Object certObj)
+ throws ELdapException {
+
+ boolean disableUnpublish = false;
+ try {
+ disableUnpublish = mConfig.getBoolean("disableUnpublish", false);
+ } catch (Exception e) {
+ }
+
+ if (disableUnpublish) {
+ CMS.debug("UserCertPublisher: disable unpublish");
+ return;
+ }
+
+ if (!(certObj instanceof X509Certificate))
+ throw new IllegalArgumentException("Illegal arg to publish");
+
+ X509Certificate cert = (X509Certificate) certObj;
+
+ try {
+ byte[] certEnc = cert.getEncoded();
+
+ // check if cert already deleted.
+ LDAPSearchResults res = conn.search(dn, LDAPv2.SCOPE_BASE,
+ "(objectclass=*)", new String[] { mCertAttr }, false);
+ LDAPEntry entry = res.next();
+
+ if (!ByteValueExists(entry.getAttribute(mCertAttr), certEnc)) {
+ log(ILogger.LL_INFO, dn + " already has not cert");
+ return;
+ }
+
+ LDAPModification mod = new LDAPModification(LDAPModification.DELETE,
+ new LDAPAttribute(mCertAttr, certEnc));
+
+ conn.modify(dn, mod);
+ } catch (CertificateEncodingException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_UNPUBLISH_ERROR", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_GET_DER_ENCODED_CERT_FAILED", e.toString()));
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("PUBLISH_NO_LDAP_SERVER"));
+ throw new ELdapServerDownException(CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), ""
+ + conn.getPort()));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_UNPUBLISH_ERROR"));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_UNPUBLISH_USERCERT_ERROR", e.toString()));
+ }
+ }
+ return;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "LdapUserCertPublisher: " + msg);
+ }
+
+ /**
+ * checks if a byte attribute has a certain value.
+ */
+ public static boolean ByteValueExists(LDAPAttribute attr, byte[] bval) {
+ if (attr == null) {
+ return false;
+ }
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> vals = attr.getByteValues();
+ byte[] val = null;
+
+ while (vals.hasMoreElements()) {
+ val = vals.nextElement();
+ if (val.length == 0)
+ continue;
+ if (PublisherUtils.byteArraysAreEqual(val, bval)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * checks if a attribute has a string value.
+ */
+ public static boolean StringValueExists(LDAPAttribute attr, String sval) {
+ if (attr == null) {
+ return false;
+ }
+ @SuppressWarnings("unchecked")
+ Enumeration<String> vals = attr.getStringValues();
+ String val = null;
+
+ while (vals.hasMoreElements()) {
+ val = vals.nextElement();
+ if (val.equalsIgnoreCase(sval)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/publishers/OCSPPublisher.java b/base/server/cms/src/com/netscape/cms/publish/publishers/OCSPPublisher.java
new file mode 100644
index 000000000..f3e9d3c6f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/publishers/OCSPPublisher.java
@@ -0,0 +1,356 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.publishers;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.Socket;
+import java.net.URLEncoder;
+import java.security.cert.CRLException;
+import java.security.cert.X509CRL;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.ldap.LDAPConnection;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapPublisher;
+import com.netscape.cmsutil.http.HttpRequest;
+import com.netscape.cmsutil.http.JssSSLSocketFactory;
+
+/**
+ * This publisher writes certificate and CRL into
+ * a directory.
+ *
+ * @version $Revision$, $Date$
+ */
+public class OCSPPublisher implements ILdapPublisher, IExtendedPluginInfo {
+ private static final String PROP_HOST = "host";
+ private static final String PROP_PORT = "port";
+ private static final String PROP_PATH = "path";
+ private static final String PROP_NICK = "nickName";
+ private static final String PROP_CLIENT_AUTH_ENABLE = "enableClientAuth";
+
+ private IConfigStore mConfig = null;
+ private String mHost = null;
+ private String mPort = null;
+ private String mPath = null;
+ private String mNickname = null;
+ private boolean mClientAuthEnabled = true;
+ private ILogger mLogger = CMS.getLogger();
+
+ /**
+ * Returns the implementation name.
+ */
+ public String getImplName() {
+ return "OCSPPublisher";
+ }
+
+ /**
+ * Returns the description of the ldap publisher.
+ */
+ public String getDescription() {
+ return "This publisher writes the CRL to CMS's OCSP server.";
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ String[] params = {
+ PROP_HOST + ";string;Host of CMS's OCSP Secure agent service",
+ PROP_PORT + ";string;Port of CMS's OCSP Secure agent service",
+ PROP_PATH + ";string;URI of CMS's OCSP Secure agent service",
+ PROP_NICK + ";string;Nickname of cert used for client authentication",
+ PROP_CLIENT_AUTH_ENABLE + ";boolean;Client Authentication enabled",
+ IExtendedPluginInfo.HELP_TOKEN +
+ ";configuration-ldappublish-publisher-ocsppublisher",
+ IExtendedPluginInfo.HELP_TEXT +
+ ";Publishes CRLs to a Online Certificate Status Manager, an OCSP responder provided by CMS."
+ };
+
+ return params;
+ }
+
+ /**
+ * Returns the current instance parameters.
+ */
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+ String host = "";
+ String port = "";
+ String path = "";
+ String nickname = "";
+ String clientAuthEnabled = "";
+
+ try {
+ host = mConfig.getString(PROP_HOST);
+ } catch (EBaseException e) {
+ }
+ v.addElement(PROP_HOST + "=" + host);
+ try {
+ port = mConfig.getString(PROP_PORT);
+ } catch (EBaseException e) {
+ }
+ v.addElement(PROP_PORT + "=" + port);
+ try {
+ path = mConfig.getString(PROP_PATH);
+ } catch (EBaseException e) {
+ }
+ v.addElement(PROP_PATH + "=" + path);
+ try {
+ nickname = mConfig.getString(PROP_NICK);
+ } catch (EBaseException e) {
+ }
+ v.addElement(PROP_NICK + "=" + nickname);
+ try {
+ clientAuthEnabled = mConfig.getString(PROP_CLIENT_AUTH_ENABLE);
+ } catch (EBaseException e) {
+ }
+ v.addElement(PROP_CLIENT_AUTH_ENABLE + "=" + clientAuthEnabled);
+ return v;
+ }
+
+ /**
+ * Returns the initial default parameters.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ IConfigStore config = CMS.getConfigStore();
+ String nickname = "";
+ // get subsystem cert nickname as default for client auth
+ try {
+ nickname = config.getString("ca.subsystem.nickname", "");
+ String tokenname = config.getString("ca.subsystem.tokenname", "");
+ if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token"))
+ nickname = tokenname + ":" + nickname;
+ } catch (Exception e) {
+ }
+
+ v.addElement(PROP_HOST + "=");
+ v.addElement(PROP_PORT + "=");
+ v.addElement(PROP_PATH + "=/ocsp/agent/ocsp/addCRL");
+ v.addElement(PROP_CLIENT_AUTH_ENABLE + "=true");
+ v.addElement(PROP_NICK + "=" + nickname);
+ return v;
+ }
+
+ /**
+ * Initializes this plugin.
+ */
+ public void init(IConfigStore config) {
+ mConfig = config;
+ try {
+ mHost = mConfig.getString(PROP_HOST, "");
+ mPort = mConfig.getString(PROP_PORT, "");
+ mPath = mConfig.getString(PROP_PATH, "");
+ mNickname = mConfig.getString(PROP_NICK, "");
+ mClientAuthEnabled = mConfig.getBoolean(PROP_CLIENT_AUTH_ENABLE, true);
+ } catch (EBaseException e) {
+ }
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ protected Socket Connect(String host, boolean secure, JssSSLSocketFactory factory) {
+ Socket socket = null;
+ StringTokenizer st = new StringTokenizer(host, " ");
+ while (st.hasMoreTokens()) {
+ String hp = st.nextToken(); // host:port
+ StringTokenizer st1 = new StringTokenizer(hp, ":");
+ String h = st1.nextToken();
+ int p = Integer.parseInt(st1.nextToken());
+ try {
+ if (secure) {
+ socket = factory.makeSocket(h, p);
+ } else {
+ socket = new Socket(h, p);
+ }
+ return socket;
+ } catch (Exception e) {
+ }
+ try {
+ Thread.sleep(5000); // 5 seconds delay
+ } catch (Exception e) {
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Publishs a object to the ldap directory.
+ *
+ * @param conn a Ldap connection
+ * (null if LDAP publishing is not enabled)
+ * @param dn dn of the ldap entry to publish cert
+ * (null if LDAP publishing is not enabled)
+ * @param object object to publish
+ * (java.security.cert.X509Certificate or,
+ * java.security.cert.X509CRL)
+ */
+ public synchronized void publish(LDAPConnection conn, String dn, Object object)
+ throws ELdapException {
+ try {
+ if (!(object instanceof X509CRL))
+ return;
+ X509CRL crl = (X509CRL) object;
+
+ // talk to agent port of CMS
+
+ // open the connection and prepare it to POST
+ boolean secure = true;
+
+ String host = mHost;
+ int port = Integer.parseInt(mPort);
+ String path = mPath;
+
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_INFO, "OCSPPublisher: " +
+ "Host='" + host + "' Port='" + port +
+ "' URL='" + path + "'");
+ CMS.debug("OCSPPublisher: " +
+ "Host='" + host + "' Port='" + port +
+ "' URL='" + path + "'");
+
+ StringBuffer query = new StringBuffer();
+ query.append("crl=");
+ query.append(URLEncoder.encode("-----BEGIN CERTIFICATE REVOCATION LIST-----\n", "UTF-8"));
+ query.append(URLEncoder.encode(CMS.BtoA(crl.getEncoded()), "UTF-8"));
+ query.append(URLEncoder.encode("\n-----END CERTIFICATE REVOCATION LIST-----", "UTF-8"));
+ query.append("&noui=true");
+
+ Socket socket = null;
+ JssSSLSocketFactory factory;
+
+ if (mClientAuthEnabled) {
+ factory = new JssSSLSocketFactory(mNickname);
+ } else {
+ factory = new JssSSLSocketFactory();
+ }
+
+ if (mHost != null && mHost.indexOf(' ') != -1) {
+ // support failover hosts configuration
+ // host parameter can be
+ // "directory.knowledge.com:1050 people.catalog.com 199.254.1.2"
+ do {
+ socket = Connect(mHost, secure, factory);
+ } while (socket == null);
+ } else {
+ if (secure) {
+ socket = factory.makeSocket(host, port);
+ } else {
+ socket = new Socket(host, port);
+ }
+ }
+
+ if (socket == null) {
+ CMS.debug("OCSPPublisher::publish() - socket is null!");
+ throw new ELdapException("socket is null");
+ }
+
+ // use HttpRequest and POST
+ HttpRequest httpReq = new HttpRequest();
+
+ httpReq.setMethod("POST");
+ httpReq.setURI(path);
+ httpReq.setHeader("Connection", "Keep-Alive");
+
+ httpReq.setHeader("Content-Type",
+ "application/x-www-form-urlencoded");
+ httpReq.setHeader("Content-Transfer-Encoding", "7bit");
+
+ httpReq.setHeader("Content-Length",
+ Integer.toString(query.length()));
+ httpReq.setContent(query.toString());
+ OutputStream os = socket.getOutputStream();
+ OutputStreamWriter outputStreamWriter = new OutputStreamWriter(os, "UTF8");
+
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_INFO, "OCSPPublisher: start sending CRL");
+ long startTime = CMS.getCurrentDate().getTime();
+ CMS.debug("OCSPPublisher: start CRL sending startTime=" + startTime);
+ httpReq.write(outputStreamWriter);
+ long endTime = CMS.getCurrentDate().getTime();
+ CMS.debug("OCSPPublisher: done CRL sending endTime=" + endTime + " diff=" + (endTime - startTime));
+
+ // Read the response
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_INFO, "OCSPPublisher: start getting response");
+ BufferedReader dis = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+ String nextline;
+ String error = "";
+ boolean status = false;
+
+ while ((nextline = dis.readLine()) != null) {
+ if (nextline.startsWith("status=")) {
+ if (nextline.substring(7, nextline.length()).equals("0")) {
+ status = true;
+ }
+ }
+ if (nextline.startsWith("error=")) {
+ error = nextline.substring(6, nextline.length());
+ }
+ }
+ dis.close();
+ if (status) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_INFO, "OCSPPublisher: successful");
+ } else {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_INFO, "OCSPPublisher: failed - " + error);
+ }
+
+ } catch (IOException e) {
+ CMS.debug("OCSPPublisher: publish failed " + e.toString());
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_OCSP_PUBLISHER_ERROR", e.toString()));
+ } catch (CRLException e) {
+ CMS.debug("OCSPPublisher: publish failed " + e.toString());
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_OCSP_PUBLISHER_ERROR", e.toString()));
+ } catch (Exception e) {
+ CMS.debug("OCSPPublisher: publish failed " + e.toString());
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("PUBLISH_OCSP_PUBLISHER_ERROR", e.toString()));
+ }
+ }
+
+ /**
+ * Unpublishs a object to the ldap directory.
+ *
+ * @param conn the Ldap connection
+ * (null if LDAP publishing is not enabled)
+ * @param dn dn of the ldap entry to unpublish cert
+ * (null if LDAP publishing is not enabled)
+ * @param object object to unpublish
+ * (java.security.cert.X509Certificate)
+ */
+ public void unpublish(LDAPConnection conn, String dn, Object object)
+ throws ELdapException {
+ // NOT USED
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/publish/publishers/PublisherUtils.java b/base/server/cms/src/com/netscape/cms/publish/publishers/PublisherUtils.java
new file mode 100644
index 000000000..280a0ce97
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/publish/publishers/PublisherUtils.java
@@ -0,0 +1,136 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.publish.publishers;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Vector;
+
+/**
+ * Publisher utility class.
+ *
+ * @version $Revision$, $Date$
+ */
+public class PublisherUtils {
+ public static void checkHost(String hostname) throws UnknownHostException {
+ InetAddress.getByName(hostname);
+ }
+
+ public static void copyStream(InputStream in, OutputStream out) throws IOException {
+ byte[] buf = new byte[4096];
+ int len;
+
+ while ((len = in.read(buf)) != -1) {
+ out.write(buf, 0, len);
+ }
+ }
+
+ public static void copyStream(BufferedReader in, OutputStreamWriter out) throws IOException {
+ char[] buf = new char[4096];
+ int len;
+
+ while ((len = in.read(buf)) != -1) {
+ out.write(buf, 0, len);
+ }
+ }
+
+ /// Sorts an array of Strings.
+ // Java currently has no general sort function. Sorting Strings is
+ // common enough that it's worth making a special case.
+ public static void sortStrings(String[] strings) {
+ // Just does a bubblesort.
+ for (int i = 0; i < strings.length - 1; ++i) {
+ for (int j = i + 1; j < strings.length; ++j) {
+ if (strings[i].compareTo(strings[j]) > 0) {
+ String t = strings[i];
+
+ strings[i] = strings[j];
+ strings[j] = t;
+ }
+ }
+ }
+ }
+
+ /// Returns a date string formatted in Unix ls style - if it's within
+ // six months of now, Mmm dd hh:ss, else Mmm dd yyyy.
+ public static String lsDateStr(Date date) {
+ long dateTime = date.getTime();
+
+ if (dateTime == -1L)
+ return "------------";
+ long nowTime = System.currentTimeMillis();
+ SimpleDateFormat formatter = new SimpleDateFormat();
+
+ if (Math.abs(nowTime - dateTime) < 183L * 24L * 60L * 60L * 1000L)
+ formatter.applyPattern("MMM dd hh:ss");
+ else
+ formatter.applyPattern("MMM dd yyyy");
+ return formatter.format(date);
+ }
+
+ /**
+ * compares contents two byte arrays returning true if exactly same.
+ */
+ static public boolean byteArraysAreEqual(byte[] a, byte[] b) {
+ if (a.length != b.length)
+ return false;
+ for (int i = 0; i < a.length; i++) {
+ if (a[i] != b[i])
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * strips out double quotes around String parameter
+ *
+ * @param s the string potentially bracketed with double quotes
+ * @return string stripped of surrounding double quotes
+ */
+ public static String stripQuotes(String s) {
+ if (s == null) {
+ return s;
+ }
+
+ if ((s.startsWith("\"")) && (s.endsWith("\""))) {
+ return (s.substring(1, (s.length() - 1)));
+ }
+
+ return s;
+ }
+
+ /**
+ * returns an array of strings from a vector of Strings
+ * there'll be trouble if the Vector contains something other
+ * than just Strings
+ */
+ public static String[] getStringArrayFromVector(Vector<String> v) {
+ String s[] = new String[v.size()];
+
+ v.copyInto(s);
+ return s;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/realm/PKIPrincipal.java b/base/server/cms/src/com/netscape/cms/realm/PKIPrincipal.java
new file mode 100644
index 000000000..c39ab4157
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/realm/PKIPrincipal.java
@@ -0,0 +1,29 @@
+package com.netscape.cms.realm;
+
+import java.util.List;
+
+import org.apache.catalina.realm.GenericPrincipal;
+
+import com.netscape.certsrv.authentication.IAuthToken;
+
+/**
+ * @author Endi S. Dewata
+ */
+
+public class PKIPrincipal extends GenericPrincipal {
+
+ IAuthToken authToken;
+
+ public PKIPrincipal(String name, String password, List<String> roles, IAuthToken authToken) {
+ super(name, password, roles);
+ this.authToken = authToken;
+ }
+
+ public PKIPrincipal(String name, String password, List<String> roles) {
+ this(name, password, roles, null);
+ }
+
+ public IAuthToken getAuthToken() {
+ return authToken;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/realm/PKIRealm.java b/base/server/cms/src/com/netscape/cms/realm/PKIRealm.java
new file mode 100644
index 000000000..b035f53f6
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/realm/PKIRealm.java
@@ -0,0 +1,160 @@
+package com.netscape.cms.realm;
+
+import java.security.Principal;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+import netscape.security.x509.X509CertImpl;
+
+import org.apache.catalina.realm.RealmBase;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authentication.ICertUserDBAuthentication;
+import com.netscape.certsrv.authentication.IPasswdUserDBAuthentication;
+import com.netscape.certsrv.usrgrp.EUsrGrpException;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cms.servlet.common.AuthCredentials;
+
+/**
+ * PKI Realm
+ *
+ * This realm provides an authentication service against PKI user database.
+ * The realm also provides an authorization service that validates request
+ * URL's against the access control list defined in the internal database.
+ */
+
+public class PKIRealm extends RealmBase {
+
+ @Override
+ protected String getName() {
+ return "PKIRealm";
+ }
+
+ @Override
+ public Principal authenticate(String username, String password) {
+ logDebug("Authenticating username "+username+" with password.");
+
+ try {
+ IAuthSubsystem authSub = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ IAuthManager authMgr = authSub.getAuthManager(IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID);
+
+ AuthCredentials creds = new AuthCredentials();
+ creds.set(IPasswdUserDBAuthentication.CRED_UID, username);
+ creds.set(IPasswdUserDBAuthentication.CRED_PWD, password);
+
+ IAuthToken authToken = authMgr.authenticate(creds); // throws exception if authentication fails
+
+ return getPrincipal(username, authToken);
+
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ @Override
+ public Principal authenticate(final X509Certificate certs[]) {
+ logDebug("Authenticating certificate chain:");
+
+ try {
+ X509CertImpl certImpls[] = new X509CertImpl[certs.length];
+ for (int i=0; i<certs.length; i++) {
+ X509Certificate cert = certs[i];
+ logDebug(" "+cert.getSubjectDN());
+
+ // Convert sun.security.x509.X509CertImpl to netscape.security.x509.X509CertImpl
+ certImpls[i] = new X509CertImpl(cert.getEncoded());
+ }
+
+ IAuthSubsystem authSub = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ IAuthManager authMgr = authSub.getAuthManager(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID);
+
+ AuthCredentials creds = new AuthCredentials();
+ creds.set(ICertUserDBAuthentication.CRED_CERT, certImpls);
+
+ IAuthToken authToken = authMgr.authenticate(creds); // throws exception if authentication fails
+
+ String username = authToken.getInString(ICertUserDBAuthentication.TOKEN_USERID);
+ logDebug("User ID: "+username);
+
+ return getPrincipal(username, authToken);
+
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ @Override
+ protected Principal getPrincipal(String username) {
+ return getPrincipal(username, (IAuthToken)null);
+ }
+
+ protected Principal getPrincipal(String username, IAuthToken authToken) {
+
+ try {
+ IUser user = getUser(username);
+ return getPrincipal(user, authToken);
+
+ } catch (Throwable e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ protected Principal getPrincipal(IUser user, IAuthToken authToken) throws EUsrGrpException {
+ List<String> roles = getRoles(user);
+ return new PKIPrincipal(user.getUserID(), null, roles, authToken);
+ }
+
+ protected IUser getUser(String username) throws EUsrGrpException {
+ IUGSubsystem ugSub = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+ IUser user = ugSub.getUser(username);
+ logDebug("User DN: "+user.getUserDN());
+ return user;
+ }
+
+ protected List<String> getRoles(IUser user) throws EUsrGrpException {
+
+ List<String> roles = new ArrayList<String>();
+
+ IUGSubsystem ugSub = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+ Enumeration<IGroup> groups = ugSub.findGroupsByUser(user.getUserDN());
+
+ logDebug("Roles:");
+ while (groups.hasMoreElements()) {
+ IGroup group = groups.nextElement();
+
+ String name = group.getName();
+ logDebug(" "+name);
+ roles.add(name);
+ }
+
+ return roles;
+ }
+
+ @Override
+ protected String getPassword(String username) {
+ return null;
+ }
+
+ /*
+ * TODO: Figure out how to do real logging
+ */
+ public void logErr(String msg) {
+ System.err.println(msg);
+ }
+
+ public void logDebug(String msg) {
+ System.out.println("PKIRealm: "+msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/request/RequestScheduler.java b/base/server/cms/src/com/netscape/cms/request/RequestScheduler.java
new file mode 100644
index 000000000..568d6f412
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/request/RequestScheduler.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.request;
+
+import java.util.Vector;
+
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestScheduler;
+
+/**
+ * This class represents a request scheduler that prioritizes
+ * the threads based on the request processing order.
+ * The request that enters the request queue first should
+ * be processed first.
+ *
+ * @version $Revision$, $Date$
+ */
+public class RequestScheduler implements IRequestScheduler {
+ private Vector<Thread> mRequestThreads = new Vector<Thread>();
+
+ /**
+ * Request entered the request queue processing.
+ *
+ * @param r request
+ */
+ public synchronized void requestIn(IRequest r) {
+ Thread current = Thread.currentThread();
+
+ if (mRequestThreads.size() == 0) {
+ current.setPriority(Thread.MAX_PRIORITY);
+ }
+ mRequestThreads.addElement(current);
+ }
+
+ /**
+ * Request exited the request queue processing.
+ *
+ * @param r request
+ */
+ public synchronized void requestOut(IRequest r) {
+ Thread current = Thread.currentThread();
+ Thread first = mRequestThreads.elementAt(0);
+
+ if (current.equals(first)) {
+ // reprioritize
+ try {
+ Thread second = mRequestThreads.elementAt(1);
+
+ second.setPriority(Thread.MAX_PRIORITY);
+ } catch (Exception e) {
+ // no second element; nothing to do
+ }
+ }
+ mRequestThreads.removeElement(current);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/selftests/ASelfTest.java b/base/server/cms/src/com/netscape/cms/selftests/ASelfTest.java
new file mode 100644
index 000000000..e77ece551
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/selftests/ASelfTest.java
@@ -0,0 +1,193 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cms.selftests;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+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.ISelfTest;
+import com.netscape.certsrv.selftests.ISelfTestSubsystem;
+
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * This class implements an individual self test.
+ * <P>
+ *
+ * @author mharmsen
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public abstract class ASelfTest
+ implements ISelfTest {
+ ////////////////////////
+ // default parameters //
+ ////////////////////////
+
+ //////////////////////////
+ // ISelfTest parameters //
+ //////////////////////////
+
+ // parameter information
+ private static final String SELF_TEST_NAME = "ASelfTest";
+
+ // variables associated with this specific object
+ protected ISelfTestSubsystem mSelfTestSubsystem = null;
+ protected String mInstanceName = null;
+ protected IConfigStore mConfig = null;
+ protected String mPrefix = null;
+
+ /////////////////////
+ // default methods //
+ /////////////////////
+
+ ///////////////////////
+ // ISelfTest methods //
+ ///////////////////////
+
+ /**
+ * 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 {
+ // store individual self test class values for this instance
+ mSelfTestSubsystem = subsystem;
+
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ } else {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_PARAMETER_WAS_NULL",
+ SELF_TEST_NAME));
+
+ throw new EMissingSelfTestException();
+ }
+
+ // store additional individual self test class values for this instance
+ mInstanceName = instanceName;
+
+ // compose self test plugin parameter property prefix
+ String pluginPath = PROP_PLUGIN + "." + instanceName;
+
+ mConfig = parameters.getSubStore(pluginPath);
+
+ if ((mConfig != null) &&
+ (mConfig.getName() != null) &&
+ (mConfig.getName() != "")) {
+ mPrefix = mConfig.getName().trim();
+ } else {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_PARAMETER_WAS_NULL",
+ SELF_TEST_NAME));
+
+ throw new EMissingSelfTestException();
+ }
+
+ return;
+ }
+
+ /**
+ * Notifies this subsystem if it is in execution mode.
+ * <P>
+ *
+ * @exception ESelfTestException failed to start
+ */
+ public abstract void startupSelfTest()
+ throws ESelfTestException;
+
+ /**
+ * Stops this subsystem. The subsystem may call shutdownSelfTest
+ * anytime after initialization.
+ * <P>
+ */
+ public abstract 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 mInstanceName;
+ }
+
+ /**
+ * 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 mConfig;
+ }
+
+ /**
+ * 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 abstract String getSelfTestDescription(Locale locale);
+
+ /**
+ * Execute an individual self test.
+ * <P>
+ *
+ * @param logger specifies logging subsystem
+ * @exception ESelfTestException self test exception
+ */
+ public abstract void runSelfTest(ILogEventListener logger)
+ throws ESelfTestException;
+}
diff --git a/base/server/cms/src/com/netscape/cms/selftests/ca/CAPresence.java b/base/server/cms/src/com/netscape/cms/selftests/ca/CAPresence.java
new file mode 100644
index 000000000..83caa0099
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/selftests/ca/CAPresence.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cms.selftests.ca;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+import java.security.cert.CertificateParsingException;
+import java.util.Locale;
+
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+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;
+
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * This class implements a self test to check for CA presence.
+ * <P>
+ *
+ * @author mharmsen
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class CAPresence
+ extends ASelfTest {
+ ////////////////////////
+ // default parameters //
+ ////////////////////////
+
+ ///////////////////////////
+ // CAPresence parameters //
+ ///////////////////////////
+
+ // parameter information
+ public static final String PROP_CA_SUB_ID = "CaSubId";
+ private String mCaSubId = null;
+
+ /////////////////////
+ // default methods //
+ /////////////////////
+
+ ////////////////////////
+ // CAPresence methods //
+ ////////////////////////
+
+ /**
+ * 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);
+
+ // retrieve mandatory parameter(s)
+ try {
+ mCaSubId = mConfig.getString(PROP_CA_SUB_ID);
+ if (mCaSubId != null) {
+ mCaSubId = mCaSubId.trim();
+ } else {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_MISSING_VALUES",
+ getSelfTestName(),
+ mPrefix
+ + "."
+ + PROP_CA_SUB_ID));
+
+ throw new EMissingSelfTestException(PROP_CA_SUB_ID);
+ }
+ } catch (EBaseException e) {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_MISSING_NAME",
+ getSelfTestName(),
+ mPrefix
+ + "."
+ + PROP_CA_SUB_ID));
+
+ throw new EMissingSelfTestException(mPrefix,
+ PROP_CA_SUB_ID,
+ null);
+ }
+
+ // retrieve optional parameter(s)
+
+ return;
+ }
+
+ /**
+ * Notifies this subsystem if it is in execution mode.
+ * <P>
+ *
+ * @exception ESelfTestException failed to start
+ */
+ public void startupSelfTest()
+ throws ESelfTestException {
+ return;
+ }
+
+ /**
+ * Stops this subsystem. The subsystem may call shutdownSelfTest
+ * anytime after initialization.
+ * <P>
+ */
+ public void shutdownSelfTest() {
+ return;
+ }
+
+ /**
+ * 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_CA_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;
+ ICertificateAuthority ca = null;
+ X509CertImpl caCert = null;
+ X509Key caPubKey = null;
+
+ ca = (ICertificateAuthority) CMS.getSubsystem(mCaSubId);
+
+ if (ca == null) {
+ // log that the CA is not installed
+ logMessage = CMS.getLogMessage("SELFTESTS_CA_IS_NOT_PRESENT",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ } else {
+ // Retrieve the CA certificate
+ caCert = ca.getCACert();
+
+ if (caCert == null) {
+ // log that the CA is not yet initialized
+ logMessage = CMS.getLogMessage(
+ "SELFTESTS_CA_IS_NOT_INITIALIZED",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ }
+
+ // Retrieve the CA certificate public key
+ try {
+ caPubKey = (X509Key) caCert.get(X509CertImpl.PUBLIC_KEY);
+
+ if (caPubKey == null) {
+ // log that something is seriously wrong with the CA
+ logMessage = CMS.getLogMessage("SELFTESTS_CA_IS_CORRUPT",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ }
+ } catch (CertificateParsingException e) {
+ // log that something is seriously wrong with the CA
+ mSelfTestSubsystem.log(logger,
+ e.toString());
+
+ throw new ESelfTestException(e.toString());
+ }
+
+ // log that the CA is present
+ logMessage = CMS.getLogMessage("SELFTESTS_CA_IS_PRESENT",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+ }
+
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/selftests/ca/CAValidity.java b/base/server/cms/src/com/netscape/cms/selftests/ca/CAValidity.java
new file mode 100644
index 000000000..b1751ecb4
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/selftests/ca/CAValidity.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cms.selftests.ca;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.util.Locale;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+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;
+
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * This class implements a self test to check the validity of the CA.
+ * <P>
+ *
+ * @author mharmsen
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class CAValidity
+ extends ASelfTest {
+ ////////////////////////
+ // default parameters //
+ ////////////////////////
+
+ ///////////////////////////
+ // CAValidity parameters //
+ ///////////////////////////
+
+ // parameter information
+ public static final String PROP_CA_SUB_ID = "CaSubId";
+ private String mCaSubId = null;
+
+ /////////////////////
+ // default methods //
+ /////////////////////
+
+ ////////////////////////
+ // CAValidity methods //
+ ////////////////////////
+
+ /**
+ * 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);
+
+ // retrieve mandatory parameter(s)
+ try {
+ mCaSubId = mConfig.getString(PROP_CA_SUB_ID);
+ if (mCaSubId != null) {
+ mCaSubId = mCaSubId.trim();
+ } else {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_MISSING_VALUES",
+ getSelfTestName(),
+ mPrefix
+ + "."
+ + PROP_CA_SUB_ID));
+
+ throw new EMissingSelfTestException(PROP_CA_SUB_ID);
+ }
+ } catch (EBaseException e) {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_MISSING_NAME",
+ getSelfTestName(),
+ mPrefix
+ + "."
+ + PROP_CA_SUB_ID));
+
+ throw new EMissingSelfTestException(mPrefix,
+ PROP_CA_SUB_ID,
+ null);
+ }
+
+ // retrieve optional parameter(s)
+
+ return;
+ }
+
+ /**
+ * Notifies this subsystem if it is in execution mode.
+ * <P>
+ *
+ * @exception ESelfTestException failed to start
+ */
+ public void startupSelfTest()
+ throws ESelfTestException {
+ return;
+ }
+
+ /**
+ * Stops this subsystem. The subsystem may call shutdownSelfTest
+ * anytime after initialization.
+ * <P>
+ */
+ public void shutdownSelfTest() {
+ return;
+ }
+
+ /**
+ * 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_CA_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;
+ ICertificateAuthority ca = null;
+ X509CertImpl caCert = null;
+
+ ca = (ICertificateAuthority) CMS.getSubsystem(mCaSubId);
+
+ if (ca == null) {
+ // log that the CA is not installed
+ logMessage = CMS.getLogMessage("SELFTESTS_CA_IS_NOT_PRESENT",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ } else {
+ // Retrieve the CA certificate
+ caCert = ca.getCACert();
+
+ if (caCert == null) {
+ // log that the CA is not yet initialized
+ logMessage = CMS.getLogMessage(
+ "SELFTESTS_CA_IS_NOT_INITIALIZED",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ }
+
+ // Retrieve the CA validity period
+ try {
+ caCert.checkValidity();
+ } catch (CertificateNotYetValidException e) {
+ // log that the CA is not yet valid
+ logMessage = CMS.getLogMessage("SELFTESTS_CA_IS_NOT_YET_VALID",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ } catch (CertificateExpiredException e) {
+ // log that the CA is expired
+ logMessage = CMS.getLogMessage("SELFTESTS_CA_IS_EXPIRED",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ }
+
+ // log that the CA is valid
+ logMessage = CMS.getLogMessage("SELFTESTS_CA_IS_VALID",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+ }
+
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/selftests/common/SystemCertsVerification.java b/base/server/cms/src/com/netscape/cms/selftests/common/SystemCertsVerification.java
new file mode 100644
index 000000000..f5b0939f1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/selftests/common/SystemCertsVerification.java
@@ -0,0 +1,213 @@
+// --- 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) 2010 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cms.selftests.common;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+import java.util.Locale;
+
+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;
+
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * This class implements a self test to check the system certs
+ * of the subsystem
+ * <P>
+ *
+ * @version $Revision: $, $Date: $
+ */
+public class SystemCertsVerification
+ extends ASelfTest {
+ ////////////////////////
+ // default parameters //
+ ////////////////////////
+
+ ///////////////////////////
+ // SystemCertsVerification parameters //
+ ///////////////////////////
+
+ // parameter information
+ public static final String PROP_SUB_ID = "SubId";
+ private String mSubId = null;
+
+ /////////////////////
+ // default methods //
+ /////////////////////
+
+ ////////////////////////
+ // SystemCertsVerification methods //
+ ////////////////////////
+
+ /**
+ * 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);
+
+ // retrieve mandatory parameter(s)
+ try {
+ mSubId = mConfig.getString(PROP_SUB_ID);
+ if (mSubId != null) {
+ mSubId = mSubId.trim();
+ } else {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_MISSING_VALUES",
+ getSelfTestName(),
+ mPrefix
+ + "."
+ + PROP_SUB_ID));
+
+ throw new EMissingSelfTestException(PROP_SUB_ID);
+ }
+ } catch (EBaseException e) {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_MISSING_NAME",
+ getSelfTestName(),
+ mPrefix
+ + "."
+ + PROP_SUB_ID));
+
+ throw new EMissingSelfTestException(mPrefix,
+ PROP_SUB_ID,
+ null);
+ }
+
+ // retrieve optional parameter(s)
+
+ return;
+ }
+
+ /**
+ * Notifies this subsystem if it is in execution mode.
+ * <P>
+ *
+ * @exception ESelfTestException failed to start
+ */
+ public void startupSelfTest()
+ throws ESelfTestException {
+ return;
+ }
+
+ /**
+ * Stops this subsystem. The subsystem may call shutdownSelfTest
+ * anytime after initialization.
+ * <P>
+ */
+ public void shutdownSelfTest() {
+ return;
+ }
+
+ /**
+ * 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_SYSTEM_CERTS_VERIFICATION_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;
+ boolean rc = false;
+
+ rc = CMS.verifySystemCerts();
+ if (rc == true) {
+ logMessage = CMS.getLogMessage("SELFTESTS_COMMON_SYSTEM_CERTS_VERIFICATION_SUCCESS",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+ } else {
+ logMessage = CMS.getLogMessage("SELFTESTS_COMMON_SYSTEM_CERTS_VERIFICATION_FAILURE",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+ throw new ESelfTestException(logMessage);
+ }
+
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/selftests/kra/KRAPresence.java b/base/server/cms/src/com/netscape/cms/selftests/kra/KRAPresence.java
new file mode 100644
index 000000000..832d2b747
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/selftests/kra/KRAPresence.java
@@ -0,0 +1,251 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cms.selftests.kra;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+import java.security.PublicKey;
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+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;
+
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * This class implements a self test to check for KRA presence.
+ * <P>
+ *
+ * @author mharmsen
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class KRAPresence
+ extends ASelfTest {
+ ////////////////////////
+ // default parameters //
+ ////////////////////////
+
+ ///////////////////////////
+ // KRAPresence parameters //
+ ///////////////////////////
+
+ // parameter information
+ public static final String PROP_KRA_SUB_ID = "SubId";
+ private String mSubId = null;
+
+ /////////////////////
+ // default methods //
+ /////////////////////
+
+ ////////////////////////
+ // KRAPresence methods //
+ ////////////////////////
+
+ /**
+ * 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);
+
+ // retrieve mandatory parameter(s)
+ try {
+ mSubId = mConfig.getString(PROP_KRA_SUB_ID);
+ if (mSubId != null) {
+ mSubId = mSubId.trim();
+ } else {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_MISSING_VALUES",
+ getSelfTestName(),
+ mPrefix
+ + "."
+ + PROP_KRA_SUB_ID));
+
+ throw new EMissingSelfTestException(PROP_KRA_SUB_ID);
+ }
+ } catch (EBaseException e) {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_MISSING_NAME",
+ getSelfTestName(),
+ mPrefix
+ + "."
+ + PROP_KRA_SUB_ID));
+
+ throw new EMissingSelfTestException(mPrefix,
+ PROP_KRA_SUB_ID,
+ null);
+ }
+
+ // retrieve optional parameter(s)
+
+ return;
+ }
+
+ /**
+ * Notifies this subsystem if it is in execution mode.
+ * <P>
+ *
+ * @exception ESelfTestException failed to start
+ */
+ public void startupSelfTest()
+ throws ESelfTestException {
+ return;
+ }
+
+ /**
+ * Stops this subsystem. The subsystem may call shutdownSelfTest
+ * anytime after initialization.
+ * <P>
+ */
+ public void shutdownSelfTest() {
+ return;
+ }
+
+ /**
+ * 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_KRA_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;
+ IKeyRecoveryAuthority kra = null;
+ org.mozilla.jss.crypto.X509Certificate kraCert = null;
+ PublicKey kraPubKey = null;
+
+ kra = (IKeyRecoveryAuthority) CMS.getSubsystem(mSubId);
+
+ if (kra == null) {
+ // log that the KRA is not installed
+ logMessage = CMS.getLogMessage("SELFTESTS_KRA_IS_NOT_PRESENT",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ } else {
+ // Retrieve the KRA certificate
+ kraCert = kra.getTransportCert();
+
+ if (kraCert == null) {
+ // log that the RA is not yet initialized
+ logMessage = CMS.getLogMessage(
+ "SELFTESTS_KRA_IS_NOT_INITIALIZED",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ }
+
+ // Retrieve the KRA certificate public key
+ kraPubKey = kraCert.getPublicKey();
+
+ if (kraPubKey == null) {
+ // log that something is seriously wrong with the KRA
+ logMessage = CMS.getLogMessage("SELFTESTS_KRA_IS_CORRUPT",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ }
+
+ // log that the KRA is present
+ logMessage = CMS.getLogMessage("SELFTESTS_KRA_IS_PRESENT",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+ }
+
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPPresence.java b/base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPPresence.java
new file mode 100644
index 000000000..a3d9e3ad3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPPresence.java
@@ -0,0 +1,280 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cms.selftests.ocsp;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+import java.security.cert.CertificateParsingException;
+import java.util.Locale;
+
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509Key;
+
+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.ocsp.IOCSPAuthority;
+import com.netscape.certsrv.security.ISigningUnit;
+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;
+
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * This class implements a self test to check for OCSP presence.
+ * <P>
+ *
+ * @author mharmsen
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class OCSPPresence
+ extends ASelfTest {
+ ////////////////////////
+ // default parameters //
+ ////////////////////////
+
+ /////////////////////////////
+ // OCSPPresence parameters //
+ /////////////////////////////
+
+ // parameter information
+ public static final String PROP_OCSP_SUB_ID = "OcspSubId";
+ private String mOcspSubId = null;
+
+ /////////////////////
+ // default methods //
+ /////////////////////
+
+ //////////////////////////
+ // OCSPPresence methods //
+ //////////////////////////
+
+ /**
+ * 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);
+
+ // retrieve mandatory parameter(s)
+ try {
+ mOcspSubId = mConfig.getString(PROP_OCSP_SUB_ID);
+ if (mOcspSubId != null) {
+ mOcspSubId = mOcspSubId.trim();
+ } else {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_MISSING_VALUES",
+ getSelfTestName(),
+ mPrefix
+ + "."
+ + PROP_OCSP_SUB_ID));
+
+ throw new EMissingSelfTestException(PROP_OCSP_SUB_ID);
+ }
+ } catch (EBaseException e) {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_MISSING_NAME",
+ getSelfTestName(),
+ mPrefix
+ + "."
+ + PROP_OCSP_SUB_ID));
+
+ throw new EMissingSelfTestException(mPrefix,
+ PROP_OCSP_SUB_ID,
+ null);
+ }
+
+ // retrieve optional parameter(s)
+
+ return;
+ }
+
+ /**
+ * Notifies this subsystem if it is in execution mode.
+ * <P>
+ *
+ * @exception ESelfTestException failed to start
+ */
+ public void startupSelfTest()
+ throws ESelfTestException {
+ return;
+ }
+
+ /**
+ * Stops this subsystem. The subsystem may call shutdownSelfTest
+ * anytime after initialization.
+ * <P>
+ */
+ public void shutdownSelfTest() {
+ return;
+ }
+
+ /**
+ * 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_OCSP_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;
+ IOCSPAuthority ocsp = null;
+ ISigningUnit ocspSigningUnit = null;
+ X509CertImpl ocspCert = null;
+ X509Key ocspPubKey = null;
+
+ ocsp = (IOCSPAuthority) CMS.getSubsystem(mOcspSubId);
+
+ if (ocsp == null) {
+ // log that the OCSP is not installed
+ logMessage = CMS.getLogMessage("SELFTESTS_OCSP_IS_NOT_PRESENT",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ } else {
+ // Retrieve the OCSP signing unit
+ ocspSigningUnit = ocsp.getSigningUnit();
+
+ if (ocspSigningUnit == null) {
+ // log that the OCSP is not yet initialized
+ logMessage = CMS.getLogMessage(
+ "SELFTESTS_OCSP_IS_NOT_INITIALIZED",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ }
+
+ // Retrieve the OCSP certificate
+ ocspCert = ocspSigningUnit.getCertImpl();
+
+ if (ocspCert == null) {
+ // log that the OCSP is not yet initialized
+ logMessage = CMS.getLogMessage(
+ "SELFTESTS_OCSP_IS_NOT_INITIALIZED",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ }
+
+ // Retrieve the OCSP certificate public key
+ try {
+ ocspPubKey = (X509Key)
+ ocspCert.get(X509CertImpl.PUBLIC_KEY);
+
+ if (ocspPubKey == null) {
+ // log that something is seriously wrong with the OCSP
+ logMessage = CMS.getLogMessage("SELFTESTS_OCSP_IS_CORRUPT",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ }
+ } catch (CertificateParsingException e) {
+ // log that something is seriously wrong with the OCSP
+ mSelfTestSubsystem.log(logger,
+ e.toString());
+
+ throw new ESelfTestException(e.toString());
+ }
+
+ // log that the OCSP is present
+ logMessage = CMS.getLogMessage("SELFTESTS_OCSP_IS_PRESENT",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+ }
+
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPValidity.java b/base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPValidity.java
new file mode 100644
index 000000000..383779d22
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/selftests/ocsp/OCSPValidity.java
@@ -0,0 +1,280 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cms.selftests.ocsp;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.util.Locale;
+
+import netscape.security.x509.X509CertImpl;
+
+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.ocsp.IOCSPAuthority;
+import com.netscape.certsrv.security.ISigningUnit;
+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;
+
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * This class implements a self test to check the validity of the OCSP.
+ * <P>
+ *
+ * @author mharmsen
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class OCSPValidity
+ extends ASelfTest {
+ ////////////////////////
+ // default parameters //
+ ////////////////////////
+
+ /////////////////////////////
+ // OCSPValidity parameters //
+ /////////////////////////////
+
+ // parameter information
+ public static final String PROP_OCSP_SUB_ID = "OcspSubId";
+ private String mOcspSubId = null;
+
+ /////////////////////
+ // default methods //
+ /////////////////////
+
+ //////////////////////////
+ // OCSPValidity methods //
+ //////////////////////////
+
+ /**
+ * 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);
+
+ // retrieve mandatory parameter(s)
+ try {
+ mOcspSubId = mConfig.getString(PROP_OCSP_SUB_ID);
+ if (mOcspSubId != null) {
+ mOcspSubId = mOcspSubId.trim();
+ } else {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_MISSING_VALUES",
+ getSelfTestName(),
+ mPrefix
+ + "."
+ + PROP_OCSP_SUB_ID));
+
+ throw new EMissingSelfTestException(PROP_OCSP_SUB_ID);
+ }
+ } catch (EBaseException e) {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_MISSING_NAME",
+ getSelfTestName(),
+ mPrefix
+ + "."
+ + PROP_OCSP_SUB_ID));
+
+ throw new EMissingSelfTestException(mPrefix,
+ PROP_OCSP_SUB_ID,
+ null);
+ }
+
+ // retrieve optional parameter(s)
+
+ return;
+ }
+
+ /**
+ * Notifies this subsystem if it is in execution mode.
+ * <P>
+ *
+ * @exception ESelfTestException failed to start
+ */
+ public void startupSelfTest()
+ throws ESelfTestException {
+ return;
+ }
+
+ /**
+ * Stops this subsystem. The subsystem may call shutdownSelfTest
+ * anytime after initialization.
+ * <P>
+ */
+ public void shutdownSelfTest() {
+ return;
+ }
+
+ /**
+ * 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_OCSP_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;
+ IOCSPAuthority ocsp = null;
+ ISigningUnit ocspSigningUnit = null;
+ X509CertImpl ocspCert = null;
+
+ ocsp = (IOCSPAuthority) CMS.getSubsystem(mOcspSubId);
+
+ if (ocsp == null) {
+ // log that the OCSP is not installed
+ logMessage = CMS.getLogMessage("SELFTESTS_OCSP_IS_NOT_PRESENT",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ } else {
+ // Retrieve the OCSP signing unit
+ ocspSigningUnit = ocsp.getSigningUnit();
+
+ if (ocspSigningUnit == null) {
+ // log that the OCSP is not yet initialized
+ logMessage = CMS.getLogMessage(
+ "SELFTESTS_OCSP_IS_NOT_INITIALIZED",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ }
+
+ // Retrieve the OCSP certificate
+ ocspCert = ocspSigningUnit.getCertImpl();
+
+ if (ocspCert == null) {
+ // log that the OCSP is not yet initialized
+ logMessage = CMS.getLogMessage(
+ "SELFTESTS_OCSP_IS_NOT_INITIALIZED",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ }
+
+ // Retrieve the OCSP validity period
+ try {
+ ocspCert.checkValidity();
+ } catch (CertificateNotYetValidException e) {
+ // log that the OCSP is not yet valid
+ logMessage = CMS.getLogMessage(
+ "SELFTESTS_OCSP_IS_NOT_YET_VALID",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ } catch (CertificateExpiredException e) {
+ // log that the OCSP is expired
+ logMessage = CMS.getLogMessage("SELFTESTS_OCSP_IS_EXPIRED",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ }
+
+ // log that the OCSP is valid
+ logMessage = CMS.getLogMessage("SELFTESTS_OCSP_IS_VALID",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+ }
+
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/selftests/ra/RAPresence.java b/base/server/cms/src/com/netscape/cms/selftests/ra/RAPresence.java
new file mode 100644
index 000000000..6facd807c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/selftests/ra/RAPresence.java
@@ -0,0 +1,261 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cms.selftests.ra;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+import java.security.PublicKey;
+import java.util.Locale;
+
+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.ra.IRegistrationAuthority;
+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;
+
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * This class implements a self test to check for RA presence.
+ * <P>
+ *
+ * <PRE>
+ * NOTE: This self-test is for Registration Authorities prior to
+ * Netscape Certificate Management System 7.0. It does NOT
+ * apply to the Registration Authority found in
+ * Red Hat Certificate System 7.3 or later (including
+ * ALL versions of Dogtag Certificate System).
+ * </PRE>
+ * <P>
+ *
+ * @deprecated
+ * @author mharmsen
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class RAPresence
+ extends ASelfTest {
+ ////////////////////////
+ // default parameters //
+ ////////////////////////
+
+ ///////////////////////////
+ // RAPresence parameters //
+ ///////////////////////////
+
+ // parameter information
+ public static final String PROP_RA_SUB_ID = "RaSubId";
+ private String mRaSubId = null;
+
+ /////////////////////
+ // default methods //
+ /////////////////////
+
+ ////////////////////////
+ // RAPresence methods //
+ ////////////////////////
+
+ /**
+ * 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);
+
+ // retrieve mandatory parameter(s)
+ try {
+ mRaSubId = mConfig.getString(PROP_RA_SUB_ID);
+ if (mRaSubId != null) {
+ mRaSubId = mRaSubId.trim();
+ } else {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_MISSING_VALUES",
+ getSelfTestName(),
+ mPrefix
+ + "."
+ + PROP_RA_SUB_ID));
+
+ throw new EMissingSelfTestException(PROP_RA_SUB_ID);
+ }
+ } catch (EBaseException e) {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage(
+ "SELFTESTS_MISSING_NAME",
+ getSelfTestName(),
+ mPrefix
+ + "."
+ + PROP_RA_SUB_ID));
+
+ throw new EMissingSelfTestException(mPrefix,
+ PROP_RA_SUB_ID,
+ null);
+ }
+
+ // retrieve optional parameter(s)
+
+ return;
+ }
+
+ /**
+ * Notifies this subsystem if it is in execution mode.
+ * <P>
+ *
+ * @exception ESelfTestException failed to start
+ */
+ public void startupSelfTest()
+ throws ESelfTestException {
+ return;
+ }
+
+ /**
+ * Stops this subsystem. The subsystem may call shutdownSelfTest
+ * anytime after initialization.
+ * <P>
+ */
+ public void shutdownSelfTest() {
+ return;
+ }
+
+ /**
+ * 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_RA_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;
+ IRegistrationAuthority ra = null;
+ org.mozilla.jss.crypto.X509Certificate raCert = null;
+ PublicKey raPubKey = null;
+
+ ra = (IRegistrationAuthority) CMS.getSubsystem(mRaSubId);
+
+ if (ra == null) {
+ // log that the RA is not installed
+ logMessage = CMS.getLogMessage("SELFTESTS_RA_IS_NOT_PRESENT",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ } else {
+ // Retrieve the RA certificate
+ raCert = ra.getRACert();
+
+ if (raCert == null) {
+ // log that the RA is not yet initialized
+ logMessage = CMS.getLogMessage(
+ "SELFTESTS_RA_IS_NOT_INITIALIZED",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ }
+
+ // Retrieve the RA certificate public key
+ raPubKey = raCert.getPublicKey();
+
+ if (raPubKey == null) {
+ // log that something is seriously wrong with the RA
+ logMessage = CMS.getLogMessage("SELFTESTS_RA_IS_CORRUPT",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+
+ throw new ESelfTestException(logMessage);
+ }
+
+ // log that the RA is present
+ logMessage = CMS.getLogMessage("SELFTESTS_RA_IS_PRESENT",
+ getSelfTestName());
+
+ mSelfTestSubsystem.log(logger,
+ logMessage);
+ }
+
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/selftests/tks/TKSKnownSessionKey.java b/base/server/cms/src/com/netscape/cms/selftests/tks/TKSKnownSessionKey.java
new file mode 100644
index 000000000..06a6398c5
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/selftests/tks/TKSKnownSessionKey.java
@@ -0,0 +1,334 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cms.selftests.tks;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+import java.util.Arrays;
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+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;
+import com.netscape.symkey.SessionKey;
+
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * This class implements a self test to check for TKS known session key.
+ * <P>
+ *
+ * @author mharmsen
+ * @author thomask
+ * @author awnuk
+ * @version $Revision$, $Date$
+ */
+public class TKSKnownSessionKey
+ extends ASelfTest {
+ // parameter information
+ public static final String PROP_TKS_SUB_ID = "TksSubId";
+ private String mTksSubId = null;
+ private String mToken = null;
+ private String mUseSoftToken = null;
+ private String mKeyName = null;
+ private byte[] mKeyInfo = null;
+ private byte[] mCardChallenge = null;
+ private byte[] mHostChallenge = null;
+ private byte[] mCUID = null;
+ private byte[] mMacKey = null;
+ private byte[] mSessionKey = 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 {
+ ISubsystem tks = null;
+ IConfigStore tksConfig = null;
+
+ super.initSelfTest(subsystem, instanceName, parameters);
+
+ mTksSubId = getConfigString(PROP_TKS_SUB_ID);
+ mToken = getConfigString("token");
+ mKeyName = getConfigString("keyName");
+ mCardChallenge = getConfigByteArray("cardChallenge", 8);
+ mHostChallenge = getConfigByteArray("hostChallenge", 8);
+ mKeyInfo = getConfigByteArray("keyName", 2);
+ mCUID = getConfigByteArray("CUID", 10);
+ mMacKey = getConfigByteArray("macKey", 16);
+ mUseSoftToken = getConfigString("useSoftToken");
+
+ String defKeySetMacKey = null;
+ tks = CMS.getSubsystem(mTksSubId);
+ if (tks != null) {
+ tksConfig = tks.getConfigStore();
+ if (tksConfig != null) {
+ try {
+ defKeySetMacKey = tksConfig.getString("defKeySet.mac_key");
+ byte defMacKey[] = com.netscape.cmsutil.util.Utils.SpecialDecode(defKeySetMacKey);
+ if (!Arrays.equals(mMacKey, defMacKey)) {
+ defKeySetMacKey = null;
+ }
+ } catch (EBaseException e) {
+ defKeySetMacKey = null;
+ }
+ }
+ }
+ if (defKeySetMacKey == null) {
+ CMS.debug("TKSKnownSessionKey: invalid mac key");
+ CMS.debug("TKSKnownSessionKey self test FAILED");
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage("SELFTESTS_INVALID_VALUES",
+ getSelfTestName(), mPrefix + "." + "macKey"));
+ throw new EInvalidSelfTestException(mPrefix, "macKey", null);
+ }
+
+ try {
+ mSessionKey = getConfigByteArray("sessionKey", 16);
+ } catch (EMissingSelfTestException e) {
+ if (mSessionKey == null) {
+ mSessionKey = SessionKey.ComputeSessionKey(mToken, mKeyName,
+ mCardChallenge, mHostChallenge,
+ mKeyInfo, mCUID, mMacKey, mUseSoftToken, null, null);
+ if (mSessionKey == null || mSessionKey.length != 16) {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage("SELFTESTS_MISSING_VALUES",
+ getSelfTestName(), mPrefix + ".sessionKey"));
+ throw new EMissingSelfTestException("sessionKey");
+ }
+ String sessionKey = SpecialEncode(mSessionKey);
+ mConfig.putString("sessionKey", sessionKey);
+ try {
+ CMS.getConfigStore().commit(true);
+ } catch (EBaseException be) {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage("SELFTESTS_MISSING_VALUES",
+ getSelfTestName(), mPrefix + ".sessionKey"));
+ throw new EMissingSelfTestException("sessionKey");
+ }
+ }
+ }
+
+ return;
+ }
+
+ private String SpecialEncode(byte data[]) {
+ StringBuffer sb = new StringBuffer();
+
+ for (int i = 0; i < data.length; i++) {
+ sb.append("#");
+ if ((data[i] & 0xff) < 16) {
+ sb.append("0");
+ }
+ sb.append(Integer.toHexString((data[i] & 0xff)));
+ }
+
+ return sb.toString();
+ }
+
+ private String getConfigString(String name) throws EMissingSelfTestException {
+ String value = null;
+
+ try {
+ value = mConfig.getString(name);
+ if (value != null) {
+ value = value.trim();
+ } else {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage("SELFTESTS_MISSING_VALUES",
+ getSelfTestName(), mPrefix + "." + name));
+ throw new EMissingSelfTestException(name);
+ }
+ } catch (EBaseException e) {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage("SELFTESTS_MISSING_NAME",
+ getSelfTestName(), mPrefix + "." + name));
+ throw new EMissingSelfTestException(mPrefix, name, null);
+ }
+
+ return value;
+ }
+
+ private byte[] getConfigByteArray(String name, int size) throws EMissingSelfTestException,
+ EInvalidSelfTestException {
+ String stringValue = getConfigString(name);
+
+ byte byteValue[] = com.netscape.cmsutil.util.Utils.SpecialDecode(stringValue);
+ if (byteValue == null) {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage("SELFTESTS_MISSING_NAME",
+ getSelfTestName(), mPrefix + "." + name));
+ throw new EMissingSelfTestException(name);
+ }
+ if (byteValue.length != size) {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage("SELFTESTS_INVALID_VALUES",
+ getSelfTestName(), mPrefix + "." + name));
+ throw new EInvalidSelfTestException(mPrefix, name, stringValue);
+ }
+
+ return byteValue;
+ }
+
+ /**
+ * Notifies this subsystem if it is in execution mode.
+ * <P>
+ *
+ * @exception ESelfTestException failed to start
+ */
+ public void startupSelfTest()
+ throws ESelfTestException {
+ return;
+ }
+
+ /**
+ * Stops this subsystem. The subsystem may call shutdownSelfTest
+ * anytime after initialization.
+ * <P>
+ */
+ public void shutdownSelfTest() {
+ return;
+ }
+
+ /**
+ * 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_TKS_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 {
+ IConfigStore cs = CMS.getConfigStore();
+ String sharedSecretName;
+ try {
+ boolean useNewNames = cs.getBoolean("tks.useNewSharedSecretNames", false);
+ if (useNewNames) {
+ String tpsList = cs.getString("tps.list", "");
+ if (tpsList.isEmpty()) {
+ CMS.debug("TKSKnownSessionKey: no shared secrets configured, exiting");
+ return;
+ }
+
+ for (String tpsID : tpsList.split(",")) {
+ sharedSecretName = cs.getString("tps." + tpsID + ".nickname", "");
+ if (!sharedSecretName.isEmpty()) {
+ CMS.debug("TKSKnownSessionKey: testing with key " + sharedSecretName);
+ generateSessionKey(logger, sharedSecretName);
+ }
+ }
+ } else {
+ // legacy systems
+ sharedSecretName = cs.getString("tks.tksSharedSymKeyName", "sharedSecret");
+ generateSessionKey(logger, sharedSecretName);
+ }
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ CMS.debug("TKSKnownSessionKey: failed to read config file to set up test");
+ String logMessage = CMS.getLogMessage("SELFTESTS_TKS_FAILED", getSelfTestName(), getSelfTestName());
+ mSelfTestSubsystem.log(logger, logMessage);
+ throw new ESelfTestException(logMessage);
+ }
+ return;
+ }
+
+ private void generateSessionKey(ILogEventListener logger, String sharedSecretName) throws ESelfTestException {
+ String logMessage;
+ String keySet = "defKeySet";
+
+ byte[] sessionKey = SessionKey.ComputeSessionKey(
+ mToken, mKeyName, mCardChallenge, mHostChallenge, mKeyInfo,
+ mCUID, mMacKey, mUseSoftToken, keySet, sharedSecretName);
+
+ // Now we just see if we can successfully generate a session key.
+ // For FIPS compliance, the routine now returns a wrapped key, which can't be extracted and compared.
+ if (sessionKey == null) {
+ CMS.debug("TKSKnownSessionKey: generated no session key");
+ CMS.debug("TKSKnownSessionKey self test FAILED");
+ logMessage = CMS.getLogMessage("SELFTESTS_TKS_FAILED", getSelfTestName(), getSelfTestName());
+ mSelfTestSubsystem.log(logger, logMessage);
+ throw new ESelfTestException(logMessage);
+ } else {
+ logMessage = CMS.getLogMessage("SELFTESTS_TKS_SUCCEEDED", getSelfTestName(), getSelfTestName());
+ mSelfTestSubsystem.log(logger, logMessage);
+ CMS.debug("TKSKnownSessionKey self test SUCCEEDED");
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/account/AccountService.java b/base/server/cms/src/com/netscape/cms/servlet/account/AccountService.java
new file mode 100644
index 000000000..611c865ae
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/account/AccountService.java
@@ -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.
+//
+// (C) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.account;
+
+import java.security.Principal;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.UriInfo;
+
+import com.netscape.certsrv.account.AccountResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class AccountService extends PKIService implements AccountResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ @Override
+ public void login() {
+ HttpSession session = servletRequest.getSession();
+ System.out.println("Creating session "+session.getId());
+
+ Principal principal = servletRequest.getUserPrincipal();
+ System.out.println("Principal: "+principal);
+ }
+
+ @Override
+ public void logout() {
+ HttpSession session = servletRequest.getSession(false);
+ if (session == null) return;
+
+ System.out.println("Destroying session "+session.getId());
+ session.invalidate();
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/ACLAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/ACLAdminServlet.java
new file mode 100644
index 000000000..1244da12c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/ACLAdminServlet.java
@@ -0,0 +1,894 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.acls.ACL;
+import com.netscape.certsrv.acls.ACLEntry;
+import com.netscape.certsrv.acls.IACL;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authorization.IAuthzManager;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.evaluators.IAccessEvaluator;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * Manage Access Control List configuration
+ *
+ * @version $Revision$, $Date$
+ */
+public class ACLAdminServlet extends AdminServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -322237202045924779L;
+ private static final String PROP_EVAL = "accessEvaluator";
+ private final static String INFO = "ACLAdminServlet";
+ private IAuthzManager mAuthzMgr = null;
+
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_ACL =
+ "LOGGING_SIGNED_AUDIT_CONFIG_ACL_3";
+
+ /**
+ * initialize the servlet.
+ * <ul>
+ * <li>http.param OP_TYPE = OP_SEARCH,
+ * <li>http.param OP_SCOPE - the scope of the request operation:
+ * <ul>
+ * <LI>"impl" ACL implementations
+ * <LI>"acls" ACL rules
+ * <LI>"evaluatorTypes" ACL evaluators.
+ * </ul>
+ * </ul>
+ *
+ * @param config servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ mAuthzMgr = mAuthz.get(mAclMethod);
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param req the object holding the request information
+ * @param resp the object holding the response information
+ */
+
+ public void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ String scope = super.getParameter(req, Constants.OP_SCOPE);
+ String op = super.getParameter(req, Constants.OP_TYPE);
+
+ if (op == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_INVALID_PROTOCOL"));
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"),
+ null, resp);
+ return;
+ }
+
+ try {
+ super.authenticate(req);
+ } catch (IOException e) {
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("ADMIN_SRVLT_FAIL_AUTHS"));
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHS_FAILED"),
+ null, resp);
+ return;
+ }
+
+ try {
+ AUTHZ_RES_NAME = "certServer.acl.configuration";
+
+ if (op.equals(OpDef.OP_SEARCH)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_ACL)) {
+ listResources(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_ACL_IMPLS)) {
+ listACLsEvaluators(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_EVALUATOR_TYPES)) {
+ listACLsEvaluatorTypes(req, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_READ)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_ACL)) {
+ getResourceACL(req, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_ACL)) {
+ updateResources(req, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_ADD)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_ACL_IMPLS)) {
+ addACLsEvaluator(req, resp, scope);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_ACL_IMPLS)) {
+ deleteACLsEvaluator(req, resp, scope);
+ return;
+ }
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_INVALID_OP_SCOPE"));
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ sendResponse(ERROR, e.toString(getLocale(req)),
+ null, resp);
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ log(ILogger.LL_DEBUG, "SRVLT_FAIL_PERFORM 2");
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_PERFORM_FAILED"),
+ null, resp);
+ return;
+ }
+
+ log(ILogger.LL_DEBUG, "SRVLT_FAIL_PERFORM 3");
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_PERFORM_FAILED"),
+ null, resp);
+ return;
+ }
+
+ /**
+ * list acls resources by name
+ */
+ private void listResources(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException, IOException,
+ EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+
+ Enumeration<ACL> res = mAuthzMgr.getACLs();
+
+ while (res.hasMoreElements()) {
+ ACL acl = res.nextElement();
+ String desc = acl.getDescription();
+
+ if (desc == null)
+ params.put(acl.getName(), "");
+ else
+ params.put(acl.getName(), desc);
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * get acls information for a resource
+ */
+ private void getResourceACL(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException, IOException,
+ EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ //get resource id first
+ String resourceId = super.getParameter(req, Constants.RS_ID);
+
+ if (resourceId == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ IACL acl = mAuthzMgr.getACL(resourceId);
+
+ if (acl != null) {
+ Enumeration<String> rightsEnum = acl.rights();
+
+ StringBuffer rights = new StringBuffer();
+
+ if (rightsEnum.hasMoreElements()) {
+ while (rightsEnum.hasMoreElements()) {
+ if (rights.length() != 0) {
+ rights.append(",");
+ }
+ String right = rightsEnum.nextElement();
+
+ rights.append(right);
+ }
+ }
+
+ params.put(Constants.PR_ACL_OPS, rights.toString());
+
+ Enumeration<ACLEntry> aclEntryEnum;
+ aclEntryEnum = acl.entries();
+ String acis = "";
+
+ if (aclEntryEnum.hasMoreElements()) {
+ while (aclEntryEnum.hasMoreElements()) {
+ if (acis != "") {
+ acis += ";";
+ }
+ ACLEntry aclEntry = aclEntryEnum.nextElement();
+ String aci = aclEntry.getACLEntryString();
+
+ acis += aci;
+ }
+ }
+
+ params.put(Constants.PR_ACI, acis);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ACLS_SRVLT_RESOURCE_NOT_FOUND"));
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ACL_RESOURCE_NOT_FOUND"),
+ null, resp);
+ return;
+ }
+ }
+
+ /**
+ * modify acls information for a resource
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ACL used when configuring Access Control List (ACL) information
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private void updateResources(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException, IOException,
+ EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ // get resource id first
+ String resourceId = super.getParameter(req, Constants.RS_ID);
+
+ if (resourceId == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // get resource acls
+ String resourceACLs = super.getParameter(req, Constants.PR_ACI);
+ String rights = super.getParameter(req, Constants.PR_ACL_RIGHTS);
+ String desc = super.getParameter(req, Constants.PR_ACL_DESC);
+
+ try {
+ mAuthzMgr.updateACLs(resourceId, rights, resourceACLs, desc);
+
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ACL_UPDATE_FAIL"),
+ null, resp);
+ return;
+ }
+ // } catch( EBaseException eAudit1 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * list access evaluators by types and class paths
+ */
+ private void listACLsEvaluators(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException, IOException,
+ EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<IAccessEvaluator> res = mAuthzMgr.aclEvaluatorElements();
+
+ while (res.hasMoreElements()) {
+ IAccessEvaluator evaluator = res.nextElement();
+
+ // params.add(evaluator.getType(), evaluator.getDescription());
+ params.put(evaluator.getType(), evaluator.getClass().getName());
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void listACLsEvaluatorTypes(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException, IOException,
+ EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<IAccessEvaluator> res = mAuthzMgr.aclEvaluatorElements();
+
+ while (res.hasMoreElements()) {
+ IAccessEvaluator evaluator = res.nextElement();
+ String[] operators = evaluator.getSupportedOperators();
+ StringBuffer str = new StringBuffer();
+
+ for (int i = 0; i < operators.length; i++) {
+ if (str.length() > 0)
+ str.append(",");
+ str.append(operators[i]);
+ }
+
+ params.put(evaluator.getType(), str.toString());
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * add access evaluators
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ACL used when configuring Access Control List (ACL) information
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param scope string used to obtain the contents of this ACL evaluator's
+ * substore
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void addACLsEvaluator(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ // get evaluator type first
+ String type = super.getParameter(req, Constants.RS_ID);
+
+ if (type == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // is the evaluator type unique?
+ /*
+ if (!mACLs.isTypeUnique(type)) {
+ String infoMsg = "replacing existing type: "+ type;
+ log(ILogger.LL_WARN, infoMsg);
+ }
+ */
+
+ // get class
+ String classPath = super.getParameter(req, Constants.PR_ACL_CLASS);
+
+ IConfigStore destStore =
+ mConfig.getSubStore(PROP_EVAL);
+ IConfigStore mStore =
+ destStore.getSubStore(ScopeDef.SC_ACL_IMPLS);
+
+ // Does the class exist?
+ Class<?> newImpl = null;
+
+ try {
+ newImpl = Class.forName(classPath);
+ } catch (ClassNotFoundException e) {
+ String errMsg = "class " + classPath + " not found";
+
+ log(ILogger.LL_FAILURE, errMsg);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ACL_CLASS_LOAD_FAIL"),
+ null, resp);
+ return;
+ }
+
+ // is the class an IAccessEvaluator?
+ try {
+ if (Class.forName("com.netscape.certsrv.evaluators.IAccessEvaluator").isAssignableFrom(newImpl) == false) {
+ String errMsg = "class not com.netscape.certsrv.evaluators.IAccessEvaluator" +
+ classPath;
+
+ log(ILogger.LL_FAILURE, errMsg);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ACL_ILL_CLASS"),
+ null, resp);
+ return;
+ }
+ } catch (Exception e) {
+ String errMsg = "class not com.netscape.certsrv.evaluators.IAccessEvaluator" +
+ classPath;
+
+ log(ILogger.LL_FAILURE, errMsg);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ACL_ILL_CLASS"),
+ null, resp);
+ return;
+ }
+
+ IConfigStore substore = mStore.makeSubStore(type);
+
+ substore.put(Constants.PR_ACL_CLASS, classPath);
+
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ACLS_SRVLT_FAIL_COMMIT"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ACL_COMMIT_FAIL"),
+ null, resp);
+ return;
+ }
+
+ // Instantiate an object for this implementation
+ IAccessEvaluator evaluator = null;
+
+ try {
+ evaluator = (IAccessEvaluator) Class.forName(classPath).newInstance();
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ACL_INST_CLASS_FAIL"),
+ null, resp);
+ return;
+ }
+
+ // initialize the access evaluator
+ if (evaluator != null) {
+ evaluator.init();
+ // add evaluator to list
+ mAuthzMgr.registerEvaluator(type, evaluator);
+ }
+
+ //...
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ // } catch( EBaseException eAudit1 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * remove access evaluators
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ACL used when configuring Access Control List (ACL) information
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param scope string used to obtain the contents of this ACL evaluator's
+ * substore
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void deleteACLsEvaluator(HttpServletRequest req,
+ HttpServletResponse resp, String scope) throws ServletException,
+ IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ NameValuePairs params = new NameValuePairs();
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // does the evaluator exist?
+ Hashtable<String, IAccessEvaluator> mEvaluators = mAuthzMgr.getAccessEvaluators();
+
+ if (mEvaluators.containsKey(id) == false) {
+ log(ILogger.LL_FAILURE, "evaluator attempted to be removed not found");
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ACL_EVAL_NOT_FOUND"),
+ null, resp);
+ return;
+ }
+
+ // it's possibl that it's being used...we have to assume that
+ // the administrator knows what she is doing, for now
+ mEvaluators.remove(id);
+
+ try {
+ IConfigStore destStore =
+ mConfig.getSubStore(PROP_EVAL);
+ IConfigStore mStore =
+ destStore.getSubStore(ScopeDef.SC_ACL_IMPLS);
+
+ mStore.removeSubStore(id);
+ } catch (Exception eeee) {
+ //CMS.debugStackTrace(eeee);
+ }
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ACLS_SRVLT_FAIL_COMMIT"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ACL_COMMIT_FAIL"),
+ null, resp);
+ return;
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ // } catch( EBaseException eAudit1 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ACL,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * Searchs for certificate requests.
+ */
+
+ /*
+ private void getACLs(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException, IOException,
+ EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos);
+ String names = getParameter(req, Constants.PT_NAMES);
+ StringTokenizer st = new StringTokenizer(names, ",");
+ while (st.hasMoreTokens()) {
+ String target = st.nextToken();
+ ACL acl = AccessManager.getInstance().getACL(target);
+ oos.writeObject(acl);
+ }
+ // BASE64Encoder encoder = new BASE64Encoder();
+ // params.add(Constants.PT_ACLS, encoder.encodeBuffer(bos.toByteArray()));
+ params.add(Constants.PT_ACLS, CMS.BtoA(bos.toByteArray()));
+ sendResponse(SUCCESS, null, params, resp);
+ }
+ */
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_ACLS,
+ level, "ACLAdminServlet: " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/AdminResources.java b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminResources.java
new file mode 100644
index 000000000..19b537854
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminResources.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.util.ListResourceBundle;
+
+/**
+ * A class represents a resource bundle for the remote admin.
+ *
+ * @version $Revision$, $Date$
+ * @see java.util.ListResourceBundle
+ */
+public class AdminResources extends ListResourceBundle {
+
+ /**
+ * Returns the content of this resource.
+ */
+ public Object[][] getContents() {
+ return contents;
+ }
+
+ /**
+ * Constants. The suffix represents the number of
+ * possible parameters.
+ */
+ static final Object[][] contents = {};
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
new file mode 100644
index 000000000..ab7af9ec3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
@@ -0,0 +1,1142 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.authorization.IAuthzSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.IAuditor;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.usrgrp.EUsrGrpException;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * A class represents an administration servlet that
+ * is responsible to serve administrative
+ * operation such as configuration parameter updates.
+ *
+ * Since each administration servlet needs to perform
+ * authentication information parsing and response
+ * formulation, it makes sense to encapsulate the
+ * commonalities into this class.
+ *
+ * By extending this serlvet, the subclass does not
+ * need to re-implement the request parsing code
+ * (i.e. authentication information parsing).
+ *
+ * If a subsystem needs to expose configuration
+ * parameters management, it should create an
+ * administration servlet (i.e. CAAdminServlet)
+ * and register it to RemoteAdmin subsystem.
+ *
+ * <code>
+ * public class CAAdminServlet extends AdminServlet {
+ * ...
+ * }
+ * </code>
+ *
+ * @version $Revision$, $Date$
+ */
+public class AdminServlet extends HttpServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7740464244137421542L;
+ private final static String HDR_AUTHORIZATION = "Authorization";
+ private final static String HDR_LANG = "accept-language";
+
+ protected ILogger mLogger = CMS.getLogger();
+ protected IAuditor auditor = CMS.getAuditor();
+ private IUGSubsystem mUG = null;
+ protected IConfigStore mConfig = null;
+ protected IAuthzSubsystem mAuthz = null;
+
+ // we don't allow to switch authz db mid-way, for now
+ protected String mAclMethod = null;
+ protected String mOp = "";
+ protected static String AUTHZ_RES_NAME = "certServer";
+ protected AuthzToken mToken;
+
+ private String mServletID = null;
+ public final static String PROP_AUTHZ_MGR = "AuthzMgr";
+ public final static String PROP_ACL = "ACLinfo";
+
+ public final static String AUTHZ_MGR_BASIC = "BasicAclAuthz";
+ public final static String AUTHZ_MGR_LDAP = "DirAclAuthz";
+ public final static String PROP_ID = "ID";
+ public final static String AUTHZ_CONFIG_STORE = "authz";
+ public final static String AUTHZ_SRC_TYPE = "sourceType";
+ public final static String AUTHZ_SRC_LDAP = "ldap";
+ public final static String AUTHZ_SRC_XML = "web.xml";
+ public static final String CERT_ATTR =
+ "javax.servlet.request.X509Certificate";
+
+ private final static String LOGGING_SIGNED_AUDIT_AUTH_FAIL =
+ "LOGGING_SIGNED_AUDIT_AUTH_FAIL_4";
+ private final static String LOGGING_SIGNED_AUDIT_AUTH_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_AUTH_SUCCESS_3";
+ private final static String LOGGING_SIGNED_AUDIT_AUTHZ_FAIL =
+ "LOGGING_SIGNED_AUDIT_AUTHZ_FAIL_4";
+ private final static String LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS_4";
+ private final static String LOGGING_SIGNED_AUDIT_ROLE_ASSUME =
+ "LOGGING_SIGNED_AUDIT_ROLE_ASSUME_3";
+ private final static String CERTUSERDB =
+ IAuthSubsystem.CERTUSERDB_AUTHMGR_ID;
+ private final static String PASSWDUSERDB =
+ IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID;
+
+ /**
+ * Constructs generic administration servlet.
+ */
+ public AdminServlet() {
+ }
+
+ /**
+ * Initializes the servlet.
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mUG = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+ mConfig = CMS.getConfigStore();
+
+ String srcType = AUTHZ_SRC_LDAP;
+
+ try {
+ IConfigStore authzConfig = mConfig.getSubStore(AUTHZ_CONFIG_STORE);
+
+ srcType = authzConfig.getString(AUTHZ_SRC_TYPE, AUTHZ_SRC_LDAP);
+ } catch (EBaseException e) {
+ CMS.debug("AdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_FAIL_SRC_TYPE"));
+ }
+ mAuthz =
+ (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ);
+
+ mServletID = getSCparam(sc, PROP_ID, "servlet id unknown");
+ CMS.debug("AdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_INITED", mServletID));
+
+ if (srcType.equalsIgnoreCase(AUTHZ_SRC_XML)) {
+ CMS.debug("AdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_INITED", ""));
+ // get authz mgr from xml file; if not specified, use
+ // ldap by default
+ mAclMethod = getSCparam(sc, PROP_AUTHZ_MGR, AUTHZ_MGR_LDAP);
+
+ if (mAclMethod.equalsIgnoreCase(AUTHZ_MGR_BASIC)) {
+ String aclInfo = sc.getInitParameter(PROP_ACL);
+
+ if (aclInfo != null) {
+ try {
+ addACLInfo(aclInfo);
+ //mAuthz.authzMgrAccessInit(mAclMethod, aclInfo);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_MGR_INIT_FAIL"));
+ throw new ServletException("failed to init authz info from xml config file");
+ }
+ CMS.debug("AdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_MGR_INIT_DONE", mServletID));
+ } else { // PROP_AUTHZ_MGR not specified, use default authzmgr
+ CMS.debug("AdminServlet: "
+ + CMS.getLogMessage("ADMIN_SRVLT_PROP_ACL_NOT_SPEC", PROP_ACL, mServletID, AUTHZ_MGR_LDAP));
+ }
+ } else { // PROP_AUTHZ_MGR not specified, use default authzmgr
+ CMS.debug("AdminServlet: "
+ + CMS.getLogMessage("ADMIN_SRVLT_PROP_ACL_NOT_SPEC", PROP_AUTHZ_MGR, mServletID, AUTHZ_MGR_LDAP));
+ }
+
+ } else {
+ mAclMethod = AUTHZ_MGR_LDAP;
+ CMS.debug("AdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_AUTH_LDAP_NOT_XML", mServletID));
+ }
+ }
+
+ public void outputHttpParameters(HttpServletRequest httpReq) {
+ CMS.debug("AdminServlet:service() uri = " + httpReq.getRequestURI());
+ Enumeration<String> paramNames = httpReq.getParameterNames();
+ while (paramNames.hasMoreElements()) {
+ String pn = paramNames.nextElement();
+ // added this facility so that password can be hidden,
+ // all sensitive parameters should be prefixed with
+ // __ (double underscores); however, in the event that
+ // a security parameter slips through, we perform multiple
+ // additional checks to insure that it is NOT displayed
+ if (pn.startsWith("__") ||
+ pn.endsWith("password") ||
+ pn.endsWith("passwd") ||
+ pn.endsWith("pwd") ||
+ pn.equalsIgnoreCase("admin_password_again") ||
+ pn.equalsIgnoreCase("directoryManagerPwd") ||
+ pn.equalsIgnoreCase("bindpassword") ||
+ pn.equalsIgnoreCase("bindpwd") ||
+ pn.equalsIgnoreCase("passwd") ||
+ pn.equalsIgnoreCase("password") ||
+ pn.equalsIgnoreCase("pin") ||
+ pn.equalsIgnoreCase("pwd") ||
+ pn.equalsIgnoreCase("pwdagain") ||
+ pn.equalsIgnoreCase("uPasswd")) {
+ CMS.debug("AdminServlet::service() param name='" + pn +
+ "' value='(sensitive)'");
+ } else {
+ CMS.debug("AdminServlet::service() param name='" + pn +
+ "' value='" + httpReq.getParameter(pn) + "'");
+ }
+ }
+ }
+
+ /**
+ * Serves HTTP admin request.
+ */
+ public void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ boolean running_state = CMS.isInRunningState();
+
+ if (!running_state)
+ throw new IOException(
+ "CMS server is not ready to serve.");
+
+ if (CMS.debugOn()) {
+ outputHttpParameters(req);
+ }
+ }
+
+ private void addACLInfo(String info) throws EBaseException {
+ StringTokenizer tokenizer = new StringTokenizer(info, "#");
+
+ while (tokenizer.hasMoreTokens()) {
+ String acl = tokenizer.nextToken();
+
+ mAuthz.authzMgrAccessInit(mAclMethod, acl);
+ }
+ }
+
+ private String getSCparam(ServletConfig sc, String param, String defVal) {
+ String val = sc.getInitParameter(param);
+
+ if (val == null)
+ return defVal;
+ else
+ return val;
+ }
+
+ /**
+ * Authenticates to the identity scope with the given
+ * userid and password via identity manager.
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTH_FAIL used when authentication fails (in case of SSL-client auth, only
+ * webserver env can pick up the SSL violation; CMS authMgr can pick up cert mis-match, so this event is used)
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTH_SUCCESS used when authentication succeeded
+ * </ul>
+ *
+ * @exception IOException an input/output error has occurred
+ */
+ protected void authenticate(HttpServletRequest req) throws
+ IOException {
+
+ String auditMessage = null;
+ String auditUID = ILogger.UNIDENTIFIED;
+ String authType = "";
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ try {
+ IConfigStore configStore = CMS.getConfigStore();
+
+ authType = configStore.getString("authType");
+ } catch (EBaseException e) {
+ // do nothing for now.
+ }
+ IAuthSubsystem auth = (IAuthSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ X509Certificate cert = null;
+
+ if (authType.equals("sslclientauth")) {
+ X509Certificate[] allCerts =
+ (X509Certificate[]) req.getAttribute(CERT_ATTR);
+
+ if (allCerts == null || allCerts.length == 0) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ ILogger.UNIDENTIFIED,
+ ILogger.FAILURE,
+ CERTUSERDB,
+ auditUID);
+
+ audit(auditMessage);
+
+ throw new IOException("No certificate");
+ }
+
+ cert = allCerts[0];
+ try {
+ byte[] certEncoded = cert.getEncoded();
+
+ cert = new X509CertImpl(certEncoded);
+
+ // save the "Subject DN" of this certificate in case it
+ // must be audited as an authentication failure
+ String certUID = cert.getSubjectDN().getName();
+
+ if (certUID != null) {
+ certUID = certUID.trim();
+
+ if (!(certUID.equals(""))) {
+ auditUID = certUID;
+ }
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ // create session (if we don't, identity will reject
+ // the authentication).
+ SessionContext sc = SessionContext.getContext();
+ IAuthToken token = null;
+
+ log(ILogger.LL_DEBUG, CMS.getLogMessage("ADMIN_SRVLT_ABOUT_AUTH",
+ mServletID));
+ try {
+ if (authType.equals("sslclientauth")) {
+ IAuthManager authMgr = auth.get(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID);
+ IAuthCredentials authCreds =
+ getAuthCreds(authMgr, cert);
+
+ token = authMgr.authenticate(authCreds);
+ } else {
+ String authToken = req.getHeader(HDR_AUTHORIZATION);
+ String b64s = authToken.substring(
+ authToken.lastIndexOf(' ') + 1);
+ String authCode = new String(Utils.base64decode(b64s));
+ String userid = authCode.substring(0,
+ authCode.indexOf(':'));
+ String password = authCode.substring(
+ authCode.indexOf(':') + 1);
+ AuthCredentials cred = new AuthCredentials();
+
+ // save the "userid" of this certificate in case it
+ // must be audited as an authentication failure
+ String pwdUID = userid;
+
+ if (pwdUID != null) {
+ pwdUID = pwdUID.trim();
+
+ if (!(pwdUID.equals(""))) {
+ auditUID = pwdUID;
+ }
+ }
+
+ cred.set("uid", userid);
+ cred.set("pwd", password);
+
+ token = auth.authenticate(cred,
+ IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID);
+ CMS.debug("AdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FOR_SRVLT",
+ mServletID));
+ }
+ } catch (EBaseException e) {
+ //will fix it later for authorization
+ /*
+ String errMsg = "authenticate(): " +
+ AdminResources.SRVLT_FAIL_AUTHS +": "+userid +":"+
+ e.getMessage();
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAIL",
+ CMS.getLogMessage("ADMIN_SRVLT_FAIL_AUTHS"),
+ userid,e.getMessage()));
+ */
+
+ if (authType.equals("sslclientauth")) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ ILogger.UNIDENTIFIED,
+ ILogger.FAILURE,
+ CERTUSERDB,
+ auditUID);
+
+ audit(auditMessage);
+ } else {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ ILogger.UNIDENTIFIED,
+ ILogger.FAILURE,
+ PASSWDUSERDB,
+ auditUID);
+
+ audit(auditMessage);
+ }
+
+ throw new IOException("authentication failed");
+ }
+
+ try {
+ String tuserid = token.getInString("userid");
+
+ if (tuserid == null) {
+ mLogger.log(
+ ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_NO_AUTH_TOKEN",
+ tuserid));
+
+ if (authType.equals("sslclientauth")) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ ILogger.UNIDENTIFIED,
+ ILogger.FAILURE,
+ CERTUSERDB,
+ auditUID);
+
+ audit(auditMessage);
+ } else {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ ILogger.UNIDENTIFIED,
+ ILogger.FAILURE,
+ PASSWDUSERDB,
+ auditUID);
+
+ audit(auditMessage);
+ }
+
+ throw new IOException("authentication failed");
+ }
+
+ // get user.
+ // this either returns null or
+ // throws exception when user not found
+ IUser user = mUG.getUser(tuserid);
+
+ if (user == null) {
+ mLogger.log(
+ ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_USER_NOT_FOUND",
+ tuserid));
+
+ if (authType.equals("sslclientauth")) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ ILogger.UNIDENTIFIED,
+ ILogger.FAILURE,
+ CERTUSERDB,
+ auditUID);
+
+ audit(auditMessage);
+ } else {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ ILogger.UNIDENTIFIED,
+ ILogger.FAILURE,
+ PASSWDUSERDB,
+ auditUID);
+
+ audit(auditMessage);
+ }
+
+ throw new IOException("authentication failed");
+ }
+
+ // set session context to work with some agent servlets.
+ // XXX should see if this can be used for more things.
+ SessionContext sessionContext = SessionContext.getContext();
+
+ sessionContext.put(SessionContext.AUTH_TOKEN, token);
+ sessionContext.put(SessionContext.USER_ID, tuserid);
+ sessionContext.put(SessionContext.USER, user);
+ } catch (EUsrGrpException e) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_USR_GRP_ERR", e.toString()));
+
+ if (authType.equals("sslclientauth")) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ ILogger.UNIDENTIFIED,
+ ILogger.FAILURE,
+ CERTUSERDB,
+ auditUID);
+
+ audit(auditMessage);
+ } else {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ ILogger.UNIDENTIFIED,
+ ILogger.FAILURE,
+ PASSWDUSERDB,
+ auditUID);
+
+ audit(auditMessage);
+ }
+
+ throw new IOException("authentication failed");
+ }
+
+ // build locale based on the client language
+ Locale locale = getLocale(req);
+
+ sc.put(SessionContext.LOCALE, locale);
+
+ if (authType.equals("sslclientauth")) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_SUCCESS,
+ auditSubjectID(),
+ ILogger.SUCCESS,
+ CERTUSERDB);
+
+ audit(auditMessage);
+ } else {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_SUCCESS,
+ auditSubjectID(),
+ ILogger.SUCCESS,
+ PASSWDUSERDB);
+
+ audit(auditMessage);
+ }
+ } catch (IOException eAudit1) {
+ if (authType.equals("sslclientauth")) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ ILogger.UNIDENTIFIED,
+ ILogger.FAILURE,
+ CERTUSERDB,
+ auditUID);
+
+ audit(auditMessage);
+ } else {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ ILogger.UNIDENTIFIED,
+ ILogger.FAILURE,
+ PASSWDUSERDB,
+ auditUID);
+
+ audit(auditMessage);
+ }
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ }
+ }
+
+ public static AuthCredentials getAuthCreds(
+ IAuthManager authMgr, X509Certificate clientCert)
+ throws EBaseException {
+ // get credentials from http parameters.
+ String[] reqCreds = authMgr.getRequiredCreds();
+ AuthCredentials creds = new AuthCredentials();
+
+ for (int i = 0; i < reqCreds.length; i++) {
+ String reqCred = reqCreds[i];
+
+ if (reqCred.equals(IAuthManager.CRED_SSL_CLIENT_CERT)) {
+ // cert could be null;
+ creds.set(reqCred, new X509Certificate[] { clientCert }
+ );
+ }
+ }
+ return creds;
+ }
+
+ /**
+ * Authorize must occur after Authenticate
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_FAIL used when authorization has failed
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS used when authorization is successful
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_ROLE_ASSUME used when user assumes a role (in current CMS that's when one
+ * accesses a role port)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @return the authorization token
+ */
+ protected AuthzToken authorize(HttpServletRequest req) {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditACLResource = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ String auditOperation = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ String resource = null;
+ String operation = null;
+
+ // use session context to get auth token for now
+ SessionContext sc = SessionContext.getContext();
+ IAuthToken authToken = (IAuthToken) sc.get(SessionContext.AUTH_TOKEN);
+
+ AuthzToken authzTok = null;
+
+ CMS.debug("AdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_CHECK_AUTHZ_AUTH", mServletID));
+ // hardcoded for now .. just testing
+ try {
+ // we check both "read" and "write" for now. later within
+ // each servlet, they can break it down
+ authzTok = mAuthz.authorize(mAclMethod, authToken, AUTHZ_RES_NAME, mOp);
+ // initialize the ACL resource, overwriting "auditACLResource"
+ // if it is not null
+ resource = (String)
+ authzTok.get(AuthzToken.TOKEN_AUTHZ_RESOURCE);
+ if (resource != null) {
+ auditACLResource = resource.trim();
+ }
+
+ // initialize the operation, overwriting "auditOperation"
+ // if it is not null
+ operation = (String)
+ authzTok.get(AuthzToken.TOKEN_AUTHZ_OPERATION);
+ if (operation != null) {
+ auditOperation = operation.trim();
+ }
+
+ CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_AUTH_SUCCEED", mServletID));
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditGroups(auditSubjectID));
+
+ audit(auditMessage);
+
+ return null;
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditGroups(auditSubjectID));
+
+ audit(auditMessage);
+
+ return null;
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditGroups(auditSubjectID));
+
+ audit(auditMessage);
+
+ return null;
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditGroups(auditSubjectID));
+
+ audit(auditMessage);
+
+ return authzTok;
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader(HDR_LANG);
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+
+ public static int SUCCESS = 0;
+ public static int ERROR = 1;
+ public static int RESTART = -1;
+
+ /**
+ * Sends response.
+ *
+ * @param returnCode return code
+ * @param errorMsg localized error message
+ * @param params result parameters
+ * @param resp HTTP servlet response
+ */
+ protected void sendResponse(int returnCode, String errorMsg,
+ NameValuePairs params, HttpServletResponse resp)
+ throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ DataOutputStream dos = new DataOutputStream(bos);
+
+ dos.writeInt(returnCode);
+ if (errorMsg != null) {
+ dos.writeUTF(errorMsg);
+ }
+ StringBuffer buf = new StringBuffer();
+
+ if (params != null) {
+ Collection<String> names = params.keySet();
+
+ if (!names.isEmpty()) {
+ for (Iterator<String> i = names.iterator(); i.hasNext(); ) {
+ String name = i.next();
+ String value = java.net.URLEncoder.encode(
+ params.get(name), "UTF-8");
+
+ buf.append(java.net.URLEncoder.encode(name, "UTF-8") +
+ "=" + value);
+ if (i.hasNext())
+ buf.append("&");
+ }
+ byte content[] = buf.toString().getBytes();
+
+ dos.write(content, 0, content.length);
+ }
+ }
+ byte msg[] = bos.toByteArray();
+
+ resp.setContentLength(msg.length);
+ resp.getOutputStream().write(msg);
+ resp.getOutputStream().flush();
+ }
+
+ /**
+ * URL decodes the given string.
+ */
+ protected String URLdecode(String s) {
+ if (s == null)
+ return null;
+ ByteArrayOutputStream out = new ByteArrayOutputStream(s.length());
+
+ for (int i = 0; i < s.length(); i++) {
+ int c = s.charAt(i);
+
+ if (c == '+') {
+ out.write(' ');
+ } else if (c == '%') {
+ int c1 = Character.digit(s.charAt(++i), 16);
+ int c2 = Character.digit(s.charAt(++i), 16);
+
+ out.write((char) (c1 * 16 + c2));
+ } else {
+ out.write(c);
+ }
+ } // end for
+ return out.toString();
+ }
+
+ protected String getParameter(HttpServletRequest req, String name) {
+ // Servlet framework already apply URLdecode
+ // return URLdecode(req.getParameter(name));
+ return req.getParameter(name);
+ }
+
+ /**
+ * Generic configuration store get operation.
+ */
+ protected synchronized void getConfig(
+ IConfigStore config, HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ //if (name.equals(Constants.PT_OP))
+ // continue;
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+
+ //System.out.println(name);
+ //System.out.println(name+","+config.getString(name));
+ params.put(name, config.getString(name));
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * Generic configuration store set operation.
+ * The caller is responsible to do validiation before
+ * calling this, and commit changes after this call.
+ */
+ protected synchronized void setConfig(
+ IConfigStore config, HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ //if (name.equals(Constants.PT_OP))
+ // continue;
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ // XXX Need validation...
+ // XXX what if update failed
+ config.putString(name, req.getParameter(name));
+ }
+ commit(true);
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * Lists configuration store.
+ */
+ protected synchronized void listConfig(
+ IConfigStore config, HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ Enumeration<String> e = config.getPropertyNames();
+ NameValuePairs params = new NameValuePairs();
+
+ while (e.hasMoreElements()) {
+ String s = e.nextElement();
+
+ params.put(s, config.getString(s));
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * authorize a user based on its authentication credentials.
+ */
+ public boolean authorize(IAuthToken token) throws EBaseException {
+ String mGroupNames[] = { "Administrators" };
+ boolean mAnd = true;
+
+ try {
+ String userid = token.getInString("userid");
+
+ if (userid == null) {
+ mLogger.log(
+ ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_GRP_AUTHZ_FAIL", userid));
+ return false;
+ }
+
+ // get user.
+ // this either returns null or throws exception when user not found
+ IUser user = mUG.getUser(userid);
+
+ if (user == null) {
+ mLogger.log(
+ ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_USER_NOT_IN_DB", userid));
+ return false;
+ }
+
+ // set session context to work with some agent servlets.
+ // XXX should see if this can be used for more things.
+ SessionContext sessionContext = SessionContext.getContext();
+
+ sessionContext.put(SessionContext.AUTH_TOKEN, token);
+ sessionContext.put(SessionContext.USER_ID, userid);
+ sessionContext.put(SessionContext.USER, user);
+
+ // check group membership of user.
+ if (mAnd) {
+ for (int i = 0; i < mGroupNames.length; i++) {
+ if (!mUG.isMemberOf(user, mGroupNames[i])) {
+ mLogger.log(
+ ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_USER_NOT_IN_GRP", userid,
+ mGroupNames[i]));
+ return false;
+ }
+ }
+ return true;
+ } else {
+ for (int i = 0; i < mGroupNames.length; i++) {
+ if (mUG.isMemberOf(user, mGroupNames[i])) {
+ mLogger.log(ILogger.EV_SYSTEM,
+ ILogger.S_OTHER, ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_GRP_AUTH_SUCC_USER", userid,
+ mGroupNames[i]));
+ return true;
+ }
+ }
+ StringBuffer groups = new StringBuffer();
+ groups.append(mGroupNames[0]);
+
+ for (int j = 1; j < mGroupNames.length; j++) {
+ groups.append(",");
+ groups.append(mGroupNames[j]);
+ }
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_USER_NOT_ANY_GRP", userid, groups.toString()));
+ return false;
+ }
+ } catch (EUsrGrpException e) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_USR_GRP_ERR", e.toString()));
+ return false;
+ }
+ }
+
+ /**
+ * FileConfigStore functionality
+ *
+ * The original config file is moved to <filename>.<date>.
+ * Commits the current properties to the configuration file.
+ * <P>
+ *
+ * @param createBackup true if a backup file should be created
+ */
+ protected void commit(boolean createBackup) throws EBaseException {
+ mConfig.commit(createBackup);
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_ADMIN,
+ level, "AdminServlet: " + msg);
+ }
+
+ /**
+ * Signed Audit Log
+ *
+ * This method is inherited by all extended admin servlets
+ * and is called to store messages to the signed audit log.
+ * <P>
+ *
+ * @param msg signed audit log message
+ */
+ protected void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+
+ if (auditor == null) {
+ return;
+ }
+
+ auditor.log(msg);
+ }
+
+ /**
+ * Signed Audit Log Subject ID
+ *
+ * This method is inherited by all extended "CMSServlet"s,
+ * and is called to obtain the "SubjectID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @return id string containing the signed audit log message SubjectID
+ */
+ protected String auditSubjectID() {
+ if (auditor == null) return null;
+ return auditor.getSubjectID();
+ }
+
+ /**
+ * Signed Audit Parameters
+ *
+ * This method is inherited by all extended admin servlets and
+ * is called to extract parameters from the HttpServletRequest
+ * and return a string of name;;value pairs separated by a '+'
+ * if more than one name;;value pair exists.
+ * <P>
+ *
+ * @param req HTTP servlet request
+ * @return a delimited string of one or more delimited name/value pairs
+ */
+ protected String auditParams(HttpServletRequest req) {
+ if (auditor == null) return null;
+
+ // always identify the scope of the request
+ String scope = req.getParameter(Constants.OP_SCOPE);
+
+ // identify the operation type of the request
+ String type = req.getParameter(Constants.OP_TYPE);
+
+ // identify the resource type of the request
+ String id = req.getParameter(Constants.RS_ID);
+
+ // identify any remaining request parameters
+ Map<String, String> params = new LinkedHashMap<String, String>();
+
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ // skip previously extracted parameters
+ if (name.equals(Constants.OP_SCOPE)) continue;
+ if (name.equals(Constants.OP_TYPE)) continue;
+ if (name.equals(Constants.RS_ID)) continue;
+
+ String value = req.getParameter(name);
+ params.put(name, value);
+ }
+
+ return auditor.getParamString(scope, type, id, params);
+ }
+
+ /**
+ * Signed Audit Groups
+ *
+ * This method is called to extract all "groups" associated
+ * with the "auditSubjectID()".
+ * <P>
+ *
+ * @param subjectID string containing the signed audit log message SubjectID
+ * @return a delimited string of groups associated
+ * with the "auditSubjectID()"
+ */
+ private String auditGroups(String subjectID) {
+ if (auditor == null) return null;
+ return auditor.getGroups(subjectID);
+ }
+
+ protected NameValuePairs convertStringArrayToNVPairs(String[] s) {
+ if (s == null)
+ return null;
+ NameValuePairs nvps = new NameValuePairs();
+ int i;
+
+ for (i = 0; i < s.length; i++) {
+ int j = s[i].indexOf(";");
+ String paramName = s[i].substring(0, j);
+ String args = s[i].substring(j + 1);
+
+ nvps.put(paramName, args);
+ }
+ return nvps;
+
+ }
+
+ protected static IExtendedPluginInfo getClassByNameAsExtendedPluginInfo(String className) {
+
+ IExtendedPluginInfo epi = null;
+
+ try {
+ // here is the new dummy obj created
+ Object o = Class.forName(className).newInstance();
+
+ epi = (IExtendedPluginInfo) o;
+ } catch (Exception e) {
+ }
+
+ return epi;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/AuthAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/AuthAdminServlet.java
new file mode 100644
index 000000000..71cf8a2ac
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/AuthAdminServlet.java
@@ -0,0 +1,1716 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthManagerProxy;
+import com.netscape.certsrv.authentication.AuthMgrPlugin;
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.authentication.EAuthMgrNotFound;
+import com.netscape.certsrv.authentication.EAuthMgrPluginNotFound;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.DestDef;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.ldap.ILdapAuthInfo;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A class representing an administration servlet for the
+ * Authentication Management subsystem. This servlet is responsible
+ * to serve configuration requests for the Auths Management subsystem.
+ *
+ *
+ * @version $Revision$, $Date$
+ */
+public class AuthAdminServlet extends AdminServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6258411211380144425L;
+ private final static String INFO = "AuthAdminServlet";
+ private IAuthSubsystem mAuths = null;
+
+ private final static String PW_PASSWORD_CACHE_ADD =
+ "PASSWORD_CACHE_ADD";
+ private final static String EDIT = ";" + Constants.EDIT;
+
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_AUTH =
+ "LOGGING_SIGNED_AUDIT_CONFIG_AUTH_3";
+
+ public AuthAdminServlet() {
+ super();
+ }
+
+ /**
+ * Initializes this servlet.
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ mAuths = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ AUTHZ_RES_NAME = "certServer.auth.configuration";
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * retrieve extended plugin info such as brief description, type info
+ * from policy, authentication,
+ * need to add: listener, mapper and publishing plugins
+ * --- same as policy, should we move this into extendedpluginhelper?
+ */
+ private void getExtendedPluginInfo(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ int colon = id.indexOf(':');
+
+ String implType = id.substring(0, colon);
+ String implName = id.substring(colon + 1);
+
+ NameValuePairs params =
+ getExtendedPluginInfo(getLocale(req), implType, implName);
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private NameValuePairs getExtendedPluginInfo(Locale locale, String implType, String implName) {
+ IExtendedPluginInfo ext_info = null;
+ Object impl = null;
+
+ impl = mAuths.getAuthManagerPlugin(implName);
+ if (impl != null) {
+ if (impl instanceof IExtendedPluginInfo) {
+ ext_info = (IExtendedPluginInfo) impl;
+ }
+ }
+
+ NameValuePairs nvps = null;
+
+ if (ext_info == null) {
+ nvps = new NameValuePairs();
+ } else {
+ nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale));
+ }
+
+ return nvps;
+
+ }
+
+ /**
+ * Serves HTTP admin request.
+ */
+ public void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+
+ String scope = req.getParameter(Constants.OP_SCOPE);
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op == null) {
+ //System.out.println("SRVLT_INVALID_PROTOCOL");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"),
+ null, resp);
+ return;
+ }
+
+ // if it is not authentication, that means it is for CSC admin ping.
+ // the best way to do is to define another protocol for ping and move
+ // it to the generic servlet which is admin servlet.
+ if (!op.equals(OpDef.OP_AUTH)) {
+ if (scope.equals(ScopeDef.SC_AUTH)) {
+ String id = req.getParameter(Constants.RS_ID);
+
+ // for CSC admin ping only
+ if (op.equals(OpDef.OP_READ) &&
+ id.equals(Constants.RS_ID_CONFIG)) {
+
+ // no need to authenticate this. if we're alive, return true.
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_PING, Constants.TRUE);
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ } else {
+ //System.out.println("SRVLT_INVALID_OP_TYPE");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_TYPE", op),
+ null, resp);
+ return;
+ }
+ }
+ }
+
+ try {
+ if (op.equals(OpDef.OP_AUTH)) {
+ if (scope.equals(ScopeDef.SC_AUTHTYPE)) {
+ IConfigStore configStore = CMS.getConfigStore();
+ String val = configStore.getString("authType", "pwd");
+ NameValuePairs params = new NameValuePairs();
+
+ params.put("authType", val);
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+ }
+ } catch (Exception e) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHS_FAILED"),
+ null, resp);
+ return;
+ }
+ // for the rest
+ try {
+ super.authenticate(req);
+ if (op.equals(OpDef.OP_AUTH)) { // for admin authentication only
+ sendResponse(SUCCESS, null, null, resp);
+ return;
+ }
+ } catch (IOException e) {
+ //System.out.println("SRVLT_FAIL_AUTHS");
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHS_FAILED"),
+ null, resp);
+ return;
+ }
+
+ try {
+ // perform operation based on scope
+ if (scope != null) {
+ AUTHZ_RES_NAME = "certServer.auth.configuration";
+ if (scope.equals(ScopeDef.SC_EXTENDED_PLUGIN_INFO)) {
+ try {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ getExtendedPluginInfo(req, resp);
+ return;
+ } catch (EBaseException e) {
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ }
+ }
+ if (op.equals(OpDef.OP_SEARCH)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_AUTH_IMPLS)) {
+ listAuthMgrPlugins(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_AUTH_MGR_INSTANCE)) {
+ listAuthMgrInsts(req, resp);
+ return;
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_READ)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_AUTH_IMPLS)) {
+ getConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_AUTH_MGR_INSTANCE)) {
+ getInstConfig(req, resp);
+ return;
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_ADD)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_AUTH_IMPLS)) {
+ addAuthMgrPlugin(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_AUTH_MGR_INSTANCE)) {
+ addAuthMgrInst(req, resp, scope);
+ return;
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_AUTH_IMPLS)) {
+ delAuthMgrPlugin(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_AUTH_MGR_INSTANCE)) {
+ delAuthMgrInst(req, resp, scope);
+ return;
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_AUTH_MGR_INSTANCE)) {
+ modAuthMgrInst(req, resp, scope);
+ return;
+ }
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ }
+ } catch (EBaseException e) {
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ }
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_PERFORM_FAILED"),
+ null, resp);
+ return;
+ }
+
+ private void putUserPWPair(String combo) {
+ int semicolon;
+
+ semicolon = combo.indexOf(";");
+ String user = combo.substring(0, semicolon);
+ String pw = combo.substring(semicolon + 1);
+
+ CMS.putPasswordCache(user, pw);
+ }
+
+ /**
+ * Add authentication manager plug-in
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_AUTH used when configuring authentication
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param scope string used to obtain the contents of this authentication
+ * manager's substore
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+
+ private synchronized void addAuthMgrPlugin(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+ // is the manager id unique?
+ if (mAuths.getPlugins().containsKey(id)) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(
+ ERROR,
+ new EAuthException(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_DUP_MGR_PLUGIN_ID",
+ id)).toString(),
+ null, resp);
+ return;
+ }
+
+ String classPath = req.getParameter(Constants.PR_AUTH_CLASS);
+
+ if (classPath == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_NULL_AUTHMGR_CLASSNAME"),
+ null, resp);
+ return;
+ }
+
+ if (classPath.equals("com.netscape.cmscore.authentication.PasswdUserDBAuthentication") ||
+ classPath.equals("com.netscape.cmscore.authentication.CertUserDBAuthentication")) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_BASE_PERMISSION_DENIED"), null, resp);
+ return;
+ }
+
+ IConfigStore destStore =
+ mConfig.getSubStore(DestDef.DEST_AUTH_ADMIN);
+ IConfigStore instancesConfig =
+ destStore.getSubStore(scope);
+
+ // Does the class exist?
+
+ Class<IAuthManager> newImpl = null;
+
+ try {
+ @SuppressWarnings("unchecked")
+ Class<IAuthManager> tmpImpl = (Class<IAuthManager>) Class.forName(classPath);
+ newImpl = tmpImpl;
+ } catch (ClassNotFoundException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_AUTHMGR_PLUGIN_NOT_FOUND"),
+ null, resp);
+ return;
+ } catch (IllegalArgumentException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_AUTHMGR_PLUGIN_NOT_FOUND"),
+ null, resp);
+ return;
+ }
+
+ // is the class an IAuthManager?
+ try {
+ if (IAuthManager.class.isAssignableFrom(newImpl) == false) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_ILL_CLASS"),
+ null, resp);
+ return;
+ }
+ } catch (NullPointerException e) { // unlikely, only if newImpl null.
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_ILL_CLASS"),
+ null, resp);
+ return;
+ }
+
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ substore.put(Constants.PR_AUTH_CLASS, classPath);
+
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // add manager to registry.
+ AuthMgrPlugin plugin = new AuthMgrPlugin(id, classPath);
+
+ mAuths.getPlugins().put(id, plugin);
+ mAuths.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_PLUGIN_ADD", id));
+
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ // } catch( EBaseException eAudit1 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * Add authentication manager instance
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_AUTH used when configuring authentication
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param scope string used to obtain the contents of this authentication
+ * manager's substore
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void addAuthMgrInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // is the manager instance id unique?
+ if (mAuths.getInstances().containsKey(id)) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_ILL_MGR_INST_ID"),
+ null, resp);
+ return;
+ }
+
+ // get required parameters
+ // SC_AUTH_IMPL_NAME is absolutely required, the rest depend on
+ // on each authenticaton manager
+ String implname = req.getParameter(Constants.PR_AUTH_IMPL_NAME);
+
+ if (implname == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_MISSING_PARAMS"),
+ null, resp);
+ return;
+ }
+
+ // prevent agent & admin creation.
+ if (implname.equals(IAuthSubsystem.PASSWDUSERDB_PLUGIN_ID) ||
+ implname.equals(IAuthSubsystem.CERTUSERDB_PLUGIN_ID)) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_BASE_PERMISSION_DENIED"), null, resp);
+ }
+
+ // check if implementation exists.
+ AuthMgrPlugin plugin =
+ mAuths.getPlugins().get(implname);
+
+ if (plugin == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(
+ ERROR,
+ new EAuthMgrPluginNotFound(CMS.getUserMessage(getLocale(req),
+ "CMS_AUTHENTICATION_AUTHMGR_NOT_FOUND", implname)).toString(),
+ null, resp);
+ return;
+ }
+
+ // now the rest of config parameters
+ // note that we only check to see if the required parameters
+ // are there, but not checking the values are valid
+ String[] configParams = mAuths.getConfigParams(implname);
+
+ IConfigStore destStore =
+ mConfig.getSubStore(DestDef.DEST_AUTH_ADMIN);
+ IConfigStore instancesConfig =
+ destStore.getSubStore(scope);
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ if (configParams != null) {
+ for (int i = 0; i < configParams.length; i++) {
+ String key = configParams[i];
+ String val = req.getParameter(key);
+
+ if (val != null) {
+ substore.put(key, val);
+ }
+ }
+ }
+ substore.put(IAuthSubsystem.PROP_PLUGIN, implname);
+
+ String pwadd = req.getParameter(PW_PASSWORD_CACHE_ADD);
+
+ if (pwadd != null) {
+ putUserPWPair(pwadd);
+ }
+
+ // Instantiate an object for this implementation
+ String className = plugin.getClassPath();
+ IAuthManager authMgrInst = null;
+
+ try {
+ authMgrInst = (IAuthManager) Class.forName(className).newInstance();
+ } catch (ClassNotFoundException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // cleanup
+ instancesConfig.removeSubStore(id);
+ sendResponse(
+ ERROR,
+ new EAuthException(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_LOAD_CLASS_FAIL",
+ className)).toString(),
+ null, resp);
+ return;
+ } catch (InstantiationException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ instancesConfig.removeSubStore(id);
+ sendResponse(
+ ERROR,
+ new EAuthException(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_LOAD_CLASS_FAIL",
+ className)).toString(),
+ null, resp);
+ return;
+ } catch (IllegalAccessException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ instancesConfig.removeSubStore(id);
+ sendResponse(
+ ERROR,
+ new EAuthException(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_LOAD_CLASS_FAIL",
+ className)).toString(),
+ null, resp);
+ return;
+ }
+
+ // initialize the authentication manager
+ try {
+ authMgrInst.init(id, implname, substore);
+ } catch (EBaseException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // don't commit in this case and cleanup the new substore.
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ }
+
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // clean up.
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // inited and commited ok. now add manager instance to list.
+ mAuths.add(id, authMgrInst);
+
+ mAuths.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_MGR_ADD", id));
+
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_AUTH_IMPL_NAME, implname);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ private synchronized void listAuthMgrPlugins(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = mAuths.getPlugins().keys();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+ AuthMgrPlugin value = mAuths.getPlugins().get(name);
+
+ if (value.isVisible()) {
+ params.put(name, value.getClassPath() + EDIT);
+ }
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void listAuthMgrInsts(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+
+ for (Enumeration<?> e = mAuths.getInstances().keys(); e.hasMoreElements();) {
+ String name = (String) e.nextElement();
+ AuthManagerProxy proxy = (AuthManagerProxy) mAuths.getInstances().get(name);
+ IAuthManager value = proxy.getAuthManager();
+ String enableStr = "enabled";
+
+ if (!proxy.isEnable()) {
+ enableStr = "disabled";
+ }
+
+ AuthMgrPlugin amgrplugin = mAuths.getPlugins().get(value.getImplName());
+
+ if (!amgrplugin.isVisible()) {
+ params.put(name, value.getImplName() + ";invisible;" + enableStr);
+ } else {
+ params.put(name, value.getImplName() + ";visible;" + enableStr);
+ }
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ /**
+ * Delete authentication manager plug-in
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_AUTH used when configuring authentication
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param scope string used to obtain the contents of this authentication
+ * manager's substore
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void delAuthMgrPlugin(HttpServletRequest req,
+ HttpServletResponse resp, String scope) throws ServletException,
+ IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ NameValuePairs params = new NameValuePairs();
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // prevent deletion of admin and agent.
+ if (id.equals(IAuthSubsystem.PASSWDUSERDB_PLUGIN_ID) ||
+ id.equals(IAuthSubsystem.CERTUSERDB_PLUGIN_ID)) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_BASE_PERMISSION_DENIED"), null, resp);
+ }
+
+ // does auth manager exist?
+ if (mAuths.getPlugins().containsKey(id) == false) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(
+ ERROR,
+ new EAuthMgrPluginNotFound(CMS.getUserMessage(getLocale(req),
+ "CMS_AUTHENTICATION_DUP_MGR_PLUGIN_ID", id)).toString(),
+ null, resp);
+ return;
+ }
+
+ // first check if any instances from this auth manager
+ // DON'T remove auth manager if any instance
+ for (Enumeration<?> e = mAuths.getInstances().keys(); e.hasMoreElements();) {
+ IAuthManager authMgr = mAuths.get((String) e.nextElement());
+
+ if (authMgr.getImplName() == id) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_MGR_IN_USE"),
+ null, resp);
+ return;
+ }
+ }
+
+ // then delete this auth manager
+ mAuths.getPlugins().remove(id);
+
+ IConfigStore destStore =
+ mConfig.getSubStore(DestDef.DEST_AUTH_ADMIN);
+ IConfigStore instancesConfig =
+ destStore.getSubStore(scope);
+
+ instancesConfig.removeSubStore(id);
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ // } catch( EBaseException eAudit1 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit1 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit1;
+ }
+ }
+
+ /**
+ * Delete authentication manager instance
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_AUTH used when configuring authentication
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param scope string used to obtain the contents of this authentication
+ * manager's substore
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void delAuthMgrInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope) throws ServletException,
+ IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ NameValuePairs params = new NameValuePairs();
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // prevent deletion of admin and agent.
+ if (id.equals(IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID) ||
+ id.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_BASE_PERMISSION_DENIED"), null, resp);
+ }
+
+ // does auth manager instance exist?
+ if (mAuths.getInstances().containsKey(id) == false) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(
+ ERROR,
+ new EAuthMgrNotFound(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_AUTHMGR_NOT_FOUND",
+ id)).toString(),
+ null, resp);
+ return;
+ }
+
+ // only remove from memory
+ // cannot shutdown because we don't keep track of whether it's
+ // being used.
+ mAuths.getInstances().remove(id);
+
+ // remove the configuration.
+ IConfigStore destStore =
+ mConfig.getSubStore(DestDef.DEST_AUTH_ADMIN);
+ IConfigStore instancesConfig =
+ destStore.getSubStore(scope);
+
+ instancesConfig.removeSubStore(id);
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ //This only works in the fact that we only support one instance per
+ //auth plugin.
+ ILdapAuthInfo authInfo = CMS.getLdapAuthInfo();
+
+ authInfo.removePassword("Rule " + id);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ // } catch( EBaseException eAudit1 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * used for getting the required configuration parameters (with
+ * possible default values) for a particular auth manager plugin
+ * implementation name specified in the RS_ID. Actually, there is
+ * no logic in here to set any default value here...there's no
+ * default value for any parameter in this authentication subsystem
+ * at this point. Later, if we do have one (or some), it can be
+ * added. The interface remains the same.
+ */
+ private synchronized void getConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+
+ String implname = req.getParameter(Constants.RS_ID);
+
+ if (implname == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ String[] configParams = mAuths.getConfigParams(implname);
+ NameValuePairs params = new NameValuePairs();
+
+ // implName is always required so always send it.
+ params.put(Constants.PR_AUTH_IMPL_NAME, "");
+ if (configParams != null) {
+ for (int i = 0; i < configParams.length; i++) {
+ params.put(configParams[i], "");
+ }
+ }
+ sendResponse(0, null, params, resp);
+ return;
+ }
+
+ private synchronized void getInstConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // does auth manager instance exist?
+ if (mAuths.getInstances().containsKey(id) == false) {
+ sendResponse(
+ ERROR,
+ new EAuthMgrNotFound(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_AUTHMGR_NOT_FOUND", id))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ IAuthManager mgrInst = mAuths.get(id);
+ IConfigStore config = mgrInst.getConfigStore();
+ String[] configParams = mgrInst.getConfigParams();
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_AUTH_IMPL_NAME, mgrInst.getImplName());
+ // implName is always required so always send it.
+ if (configParams != null) {
+ for (int i = 0; i < configParams.length; i++) {
+ String key = configParams[i];
+ String val = config.get(key);
+
+ if (val != null) {
+ params.put(key, val);
+ } else {
+ params.put(key, "");
+ }
+ }
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ /**
+ * Modify authentication manager instance
+ * This will actually create a new instance with new configuration
+ * parameters and replace the old instance if the new instance is
+ * created and initialized successfully.
+ * The old instance is left running, so this is very expensive.
+ * Restart of server recommended.
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_AUTH used when configuring authentication
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param scope string used to obtain the contents of this authentication
+ * manager's substore
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void modAuthMgrInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+
+ // expensive operation.
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // prevent modification of admin and agent.
+ if (id.equals(IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID) ||
+ id.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_BASE_PERMISSION_DENIED"), null, resp);
+ }
+
+ // Does the manager instance exist?
+ if (!mAuths.getInstances().containsKey(id)) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage("CMS_AUTHENTICATION_MGR_IMPL_NOT_FOUND"),
+ null, resp);
+ return;
+ }
+
+ // get new implementation (same or different.)
+ String implname = req.getParameter(Constants.PR_AUTH_IMPL_NAME);
+
+ if (implname == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage("CMS_AUTHENTICATION_MISSING_PARAMS"),
+ null, resp);
+ return;
+ }
+
+ // get plugin for implementation
+ AuthMgrPlugin plugin = mAuths.getPlugins().get(implname);
+
+ if (plugin == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(
+ ERROR,
+ new EAuthMgrPluginNotFound(CMS.getUserMessage(getLocale(req),
+ "CMS_AUTHENTICATION_AUTHMGR_NOT_FOUND", implname)).toString(),
+ null, resp);
+ return;
+ }
+
+ // save old instance substore params in case new one fails.
+
+ IAuthManager oldinst = mAuths.get(id);
+ IConfigStore oldConfig = oldinst.getConfigStore();
+
+ String[] oldConfigParms = oldinst.getConfigParams();
+ NameValuePairs saveParams = new NameValuePairs();
+
+ // implName is always required so always include it it.
+ saveParams.put(IAuthSubsystem.PROP_PLUGIN,
+ oldConfig.get(IAuthSubsystem.PROP_PLUGIN));
+ if (oldConfigParms != null) {
+ for (int i = 0; i < oldConfigParms.length; i++) {
+ String key = oldConfigParms[i];
+ Object val = oldConfig.get(key);
+
+ if (val != null) {
+ saveParams.put(key, (String) val);
+ }
+ }
+ }
+
+ // on to the new instance.
+
+ // remove old substore.
+
+ IConfigStore destStore =
+ mConfig.getSubStore(DestDef.DEST_AUTH_ADMIN);
+ IConfigStore instancesConfig =
+ destStore.getSubStore(scope);
+
+ instancesConfig.removeSubStore(id);
+
+ // create new substore.
+
+ String[] configParams = mAuths.getConfigParams(implname);
+
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ substore.put(IAuthSubsystem.PROP_PLUGIN, implname);
+ if (configParams != null) {
+ for (int i = 0; i < configParams.length; i++) {
+ String key = configParams[i];
+ String val = req.getParameter(key);
+
+ if (val != null) {
+ substore.put(key, val);
+ }
+ }
+ }
+
+ // Instantiate an object for new implementation
+
+ String className = plugin.getClassPath();
+ IAuthManager newMgrInst = null;
+
+ try {
+ newMgrInst = (IAuthManager) Class.forName(className).newInstance();
+ } catch (ClassNotFoundException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // cleanup
+ restore(instancesConfig, id, saveParams);
+ sendResponse(
+ ERROR,
+ new EAuthException(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_LOAD_CLASS_FAIL",
+ className)).toString(),
+ null, resp);
+ return;
+ } catch (InstantiationException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ restore(instancesConfig, id, saveParams);
+ sendResponse(
+ ERROR,
+ new EAuthException(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_LOAD_CLASS_FAIL",
+ className)).toString(),
+ null, resp);
+ return;
+ } catch (IllegalAccessException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ restore(instancesConfig, id, saveParams);
+ sendResponse(
+ ERROR,
+ new EAuthException(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_LOAD_CLASS_FAIL",
+ className)).toString(),
+ null, resp);
+ return;
+ }
+
+ // initialize the authentication manager
+
+ try {
+ newMgrInst.init(id, implname, substore);
+ } catch (EBaseException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // don't commit in this case and cleanup the new substore.
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ }
+
+ // initialized ok. commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // clean up.
+ restore(instancesConfig, id, saveParams);
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // commited ok. replace instance.
+
+ mAuths.add(id, newMgrInst);
+
+ mAuths.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_MGR_REPL", id));
+
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_AUTH,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ // convenience routine.
+ private static void restore(IConfigStore store,
+ String id, NameValuePairs saveParams) {
+ store.removeSubStore(id);
+ IConfigStore rstore = store.makeSubStore(id);
+
+ for (String key : saveParams.keySet()) {
+ String value = saveParams.get(key);
+
+ if (value != null)
+ rstore.put(key, value);
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/AuthCredentials.java b/base/server/cms/src/com/netscape/cms/servlet/admin/AuthCredentials.java
new file mode 100644
index 000000000..42c8da175
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/AuthCredentials.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+
+/**
+ * Authentication Credentials as input to the authMgr
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class AuthCredentials implements IAuthCredentials {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6938644716486895814L;
+ private Hashtable<String, Object> authCreds = null;
+ // Inserted by bskim
+ private IArgBlock argblk = null;
+
+ // Insert end
+
+ public AuthCredentials() {
+ authCreds = new Hashtable<String, Object>();
+ }
+
+ /**
+ * sets a credential with credential name and the credential
+ *
+ * @param name credential name
+ * @param cred credential
+ * @exception com.netscape.certsrv.base.EBaseException NullPointerException
+ */
+ public void set(String name, Object cred) throws EBaseException {
+ if (cred == null) {
+ throw new EBaseException("AuthCredentials.set()");
+ }
+
+ authCreds.put(name, cred);
+ }
+
+ /**
+ * returns the credential to which the specified name is mapped in this
+ * credential set
+ *
+ * @param name credential name
+ * @return the named authentication credential
+ */
+ public Object get(String name) {
+ return authCreds.get(name);
+ }
+
+ /**
+ * removes the name and its corresponding credential from this
+ * credential set. This method does nothing if the named
+ * credential is not in the credential set.
+ *
+ * @param name credential name
+ */
+ public void delete(String name) {
+ authCreds.remove(name);
+ }
+
+ /**
+ * returns an enumeration of the credential names in this credential
+ * set. Use the Enumeration methods on the returned object to
+ * fetch the elements sequentially.
+ *
+ * @return an enumeration of the names in this credential set
+ * @see java.util.Enumeration
+ */
+ public Enumeration<String> getElements() {
+ return authCreds.keys();
+ }
+
+ // Inserted by bskim
+ public void setArgBlock(IArgBlock blk) {
+ argblk = blk;
+ return;
+ }
+
+ // Insert end
+
+ public IArgBlock getArgBlock() {
+ return argblk;
+ }
+ // Insert end
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/CAAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/CAAdminServlet.java
new file mode 100644
index 000000000..09c77e557
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/CAAdminServlet.java
@@ -0,0 +1,1576 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.UnknownHostException;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ca.ICMSCRLExtensions;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequestListener;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * A class representings an administration servlet for Certificate
+ * Authority. This servlet is responsible to serve CA
+ * administrative operations such as configuration parameter
+ * updates.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CAAdminServlet extends AdminServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 6200983242040946840L;
+
+ public final static String PROP_EMAIL_TEMPLATE = "emailTemplate";
+
+ private final static String INFO = "CAAdminServlet";
+
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE =
+ "LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE_3";
+
+ private ICertificateAuthority mCA = null;
+ protected static final String PROP_ENABLED = "enabled";
+
+ /**
+ * Constructs CA servlet.
+ */
+ public CAAdminServlet() {
+ super();
+ }
+
+ /**
+ * Initializes this servlet.
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ mCA = (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Serves HTTP request. Each request is authenticated to
+ * the authenticate manager.
+ */
+ public void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+
+ //get all operational flags
+ String op = req.getParameter(Constants.OP_TYPE);
+ String scope = req.getParameter(Constants.OP_SCOPE);
+
+ //check operational flags
+ if ((op == null) || (scope == null)) {
+ sendResponse(1, "Invalid Protocol", null, resp);
+ return;
+ }
+
+ super.authenticate(req);
+
+ try {
+ AUTHZ_RES_NAME = "certServer.ca.configuration";
+ if (scope.equals(ScopeDef.SC_EXTENDED_PLUGIN_INFO)) {
+ try {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ getExtendedPluginInfo(req, resp);
+ return;
+ } catch (EBaseException e) {
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ }
+ }
+
+ if (op.equals(OpDef.OP_READ)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_GENERAL))
+ getGeneralConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_CONNECTOR))
+ getConnectorConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_CRLIPS))
+ getCRLIPsConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_CRL))
+ getCRLConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_NOTIFICATION_REQ_COMP))
+ getNotificationReqCompConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_NOTIFICATION_REV_COMP))
+ getNotificationRevCompConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_NOTIFICATION_RIQ))
+ getNotificationRIQConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_CRLEXTS_RULES))
+ getCRLExtsConfig(req, resp);
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_GENERAL))
+ setGeneralConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_CONNECTOR))
+ setConnectorConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_CRLIPS))
+ setCRLIPsConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_CRL))
+ setCRLConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_NOTIFICATION_REQ_COMP))
+ setNotificationReqCompConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_NOTIFICATION_REV_COMP))
+ setNotificationRevCompConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_NOTIFICATION_RIQ))
+ setNotificationRIQConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_CRLEXTS_RULES))
+ setCRLExtsConfig(req, resp);
+ } else if (op.equals(OpDef.OP_SEARCH)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_CRLEXTS_RULES))
+ listCRLExtsConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_CRLIPS))
+ listCRLIPsConfig(req, resp);
+ } else if (op.equals(OpDef.OP_ADD)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_CRLIPS))
+ addCRLIPsConfig(req, resp);
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_CRLIPS))
+ deleteCRLIPsConfig(req, resp);
+ } else {
+ sendResponse(1, "Unknown operation", null, resp);
+ }
+ } catch (Exception e) {
+ sendResponse(1, e.toString(), null, resp);
+ return;
+ }
+ }
+
+ /*==========================================================
+ * private methods
+ *==========================================================*/
+
+ /*
+ * handle request completion (cert issued) notification config requests
+ */
+ private void getNotificationCompConfig(HttpServletRequest req,
+ HttpServletResponse resp, IConfigStore rc) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_ENABLE))
+ continue;
+ params.put(name, rc.getString(name, ""));
+ }
+
+ params.put(Constants.PR_ENABLE,
+ rc.getString(PROP_ENABLED, Constants.FALSE));
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void getNotificationRevCompConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ IConfigStore config = mCA.getConfigStore();
+ IConfigStore nc =
+ config.getSubStore(ICertificateAuthority.PROP_NOTIFY_SUBSTORE);
+ IConfigStore rc = nc.getSubStore(ICertificateAuthority.PROP_CERT_REVOKED_SUBSTORE);
+
+ getNotificationCompConfig(req, resp, rc);
+ }
+
+ private void getNotificationReqCompConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ IConfigStore config = mCA.getConfigStore();
+ IConfigStore nc =
+ config.getSubStore(ICertificateAuthority.PROP_NOTIFY_SUBSTORE);
+ IConfigStore rc = nc.getSubStore(ICertificateAuthority.PROP_CERT_ISSUED_SUBSTORE);
+
+ getNotificationCompConfig(req, resp, rc);
+ }
+
+ /*
+ * handle getting request in queue notification config info
+ */
+ private void getNotificationRIQConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+
+ IConfigStore config = mCA.getConfigStore();
+ IConfigStore nc =
+ config.getSubStore(ICertificateAuthority.PROP_NOTIFY_SUBSTORE);
+
+ IConfigStore riq = nc.getSubStore(ICertificateAuthority.PROP_REQ_IN_Q_SUBSTORE);
+
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_ENABLE))
+ continue;
+ params.put(name, riq.getString(name, ""));
+ }
+
+ params.put(Constants.PR_ENABLE,
+ riq.getString(PROP_ENABLED, Constants.FALSE));
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /*
+ * handle setting request in queue notification config info
+ */
+ private void setNotificationRIQConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ IConfigStore config = mCA.getConfigStore();
+ IConfigStore nc =
+ config.getSubStore(ICertificateAuthority.PROP_NOTIFY_SUBSTORE);
+
+ IConfigStore riq = nc.getSubStore(ICertificateAuthority.PROP_REQ_IN_Q_SUBSTORE);
+
+ //set rest of the parameters
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_ENABLE))
+ continue;
+ String val = req.getParameter(name);
+
+ // if it's emailTemplate, check to see if the path exists
+ if (name.equalsIgnoreCase(PROP_EMAIL_TEMPLATE)) {
+ File template = new File(val);
+
+ if ((!template.exists()) || (!template.canRead())
+ || (template.isDirectory())) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_INVALID_PATH"));
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PATH"),
+ null, resp);
+ return;
+ }
+ }
+ riq.putString(name, val);
+ mCA.getRequestInQListener().set(name, val);
+ }
+
+ // set enable flag
+ String enabledString = req.getParameter(Constants.PR_ENABLE);
+
+ riq.putString(PROP_ENABLED, enabledString);
+ mCA.getRequestInQListener().set(PROP_ENABLED, enabledString);
+
+ commit(true);
+
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ /*
+ * handle setting request complete notification config info
+ */
+ private void setNotificationCompConfig(HttpServletRequest req,
+ HttpServletResponse resp, IConfigStore rc, IRequestListener thisListener) throws ServletException,
+ IOException, EBaseException {
+
+ //set rest of the parameters
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_ENABLE))
+ continue;
+ String val = req.getParameter(name);
+
+ // if it's emailTemplate, check to see if the path exists
+ if (name.equalsIgnoreCase(PROP_EMAIL_TEMPLATE)) {
+ File template = new File(val);
+
+ if ((!template.exists()) || (!template.canRead())
+ || (template.isDirectory())) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_INVALID_PATH"));
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PATH"),
+ null, resp);
+ return;
+ }
+ }
+ rc.putString(name, val);
+ thisListener.set(name, val);
+ }
+
+ // set enable flag
+ String enabledString = req.getParameter(Constants.PR_ENABLE);
+
+ rc.putString(PROP_ENABLED, enabledString);
+ thisListener.set(PROP_ENABLED, enabledString);
+
+ commit(true);
+
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ private void setNotificationRevCompConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ IConfigStore config = mCA.getConfigStore();
+ IConfigStore nc =
+ config.getSubStore(ICertificateAuthority.PROP_NOTIFY_SUBSTORE);
+
+ IConfigStore rc = nc.getSubStore(ICertificateAuthority.PROP_CERT_REVOKED_SUBSTORE);
+
+ setNotificationCompConfig(req, resp, rc, mCA.getCertRevokedListener());
+ }
+
+ private void setNotificationReqCompConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ IConfigStore config = mCA.getConfigStore();
+ IConfigStore nc =
+ config.getSubStore(ICertificateAuthority.PROP_NOTIFY_SUBSTORE);
+
+ IConfigStore rc = nc.getSubStore(ICertificateAuthority.PROP_CERT_ISSUED_SUBSTORE);
+
+ setNotificationCompConfig(req, resp, rc, mCA.getCertIssuedListener());
+
+ }
+
+ private void listCRLIPsConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+
+ Enumeration<ICRLIssuingPoint> ips = mCA.getCRLIssuingPoints();
+
+ while (ips.hasMoreElements()) {
+ ICRLIssuingPoint ip = ips.nextElement();
+
+ if (ip != null) {
+ String ipId = ip.getId();
+
+ if (ipId != null && ipId.length() > 0)
+ params.put(ipId, ip.getDescription());
+ params.put(ipId + "." + Constants.PR_ENABLED,
+ (Boolean.valueOf(ip.isCRLIssuingPointEnabled())).toString());
+ }
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void getCRLIPsConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id != null && id.length() > 0) {
+ ICRLIssuingPoint ip = mCA.getCRLIssuingPoint(id);
+
+ if (ip != null) {
+
+ Enumeration<String> e = req.getParameterNames();
+ String value = "";
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.PR_ENABLED)) {
+ if (ip.isCRLIssuingPointEnabled()) {
+ value = Constants.TRUE;
+ } else {
+ value = Constants.FALSE;
+ }
+ }
+ if (name.equals(Constants.PR_ID))
+ value = id;
+ if (name.equals(Constants.PR_DESCRIPTION))
+ value = ip.getDescription();
+ if (name.equals(Constants.PR_CLASS))
+ value = ip.getClass().getName();
+
+ params.put(name, value);
+ }
+ }
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * Add CRL issuing points configuration
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE used when configuring CRL profile (extensions,
+ * frequency, CRL format)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private void addCRLIPsConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ NameValuePairs params = new NameValuePairs();
+
+ String ipId = req.getParameter(Constants.PR_ID);
+
+ if (ipId == null || ipId.length() == 0) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, "Missing CRL IP name", null, resp);
+ return;
+ }
+ params.put(Constants.PR_ID, ipId);
+
+ String desc = req.getParameter(Constants.PR_DESCRIPTION);
+
+ if (desc == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, "Missing CRL IP description", null, resp);
+ return;
+ }
+ params.put(Constants.PR_DESCRIPTION, desc);
+
+ String sEnable = req.getParameter(Constants.PR_ENABLED);
+ boolean enable = true;
+
+ if (sEnable != null && sEnable.length() > 0 &&
+ sEnable.equalsIgnoreCase(Constants.FALSE)) {
+ enable = false;
+ params.put(Constants.PR_ENABLED, Constants.FALSE);
+ } else {
+ params.put(Constants.PR_ENABLED, Constants.TRUE);
+ }
+
+ IConfigStore crlSubStore =
+ mCA.getConfigStore().getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE);
+ Enumeration<String> crlNames = crlSubStore.getSubStoreNames();
+
+ while (crlNames.hasMoreElements()) {
+ String name = crlNames.nextElement();
+
+ if (ipId.equals(name)) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, ipId + " CRL IP already exists", null, resp);
+ return;
+ }
+ }
+ if (!mCA.addCRLIssuingPoint(crlSubStore, ipId, enable, desc)) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, "Cannot add or edit CRL IP", null, resp);
+ return;
+ }
+ commit(true);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * Set CRL issuing points configuration
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE used when configuring CRL profile (extensions,
+ * frequency, CRL format)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private void setCRLIPsConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ NameValuePairs params = new NameValuePairs();
+
+ String ipId = req.getParameter(Constants.PR_ID);
+
+ if (ipId == null || ipId.length() == 0) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, "Missing CRL IP name", null, resp);
+ return;
+ }
+ params.put(Constants.PR_ID, ipId);
+
+ String desc = req.getParameter(Constants.PR_DESCRIPTION);
+
+ if (desc == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, "Missing CRL IP description", null, resp);
+ return;
+ }
+ params.put(Constants.PR_DESCRIPTION, desc);
+
+ String sEnable = req.getParameter(Constants.PR_ENABLED);
+ boolean enable = true;
+
+ if (sEnable != null && sEnable.length() > 0 &&
+ sEnable.equalsIgnoreCase(Constants.FALSE)) {
+ enable = false;
+ params.put(Constants.PR_ENABLED, Constants.FALSE);
+ } else {
+ params.put(Constants.PR_ENABLED, Constants.TRUE);
+ }
+
+ IConfigStore crlSubStore =
+ mCA.getConfigStore().getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE);
+ boolean done = false;
+ Enumeration<String> crlNames = crlSubStore.getSubStoreNames();
+
+ while (crlNames.hasMoreElements()) {
+ String name = crlNames.nextElement();
+
+ if (ipId.equals(name)) {
+ ICRLIssuingPoint ip = mCA.getCRLIssuingPoint(ipId);
+
+ if (ip != null) {
+ ip.setDescription(desc);
+ ip.enableCRLIssuingPoint(enable);
+ }
+ IConfigStore c = crlSubStore.getSubStore(ipId);
+
+ if (c != null) {
+ c.putString(Constants.PR_DESCRIPTION, desc);
+ c.putString(Constants.PR_ENABLED,
+ (enable) ? Constants.TRUE : Constants.FALSE);
+ }
+ done = true;
+ break;
+ }
+ }
+ if (!done) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, "Missing CRL IP " + ipId, null, resp);
+ return;
+ }
+ commit(true);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * Delete CRL issuing points configuration
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE used when configuring CRL profile (extensions,
+ * frequency, CRL format)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private void deleteCRLIPsConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ NameValuePairs params = new NameValuePairs();
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id != null && id.length() > 0) {
+ IConfigStore crlSubStore =
+ mCA.getConfigStore().getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE);
+ boolean done = false;
+ Enumeration<String> crlNames = crlSubStore.getSubStoreNames();
+
+ while (crlNames.hasMoreElements()) {
+ String name = crlNames.nextElement();
+
+ if (id.equals(name)) {
+ mCA.deleteCRLIssuingPoint(crlSubStore, id);
+ done = true;
+ break;
+ }
+ }
+ if (!done) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, "Missing CRL IP " + id, null, resp);
+ return;
+ }
+ commit(true);
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ private void getCRLExtsConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+
+ String ipId = null;
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ ipId = name;
+ }
+ if (ipId == null || ipId.length() <= 0) {
+ ipId = ICertificateAuthority.PROP_MASTER_CRL;
+ }
+
+ ICRLIssuingPoint ip = mCA.getCRLIssuingPoint(ipId);
+ ICMSCRLExtensions crlExts = ip.getCRLExtensions();
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id != null) {
+ params = crlExts.getConfigParams(id);
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * Delete CRL extensions configuration
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE used when configuring CRL profile (extensions,
+ * frequency, CRL format)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private void setCRLExtsConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ NameValuePairs params = new NameValuePairs();
+
+ String ipId = req.getParameter(Constants.PR_ID);
+
+ if (ipId == null || ipId.length() <= 0) {
+ ipId = ICertificateAuthority.PROP_MASTER_CRL;
+ }
+
+ ICRLIssuingPoint ip = mCA.getCRLIssuingPoint(ipId);
+ ICMSCRLExtensions crlExts = ip.getCRLExtensions();
+
+ IConfigStore config = mCA.getConfigStore();
+ IConfigStore crlsSubStore =
+ config.getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE);
+ IConfigStore crlSubStore = crlsSubStore.getSubStore(ipId);
+ IConfigStore crlExtsSubStore =
+ crlSubStore.getSubStore(ICertificateAuthority.PROP_CRLEXT_SUBSTORE);
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id != null) {
+ IConfigStore crlExtSubStore = crlExtsSubStore.getSubStore(id);
+
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_CRLEXT_IMPL_NAME))
+ continue;
+ if (name.equals("RULENAME"))
+ continue;
+ String value = req.getParameter(name);
+
+ params.put(name, value);
+ }
+ crlExts.setConfigParams(id, params, crlExtSubStore);
+ commit(true);
+ ip.clearCRLCache();
+ ip.updateCRLCacheRepository();
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, null, resp);
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ private void listCRLExtsConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+
+ String id = req.getParameter(Constants.PR_ID);
+
+ if (id == null || id.length() <= 0) {
+ id = ICertificateAuthority.PROP_MASTER_CRL;
+ }
+
+ IConfigStore config = mCA.getConfigStore();
+ IConfigStore crlsSubStore = config.getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE);
+ IConfigStore crlSubStore = crlsSubStore.getSubStore(id);
+ IConfigStore crlExtsSubStore = crlSubStore.getSubStore(ICertificateAuthority.PROP_CRLEXT_SUBSTORE);
+
+ if (crlExtsSubStore != null) {
+ Enumeration<String> enumExts = crlExtsSubStore.getSubStoreNames();
+
+ while (enumExts.hasMoreElements()) {
+ String extName = enumExts.nextElement();
+ boolean crlExtEnabled = false;
+ IConfigStore crlExtSubStore = crlExtsSubStore.getSubStore(extName);
+ Enumeration<String> properties = crlExtSubStore.getPropertyNames();
+
+ while (properties.hasMoreElements()) {
+ String name = properties.nextElement();
+
+ if (name.equals(Constants.PR_ENABLE)) {
+ crlExtEnabled = crlExtSubStore.getBoolean(name, false);
+ }
+ }
+ params.put(extName, extName + ";visible;" + ((crlExtEnabled) ? "enabled" : "disabled"));
+ }
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * retrieve extended plugin info such as brief description,
+ * type info from CRL extensions
+ */
+ private void getExtendedPluginInfo(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String id = req.getParameter(Constants.RS_ID);
+ int colon = id.indexOf(':');
+
+ String implType = id.substring(0, colon);
+ String implName = id.substring(colon + 1);
+
+ NameValuePairs params =
+ getExtendedPluginInfo(getLocale(req), implType, implName);
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private NameValuePairs getExtendedPluginInfo(Locale locale, String implType, String implName) {
+ IExtendedPluginInfo ext_info = null;
+ Object impl = null;
+
+ String ipId = null;
+ String name = null;
+
+ Enumeration<ICRLIssuingPoint> ips = mCA.getCRLIssuingPoints();
+ if (ips.hasMoreElements()) {
+ ICRLIssuingPoint ip = ips.nextElement();
+ if (ip != null) {
+ ipId = ip.getId();
+ }
+ }
+ if (ipId != null) {
+ ICRLIssuingPoint ip = mCA.getCRLIssuingPoint(ipId);
+ ICMSCRLExtensions crlExts = ip.getCRLExtensions();
+ name = crlExts.getClassPath(implName);
+ }
+ if (name != null) {
+ impl = getClassByNameAsExtendedPluginInfo(name);
+ }
+ if (impl != null) {
+ if (impl instanceof IExtendedPluginInfo) {
+ ext_info = (IExtendedPluginInfo) impl;
+ }
+ }
+
+ NameValuePairs nvps = null;
+
+ if (ext_info == null) {
+ nvps = new NameValuePairs();
+ } else {
+ nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale));
+ }
+
+ return nvps;
+ }
+
+ /**
+ * Set CRL configuration
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE used when configuring CRL profile (extensions,
+ * frequency, CRL format)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private void setCRLConfig(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ NameValuePairs params = new NameValuePairs();
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null || id.length() <= 0 ||
+ id.equals(Constants.RS_ID_CONFIG)) {
+ id = ICertificateAuthority.PROP_MASTER_CRL;
+ }
+ ICRLIssuingPoint ip = mCA.getCRLIssuingPoint(id);
+
+ //Save New Settings to the config file
+ IConfigStore config = mCA.getConfigStore();
+ IConfigStore crlsSubStore = config.getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE);
+ IConfigStore crlSubStore = crlsSubStore.getSubStore(id);
+
+ //set reset of the parameters
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_ENABLE))
+ continue;
+ String value = req.getParameter(name);
+
+ params.put(name, value);
+ crlSubStore.putString(name, value);
+ }
+ boolean noRestart = ip.updateConfig(params);
+
+ commit(true);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ if (noRestart)
+ sendResponse(SUCCESS, null, null, resp);
+ else
+ sendResponse(RESTART, null, null, resp);
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ private void getCRLConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null || id.length() <= 0 ||
+ id.equals(Constants.RS_ID_CONFIG)) {
+ id = ICertificateAuthority.PROP_MASTER_CRL;
+ }
+ IConfigStore crlsSubStore =
+ mCA.getConfigStore().getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE);
+ IConfigStore crlSubStore = crlsSubStore.getSubStore(id);
+
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_ENABLE))
+ continue;
+ params.put(name, crlSubStore.getString(name, ""));
+ }
+
+ getSigningAlgConfig(params);
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void getConnectorConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ IConfigStore caConfig = mCA.getConfigStore();
+ IConfigStore connectorConfig = caConfig.getSubStore("connector");
+ IConfigStore caConnectorConfig = null;
+
+ if (isKRAConnector(req)) {
+ caConnectorConfig = connectorConfig.getSubStore("KRA");
+ } else if (isCLAConnector(req)) {
+ caConnectorConfig = connectorConfig.getSubStore("CLA");
+ }
+
+ Enumeration<String> enum1 = req.getParameterNames();
+ NameValuePairs params = new NameValuePairs();
+
+ if (caConnectorConfig != null) {
+ while (enum1.hasMoreElements()) {
+ String name = enum1.nextElement();
+
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+
+ params.put(name, caConnectorConfig.getString(name, ""));
+ }
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void setConnectorConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ IConfigStore caConfig = mCA.getConfigStore();
+ IConfigStore connectorConfig = caConfig.getSubStore("connector");
+ IConfigStore caConnectorConfig = null;
+
+ // String nickname = CMS.getServerCertNickname();
+
+ if (isKRAConnector(req)) {
+ caConnectorConfig = connectorConfig.getSubStore("KRA");
+ } else if (isCLAConnector(req)) {
+ caConnectorConfig = connectorConfig.getSubStore("CLA");
+ }
+
+ Enumeration<String> enum1 = req.getParameterNames();
+
+ if (caConnectorConfig != null) {
+ while (enum1.hasMoreElements()) {
+ String name = enum1.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ /*
+ if (name.equals("nickName")) {
+ caConnectorConfig.putString(name, nickname);
+ continue;
+ }
+ */
+ if (name.equals("host")) {
+ try {
+ Utils.checkHost(req.getParameter("host"));
+ } catch (UnknownHostException e) {
+ sendResponse(ERROR, "Unknown Host " + req.getParameter("host"), null, resp);
+ return;
+ }
+ }
+ caConnectorConfig.putString(name, req.getParameter(name));
+ }
+ }
+
+ commit(true);
+ sendResponse(RESTART, null, null, resp);
+ }
+
+ private boolean isKRAConnector(HttpServletRequest req) {
+ Enumeration<String> enum1 = req.getParameterNames();
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+
+ if (key.equals("RS_ID")) {
+ String val = req.getParameter(key);
+
+ if (val.equals("Data Recovery Manager Connector"))
+ return true;
+ else
+ return false;
+ }
+ }
+ return false;
+ }
+
+ private boolean isCLAConnector(HttpServletRequest req) {
+ Enumeration<String> enum1 = req.getParameterNames();
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+
+ if (key.equals("RS_ID")) {
+ String val = req.getParameter(key);
+
+ if (val.equals("Clone Master Manager Connector"))
+ return true;
+ else
+ return false;
+ }
+ }
+ return false;
+ }
+
+ private void getGeneralConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ String value = "false";
+
+ /*
+ ISubsystem eeGateway =
+ SubsystemRegistry.getInstance().get("eeGateway");
+ if (eeGateway != null) {
+ IConfigStore eeConfig = eeGateway.getConfigStore();
+ if (eeConfig != null)
+ value = eeConfig.getString("enabled", "true");
+ String ocspValue = "true";
+ ocspValue = eeConfig.getString("enableOCSP", "true");
+ params.add(Constants.PR_OCSP_ENABLED, ocspValue);
+ }
+ params.add(Constants.PR_EE_ENABLED, value);
+ */
+
+ IConfigStore caConfig = mCA.getConfigStore();
+
+ value = caConfig.getString(ICertificateAuthority.PROP_ENABLE_PAST_CATIME, "false");
+ params.put(Constants.PR_VALIDITY, value);
+
+ getSigningAlgConfig(params);
+ getSerialConfig(params);
+ getMaxSerialConfig(params);
+ params.put(Constants.PR_SN_MANAGEMENT,
+ Boolean.toString(mCA.getDBSubsystem().getEnableSerialMgmt()));
+ params.put(Constants.PR_RANDOM_SN,
+ Boolean.toString(mCA.getCertificateRepository().getEnableRandomSerialNumbers()));
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void getSigningAlgConfig(NameValuePairs params) {
+ params.put(Constants.PR_DEFAULT_ALGORITHM,
+ mCA.getDefaultAlgorithm());
+ String[] algorithms = mCA.getCASigningAlgorithms();
+ StringBuffer algorStr = new StringBuffer();
+
+ for (int i = 0; i < algorithms.length; i++) {
+ if (i == 0)
+ algorStr.append(algorithms[i]);
+ else {
+ algorStr.append(":");
+ algorStr.append(algorithms[i]);
+ }
+ }
+ params.put(Constants.PR_ALL_ALGORITHMS, algorStr.toString());
+ }
+
+ private void getSerialConfig(NameValuePairs params) {
+ params.put(Constants.PR_SERIAL,
+ mCA.getStartSerial());
+ }
+
+ private void getMaxSerialConfig(NameValuePairs params) {
+ params.put(Constants.PR_MAXSERIAL,
+ mCA.getMaxSerial());
+ }
+
+ private void setGeneralConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ /*
+ ISubsystem eeGateway =
+ SubsystemRegistry.getInstance().get("eeGateway");
+ */
+
+ Enumeration<String> enum1 = req.getParameterNames();
+ boolean restart = false;
+
+ //mCA.setMaxSerial("");
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.PR_EE_ENABLED)) {
+
+ /*
+ if (eeConfig != null) {
+ if (((EEGateway)eeGateway).isEnabled() &&
+ value.equals("false") ||
+ !((EEGateway)eeGateway).isEnabled() &&
+ value.equals("true")) {
+ restart=true;;
+ }
+ eeConfig.putString("enabled", value);
+ }
+ */
+ } else if (key.equals(Constants.PR_VALIDITY)) {
+ mCA.setValidity(value);
+ } else if (key.equals(Constants.PR_DEFAULT_ALGORITHM)) {
+ mCA.setDefaultAlgorithm(value);
+ } else if (key.equals(Constants.PR_SERIAL)) {
+ mCA.setStartSerial(value);
+ } else if (key.equals(Constants.PR_MAXSERIAL)) {
+ mCA.setMaxSerial(value);
+ } else if (key.equals(Constants.PR_SN_MANAGEMENT)) {
+ mCA.getDBSubsystem().setEnableSerialMgmt(Boolean.valueOf(value));
+ } else if (key.equals(Constants.PR_RANDOM_SN)) {
+ mCA.getCertificateRepository().setEnableRandomSerialNumbers(Boolean.valueOf(value), true, false);
+ }
+ }
+
+ commit(true);
+ if (restart)
+ sendResponse(RESTART, null, null, resp);
+ else
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, "CAAdminServlet: " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java
new file mode 100644
index 000000000..74c1a94a6
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java
@@ -0,0 +1,3424 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.PQGParams;
+import org.mozilla.jss.crypto.SignatureAlgorithm;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.util.ConsolePasswordCallback;
+import org.mozilla.jss.util.PasswordCallback;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.cert.ICrossCertPairSubsystem;
+import com.netscape.certsrv.common.ConfigConstants;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ocsp.IOCSPAuthority;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.security.ICryptoSubsystem;
+import com.netscape.certsrv.security.ISigningUnit;
+import com.netscape.certsrv.security.KeyCertData;
+import com.netscape.certsrv.selftests.EMissingSelfTestException;
+import com.netscape.certsrv.selftests.ESelfTestException;
+import com.netscape.certsrv.selftests.ISelfTest;
+import com.netscape.certsrv.selftests.ISelfTestSubsystem;
+import com.netscape.certsrv.tks.ITKSAuthority;
+import com.netscape.cmsutil.util.Cert;
+import com.netscape.cmsutil.util.Utils;
+import com.netscape.symkey.SessionKey;
+
+/**
+ * A class representings an administration servlet. This
+ * servlet is responsible to serve Certificate Server
+ * level administrative operations such as configuration
+ * parameter updates.
+ *
+ * @version $Revision$, $Date$
+ */
+public final class CMSAdminServlet extends AdminServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 714370238027440050L;
+ private final static String INFO = "CMSAdminServlet";
+ private final static String BEGIN_HEADER = "-----BEGIN CERTIFICATE-----";
+ private final static String END_HEADER = "-----END CERTIFICATE-----";
+
+ private final static String PROP_DB = "dbs";
+ private final static String PROP_SMTP = "smtp";
+ private final static String PROP_INTERNAL_DB = "internaldb";
+
+ private ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+ private final static byte EOL[] = { Character.LINE_SEPARATOR };
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION =
+ "LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION_3";
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY =
+ "LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY_3";
+ private final static String LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC =
+ "LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC_3";
+ private final static String LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION =
+ "LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION_2";
+ private final static String LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION =
+ "LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION_3";
+
+ // CMS must be instantiated before this admin servlet.
+
+ /**
+ * Constructs CA servlet.
+ */
+ public CMSAdminServlet() {
+ super();
+ }
+
+ /**
+ * Initializes this servlet.
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Serves HTTP request.
+ */
+ public void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+ try {
+ super.authenticate(req);
+ } catch (IOException e) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHS_FAILED"),
+ null, resp);
+ return;
+ }
+
+ String scope = req.getParameter(Constants.OP_SCOPE);
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ try {
+ AUTHZ_RES_NAME = "certServer.general.configuration";
+ if (scope.equals(ScopeDef.SC_PLATFORM)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ getEnv(req, resp);
+ return;
+ }
+ if (op.equals(OpDef.OP_READ)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_LDAP))
+ getDBConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_SMTP))
+ readSMTPConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_STAT))
+ readStat(req, resp);
+ else if (scope.equals(ScopeDef.SC_ENCRYPTION))
+ readEncryption(req, resp);
+ else if (scope.equals(ScopeDef.SC_TOKEN))
+ getAllTokenNames(req, resp);
+ else if (scope.equals(ScopeDef.SC_SUBJECT_NAME))
+ getSubjectName(req, resp);
+ else if (scope.equals(ScopeDef.SC_GET_NICKNAMES))
+ getAllNicknames(req, resp);
+ else if (scope.equals(ScopeDef.SC_CERT_PRETTY_PRINT))
+ getCertPrettyPrint(req, resp);
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_LDAP))
+ setDBConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_SMTP))
+ modifySMTPConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_TASKS))
+ performTasks(req, resp);
+ else if (scope.equals(ScopeDef.SC_ENCRYPTION))
+ modifyEncryption(req, resp);
+ else if (scope.equals(ScopeDef.SC_ISSUE_IMPORT_CERT))
+ issueImportCert(req, resp);
+ else if (scope.equals(ScopeDef.SC_INSTALL_CERT))
+ installCert(req, resp);
+ else if (scope.equals(ScopeDef.SC_IMPORT_CROSS_CERT))
+ importXCert(req, resp);
+ else if (scope.equals(ScopeDef.SC_DELETE_CERTS))
+ deleteCerts(req, resp);
+ else if (scope.equals(ScopeDef.SC_TRUST))
+ trustCACert(req, resp);
+ else if (scope.equals(ScopeDef.SC_TOKEN_LOGON))
+ loggedInToken(req, resp);
+ else if (scope.equals(ScopeDef.SC_ROOTCERT_TRUSTBIT))
+ setRootCertTrust(req, resp);
+ } else if (op.equals(OpDef.OP_SEARCH)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_SUBSYSTEM))
+ readSubsystem(req, resp);
+ else if (scope.equals(ScopeDef.SC_CA_CERTLIST))
+ getCACerts(req, resp);
+ else if (scope.equals(ScopeDef.SC_ALL_CERTLIST))
+ getAllCertsManage(req, resp);
+ else if (scope.equals(ScopeDef.SC_USERCERTSLIST))
+ getUserCerts(req, resp);
+ else if (scope.equals(ScopeDef.SC_TKSKEYSLIST))
+ getTKSKeys(req, resp);
+ else if (scope.equals(ScopeDef.SC_TOKEN))
+ getAllTokenNames(req, resp);
+ else if (scope.equals(ScopeDef.SC_ROOTCERTSLIST))
+ getRootCerts(req, resp);
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ mOp = "delete";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_ROOTCERTSLIST)) {
+ deleteRootCert(req, resp);
+ } else if (scope.equals(ScopeDef.SC_USERCERTSLIST)) {
+ deleteUserCert(req, resp);
+ }
+ } else if (op.equals(OpDef.OP_PROCESS)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_CERT_REQUEST))
+ getCertRequest(req, resp);
+ else if (scope.equals(ScopeDef.SC_SUBJECT_NAME))
+ processSubjectName(req, resp);
+ else if (scope.equals(ScopeDef.SC_CERTINFO))
+ getCertInfo(req, resp);
+ else if (scope.equals(ScopeDef.SC_CERT_PRETTY_PRINT))
+ getCertPrettyPrint(req, resp);
+ else if (scope.equals(ScopeDef.SC_ROOTCERT_TRUSTBIT))
+ getRootCertTrustBit(req, resp);
+ else if (scope.equals(ScopeDef.SC_TOKEN_STATUS))
+ checkTokenStatus(req, resp);
+ else if (scope.equals(ScopeDef.SC_SELFTESTS))
+ runSelfTestsOnDemand(req, resp);
+ else if (scope.equals(ScopeDef.SC_TKSKEYSLIST))
+ createMasterKey(req, resp);
+ } else if (op.equals(OpDef.OP_VALIDATE)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_SUBJECT_NAME))
+ validateSubjectName(req, resp);
+ else if (scope.equals(ScopeDef.SC_KEY_LENGTH))
+ validateKeyLength(req, resp);
+ else if (scope.equals(ScopeDef.SC_CERTIFICATE_EXTENSION))
+ validateCertExtension(req, resp);
+ else if (scope.equals(ScopeDef.SC_KEY_CURVENAME))
+ validateCurveName(req, resp);
+ }
+ } catch (EBaseException e) {
+ sendResponse(ERROR, e.toString(getLocale(req)),
+ null, resp);
+ return;
+ } catch (Exception e) {
+ StringWriter sw = new StringWriter();
+
+ e.printStackTrace(new PrintWriter(sw));
+
+ sendResponse(1, "operation failure", null, resp);
+ return;
+ }
+ }
+
+ private void getEnv(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+
+ if (File.separator.equals("\\"))
+ params.put(Constants.PR_NT, Constants.TRUE);
+ else
+ params.put(Constants.PR_NT, Constants.FALSE);
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void getAllTokenNames(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_TOKEN_LIST, jssSubSystem.getTokenList());
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void getAllNicknames(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+
+ params.put(Constants.PR_ALL_NICKNAMES, jssSubSystem.getAllCerts());
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private boolean isSubsystemInstalled(String subsystem) {
+ Enumeration<ISubsystem> e = CMS.getSubsystems();
+
+ while (e.hasMoreElements()) {
+ ISubsystem sys = e.nextElement();
+
+ //get subsystem type
+ if ((sys instanceof IKeyRecoveryAuthority) &&
+ subsystem.equals("kra"))
+ return true;
+ else if ((sys instanceof IRegistrationAuthority) &&
+ subsystem.equals("ra"))
+ return true;
+ else if ((sys instanceof ICertificateAuthority) &&
+ subsystem.equals("ca"))
+ return true;
+ else if ((sys instanceof IOCSPAuthority) &&
+ subsystem.equals("ocsp"))
+ return true;
+ }
+
+ return false;
+ }
+
+ private void readEncryption(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ Enumeration<ISubsystem> e = CMS.getSubsystems();
+ boolean isCAInstalled = false;
+ boolean isRAInstalled = false;
+ boolean isKRAInstalled = false;
+
+ while (e.hasMoreElements()) {
+ ISubsystem sys = e.nextElement();
+
+ //get subsystem type
+ if (sys instanceof IKeyRecoveryAuthority)
+ isKRAInstalled = true;
+ else if (sys instanceof IRegistrationAuthority)
+ isRAInstalled = true;
+ else if (sys instanceof ICertificateAuthority)
+ isCAInstalled = true;
+
+ }
+
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ String caTokenName = "";
+
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_CIPHER_VERSION,
+ jssSubSystem.getCipherVersion());
+ params.put(Constants.PR_CIPHER_FORTEZZA, jssSubSystem.isCipherFortezza());
+ params.put(Constants.PR_CIPHER_PREF, jssSubSystem.getCipherPreferences());
+
+ String tokenList = jssSubSystem.getTokenList();
+
+ String tokenNewList = "";
+ StringTokenizer tokenizer = new StringTokenizer(tokenList, ",");
+
+ while (tokenizer.hasMoreElements()) {
+ String tokenName = (String) tokenizer.nextElement();
+ String certs = jssSubSystem.getCertListWithoutTokenName(tokenName);
+
+ if (certs.equals(""))
+ continue;
+ if (tokenNewList.equals(""))
+ tokenNewList = tokenNewList + tokenName;
+ else
+ tokenNewList = tokenNewList + "," + tokenName;
+ tokenName = escapeString(tokenName);
+ params.put(Constants.PR_TOKEN_PREFIX + tokenName, certs);
+ }
+
+ params.put(Constants.PR_TOKEN_LIST, tokenNewList);
+
+ if (isCAInstalled) {
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ ISigningUnit signingUnit = ca.getSigningUnit();
+
+ caTokenName = signingUnit.getTokenName();
+
+ if (caTokenName.equals(jssSubSystem.getInternalTokenName()))
+ caTokenName = Constants.PR_INTERNAL_TOKEN;
+
+ String caNickName = signingUnit.getNickname();
+
+ //params.add(Constants.PR_CERT_CA, caTokenName+","+caNickName);
+ params.put(Constants.PR_CERT_CA, getCertNickname(caNickName));
+ }
+
+ if (isRAInstalled) {
+ IRegistrationAuthority ra = (IRegistrationAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_RA);
+ String raNickname = ra.getNickname();
+
+ params.put(Constants.PR_CERT_RA, getCertNickname(raNickname));
+ }
+
+ if (isKRAInstalled) {
+ IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_KRA);
+ String kraNickname = kra.getNickname();
+
+ params.put(Constants.PR_CERT_TRANS, getCertNickname(kraNickname));
+ }
+
+ String nickName = CMS.getServerCertNickname();
+
+ params.put(Constants.PR_CERT_SERVER, getCertNickname(nickName));
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private String escapeString(String name) {
+ StringTokenizer tokenizer = new StringTokenizer(name, " ");
+ StringBuffer tokenname = new StringBuffer();
+
+ if (tokenizer.countTokens() == 1)
+ return name;
+ while (tokenizer.hasMoreElements()) {
+ if (tokenizer.countTokens() == 1)
+ tokenname.append((String) tokenizer.nextElement());
+ else {
+ tokenname.append((String) tokenizer.nextElement());
+ tokenname.append("%20");
+ }
+ }
+
+ return tokenname.toString();
+ }
+
+ private String getCertNickname(String nickName) {
+ if (!nickName.equals("")) {
+ StringTokenizer tokenizer = new StringTokenizer(nickName, ":");
+ String tokenName = "";
+
+ if (tokenizer.countTokens() > 1) {
+ tokenName = (String) tokenizer.nextElement();
+ } else {
+ tokenName = Constants.PR_INTERNAL_TOKEN;
+ }
+ return tokenName + "," + ((String) tokenizer.nextElement());
+ }
+ return "";
+ }
+
+ /**
+ * Modify encryption configuration
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION used when configuring encryption (cert settings and SSL
+ * cipher preferences)
+ * </ul>
+ *
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException failed to modify encryption configuration
+ */
+ private void modifyEncryption(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ Enumeration<String> enum1 = req.getParameterNames();
+ NameValuePairs params = new NameValuePairs();
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+
+ jssSubSystem.getInternalTokenName();
+ Enumeration<ISubsystem> e = CMS.getSubsystems();
+ boolean isCAInstalled = false;
+ boolean isRAInstalled = false;
+ boolean isKRAInstalled = false;
+
+ while (e.hasMoreElements()) {
+ ISubsystem sys = e.nextElement();
+
+ //get subsystem type
+ if (sys instanceof IKeyRecoveryAuthority)
+ isKRAInstalled = true;
+ else if (sys instanceof IRegistrationAuthority)
+ isRAInstalled = true;
+ else if (sys instanceof ICertificateAuthority)
+ isCAInstalled = true;
+ }
+
+ ICertificateAuthority ca = null;
+ IRegistrationAuthority ra = null;
+ IKeyRecoveryAuthority kra = null;
+
+ if (isCAInstalled)
+ ca = (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ if (isRAInstalled)
+ ra = (IRegistrationAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_RA);
+ if (isKRAInstalled)
+ kra = (IKeyRecoveryAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_KRA);
+
+ boolean isCACert = true;
+
+ while (enum1.hasMoreElements()) {
+ String name = enum1.nextElement();
+ String val = req.getParameter(name);
+
+ if (name.equals(Constants.PR_CIPHER_PREF)) {
+ jssSubSystem.setCipherPreferences(val);
+ } else if (name.equals(Constants.PR_CERT_CA)) {
+ ISigningUnit signingUnit = ca.getSigningUnit();
+
+ if ((val != null) && (!val.equals(""))) {
+ StringTokenizer tokenizer = new StringTokenizer(val, ",");
+
+ if (tokenizer.countTokens() != 2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ throw new EBaseException(CMS.getLogMessage("BASE_INVALID_UI_INFO"));
+ }
+
+ String tokenName = (String) tokenizer.nextElement();
+ String nickName = (String) tokenizer.nextElement();
+
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN)) {
+ tokenName = jssSubSystem.getInternalTokenName();
+ } else {
+ nickName = tokenName + ":" + nickName;
+ }
+
+ isCACert = jssSubSystem.isCACert(nickName);
+ if (isCACert) {
+ signingUnit.updateConfig(nickName, tokenName);
+ } else
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ throw new EBaseException(CMS.getLogMessage("BASE_NOT_CA_CERT"));
+ }
+ } else if (name.equals(Constants.PR_CERT_RA)) {
+ if ((val != null) && (!val.equals(""))) {
+ String nickName = getCertConfigNickname(val);
+
+ ra.setNickname(nickName);
+ }
+ } else if (name.equals(Constants.PR_CERT_TRANS)) {
+ if ((val != null) && (!val.equals(""))) {
+ String nickName = getCertConfigNickname(val);
+
+ kra.setNickname(nickName);
+ }
+ } else if (name.equals(Constants.PR_CERT_SERVER)) {
+ if ((val != null) && (!val.equals(""))) {
+ String nickName = getCertConfigNickname(val);
+
+ modifyRADMCert(nickName);
+ modifyAgentGatewayCert(nickName);
+ if (isRAInstalled)
+ modifyEEGatewayCert(ra, nickName);
+ if (isCAInstalled)
+ modifyCAGatewayCert(ca, nickName);
+ }
+ }
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(RESTART, null, params, resp);
+ mConfig.commit(true);
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ private String getCertConfigNickname(String val) throws EBaseException {
+ StringTokenizer tokenizer = new StringTokenizer(val, ",");
+
+ if (tokenizer.countTokens() != 2) {
+ throw new EBaseException(CMS.getLogMessage("BASE_INVALID_UI_INFO"));
+ }
+ String tokenName = (String) tokenizer.nextElement();
+
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN))
+ tokenName = "";
+ else
+ tokenName = tokenName + ":";
+ return (tokenName + (String) tokenizer.nextElement());
+ }
+
+ private void modifyRADMCert(String nickName) {
+ CMS.setServerCertNickname(nickName);
+
+ /*
+ RemoteAdmin raAdmin = (RemoteAdmin)RemoteAdmin.getInstance();
+ HTTPService httpsService = raAdmin.getHttpsService();
+ httpsService.setNickName(nickName);
+ */
+ }
+
+ private void modifyAgentGatewayCert(String nickName) {
+ CMS.setServerCertNickname(nickName);
+
+ /*
+ AgentGateway gateway = (AgentGateway)mReg.get(AgentGateway.ID);
+ HTTPService httpsService = gateway.getHttpsService();
+ httpsService.setNickName(nickName);
+ */
+ }
+
+ private void modifyEEGatewayCert(IRegistrationAuthority ra, String nickName) {
+ CMS.setServerCertNickname(nickName);
+
+ /*
+ HTTPSubsystem eeGateway = ra.getHTTPSubsystem();
+ HTTPService httpsService = eeGateway.getHttpsService();
+ httpsService.setNickName(nickName);
+ */
+ }
+
+ private void modifyCAGatewayCert(ICertificateAuthority ca, String nickName) {
+ CMS.setServerCertNickname(nickName);
+
+ /*
+ HTTPSubsystem caGateway = ca.getHTTPSubsystem();
+ HTTPService httpsService = caGateway.getHttpsService();
+ httpsService.setNickName(nickName);
+ */
+ }
+
+ /**
+ * Performs Server Tasks: RESTART/STOP operation
+ */
+ private void performTasks(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String restart = req.getParameter(Constants.PR_SERVER_RESTART);
+ String stop = req.getParameter(Constants.PR_SERVER_STOP);
+ NameValuePairs params = new NameValuePairs();
+
+ if (restart != null) {
+ //XXX Uncommented afetr watchdog is implemented
+ sendResponse(SUCCESS, null, params, resp);
+ //mServer.restart();
+ return;
+ }
+
+ if (stop != null) {
+ //XXX Send response first then shutdown
+ sendResponse(SUCCESS, null, params, resp);
+ CMS.shutdown();
+ return;
+ }
+
+ sendResponse(ERROR, "Unknown operation", null, resp);
+
+ }
+
+ /**
+ * Reads subsystems that server has loaded with.
+ */
+ private void readSubsystem(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<ISubsystem> e = CMS.getSubsystems();
+
+ while (e.hasMoreElements()) {
+ String type = "";
+ ISubsystem sys = e.nextElement();
+
+ //get subsystem type
+ if (sys instanceof IKeyRecoveryAuthority)
+ type = Constants.PR_KRA_INSTANCE;
+ if (sys instanceof IRegistrationAuthority)
+ type = Constants.PR_RA_INSTANCE;
+ if (sys instanceof ICertificateAuthority)
+ type = Constants.PR_CA_INSTANCE;
+ if (sys instanceof IOCSPAuthority)
+ type = Constants.PR_OCSP_INSTANCE;
+ if (sys instanceof ITKSAuthority)
+ type = Constants.PR_TKS_INSTANCE;
+ if (!type.trim().equals(""))
+ params.put(sys.getId(), type);
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * Reads server statistics.
+ */
+ private void readStat(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String installdate = cs.getString(Constants.PR_STAT_INSTALLDATE, "");
+ params.put(Constants.PR_STAT_INSTALLDATE, installdate);
+ } catch (Exception e) {
+ }
+
+ try {
+ String version = cs.getString(Constants.PR_STAT_VERSION, "");
+ params.put(Constants.PR_STAT_VERSION, version);
+ } catch (Exception e) {
+ }
+
+ try {
+ String instanceId = cs.getString(Constants.PR_STAT_INSTANCEID, "");
+ params.put(Constants.PR_STAT_INSTANCEID, instanceId);
+ } catch (Exception e) {
+ }
+
+ params.put(Constants.PR_STAT_STARTUP,
+ (new Date(CMS.getStartupTime())).toString());
+ params.put(Constants.PR_STAT_TIME,
+ (new Date(System.currentTimeMillis())).toString());
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * Modifies database information.
+ */
+ private void setDBConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ IConfigStore dbConfig = mConfig.getSubStore(PROP_INTERNAL_DB);
+ Enumeration<String> enum1 = req.getParameterNames();
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+
+ if (key.equals(Constants.OP_TYPE))
+ continue;
+ if (key.equals(Constants.RS_ID))
+ continue;
+ if (key.equals(Constants.OP_SCOPE))
+ continue;
+
+ dbConfig.putString(key, req.getParameter(key));
+ }
+
+ sendResponse(RESTART, null, null, resp);
+ mConfig.commit(true);
+ }
+
+ /**
+ * Create Master Key
+ */
+ private void createMasterKey(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = req.getParameterNames();
+ String newKeyName = null, selectedToken = null;
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.PR_KEY_LIST)) {
+ newKeyName = req.getParameter(name);
+ }
+ if (name.equals(Constants.PR_TOKEN_LIST)) {
+ selectedToken = req.getParameter(name);
+ }
+
+ }
+ if (selectedToken != null && newKeyName != null) {
+ SessionKey.GenMasterKey(selectedToken, newKeyName); // check for errors
+ CMS.getConfigStore().putString("tks.defaultSlot", selectedToken);
+ String masterKeyPrefix = CMS.getConfigStore().getString("tks.master_key_prefix", null);
+
+ SessionKey.SetDefaultPrefix(masterKeyPrefix);
+ params.put(Constants.PR_KEY_LIST, newKeyName);
+ params.put(Constants.PR_TOKEN_LIST, selectedToken);
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * Reads secmod.db
+ */
+ private void getTKSKeys(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.PR_TOKEN_LIST)) {
+ String selectedToken = req.getParameter(name);
+
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+
+ CryptoToken token = null;
+ CryptoManager mCryptoManager = null;
+ try {
+ mCryptoManager = CryptoManager.getInstance();
+ } catch (Exception e2) {
+ }
+
+ if (!jssSubSystem.isTokenLoggedIn(selectedToken)) {
+ PasswordCallback cpcb = new ConsolePasswordCallback();
+ while (true) {
+ try {
+ token = mCryptoManager.getTokenByName(selectedToken);
+ token.login(cpcb);
+ break;
+ } catch (Exception e3) {
+ //log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_INCORRECT_PWD"));
+ continue;
+ }
+ }
+ }
+ // String symKeys = new String("key1,key2");
+ String symKeys = SessionKey.ListSymmetricKeys(selectedToken);
+ params.put(Constants.PR_TOKEN_LIST, symKeys);
+
+ }
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * Reads database information.
+ */
+ private void getDBConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ IConfigStore dbConfig = mConfig.getSubStore(PROP_DB);
+ IConfigStore ldapConfig = dbConfig.getSubStore("ldap");
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_SECURE_PORT_ENABLED))
+ params.put(name, ldapConfig.getString(name, "Constants.FALSE"));
+ else
+ params.put(name, ldapConfig.getString(name, ""));
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * Modifies SMTP configuration.
+ */
+ private void modifySMTPConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ // XXX
+ IConfigStore sConfig = mConfig.getSubStore(PROP_SMTP);
+
+ String host = req.getParameter(Constants.PR_SERVER_NAME);
+
+ if (host != null)
+ sConfig.putString("host", host);
+
+ String port = req.getParameter(Constants.PR_PORT);
+
+ if (port != null)
+ sConfig.putString("port", port);
+
+ commit(true);
+
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ /**
+ * Reads SMTP configuration.
+ */
+ private void readSMTPConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ IConfigStore dbConfig = mConfig.getSubStore(PROP_SMTP);
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_SERVER_NAME,
+ dbConfig.getString("host"));
+ params.put(Constants.PR_PORT,
+ dbConfig.getString("port"));
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void loggedInToken(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ Enumeration<String> enum1 = req.getParameterNames();
+ String tokenName = "";
+ String pwd = "";
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.PR_TOKEN_NAME)) {
+ tokenName = value;
+ } else if (key.equals(Constants.PR_TOKEN_PASSWD)) {
+ pwd = value;
+ }
+ }
+
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+
+ jssSubSystem.loggedInToken(tokenName, pwd);
+
+ /* Do a "PUT" of the new pw to the watchdog" */
+ CMS.putPasswordCache(tokenName, pwd);
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ private void checkTokenStatus(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ Enumeration<String> enum1 = req.getParameterNames();
+ String key = "";
+ String value = "";
+
+ while (enum1.hasMoreElements()) {
+ key = enum1.nextElement();
+ value = req.getParameter(key);
+ if (key.equals(Constants.PR_TOKEN_NAME)) {
+ break;
+ }
+ }
+
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ boolean status = jssSubSystem.isTokenLoggedIn(value);
+
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_LOGGED_IN, "" + status);
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * Retrieve a certificate request
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC used when asymmetric keys are generated
+ * </ul>
+ *
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException failed to retrieve certificate request
+ */
+ private void getCertRequest(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditPublicKey = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> enum1 = req.getParameterNames();
+ String tokenName = Constants.PR_INTERNAL_TOKEN_NAME;
+ String keyType = "";
+ int keyLength = 512;
+ String subjectName = "";
+ String certType = Constants.PR_CA_SIGNING_CERT;
+ String dir = "";
+ String pathname = "";
+ String otherNickname = "";
+ String keyCurveName = "";
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.PR_TOKEN_NAME)) {
+ if (!value.equals(Constants.PR_INTERNAL_TOKEN))
+ tokenName = value;
+ } else if (key.equals(Constants.PR_KEY_LENGTH)) {
+ keyLength = Integer.parseInt(value);
+ } else if (key.equals(Constants.PR_KEY_TYPE)) {
+ keyType = value;
+ } else if (key.equals(Constants.RS_ID)) {
+ certType = value;
+ } else if (key.equals(Constants.PR_SUBJECT_NAME)) {
+ subjectName = value;
+ } else if (key.equals(Constants.PR_NICKNAME)) {
+ otherNickname = value;
+ } else if (key.equals(Constants.PR_KEY_CURVENAME)) {
+ keyCurveName = value;
+ }
+ }
+
+ pathname = mConfig.getString("instanceRoot", "")
+ + File.separator + "conf" + File.separator;
+ dir = pathname;
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+
+ KeyPair keypair = null;
+ PQGParams pqgParams = null;
+ String nickname = "";
+
+ // other cert and has the existing key
+ if (certType.equals(Constants.PR_OTHER_CERT) && keyType.equals(""))
+ nickname = otherNickname;
+ else if (!certType.equals(Constants.PR_OTHER_CERT))
+ nickname = getNickname(certType);
+
+ String nicknameWithoutTokenName = "";
+
+ if (nickname != null && !nickname.equals("")) {
+ int index = nickname.indexOf(":");
+
+ nicknameWithoutTokenName = nickname;
+ if (index >= 0)
+ nicknameWithoutTokenName = nickname.substring(index + 1);
+ }
+
+ if (keyType.equals("")) {
+ if (nickname.equals("")) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditPublicKey);
+
+ audit(auditMessage);
+
+ throw new EBaseException(
+ CMS.getLogMessage("BASE_CERT_NOT_FOUND"));
+ }
+ keypair = jssSubSystem.getKeyPair(nickname);
+ } else {
+ if (keyType.equals("ECC")) {
+ // get ECC keypair
+ keypair = jssSubSystem.getECCKeyPair(tokenName, keyCurveName, certType);
+ } else { //DSA or RSA
+ if (keyType.equals("DSA"))
+ pqgParams = jssSubSystem.getPQG(keyLength);
+ keypair = jssSubSystem.getKeyPair(tokenName, keyType, keyLength, pqgParams);
+ }
+ }
+
+ // reset the "auditPublicKey"
+ auditPublicKey = auditPublicKey(keypair);
+
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT)) {
+ pathname = pathname + File.separator + "cacsr.txt";
+ if (!keyType.equals(""))
+ setCANewnickname(tokenName, nicknameWithoutTokenName);
+ } else if (certType.equals(Constants.PR_RA_SIGNING_CERT)) {
+ pathname = pathname + File.separator + "racsr.txt";
+ if (!keyType.equals(""))
+ setRANewnickname(tokenName, nicknameWithoutTokenName);
+ } else if (certType.equals(Constants.PR_OCSP_SIGNING_CERT)) {
+ pathname = pathname + File.separator + "ocspcsr.txt";
+ if (!keyType.equals(""))
+ setOCSPNewnickname(tokenName, nicknameWithoutTokenName);
+ } else if (certType.equals(Constants.PR_KRA_TRANSPORT_CERT)) {
+ pathname = pathname + File.separator + "kracsr.txt";
+ if (!keyType.equals(""))
+ setKRANewnickname(tokenName, nicknameWithoutTokenName);
+ } else if (certType.equals(Constants.PR_SERVER_CERT)) {
+ pathname = pathname + File.separator + "sslcsr.txt";
+ if (!keyType.equals(""))
+ setAgentNewnickname(tokenName, nicknameWithoutTokenName);
+ } else if (certType.equals(Constants.PR_SERVER_CERT_RADM)) {
+ pathname = pathname + File.separator + "sslcsrradm.txt";
+ if (!keyType.equals(""))
+ setRADMNewnickname(tokenName, nicknameWithoutTokenName);
+ } else if (certType.equals(Constants.PR_OTHER_CERT)) {
+ pathname = pathname + File.separator + "othercsr.txt";
+ }
+ String certReq = jssSubSystem.getCertRequest(subjectName, keypair);
+
+ params.put(Constants.PR_CSR, certReq);
+ params.put(Constants.PR_CERT_REQUEST_DIR, dir);
+ PrintStream ps = new PrintStream(new FileOutputStream(pathname));
+
+ ps.println(certReq);
+ ps.close();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditPublicKey);
+
+ audit(auditMessage);
+
+ mConfig.commit(true);
+ sendResponse(SUCCESS, null, params, resp);
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditPublicKey);
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditPublicKey);
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditPublicKey );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ private void setCANewnickname(String tokenName, String nickname)
+ throws EBaseException {
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ ISigningUnit signingUnit = ca.getSigningUnit();
+
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME))
+ signingUnit.setNewNickName(nickname);
+ else {
+ if (tokenName.equals("") && nickname.equals(""))
+ signingUnit.setNewNickName("");
+ else
+ signingUnit.setNewNickName(tokenName + ":" + nickname);
+ }
+ }
+
+ private String getCANewnickname() throws EBaseException {
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ ISigningUnit signingUnit = ca.getSigningUnit();
+
+ return signingUnit.getNewNickName();
+ }
+
+ private void setRANewnickname(String tokenName, String nickname)
+ throws EBaseException {
+ IRegistrationAuthority ra = (IRegistrationAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_RA);
+
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME))
+ ra.setNewNickName(nickname);
+ else {
+ if (tokenName.equals("") && nickname.equals(""))
+ ra.setNewNickName("");
+ else
+ ra.setNewNickName(tokenName + ":" + nickname);
+ }
+ }
+
+ private String getRANewnickname() throws EBaseException {
+ IRegistrationAuthority ra = (IRegistrationAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_RA);
+
+ return ra.getNewNickName();
+ }
+
+ private void setOCSPNewnickname(String tokenName, String nickname)
+ throws EBaseException {
+ IOCSPAuthority ocsp = (IOCSPAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_OCSP);
+
+ if (ocsp != null) {
+ ISigningUnit signingUnit = ocsp.getSigningUnit();
+
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME))
+ signingUnit.setNewNickName(nickname);
+ else {
+ if (tokenName.equals("") && nickname.equals(""))
+ signingUnit.setNewNickName("");
+ else
+ signingUnit.setNewNickName(tokenName + ":" + nickname);
+ }
+ } else {
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ ISigningUnit signingUnit = ca.getOCSPSigningUnit();
+
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME))
+ signingUnit.setNewNickName(nickname);
+ else {
+ if (tokenName.equals("") && nickname.equals(""))
+ signingUnit.setNewNickName("");
+ else
+ signingUnit.setNewNickName(tokenName + ":" + nickname);
+ }
+ }
+ }
+
+ private String getOCSPNewnickname() throws EBaseException {
+ IOCSPAuthority ocsp = (IOCSPAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_OCSP);
+
+ if (ocsp != null) {
+ ISigningUnit signingUnit = ocsp.getSigningUnit();
+
+ return signingUnit.getNewNickName();
+ } else {
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ ISigningUnit signingUnit = ca.getOCSPSigningUnit();
+
+ return signingUnit.getNewNickName();
+ }
+ }
+
+ private void setKRANewnickname(String tokenName, String nickname)
+ throws EBaseException {
+ IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_KRA);
+
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME))
+ kra.setNewNickName(nickname);
+ else {
+ if (tokenName.equals("") && nickname.equals(""))
+ kra.setNewNickName("");
+ else
+ kra.setNewNickName(tokenName + ":" + nickname);
+ }
+ }
+
+ private String getKRANewnickname() throws EBaseException {
+ IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_KRA);
+
+ return kra.getNewNickName();
+ }
+
+ private void setRADMNewnickname(String tokenName, String nickName)
+ throws EBaseException {
+ CMS.setServerCertNickname(tokenName, nickName);
+
+ /*
+ RemoteAdmin raAdmin = (RemoteAdmin)RemoteAdmin.getInstance();
+ HTTPService httpsService = raAdmin.getHttpsService();
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME))
+ httpsService.setNewNickName(nickName);
+ else {
+ if (tokenName.equals("") && nickName.equals(""))
+ httpsService.setNewNickName("");
+ else
+ httpsService.setNewNickName(tokenName+":"+nickName);
+ }
+ */
+ }
+
+ private String getRADMNewnickname()
+ throws EBaseException {
+ // assuming the nickname does not change.
+ return CMS.getServerCertNickname();
+
+ /*
+ RemoteAdmin raAdmin = (RemoteAdmin)RemoteAdmin.getInstance();
+ HTTPService httpsService = raAdmin.getHttpsService();
+ return httpsService.getNewNickName();
+ */
+ }
+
+ private void setAgentNewnickname(String tokenName, String nickName)
+ throws EBaseException {
+ CMS.setServerCertNickname(tokenName, nickName);
+
+ /*
+ AgentGateway gateway = (AgentGateway)mReg.get(AgentGateway.ID);
+ HTTPService httpsService = gateway.getHttpsService();
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME))
+ httpsService.setNewNickName(nickName);
+ else {
+ if (tokenName.equals("") && nickName.equals(""))
+ httpsService.setNewNickName("");
+ else
+ httpsService.setNewNickName(tokenName+":"+nickName);
+ }
+ */
+ }
+
+ private String getAgentNewnickname()
+ throws EBaseException {
+ // assuming the nickname does not change.
+ return CMS.getServerCertNickname();
+
+ /*
+ AgentGateway gateway = (AgentGateway)mReg.get(AgentGateway.ID);
+ HTTPService httpsService = gateway.getHttpsService();
+ return httpsService.getNewNickName();
+ */
+ }
+
+ /**
+ * Issue import certificate
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY used when "Certificate Setup Wizard" is used to
+ * import CA certs into the certificate database
+ * </ul>
+ *
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException failed to issue an import certificate
+ */
+ private void issueImportCert(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ Enumeration<String> enum1 = req.getParameterNames();
+ String tokenName = Constants.PR_INTERNAL_TOKEN_NAME;
+ String keyType = "RSA";
+ KeyCertData properties = new KeyCertData();
+
+ String newtokenname = null;
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (!key.equals("pathname")) {
+ if (key.equals(Constants.PR_TOKEN_NAME))
+ newtokenname = value;
+ properties.put(key, value);
+ }
+ }
+
+ String certType = (String) properties.get(Constants.RS_ID);
+
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ ICertificateRepository repository =
+ ca.getCertificateRepository();
+ ISigningUnit signingUnit = ca.getSigningUnit();
+ String oldtokenname = null;
+ //this is the old nick name
+ String nickname = getNickname(certType);
+ String nicknameWithoutTokenName = "";
+ String oldcatokenname = signingUnit.getTokenName();
+ String canickname = getNickname(Constants.PR_CA_SIGNING_CERT);
+ String canicknameWithoutTokenName = "";
+
+ int index = nickname.indexOf(":");
+
+ if (index == -1) {
+ nicknameWithoutTokenName = nickname;
+ oldtokenname = Constants.PR_INTERNAL_TOKEN_NAME;
+ } else if (index > 0 && (index < (nickname.length() - 1))) {
+ nicknameWithoutTokenName = nickname.substring(index + 1);
+ oldtokenname = nickname.substring(0, index);
+ } else {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ throw new EBaseException(CMS.getLogMessage("BASE_CERT_NOT_FOUND"));
+ }
+
+ if (newtokenname == null)
+ newtokenname = oldtokenname;
+ index = canickname.indexOf(":");
+ if (index == -1) {
+ canicknameWithoutTokenName = canickname;
+ } else if (index > 0 && (index < (canickname.length() - 1))) {
+ canicknameWithoutTokenName = canickname.substring(index + 1);
+ } else {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ throw new EBaseException(CMS.getLogMessage("BASE_CERT_NOT_FOUND"));
+ }
+
+ //xxx renew ca ,use old issuer?
+ properties.setIssuerName(
+ jssSubSystem.getCertSubjectName(oldcatokenname,
+ canicknameWithoutTokenName));
+
+ KeyPair pair = null;
+
+ if (nickname.equals("")) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ throw new EBaseException(CMS.getLogMessage("BASE_CERT_NOT_FOUND"));
+ }
+
+ //xxx set to old nickname?
+ properties.setCertNickname(nickname);
+ if (!certType.equals(Constants.PR_CA_SIGNING_CERT)) {
+ CertificateExtensions exts = jssSubSystem.getExtensions(
+ oldcatokenname, canicknameWithoutTokenName);
+
+ properties.setCAExtensions(exts);
+ }
+
+ KeyPair caKeyPair = null;
+ String defaultSigningAlg = null;
+ String defaultOCSPSigningAlg = null;
+
+ if (properties.getHashType() != null) {
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT)) {
+ defaultSigningAlg = properties.getHashType();
+ }
+ if (certType.equals(Constants.PR_OCSP_SIGNING_CERT)) {
+ defaultOCSPSigningAlg = properties.getHashType();
+ }
+ }
+
+ // create a new CA certificate or ssl server cert
+ if (properties.getKeyCurveName() != null) { //new ECC
+ CMS.debug("CMSAdminServlet: issueImportCert: generating ECC keys");
+ pair = jssSubSystem.getECCKeyPair(properties);
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT))
+ caKeyPair = pair;
+ } else if (properties.getKeyLength() != null) { //new RSA or DSA
+ keyType = properties.getKeyType();
+ String keyLen = properties.getKeyLength();
+
+ if (keyType.equals("DSA")) {
+ @SuppressWarnings("unused")
+ PQGParams pqgParams =
+ jssSubSystem.getCAPQG(Integer.parseInt(keyLen), mConfig); // check for errors
+ //properties.put(Constants.PR_PQGPARAMS, pqgParams);
+ }
+ pair = jssSubSystem.getKeyPair(properties);
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT))
+ caKeyPair = pair;
+ // renew the CA certificate or ssl server cert
+ } else {
+ pair = jssSubSystem.getKeyPair(nickname);
+ // should get it from the CA signing certificate
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT)) {
+ updateCASignature(nickname, properties, jssSubSystem);
+ caKeyPair = pair;
+ defaultSigningAlg = signingUnit.getDefaultAlgorithm();
+ }
+
+ /*
+ String alg = jssSubSystem.getSignatureAlgorithm(nickname);
+ SignatureAlgorithm sigAlg = SigningUnit.mapAlgorithmToJss(alg);
+ properties.setSignatureAlgorithm(sigAlg);
+ properties.setAlgorithmId(
+ jssSubSystem.getAlgorithmId(alg, mConfig));
+ */
+ }
+
+ String alg = properties.getSignedBy();
+ if (!certType.equals(Constants.PR_CA_SIGNING_CERT)) {
+ caKeyPair = jssSubSystem.getKeyPair(canickname);
+ updateCASignature(canickname, properties, jssSubSystem);
+ } else if (alg != null) {
+ // self signed CA signing cert, new keys
+ // value provided for signedBy
+ SignatureAlgorithm sigAlg = Cert.mapAlgorithmToJss(alg);
+ properties.setSignatureAlgorithm(sigAlg);
+ properties.setAlgorithmId(jssSubSystem.getAlgorithmId(alg, mConfig));
+ }
+
+ if (pair == null)
+ CMS.debug("CMSAdminServlet: issueImportCert: key pair is null");
+
+ BigInteger nextSerialNo = repository.getNextSerialNumber();
+
+ properties.setSerialNumber(nextSerialNo);
+ properties.setKeyPair(pair);
+ properties.setConfigFile(mConfig);
+ // properties.put(Constants.PR_CA_KEYPAIR, pair);
+ properties.put(Constants.PR_CA_KEYPAIR, caKeyPair);
+
+ X509CertImpl signedCert =
+ jssSubSystem.getSignedCert(properties, certType,
+ caKeyPair.getPrivate());
+
+ if (signedCert == null)
+ CMS.debug("CMSAdminServlet: issueImportCert: signedCert is null");
+
+ /* bug 600124
+ try {
+ jssSubSystem.deleteTokenCertificate(nickname, pathname);
+ } catch (Throwable e) {
+ //skip it
+ }
+ */
+
+ boolean nicknameChanged = false;
+
+ //xxx import cert with nickname without token name?
+ //jss adds the token prefix!!!
+ //log(ILogger.LL_DEBUG,"import as alias"+ nicknameWithoutTokenName);
+ try {
+ CMS.debug("CMSAdminServlet: issueImportCert: Importing cert: " + nicknameWithoutTokenName);
+ jssSubSystem.importCert(signedCert, nicknameWithoutTokenName,
+ certType);
+ } catch (EBaseException e) {
+ // if it fails, let use a different nickname to try
+ Date now = new Date();
+ String newNickname = nicknameWithoutTokenName
+ + "-" + now.getTime();
+
+ CMS.debug("CMSAdminServlet: issueImportCert: Importing cert with nickname: " + newNickname);
+ jssSubSystem.importCert(signedCert, newNickname,
+ certType);
+ nicknameWithoutTokenName = newNickname;
+ nicknameChanged = true;
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ nickname = newNickname;
+ } else {
+ nickname = tokenName + ":" + newNickname;
+ }
+ }
+
+ ICertRecord certRecord = repository.createCertRecord(
+ signedCert.getSerialNumber(),
+ signedCert, null);
+
+ repository.addCertificateRecord(certRecord);
+
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT)) {
+ try {
+ X509CertInfo certInfo = (X509CertInfo) signedCert.get(
+ X509CertImpl.NAME + "." + X509CertImpl.INFO);
+ CertificateExtensions extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+
+ if (extensions != null) {
+ BasicConstraintsExtension basic =
+ (BasicConstraintsExtension)
+ extensions.get(BasicConstraintsExtension.NAME);
+
+ if (basic == null)
+ log(CMS.getLogMessage("ADMIN_SRVLT_BASIC_CONSTRAIN_NULL"));
+ else {
+ Integer pathlen = (Integer)
+ basic.get(BasicConstraintsExtension.PATH_LEN);
+ int num = pathlen.intValue();
+
+ if (num == 0)
+ ca.setBasicConstraintMaxLen(num);
+ else if (num > 0) {
+ num = num - 1;
+ ca.setBasicConstraintMaxLen(num);
+ }
+ }
+ } else
+ log(CMS.getLogMessage("ADMIN_SRVLT_CERT_NO_EXT"));
+ } catch (Exception eee) {
+ log("CMSAdminServlet: Exception caught: " + eee.toString());
+ }
+ }
+
+ CMS.debug("CMSAdminServlet: oldtoken:" + oldtokenname
+ + " newtoken:" + newtokenname + " nickname:" + nickname);
+ if ((newtokenname != null &&
+ !newtokenname.equals(oldtokenname)) || nicknameChanged) {
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT)) {
+ if (newtokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ signingUnit.updateConfig(nicknameWithoutTokenName,
+ newtokenname);
+ } else {
+ signingUnit.updateConfig(newtokenname + ":" +
+ nicknameWithoutTokenName,
+ newtokenname);
+ }
+ } else if (certType.equals(Constants.PR_SERVER_CERT)) {
+ if (newtokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ nickname = nicknameWithoutTokenName;
+ } else {
+ nickname = newtokenname + ":"
+ + nicknameWithoutTokenName;
+ }
+
+ //setRADMNewnickname("","");
+ //modifyRADMCert(nickname);
+ modifyAgentGatewayCert(nickname);
+ if (isSubsystemInstalled("ra")) {
+ IRegistrationAuthority ra =
+ (IRegistrationAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_RA);
+
+ modifyEEGatewayCert(ra, nickname);
+ }
+ if (isSubsystemInstalled("ca")) {
+ modifyCAGatewayCert(ca, nickname);
+ }
+ } else if (certType.equals(Constants.PR_SERVER_CERT_RADM)) {
+ if (newtokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ nickname = nicknameWithoutTokenName;
+ } else {
+ nickname = newtokenname + ":"
+ + nicknameWithoutTokenName;
+ }
+
+ modifyRADMCert(nickname);
+ } else if (certType.equals(Constants.PR_OCSP_SIGNING_CERT)) {
+ if (ca != null) {
+ ISigningUnit ocspSigningUnit = ca.getOCSPSigningUnit();
+
+ if (newtokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ ocspSigningUnit.updateConfig(
+ nicknameWithoutTokenName, newtokenname);
+ } else {
+ ocspSigningUnit.updateConfig(newtokenname + ":" +
+ nicknameWithoutTokenName,
+ newtokenname);
+ }
+ }
+ }
+ }
+
+ // set signing algorithms if needed
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT))
+ signingUnit.setDefaultAlgorithm(defaultSigningAlg);
+
+ if (defaultOCSPSigningAlg != null) {
+ ISigningUnit ocspSigningUnit = ca.getOCSPSigningUnit();
+ ocspSigningUnit.setDefaultAlgorithm(defaultOCSPSigningAlg);
+ }
+
+ properties.clear();
+ properties = null;
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ mConfig.commit(true);
+ sendResponse(SUCCESS, null, null, resp);
+ } catch (EBaseException eAudit1) {
+ CMS.debug("CMSAdminServlet: issueImportCert: EBaseException thrown: " + eAudit1.toString());
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ CMS.debug("CMSAdminServlet: issueImportCert: IOException thrown: " + eAudit2.toString());
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ private void updateCASignature(String nickname, KeyCertData properties,
+ ICryptoSubsystem jssSubSystem) throws EBaseException {
+ String alg = jssSubSystem.getSignatureAlgorithm(nickname);
+ SignatureAlgorithm sigAlg = Cert.mapAlgorithmToJss(alg);
+
+ properties.setSignatureAlgorithm(sigAlg);
+ properties.setAlgorithmId(
+ jssSubSystem.getAlgorithmId(alg, mConfig));
+ }
+
+ /**
+ * Install certificates
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY used when "Certificate Setup Wizard" is used to
+ * import CA certs into the certificate database
+ * </ul>
+ *
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException failed to install a certificate
+ */
+ private void installCert(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String tokenName = Constants.PR_INTERNAL_TOKEN_NAME;
+ String pkcs = "";
+ String certType = "";
+ String nickname = "";
+ String pathname = "";
+ String serverRoot = "";
+ String serverID = "";
+ String certpath = "";
+ Enumeration<String> enum1 = req.getParameterNames();
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.PR_PKCS10))
+ pkcs = value;
+ else if (key.equals(Constants.RS_ID))
+ certType = value;
+ else if (key.equals(Constants.PR_NICKNAME))
+ nickname = value;
+ else if (key.equals("pathname"))
+ pathname = value;
+ else if (key.equals(Constants.PR_SERVER_ROOT))
+ serverRoot = value;
+ else if (key.equals(Constants.PR_SERVER_ID))
+ serverID = value;
+ else if (key.equals(Constants.PR_CERT_FILEPATH))
+ certpath = value;
+ }
+
+ try {
+ if (pkcs == null || pkcs.equals("")) {
+ if (certpath == null || certpath.equals("")) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ EBaseException ex = new EBaseException(
+ CMS.getLogMessage("BASE_INVALID_FILE_PATH"));
+
+ throw ex;
+ } else {
+ FileInputStream in = new FileInputStream(certpath);
+ BufferedReader d =
+ new BufferedReader(new InputStreamReader(in));
+ String content = "";
+
+ pkcs = "";
+ StringBuffer sb = new StringBuffer();
+ while ((content = d.readLine()) != null) {
+ sb.append(content);
+ sb.append("\n");
+ }
+
+ pkcs = sb.toString();
+ if (d != null) {
+ d.close();
+ }
+ pkcs = pkcs.substring(0, pkcs.length() - 1);
+ }
+ }
+ } catch (IOException ee) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ throw new EBaseException(
+ CMS.getLogMessage("BASE_OPEN_FILE_FAILED"));
+ }
+
+ pkcs = pkcs.trim();
+ pathname = serverRoot + File.separator + serverID
+ + File.separator + "config" + File.separator + pathname;
+
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ //String nickname = getNickname(certType);
+ String nicknameWithoutTokenName = "";
+
+ int index = nickname.indexOf(":");
+
+ if (index == -1)
+ nicknameWithoutTokenName = nickname;
+ else if (index > 0 && (index < (nickname.length() - 1))) {
+ tokenName = nickname.substring(0, index);
+ nicknameWithoutTokenName = nickname.substring(index + 1);
+ } else {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ throw new EBaseException(
+ CMS.getLogMessage("BASE_CERT_NOT_FOUND"));
+ }
+
+ /*
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT) ||
+ certType.equals(Constants.PR_RA_SIGNING_CERT) ||
+ certType.equals(Constants.PR_OCSP_SIGNING_CERT) ||
+ certType.equals(Constants.PR_KRA_TRANSPORT_CERT) ||
+ certType.equals(Constants.PR_SERVER_CERT) ||
+ certType.equals(Constants.PR_SERVER_CERT_RADM)) {
+ String oldnickname = getNickname(certType);
+ try {
+ jssSubsystem.deleteTokenCertificate(oldnickname,
+ pathname);
+ //jssSubsystem.deleteTokenCertificate(nickname,
+ pathname);
+ } catch (EBaseException e) {
+ // skip it
+ }
+ } else {
+ try {
+ jssSubsystem.deleteTokenCertificate(nickname, pathname);
+ } catch (EBaseException e) {
+ // skip it
+ }
+ }
+ */
+
+ // 600124 - renewal of SSL crash the server
+ // we now do not delete previously installed certificates.
+
+ // Same Subject | Same Nickname | Same Key | Legal
+ // -----------------------------------------------------------
+ // 1. Yes Yes No Yes
+ // 2. Yes Yes Yes Yes
+ // 3. No No Yes Yes
+ // 4. No No No Yes
+ // 5. No Yes Yes No
+ // 6. No Yes No No
+ // 7. Yes No Yes No
+ // 8. Yes No No No
+
+ // Based on above table, the following cases are permitted:
+ // Existing Key:
+ // (a) Same Subject & Same Nickname --- (2)
+ // (b) Different Subject & Different Nickname --- (3)
+ // (In order to support Case b., we need to use a different
+ // nickname).
+ // New Key:
+ // (c) Same Subject & Same Nickname --- (1)
+ // (d) Different Subject & Different Nickname --- (4)
+ // (In order to support Case b., we need to use a different
+ // nickname).
+ //
+
+ CMS.debug("CMSAdminServlet.installCert(): About to try jssSubSystem.importCert: "
+ + nicknameWithoutTokenName);
+ try {
+ jssSubSystem.importCert(pkcs, nicknameWithoutTokenName,
+ certType);
+ } catch (EBaseException e) {
+
+ boolean certFound = false;
+
+ String eString = e.toString();
+ if (eString.contains("Failed to find certificate that was just imported")) {
+ CMS.debug("CMSAdminServlet.installCert(): nickname="
+ + nicknameWithoutTokenName + " TokenException: " + eString);
+
+ X509Certificate cert = null;
+ try {
+ cert = CryptoManager.getInstance().findCertByNickname(nickname);
+ if (cert != null) {
+ certFound = true;
+ }
+ CMS.debug("CMSAdminServlet.installCert() Found cert just imported: " + nickname);
+ } catch (Exception ex) {
+ CMS.debug("CMSAdminServlet.installCert() Can't find cert just imported: " + ex.toString());
+ }
+ }
+
+ if (!certFound) {
+ // if it fails, let use a different nickname to try
+ Date now = new Date();
+ String newNickname = nicknameWithoutTokenName + "-" +
+ now.getTime();
+
+ jssSubSystem.importCert(pkcs, newNickname, certType);
+ nicknameWithoutTokenName = newNickname;
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ nickname = newNickname;
+ } else {
+ nickname = tokenName + ":" + newNickname;
+ }
+ CMS.debug("CMSAdminServlet: installCert(): After second install attempt following initial error: nickname="
+ + nickname);
+ }
+ }
+
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT)) {
+ ICertificateAuthority ca =
+ (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ ISigningUnit signingUnit = ca.getSigningUnit();
+ String signatureAlg =
+ jssSubSystem.getSignatureAlgorithm(nickname);
+
+ signingUnit.setDefaultAlgorithm(signatureAlg);
+ setCANewnickname("", "");
+ try {
+ CertificateExtensions extensions = null;
+
+ if (nickname.equals(nicknameWithoutTokenName)) {
+ signingUnit.updateConfig(nickname,
+ Constants.PR_INTERNAL_TOKEN_NAME);
+ extensions = jssSubSystem.getExtensions(
+ Constants.PR_INTERNAL_TOKEN_NAME, nickname);
+ } else {
+ String tokenname1 = nickname.substring(0, index);
+
+ signingUnit.updateConfig(nickname, tokenname1);
+ extensions = jssSubSystem.getExtensions(tokenname1,
+ nicknameWithoutTokenName);
+ }
+ if (extensions != null) {
+ BasicConstraintsExtension basic =
+ (BasicConstraintsExtension)
+ extensions.get(BasicConstraintsExtension.NAME);
+
+ if (basic == null)
+ log(CMS.getLogMessage("ADMIN_SRVLT_BASIC_CONSTRAIN_NULL"));
+ else {
+ Integer pathlen = (Integer)
+ basic.get(BasicConstraintsExtension.PATH_LEN);
+ int num = pathlen.intValue();
+
+ if (num == 0)
+ ca.setBasicConstraintMaxLen(num);
+ else if (num > 0) {
+ num = num - 1;
+ ca.setBasicConstraintMaxLen(num);
+ }
+ }
+ } else {
+ log(CMS.getLogMessage("ADMIN_SRVLT_CERT_NO_EXT"));
+ }
+ } catch (Exception eee) {
+ log("CMSAdminServlet: Exception: " + eee.toString());
+ }
+ } else if (certType.equals(Constants.PR_RA_SIGNING_CERT)) {
+ setRANewnickname("", "");
+ IRegistrationAuthority ra =
+ (IRegistrationAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_RA);
+
+ ra.setNickname(nickname);
+ } else if (certType.equals(Constants.PR_OCSP_SIGNING_CERT)) {
+ setOCSPNewnickname("", "");
+ IOCSPAuthority ocsp =
+ (IOCSPAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_OCSP);
+
+ if (ocsp != null) {
+ ISigningUnit signingUnit = ocsp.getSigningUnit();
+
+ if (nickname.equals(nicknameWithoutTokenName)) {
+ signingUnit.updateConfig(nickname,
+ Constants.PR_INTERNAL_TOKEN_NAME);
+ } else {
+ String tokenname1 = nickname.substring(0, index);
+
+ signingUnit.updateConfig(nickname, tokenname1);
+ }
+ } else {
+ ICertificateAuthority ca =
+ (ICertificateAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ ISigningUnit signingUnit = ca.getOCSPSigningUnit();
+
+ if (nickname.equals(nicknameWithoutTokenName)) {
+ signingUnit.updateConfig(nickname,
+ Constants.PR_INTERNAL_TOKEN_NAME);
+ } else {
+ String tokenname1 = nickname.substring(0, index);
+
+ signingUnit.updateConfig(nickname, tokenname1);
+ }
+ }
+ } else if (certType.equals(Constants.PR_KRA_TRANSPORT_CERT)) {
+ setKRANewnickname("", "");
+ IKeyRecoveryAuthority kra =
+ (IKeyRecoveryAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_KRA);
+
+ kra.setNickname(nickname);
+ } else if (certType.equals(Constants.PR_SERVER_CERT)) {
+ setAgentNewnickname("", "");
+ //modifyRADMCert(nickname);
+ modifyAgentGatewayCert(nickname);
+ if (isSubsystemInstalled("ra")) {
+ IRegistrationAuthority ra =
+ (IRegistrationAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_RA);
+
+ modifyEEGatewayCert(ra, nickname);
+ }
+ if (isSubsystemInstalled("ca")) {
+ ICertificateAuthority ca =
+ (ICertificateAuthority)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+
+ modifyCAGatewayCert(ca, nickname);
+ }
+ } else if (certType.equals(Constants.PR_SERVER_CERT_RADM)) {
+ setRADMNewnickname("", "");
+ modifyRADMCert(nickname);
+ }
+
+ boolean verified = CMS.verifySystemCertByNickname(nickname, null);
+ if (verified == true) {
+ CMS.debug("CMSAdminServlet: installCert(): verifySystemCertByNickname() succeeded:" + nickname);
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ nickname);
+
+ audit(auditMessage);
+ } else {
+ CMS.debug("CMSAdminServlet: installCert(): verifySystemCertByNickname() failed:" + nickname);
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ auditSubjectID,
+ ILogger.FAILURE,
+ nickname);
+
+ audit(auditMessage);
+ }
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ mConfig.commit(true);
+ if (verified == true) {
+ sendResponse(SUCCESS, null, null, resp);
+ } else {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_CERT_VALIDATE_FAILED"),
+ null, resp);
+ }
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * For "importing" cross-signed cert into internal db for further
+ * cross pair matching and publishing
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY used when "Certificate Setup Wizard" is used to
+ * import a CA cross-signed certificate into the database
+ * </ul>
+ *
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException failed to import a cross-certificate pair
+ */
+ private void importXCert(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String b64Cert = "";
+ String pathname = "";
+ String serverRoot = "";
+ String serverID = "";
+ String certpath = "";
+ Enumeration<String> enum1 = req.getParameterNames();
+ NameValuePairs results = new NameValuePairs();
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ // really should be PR_CERT_CONTENT
+ if (key.equals(Constants.PR_PKCS10))
+ b64Cert = value;
+ else if (key.equals("pathname"))
+ pathname = value;
+ else if (key.equals(Constants.PR_SERVER_ROOT))
+ serverRoot = value;
+ else if (key.equals(Constants.PR_SERVER_ID))
+ serverID = value;
+ else if (key.equals(Constants.PR_CERT_FILEPATH))
+ certpath = value;
+ }
+
+ try {
+ if (b64Cert == null || b64Cert.equals("")) {
+ if (certpath == null || certpath.equals("")) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ EBaseException ex = new EBaseException(
+ CMS.getLogMessage("BASE_INVALID_FILE_PATH"));
+
+ throw ex;
+ } else {
+ FileInputStream in = new FileInputStream(certpath);
+ BufferedReader d =
+ new BufferedReader(new InputStreamReader(in));
+ String content = "";
+
+ b64Cert = "";
+ StringBuffer sb = new StringBuffer();
+ while ((content = d.readLine()) != null) {
+ sb.append(content);
+ sb.append("\n");
+ }
+ b64Cert = sb.toString();
+ if (d != null) {
+ d.close();
+ }
+ b64Cert = b64Cert.substring(0, b64Cert.length() - 1);
+ }
+ }
+ } catch (IOException ee) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ throw new EBaseException(
+ CMS.getLogMessage("BASE_OPEN_FILE_FAILED"));
+ }
+ CMS.debug("CMSAdminServlet: got b64Cert");
+ b64Cert = Cert.stripBrackets(b64Cert.trim());
+
+ // Base64 decode cert
+ byte[] bCert = null;
+
+ try {
+ bCert = Utils.base64decode(b64Cert);
+ } catch (Exception e) {
+ CMS.debug("CMSAdminServlet: exception: " + e.toString());
+ }
+
+ pathname = serverRoot + File.separator + serverID
+ + File.separator + "config" + File.separator + pathname;
+
+ ICrossCertPairSubsystem ccps =
+ (ICrossCertPairSubsystem) CMS.getSubsystem("CrossCertPair");
+
+ try {
+ //this will import into internal ldap crossCerts entry
+ ccps.importCert(bCert);
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(1, "xcert importing failure:" + e.toString(),
+ null, resp);
+ return;
+ }
+
+ try {
+ // this will publish all of the cross cert pairs from internal
+ // db to publishing directory, if turned on
+ ccps.publishCertPairs();
+ } catch (EBaseException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(1, "xcerts publishing failure:" + e.toString(), null, resp);
+ return;
+ }
+
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ String content = jssSubSystem.getCertPrettyPrint(b64Cert,
+ super.getLocale(req));
+
+ results.put(Constants.PR_NICKNAME, "FBCA cross-signed cert");
+ results.put(Constants.PR_CERT_CONTENT, content);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, results, resp);
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ private String getNickname(String certType) throws EBaseException {
+ String nickname = "";
+
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT)) {
+ ICertificateAuthority ca =
+ (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ ISigningUnit signingUnit = ca.getSigningUnit();
+
+ nickname = signingUnit.getNickname();
+ } else if (certType.equals(Constants.PR_OCSP_SIGNING_CERT)) {
+ IOCSPAuthority ocsp =
+ (IOCSPAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_OCSP);
+
+ if (ocsp == null) {
+ // this is a local CA service
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ ISigningUnit signingUnit = ca.getOCSPSigningUnit();
+
+ nickname = signingUnit.getNickname();
+ } else {
+ ISigningUnit signingUnit = ocsp.getSigningUnit();
+
+ nickname = signingUnit.getNickname();
+ }
+ } else if (certType.equals(Constants.PR_RA_SIGNING_CERT)) {
+ IRegistrationAuthority ra =
+ (IRegistrationAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_RA);
+
+ nickname = ra.getNickname();
+ } else if (certType.equals(Constants.PR_KRA_TRANSPORT_CERT)) {
+ IKeyRecoveryAuthority kra =
+ (IKeyRecoveryAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_KRA);
+
+ nickname = kra.getNickname();
+ } else if (certType.equals(Constants.PR_SERVER_CERT)) {
+ nickname = CMS.getServerCertNickname();
+ } else if (certType.equals(Constants.PR_SERVER_CERT_RADM)) {
+ nickname = CMS.getServerCertNickname();
+ }
+
+ return nickname;
+ }
+
+ private void getCertInfo(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ Enumeration<String> enum1 = req.getParameterNames();
+ NameValuePairs results = new NameValuePairs();
+ String pkcs = "";
+ String path = "";
+ String certType = "";
+ String otherNickname = "";
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.PR_PKCS10)) {
+ pkcs = value;
+ } else if (key.equals(Constants.RS_ID)) {
+ certType = value;
+ } else if (key.equals(Constants.PR_CERT_FILEPATH)) {
+ path = value;
+ } else if (key.equals(Constants.PR_NICKNAME)) {
+ otherNickname = value;
+ }
+ }
+
+ try {
+ if (pkcs == null || pkcs.equals("")) {
+
+ if (path == null || path.equals("")) {
+ EBaseException ex = new EBaseException(
+ CMS.getLogMessage("BASE_INVALID_FILE_PATH"));
+
+ throw ex;
+ } else {
+ FileInputStream in = new FileInputStream(path);
+ BufferedReader d =
+ new BufferedReader(new InputStreamReader(in));
+ String content = "";
+
+ pkcs = "";
+ StringBuffer sb = new StringBuffer();
+ while ((content = d.readLine()) != null) {
+ sb.append(content);
+ sb.append("\n");
+ }
+ pkcs = sb.toString();
+ if (d != null) {
+ d.close();
+ }
+ pkcs = pkcs.substring(0, pkcs.length() - 1);
+ }
+ }
+ } catch (IOException ee) {
+ throw new EBaseException(CMS.getLogMessage("BASE_OPEN_FILE_FAILED"));
+ }
+
+ pkcs = pkcs.trim();
+ int totalLen = pkcs.length();
+
+ if (pkcs.indexOf(BEGIN_HEADER) != 0 ||
+ pkcs.indexOf(END_HEADER) != (totalLen - 25)) {
+ throw (new EBaseException(CMS.getLogMessage("BASE_INVALID_CERT_FORMAT")));
+ }
+
+ String nickname = "";
+
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT)) {
+ nickname = getCANewnickname();
+ } else if (certType.equals(Constants.PR_RA_SIGNING_CERT)) {
+ nickname = getRANewnickname();
+ } else if (certType.equals(Constants.PR_KRA_TRANSPORT_CERT)) {
+ nickname = getKRANewnickname();
+ } else if (certType.equals(Constants.PR_SERVER_CERT)) {
+ nickname = getAgentNewnickname();
+ } else if (certType.equals(Constants.PR_SERVER_CERT_RADM)) {
+ nickname = getRADMNewnickname();
+ } else if (certType.equals(Constants.PR_OTHER_CERT)) {
+ nickname = otherNickname;
+ } else if (certType.equals(Constants.PR_OCSP_SIGNING_CERT)) {
+ nickname = getOCSPNewnickname();
+ }
+ if (nickname.equals(""))
+ nickname = getNickname(certType);
+
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ String content = jssSubSystem.getCertPrettyPrint(pkcs,
+ super.getLocale(req));
+
+ if (nickname != null && !nickname.equals(""))
+ results.put(Constants.PR_NICKNAME, nickname);
+ results.put(Constants.PR_CERT_CONTENT, content);
+ //results = jssSubSystem.getCertInfo(value);
+
+ sendResponse(SUCCESS, null, results, resp);
+ }
+
+ private void getCertPrettyPrint(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ Enumeration<String> enum1 = req.getParameterNames();
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ String nickname = "";
+ String serialno = "";
+ String issuername = "";
+ Locale locale = super.getLocale(req);
+ NameValuePairs pairs = new NameValuePairs();
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.OP_TYPE))
+ continue;
+ if (key.equals(Constants.RS_ID))
+ continue;
+ if (key.equals(Constants.OP_SCOPE))
+ continue;
+ if (key.equals(Constants.PR_NICK_NAME)) {
+ nickname = value;
+ continue;
+ }
+ if (key.equals(Constants.PR_SERIAL_NUMBER)) {
+ serialno = value;
+ continue;
+ }
+ if (key.equals(Constants.PR_ISSUER_NAME)) {
+ issuername = value;
+ continue;
+ }
+ }
+
+ String print = jssSubSystem.getCertPrettyPrintAndFingerPrint(nickname,
+ serialno, issuername, locale);
+ pairs.put(nickname, print);
+
+ sendResponse(SUCCESS, null, pairs, resp);
+ }
+
+ private void getRootCertTrustBit(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ Enumeration<String> enum1 = req.getParameterNames();
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ String nickname = "";
+ String serialno = "";
+ String issuername = "";
+ NameValuePairs pairs = new NameValuePairs();
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.OP_TYPE))
+ continue;
+ if (key.equals(Constants.RS_ID))
+ continue;
+ if (key.equals(Constants.OP_SCOPE))
+ continue;
+ if (key.equals(Constants.PR_NICK_NAME)) {
+ nickname = value;
+ continue;
+ }
+ if (key.equals(Constants.PR_SERIAL_NUMBER)) {
+ serialno = value;
+ continue;
+ }
+ if (key.equals(Constants.PR_ISSUER_NAME)) {
+ issuername = value;
+ continue;
+ }
+ }
+
+ String trustbit = jssSubSystem.getRootCertTrustBit(nickname,
+ serialno, issuername);
+ pairs.put(nickname, trustbit);
+
+ sendResponse(SUCCESS, null, pairs, resp);
+ }
+
+ private void getCACerts(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ NameValuePairs pairs = jssSubSystem.getCACerts();
+
+ sendResponse(SUCCESS, null, pairs, resp);
+ }
+
+ private void deleteRootCert(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String id = req.getParameter(Constants.RS_ID);
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ int mindex = id.indexOf(":SERIAL#<");
+ String nickname = id.substring(0, mindex);
+ String sstr1 = id.substring(mindex);
+ int lindex = sstr1.indexOf(">");
+ String serialno = sstr1.substring(9, lindex);
+ String issuername = sstr1.substring(lindex + 1);
+ jssSubSystem.deleteRootCert(nickname, serialno, issuername);
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ private void deleteUserCert(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String id = req.getParameter(Constants.RS_ID);
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ int mindex = id.indexOf(":SERIAL#<");
+ String nickname = id.substring(0, mindex);
+ String sstr1 = id.substring(mindex);
+ int lindex = sstr1.indexOf(">");
+ String serialno = sstr1.substring(9, lindex);
+ String issuername = sstr1.substring(lindex + 1);
+ jssSubSystem.deleteUserCert(nickname, serialno, issuername);
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ private void getRootCerts(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ NameValuePairs pairs = jssSubSystem.getRootCerts();
+
+ sendResponse(SUCCESS, null, pairs, resp);
+ }
+
+ private void getAllCertsManage(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ NameValuePairs pairs = jssSubSystem.getAllCertsManage();
+
+ sendResponse(SUCCESS, null, pairs, resp);
+ }
+
+ private void getUserCerts(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ NameValuePairs pairs = jssSubSystem.getUserCerts();
+ sendResponse(SUCCESS, null, pairs, resp);
+ }
+
+ private void deleteCerts(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ Enumeration<String> enum1 = req.getParameterNames();
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ String nickname = "";
+ String date = "";
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.OP_TYPE))
+ continue;
+ if (key.equals(Constants.RS_ID))
+ continue;
+ if (key.equals(Constants.OP_SCOPE))
+ continue;
+ int index = value.indexOf(";");
+
+ nickname = value.substring(0, index);
+ date = value.substring(index + 1);
+ // cant use this one now since jss doesnt have the interface to
+ // do it.
+ jssSubSystem.deleteCert(nickname, date);
+ // jssSubsystem.deleteCACert(nickname, date);
+ }
+
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ private void validateSubjectName(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ Enumeration<String> enum1 = req.getParameterNames();
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.PR_SUBJECT_NAME)) {
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+
+ jssSubSystem.isX500DN(value);
+ }
+ }
+
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ private void validateKeyLength(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ private void validateCurveName(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ Enumeration<String> enum1 = req.getParameterNames();
+ String curveName = null;
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.PR_KEY_CURVENAME)) {
+ curveName = value;
+ }
+ }
+ // check that the curvename is in the list of supported curves
+ String curveList = mConfig.getString("keys.ecc.curve.list", "nistp521");
+ String[] curves = curveList.split(",");
+ boolean match = false;
+ for (int i = 0; i < curves.length; i++) {
+ if (curves[i].equals(curveName)) {
+ match = true;
+ }
+ }
+ if (!match) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ECC_CURVE_NAME"));
+ }
+
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ private void validateCertExtension(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ Enumeration<String> enum1 = req.getParameterNames();
+ String certExt = "";
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(ConfigConstants.PR_CERTIFICATE_EXTENSION)) {
+ certExt = value;
+ break;
+ }
+ }
+
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+
+ jssSubSystem.checkCertificateExt(certExt);
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ private void getSubjectName(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> enum1 = req.getParameterNames();
+
+ String nickname = "";
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.RS_ID)) {
+ nickname = getNickname(value);
+ break;
+ }
+ }
+
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ String subjectName = jssSubSystem.getSubjectDN(nickname);
+
+ params.put(Constants.PR_SUBJECT_NAME, subjectName);
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void processSubjectName(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> enum1 = req.getParameterNames();
+
+ String nickname = "";
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.PR_NICKNAME)) {
+ nickname = value;
+ }
+ }
+
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ String subjectName = jssSubSystem.getSubjectDN(nickname);
+
+ params.put(Constants.PR_SUBJECT_NAME, subjectName);
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ public void setRootCertTrust(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String nickname = req.getParameter(Constants.PR_NICK_NAME);
+ String serialno = req.getParameter(Constants.PR_SERIAL_NUMBER);
+ String issuername = req.getParameter(Constants.PR_ISSUER_NAME);
+ String trust = req.getParameter("trustbit");
+
+ CMS.debug("CMSAdminServlet: setRootCertTrust()");
+
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ try {
+ jssSubSystem.setRootCertTrust(nickname, serialno, issuername, trust);
+ } catch (EBaseException e) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ // rethrow the specific exception to be handled later
+ throw e;
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ /**
+ * Establish trust of a CA certificate
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY used when "Manage Certificate" is used to edit
+ * the trustness of certs and deletion of certs
+ * </ul>
+ *
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException failed to establish CA certificate trust
+ */
+ private void trustCACert(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ CMS.debug("CMSAdminServlet: trustCACert()");
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ Enumeration<String> enum1 = req.getParameterNames();
+ ICryptoSubsystem jssSubSystem = (ICryptoSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+ String trust = "";
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.RS_ID)) {
+ trust = value;
+ } else if (key.equals("certName0")) {
+ int index = value.indexOf(";");
+ String nickname = value.substring(0, index);
+ String date = value.substring(index + 1);
+
+ jssSubSystem.trustCert(nickname, date, trust);
+ }
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ //sendResponse(SUCCESS, null, null, resp);
+ sendResponse(RESTART, null, null, resp);
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * Execute all self tests specified to be run on demand.
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION used when self tests are run on demand
+ * </ul>
+ *
+ * @exception EMissingSelfTestException a self test plugin instance
+ * property name was missing
+ * @exception ESelfTestException a self test is missing a required
+ * configuration parameter
+ * @exception IOException an input/output error has occurred
+ */
+ private synchronized void
+ runSelfTestsOnDemand(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws EMissingSelfTestException,
+ ESelfTestException,
+ IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ if (CMS.debugOn()) {
+ CMS.debug("CMSAdminServlet::runSelfTestsOnDemand():"
+ + " ENTERING . . .");
+ }
+ Enumeration<String> enum1 = req.getParameterNames();
+ String request = "";
+ NameValuePairs results = new NameValuePairs();
+ String content = "";
+ String instanceName = null;
+ String instanceFullName = null;
+ String logMessage = null;
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.PR_RUN_SELFTESTS_ON_DEMAND)) {
+ request = value;
+ }
+ }
+
+ ISelfTestSubsystem mSelfTestSubsystem = (ISelfTestSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_SELFTESTS);
+
+ if ((request == null) ||
+ (request.equals(""))) {
+ // self test plugin run on demand request parameter was missing
+ // log the error
+ logMessage = CMS.getLogMessage("SELFTESTS_RUN_ON_DEMAND_REQUEST",
+ getServletInfo(),
+ Constants.PR_RUN_SELFTESTS_ON_DEMAND
+ );
+
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ logMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ // notify console of FAILURE
+ content += logMessage
+ + "\n";
+ sendResponse(ERROR, content, null, resp);
+
+ // raise an exception
+ throw new ESelfTestException(logMessage);
+ }
+
+ // run all self test plugin instances (designated on-demand)
+ String[] selftests = mSelfTestSubsystem.listSelfTestsEnabledOnDemand();
+
+ if (selftests != null && selftests.length > 0) {
+ // log that execution of on-demand self tests has begun
+ logMessage = CMS.getLogMessage("SELFTESTS_RUN_ON_DEMAND",
+ getServletInfo());
+
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ logMessage);
+
+ // store this information for console notification
+ content += logMessage
+ + "\n";
+
+ for (int i = 0; i < selftests.length; i++) {
+ if (selftests[i] != null) {
+ instanceName = selftests[i].trim();
+ instanceFullName = ISelfTestSubsystem.ID
+ + "."
+ + ISelfTestSubsystem.PROP_CONTAINER
+ + "."
+ + ISelfTestSubsystem.PROP_INSTANCE
+ + "."
+ + instanceName;
+ } else {
+ // self test plugin instance property name was missing
+ // log the error
+ logMessage = CMS.getLogMessage(
+ "SELFTESTS_PARAMETER_WAS_NULL",
+ getServletInfo());
+
+ mSelfTestSubsystem.log(
+ mSelfTestSubsystem.getSelfTestLogger(),
+ logMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ // notify console of FAILURE
+ content += logMessage
+ + "\n";
+ sendResponse(ERROR, content, null, resp);
+
+ // raise an exception
+ throw new EMissingSelfTestException();
+ }
+
+ ISelfTest test = mSelfTestSubsystem.getSelfTest(instanceName);
+
+ if (test == null) {
+ // self test plugin instance property name is not present
+ // log the error
+ logMessage = CMS.getLogMessage("SELFTESTS_MISSING_NAME",
+ getServletInfo(),
+ instanceFullName);
+
+ mSelfTestSubsystem.log(
+ mSelfTestSubsystem.getSelfTestLogger(),
+ logMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ // notify console of FAILURE
+ content += logMessage
+ + "\n";
+ sendResponse(ERROR, content, null, resp);
+
+ // raise an exception
+ throw new EMissingSelfTestException(instanceFullName);
+ }
+
+ try {
+ if (CMS.debugOn()) {
+ CMS.debug("CMSAdminServlet::runSelfTestsOnDemand():"
+ + " running \""
+ + test.getSelfTestName()
+ + "\"");
+ }
+
+ // store this information for console notification
+ content += "CMSAdminServlet::runSelfTestsOnDemand():"
+ + " running \""
+ + test.getSelfTestName()
+ + "\" . . .\n";
+
+ test.runSelfTest(mSelfTestSubsystem.getSelfTestLogger());
+
+ // store this information for console notification
+ content += "COMPLETED SUCCESSFULLY\n";
+ } catch (ESelfTestException e) {
+ // Check to see if the self test was critical:
+ if (mSelfTestSubsystem.isSelfTestCriticalOnDemand(
+ instanceName)) {
+ // log the error
+ logMessage = CMS.getLogMessage(
+ "SELFTESTS_RUN_ON_DEMAND_FAILED",
+ getServletInfo(),
+ instanceFullName);
+
+ mSelfTestSubsystem.log(
+ mSelfTestSubsystem.getSelfTestLogger(),
+ logMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ // notify console of FAILURE
+ content += "FAILED WITH CRITICAL ERROR\n";
+ content += logMessage
+ + "\n";
+ sendResponse(ERROR, content, null, resp);
+
+ // shutdown the system gracefully
+ CMS.shutdown();
+
+ return;
+ } else {
+ // store this information for console notification
+ content += "FAILED WITH NON-CRITICAL ERROR\n";
+ }
+ }
+ }
+
+ // log that execution of all "critical" on-demand self tests
+ // has completed "successfully"
+ logMessage = CMS.getLogMessage("SELFTESTS_RUN_ON_DEMAND_SUCCEEDED",
+ getServletInfo());
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ logMessage);
+
+ // store this information for console notification
+ content += logMessage
+ + "\n";
+ } else {
+ // log this fact
+ logMessage = CMS.getLogMessage("SELFTESTS_NOT_RUN_ON_DEMAND",
+ getServletInfo());
+
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ logMessage);
+
+ // store this information for console notification
+ content += logMessage
+ + "\n";
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION,
+ auditSubjectID,
+ ILogger.SUCCESS);
+
+ audit(auditMessage);
+
+ // notify console of SUCCESS
+ results.put(Constants.PR_RUN_SELFTESTS_ON_DEMAND_CLASS,
+ CMSAdminServlet.class.getName());
+ results.put(Constants.PR_RUN_SELFTESTS_ON_DEMAND_CONTENT,
+ content);
+ sendResponse(SUCCESS, null, results, resp);
+
+ if (CMS.debugOn()) {
+ CMS.debug("CMSAdminServlet::runSelfTestsOnDemand():"
+ + " EXITING.");
+ }
+ } catch (EMissingSelfTestException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (ESelfTestException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ } catch (IOException eAudit3) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit3;
+ }
+ }
+
+ public void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, level, "CMSAdminServlet: " + msg);
+ }
+
+ /**
+ * Signed Audit Log Public Key
+ *
+ * This method is called to obtain the public key from the passed in
+ * "KeyPair" object for a signed audit log message.
+ * <P>
+ *
+ * @param object a Key Pair Object
+ * @return key string containing the public key
+ */
+ private String auditPublicKey(KeyPair object) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ if (object == null) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ byte rawData[] = null;
+
+ rawData = object.getPublic().getEncoded();
+
+ String key = null;
+ StringBuffer sb = new StringBuffer();
+
+ // convert "rawData" into "base64Data"
+ if (rawData != null) {
+ String base64Data = null;
+
+ base64Data = Utils.base64encode(rawData).trim();
+
+ // extract all line separators from the "base64Data"
+ for (int i = 0; i < base64Data.length(); i++) {
+ if (base64Data.substring(i, i).getBytes() != EOL) {
+ sb.append(base64Data.substring(i, i));
+ }
+ }
+ }
+ key = sb.toString();
+
+ if (key != null) {
+ key = key.trim();
+
+ if (key.equals("")) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ } else {
+ return key;
+ }
+ } else {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/GroupMemberProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/admin/GroupMemberProcessor.java
new file mode 100644
index 000000000..399b97d0c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/GroupMemberProcessor.java
@@ -0,0 +1,394 @@
+// --- 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 com.netscape.cms.servlet.admin;
+
+import java.net.URI;
+import java.net.URLEncoder;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.ws.rs.core.MediaType;
+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.ConflictingOperationException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.base.ResourceNotFoundException;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.group.GroupMemberCollection;
+import com.netscape.certsrv.group.GroupMemberData;
+import com.netscape.certsrv.group.GroupNotFoundException;
+import com.netscape.certsrv.group.GroupResource;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.IAuditor;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.cms.servlet.processors.Processor;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class GroupMemberProcessor extends Processor {
+
+ public final static int DEFAULT_SIZE = 20;
+
+ public final static String MULTI_ROLE_ENABLE = "multiroles.enable";
+ public final static String MULTI_ROLE_ENFORCE_GROUP_LIST = "multiroles.false.groupEnforceList";
+
+ public static String[] multiRoleGroupEnforceList;
+
+ public IUGSubsystem userGroupManager = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+
+ protected UriInfo uriInfo;
+
+ public GroupMemberProcessor(Locale locale) throws EBaseException {
+ super("group", locale);
+ }
+
+ public UriInfo getUriInfo() {
+ return uriInfo;
+ }
+
+ public void setUriInfo(UriInfo uriInfo) {
+ this.uriInfo = uriInfo;
+ }
+
+ public GroupMemberData createGroupMemberData(String groupID, String memberID) throws Exception {
+
+ GroupMemberData groupMemberData = new GroupMemberData();
+ groupMemberData.setID(memberID);
+ groupMemberData.setGroupID(groupID);
+
+ URI uri = uriInfo.getBaseUriBuilder()
+ .path(GroupResource.class)
+ .path("{groupID}/members/{memberID}")
+ .build(
+ URLEncoder.encode(groupID, "UTF-8"),
+ URLEncoder.encode(memberID, "UTF-8"));
+
+ groupMemberData.setLink(new Link("self", uri));
+
+ return groupMemberData;
+ }
+
+ public GroupMemberCollection findGroupMembers(String groupID, Integer start, Integer size) {
+ try {
+ start = start == null ? 0 : start;
+ size = size == null ? DEFAULT_SIZE : size;
+
+ if (groupID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID"));
+ }
+
+ IGroup group = userGroupManager.getGroupFromName(groupID);
+ if (group == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_GROUP_NOT_EXIST"));
+ throw new GroupNotFoundException(groupID);
+ }
+
+ GroupMemberCollection response = new GroupMemberCollection();
+
+ Enumeration<String> members = group.getMemberNames();
+
+ int i = 0;
+
+ // skip to the start of the page
+ for ( ; i<start && members.hasMoreElements(); i++) members.nextElement();
+
+ // return entries up to the page size
+ for ( ; i<start+size && members.hasMoreElements(); i++) {
+ String memberID = members.nextElement();
+ response.addMember(createGroupMemberData(groupID, memberID));
+ }
+
+ // count the total entries
+ for ( ; members.hasMoreElements(); i++) members.nextElement();
+
+ 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 response;
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ CMS.debug(e);
+ throw new PKIException(getUserMessage("CMS_INTERNAL_ERROR"));
+ }
+ }
+
+ public GroupMemberData getGroupMember(String groupID, String memberID) {
+ try {
+ if (groupID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID"));
+ }
+
+ IGroup group = userGroupManager.getGroupFromName(groupID);
+ if (group == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_GROUP_NOT_EXIST"));
+ throw new GroupNotFoundException(groupID);
+ }
+
+ Enumeration<String> e = group.getMemberNames();
+ while (e.hasMoreElements()) {
+ String memberName = e.nextElement();
+ if (!memberName.equals(memberID)) continue;
+
+ GroupMemberData groupMemberData = createGroupMemberData(groupID, memberID);
+ return groupMemberData;
+ }
+
+ throw new ResourceNotFoundException("Group member " + memberID + " not found");
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ public Response addGroupMember(GroupMemberData groupMemberData) {
+ String groupID = groupMemberData.getGroupID();
+ try {
+ if (groupID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID"));
+ }
+
+ IGroup group = userGroupManager.getGroupFromName(groupID);
+ if (group == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_GROUP_NOT_EXIST"));
+ throw new GroupNotFoundException(groupID);
+ }
+
+ String memberID = groupMemberData.getID();
+ boolean multiRole = true;
+
+ try {
+ IConfigStore config = CMS.getConfigStore();
+ multiRole = config.getBoolean(MULTI_ROLE_ENABLE);
+ } catch (Exception e) {
+ // ignore
+ }
+
+ if (multiRole) {
+ // a user can be a member of multiple groups
+ userGroupManager.addUserToGroup(group, memberID);
+
+ } else {
+ // a user can be a member of at most one group in the enforce list
+ if (isGroupInMultiRoleEnforceList(groupID)) {
+ // make sure the user is not already a member in another group in the list
+ if (!isDuplicate(groupID, memberID)) {
+ userGroupManager.addUserToGroup(group, memberID);
+ } else {
+ throw new ConflictingOperationException(CMS.getUserMessage("CMS_BASE_DUPLICATE_ROLES", memberID));
+ }
+
+ } else {
+ // the user can be a member of multiple groups outside the list
+ userGroupManager.addUserToGroup(group, memberID);
+ }
+ }
+
+ // for audit log
+ SessionContext sContext = SessionContext.getContext();
+ String adminId = (String) sContext.get(SessionContext.USER_ID);
+
+ logger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP,
+ AuditFormat.LEVEL, AuditFormat.ADDUSERGROUPFORMAT,
+ new Object[] { adminId, memberID, groupID });
+
+ auditAddGroupMember(groupID, groupMemberData, ILogger.SUCCESS);
+
+ // read the data back
+ groupMemberData = getGroupMember(groupID, memberID);
+
+ return Response
+ .created(groupMemberData.getLink().getHref())
+ .entity(groupMemberData)
+ .type(MediaType.APPLICATION_XML)
+ .build();
+
+ } catch (PKIException e) {
+ auditAddGroupMember(groupID, groupMemberData, ILogger.FAILURE);
+ throw e;
+
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ auditAddGroupMember(groupID, groupMemberData, ILogger.FAILURE);
+ throw new PKIException(getUserMessage("CMS_USRGRP_USER_ADD_FAILED"));
+ }
+ }
+
+ public boolean isGroupInMultiRoleEnforceList(String groupID) {
+
+ if (groupID == null || groupID.equals("")) {
+ return true;
+ }
+
+ String groupList = null;
+ if (multiRoleGroupEnforceList == null) {
+ try {
+ IConfigStore config = CMS.getConfigStore();
+ groupList = config.getString(MULTI_ROLE_ENFORCE_GROUP_LIST);
+ } catch (Exception e) {
+ // ignore
+ }
+
+ if (groupList != null && !groupList.equals("")) {
+ multiRoleGroupEnforceList = groupList.split(",");
+ for (int j = 0; j < multiRoleGroupEnforceList.length; j++) {
+ multiRoleGroupEnforceList[j] = multiRoleGroupEnforceList[j].trim();
+ }
+ }
+ }
+
+ if (multiRoleGroupEnforceList == null)
+ return true;
+
+ for (int i = 0; i < multiRoleGroupEnforceList.length; i++) {
+ if (groupID.equals(multiRoleGroupEnforceList[i])) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public boolean isDuplicate(String groupID, String memberID) {
+
+ // Let's not mess with users that are already a member of this group
+ try {
+ boolean isMember = userGroupManager.isMemberOf(memberID, groupID);
+ if (isMember == true) return false;
+
+ } catch (Exception e) {
+ // ignore
+ }
+
+ try {
+ Enumeration<IGroup> groups = userGroupManager.listGroups("*");
+ while (groups.hasMoreElements()) {
+ IGroup group = groups.nextElement();
+ String name = group.getName();
+
+ Enumeration<IGroup> g = userGroupManager.findGroups(name);
+ IGroup g1 = g.nextElement();
+
+ if (!name.equals(groupID)) {
+ if (isGroupInMultiRoleEnforceList(name)) {
+ Enumeration<String> members = g1.getMemberNames();
+ while (members.hasMoreElements()) {
+ String m1 = members.nextElement();
+ if (m1.equals(memberID))
+ return true;
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+
+ return false;
+ }
+
+ public void removeGroupMember(String groupID, String memberID) {
+ GroupMemberData groupMemberData = new GroupMemberData();
+ groupMemberData.setID(memberID);
+ groupMemberData.setGroupID(groupID);
+ removeGroupMember(groupMemberData);
+ }
+
+ public void removeGroupMember(GroupMemberData groupMemberData) {
+ String groupID = groupMemberData.getGroupID();
+ try {
+ if (groupID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID"));
+ }
+
+ IGroup group = userGroupManager.getGroupFromName(groupID);
+ if (group == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_GROUP_NOT_EXIST"));
+ throw new GroupNotFoundException(groupID);
+ }
+
+ String memberID = groupMemberData.getID();
+ userGroupManager.removeUserFromGroup(group, memberID);
+
+ // for audit log
+ SessionContext sContext = SessionContext.getContext();
+ String adminId = (String) sContext.get(SessionContext.USER_ID);
+
+ logger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP,
+ AuditFormat.LEVEL, AuditFormat.REMOVEUSERGROUPFORMAT,
+ new Object[] { adminId, memberID, groupID });
+
+ auditDeleteGroupMember(groupID, groupMemberData, ILogger.SUCCESS);
+
+ } catch (PKIException e) {
+ auditDeleteGroupMember(groupID, groupMemberData, ILogger.FAILURE);
+ throw e;
+
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ auditDeleteGroupMember(groupID, groupMemberData, ILogger.FAILURE);
+ throw new PKIException(getUserMessage("CMS_USRGRP_USER_ADD_FAILED"));
+ }
+ }
+
+ public void log(int level, String message) {
+ log(ILogger.S_USRGRP, level, message);
+ }
+
+ public void auditAddGroupMember(String groupID, GroupMemberData groupMemberData, String status) {
+ audit(OpDef.OP_ADD, groupID, getParams(groupMemberData), status);
+ }
+
+ public void auditDeleteGroupMember(String groupID, GroupMemberData groupMemberData, String status) {
+ audit(OpDef.OP_DELETE, groupID, getParams(groupMemberData), status);
+ }
+
+ public void audit(String type, String id, Map<String, String> params, String status) {
+ audit(IAuditor.LOGGING_SIGNED_AUDIT_CONFIG_ROLE, ScopeDef.SC_GROUP_MEMBERS, type, id, params, status);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/GroupService.java b/base/server/cms/src/com/netscape/cms/servlet/admin/GroupService.java
new file mode 100644
index 000000000..91fec08c4
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/GroupService.java
@@ -0,0 +1,423 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.admin;
+
+import java.net.URI;
+import java.net.URLEncoder;
+import java.util.Enumeration;
+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.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.commons.lang.StringUtils;
+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.EBaseException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.group.GroupCollection;
+import com.netscape.certsrv.group.GroupData;
+import com.netscape.certsrv.group.GroupMemberCollection;
+import com.netscape.certsrv.group.GroupMemberData;
+import com.netscape.certsrv.group.GroupNotFoundException;
+import com.netscape.certsrv.group.GroupResource;
+import com.netscape.certsrv.logging.IAuditor;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.cms.servlet.base.PKIService;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class GroupService extends PKIService implements GroupResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public final static int DEFAULT_SIZE = 20;
+
+ public IUGSubsystem userGroupManager = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+
+ public GroupData createGroupData(IGroup group) throws Exception {
+
+ GroupData groupData = new GroupData();
+
+ String id = group.getGroupID();
+ if (!StringUtils.isEmpty(id)) groupData.setID(id);
+
+ String description = group.getDescription();
+ if (!StringUtils.isEmpty(description)) groupData.setDescription(description);
+
+ String groupID = URLEncoder.encode(groupData.getID(), "UTF-8");
+ URI uri = uriInfo.getBaseUriBuilder().path(GroupResource.class).path("{groupID}").build(groupID);
+ groupData.setLink(new Link("self", uri));
+
+ return groupData;
+ }
+
+ /**
+ * Searches for users in LDAP directory.
+ *
+ * Request/Response Syntax:
+ * http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ */
+ @Override
+ public GroupCollection findGroups(String filter, Integer start, Integer size) {
+ try {
+ filter = StringUtils.isEmpty(filter) ? "*" : "*"+LDAPUtil.escapeFilter(filter)+"*";
+ start = start == null ? 0 : start;
+ size = size == null ? DEFAULT_SIZE : size;
+
+ Enumeration<IGroup> groups = userGroupManager.listGroups(filter);
+
+ GroupCollection response = new GroupCollection();
+
+ int i = 0;
+
+ // skip to the start of the page
+ for ( ; i<start && groups.hasMoreElements(); i++) groups.nextElement();
+
+ // return entries up to the page size
+ for ( ; i<start+size && groups.hasMoreElements(); i++) {
+ IGroup group = groups.nextElement();
+ response.addGroup(createGroupData(group));
+ }
+
+ // count the total entries
+ for ( ; groups.hasMoreElements(); i++) groups.nextElement();
+
+ 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 response;
+
+ } catch (Exception e) {
+ throw new PKIException(getUserMessage("CMS_INTERNAL_ERROR", headers));
+ }
+ }
+
+ /**
+ * finds a group
+ * Request/Response Syntax:
+ * http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ */
+ @Override
+ public GroupData getGroup(String groupID) {
+
+ try {
+ if (groupID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID", headers));
+ }
+
+ IGroup group = userGroupManager.getGroupFromName(groupID);
+ if (group == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_GROUP_NOT_EXIST"));
+ throw new GroupNotFoundException(groupID);
+ }
+
+ return createGroupData(group);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ throw new PKIException(getUserMessage("CMS_INTERNAL_ERROR", headers));
+ }
+ }
+
+ /**
+ * Adds a new group in local scope.
+ * <P>
+ *
+ * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#group
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ */
+ @Override
+ public Response addGroup(GroupData groupData) {
+
+ String groupID = groupData.getID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ if (groupID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID", headers));
+ }
+
+ IGroup group = userGroupManager.createGroup(groupID);
+
+ String description = groupData.getDescription();
+ if (description != null) {
+ group.set("description", description);
+ } else {
+ group.set("description", "");
+ }
+
+ // allow adding a group with no members
+ try {
+ userGroupManager.addGroup(group);
+
+ auditAddGroup(groupID, groupData, ILogger.SUCCESS);
+
+ // read the data back
+ groupData = getGroup(groupID);
+
+ return Response
+ .created(groupData.getLink().getHref())
+ .entity(groupData)
+ .type(MediaType.APPLICATION_XML)
+ .build();
+
+ } catch (Exception e) {
+ throw new PKIException(getUserMessage("CMS_USRGRP_GROUP_ADD_FAILED", headers));
+ }
+
+ } catch (PKIException e) {
+ auditAddGroup(groupID, groupData, ILogger.FAILURE);
+ throw e;
+
+ } catch (EBaseException e) {
+ auditAddGroup(groupID, groupData, ILogger.FAILURE);
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ /**
+ * modifies a group
+ * <P>
+ *
+ * last person of the super power group "Certificate Server Administrators" can never be removed.
+ * <P>
+ *
+ * http://warp.mcom.com/server/certificate/columbo/design/ ui/admin-protocol-definition.html#group
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ */
+ @Override
+ public Response modifyGroup(String groupID, GroupData groupData) {
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ if (groupID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID", headers));
+ }
+
+ IGroup group = userGroupManager.getGroupFromName(groupID);
+
+ group.set("description", groupData.getDescription());
+
+ // allow adding a group with no members, except "Certificate
+ // Server Administrators"
+ try {
+ userGroupManager.modifyGroup(group);
+
+ auditModifyGroup(groupID, groupData, ILogger.SUCCESS);
+
+ // read the data back
+ groupData = getGroup(groupID);
+
+ return Response
+ .ok(groupData)
+ .type(MediaType.APPLICATION_XML)
+ .build();
+
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ throw new PKIException(getUserMessage("CMS_USRGRP_GROUP_MODIFY_FAILED", headers));
+ }
+
+ } catch (PKIException e) {
+ auditModifyGroup(groupID, groupData, ILogger.FAILURE);
+ throw e;
+
+ } catch (EBaseException e) {
+ auditModifyGroup(groupID, groupData, ILogger.FAILURE);
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ /**
+ * removes a group
+ * <P>
+ *
+ * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#group
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ */
+ @Override
+ public void removeGroup(String groupID) {
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ if (groupID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID", headers));
+ }
+
+ // if fails, let the exception fall through
+ userGroupManager.removeGroup(groupID);
+
+ auditDeleteGroup(groupID, ILogger.SUCCESS);
+
+ } catch (PKIException e) {
+ auditDeleteGroup(groupID, ILogger.FAILURE);
+ throw e;
+
+ } catch (EBaseException e) {
+ auditDeleteGroup(groupID, ILogger.FAILURE);
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public GroupMemberCollection findGroupMembers(String groupID, Integer start, Integer size) {
+ try {
+ GroupMemberProcessor processor = new GroupMemberProcessor(getLocale(headers));
+ processor.setUriInfo(uriInfo);
+ return processor.findGroupMembers(groupID, start, size);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ throw new PKIException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public GroupMemberData getGroupMember(String groupID, String memberID) {
+ try {
+ GroupMemberProcessor processor = new GroupMemberProcessor(getLocale(headers));
+ processor.setUriInfo(uriInfo);
+ return processor.getGroupMember(groupID, memberID);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ throw new PKIException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public Response addGroupMember(String groupID, String memberID) {
+ GroupMemberData groupMemberData = new GroupMemberData();
+ groupMemberData.setID(memberID);
+ groupMemberData.setGroupID(groupID);
+ return addGroupMember(groupMemberData);
+ }
+
+ public Response addGroupMember(GroupMemberData groupMemberData) {
+ try {
+ GroupMemberProcessor processor = new GroupMemberProcessor(getLocale(headers));
+ processor.setUriInfo(uriInfo);
+ return processor.addGroupMember(groupMemberData);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ throw new PKIException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public void removeGroupMember(String groupID, String memberID) {
+ try {
+ GroupMemberProcessor processor = new GroupMemberProcessor(getLocale(headers));
+ processor.setUriInfo(uriInfo);
+ processor.removeGroupMember(groupID, memberID);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ throw new PKIException(e.getMessage(), e);
+ }
+ }
+
+ public void log(int level, String message) {
+ log(ILogger.S_USRGRP, level, message);
+ }
+
+ public void auditAddGroup(String groupID, GroupData groupData, String status) {
+ audit(OpDef.OP_ADD, groupID, getParams(groupData), status);
+ }
+
+ public void auditModifyGroup(String groupID, GroupData groupData, String status) {
+ audit(OpDef.OP_MODIFY, groupID, getParams(groupData), status);
+ }
+
+ public void auditDeleteGroup(String groupID, String status) {
+ audit(OpDef.OP_DELETE, groupID, null, status);
+ }
+
+ public void audit(String type, String id, Map<String, String> params, String status) {
+ audit(IAuditor.LOGGING_SIGNED_AUDIT_CONFIG_ROLE, ScopeDef.SC_GROUPS, type, id, params, status);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/JobsAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/JobsAdminServlet.java
new file mode 100644
index 000000000..314a4072f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/JobsAdminServlet.java
@@ -0,0 +1,1006 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.DestDef;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.jobs.EJobsException;
+import com.netscape.certsrv.jobs.IJob;
+import com.netscape.certsrv.jobs.IJobsScheduler;
+import com.netscape.certsrv.jobs.JobPlugin;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A class representing an administration servlet for the
+ * Jobs Scheduler and it's scheduled jobs.
+ *
+ * @version $Revision$, $Date$
+ */
+public class JobsAdminServlet extends AdminServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 561767449283982015L;
+ // ... remove later
+ private final static String VISIBLE = ";visible";
+ private final static String ENABLED = ";enabled";
+ private final static String DISABLED = ";disabled";
+
+ private final static String INFO = "JobsAdminServlet";
+ private IJobsScheduler mJobsSched = null;
+
+ /**
+ * Constructs JobsAdminServlet.
+ */
+ public JobsAdminServlet() {
+ super();
+ }
+
+ /**
+ * Initializes this servlet.
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ mJobsSched = (IJobsScheduler)
+ CMS.getSubsystem(CMS.SUBSYSTEM_JOBS);
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * retrieve extended plugin info such as brief description, type info
+ * from jobs
+ */
+ private void getExtendedPluginInfo(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ int colon = id.indexOf(':');
+
+ String implType = id.substring(0, colon);
+ String implName = id.substring(colon + 1);
+
+ NameValuePairs params =
+ getExtendedPluginInfo(getLocale(req), implType, implName);
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private NameValuePairs getExtendedPluginInfo(Locale locale, String implType, String implName) {
+ IExtendedPluginInfo ext_info = null;
+ Object impl = null;
+
+ JobPlugin jp =
+ mJobsSched.getPlugins().get(implName);
+
+ if (jp != null)
+ impl = getClassByNameAsExtendedPluginInfo(jp.getClassPath());
+ if (impl != null) {
+ if (impl instanceof IExtendedPluginInfo) {
+ ext_info = (IExtendedPluginInfo) impl;
+ }
+ }
+
+ NameValuePairs nvps = null;
+
+ if (ext_info == null) {
+ nvps = new NameValuePairs();
+ } else {
+ nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale));
+ }
+
+ return nvps;
+
+ }
+
+ /**
+ * Serves HTTP admin request.
+ */
+ public void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+
+ String scope = req.getParameter(Constants.OP_SCOPE);
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op == null) {
+ //System.out.println("SRVLT_INVALID_PROTOCOL");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"),
+ null, resp);
+ return;
+ }
+
+ try {
+ super.authenticate(req);
+ } catch (IOException e) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHS_FAILED"),
+ null, resp);
+ return;
+ }
+
+ try {
+ AUTHZ_RES_NAME = "certServer.job.configuration";
+ if (op.equals(OpDef.OP_READ)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_JOBS))
+ getSettings(req, resp);
+ else if (scope.equals(ScopeDef.SC_JOBS_IMPLS))
+ getConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_JOBS_INSTANCE))
+ getInstConfig(req, resp);
+ else if (scope.equals(ScopeDef.SC_EXTENDED_PLUGIN_INFO)) {
+ try {
+ getExtendedPluginInfo(req, resp);
+ } catch (EBaseException e) {
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ }
+ } else {
+ //System.out.println("SRVLT_INVALID_OP_SCOPE");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_JOBS)) {
+ setSettings(req, resp);
+ } else if (scope.equals(ScopeDef.SC_JOBS_INSTANCE)) {
+ modJobsInst(req, resp, scope);
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_SEARCH)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_JOBS_IMPLS))
+ listJobPlugins(req, resp);
+ else if (scope.equals(ScopeDef.SC_JOBS_INSTANCE))
+ listJobsInsts(req, resp);
+ else {
+ //System.out.println("SRVLT_INVALID_OP_SCOPE");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_ADD)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_JOBS_IMPLS))
+ addJobPlugin(req, resp, scope);
+ else if (scope.equals(ScopeDef.SC_JOBS_INSTANCE))
+ addJobsInst(req, resp, scope);
+ else {
+ //System.out.println("SRVLT_INVALID_OP_SCOPE");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_JOBS_IMPLS))
+ delJobPlugin(req, resp, scope);
+ else if (scope.equals(ScopeDef.SC_JOBS_INSTANCE))
+ delJobsInst(req, resp, scope);
+ else {
+ //System.out.println("SRVLT_INVALID_OP_SCOPE");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_TYPE", op),
+ null, resp);
+ return;
+ }
+ } catch (EBaseException e) {
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ }
+ }
+
+ private synchronized void addJobPlugin(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+ // is the job plugin id unique?
+ if (mJobsSched.getPlugins().containsKey(id)) {
+ sendResponse(ERROR,
+ new EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_ILL_JOB_PLUGIN_ID", id))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ String classPath = req.getParameter(Constants.PR_JOBS_CLASS);
+
+ if (classPath == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_NULL_CLASS"),
+ null, resp);
+ return;
+ }
+
+ IConfigStore destStore =
+ mConfig.getSubStore(DestDef.DEST_JOBS_ADMIN);
+ IConfigStore instancesConfig =
+ destStore.getSubStore(scope);
+
+ // Does the class exist?
+ Class<?> newImpl = null;
+
+ try {
+ newImpl = Class.forName(classPath);
+ } catch (ClassNotFoundException e) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_NO_CLASS"),
+ null, resp);
+ return;
+ } catch (IllegalArgumentException e) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_NO_CLASS"),
+ null, resp);
+ return;
+ }
+
+ // is the class an IJob?
+ try {
+ if (IJob.class.isAssignableFrom(newImpl) == false) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_ILL_CLASS"),
+ null, resp);
+ return;
+ }
+ } catch (NullPointerException e) { // unlikely, only if newImpl null.
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_ILL_CLASS"),
+ null, resp);
+ return;
+ }
+
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ substore.put(Constants.PR_JOBS_CLASS, classPath);
+
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // add manager to registry.
+ JobPlugin plugin = new JobPlugin(id, classPath);
+
+ mJobsSched.getPlugins().put(id, plugin);
+ mJobsSched.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_JS_PLUGIN_ADD", id));
+
+ NameValuePairs params = new NameValuePairs();
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void addJobsInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // is the job instance id unique?
+ if (mJobsSched.getInstances().containsKey(id)) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_ILL_JOB_INST_ID"),
+ null, resp);
+ return;
+ }
+
+ // get required parameters
+ // SC_JOBS_IMPL_NAME is absolutely required, the rest depend on
+ // on each job plugin
+ String implname = req.getParameter(Constants.PR_JOBS_IMPL_NAME);
+
+ if (implname == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_ADD_MISSING_PARAMS"),
+ null, resp);
+ return;
+ }
+
+ // check if implementation exists.
+ JobPlugin plugin =
+ mJobsSched.getPlugins().get(implname);
+
+ if (plugin == null) {
+ sendResponse(ERROR,
+ new
+ EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_JOB_PLUGIN_NOT_FOUND",
+ id)).toString(),
+ null, resp);
+ return;
+ }
+
+ // now the rest of config parameters
+ // note that we only check to see if the required parameters
+ // are there, but not checking the values are valid
+ String[] configParams = mJobsSched.getConfigParams(implname);
+
+ IConfigStore destStore =
+ mConfig.getSubStore(DestDef.DEST_JOBS_ADMIN);
+ IConfigStore instancesConfig =
+ destStore.getSubStore(scope);
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ if (configParams != null) {
+ for (int i = 0; i < configParams.length; i++) {
+ String key = configParams[i];
+ String val = req.getParameter(key);
+
+ if (val != null && !val.equals("")) {
+ substore.put(key, val);
+ } else if (!key.equals("profileId")) {
+ sendResponse(ERROR,
+ new
+ EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_MISSING_INST_PARAM_VAL",
+ key)).toString(),
+ null, resp);
+ return;
+ }
+ }
+ }
+
+ substore.put(IJobsScheduler.PROP_PLUGIN, implname);
+
+ // Instantiate an object for this implementation
+ String className = plugin.getClassPath();
+ IJob jobsInst = null;
+
+ try {
+ jobsInst = (IJob) Class.forName(className).newInstance();
+ } catch (ClassNotFoundException e) {
+ // cleanup
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ new EJobsException(
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_LOAD_CLASS_FAILED", className)).toString(),
+ null, resp);
+ return;
+ } catch (InstantiationException e) {
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ new EJobsException(
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_LOAD_CLASS_FAILED", className)).toString(),
+ null, resp);
+ return;
+ } catch (IllegalAccessException e) {
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ new EJobsException(
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_LOAD_CLASS_FAILED", className)).toString(),
+ null, resp);
+ return;
+ }
+
+ IJobsScheduler scheduler = (IJobsScheduler)
+ CMS.getSubsystem(CMS.SUBSYSTEM_JOBS);
+
+ // initialize the job plugin
+ try {
+ jobsInst.init(scheduler, id, implname, substore);
+ } catch (EBaseException e) {
+ // don't commit in this case and cleanup the new substore.
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ }
+
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // clean up.
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // inited and commited ok. now add manager instance to list.
+ mJobsSched.getInstances().put(id, jobsInst);
+
+ mJobsSched.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_JOB_INST_ADD", id));
+
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_JOBS_IMPL_NAME, implname);
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void listJobPlugins(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = mJobsSched.getPlugins().keys();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+ JobPlugin value = mJobsSched.getPlugins().get(name);
+
+ params.put(name, value.getClassPath());
+ // params.add(name, value.getClassPath()+EDIT);
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void listJobsInsts(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+
+ for (Enumeration<String> e = mJobsSched.getInstances().keys(); e.hasMoreElements();) {
+ String name = e.nextElement();
+ IJob value = mJobsSched.getInstances().get(name);
+
+ // params.add(name, value.getImplName());
+ params.put(name, value.getImplName() + VISIBLE +
+ (value.isEnabled() ? ENABLED : DISABLED)
+ );
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void delJobPlugin(HttpServletRequest req,
+ HttpServletResponse resp, String scope) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // does this job plugin exist?
+ if (mJobsSched.getPlugins().containsKey(id) == false) {
+ sendResponse(ERROR,
+ new
+ EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_JOB_PLUGIN_NOT_FOUND",
+ id)).toString(),
+ null, resp);
+ return;
+ }
+
+ // first check if any instances from this job plugin
+ // DON'T remove job plugin if any instance
+ for (Enumeration<IJob> e = mJobsSched.getInstances().elements(); e.hasMoreElements();) {
+ IJob jobs = e.nextElement();
+
+ if ((jobs.getImplName()).equals(id)) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_JOB_IN_USE"),
+ null, resp);
+ return;
+ }
+ }
+
+ // then delete this job plugin
+ mJobsSched.getPlugins().remove(id);
+
+ IConfigStore destStore =
+ mConfig.getSubStore(DestDef.DEST_JOBS_ADMIN);
+ IConfigStore instancesConfig =
+ destStore.getSubStore(scope);
+
+ instancesConfig.removeSubStore(id);
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void delJobsInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // does job plugin instance exist?
+ if (mJobsSched.getInstances().containsKey(id) == false) {
+ sendResponse(ERROR,
+ new EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_JOB_NOT_FOUND",
+ id)).toString(),
+ null, resp);
+ return;
+ }
+
+ // only remove from memory
+ // cannot shutdown because we don't keep track of whether it's
+ // being used.
+ mJobsSched.getInstances().remove(id);
+
+ // remove the configuration.
+ IConfigStore destStore =
+ mConfig.getSubStore(DestDef.DEST_JOBS_ADMIN);
+ IConfigStore instancesConfig =
+ destStore.getSubStore(scope);
+
+ instancesConfig.removeSubStore(id);
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ /**
+ * used for getting the required configuration parameters (with
+ * possible default values) for a particular job plugin
+ * implementation name specified in the RS_ID. Actually, there is
+ * no logic in here to set any default value here...there's no
+ * default value for any parameter in this job scheduler subsystem
+ * at this point. Later, if we do have one (or some), it can be
+ * added. The interface remains the same.
+ */
+ private synchronized void getConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+
+ String implname = req.getParameter(Constants.RS_ID);
+
+ if (implname == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ String[] configParams = mJobsSched.getConfigParams(implname);
+ NameValuePairs params = new NameValuePairs();
+
+ // implName is always required so always send it.
+ params.put(Constants.PR_JOBS_IMPL_NAME, "");
+ if (configParams != null) {
+ for (int i = 0; i < configParams.length; i++) {
+ params.put(configParams[i], "");
+ }
+ }
+ sendResponse(0, null, params, resp);
+ return;
+ }
+
+ private synchronized void getInstConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // does job plugin instance exist?
+ if (mJobsSched.getInstances().containsKey(id) == false) {
+ sendResponse(ERROR,
+ new EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_JOB_NOT_FOUND",
+ id)).toString(),
+ null, resp);
+ return;
+ }
+
+ IJob jobInst = mJobsSched.getInstances().get(id);
+ IConfigStore config = jobInst.getConfigStore();
+ String[] configParams = jobInst.getConfigParams();
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_JOBS_IMPL_NAME, jobInst.getImplName());
+
+ // implName is always required so always send it.
+ if (configParams != null) {
+ for (int i = 0; i < configParams.length; i++) {
+ String key = configParams[i];
+
+ String val = config.get(key);
+
+ if (val != null && !val.equals("")) {
+ params.put(key, val);
+ } else {
+ params.put(key, "");
+ }
+ }
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ /**
+ * Modify job plugin instance.
+ * This will actually create a new instance with new configuration
+ * parameters and replace the old instance, if the new instance
+ * created and initialized successfully.
+ * The old instance is left running. so this is very expensive.
+ * Restart of server recommended.
+ */
+ private synchronized void modJobsInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+
+ // expensive operation.
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // Does the job instance exist?
+ if (!mJobsSched.getInstances().containsKey(id)) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_ILL_JOB_INST_ID"),
+ null, resp);
+ return;
+ }
+
+ // get new implementation (same or different.)
+ String implname = req.getParameter(Constants.PR_JOBS_IMPL_NAME);
+
+ if (implname == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_ADD_MISSING_PARAMS"),
+ null, resp);
+ return;
+ }
+
+ // get plugin for implementation
+ JobPlugin plugin =
+ mJobsSched.getPlugins().get(implname);
+
+ if (plugin == null) {
+ sendResponse(ERROR,
+ new EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_JOB_PLUGIN_NOT_FOUND",
+ id)).toString(),
+ null, resp);
+ return;
+ }
+
+ // save old instance substore params in case new one fails.
+
+ IJob oldinst =
+ mJobsSched.getInstances().get(id);
+ IConfigStore oldConfig = oldinst.getConfigStore();
+
+ String[] oldConfigParms = oldinst.getConfigParams();
+ NameValuePairs saveParams = new NameValuePairs();
+
+ // implName is always required so always include it it.
+ saveParams.put(IJobsScheduler.PROP_PLUGIN,
+ oldConfig.get(IJobsScheduler.PROP_PLUGIN));
+ if (oldConfigParms != null) {
+ for (int i = 0; i < oldConfigParms.length; i++) {
+ String key = oldConfigParms[i];
+ Object val = oldConfig.get(key);
+
+ if (val != null) {
+ saveParams.put(key, (String) val);
+ }
+ }
+ }
+
+ // on to the new instance.
+
+ // remove old substore.
+
+ IConfigStore destStore =
+ mConfig.getSubStore(DestDef.DEST_JOBS_ADMIN);
+ IConfigStore instancesConfig =
+ destStore.getSubStore(scope);
+
+ instancesConfig.removeSubStore(id);
+
+ // create new substore.
+
+ String[] configParams = mJobsSched.getConfigParams(implname);
+
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ substore.put(IJobsScheduler.PROP_PLUGIN, implname);
+ if (configParams != null) {
+ for (int i = 0; i < configParams.length; i++) {
+ String key = configParams[i];
+ String val = req.getParameter(key);
+
+ if (val != null && !val.equals("")) {
+ substore.put(key, val);
+ } else if (!key.equals("profileId")) {
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR,
+ new
+ EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_MISSING_INST_PARAM_VAL",
+ key)).toString(),
+ null, resp);
+ return;
+ }
+ }
+ }
+ // Instantiate an object for new implementation
+
+ String className = plugin.getClassPath();
+ IJob newJobInst = null;
+
+ try {
+ newJobInst = (IJob) Class.forName(className).newInstance();
+ } catch (ClassNotFoundException e) {
+ // cleanup
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR,
+ new EJobsException(
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_LOAD_CLASS_FAILED", className)).toString(),
+ null, resp);
+ return;
+ } catch (InstantiationException e) {
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR,
+ new EJobsException(
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_LOAD_CLASS_FAILED", className)).toString(),
+ null, resp);
+ return;
+ } catch (IllegalAccessException e) {
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR,
+ new EJobsException(
+ CMS.getUserMessage(getLocale(req), "CMS_JOB_LOAD_CLASS_FAILED", className)).toString(),
+ null, resp);
+ return;
+ }
+
+ // initialize the job plugin
+
+ IJobsScheduler scheduler = (IJobsScheduler)
+ CMS.getSubsystem(CMS.SUBSYSTEM_JOBS);
+
+ try {
+ newJobInst.init(scheduler, id, implname, substore);
+ } catch (EBaseException e) {
+ // don't commit in this case and cleanup the new substore.
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ } catch (Exception e) {
+ CMS.debug("JobsAdminServlet: modJobsInst: " + e);
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR, "unidentified error" + e, null, resp);
+ return;
+ }
+
+ // initialized ok. commiting
+ try {
+ mConfig.commit(true);
+
+ } catch (EBaseException e) {
+ // clean up.
+ restore(instancesConfig, id, saveParams);
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // commited ok. replace instance.
+
+ mJobsSched.getInstances().put(id, newJobInst);
+
+ mJobsSched.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_JOB_INST_REP", id));
+
+ NameValuePairs params = new NameValuePairs();
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private void getSettings(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ IConfigStore config = mConfig.getSubStore(DestDef.DEST_JOBS_ADMIN);
+
+ params.put(Constants.PR_ENABLE,
+ config.getString(IJobsScheduler.PROP_ENABLED,
+ Constants.FALSE));
+ // default 1 minute
+ params.put(Constants.PR_JOBS_FREQUENCY,
+ config.getString(IJobsScheduler.PROP_INTERVAL, "1"));
+
+ //System.out.println("Send: "+params.toString());
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void setSettings(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ //Save New Settings to the config file
+ IConfigStore config = mConfig.getSubStore(DestDef.DEST_JOBS_ADMIN);
+
+ String enabled = config.getString(IJobsScheduler.PROP_ENABLED);
+ String enabledSetTo = req.getParameter(Constants.PR_ENABLE);
+ boolean enabledChanged = false;
+
+ if (!enabled.equalsIgnoreCase(enabledSetTo)) {
+ enabledChanged = true;
+ // set enable flag
+ config.putString(IJobsScheduler.PROP_ENABLED, enabledSetTo);
+ }
+
+ //set frequency
+ String interval =
+ req.getParameter(Constants.PR_JOBS_FREQUENCY);
+
+ if (interval != null) {
+ config.putString(IJobsScheduler.PROP_INTERVAL, interval);
+ mJobsSched.setInterval(
+ config.getInteger(IJobsScheduler.PROP_INTERVAL));
+ }
+
+ if (enabledChanged == true) {
+ if (enabled.equalsIgnoreCase("false")) { // turned on
+ mJobsSched.startDaemon();
+ }
+ }
+ mConfig.commit(true);
+
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ // convenience routine.
+ private static void restore(IConfigStore store,
+ String id, NameValuePairs saveParams) {
+ store.removeSubStore(id);
+ IConfigStore rstore = store.makeSubStore(id);
+
+ for (String key : saveParams.keySet()) {
+ String value = saveParams.get(key);
+
+ if (!value.equals(""))
+ rstore.put(key, value);
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/KRAAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/KRAAdminServlet.java
new file mode 100644
index 000000000..3f9f558e0
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/KRAAdminServlet.java
@@ -0,0 +1,233 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A class representings an administration servlet for Key
+ * Recovery Authority. This servlet is responsible to serve
+ * KRA administrative operation such as configuration
+ * parameter updates.
+ *
+ * @version $Revision$, $Date$
+ */
+public class KRAAdminServlet extends AdminServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5794220348195666729L;
+
+ protected static final String PROP_ENABLED = "enabled";
+
+ private final static String INFO = "KRAAdminServlet";
+
+ private IKeyRecoveryAuthority mKRA = null;
+
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_DRM =
+ "LOGGING_SIGNED_AUDIT_CONFIG_DRM_3";
+
+ /**
+ * Constructs KRA servlet.
+ */
+ public KRAAdminServlet() {
+ super();
+ }
+
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ mKRA = (IKeyRecoveryAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_KRA);
+ }
+
+ /**
+ * Returns serlvet information.
+ *
+ * @return name of this servlet
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Serves HTTP admin request.
+ *
+ * @param req HTTP request
+ * @param resp HTTP response
+ */
+ public void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+
+ super.authenticate(req);
+ String scope = req.getParameter(Constants.OP_SCOPE);
+
+ if (scope == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_TYPE", op),
+ null, resp);
+ return;
+ }
+
+ try {
+ AUTHZ_RES_NAME = "certServer.kra.configuration";
+ if (op.equals(OpDef.OP_READ)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ /* Functions not implemented in console
+ if (scope.equals(ScopeDef.SC_AUTO_RECOVERY)) {
+ readAutoRecoveryConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_RECOVERY)) {
+ readRecoveryConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_NOTIFICATION_RIQ)) {
+ getNotificationRIQConfig(req, resp);
+ return;
+ } else
+ */
+ if (scope.equals(ScopeDef.SC_GENERAL)) {
+ getGeneralConfig(req, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ /* Functions not implemented in console
+ if (scope.equals(ScopeDef.SC_AUTO_RECOVERY)) {
+ modifyAutoRecoveryConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_AGENT_PWD)) {
+ changeAgentPwd(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_MNSCHEME)) {
+ changeMNScheme(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_NOTIFICATION_RIQ)) {
+ setNotificationRIQConfig(req, resp);
+ return;
+ } else
+ */
+ if (scope.equals(ScopeDef.SC_GENERAL)) {
+ setGeneralConfig(req, resp);
+ }
+ }
+ } catch (EBaseException e) {
+ // convert exception into locale-specific message
+ sendResponse(ERROR, e.toString(getLocale(req)),
+ null, resp);
+ return;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"),
+ null, resp);
+ }
+
+ private void getGeneralConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ int value = 1;
+
+ value = mKRA.getNoOfRequiredAgents();
+ params.put(Constants.PR_NO_OF_REQUIRED_RECOVERY_AGENTS, Integer.toString(value));
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void setGeneralConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ Enumeration<String> enum1 = req.getParameterNames();
+ boolean restart = false;
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.PR_NO_OF_REQUIRED_RECOVERY_AGENTS)) {
+ try {
+ int number = Integer.parseInt(value);
+ mKRA.setNoOfRequiredAgents(number);
+ } catch (NumberFormatException e) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_DRM,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ throw new EBaseException("Number of agents must be an integer");
+ }
+ }
+ }
+
+ commit(true);
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_DRM,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ if (restart)
+ sendResponse(RESTART, null, null, resp);
+ else
+ sendResponse(SUCCESS, null, null, resp);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/KRAConnectorProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/admin/KRAConnectorProcessor.java
new file mode 100644
index 000000000..61536f346
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/KRAConnectorProcessor.java
@@ -0,0 +1,223 @@
+// --- 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 com.netscape.cms.servlet.admin;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+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.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.ca.ICAService;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.connector.IConnector;
+import com.netscape.certsrv.system.KRAConnectorInfo;
+import com.netscape.cms.servlet.processors.Processor;
+
+/**
+ * @author Ade Lee
+ */
+public class KRAConnectorProcessor extends Processor {
+ private boolean connectorExists = false;
+
+ // Connector constants
+ public final static String PREFIX = "ca.connector.KRA";
+
+ public KRAConnectorProcessor(Locale locale) throws EPropertyNotFound, EBaseException {
+ super("kraconnector", locale);
+ ICertificateAuthority ca = (ICertificateAuthority)CMS.getSubsystem("ca");
+ ICAService caService = (ICAService)ca.getCAService();
+ connectorExists = (caService.getKRAConnector() != null)? true:false;
+ }
+
+ public void removeConnector(String newHost, String newPort) throws EPropertyNotFound, EBaseException {
+ if (! connectorExists) {
+ CMS.debug("removeConnector: no KRA connector exists, returning success");
+ return;
+ }
+
+ if ((newHost == null) || (newPort == null)) {
+ CMS.debug("removeConnector: malformed request. newHost or newPort is null");
+ throw new BadRequestException("Bad Request: KRA Host or Port not defined");
+ }
+ IConfigStore cs = CMS.getConfigStore();
+ String host = cs.getString(PREFIX + ".host");
+ String port = cs.getString(PREFIX + ".port");
+
+ if ((host == null) || (port == null)) {
+ CMS.debug("removeConnector: bad connector configuration - host or port are null");
+ throw new PKIException("Bad Connector configuration on this CA");
+ }
+
+ String hostport = newHost + ":" + newPort;
+ if ((host.equals(newHost)) && port.equals(newPort)) {
+ CMS.debug("removeConnector: Removing " + PREFIX + " substore");
+ cs.removeSubStore(PREFIX);
+ cs.commit(true);
+ deleteConnector();
+ } else if (host.indexOf(' ') != -1) { // host is a list
+ String[] hostList = host.trim().split(" ");
+ ArrayList<String> finalList = new ArrayList<String>();
+ for (String h : hostList) {
+ if (! h.equals(hostport)) {
+ finalList.add(h);
+ }
+ }
+ if (finalList.size() == hostList.length) {
+ CMS.debug("removeConnector: no connector for " + hostport + " exists. Returning success");
+ return;
+ }
+
+ CMS.debug("removeConnector: Removing " + hostport + " from " + PREFIX);
+
+ if (finalList.size() == 0) {
+ CMS.debug("removeConnector: Removing " + PREFIX + " substore");
+ cs.removeSubStore(PREFIX);
+ cs.commit(true);
+ deleteConnector();
+ } else if (finalList.size() == 1) {
+ cs.putString(PREFIX + ".host", finalList.get(0).split(":")[0]);
+ cs.putString(PREFIX + ".port", finalList.get(0).split(":")[1]);
+ cs.commit(true);
+ replaceConnector();
+ } else {
+ String finalString = StringUtils.join(finalList, " ");
+ cs.putString(PREFIX + ".host", finalString.trim());
+ cs.commit(true);
+ replaceConnector();
+ }
+ } else {
+ CMS.debug("removeConnector: no connector for " + hostport + " exists. Returning success");
+ }
+ }
+
+ public void stopConnector() {
+ ICertificateAuthority ca = (ICertificateAuthority)CMS.getSubsystem("ca");
+ ICAService caService = (ICAService)ca.getCAService();
+ IConnector kraConnector = caService.getKRAConnector();
+ if (kraConnector != null) {
+ kraConnector.stop();
+ }
+ }
+
+ public void startConnector() {
+ ICertificateAuthority ca = (ICertificateAuthority)CMS.getSubsystem("ca");
+ ICAService caService = (ICAService)ca.getCAService();
+ IConnector kraConnector = caService.getKRAConnector();
+ if (kraConnector != null) {
+ kraConnector.start();
+ }
+ }
+
+ public void replaceConnector() throws EBaseException {
+ // stop the old connector
+ stopConnector();
+
+ ICertificateAuthority ca = (ICertificateAuthority)CMS.getSubsystem("ca");
+ ICAService caService = (ICAService)ca.getCAService();
+ IConfigStore cs = CMS.getConfigStore();
+
+ IConnector kraConnector = caService.getConnector(cs.getSubStore(PREFIX));
+ caService.setKRAConnector(kraConnector);
+
+ startConnector();
+ }
+
+ public void deleteConnector() {
+ stopConnector();
+
+ ICertificateAuthority ca = (ICertificateAuthority)CMS.getSubsystem("ca");
+ ICAService caService = (ICAService)ca.getCAService();
+ caService.setKRAConnector(null);
+ }
+
+ public void addConnector(KRAConnectorInfo info) throws EPropertyNotFound, EBaseException {
+ IConfigStore cs = CMS.getConfigStore();
+ String newHost = info.getHost();
+ String newPort = info.getPort();
+ String newTransportCert = info.getTransportCert();
+
+ if ((newHost == null) || (newPort == null) || (newTransportCert == null)) {
+ CMS.debug("addConnector: malformed request. newHost, newPort or transport cert is null");
+ throw new BadRequestException("Bad Request: KRA host, port or transport cert not defined");
+ }
+
+ if (connectorExists) {
+ String host = cs.getString(PREFIX + ".host");
+ String port = cs.getString(PREFIX + ".port");
+
+ if ((!host.equals(newHost)) || (!port.equals(newPort))) { //existing connector is not the same
+
+ // check transport cert
+ String transportCert = cs.getString(PREFIX + ".transportCert");
+ if (!transportCert.equals(newTransportCert)) {
+ CMS.debug("addConnector: Connector is already defined");
+ throw new BadRequestException("KRA connector has already been defined for this CA");
+ }
+
+ String hostport = newHost + ":" + newPort;
+ if (host.indexOf(' ') != -1) { // host is a list
+ String[] hostList = host.trim().split(" ");
+ for (String h : hostList) {
+ if (h.equals(hostport)) {
+ CMS.debug("addConnector: connector for " + hostport +
+ " is already present. Returning success");
+ return;
+ }
+ }
+
+ CMS.debug("addConnector: adding " + hostport + " to KRA connector host list");
+ cs.putString(PREFIX + ".host", host + " " + hostport);
+ cs.commit(true);
+ replaceConnector();
+ return;
+ } else { // host is not a list, turn it into one
+ CMS.debug("addConnector: adding " + hostport + " to KRA connector");
+ cs.putString(PREFIX + ".host", host + ":" + port + " " + hostport);
+ cs.commit(true);
+ replaceConnector();
+ return;
+ }
+ }
+ }
+
+ // connector does not exist, or existing connector is the same host/port and we are replacing it
+ cs.putString(PREFIX + ".host", info.getHost());
+ cs.putString(PREFIX + ".port", info.getPort());
+ cs.putString(PREFIX + ".enable", info.getEnable() != null ? info.getEnable() : "true");
+ cs.putString(PREFIX + ".local", info.getLocal() != null ? info.getLocal(): "false");
+ cs.putString(PREFIX + ".timeout", info.getTimeout() != null ? info.getTimeout() : "30");
+ cs.putString(PREFIX + ".uri", info.getUri() != null ? info.getUri() : "/kra/agent/kra/connector");
+ cs.putString(PREFIX + ".transportCert", info.getTransportCert());
+
+ String nickname = cs.getString("ca.subsystem.nickname", "");
+ String tokenname = cs.getString("ca.subsystem.tokenname", "");
+ if (!tokenname.equals("Internal Key Storage Token"))
+ nickname = tokenname + ":" + nickname;
+ cs.putString(PREFIX + ".nickName", nickname);
+ cs.commit(true);
+
+ replaceConnector();
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/KRAConnectorService.java b/base/server/cms/src/com/netscape/cms/servlet/admin/KRAConnectorService.java
new file mode 100644
index 000000000..53ff8e9a2
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/KRAConnectorService.java
@@ -0,0 +1,78 @@
+// --- 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 com.netscape.cms.servlet.admin;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.UriInfo;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.system.KRAConnectorInfo;
+import com.netscape.certsrv.system.KRAConnectorResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Ade Lee
+ */
+public class KRAConnectorService extends PKIService implements KRAConnectorResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ @Override
+ public void addConnector(KRAConnectorInfo info) {
+ try {
+ KRAConnectorProcessor processor = new KRAConnectorProcessor(getLocale(headers));
+ processor.addConnector(info);
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public void removeConnector(String host, String port) {
+ try {
+ KRAConnectorProcessor processor = new KRAConnectorProcessor(getLocale(headers));
+ processor.removeConnector(host, port);
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public void addConnector(MultivaluedMap<String, String> form) {
+ KRAConnectorInfo info = new KRAConnectorInfo(form);
+ addConnector(info);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/LogAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/LogAdminServlet.java
new file mode 100644
index 000000000..d66522421
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/LogAdminServlet.java
@@ -0,0 +1,2352 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.logging.ELogException;
+import com.netscape.certsrv.logging.ELogNotFound;
+import com.netscape.certsrv.logging.ELogPluginNotFound;
+import com.netscape.certsrv.logging.ILogEventListener;
+import com.netscape.certsrv.logging.ILogSubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.LogPlugin;
+
+/**
+ * A class representings an administration servlet for logging
+ * subsystem. This servlet is responsible to serve
+ * logging administrative operation such as configuration
+ * parameter updates and log retriever.
+ *
+ * @version $Revision$, $Date$
+ */
+public class LogAdminServlet extends AdminServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -99699953656847603L;
+
+ private final static String INFO = "LogAdminServlet";
+
+ private ILogSubsystem mSys = null;
+
+ private final static String SIGNED_AUDIT_LOG_TYPE = "SignedAudit";
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT =
+ "LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT_3";
+ private final static String LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE =
+ "LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE_4";
+
+ /**
+ * Constructs Log servlet.
+ */
+ public LogAdminServlet() {
+ super();
+ }
+
+ public static Hashtable<String, String> toHashtable(HttpServletRequest req) {
+ Hashtable<String, String> httpReqHash = new Hashtable<String, String>();
+ Enumeration<?> names = req.getParameterNames();
+
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+
+ httpReqHash.put(name, req.getParameter(name));
+ }
+ return httpReqHash;
+ }
+
+ /**
+ * Initializes this servlet.
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ mSys = (ILogSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_LOG);
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Serves HTTP admin request.
+ */
+ public void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"),
+ null, resp);
+ return;
+ }
+
+ super.authenticate(req);
+
+ try {
+ // perform operation based on scope
+ String scope = req.getParameter(Constants.OP_SCOPE);
+
+ if (scope != null) {
+ AUTHZ_RES_NAME = "certServer.log.configuration";
+ if (scope.equals(ScopeDef.SC_EXTENDED_PLUGIN_INFO)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ try {
+ getExtendedPluginInfo(req, resp);
+ return;
+ } catch (EBaseException e) {
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ }
+ }
+
+ if (op.equals(OpDef.OP_READ)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+
+ if (scope.equals(ScopeDef.SC_LOG_IMPLS)) {
+ getConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_LOG_RULES)) {
+ getInstConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_GENERAL)) {
+ getGeneralConfig(req, resp);
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+
+ if (scope.equals(ScopeDef.SC_LOG_IMPLS)) {
+ delLogPlugin(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_LOG_RULES)) {
+ delLogInst(req, resp, scope);
+ return;
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_ADD)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+
+ if (scope.equals(ScopeDef.SC_LOG_IMPLS)) {
+ addLogPlugin(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_LOG_RULES)) {
+ addLogInst(req, resp, scope);
+ return;
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ AUTHZ_RES_NAME = "certServer.log.configuration";
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+
+ if (scope.equals(ScopeDef.SC_LOG_RULES)) {
+ modLogInst(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_GENERAL)) {
+ setGeneralConfig(req, resp);
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_SEARCH)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_LOG_IMPLS)) {
+ listLogPlugins(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_LOG_RULES)) {
+ listLogInsts(req, resp, true);
+ return;
+ } else if (scope.equals(ScopeDef.SC_LOG_INSTANCES)) {
+ listLogInsts(req, resp, false);
+ return;
+ } else if (scope.equals(ScopeDef.SC_LOG_CONTENT)) {
+ String instName = req.getParameter(Constants.PR_LOG_INSTANCE);
+
+ if (instName.equals("System")) {
+ AUTHZ_RES_NAME = "certServer.log.content.system";
+ } else if (instName.equals("Transactions")) {
+ AUTHZ_RES_NAME = "certServer.log.content.transactions";
+ } else if (instName.equals(Constants.PR_LOG_SIGNED_AUDIT)) {
+ AUTHZ_RES_NAME = "certServer.log.content.signedAudit";
+ }
+
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+
+ ILogEventListener loginst =
+ mSys.getLogInstance(instName);
+
+ if (loginst != null) {
+ NameValuePairs nvps = loginst.retrieveLogContent(toHashtable(req));
+
+ sendResponse(SUCCESS, null, nvps, resp);
+ }
+ return;
+ } else if (scope.equals(ScopeDef.SC_LOG_ARCH)) {
+ String instName = req.getParameter(Constants.PR_LOG_INSTANCE);
+
+ if (instName.equals("System")) {
+ AUTHZ_RES_NAME = "certServer.log.content.system";
+ } else if (instName.equals("Transactions")) {
+ AUTHZ_RES_NAME = "certServer.log.content.transactions";
+ } else if (instName.equals(Constants.PR_LOG_SIGNED_AUDIT)) {
+ AUTHZ_RES_NAME = "certServer.log.content.signedAudit";
+ }
+
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ ILogEventListener loginst =
+ mSys.getLogInstance(instName);
+
+ if (loginst != null) {
+ NameValuePairs nvps = loginst.retrieveLogList(toHashtable(req));
+
+ sendResponse(SUCCESS, null, nvps, resp);
+ }
+ return;
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_TYPE", op),
+ null, resp);
+ return;
+ }
+ }
+ } catch (EBaseException e) {
+ // if it is EBaseException, we can output better
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ } catch (Exception e) {
+ System.out.println("XXX >>>" + e.toString() + "<<<");
+ e.printStackTrace();
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"),
+ null, resp);
+ }
+
+ return;
+ }
+
+ private synchronized void listLogInsts(HttpServletRequest req,
+ HttpServletResponse resp, boolean all) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = mSys.getLogInsts().keys();
+
+ for (; e.hasMoreElements();) {
+ String name = e.nextElement();
+ ILogEventListener value = ((ILogSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_LOG)).getLogInstance(name);
+
+ if (value == null)
+ continue;
+ String pName = mSys.getLogPluginName(value);
+ LogPlugin pClass = mSys.getLogPlugins().get(pName);
+ String c = pClass.getClassPath();
+
+ // not show ntEventlog here
+ if (all || (!all && !c.endsWith("NTEventLog")))
+ params.put(name, pName + ";visible");
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ /**
+ * retrieve extended plugin info such as brief description, type info
+ * from logging
+ */
+ private void getExtendedPluginInfo(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ int colon = id.indexOf(':');
+
+ String implType = id.substring(0, colon);
+ String implName = id.substring(colon + 1);
+ NameValuePairs params = getExtendedPluginInfo(getLocale(req), implType, implName);
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private NameValuePairs getExtendedPluginInfo(Locale locale, String implType, String implName) {
+ IExtendedPluginInfo ext_info = null;
+ Object impl = null;
+ LogPlugin lp = mSys.getLogPlugins().get(implName);
+
+ if (lp != null) {
+ impl = getClassByNameAsExtendedPluginInfo(lp.getClassPath());
+ }
+ if (impl != null) {
+ if (impl instanceof IExtendedPluginInfo) {
+ ext_info = (IExtendedPluginInfo) impl;
+ }
+ }
+
+ NameValuePairs nvps = null;
+
+ if (ext_info == null) {
+ nvps = new NameValuePairs();
+ } else {
+ nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale));
+ }
+
+ return nvps;
+
+ }
+
+ /**
+ * Add log plug-in
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT used when configuring signedAudit
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param scope string used to obtain the contents of the log's substore
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ @SuppressWarnings("unchecked")
+ private synchronized void addLogPlugin(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String logType = null;
+ String id = req.getParameter(Constants.RS_ID);
+
+ // if this "required" parameter is not present,
+ // always log messages to the signed audit log
+ logType = id;
+ if (logType == null) {
+ logType = SIGNED_AUDIT_LOG_TYPE;
+ }
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // is the log id unique?
+ if (mSys.getLogPlugins().containsKey(id)) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ new ELogException(CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_ILL_PLUGIN_ID", id))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ String classPath = req.getParameter(Constants.PR_LOG_CLASS);
+
+ if (classPath == null) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_NULL_CLASS"),
+ null, resp);
+ return;
+ }
+
+ IConfigStore destStore = null;
+
+ destStore = mConfig.getSubStore("log");
+ IConfigStore instancesConfig =
+ destStore.getSubStore("impl");
+
+ // Does the class exist?
+ Class<ILogEventListener> newImpl = null;
+
+ try {
+ newImpl = (Class<ILogEventListener>) Class.forName(classPath);
+ } catch (ClassNotFoundException e) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_NO_CLASS"),
+ null, resp);
+ return;
+ } catch (IllegalArgumentException e) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_NO_CLASS"),
+ null, resp);
+ return;
+ }
+
+ // is the class an ILogEventListner?
+ try {
+ if (ILogEventListener.class.isAssignableFrom(newImpl) == false) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_ILL_CLASS"),
+ null, resp);
+ return;
+ }
+ } catch (NullPointerException e) { // unlikely, only if newImpl null.
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_ILL_CLASS"),
+ null, resp);
+ return;
+ }
+
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ substore.put(Constants.PR_LOG_CLASS, classPath);
+
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ //System.out.println("SRVLT_FAIL_COMMIT");
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // add log to registry.
+ LogPlugin plugin = new LogPlugin(id, classPath);
+
+ mSys.getLogPlugins().put(id, plugin);
+
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ // } catch( EBaseException eAudit1 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ private boolean isValidID(String id) {
+ if (id == null)
+ return false;
+ for (int i = 0; i < id.length(); i++) {
+ if (!Character.isLetterOrDigit(id.charAt(i)))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Add log instance
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT used when configuring signedAudit
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param scope string used to obtain the contents of the log's substore
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void addLogInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String logType = null;
+ String id = req.getParameter(Constants.RS_ID);
+
+ // if this "required" parameter is not present,
+ // always log messages to the signed audit log
+ logType = id;
+ if (logType == null) {
+ logType = SIGNED_AUDIT_LOG_TYPE;
+ }
+
+ if (id == null) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ if (!isValidID(id)) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR, "Invalid ID '" + id + "'",
+ null, resp);
+ return;
+ }
+
+ if (mSys.getLogInsts().containsKey(id)) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_ILL_INST_ID"),
+ null, resp);
+ return;
+ }
+
+ // get required parameters
+ String implname = req.getParameter(
+ Constants.PR_LOG_IMPL_NAME);
+
+ if (implname == null) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_ADD_MISSING_PARAMS"),
+ null, resp);
+ return;
+ }
+
+ // check if implementation exists.
+ LogPlugin plugin =
+ mSys.getLogPlugins().get(
+ implname);
+
+ if (plugin == null) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(
+ ERROR,
+ new ELogPluginNotFound(CMS.getUserMessage(getLocale(req), "CMS_LOG_PLUGIN_NOT_FOUND", implname))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ Vector<String> configParams = mSys.getLogDefaultParams(implname);
+
+ IConfigStore destStore =
+ mConfig.getSubStore("log");
+ IConfigStore instancesConfig =
+ destStore.getSubStore("instance");
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+ String val = req.getParameter(kv.substring(0, index));
+
+ if (val == null) {
+ substore.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ } else {
+ substore.put(kv.substring(0, index),
+ val);
+ }
+ }
+ }
+ substore.put("pluginName", implname);
+
+ // Fix Blackflag Bug #615603: Currently, although expiring log
+ // files is no longer supported, it is still a required parameter
+ // that must be present during the creation and modification of
+ // custom log plugins.
+ substore.put("expirationTime", "0");
+
+ // Instantiate an object for this implementation
+ String className = plugin.getClassPath();
+ ILogEventListener logInst = null;
+
+ try {
+ logInst = (ILogEventListener) Class.forName(className).newInstance();
+ } catch (ClassNotFoundException e) {
+ // cleanup
+ instancesConfig.removeSubStore(id);
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ new ELogException(CMS.getUserMessage(getLocale(req), "CMS_LOG_LOAD_CLASS_FAIL", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (InstantiationException e) {
+ instancesConfig.removeSubStore(id);
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ new ELogException(CMS.getUserMessage(getLocale(req), "CMS_LOG_LOAD_CLASS_FAIL", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (IllegalAccessException e) {
+ instancesConfig.removeSubStore(id);
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ new ELogException(CMS.getUserMessage(getLocale(req), "CMS_LOG_LOAD_CLASS_FAIL", className))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ // initialize the log
+ try {
+ logInst.init(mSys, substore);
+ } catch (EBaseException e) {
+ // don't commit in this case and cleanup the new substore.
+ instancesConfig.removeSubStore(id);
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ } catch (Throwable e) {
+ instancesConfig.removeSubStore(id);
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR, e.toString(), null, resp);
+ return;
+ }
+
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // clean up.
+ instancesConfig.removeSubStore(id);
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // inited and commited ok. now add log instance to list.
+ mSys.getLogInsts().put(id, logInst);
+
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_LOG_IMPL_NAME, implname);
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ // } catch( EBaseException eAudit1 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ private synchronized void listLogPlugins(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = mSys.getLogPlugins().keys();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+ LogPlugin value = mSys.getLogPlugins().get(name);
+ // get Description
+ String c = value.getClassPath();
+ String desc = "unknown";
+
+ try {
+ ILogEventListener lp = (ILogEventListener)
+ Class.forName(c).newInstance();
+
+ desc = lp.getDescription();
+ } catch (Exception exp) {
+ sendResponse(ERROR, exp.toString(), null,
+ resp);
+ return;
+ }
+ params.put(name, value.getClassPath() + "," + desc);
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ public String getLogPluginName(ILogEventListener log) {
+ IConfigStore cs = log.getConfigStore();
+
+ try {
+ return cs.getString("pluginName", "");
+ } catch (EBaseException e) {
+ return "";
+ }
+ }
+
+ /**
+ * Delete log instance
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT used when configuring signedAudit
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param scope string used to obtain the contents of the log's substore
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void delLogInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String logType = null;
+ NameValuePairs params = new NameValuePairs();
+ String id = req.getParameter(Constants.RS_ID);
+
+ // if this "required" parameter is not present,
+ // always log messages to the signed audit log
+ logType = id;
+ if (logType == null) {
+ logType = SIGNED_AUDIT_LOG_TYPE;
+ }
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // Does the log instance exist?
+ if (mSys.getLogInsts().containsKey(id) == false) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ new ELogNotFound(CMS.getUserMessage(getLocale(req), "CMS_LOG_INSTANCE_NOT_FOUND", id))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ // only remove from memory
+ // cannot shutdown because we don't keep track of whether it's
+ // being used.
+ mSys.getLogInsts().remove(id);
+
+ // remove the configuration.
+ IConfigStore destStore =
+ mConfig.getSubStore("log");
+ IConfigStore instancesConfig =
+ destStore.getSubStore("instance");
+
+ instancesConfig.removeSubStore(id);
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ //System.out.println("SRVLT_FAIL_COMMIT");
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ // } catch( EBaseException eAudit1 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * Delete log plug-in
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT used when configuring signedAudit
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param scope string used to obtain the contents of the log's substore
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void delLogPlugin(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String logType = null;
+ NameValuePairs params = new NameValuePairs();
+ String id = req.getParameter(Constants.RS_ID);
+
+ // if this "required" parameter is not present,
+ // always log messages to the signed audit log
+ logType = id;
+ if (logType == null) {
+ logType = SIGNED_AUDIT_LOG_TYPE;
+ }
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ if (mSys.getLogPlugins().containsKey(id) == false) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ new ELogPluginNotFound(CMS.getUserMessage(getLocale(req), "CMS_LOG_PLUGIN_NOT_FOUND", id))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ // first check if any instances from this log
+ // DON'T remove log if any instance
+ for (Enumeration<String> e = mSys.getLogInsts().keys(); e.hasMoreElements();) {
+ String name = e.nextElement();
+ ILogEventListener log = mSys.getLogInstance(name);
+
+ if (getLogPluginName(log) == id) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_IN_USE"),
+ null, resp);
+ return;
+ }
+ }
+
+ // then delete this log
+ mSys.getLogPlugins().remove(id);
+
+ IConfigStore destStore =
+ mConfig.getSubStore("log");
+ IConfigStore instancesConfig =
+ destStore.getSubStore("impl");
+
+ instancesConfig.removeSubStore(id);
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ // } catch( EBaseException eAudit1 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * Modify log instance
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT used when configuring signedAudit
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE used when log file name (including any path changes) for
+ * any of audit, system, transaction, or other customized log file change is attempted (authorization should not
+ * allow, but make sure it's written after the attempt)
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE used when log expiration time change is attempted
+ * (authorization should not allow, but make sure it's written after the attempt)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param scope string used to obtain the contents of the log's substore
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void modLogInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String logType = null;
+ String origLogPath = req.getParameter(Constants.PR_LOG_FILENAME);
+ String newLogPath = origLogPath;
+ String origExpirationTime = req.getParameter(
+ Constants.PR_LOG_EXPIRED_TIME);
+ String newExpirationTime = origExpirationTime;
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = req.getParameter(Constants.RS_ID);
+
+ // if this "required" parameter is not present,
+ // always log messages to the signed audit log
+ logType = id;
+ if (logType == null) {
+ logType = SIGNED_AUDIT_LOG_TYPE;
+ }
+
+ if (origLogPath != null) {
+ origLogPath = origLogPath.trim();
+ newLogPath = newLogPath.trim();
+ } else {
+ origLogPath = "";
+ newLogPath = "";
+ }
+
+ if (origExpirationTime != null) {
+ origExpirationTime = origExpirationTime.trim();
+ newExpirationTime = newExpirationTime.trim();
+ } else {
+ origExpirationTime = "";
+ newExpirationTime = "";
+ }
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // Does the manager instance exist?
+ if (!mSys.getLogInsts().containsKey(id)) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_ILL_INST_ID"),
+ null, resp);
+ return;
+ }
+
+ // get new implementation (same or different.)
+ String implname = req.getParameter(Constants.PR_LOG_IMPL_NAME);
+
+ if (implname == null) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_ADD_MISSING_PARAMS"),
+
+ null, resp);
+ return;
+ }
+ // get plugin for implementation
+ LogPlugin plugin =
+ mSys.getLogPlugins().get(implname);
+
+ if (plugin == null) {
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(
+ ERROR,
+ new ELogPluginNotFound(CMS.getUserMessage(getLocale(req), "CMS_LOG_PLUGIN_NOT_FOUND", implname))
+ .toString(), null, resp);
+ return;
+ }
+
+ // save old instance substore params in case new one fails.
+
+ ILogEventListener oldinst =
+ mSys.getLogInstance(id);
+ Vector<String> oldConfigParms = oldinst.getInstanceParams();
+ NameValuePairs saveParams = new NameValuePairs();
+
+ // implName is always required so always include it it.
+ saveParams.put("pluginName", implname);
+ if (oldConfigParms != null) {
+ for (int i = 0; i < oldConfigParms.size(); i++) {
+ String kv = oldConfigParms.elementAt(i);
+ int index = kv.indexOf('=');
+
+ saveParams.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ }
+ }
+
+ // on to the new instance.
+
+ // remove old substore.
+
+ IConfigStore destStore =
+ mConfig.getSubStore("log");
+ IConfigStore instancesConfig =
+ destStore.getSubStore("instance");
+
+ // create new substore.
+
+ Vector<String> configParams = mSys.getLogInstanceParams(id);
+
+ //instancesConfig.removeSubStore(id);
+
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ substore.put("pluginName", implname);
+
+ // Fix Blackflag Bug #615603: Currently, although expiring log
+ // files is no longer supported, it is still a required parameter
+ // that must be present during the creation and modification of
+ // custom log plugins.
+ substore.put("expirationTime", "0");
+
+ // IMPORTANT: save a copy of the original log file path
+ origLogPath = substore.getString(Constants.PR_LOG_FILENAME);
+ newLogPath = origLogPath;
+
+ if (origLogPath != null) {
+ origLogPath = origLogPath.trim();
+ newLogPath = newLogPath.trim();
+ } else {
+ origLogPath = "";
+ newLogPath = "";
+ }
+
+ // IMPORTANT: save a copy of the original log expiration time
+ origExpirationTime = substore.getString(
+ Constants.PR_LOG_EXPIRED_TIME);
+ newExpirationTime = origExpirationTime;
+
+ if (origExpirationTime != null) {
+ origExpirationTime = origExpirationTime.trim();
+ newExpirationTime = newExpirationTime.trim();
+ } else {
+ origExpirationTime = "";
+ newExpirationTime = "";
+ }
+
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ AUTHZ_RES_NAME =
+ "certServer.log.configuration";
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+ String key = kv.substring(0, index);
+ String val = req.getParameter(key);
+
+ if (key.equals("level")) {
+ if (val.equals(ILogger.LL_DEBUG_STRING))
+ val = "0";
+ else if (val.equals(ILogger.LL_INFO_STRING))
+ val = "1";
+ else if (val.equals(ILogger.LL_WARN_STRING))
+ val = "2";
+ else if (val.equals(ILogger.LL_FAILURE_STRING))
+ val = "3";
+ else if (val.equals(ILogger.LL_MISCONF_STRING))
+ val = "4";
+ else if (val.equals(ILogger.LL_CATASTRPHE_STRING))
+ val = "5";
+ else if (val.equals(ILogger.LL_SECURITY_STRING))
+ val = "6";
+
+ }
+
+ if (key.equals("rolloverInterval")) {
+ if (val.equals("Hourly"))
+ val = Integer.toString(60 * 60);
+ else if (val.equals("Daily"))
+ val = Integer.toString(60 * 60 * 24);
+ else if (val.equals("Weekly"))
+ val = Integer.toString(60 * 60 * 24 * 7);
+ else if (val.equals("Monthly"))
+ val = Integer.toString(60 * 60 * 24 * 30);
+ else if (val.equals("Yearly"))
+ val = Integer.toString(60 * 60 * 24 * 365);
+ }
+
+ if (val != null) {
+ if (key.equals("fileName")) {
+ String origVal = substore.getString(key);
+
+ val = val.trim();
+ newLogPath = val;
+ if (!val.equals(origVal.trim())) {
+ AUTHZ_RES_NAME =
+ "certServer.log.configuration.fileName";
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ // store a message in the signed audit log
+ // file (regardless of logType)
+ if (!(newLogPath.equals(origLogPath))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ logType,
+ newLogPath);
+
+ audit(auditMessage);
+ }
+
+ // store a message in the signed audit log
+ // file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ }
+ }
+ /*
+ if (key.equals("expirationTime")) {
+ String origVal = substore.getString(key);
+
+ val = val.trim();
+ newExpirationTime = val;
+ if (!val.equals(origVal.trim())) {
+ if (id.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ AUTHZ_RES_NAME =
+ "certServer.log.configuration.signedAudit.expirationTime";
+ }
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ // store a message in the signed audit log
+ // file (regardless of logType)
+ if (!(newExpirationTime.equals(origExpirationTime))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ logType,
+ newExpirationTime);
+
+ audit(auditMessage);
+ }
+
+ // store a message in the signed audit log
+ // file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ }
+ }
+ */
+ substore.put(key, val);
+ }
+ }
+ }
+
+ // Instantiate an object for new implementation
+
+ String className = plugin.getClassPath();
+ @SuppressWarnings("unused")
+ ILogEventListener newMgrInst = null;
+
+ try {
+ newMgrInst = (ILogEventListener)
+ Class.forName(className).newInstance();
+ } catch (ClassNotFoundException e) {
+ // check to see if the log file path parameter was changed
+ newLogPath = auditCheckLogPath(req);
+
+ // check to see if the log expiration time parameter was changed
+ // newExpirationTime = auditCheckLogExpirationTime(req);
+
+ // cleanup
+ restore(instancesConfig, id, saveParams);
+
+ // store a message in the signed audit log file
+ // (regardless of logType)
+ if (!(newLogPath.equals(origLogPath))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ logType,
+ newLogPath);
+
+ audit(auditMessage);
+ }
+
+ // store a message in the signed audit log file
+ // (regardless of logType)
+ /*
+ if (!(newExpirationTime.equals(origExpirationTime))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ logType,
+ newExpirationTime);
+
+ audit(auditMessage);
+ }*/
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ new ELogException(CMS.getUserMessage(getLocale(req), "CMS_LOG_LOAD_CLASS_FAIL", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (InstantiationException e) {
+ // check to see if the log file path parameter was changed
+ newLogPath = auditCheckLogPath(req);
+
+ // check to see if the log expiration time parameter was changed
+ //newExpirationTime = auditCheckLogExpirationTime(req);
+
+ restore(instancesConfig, id, saveParams);
+
+ // store a message in the signed audit log file
+ // (regardless of logType)
+ if (!(newLogPath.equals(origLogPath))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ logType,
+ newLogPath);
+
+ audit(auditMessage);
+ }
+
+ // store a message in the signed audit log file
+ // (regardless of logType)
+ /*if (!(newExpirationTime.equals(origExpirationTime))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ logType,
+ newExpirationTime);
+
+ audit(auditMessage);
+ }*/
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ new ELogException(CMS.getUserMessage(getLocale(req), "CMS_LOG_LOAD_CLASS_FAIL", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (IllegalAccessException e) {
+ // check to see if the log file path parameter was changed
+ newLogPath = auditCheckLogPath(req);
+
+ // check to see if the log expiration time parameter was changed
+ //newExpirationTime = auditCheckLogExpirationTime(req);
+
+ restore(instancesConfig, id, saveParams);
+
+ // store a message in the signed audit log file
+ // (regardless of logType)
+ if (!(newLogPath.equals(origLogPath))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ logType,
+ newLogPath);
+
+ audit(auditMessage);
+ }
+
+ // store a message in the signed audit log file
+ // (regardless of logType)
+ /* if (!(newExpirationTime.equals(origExpirationTime))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ logType,
+ newExpirationTime);
+
+ audit(auditMessage);
+ } */
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ new ELogException(CMS.getUserMessage(getLocale(req), "CMS_LOG_LOAD_CLASS_FAIL", className))
+ .toString(),
+ null, resp);
+ return;
+ }
+ // initialize the log
+
+ // initialized ok. commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // check to see if the log file path parameter was changed
+ newLogPath = auditCheckLogPath(req);
+
+ // check to see if the log expiration time parameter was changed
+ // newExpirationTime = auditCheckLogExpirationTime(req);
+
+ // clean up.
+ restore(instancesConfig, id, saveParams);
+ //System.out.println("SRVLT_FAIL_COMMIT");
+
+ // store a message in the signed audit log file
+ // (regardless of logType)
+ if (!(newLogPath.equals(origLogPath))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ logType,
+ newLogPath);
+
+ audit(auditMessage);
+ }
+
+ // store a message in the signed audit log file
+ // (regardless of logType)
+ /* if (!(newExpirationTime.equals(origExpirationTime))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ logType,
+ newExpirationTime);
+
+ audit(auditMessage);
+ }*/
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // commited ok. replace instance.
+
+ // REMOVED - we didn't do anything to shut off the old instance
+ // so, it will still be running at this point. You'd have two
+ // log isntances writing to the same file - this would be a big PROBLEM!!!
+
+ //mSys.getLogInsts().put(id, newMgrInst);
+
+ NameValuePairs params = new NameValuePairs();
+
+ // check to see if the log file path parameter was changed
+ newLogPath = auditCheckLogPath(req);
+
+ // check to see if the log expiration time parameter was changed
+ //newExpirationTime = auditCheckLogExpirationTime(req);
+
+ // store a message in the signed audit log file
+ // (regardless of logType)
+ if (!(newLogPath.equals(origLogPath))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ logType,
+ newLogPath);
+
+ audit(auditMessage);
+ }
+
+ // store a message in the signed audit log file
+ // (regardless of logType)
+ /*if (!(newExpirationTime.equals(origExpirationTime))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ logType,
+ newExpirationTime);
+
+ audit(auditMessage);
+ }*/
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ sendResponse(RESTART, null, params, resp);
+ return;
+ } catch (EBaseException eAudit1) {
+ // check to see if the log file path parameter was changed
+ newLogPath = auditCheckLogPath(req);
+
+ // check to see if the log expiration time parameter was changed
+ // newExpirationTime = auditCheckLogExpirationTime(req);
+
+ // store a message in the signed audit log file
+ // (regardless of logType)
+ if (!(newLogPath.equals(origLogPath))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ logType,
+ newLogPath);
+
+ audit(auditMessage);
+ }
+
+ // store a message in the signed audit log file
+ // (regardless of logType)
+ /* if (!(newExpirationTime.equals(origExpirationTime))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ logType,
+ newExpirationTime);
+
+ audit(auditMessage);
+ } */
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // check to see if the log file path parameter was changed
+ newLogPath = auditCheckLogPath(req);
+
+ // check to see if the log expiration time parameter was changed
+ // newExpirationTime = auditCheckLogExpirationTime(req);
+
+ // store a message in the signed audit log file
+ // (regardless of logType)
+ if (!(newLogPath.equals(origLogPath))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ logType,
+ newLogPath);
+
+ audit(auditMessage);
+ }
+
+ // store a message in the signed audit log file
+ // (regardless of logType)
+ /*if (!(newExpirationTime.equals(origExpirationTime))) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ logType,
+ newExpirationTime);
+
+ audit(auditMessage);
+ }*/
+
+ // store a message in the signed audit log file
+ if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ }
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // check to see if the log file path parameter was changed
+ // newLogPath = auditCheckLogPath( req );
+ //
+ // // check to see if the log expiration time parameter was changed
+ // newExpirationTime = auditCheckLogExpirationTime( req );
+ //
+ // // store a message in the signed audit log file
+ // // (regardless of logType)
+ // if( !( newLogPath.equals( origLogPath ) ) ) {
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // logType,
+ // newLogPath );
+ //
+ // audit( auditMessage );
+ // }
+ //
+ // // store a message in the signed audit log file
+ // // (regardless of logType)
+ // if( !( newExpirationTime.equals( origExpirationTime ) ) ) {
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // logType,
+ // newExpirationTime );
+ //
+ // audit( auditMessage );
+ // }
+ //
+ // // store a message in the signed audit log file
+ // if( logType.equals( SIGNED_AUDIT_LOG_TYPE ) ) {
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ // }
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * used for getting the required configuration parameters (with
+ * possible default values) for a particular plugin
+ * implementation name specified in the RS_ID. Actually, there is
+ * no logic in here to set any default value here...there's no
+ * default value for any parameter in this log subsystem
+ * at this point. Later, if we do have one (or some), it can be
+ * added. The interface remains the same.
+ */
+ private synchronized void getConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+
+ String implname = req.getParameter(Constants.RS_ID);
+
+ if (implname == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ Vector<String> configParams = mSys.getLogDefaultParams(implname);
+ NameValuePairs params = new NameValuePairs();
+
+ // implName is always required so always send it.
+ params.put(Constants.PR_LOG_IMPL_NAME, "");
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+
+ if (index == -1) {
+ params.put(kv, "");
+ } else {
+ params.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ }
+ }
+ }
+ sendResponse(0, null, params, resp);
+ return;
+ }
+
+ private synchronized void getInstConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // does log instance exist?
+ if (mSys.getLogInsts().containsKey(id) == false) {
+ sendResponse(ERROR,
+ new ELogNotFound(CMS.getUserMessage(getLocale(req), "CMS_LOG_INSTANCE_NOT_FOUND", id)).toString(),
+ null, resp);
+ return;
+ }
+
+ ILogEventListener logInst = mSys.getLogInstance(id);
+ Vector<String> configParams = logInst.getInstanceParams();
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_LOG_IMPL_NAME,
+ getLogPluginName(logInst));
+ // implName is always required so always send it.
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+
+ params.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ }
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ // convenience routine.
+ private static void restore(IConfigStore store,
+ String id, NameValuePairs saveParams) {
+ store.removeSubStore(id);
+ IConfigStore rstore = store.makeSubStore(id);
+
+ for (String key : saveParams.keySet()) {
+ String value = saveParams.get(key);
+
+ if (value != null)
+ rstore.put(key, value);
+ }
+ }
+
+ /**
+ * Signed Audit Check Log Path
+ *
+ * This method is called to extract the log file path.
+ * <P>
+ *
+ * @param req http servlet request
+ * @return a string containing the log file path
+ */
+ private String auditCheckLogPath(HttpServletRequest req) {
+ // check to see if the log file path parameter was changed
+ String logPath = req.getParameter(Constants.PR_LOG_FILENAME);
+
+ if (logPath == null) {
+ logPath = "";
+ }
+
+ logPath = logPath.trim();
+
+ return logPath;
+ }
+
+ private void getGeneralConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ String value = "false";
+
+ value = mConfig.getString(Constants.PR_DEBUG_LOG_ENABLE, "false");
+ params.put(Constants.PR_DEBUG_LOG_ENABLE, value);
+
+ value = mConfig.getString(Constants.PR_DEBUG_LOG_LEVEL, "0");
+ params.put(Constants.PR_DEBUG_LOG_LEVEL, value);
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void setGeneralConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ Enumeration<String> enum1 = req.getParameterNames();
+ boolean restart = false;
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.PR_DEBUG_LOG_ENABLE)) {
+ if (value.equals("true") || value.equals("false")) {
+ mConfig.putString(Constants.PR_DEBUG_LOG_ENABLE, value);
+ } else {
+ CMS.debug("setGeneralConfig: Invalid value for " + Constants.PR_DEBUG_LOG_ENABLE + ": " + value);
+ throw new EBaseException("Invalid value for " + Constants.PR_DEBUG_LOG_ENABLE);
+ }
+ } else if (key.equals(Constants.PR_DEBUG_LOG_LEVEL)) {
+ try {
+ Integer.parseInt(value); // check for errors
+ mConfig.putString(Constants.PR_DEBUG_LOG_LEVEL, value);
+ } catch (NumberFormatException e) {
+ CMS.debug("setGeneralConfig: Invalid value for " + Constants.PR_DEBUG_LOG_LEVEL + ": " + value);
+ throw new EBaseException("Invalid value for " + Constants.PR_DEBUG_LOG_LEVEL);
+ }
+ }
+ }
+
+ mConfig.commit(true);
+
+ if (restart)
+ sendResponse(RESTART, null, null, resp);
+ else
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/OCSPAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/OCSPAdminServlet.java
new file mode 100644
index 000000000..a7ff92274
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/OCSPAdminServlet.java
@@ -0,0 +1,541 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ocsp.IOCSPAuthority;
+import com.netscape.certsrv.ocsp.IOCSPStore;
+
+/**
+ * A class representings an administration servlet for Certificate
+ * Authority. This servlet is responsible to serve OCSP
+ * administrative operations such as configuration parameter
+ * updates.
+ *
+ * @version $Revision$, $Date$
+ */
+public class OCSPAdminServlet extends AdminServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3349635369730415767L;
+
+ protected static final String PROP_ENABLED = "enabled";
+
+ private final static String INFO = "OCSPAdminServlet";
+
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE =
+ "LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE_3";
+
+ private IOCSPAuthority mOCSP = null;
+
+ public OCSPAdminServlet() {
+ super();
+ }
+
+ /**
+ * Initializes this servlet.
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ mOCSP = (IOCSPAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_OCSP);
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Serves HTTP request. Each request is authenticated to
+ * the authenticate manager.
+ */
+ public void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+
+ //get all operational flags
+ String op = req.getParameter(Constants.OP_TYPE);
+ String scope = req.getParameter(Constants.OP_SCOPE);
+
+ //check operational flags
+ if ((op == null) || (scope == null)) {
+ sendResponse(1, "Invalid Protocol", null, resp);
+ return;
+ }
+
+ super.authenticate(req);
+
+ try {
+ AUTHZ_RES_NAME = "certServer.ocsp.configuration";
+ if (scope.equals(ScopeDef.SC_EXTENDED_PLUGIN_INFO)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ try {
+ getExtendedPluginInfo(req, resp);
+ return;
+ } catch (EBaseException e) {
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ }
+ }
+
+ if (scope.equals(ScopeDef.SC_OCSPSTORE_DEFAULT)) {
+ if (op.equals(OpDef.OP_MODIFY)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ setDefaultStore(req, resp);
+ return;
+ }
+ }
+
+ if (op.equals(OpDef.OP_READ)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_GENERAL)) {
+ getGeneralConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_OCSPSTORES_RULES)) {
+ getOCSPStoresConfig(req, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_GENERAL)) {
+ setGeneralConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_OCSPSTORES_RULES)) {
+ setOCSPStoresConfig(req, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_SEARCH)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_OCSPSTORES_RULES)) {
+ listOCSPStoresConfig(req, resp);
+ return;
+ }
+ }
+ } catch (Exception e) {
+ sendResponse(1, e.toString(), null, resp);
+ return;
+ }
+ }
+
+ /**
+ * retrieve extended plugin info such as brief description,
+ * type info from CRL extensions
+ */
+ private void getExtendedPluginInfo(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String id = req.getParameter(Constants.RS_ID);
+ int colon = id.indexOf(':');
+
+ String implType = id.substring(0, colon);
+ String implName = id.substring(colon + 1);
+
+ NameValuePairs params =
+ getExtendedPluginInfo(getLocale(req), implType, implName);
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private NameValuePairs getExtendedPluginInfo(Locale locale, String implType, String implName) {
+ IExtendedPluginInfo ext_info = null;
+ Object impl = null;
+
+ impl = getClassByNameAsExtendedPluginInfo(implName);
+ if (impl != null) {
+ if (impl instanceof IExtendedPluginInfo) {
+ ext_info = (IExtendedPluginInfo) impl;
+ }
+ }
+
+ NameValuePairs nvps = null;
+
+ if (ext_info == null) {
+ nvps = new NameValuePairs();
+ } else {
+ nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale));
+ }
+
+ return nvps;
+
+ }
+
+ /**
+ * Set default OCSP store
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE used when configuring OCSP profile (everything under
+ * Online Certificate Status Manager)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private void setDefaultStore(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = req.getParameter(Constants.RS_ID);
+
+ mOCSP.getConfigStore().putString(IOCSPAuthority.PROP_DEF_STORE_ID,
+ id);
+ commit(true);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, null, resp);
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ private void getOCSPStoresConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ IOCSPStore store = mOCSP.getOCSPStore(id);
+ NameValuePairs params = store.getConfigParameters();
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * Set OCSP store configuration
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE used when configuring OCSP profile (everything under
+ * Online Certificate Status Manager)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private void setOCSPStoresConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ NameValuePairs params = new NameValuePairs();
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ IOCSPStore store = mOCSP.getOCSPStore(id);
+
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_CRLEXT_IMPL_NAME))
+ continue;
+ if (name.equals("RULENAME"))
+ continue;
+ String value = req.getParameter(name);
+
+ params.put(name, value);
+ }
+ store.setConfigParameters(params);
+ commit(true);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, null, resp);
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ private void listOCSPStoresConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ IConfigStore config = mOCSP.getConfigStore();
+ String defStore = config.getString(IOCSPAuthority.PROP_DEF_STORE_ID);
+ IConfigStore SubStore = config.getSubStore(IOCSPAuthority.PROP_STORE);
+ Enumeration<String> enumStores = SubStore.getSubStoreNames();
+
+ while (enumStores.hasMoreElements()) {
+ String storeName = enumStores.nextElement();
+ boolean storeEnabled = false;
+
+ if (storeName.equals(defStore)) {
+ storeEnabled = true;
+ }
+ params.put(storeName, storeName + ";visible;" + ((storeEnabled) ? "enabled" : "disabled"));
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void getGeneralConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+
+ getSigningAlgConfig(params);
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void getSigningAlgConfig(NameValuePairs params) {
+ params.put(Constants.PR_DEFAULT_ALGORITHM,
+ mOCSP.getDefaultAlgorithm());
+ String[] algorithms = mOCSP.getOCSPSigningAlgorithms();
+ StringBuffer algorStr = new StringBuffer();
+
+ for (int i = 0; i < algorithms.length; i++) {
+ if (i == 0)
+ algorStr.append(algorithms[i]);
+ else
+ algorStr.append(":");
+ algorStr.append(algorithms[i]);
+ }
+ params.put(Constants.PR_ALL_ALGORITHMS, algorStr.toString());
+ }
+
+ /**
+ * Set general OCSP configuration
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE used when configuring OCSP profile (everything under
+ * Online Certificate Status Manager)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private void setGeneralConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ Enumeration<String> enum1 = req.getParameterNames();
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+ String value = req.getParameter(key);
+
+ if (key.equals(Constants.PR_DEFAULT_ALGORITHM)) {
+ mOCSP.setDefaultAlgorithm(value);
+ }
+ }
+
+ commit(true);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, null, resp);
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/PolicyAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/PolicyAdminServlet.java
new file mode 100644
index 000000000..bfc1e6f4a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/PolicyAdminServlet.java
@@ -0,0 +1,1257 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.policy.IPolicyRule;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+
+/**
+ * This class is an administration servlet for policy management.
+ *
+ * Each service (CA, KRA, RA) should be responsible
+ * for registering an instance of this with the remote
+ * administration subsystem.
+ *
+ * @deprecated
+ * @version $Revision$, $Date$
+ */
+public class PolicyAdminServlet extends AdminServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8850646362111106656L;
+
+ public final static String PROP_AUTHORITY = "authority";
+
+ private final static String INFO = "PolicyAdminServlet";
+ private final static String PW_PASSWORD_CACHE_ADD =
+ "PASSWORD_CACHE_ADD";
+
+ public final static String PROP_PREDICATE = "predicate";
+ private IPolicyProcessor mProcessor = null;
+ private IAuthority mAuthority = null;
+
+ // These will be moved to PolicyResources
+ public static String INVALID_POLICY_SCOPE = "Invalid policy administration scope";
+ public static String INVALID_POLICY_IMPL_OP = "Invalid operation for policy implementation management";
+ public static String NYI = "Not Yet Implemented";
+ public static String INVALID_POLICY_IMPL_CONFIG = "Invalid policy implementation configuration";
+ public static String INVALID_POLICY_INSTANCE_CONFIG = "Invalid policy instance configuration";
+ public static String MISSING_POLICY_IMPL_ID = "Missing policy impl id in request";
+ public static String MISSING_POLICY_IMPL_CLASS = "Missing policy impl class in request";
+ public static String INVALID_POLICY_IMPL_ID = "Invalid policy impl id in request";
+ public static String MISSING_POLICY_INST_ID = "Missing policy impl id in request";
+ public static String INVALID_POLICY_INST_ID = "Invalid policy impl id in request";
+ public static String COMMA = ",";
+ public static String MISSING_POLICY_ORDERING = "Missing policy ordering";
+
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY =
+ "LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY_3";
+
+ /**
+ * Constructs administration servlet.
+ */
+ public PolicyAdminServlet() {
+ super();
+ }
+
+ /**
+ * Initializes this servlet.
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ String authority = config.getInitParameter(PROP_AUTHORITY);
+ String policyStatus = null;
+
+ CMS.debug("PolicyAdminServlet: In Policy Admin Servlet init!");
+
+ // CMS 6.1 began utilizing the "Certificate Profiles" framework
+ // instead of the legacy "Certificate Policies" framework.
+ //
+ // Beginning with CS 8.1, to meet the Common Criteria evaluation
+ // performed on this version of the product, it was determined
+ // that this legacy "Certificate Policies" framework would be
+ // deprecated and disabled by default (see Bugzilla Bug #472597).
+ //
+ // NOTE: The "Certificate Policies" framework ONLY applied to
+ // to CA, KRA, and legacy RA (pre-CMS 7.0) subsystems.
+ //
+ // Further, the "PolicyAdminServlet.java" servlet is ONLY used
+ // by the CA Console for the following:
+ //
+ // SERVLET-NAME URL-PATTERN
+ // ====================================================
+ // capolicy ca/capolicy
+ //
+ // Finally, the "PolicyAdminServlet.java" servlet is ONLY used
+ // by the KRA Console for the following:
+ //
+ // SERVLET-NAME URL-PATTERN
+ // ====================================================
+ // krapolicy kra/krapolicy
+ //
+ if (authority != null)
+ mAuthority = (IAuthority) CMS.getSubsystem(authority);
+ if (mAuthority != null)
+ if (mAuthority instanceof ICertificateAuthority) {
+ mProcessor = ((ICertificateAuthority) mAuthority).getPolicyProcessor();
+ try {
+ policyStatus = ICertificateAuthority.ID
+ + "." + "Policy"
+ + "." + IPolicyProcessor.PROP_ENABLE;
+ if (mConfig.getBoolean(policyStatus, true) == true) {
+ // NOTE: If "ca.Policy.enable=<boolean>" is missing,
+ // then the referenced instance existed prior
+ // to this name=value pair existing in its
+ // 'CS.cfg' file, and thus we err on the
+ // side that the user may still need to
+ // use the policy framework.
+ CMS.debug("PolicyAdminServlet::init "
+ + "Certificate Policy Framework (deprecated) "
+ + "is ENABLED");
+ } else {
+ // CS 8.1 Default: ca.Policy.enable=false
+ CMS.debug("PolicyAdminServlet::init "
+ + "Certificate Policy Framework (deprecated) "
+ + "is DISABLED");
+ return;
+ }
+ } catch (EBaseException e) {
+ throw new ServletException(authority
+ + " does not have a "
+ + "master policy switch called '"
+ + policyStatus + "'");
+ }
+ } else if (mAuthority instanceof IRegistrationAuthority) {
+ // this refers to the legacy RA (pre-CMS 7.0)
+ mProcessor = ((IRegistrationAuthority) mAuthority).getPolicyProcessor();
+ } else if (mAuthority instanceof IKeyRecoveryAuthority) {
+ mProcessor = ((IKeyRecoveryAuthority) mAuthority).getPolicyProcessor();
+ try {
+ policyStatus = IKeyRecoveryAuthority.ID
+ + "." + "Policy"
+ + "." + IPolicyProcessor.PROP_ENABLE;
+ if (mConfig.getBoolean(policyStatus, true) == true) {
+ // NOTE: If "kra.Policy.enable=<boolean>" is missing,
+ // then the referenced instance existed prior
+ // to this name=value pair existing in its
+ // 'CS.cfg' file, and thus we err on the
+ // side that the user may still need to
+ // use the policy framework.
+ CMS.debug("PolicyAdminServlet::init "
+ + "Certificate Policy Framework (deprecated) "
+ + "is ENABLED");
+ } else {
+ // CS 8.1 Default: kra.Policy.enable=false
+ CMS.debug("PolicyAdminServlet::init "
+ + "Certificate Policy Framework (deprecated) "
+ + "is DISABLED");
+ return;
+ }
+ } catch (EBaseException e) {
+ throw new ServletException(authority
+ + " does not have a "
+ + "master policy switch called '"
+ + policyStatus + "'");
+ }
+ } else
+ throw new ServletException(authority + " does not have policy processor!");
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * retrieve extended plugin info such as brief description, type info
+ * from policy, authentication,
+ * need to add: listener, mapper and publishing plugins
+ */
+ private void getExtendedPluginInfo(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ if (!readAuthorize(req, resp))
+ return;
+ String id = req.getParameter(Constants.RS_ID);
+ NameValuePairs params = null;
+
+ int colon = id.indexOf(':');
+
+ String implType = id.substring(0, colon);
+ String implName1 = id.substring(colon + 1);
+ String implName = implName1;
+ String instName = null;
+
+ colon = implName1.indexOf(':');
+ if (colon > -1) {
+ implName = implName1.substring(0, colon);
+ instName = implName1.substring(colon + 1);
+ params = getExtendedPluginInfo(getLocale(req), implType, implName, instName);
+ } else {
+ params = getExtendedPluginInfo(getLocale(req), implType, implName);
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private NameValuePairs getExtendedPluginInfo(Locale locale, String implType, String implName) {
+ IExtendedPluginInfo ext_info = null;
+ Object impl = null;
+ IPolicyRule policy = mProcessor.getPolicyImpl(implName);
+
+ impl = policy;
+
+ if (impl != null) {
+ if (impl instanceof IExtendedPluginInfo) {
+ ext_info = (IExtendedPluginInfo) impl;
+ }
+ }
+
+ NameValuePairs nvps = null;
+
+ if (ext_info == null) {
+ nvps = new NameValuePairs();
+ } else {
+ nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale));
+ }
+
+ return nvps;
+ }
+
+ public NameValuePairs getExtendedPluginInfo(Locale locale, String pluginType,
+ String implName,
+ String instName) {
+ IExtendedPluginInfo ext_info = null;
+
+ Object impl = null;
+
+ IPolicyRule policy = mProcessor.getPolicyInstance(instName);
+
+ impl = policy;
+ if (impl == null) {
+ impl = mProcessor.getPolicyImpl(implName);
+ }
+ if (impl != null) {
+ if (impl instanceof IExtendedPluginInfo) {
+ ext_info = (IExtendedPluginInfo) impl;
+ }
+ }
+
+ NameValuePairs nvps = null;
+
+ if (ext_info == null) {
+ nvps = new NameValuePairs();
+ } else {
+ nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale));
+
+ }
+
+ if (nvps != null) {
+ addDefaultParams(impl, nvps);
+ }
+
+ return nvps;
+ }
+
+ private void addDefaultParams(Object ext_info, NameValuePairs nvps) {
+
+ /* make sure policy rules have 'enable' and 'predicate' */
+
+ if (ext_info instanceof IPolicyRule) {
+ if (nvps.get(IPolicyRule.PROP_ENABLE) == null) {
+ nvps.put(IPolicyRule.PROP_ENABLE, "boolean;Enable this policy rule");
+ }
+ if (nvps.get(PROP_PREDICATE) == null) {
+ nvps.put(PROP_PREDICATE, "string;Rules describing when this policy should run.");
+ }
+ }
+ }
+
+ /**
+ * Serves HTTP admin request.
+ */
+ public void service(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+
+ super.authenticate(req);
+
+ AUTHZ_RES_NAME = "certServer.policy.configuration";
+ String scope = req.getParameter(Constants.OP_SCOPE);
+
+ if (scope.equals(ScopeDef.SC_POLICY_RULES))
+ processPolicyRuleMgmt(req, resp);
+ else if (scope.equals(ScopeDef.SC_POLICY_IMPLS))
+ processPolicyImplMgmt(req, resp);
+ else if (scope.equals(ScopeDef.SC_EXTENDED_PLUGIN_INFO)) {
+ try {
+ getExtendedPluginInfo(req, resp);
+ } catch (EBaseException e) {
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ }
+ } else
+ sendResponse(ERROR, INVALID_POLICY_SCOPE, null, resp);
+ }
+
+ private boolean readAuthorize(HttpServletRequest req,
+ HttpServletResponse resp) throws IOException {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return false;
+ }
+ return true;
+ }
+
+ private boolean modifyAuthorize(HttpServletRequest req,
+ HttpServletResponse resp) throws IOException {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Process Policy Implementation Management.
+ */
+ public void processPolicyImplMgmt(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Get operation type
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op.equals(OpDef.OP_SEARCH)) {
+ if (!readAuthorize(req, resp))
+ return;
+ listPolicyImpls(req, resp);
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ deletePolicyImpl(req, resp);
+ } else if (op.equals(OpDef.OP_READ)) {
+ if (!readAuthorize(req, resp))
+ return;
+ getPolicyImplConfig(req, resp);
+ } else if (op.equals(OpDef.OP_ADD)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ addPolicyImpl(req, resp);
+ } else
+ sendResponse(ERROR, INVALID_POLICY_IMPL_OP,
+ null, resp);
+ }
+
+ public void processPolicyRuleMgmt(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Get operation type
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op.equals(OpDef.OP_SEARCH)) {
+ if (!readAuthorize(req, resp))
+ return;
+ listPolicyInstances(req, resp);
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ deletePolicyInstance(req, resp);
+ } else if (op.equals(OpDef.OP_READ)) {
+ if (!readAuthorize(req, resp))
+ return;
+ getPolicyInstanceConfig(req, resp);
+ } else if (op.equals(OpDef.OP_ADD)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ addPolicyInstance(req, resp);
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id.equalsIgnoreCase(Constants.RS_ID_ORDER))
+ changePolicyInstanceOrdering(req, resp);
+ else
+ modifyPolicyInstance(req, resp);
+ } else
+ sendResponse(ERROR, INVALID_POLICY_IMPL_OP,
+ null, resp);
+ }
+
+ public void listPolicyImpls(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ Enumeration<String> policyImplNames = mProcessor.getPolicyImplsInfo();
+ Enumeration<IPolicyRule> policyImpls = mProcessor.getPolicyImpls();
+
+ if (policyImplNames == null ||
+ policyImpls == null) {
+ sendResponse(ERROR, INVALID_POLICY_IMPL_CONFIG, null, resp);
+ return;
+ }
+
+ // Assemble a name value pair;
+ NameValuePairs nvp = new NameValuePairs();
+
+ while (policyImplNames.hasMoreElements() &&
+ policyImpls.hasMoreElements()) {
+ String id = policyImplNames.nextElement();
+ IPolicyRule impl = policyImpls.nextElement();
+ String className =
+ impl.getClass().getName();
+ String desc = impl.getDescription();
+
+ nvp.put(id, className + "," + desc);
+ }
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ public void listPolicyInstances(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ Enumeration<String> instancesInfo = mProcessor.getPolicyInstancesInfo();
+
+ if (instancesInfo == null) {
+ sendResponse(ERROR, INVALID_POLICY_INSTANCE_CONFIG, null, resp);
+ return;
+ }
+
+ // Assemble name value pairs
+ NameValuePairs nvp = new NameValuePairs();
+
+ while (instancesInfo.hasMoreElements()) {
+ String info = instancesInfo.nextElement();
+ int i = info.indexOf(";");
+
+ nvp.put(info.substring(0, i), info.substring(i + 1));
+
+ }
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ /**
+ * Delete policy implementation
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY used when configuring cert policy constraints and
+ * extensions
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void deletePolicyImpl(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ // Get the policy impl id.
+ String id = req.getParameter(Constants.RS_ID).trim();
+
+ if (id == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp);
+ return;
+ }
+
+ try {
+ mProcessor.deletePolicyImpl(id);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, null, resp);
+ } catch (Exception e) {
+ //e.printStackTrace();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, e.toString(), null, resp);
+ }
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ public void getPolicyImplConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Get the policy impl id.
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp);
+ return;
+ }
+
+ Vector<String> v = mProcessor.getPolicyImplConfig(id);
+
+ if (v == null) {
+ sendResponse(ERROR, INVALID_POLICY_IMPL_ID, null, resp);
+ return;
+ }
+ NameValuePairs nvp = new NameValuePairs();
+
+ for (Enumeration<String> e = v.elements(); e.hasMoreElements();) {
+ String nv = e.nextElement();
+ int index = nv.indexOf("=");
+
+ nvp.put(nv.substring(0, index), nv.substring(index + 1));
+ }
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ /**
+ * Add policy implementation
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY used when configuring cert policy constraints and
+ * extensions
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void addPolicyImpl(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ // Get the policy impl id and class path.
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp);
+ return;
+ }
+
+ String classPath = req.getParameter(Constants.PR_POLICY_CLASS);
+
+ if (classPath == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, MISSING_POLICY_IMPL_CLASS, null, resp);
+ return;
+ }
+ try {
+ mProcessor.addPolicyImpl(id, classPath);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, null, resp);
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, e.toString(), null, resp);
+ }
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Delete policy instance
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY used when configuring cert policy constraints and
+ * extensions
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void deletePolicyInstance(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ // Get the policy impl id.
+ String id = req.getParameter(Constants.RS_ID).trim();
+
+ if (id == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, MISSING_POLICY_INST_ID, null, resp);
+ return;
+ }
+
+ try {
+ mProcessor.deletePolicyInstance(id);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, null, resp);
+ } catch (Exception e) {
+ //e.printStackTrace();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, e.toString(), null, resp);
+ }
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ public void getPolicyInstanceConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Get the policy rule id.
+ String id = req.getParameter(Constants.RS_ID).trim();
+
+ if (id == null) {
+ sendResponse(ERROR, MISSING_POLICY_INST_ID, null, resp);
+ return;
+ }
+
+ Vector<String> v = mProcessor.getPolicyInstanceConfig(id);
+
+ if (v == null) {
+ sendResponse(ERROR, INVALID_POLICY_INST_ID, null, resp);
+ return;
+ }
+ NameValuePairs nvp = new NameValuePairs();
+
+ for (Enumeration<String> e = v.elements(); e.hasMoreElements();) {
+ String nv = e.nextElement();
+ int index = nv.indexOf("=");
+ String name = nv.substring(0, index);
+ String value = nv.substring(index + 1);
+
+ if (value == null) {
+ value = "";
+ }
+
+ nvp.put(name, value);
+
+ }
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ public void
+ putUserPWPair(String combo) {
+ int semicolon;
+
+ semicolon = combo.indexOf(";");
+ String user = combo.substring(0, semicolon);
+ String pw = combo.substring(semicolon + 1);
+
+ CMS.putPasswordCache(user, pw);
+ }
+
+ /**
+ * Add policy instance
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY used when configuring cert policy constraints and
+ * extensions
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void addPolicyInstance(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ // Get the policy impl id and class path.
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, MISSING_POLICY_INST_ID, null, resp);
+ return;
+ }
+
+ // Get the default config params for the implementation.
+ String implName = req.getParameter(IPolicyRule.PROP_IMPLNAME);
+
+ if (implName == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp);
+ return;
+ }
+
+ // We need to fetch parameters: enable, predicate and implname
+ // always, and any additional parameters as required by the
+ // implementation.
+ Hashtable<String, String> ht = new Hashtable<String, String>();
+ String val = req.getParameter(IPolicyRule.PROP_ENABLE).trim();
+
+ if (val == null)
+ val = "true";
+ ht.put(IPolicyRule.PROP_ENABLE, val);
+
+ val = req.getParameter(IPolicyRule.PROP_PREDICATE);
+ if (val != null)
+ ht.put(IPolicyRule.PROP_PREDICATE, val);
+ ht.put(IPolicyRule.PROP_IMPLNAME, implName);
+
+ Vector<String> v = mProcessor.getPolicyImplConfig(implName);
+
+ if (v == null) {
+ // Invalid impl id
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, INVALID_POLICY_IMPL_ID, null, resp);
+ return;
+ }
+ for (Enumeration<String> e = v.elements(); e.hasMoreElements();) {
+ String nv = e.nextElement();
+ int index = nv.indexOf("=");
+ String key = nv.substring(0, index);
+
+ val = req.getParameter(key).trim();
+ if (val != null)
+ ht.put(key, val);
+ }
+
+ String pwadd = req.getParameter(PW_PASSWORD_CACHE_ADD);
+
+ if (pwadd != null) {
+ putUserPWPair(pwadd);
+ }
+
+ try {
+ mProcessor.addPolicyInstance(id, ht);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, null, resp);
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, e.toString(), null, resp);
+ }
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Change ordering of policy instances
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY used when configuring cert policy constraints and
+ * extensions
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void changePolicyInstanceOrdering(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String policyOrder =
+ req.getParameter(Constants.PR_POLICY_ORDER);
+
+ if (policyOrder == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, MISSING_POLICY_ORDERING, null, resp);
+ return;
+ }
+ try {
+ mProcessor.changePolicyInstanceOrdering(policyOrder);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, null, resp);
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, e.toString(), null, resp);
+ }
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Modify policy instance
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY used when configuring cert policy constraints and
+ * extensions
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void modifyPolicyInstance(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ // Get the policy impl id and class path.
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, MISSING_POLICY_INST_ID, null, resp);
+ return;
+ }
+
+ // Get the default config params for the implementation.
+ String implName = req.getParameter(IPolicyRule.PROP_IMPLNAME).trim();
+
+ if (implName == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp);
+ return;
+ }
+
+ // We need to fetch parameters: enable, predicate and implname
+ // always, and any additional parameters as required by the
+ // implementation.
+ Hashtable<String, String> ht = new Hashtable<String, String>();
+ String val = req.getParameter(IPolicyRule.PROP_ENABLE).trim();
+
+ if (val == null)
+ val = "true";
+ ht.put(IPolicyRule.PROP_ENABLE, val);
+
+ val = req.getParameter(IPolicyRule.PROP_PREDICATE);
+ if (val != null)
+ ht.put(IPolicyRule.PROP_PREDICATE, val);
+ ht.put(IPolicyRule.PROP_IMPLNAME, implName);
+ Vector<String> v = mProcessor.getPolicyImplConfig(implName);
+
+ if (v == null) {
+ // Invalid impl id
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, INVALID_POLICY_IMPL_ID, null, resp);
+ return;
+ }
+ // XXX
+ for (Enumeration<String> n = req.getParameterNames(); n.hasMoreElements();) {
+ String p = n.nextElement();
+ String l = req.getParameter(p);
+
+ if (l != null)
+ ht.put(p, l);
+ }
+
+ /*
+ for(Enumeration e = v.elements(); e.hasMoreElements(); )
+ {
+ String nv = (String)e.nextElement();
+ int index = nv.indexOf("=");
+ String key = nv.substring(0, index);
+ val = req.getParameter(key);
+ if (val != null)
+ ht.put(key, val);
+ }
+ */
+
+ try {
+ mProcessor.modifyPolicyInstance(id, ht);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, null, resp);
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, e.toString(), null, resp);
+ }
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/ProfileAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/ProfileAdminServlet.java
new file mode 100644
index 000000000..3d25b8b71
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/ProfileAdminServlet.java
@@ -0,0 +1,2666 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IPolicyConstraint;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileEx;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.IProfileOutput;
+import com.netscape.certsrv.profile.IProfilePolicy;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.registry.IPluginInfo;
+import com.netscape.certsrv.registry.IPluginRegistry;
+
+/**
+ * This class is an administration servlet for policy management.
+ *
+ * Each service (CA, KRA, RA) should be responsible
+ * for registering an instance of this with the remote
+ * administration subsystem.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ProfileAdminServlet extends AdminServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 4828203666899891742L;
+
+ public final static String PROP_AUTHORITY = "authority";
+
+ private final static String INFO = "ProfileAdminServlet";
+
+ public final static String PROP_PREDICATE = "predicate";
+ private IPluginRegistry mRegistry = null;
+ private IProfileSubsystem mProfileSub = null;
+
+ // These will be moved to PolicyResources
+ public static String INVALID_POLICY_SCOPE = "Invalid policy administration scope";
+ public static String INVALID_POLICY_IMPL_OP = "Invalid operation for policy implementation management";
+ public static String NYI = "Not Yet Implemented";
+ public static String INVALID_POLICY_IMPL_CONFIG = "Invalid policy implementation configuration";
+ public static String INVALID_POLICY_INSTANCE_CONFIG = "Invalid policy instance configuration";
+ public static String MISSING_POLICY_IMPL_ID = "Missing policy impl id in request";
+ public static String MISSING_POLICY_IMPL_CLASS = "Missing policy impl class in request";
+ public static String INVALID_POLICY_IMPL_ID = "Invalid policy impl id in request";
+ public static String MISSING_POLICY_INST_ID = "Missing policy id in request";
+ public static String POLICY_INST_ID_ALREADY_USED = "policy id already used";
+ public static String INVALID_POLICY_INST_ID = "Invalid policy id in request";
+ public static String COMMA = ",";
+ public static String MISSING_POLICY_ORDERING = "Missing policy ordering";
+ public static String BAD_CONFIGURATION_VAL = "Invalid configuration value.";
+
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE =
+ "LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE_3";
+
+ /**
+ * Constructs administration servlet.
+ */
+ public ProfileAdminServlet() {
+ super();
+ }
+
+ /**
+ * Initializes this servlet.
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+
+ mRegistry = (IPluginRegistry) CMS.getSubsystem(CMS.SUBSYSTEM_REGISTRY);
+ mProfileSub = (IProfileSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_PROFILE);
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Serves HTTP admin request.
+ */
+ public void service(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+
+ super.authenticate(req);
+
+ AUTHZ_RES_NAME = "certServer.profile.configuration";
+ String scope = req.getParameter(Constants.OP_SCOPE);
+
+ CMS.debug("ProfileAdminServlet: service scope: " + scope);
+ if (scope.equals(ScopeDef.SC_PROFILE_RULES)) {
+ processProfileRuleMgmt(req, resp);
+ } else if (scope.equals(ScopeDef.SC_PROFILE_POLICIES)) {
+ processProfilePolicy(req, resp);
+ } else if (scope.equals(ScopeDef.SC_PROFILE_DEFAULT_POLICY)) {
+ processPolicyDefaultConfig(req, resp);
+ } else if (scope.equals(ScopeDef.SC_PROFILE_CONSTRAINT_POLICY)) {
+ processPolicyConstraintConfig(req, resp);
+ } else if (scope.equals(ScopeDef.SC_POLICY_IMPLS)) {
+ processPolicyImplMgmt(req, resp);
+ } else if (scope.equals(ScopeDef.SC_PROFILE_INPUT)) {
+ processProfileInput(req, resp);
+ } else if (scope.equals(ScopeDef.SC_PROFILE_OUTPUT)) {
+ processProfileOutput(req, resp);
+ } else if (scope.equals(ScopeDef.SC_PROFILE_INPUT_CONFIG)) {
+ processProfileInputConfig(req, resp);
+ } else if (scope.equals(ScopeDef.SC_PROFILE_OUTPUT_CONFIG)) {
+ processProfileOutputConfig(req, resp);
+ } else
+ sendResponse(ERROR, INVALID_POLICY_SCOPE, null, resp);
+ }
+
+ private boolean readAuthorize(HttpServletRequest req,
+ HttpServletResponse resp) throws IOException {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return false;
+ }
+ return true;
+ }
+
+ private boolean modifyAuthorize(HttpServletRequest req,
+ HttpServletResponse resp) throws IOException {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return false;
+ }
+ return true;
+ }
+
+ public void processProfilePolicy(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Get operation type
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op.equals(OpDef.OP_READ)) {
+ if (!readAuthorize(req, resp))
+ return;
+ getProfilePolicy(req, resp);
+ } else if (op.equals(OpDef.OP_ADD)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ addProfilePolicy(req, resp);
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ deleteProfilePolicy(req, resp);
+ }
+ }
+
+ public void processProfileInput(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Get operation type
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op.equals(OpDef.OP_READ)) {
+ if (!readAuthorize(req, resp))
+ return;
+ getProfileInput(req, resp);
+ } else if (op.equals(OpDef.OP_ADD)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ addProfileInput(req, resp);
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ deleteProfileInput(req, resp);
+ }
+ }
+
+ public void processProfileOutput(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Get operation type
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op.equals(OpDef.OP_READ)) {
+ if (!readAuthorize(req, resp))
+ return;
+ getProfileOutput(req, resp);
+ } else if (op.equals(OpDef.OP_ADD)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ addProfileOutput(req, resp);
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ deleteProfileOutput(req, resp);
+ }
+ }
+
+ public void processProfileInputConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Get operation type
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op.equals(OpDef.OP_READ)) {
+ if (!readAuthorize(req, resp))
+ return;
+ getInputConfig(req, resp);
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ modifyInputConfig(req, resp);
+ }
+ }
+
+ public void processProfileOutputConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Get operation type
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op.equals(OpDef.OP_READ)) {
+ if (!readAuthorize(req, resp))
+ return;
+ getOutputConfig(req, resp);
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ modifyOutputConfig(req, resp);
+ }
+ }
+
+ public void processPolicyDefaultConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Get operation type
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op.equals(OpDef.OP_READ)) {
+ if (!readAuthorize(req, resp))
+ return;
+ getPolicyDefaultConfig(req, resp);
+ } else if (op.equals(OpDef.OP_ADD)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ addPolicyDefaultConfig(req, resp);
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ modifyPolicyDefaultConfig(req, resp);
+ }
+ }
+
+ public void processPolicyConstraintConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Get operation type
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ CMS.debug("ProfileAdminServlet: processPolicyConstraintConfig op " + op);
+ if (op.equals(OpDef.OP_READ)) {
+ if (!readAuthorize(req, resp))
+ return;
+ getPolicyConstraintConfig(req, resp);
+ } else if (op.equals(OpDef.OP_ADD)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ addPolicyConstraintConfig(req, resp);
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ modifyPolicyConstraintConfig(req, resp);
+ }
+ }
+
+ /**
+ * Process Policy Implementation Management.
+ */
+ public void processPolicyImplMgmt(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Get operation type
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op.equals(OpDef.OP_SEARCH)) {
+ if (!readAuthorize(req, resp))
+ return;
+ listProfileImpls(req, resp);
+ } else
+ sendResponse(ERROR, INVALID_POLICY_IMPL_OP,
+ null, resp);
+ }
+
+ public void processProfileRuleMgmt(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Get operation type
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op.equals(OpDef.OP_SEARCH)) {
+ if (!readAuthorize(req, resp))
+ return;
+ listProfileInstances(req, resp);
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ deleteProfileInstance(req, resp);
+ } else if (op.equals(OpDef.OP_READ)) {
+ if (!readAuthorize(req, resp))
+ return;
+ getProfileInstanceConfig(req, resp);
+ } else if (op.equals(OpDef.OP_ADD)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ addProfileInstance(req, resp);
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ modifyProfileInstance(req, resp);
+ } else
+ sendResponse(ERROR, INVALID_POLICY_IMPL_OP,
+ null, resp);
+ }
+
+ /**
+ * Lists all registered profile impementations
+ */
+ public void listProfileImpls(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ Enumeration<String> impls = mRegistry.getIds("profile");
+ NameValuePairs nvp = new NameValuePairs();
+
+ while (impls.hasMoreElements()) {
+ String id = impls.nextElement();
+ IPluginInfo info = mRegistry.getPluginInfo("profile", id);
+
+ nvp.put(id, info.getClassName() + "," +
+ info.getDescription(getLocale(req)));
+ }
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ /**
+ * Add policy profile
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void addProfilePolicy(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ CMS.debug("ProfileAdminServlet: in addProfilePolicy");
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = req.getParameter(Constants.RS_ID);
+
+ StringTokenizer st = new StringTokenizer(id, ";");
+ String profileId = st.nextToken();
+ String policyId = st.nextToken();
+ String defImpl = st.nextToken();
+ String conImpl = st.nextToken();
+
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ if (mProfileSub.isProfileEnable(profileId)) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req),
+ "CMS_PROFILE_CREATE_POLICY_FAILED",
+ "Profile is currently enabled"),
+ null, resp);
+ return;
+ }
+
+ StringTokenizer ss = new StringTokenizer(policyId, ":");
+ String setId = ss.nextToken();
+ String pId = ss.nextToken();
+
+ try {
+ if (!isValidId(setId)) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req),
+ "CMS_PROFILE_CREATE_POLICY_FAILED",
+ "Invalid set id " + setId),
+ null, resp);
+ return;
+ }
+ if (!isValidId(pId)) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req),
+ "CMS_PROFILE_CREATE_POLICY_FAILED",
+ "Invalid policy id " + pId),
+ null, resp);
+ return;
+ }
+ profile.createProfilePolicy(setId, pId,
+ defImpl, conImpl);
+ } catch (EBaseException e1) {
+ // error
+ CMS.debug("ProfileAdminServlet: addProfilePolicy " +
+ e1.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_PROFILE_CREATE_POLICY_FAILED",
+ e1.toString()),
+ null, resp);
+ return;
+ }
+ NameValuePairs nvp = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Add profile input
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void addProfileInput(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = req.getParameter(Constants.RS_ID);
+
+ StringTokenizer st = new StringTokenizer(id, ";");
+ String profileId = st.nextToken();
+ String inputId = st.nextToken();
+ String inputImpl = st.nextToken();
+
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ Enumeration<String> names = req.getParameterNames();
+ NameValuePairs nvps = new NameValuePairs();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+
+ if (name.equals("OP_SCOPE"))
+ continue;
+ if (name.equals("OP_TYPE"))
+ continue;
+ if (name.equals("RS_ID"))
+ continue;
+ nvps.put(name, req.getParameter(name));
+ }
+
+ try {
+ profile.createProfileInput(inputId, inputImpl, nvps);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_PROFILE_CREATE_INPUT_FAILED",
+ e1.toString()),
+ null, resp);
+
+ return;
+ }
+
+ NameValuePairs nvp = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Add profile output
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void addProfileOutput(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = req.getParameter(Constants.RS_ID);
+
+ StringTokenizer st = new StringTokenizer(id, ";");
+ String profileId = st.nextToken();
+ String outputId = st.nextToken();
+ String outputImpl = st.nextToken();
+
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ Enumeration<String> names = req.getParameterNames();
+ NameValuePairs nvps = new NameValuePairs();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+
+ if (name.equals("OP_SCOPE"))
+ continue;
+ if (name.equals("OP_TYPE"))
+ continue;
+ if (name.equals("RS_ID"))
+ continue;
+ nvps.put(name, req.getParameter(name));
+ }
+
+ try {
+ profile.createProfileOutput(outputId, outputImpl,
+ nvps);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_PROFILE_CREATE_OUTPUT_FAILED",
+ e1.toString()),
+ null, resp);
+
+ return;
+ }
+
+ NameValuePairs nvp = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Delete policy profile
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void deleteProfilePolicy(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String profileId = "";
+ String policyId = "";
+ Enumeration<String> names = req.getParameterNames();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+
+ if (name.equals("OP_SCOPE"))
+ continue;
+ if (name.equals("OP_TYPE"))
+ continue;
+ if (name.equals("RS_ID"))
+ profileId = req.getParameter(name);
+ if (name.equals("POLICYID"))
+ policyId = req.getParameter(name);
+ }
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ StringTokenizer ss = new StringTokenizer(policyId, ":");
+ String setId = ss.nextToken();
+ String pId = ss.nextToken();
+
+ try {
+ profile.deleteProfilePolicy(setId, pId);
+ } catch (EBaseException e1) {
+ CMS.debug("ProfileAdminServlet: " + e1.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ NameValuePairs nvp = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Delete profile input
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void deleteProfileInput(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String profileId = "";
+ String inputId = "";
+ Enumeration<String> names = req.getParameterNames();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+
+ if (name.equals("OP_SCOPE"))
+ continue;
+ if (name.equals("OP_TYPE"))
+ continue;
+ if (name.equals("RS_ID"))
+ profileId = req.getParameter(name);
+ if (name.equals("INPUTID"))
+ inputId = req.getParameter(name);
+ }
+ CMS.debug("ProfileAdminServlet: deleteProfileInput profileId -> " + profileId);
+ CMS.debug("ProfileAdminServlet: deleteProfileInput inputId -> " + inputId);
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ CMS.debug("deleteProfileInput profile -> " + profile);
+ try {
+ profile.deleteProfileInput(inputId);
+ } catch (EBaseException e1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ NameValuePairs nvp = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Delete profile output
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void deleteProfileOutput(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String profileId = "";
+ String outputId = "";
+ Enumeration<String> names = req.getParameterNames();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+
+ if (name.equals("OP_SCOPE"))
+ continue;
+ if (name.equals("OP_TYPE"))
+ continue;
+ if (name.equals("RS_ID"))
+ profileId = req.getParameter(name);
+ if (name.equals("OUTPUTID"))
+ outputId = req.getParameter(name);
+ }
+ CMS.debug("ProfileAdminServlet: deleteProfileOutput profileId -> " + profileId);
+ CMS.debug("ProfileAdminServlet: deleteProfileOutput outputId -> " + outputId);
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ CMS.debug("ProfileAdminServlet: deleteProfileOutput profile -> " + profile);
+ try {
+ profile.deleteProfileOutput(outputId);
+ } catch (EBaseException e1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ NameValuePairs nvp = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Add default policy profile configuration
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void addPolicyDefaultConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = req.getParameter(Constants.RS_ID);
+
+ StringTokenizer st = new StringTokenizer(id, ";");
+ String profileId = st.nextToken();
+ String policyId = st.nextToken();
+
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ StringTokenizer ss = new StringTokenizer(policyId, ":");
+ String setId = ss.nextToken();
+ String pId = ss.nextToken();
+
+ IProfilePolicy policy = profile.getProfilePolicy(setId, pId);
+ IPolicyDefault def = policy.getDefault();
+
+ Enumeration<String> names = req.getParameterNames();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+
+ if (name.equals("OP_SCOPE"))
+ continue;
+ if (name.equals("OP_TYPE"))
+ continue;
+ if (name.equals("RS_ID"))
+ continue;
+ try {
+ def.setConfig(name, req.getParameter(name));
+
+ } catch (EPropertyException e) {
+
+ CMS.debug("ProfileAdminServlet: modifyPolicyDefConfig setConfig exception.");
+ try {
+ profile.deleteProfilePolicy(setId, pId);
+ } catch (Exception e11) {
+ }
+ sendResponse(ERROR, BAD_CONFIGURATION_VAL, null, resp);
+ return;
+ }
+ // defConfig.putString("params." + name, req.getParameter(name));
+ }
+ try {
+ profile.getConfigStore().commit(false);
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+ NameValuePairs nvp = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Add policy constraints profile configuration
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void addPolicyConstraintConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = req.getParameter(Constants.RS_ID);
+
+ StringTokenizer st = new StringTokenizer(id, ";");
+ String profileId = st.nextToken();
+ String policyId = st.nextToken();
+
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ StringTokenizer ss = new StringTokenizer(policyId, ":");
+ String setId = ss.nextToken();
+ String pId = ss.nextToken();
+
+ IProfilePolicy policy = profile.getProfilePolicy(setId, pId);
+ IPolicyConstraint con = policy.getConstraint();
+
+ Enumeration<String> names = req.getParameterNames();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+
+ if (name.equals("OP_SCOPE"))
+ continue;
+ if (name.equals("OP_TYPE"))
+ continue;
+ if (name.equals("RS_ID"))
+ continue;
+
+ try {
+ con.setConfig(name, req.getParameter(name));
+
+ } catch (EPropertyException e) {
+
+ CMS.debug("ProfileAdminServlet: addPolicyConstraintsConfig setConfig exception.");
+ try {
+ profile.deleteProfilePolicy(setId, pId);
+ } catch (Exception e11) {
+ }
+ sendResponse(ERROR, BAD_CONFIGURATION_VAL, null, resp);
+ return;
+ }
+ // conConfig.putString("params." + name, req.getParameter(name));
+ }
+ try {
+ profile.getConfigStore().commit(false);
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ NameValuePairs nvp = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Modify default policy profile configuration
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void modifyPolicyDefaultConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = req.getParameter(Constants.RS_ID);
+
+ StringTokenizer st = new StringTokenizer(id, ";");
+ String profileId = st.nextToken();
+ String policyId = st.nextToken();
+
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ StringTokenizer ss = new StringTokenizer(policyId, ":");
+ String setId = ss.nextToken();
+ String pId = ss.nextToken();
+ IProfilePolicy policy = profile.getProfilePolicy(setId, pId);
+ IPolicyDefault def = policy.getDefault();
+
+ Enumeration<String> names = req.getParameterNames();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+
+ if (name.equals("OP_SCOPE"))
+ continue;
+ if (name.equals("OP_TYPE"))
+ continue;
+ if (name.equals("RS_ID"))
+ continue;
+ try {
+ def.setConfig(name, req.getParameter(name));
+
+ } catch (EPropertyException e) {
+
+ CMS.debug("ProfileAdminServlet: modifyPolicyDefConfig setConfig exception.");
+ sendResponse(ERROR, BAD_CONFIGURATION_VAL, null, resp);
+ return;
+ }
+ // defConfig.putString("params." + name, req.getParameter(name));
+ }
+ try {
+ profile.getConfigStore().commit(false);
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+ NameValuePairs nvp = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Modify profile input configuration
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void modifyInputConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = req.getParameter(Constants.RS_ID);
+
+ StringTokenizer st = new StringTokenizer(id, ";");
+ String profileId = st.nextToken();
+ String inputId = st.nextToken();
+
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ IProfileInput input = profile.getProfileInput(inputId);
+ IConfigStore inputConfig = input.getConfigStore();
+
+ Enumeration<String> names = req.getParameterNames();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+
+ if (name.equals("OP_SCOPE"))
+ continue;
+ if (name.equals("OP_TYPE"))
+ continue;
+ if (name.equals("RS_ID"))
+ continue;
+ inputConfig.putString("params." + name, req.getParameter(name));
+ }
+ try {
+ profile.getConfigStore().commit(false);
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+ NameValuePairs nvp = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Modify profile output configuration
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void modifyOutputConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = req.getParameter(Constants.RS_ID);
+
+ StringTokenizer st = new StringTokenizer(id, ";");
+ String profileId = st.nextToken();
+ String outputId = st.nextToken();
+
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ IProfileOutput output = profile.getProfileOutput(outputId);
+ IConfigStore outputConfig = output.getConfigStore();
+
+ Enumeration<String> names = req.getParameterNames();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+
+ if (name.equals("OP_SCOPE"))
+ continue;
+ if (name.equals("OP_TYPE"))
+ continue;
+ if (name.equals("RS_ID"))
+ continue;
+ outputConfig.putString("params." + name,
+ req.getParameter(name));
+ }
+ try {
+ profile.getConfigStore().commit(false);
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+ NameValuePairs nvp = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Modify policy constraints profile configuration
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void modifyPolicyConstraintConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = req.getParameter(Constants.RS_ID);
+
+ StringTokenizer st = new StringTokenizer(id, ";");
+ String profileId = st.nextToken();
+ String policyId = st.nextToken();
+
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ StringTokenizer ss = new StringTokenizer(policyId, ":");
+ String setId = ss.nextToken();
+ String pId = ss.nextToken();
+ IProfilePolicy policy = profile.getProfilePolicy(setId, pId);
+ IPolicyConstraint con = policy.getConstraint();
+
+ Enumeration<String> names = req.getParameterNames();
+
+ CMS.debug("ProfileAdminServlet: modifyPolicyConstraintConfig policy " + policy + " con " + con);
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+
+ if (name.equals("OP_SCOPE"))
+ continue;
+ if (name.equals("OP_TYPE"))
+ continue;
+ if (name.equals("RS_ID"))
+ continue;
+
+ // CMS.debug("ProfileAdminServlet: modifyPolicyConstraintConfig name" + name + " val " + req.getParameter(name));
+ try {
+ con.setConfig(name, req.getParameter(name));
+
+ } catch (EPropertyException e) {
+
+ CMS.debug("ProfileAdminServlet: modifyPolicyConstraintsConfig setConfig exception.");
+ sendResponse(ERROR, BAD_CONFIGURATION_VAL, null, resp);
+ return;
+ }
+ //conConfig.putString("params." + name, req.getParameter(name));
+ }
+ try {
+ profile.getConfigStore().commit(false);
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ NameValuePairs nvp = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ public void getPolicyDefaultConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ StringTokenizer st = new StringTokenizer(id, ";");
+ String profileId = st.nextToken();
+ String policyId = st.nextToken();
+
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ CMS.debug("ProfileAdminServlet::getPolicyDefaultConfig() - " +
+ "profile is null!");
+ throw new ServletException(e1.toString());
+ }
+
+ IProfilePolicy policy = null;
+ IPolicyDefault rule = null;
+
+ StringTokenizer ss = new StringTokenizer(policyId, ":");
+ String setId = ss.nextToken();
+ String pId = ss.nextToken();
+
+ policy = profile.getProfilePolicy(setId, pId);
+ rule = policy.getDefault();
+
+ NameValuePairs nvp = new NameValuePairs();
+ Enumeration<String> names = rule.getConfigNames();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ IDescriptor desc = rule.getConfigDescriptor(getLocale(req), name);
+
+ if (desc == null) {
+ nvp.put(name, ";" + ";" + rule.getConfig(name));
+ } else {
+ nvp.put(name,
+ desc.getSyntax()
+ + ";" + ";" + getNonNull(desc.getConstraint()) + ";"
+ + desc.getDescription(getLocale(req)) + ";" + rule.getConfig(name));
+ }
+ }
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ public void getPolicyConstraintConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String id = req.getParameter(Constants.RS_ID);
+ String constraintsList = req.getParameter(Constants.PR_CONSTRAINTS_LIST);
+
+ // this one gets called when one of the elements in the default list get
+ // selected, then it returns the list of supported constraintsPolicy
+ if (constraintsList != null) {
+
+ }
+
+ StringTokenizer st = new StringTokenizer(id, ";");
+ String profileId = st.nextToken();
+ String policyId = st.nextToken();
+
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ CMS.debug("ProfileAdminServlet::getPolicyConstraintConfig() - " +
+ "profile is null!");
+ throw new ServletException(e1.toString());
+ }
+
+ StringTokenizer ss = new StringTokenizer(policyId, ":");
+ String setId = ss.nextToken();
+ String pId = ss.nextToken();
+ IProfilePolicy policy = profile.getProfilePolicy(setId, pId);
+ IPolicyConstraint rule = policy.getConstraint();
+
+ NameValuePairs nvp = new NameValuePairs();
+ Enumeration<String> names = rule.getConfigNames();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ IDescriptor desc = rule.getConfigDescriptor(getLocale(req), name);
+
+ if (desc == null) {
+ nvp.put(name, ";" + rule.getConfig(name));
+ } else {
+ nvp.put(name,
+ desc.getSyntax()
+ + ";" + getNonNull(desc.getConstraint()) + ";" + desc.getDescription(getLocale(req))
+ + ";" + rule.getConfig(name));
+ }
+ }
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ public void getProfilePolicy(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ // only allow profile retrival if it is disabled
+
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(id);
+ } catch (EBaseException e1) {
+ CMS.debug("ProfileAdminServlet::getProfilePolicy() - " +
+ "profile is null!");
+ throw new ServletException(e1.toString());
+ }
+
+ NameValuePairs nvp = new NameValuePairs();
+ Enumeration<String> setIds = profile.getProfilePolicySetIds();
+
+ if (!setIds.hasMoreElements()) {
+ // no set id; this is a brand new profile
+ sendResponse(SUCCESS, null, nvp, resp);
+ return;
+ }
+ while (setIds.hasMoreElements()) {
+ String setId = setIds.nextElement();
+ Enumeration<IProfilePolicy> policies = profile.getProfilePolicies(setId);
+
+ while (policies.hasMoreElements()) {
+ IProfilePolicy policy = policies.nextElement();
+ IPolicyDefault def = policy.getDefault();
+ IPolicyConstraint con = policy.getConstraint();
+
+ nvp.put(setId + ":" + policy.getId(),
+ def.getName(getLocale(req)) + ";" +
+ con.getName(getLocale(req)));
+ }
+ }
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ public void getProfileOutput(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String id = req.getParameter(Constants.RS_ID);
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(id);
+ } catch (EBaseException e1) {
+ CMS.debug("ProfileAdminServlet::getProfileOutput() - " +
+ "profile is null!");
+ throw new ServletException(e1.toString());
+ }
+
+ NameValuePairs nvp = new NameValuePairs();
+ Enumeration<String> outputs = profile.getProfileOutputIds();
+
+ while (outputs.hasMoreElements()) {
+ String outputId = outputs.nextElement();
+ IProfileOutput output = profile.getProfileOutput(outputId);
+
+ nvp.put(outputId, output.getName(getLocale(req)));
+ }
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ public void getProfileInput(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String id = req.getParameter(Constants.RS_ID);
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(id);
+ } catch (EBaseException e1) {
+ CMS.debug("ProfileAdminServlet::getProfileInput() - " +
+ "profile is null!");
+ throw new ServletException(e1.toString());
+ }
+
+ NameValuePairs nvp = new NameValuePairs();
+ Enumeration<String> inputs = profile.getProfileInputIds();
+
+ while (inputs.hasMoreElements()) {
+ String inputId = inputs.nextElement();
+ IProfileInput input = profile.getProfileInput(inputId);
+
+ nvp.put(inputId, input.getName(getLocale(req)));
+ }
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ public void getInputConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ String id = req.getParameter(Constants.RS_ID);
+ StringTokenizer st = new StringTokenizer(id, ";");
+ String profileId = st.nextToken();
+ String inputId = st.nextToken();
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ CMS.debug("ProfileAdminServlet::getInputConfig() - " +
+ "profile is null!");
+ throw new ServletException(e1.toString());
+ }
+
+ IProfileInput profileInput = null;
+ NameValuePairs nvp = new NameValuePairs();
+
+ profileInput = profile.getProfileInput(inputId);
+ Enumeration<String> names = profileInput.getConfigNames();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ IDescriptor desc = profileInput.getConfigDescriptor(
+ getLocale(req), name);
+ if (desc == null) {
+ nvp.put(name, ";" + ";" + profileInput.getConfig(name));
+ } else {
+ nvp.put(name, desc.getSyntax() + ";" +
+ getNonNull(desc.getConstraint()) + ";" +
+ desc.getDescription(getLocale(req)) + ";" +
+ profileInput.getConfig(name));
+ }
+ }
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ public void getOutputConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ String id = req.getParameter(Constants.RS_ID);
+ StringTokenizer st = new StringTokenizer(id, ";");
+ String profileId = st.nextToken();
+ String outputId = st.nextToken();
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(profileId);
+ } catch (EBaseException e1) {
+ CMS.debug("ProfileAdminServlet::getOutputConfig() - " +
+ "profile is null!");
+ throw new ServletException(e1.toString());
+ }
+
+ IProfileOutput profileOutput = null;
+ NameValuePairs nvp = new NameValuePairs();
+
+ profileOutput = profile.getProfileOutput(outputId);
+ Enumeration<String> names = profileOutput.getConfigNames();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ IDescriptor desc = profileOutput.getConfigDescriptor(
+ getLocale(req), name);
+ if (desc == null) {
+ nvp.put(name, ";" + ";" + profileOutput.getConfig(name));
+ } else {
+ nvp.put(name, desc.getSyntax() + ";" +
+ getNonNull(desc.getConstraint()) + ";" +
+ desc.getDescription(getLocale(req)) + ";" +
+ profileOutput.getConfig(name));
+ }
+ }
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ public void listProfileInstances(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ NameValuePairs nvp = new NameValuePairs();
+ Enumeration<String> e = mProfileSub.getProfileIds();
+
+ while (e.hasMoreElements()) {
+ String profileId = e.nextElement();
+
+ String status = null;
+
+ if (mProfileSub.isProfileEnable(profileId)) {
+ status = "enabled";
+ } else {
+ status = "disabled";
+ }
+
+ // mInstanceId + ";visible;" + enabled
+ nvp.put(profileId, profileId + ";visible;" + status);
+ }
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ public void getProfileInstanceConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ String id = req.getParameter(Constants.RS_ID);
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(id);
+ } catch (EBaseException e1) {
+ CMS.debug("ProfileAdminServlet::getProfileInstanceConfig() - " +
+ "profile is null!");
+ throw new ServletException(e1.toString());
+ }
+
+ NameValuePairs nvp = new NameValuePairs();
+
+ nvp.put("name", profile.getName(getLocale(req)));
+ nvp.put("desc", profile.getDescription(getLocale(req)));
+ nvp.put("visible", Boolean.toString(profile.isVisible()));
+ nvp.put("enable", Boolean.toString(
+ mProfileSub.isProfileEnable(id)));
+
+ String authid = profile.getAuthenticatorId();
+
+ if (authid == null) {
+ nvp.put("auth", "");
+ } else {
+ nvp.put("auth", authid);
+ }
+ CMS.debug("ProfileAdminServlet: authid=" + authid);
+ nvp.put("plugin", mProfileSub.getProfileClassId(id));
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ /**
+ * Delete profile instance
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void deleteProfileInstance(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ // Get the policy impl id and class path.
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, MISSING_POLICY_INST_ID, null, resp);
+ return;
+ }
+
+ String config = null;
+
+ try {
+ config = CMS.getConfigStore().getString("profile." + id + ".config");
+ } catch (EBaseException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ try {
+ mProfileSub.deleteProfile(id, config);
+ } catch (EProfileException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), e.toString(), id), null, resp);
+ return;
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, null, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ public void
+ putUserPWPair(String combo) {
+ int semicolon;
+
+ semicolon = combo.indexOf(";");
+ String user = combo.substring(0, semicolon);
+ String pw = combo.substring(semicolon + 1);
+
+ CMS.putPasswordCache(user, pw);
+ }
+
+ public boolean isValidId(String id) {
+ for (int i = 0; i < id.length(); i++) {
+ char c = id.charAt(i);
+ if (!Character.isLetterOrDigit(c))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Add profile instance
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void addProfileInstance(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ // Get the policy impl id and class path.
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null || id.trim().equals("") || !isValidId(id)) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, MISSING_POLICY_INST_ID, null, resp);
+ return;
+ }
+
+ // see if profile id already used
+ IProfile p = null;
+
+ try {
+ p = mProfileSub.getProfile(id);
+ } catch (EProfileException e1) {
+ }
+ if (p != null) {
+ sendResponse(ERROR, POLICY_INST_ID_ALREADY_USED, null, resp);
+ return;
+ }
+
+ String impl = req.getParameter("impl");
+ String name = req.getParameter("name");
+ String visible = req.getParameter("visible");
+ String auth = req.getParameter("auth");
+ String config = null;
+
+ ISubsystem subsystem = CMS.getSubsystem("ca");
+ String subname = "ca";
+
+ if (subsystem == null)
+ subname = "ra";
+
+ String subpath = "/profiles/";
+
+ try {
+ String version = CMS.getConfigStore().getString("cms.version");
+ if (version.indexOf('.') > -1) {
+ version = version.substring(0, version.indexOf('.'));
+ }
+ int v = Integer.parseInt(version);
+ if (v >= 10) {
+ subpath = "/ca/profiles/";
+ }
+ config = CMS.getConfigStore().getString("instanceRoot") + subpath + subname + "/" + id + ".cfg";
+ } catch (EBaseException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ IPluginInfo info = mRegistry.getPluginInfo("profile", impl);
+
+ IProfile profile = null;
+
+ // create configuration file
+ File configFile = new File(config);
+
+ configFile.createNewFile();
+
+ // create profile
+ try {
+ profile = mProfileSub.createProfile(id, impl,
+ info.getClassName(),
+ config);
+ profile.setName(getLocale(req), name);
+ profile.setDescription(getLocale(req), name);
+ if (visible != null && visible.equals("true")) {
+ profile.setVisible(true);
+ } else {
+ profile.setVisible(false);
+ }
+ profile.setAuthenticatorId(auth);
+ profile.getConfigStore().commit(false);
+
+ mProfileSub.createProfileConfig(id, impl, config);
+ if (profile instanceof IProfileEx) {
+ // populates profile specific plugins such as
+ // policies, inputs and outputs
+ ((IProfileEx) profile).populate();
+ }
+ } catch (Exception e) {
+ CMS.debug("ProfileAdminServlet: " + e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, null, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ /**
+ * Modify profile instance
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings
+ * and cert profile; obsoletes extensions and constraints policies)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ */
+ public void modifyProfileInstance(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ // Get the policy impl id and class path.
+ String id = req.getParameter(Constants.RS_ID);
+
+ IProfile profile = null;
+
+ try {
+ profile = mProfileSub.getProfile(id);
+ } catch (EBaseException e1) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, null, null, resp);
+ return;
+ }
+ String name = req.getParameter("name");
+ String desc = req.getParameter("desc");
+ String auth = req.getParameter("auth");
+ String visible = req.getParameter("visible");
+
+ // String config = req.getParameter("config");
+
+ profile.setAuthenticatorId(auth);
+ profile.setName(getLocale(req), name);
+ profile.setDescription(getLocale(req), desc);
+ if (visible != null && visible.equals("true")) {
+ profile.setVisible(true);
+ } else {
+ profile.setVisible(false);
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ try {
+ profile.getConfigStore().commit(false);
+ } catch (Exception e) {
+ }
+
+ sendResponse(SUCCESS, null, null, resp);
+ } catch (IOException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+ }
+
+ protected String getNonNull(String s) {
+ if (s == null)
+ return "";
+ return s;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/PublisherAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/PublisherAdminServlet.java
new file mode 100644
index 000000000..423fad360
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/PublisherAdminServlet.java
@@ -0,0 +1,3110 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.ExtendedPluginInfo;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.Plugin;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ConfigConstants;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ILdapAuthInfo;
+import com.netscape.certsrv.ldap.ILdapBoundConnFactory;
+import com.netscape.certsrv.ldap.ILdapConnInfo;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.EMapperNotFound;
+import com.netscape.certsrv.publish.EMapperPluginNotFound;
+import com.netscape.certsrv.publish.EPublisherNotFound;
+import com.netscape.certsrv.publish.EPublisherPluginNotFound;
+import com.netscape.certsrv.publish.ERuleNotFound;
+import com.netscape.certsrv.publish.ERulePluginNotFound;
+import com.netscape.certsrv.publish.ILdapMapper;
+import com.netscape.certsrv.publish.ILdapPublisher;
+import com.netscape.certsrv.publish.ILdapRule;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.publish.MapperPlugin;
+import com.netscape.certsrv.publish.MapperProxy;
+import com.netscape.certsrv.publish.PublisherPlugin;
+import com.netscape.certsrv.publish.PublisherProxy;
+import com.netscape.certsrv.publish.RulePlugin;
+import com.netscape.certsrv.security.ICryptoSubsystem;
+import com.netscape.cmsutil.password.IPasswordStore;
+
+/**
+ * A class representing an publishing servlet for the
+ * Publishing subsystem. This servlet is responsible
+ * to serve configuration requests for the Publishing subsystem.
+ *
+ * @version $Revision$, $Date$
+ */
+public class PublisherAdminServlet extends AdminServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7055088618787207262L;
+
+ public final static String PROP_AUTHORITY = "authority";
+
+ private final static String INFO = "PublisherAdminServlet";
+ public final static String NOMAPPER = "<NONE>";
+ private IPublisherProcessor mProcessor = null;
+ private IAuthority mAuth = null;
+
+ public PublisherAdminServlet() {
+ super();
+ }
+
+ /**
+ * Initializes this servlet.
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ String authority = config.getInitParameter(PROP_AUTHORITY);
+
+ if (authority != null)
+ mAuth = (IAuthority) CMS.getSubsystem(authority);
+ if (mAuth != null)
+ if (mAuth instanceof ICertificateAuthority) {
+ mProcessor = ((ICertificateAuthority) mAuth).getPublisherProcessor();
+ } else
+ throw new ServletException(authority + " does not have publishing processor!");
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Serves HTTP admin request.
+ */
+ public void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+
+ CMS.debug("PublisherAdminServlet: in service");
+ String scope = req.getParameter(Constants.OP_SCOPE);
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op == null) {
+ //System.out.println("SRVLT_INVALID_PROTOCOL");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"),
+ null, resp);
+ return;
+ }
+
+ // for the rest
+ try {
+ super.authenticate(req);
+
+ if (op.equals(OpDef.OP_AUTH)) { // for admin authentication only
+ sendResponse(SUCCESS, null, null, resp);
+ return;
+ }
+ } catch (IOException e) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHS_FAILED"),
+ null, resp);
+ return;
+ }
+ try {
+ AUTHZ_RES_NAME = "certServer.publisher.configuration";
+ if (scope != null) {
+ if (op.equals(OpDef.OP_READ)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_LDAP)) {
+ getLDAPDest(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_PUBLISHER_IMPLS)) {
+ getConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_PUBLISHER_RULES)) {
+ getInstConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_MAPPER_IMPLS)) {
+ getMapperConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_MAPPER_RULES)) {
+ getMapperInstConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_RULE_IMPLS)) {
+ getRuleConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_EXTENDED_PLUGIN_INFO)) {
+ getExtendedPluginInfo(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_RULE_RULES)) {
+ getRuleInstConfig(req, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_LDAP)) {
+ setLDAPDest(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_PUBLISHER_RULES)) {
+ modPublisherInst(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_MAPPER_RULES)) {
+ modMapperInst(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_RULE_RULES)) {
+ modRuleInst(req, resp, scope);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_PROCESS)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_LDAP)) {
+ testSetLDAPDest(req, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_SEARCH)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_PUBLISHER_IMPLS)) {
+ listPublisherPlugins(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_PUBLISHER_RULES)) {
+ listPublisherInsts(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_MAPPER_IMPLS)) {
+ listMapperPlugins(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_MAPPER_RULES)) {
+ listMapperInsts(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_RULE_IMPLS)) {
+ listRulePlugins(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_RULE_RULES)) {
+ listRuleInsts(req, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_ADD)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_PUBLISHER_IMPLS)) {
+ addPublisherPlugin(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_PUBLISHER_RULES)) {
+ addPublisherInst(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_MAPPER_IMPLS)) {
+ addMapperPlugin(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_MAPPER_RULES)) {
+ addMapperInst(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_RULE_IMPLS)) {
+ addRulePlugin(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_RULE_RULES)) {
+ addRuleInst(req, resp, scope);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_PUBLISHER_IMPLS)) {
+ delPublisherPlugin(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_PUBLISHER_RULES)) {
+ delPublisherInst(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_MAPPER_IMPLS)) {
+ delMapperPlugin(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_MAPPER_RULES)) {
+ delMapperInst(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_RULE_IMPLS)) {
+ delRulePlugin(req, resp, scope);
+ return;
+ } else if (scope.equals(ScopeDef.SC_RULE_RULES)) {
+ delRuleInst(req, resp, scope);
+ return;
+ }
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_TYPE", op),
+ null, resp);
+ return;
+ }
+ } else {
+ //System.out.println("SRVLT_INVALID_OP_SCOPE");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ } catch (EBaseException e) {
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ }
+ //System.out.println("SRVLT_FAIL_PERFORM 2");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_PERFORM_FAILED"),
+ null, resp);
+ return;
+ }
+
+ private IExtendedPluginInfo getExtendedPluginInfo(IPublisherProcessor
+ p) {
+ Enumeration<String> mappers = p.getMapperInsts().keys();
+ Enumeration<String> publishers = p.getPublisherInsts().keys();
+
+ StringBuffer map = new StringBuffer();
+
+ for (; mappers.hasMoreElements();) {
+ String name = mappers.nextElement();
+
+ if (map.length() == 0) {
+ map.append(name);
+ } else {
+ map.append(",");
+ map.append(name);
+ }
+ }
+ StringBuffer publish = new StringBuffer();
+
+ for (; publishers.hasMoreElements();) {
+ String name = publishers.nextElement();
+
+ publish.append(",");
+ publish.append(name);
+ }
+
+ String epi[] = new String[] {
+ "type;choice(cacert,crl,certs,xcert);The certType of the request",
+ "mapper;choice("
+ + map.toString()
+ + ");Use the mapper to find the ldap dn to publish the certificate or crl",
+ "publisher;choice("
+ + publish.toString()
+ + ");Use the publisher to publish the certificate or crl a directory etc",
+ "enable;boolean;",
+ "predicate;string;"
+ };
+
+ return new ExtendedPluginInfo(epi);
+ }
+
+ private NameValuePairs getExtendedPluginInfo(Locale locale, String implType, String implName) {
+ IExtendedPluginInfo ext_info = null;
+ Object impl = null;
+
+ if (implType.equals(Constants.PR_EXT_PLUGIN_IMPLTYPE_PUBLISHRULE)) {
+ IPublisherProcessor p_processor = mProcessor;
+
+ // Should get the registered rules from processor
+ // instead of plugin
+ // OLD: impl = getClassByNameAsExtendedPluginInfo(plugin.getClassPath());
+ impl = getExtendedPluginInfo(p_processor);
+ } else if (implType.equals(Constants.PR_EXT_PLUGIN_IMPLTYPE_MAPPER)) {
+ IPublisherProcessor p_processor = mProcessor;
+ Plugin plugin = p_processor.getMapperPlugins().get(implName
+ );
+
+ impl = getClassByNameAsExtendedPluginInfo(plugin.getClassPath());
+
+ } else if (implType.equals(Constants.PR_EXT_PLUGIN_IMPLTYPE_PUBLISHER)) {
+ IPublisherProcessor p_processor = mProcessor;
+ Plugin plugin = p_processor.getPublisherPlugins().get(implName);
+
+ impl = getClassByNameAsExtendedPluginInfo(plugin.getClassPath());
+ }
+ if (impl != null) {
+ if (impl instanceof IExtendedPluginInfo) {
+ ext_info = (IExtendedPluginInfo) impl;
+ }
+ }
+
+ NameValuePairs nvps = null;
+
+ if (ext_info == null) {
+ nvps = new NameValuePairs();
+ } else {
+ nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale));
+ }
+
+ return nvps;
+
+ }
+
+ /**
+ * retrieve extended plugin info such as brief description, type info
+ * from policy, authentication,
+ * need to add: listener, mapper and publishing plugins
+ */
+ private void getExtendedPluginInfo(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ int colon = id.indexOf(':');
+
+ String implType = id.substring(0, colon);
+ String implName = id.substring(colon + 1);
+
+ NameValuePairs params =
+ getExtendedPluginInfo(getLocale(req), implType, implName);
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void getLDAPDest(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ IConfigStore config = mAuth.getConfigStore();
+ IConfigStore publishcfg = config.getSubStore(IPublisherProcessor.PROP_PUBLISH_SUBSTORE);
+ IConfigStore ldapcfg = publishcfg.getSubStore(IPublisherProcessor.PROP_LDAP_PUBLISH_SUBSTORE);
+ IConfigStore ldap = ldapcfg.getSubStore(IPublisherProcessor.PROP_LDAP);
+
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_ENABLE))
+ continue;
+ if (name.equals(Constants.PR_PUBLISHING_ENABLE))
+ continue;
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_ENABLE))
+ continue;
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_THREADS))
+ continue;
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_PAGE_SIZE))
+ continue;
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_PRIORITY))
+ continue;
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_STATUS))
+ continue;
+ if (name.equals(Constants.PR_CERT_NAMES)) {
+ ICryptoSubsystem jss = (ICryptoSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO);
+
+ params.put(name, jss.getAllCerts());
+ } else {
+ String value = ldap.getString(name, "");
+
+ if (value == null || value.equals("")) {
+ if (name.equals(ILdapBoundConnFactory.PROP_LDAPCONNINFO + "." + ILdapConnInfo.PROP_HOST)) {
+ value = mConfig.getString(ConfigConstants.PR_MACHINE_NAME, null);
+ } else if (name.equals(ILdapBoundConnFactory.PROP_LDAPCONNINFO + "." + ILdapConnInfo.PROP_PORT)) {
+ value = ILdapConnInfo.PROP_PORT_DEFAULT;
+ } else if (name.equals(ILdapBoundConnFactory.PROP_LDAPAUTHINFO + "." + ILdapAuthInfo.PROP_BINDDN)) {
+ value = ILdapAuthInfo.PROP_BINDDN_DEFAULT;
+ }
+ }
+ params.put(name, value);
+ }
+ }
+ params.put(Constants.PR_PUBLISHING_ENABLE,
+ publishcfg.getString(IPublisherProcessor.PROP_ENABLE, Constants.FALSE));
+ params.put(Constants.PR_PUBLISHING_QUEUE_ENABLE,
+ publishcfg.getString(Constants.PR_PUBLISHING_QUEUE_ENABLE, Constants.TRUE));
+ params.put(Constants.PR_PUBLISHING_QUEUE_THREADS,
+ publishcfg.getString(Constants.PR_PUBLISHING_QUEUE_THREADS, "3"));
+ params.put(Constants.PR_PUBLISHING_QUEUE_PAGE_SIZE,
+ publishcfg.getString(Constants.PR_PUBLISHING_QUEUE_PAGE_SIZE, "40"));
+ params.put(Constants.PR_PUBLISHING_QUEUE_PRIORITY,
+ publishcfg.getString(Constants.PR_PUBLISHING_QUEUE_PRIORITY, "0"));
+ params.put(Constants.PR_PUBLISHING_QUEUE_STATUS,
+ publishcfg.getString(Constants.PR_PUBLISHING_QUEUE_STATUS, "200"));
+ params.put(Constants.PR_ENABLE,
+ ldapcfg.getString(IPublisherProcessor.PROP_ENABLE, Constants.FALSE));
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void setLDAPDest(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+
+ //Save New Settings to the config file
+ IConfigStore config = mAuth.getConfigStore();
+ IConfigStore publishcfg = config.getSubStore(IPublisherProcessor.PROP_PUBLISH_SUBSTORE);
+ IConfigStore ldapcfg = publishcfg.getSubStore(IPublisherProcessor.PROP_LDAP_PUBLISH_SUBSTORE);
+ IConfigStore ldap = ldapcfg.getSubStore(IPublisherProcessor.PROP_LDAP);
+
+ //set enable flag
+ publishcfg.putString(IPublisherProcessor.PROP_ENABLE, req.getParameter(Constants.PR_PUBLISHING_ENABLE));
+ String enable = req.getParameter(Constants.PR_ENABLE);
+
+ ldapcfg.putString(IPublisherProcessor.PROP_ENABLE, enable);
+ if (enable.equals("false")) {
+ // need to disable the ldap module here
+ mProcessor.setLdapConnModule(null);
+ }
+
+ //set reset of the parameters
+ Enumeration<String> e = req.getParameterNames();
+ String pwd = null;
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_ENABLE))
+ continue;
+ if (name.equals(Constants.PR_PUBLISHING_ENABLE))
+ continue;
+ // don't store password in the config file.
+ if (name.equals(Constants.PR_BIND_PASSWD))
+ continue; // old style password read from config.
+ if (name.equals(Constants.PR_DIRECTORY_MANAGER_PWD)) {
+ pwd = req.getParameter(name);
+ continue;
+ }
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_ENABLE)) {
+ publishcfg.putString(name, req.getParameter(name));
+ continue;
+ }
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_THREADS)) {
+ publishcfg.putString(name, req.getParameter(name));
+ continue;
+ }
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_PAGE_SIZE)) {
+ publishcfg.putString(name, req.getParameter(name));
+ continue;
+ }
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_PRIORITY)) {
+ publishcfg.putString(name, req.getParameter(name));
+ continue;
+ }
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_STATUS)) {
+ publishcfg.putString(name, req.getParameter(name));
+ continue;
+ }
+
+ /* Don't enter the publishing pw into the config store */
+ ldap.putString(name, req.getParameter(name));
+ }
+
+ commit(true);
+
+ /* Do a "PUT" of the new pw to the watchdog"
+ ** do not remove - cfu
+ if (pwd != null)
+ CMS.putPasswordCache(PW_TAG_CA_LDAP_PUBLISHING, pwd);
+ */
+
+ // support publishing dirsrv with different pwd than internaldb
+ // update passwordFile
+ String prompt = ldap.getString(Constants.PR_BINDPWD_PROMPT);
+ IPasswordStore pwdStore = CMS.getPasswordStore();
+ CMS.debug("PublisherAdminServlet: setLDAPDest(): saving password for " + prompt + " to password file");
+ pwdStore.putPassword(prompt, pwd);
+ pwdStore.commit();
+ CMS.debug("PublisherAdminServlet: setLDAPDest(): password saved");
+
+ /* we'll shut down and restart the PublisherProcessor instead
+ // what a hack to do this without require restart server
+ // ILdapAuthInfo authInfo = CMS.getLdapAuthInfo();
+ ILdapConnModule connModule = mProcessor.getLdapConnModule();
+ ILdapAuthInfo authInfo = null;
+ if (connModule != null) {
+ authInfo = connModule.getLdapAuthInfo();
+ }
+
+ // authInfo.addPassword(PW_TAG_CA_LDAP_PUBLISHING, pwd);
+ if (authInfo != null) {
+ CMS.debug("PublisherAdminServlet: setLDAPDest(): adding password to memory cache");
+ authInfo.addPassword(prompt, pwd);
+ } else
+ CMS.debug("PublisherAdminServlet: setLDAPDest(): authInfo null");
+ */
+
+ try {
+ CMS.debug("PublisherAdminServlet: setLDAPDest(): restarting publishing processor");
+ mProcessor.shutdown();
+ mProcessor.startup();
+ CMS.debug("PublisherAdminServlet: setLDAPDest(): publishing processor restarted");
+ } catch (Exception ex) {
+ // force to save the config even there is error
+ // ignore any exception
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_FAIL_RES_LDAP", ex.toString()));
+ }
+
+ //XXX See if we can dynamically in B2
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ private void testSetLDAPDest(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+
+ CMS.debug("PublisherAdmineServlet: in testSetLDAPDest");
+ //Save New Settings to the config file
+ IConfigStore config = mAuth.getConfigStore();
+ IConfigStore publishcfg = config.getSubStore(IPublisherProcessor.PROP_PUBLISH_SUBSTORE);
+ IConfigStore ldapcfg = publishcfg.getSubStore(IPublisherProcessor.PROP_LDAP_PUBLISH_SUBSTORE);
+ IConfigStore ldap = ldapcfg.getSubStore(IPublisherProcessor.PROP_LDAP);
+
+ //set enable flag
+ publishcfg.putString(IPublisherProcessor.PROP_ENABLE,
+ req.getParameter(Constants.PR_PUBLISHING_ENABLE));
+ String ldapPublish = req.getParameter(Constants.PR_ENABLE);
+
+ ldapcfg.putString(IPublisherProcessor.PROP_ENABLE, ldapPublish);
+ if (ldapPublish.equals("false")) {
+ // need to disable the ldap module here
+ mProcessor.setLdapConnModule(null);
+ }
+
+ //set reset of the parameters
+ Enumeration<String> e = req.getParameterNames();
+ String pwd = null;
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_ENABLE))
+ continue;
+ if (name.equals(Constants.PR_PUBLISHING_ENABLE))
+ continue;
+ // don't store password in the config file.
+ if (name.equals(Constants.PR_BIND_PASSWD))
+ continue; // old style password read from config.
+ if (name.equals(Constants.PR_DIRECTORY_MANAGER_PWD)) {
+ pwd = req.getParameter(name);
+ continue;
+ }
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_ENABLE)) {
+ publishcfg.putString(name, req.getParameter(name));
+ continue;
+ }
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_THREADS)) {
+ publishcfg.putString(name, req.getParameter(name));
+ continue;
+ }
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_PAGE_SIZE)) {
+ publishcfg.putString(name, req.getParameter(name));
+ continue;
+ }
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_PRIORITY)) {
+ publishcfg.putString(name, req.getParameter(name));
+ continue;
+ }
+ if (name.equals(Constants.PR_PUBLISHING_QUEUE_STATUS)) {
+ publishcfg.putString(name, req.getParameter(name));
+ continue;
+ }
+
+ /* Don't enter the publishing pw into the config store */
+ ldap.putString(name, req.getParameter(name));
+ }
+
+ // test before commit
+ if (publishcfg.getBoolean(IPublisherProcessor.PROP_ENABLE) &&
+ ldapcfg.getBoolean(IPublisherProcessor.PROP_ENABLE)) {
+ params.put("title",
+ "You've attempted to configure CMS to connect" +
+ " to a LDAP directory. The connection status is" +
+ " as follows:\n \n");
+ LDAPConnection conn = null;
+ ILdapConnInfo connInfo =
+ CMS.getLdapConnInfo(ldap.getSubStore(
+ ILdapBoundConnFactory.PROP_LDAPCONNINFO));
+ //LdapAuthInfo authInfo =
+ //new LdapAuthInfo(ldap.getSubStore(
+ // ILdapBoundConnFactory.PROP_LDAPAUTHINFO));
+ String host = connInfo.getHost();
+ int port = connInfo.getPort();
+ boolean secure = connInfo.getSecure();
+ //int authType = authInfo.getAuthType();
+ String authType = ldap.getSubStore(
+ ILdapBoundConnFactory.PROP_LDAPAUTHINFO).getString(ILdapAuthInfo.PROP_LDAPAUTHTYPE);
+ int version = connInfo.getVersion();
+ String bindAs = null;
+ String certNickName = null;
+
+ if (authType.equals(ILdapAuthInfo.LDAP_SSLCLIENTAUTH_STR)) {
+ try {
+ //certNickName = authInfo.getParms()[0];
+ certNickName =
+ ldap.getSubStore(
+ ILdapBoundConnFactory.PROP_LDAPAUTHINFO).getString(
+ ILdapAuthInfo.PROP_CLIENTCERTNICKNAME);
+ conn = new LDAPConnection(CMS.getLdapJssSSLSocketFactory(
+ certNickName));
+ CMS.debug("Publishing Test certNickName=" + certNickName);
+ params.put(Constants.PR_CONN_INITED,
+ "Create ssl LDAPConnection with certificate: " +
+ certNickName + dashes(70 - 44 - certNickName.length()) + " Success");
+ } catch (Exception ex) {
+ params.put(Constants.PR_CONN_INIT_FAIL,
+ "Create ssl LDAPConnection with certificate: "
+ +
+ certNickName + dashes(70 - 44 - certNickName.length()) + " failure\n"
+ + " exception: " + ex);
+ params.put(Constants.PR_SAVE_NOT,
+ "\n \nIf the problem is not fixed then LDAP publishing will fail.\n" +
+ "Do you want to save the configuration anyway?");
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+ try {
+ conn.connect(host, port);
+ params.put(Constants.PR_CONN_OK,
+ "Connect to directory server "
+ +
+ host + " at port " + port +
+ dashes(70 - 37 - host.length() - (Integer.valueOf(port)).toString().length())
+ + " Success");
+ params.put(Constants.PR_AUTH_OK,
+ "Authentication: SSL client authentication" +
+ dashes(70 - 41) + " Success" +
+ "\nBind to the directory as: " + certNickName +
+ dashes(70 - 26 - certNickName.length()) + " Success");
+ } catch (LDAPException ex) {
+ if (ex.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ params.put(Constants.PR_CONN_FAIL,
+ "Connect to directory server " +
+ host + " at port " + port +
+ dashes(70 - 37 - host.length() - (Integer.valueOf(port)).toString().length()) +
+ " Failure\n" +
+ " error: server unavailable");
+ } else {
+ params.put(Constants.PR_CONN_FAIL,
+ "Connect to directory server " +
+ host + " at port " + port +
+ dashes(70 - 37 - host.length() - (Integer.valueOf(port)).toString().length()) +
+ " Failure");
+ }
+ params.put(Constants.PR_SAVE_NOT,
+ "\n \nIf the problem is not fixed then " +
+ "LDAP publishing will fail.\n" +
+ "Do you want to save the configuration anyway?");
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+ } else {
+ try {
+ if (secure) {
+ conn = new LDAPConnection(
+ CMS.getLdapJssSSLSocketFactory());
+ params.put(Constants.PR_CONN_INITED,
+ "Create ssl LDAPConnection" +
+ dashes(70 - 25) + " Success");
+ } else {
+ conn = new LDAPConnection();
+ params.put(Constants.PR_CONN_INITED,
+ "Create LDAPConnection" +
+ dashes(70 - 21) + " Success");
+ }
+ } catch (Exception ex) {
+ params.put(Constants.PR_CONN_INIT_FAIL,
+ "Create LDAPConnection" +
+ dashes(70 - 21) + " Failure\n" +
+ "exception: " + ex);
+ params.put(Constants.PR_SAVE_NOT,
+ "\n \nIf the problem is not fixed then " +
+ "LDAP publishing will fail.\n" +
+ "Do you want to save the configuration anyway?");
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+ try {
+ conn.connect(host, port);
+ params.put(Constants.PR_CONN_OK,
+ "Connect to directory server "
+ +
+ host + " at port " + port +
+ dashes(70 - 37 - host.length() - (Integer.valueOf(port)).toString().length())
+ + " Success");
+ } catch (LDAPException ex) {
+ if (ex.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ params.put(Constants.PR_CONN_FAIL,
+ "Connect to directory server "
+ +
+ host + " at port " + port +
+ dashes(70 - 37 - host.length() - (Integer.valueOf(port)).toString().length())
+ + " Failure" +
+ "\nerror: server unavailable");
+ } else {
+ params.put(Constants.PR_CONN_FAIL,
+ "Connect to directory server "
+ +
+ host + " at port " + port +
+ dashes(70 - 37 - host.length() - (Integer.valueOf(port)).toString().length())
+ + " Failure" +
+ "\nexception: " + ex);
+ }
+ params.put(Constants.PR_SAVE_NOT,
+ "\n \nIf the problem is not fixed then " +
+ "LDAP publishing will fail.\n" +
+ "Do you want to save the configuration anyway?");
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+ try {
+ //bindAs = authInfo.getParms()[0];
+ bindAs = ldap.getSubStore(
+ ILdapBoundConnFactory.PROP_LDAPAUTHINFO).getString(ILdapAuthInfo.PROP_BINDDN);
+ conn.authenticate(version, bindAs, pwd);
+ params.put(Constants.PR_AUTH_OK,
+ "Authentication: Basic authentication" +
+ dashes(70 - 36) + " Success" +
+ "\nBind to the directory as: " + bindAs +
+ dashes(70 - 26 - bindAs.length()) + " Success");
+ } catch (LDAPException ex) {
+ if (ex.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT) {
+ params.put(Constants.PR_AUTH_FAIL,
+ "Authentication: Basic authentication" +
+ dashes(70 - 36) + "Failure" +
+ "\nBind to the directory as: " + bindAs +
+ dashes(70 - 26 - bindAs.length()) +
+ "Failure" + "\nThe object doesn't exist. " +
+ "Please correct the value assigned in the" +
+ " \"Directory manager DN\" field.");
+ } else if (ex.getLDAPResultCode() == LDAPException.INVALID_CREDENTIALS) {
+ params.put(Constants.PR_AUTH_FAIL,
+ "Authentication: Basic authentication" +
+ dashes(70 - 36) + " Failure" +
+ "\nBind to the directory as: " + bindAs +
+ dashes(70 - 26 - bindAs.length()) +
+ " Failure" + "\nInvalid password. " +
+ "Please correct the value assigned in the" +
+ " \"Password\" field.");
+ } else {
+ params.put(Constants.PR_AUTH_FAIL,
+ "Authentication: Basic authentication" +
+ dashes(70 - 36) + " Failure" +
+ "\nBind to the directory as: " + bindAs +
+ dashes(70 - 26 - bindAs.length()) +
+ " Failure");
+ }
+ params.put(Constants.PR_SAVE_NOT,
+ "\n \nIf the problem is not fixed then " +
+ "LDAP publishing will fail.\n" +
+ "Do you want to save the configuration anyway?");
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+ }
+
+ }
+
+ //commit(true);
+ if (ldapcfg.getBoolean(IPublisherProcessor.PROP_ENABLE) &&
+ pwd != null) {
+
+ /* Do a "PUT" of the new pw to the watchdog"
+ ** do not remove - cfu
+ CMS.putPasswordCache(PW_TAG_CA_LDAP_PUBLISHING, pwd);
+ */
+
+ // support publishing dirsrv with different pwd than internaldb
+ // update passwordFile
+ String prompt = ldap.getString(Constants.PR_BINDPWD_PROMPT);
+ IPasswordStore pwdStore = CMS.getPasswordStore();
+ CMS.debug("PublisherAdminServlet: testSetLDAPDest(): saving password for " +
+ prompt + " to password file");
+ pwdStore.putPassword(prompt, pwd);
+ pwdStore.commit();
+ CMS.debug("PublisherAdminServlet: testSetLDAPDest(): password saved");
+ /* we'll shut down and restart the PublisherProcessor instead
+ // what a hack to do this without require restart server
+ // ILdapAuthInfo authInfo = CMS.getLdapAuthInfo();
+ ILdapConnModule connModule = mProcessor.getLdapConnModule();
+ ILdapAuthInfo authInfo = null;
+ if (connModule != null) {
+ authInfo = connModule.getLdapAuthInfo();
+ } else
+ CMS.debug("PublisherAdminServlet: testSetLDAPDest(): connModule null");
+
+ // authInfo.addPassword(PW_TAG_CA_LDAP_PUBLISHING, pwd);
+ if (authInfo != null) {
+ CMS.debug("PublisherAdminServlet: testSetLDAPDest(): adding password to memory cache");
+ authInfo.addPassword(prompt, pwd);
+ } else
+ CMS.debug("PublisherAdminServlet: testSetLDAPDest(): authInfo null");
+ */
+ }
+ //params.add(Constants.PR_SAVE_OK,
+ // "\n \nConfiguration changes are now committed.");
+
+ mProcessor.shutdown();
+
+ if (publishcfg.getBoolean(IPublisherProcessor.PROP_ENABLE)) {
+ mProcessor.startup();
+ //params.add("restarted", "Publishing is restarted.");
+
+ if (ldapcfg.getBoolean(IPublisherProcessor.PROP_ENABLE)) {
+ ICertAuthority authority = (ICertAuthority) mProcessor.getAuthority();
+
+ if (!(authority instanceof ICertificateAuthority))
+ return;
+ ICertificateAuthority ca = (ICertificateAuthority) authority;
+
+ // publish ca cert
+ try {
+ mProcessor.publishCACert(ca.getCACert());
+ CMS.debug("PublisherAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_PUB_CA_CERT"));
+ params.put("publishCA",
+ "CA certificate is published.");
+ } catch (Exception ex) {
+ // exception not thrown - not seen as a fatal error.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_NO_PUB_CA_CERT", ex.toString()));
+ params.put("publishCA",
+ "Failed to publish CA certificate.");
+ int index = ex.toString().indexOf("Failed to create CA");
+
+ if (index > -1) {
+ params.put("createError",
+ ex.toString().substring(index));
+ }
+ mProcessor.shutdown();
+ // Do you want to enable LDAP publishing anyway
+ params.put(Constants.PR_SAVE_NOT,
+ "\n \nIf the problem is not fixed then " +
+ "the CA certificate won't be published.\n" +
+ "Do you want to enable LDAP publishing anyway?");
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+
+ }
+ // publish crl
+ try {
+ CMS.debug("PublisherAdminServlet: about to update CRL");
+ ca.publishCRLNow();
+ CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_PUB_CRL"));
+ params.put("publishCRL",
+ "CRL is published.");
+ } catch (Exception ex) {
+ // exception not thrown - not seen as a fatal error.
+ log(ILogger.LL_FAILURE,
+ "Could not publish crl " + ex.toString());
+ params.put("publishCRL",
+ "Failed to publish CRL.");
+ mProcessor.shutdown();
+ // Do you want to enable LDAP publishing anyway
+ params.put(Constants.PR_SAVE_NOT,
+ "\n \nIf the problem is not fixed then " +
+ "the CRL won't be published.\n" +
+ "Do you want to enable LDAP publishing anyway?");
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+ }
+ commit(true);
+ params.put(Constants.PR_SAVE_OK,
+ "\n \nConfiguration changes are now committed.");
+ params.put("restarted", "Publishing is restarted.");
+ } else {
+ commit(true);
+ params.put(Constants.PR_SAVE_OK,
+ "\n \nConfiguration changes are now committed.");
+ params.put("stopped",
+ "Publishing is stopped.");
+ }
+
+ //XXX See if we can dynamically in B2
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private synchronized void addMapperPlugin(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // is the manager id unique?
+ if (mProcessor.getMapperPlugins().containsKey(id)) {
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_PLUGIN_ID", id))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ String classPath = req.getParameter(Constants.PR_MAPPER_CLASS);
+
+ if (classPath == null) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NULL_CLASS"), null, resp);
+ return;
+ }
+
+ IConfigStore destStore = null;
+
+ destStore = mConfig.getSubStore(mAuth.getId() + ".publish.mapper");
+ IConfigStore instancesConfig = destStore.getSubStore("impl");
+
+ // Does the class exist?
+ Class<?> newImpl = null;
+
+ try {
+ newImpl = Class.forName(classPath);
+ } catch (ClassNotFoundException e) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NO_CLASS"), null, resp);
+ return;
+ } catch (IllegalArgumentException e) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NO_CLASS"), null, resp);
+ return;
+ }
+
+ // is the class an ILdapMapper?
+ try {
+ if (ILdapMapper.class.isAssignableFrom(newImpl) == false) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_CLASS", classPath), null,
+ resp);
+ return;
+ }
+ } catch (NullPointerException e) { // unlikely, only if newImpl null.
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_CLASS", classPath), null, resp);
+ return;
+ }
+
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ substore.put(Constants.PR_MAPPER_CLASS, classPath);
+
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // add mapper to registry.
+ MapperPlugin plugin = new MapperPlugin(id, classPath);
+
+ mProcessor.getMapperPlugins().put(id, plugin);
+ mProcessor.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_MAPPER_ADDED", ""));
+
+ NameValuePairs params = new NameValuePairs();
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private boolean isValidID(String id) {
+ if (id == null)
+ return false;
+ for (int i = 0; i < id.length(); i++) {
+ if (!Character.isLetterOrDigit(id.charAt(i)))
+ return false;
+ }
+ return true;
+ }
+
+ private synchronized void addMapperInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ if (!isValidID(id)) {
+ sendResponse(ERROR, "Invalid ID '" + id + "'",
+ null, resp);
+ return;
+ }
+
+ if (mProcessor.getMapperInsts().containsKey(id)) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_INST_ID", id),
+ null, resp);
+ return;
+ }
+
+ // get required parameters
+ String implname = req.getParameter(
+ Constants.PR_MAPPER_IMPL_NAME);
+
+ if (implname == null) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ADD_MISSING_PARAMS"), null, resp);
+ return;
+ }
+
+ // check if implementation exists.
+ MapperPlugin plugin =
+ mProcessor.getMapperPlugins().get(
+ implname);
+
+ if (plugin == null) {
+ sendResponse(
+ ERROR,
+ new EMapperPluginNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_MAPPER_PLUGIN_NOT_FOUND",
+ implname)).toString(),
+ null, resp);
+ return;
+ }
+
+ Vector<String> configParams = mProcessor.getMapperDefaultParams(implname);
+
+ IConfigStore destStore = mConfig.getSubStore(mAuth.getId() + ".publish.mapper");
+ IConfigStore instancesConfig = destStore.getSubStore("instance");
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+ String val = req.getParameter(kv.substring(0, index));
+
+ if (val == null) {
+ substore.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ } else {
+ substore.put(kv.substring(0, index),
+ val);
+ }
+ }
+ }
+ substore.put("pluginName", implname);
+
+ // Instantiate an object for this implementation
+ String className = plugin.getClassPath();
+ ILdapMapper mapperInst = null;
+
+ try {
+ mapperInst = (ILdapMapper) Class.forName(className).newInstance();
+ } catch (ClassNotFoundException e) {
+ // cleanup
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (InstantiationException e) {
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (IllegalAccessException e) {
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ // initialize the mapper
+ try {
+ mapperInst.init(substore);
+ } catch (EBaseException e) {
+ // don't commit in this case and cleanup the new substore.
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ } catch (Throwable e) {
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR, e.toString(), null, resp);
+ return;
+ }
+
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // clean up.
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // inited and commited ok. now add mapper instance to list.
+ mProcessor.getMapperInsts().put(id, new MapperProxy(true, mapperInst));
+
+ mProcessor.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_MAPPER_INST_ADDED", id));
+
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_MAPPER_IMPL_NAME, implname);
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void listMapperPlugins(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = mProcessor.getMapperPlugins().keys();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+ MapperPlugin value = mProcessor.getMapperPlugins().get(name);
+ // get Description
+ String c = value.getClassPath();
+ String desc = "unknown";
+
+ try {
+ ILdapMapper lp = (ILdapMapper)
+ Class.forName(c).newInstance();
+
+ desc = lp.getDescription();
+ } catch (Exception exp) {
+ sendResponse(ERROR, exp.toString(), null,
+ resp);
+ return;
+ }
+ params.put(name, value.getClassPath() + "," + desc);
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ public String getMapperPluginName(ILdapMapper mapper) {
+ IConfigStore cs = mapper.getConfigStore();
+
+ try {
+ return cs.getString("pluginName", "");
+ } catch (EBaseException e) {
+ return "";
+ }
+ }
+
+ private synchronized void listMapperInsts(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = mProcessor.getMapperInsts().keys();
+
+ for (; e.hasMoreElements();) {
+ String name = e.nextElement();
+ ILdapMapper value = mProcessor.getMapperInstance(name);
+
+ params.put(name, getMapperPluginName(value) + ";visible");
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void delMapperInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // does a`mapper instance exist?
+ if (mProcessor.getMapperInsts().containsKey(id) == false) {
+ sendResponse(
+ ERROR,
+ new EMapperNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_MAPPER_NOT_FOUND", id)).toString(),
+ null, resp);
+ return;
+ }
+
+ // only remove from memory
+ // cannot shutdown because we don't keep track of whether it's
+ // being used.
+ mProcessor.getMapperInsts().remove(id);
+
+ // remove the configuration.
+ IConfigStore destStore =
+ mConfig.getSubStore(
+ mAuth.getId() + ".publish.mapper");
+ IConfigStore instancesConfig = destStore.getSubStore("instance");
+
+ instancesConfig.removeSubStore(id);
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void delMapperPlugin(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ if (mProcessor.getMapperPlugins().containsKey(id) == false) {
+ sendResponse(
+ ERROR,
+ new EMapperPluginNotFound(CMS
+ .getUserMessage(getLocale(req), "CMS_LDAP_MAPPER_PLUGIN_NOT_FOUND", id)).toString(),
+ null, resp);
+ return;
+ }
+
+ // first check if any instances from this mapper
+ // DON'T remove mapper if any instance
+ for (Enumeration<String> e = mProcessor.getMapperInsts().keys(); e.hasMoreElements();) {
+ String name = e.nextElement();
+ ILdapMapper mapper = mProcessor.getMapperInstance(name);
+
+ if (id.equals(getMapperPluginName(mapper))) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_IN_USE"), null, resp);
+ return;
+ }
+ }
+
+ // then delete this mapper
+ mProcessor.getMapperPlugins().remove(id);
+
+ IConfigStore destStore =
+ mConfig.getSubStore(
+ mAuth.getId() + ".publish.mapper");
+ IConfigStore instancesConfig =
+ destStore.getSubStore("impl");
+
+ instancesConfig.removeSubStore(id);
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void getMapperConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+
+ String implname = req.getParameter(Constants.RS_ID);
+
+ if (implname == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ Vector<String> configParams = mProcessor.getMapperDefaultParams(implname);
+ NameValuePairs params = new NameValuePairs();
+
+ // implName is always required so always send it.
+ params.put(Constants.PR_MAPPER_IMPL_NAME, "");
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+
+ params.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ }
+ }
+ sendResponse(0, null, params, resp);
+ return;
+ }
+
+ private synchronized void getMapperInstConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // does mapper instance exist?
+ if (mProcessor.getMapperInsts().containsKey(id) == false) {
+ sendResponse(
+ ERROR,
+ new EMapperNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_MAPPER_NOT_FOUND", id)).toString(),
+ null, resp);
+ return;
+ }
+
+ ILdapMapper mapperInst = mProcessor.getMapperInstance(id);
+ Vector<String> configParams = mapperInst.getInstanceParams();
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_MAPPER_IMPL_NAME,
+ getMapperPluginName(mapperInst));
+ // implName is always required so always send it.
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+
+ params.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ }
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void modMapperInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // Does the manager instance exist?
+ if (!mProcessor.getMapperInsts().containsKey(id)) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_INST_ID", id),
+ null, resp);
+ return;
+ }
+
+ // get new implementation (same or different.)
+ String implname = req.getParameter(Constants.PR_MAPPER_IMPL_NAME);
+
+ if (implname == null) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ADD_MISSING_PARAMS"), null, resp);
+ return;
+ }
+ // get plugin for implementation
+ MapperPlugin plugin =
+ mProcessor.getMapperPlugins().get(implname);
+
+ if (plugin == null) {
+ sendResponse(
+ ERROR,
+ new EMapperPluginNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_MAPPER_PLUGIN_NOT_FOUND",
+ implname)).toString(),
+ null, resp);
+ return;
+ }
+
+ // save old instance substore params in case new one fails.
+
+ ILdapMapper oldinst =
+ mProcessor.getMapperInstance(id);
+ Vector<String> oldConfigParms = oldinst.getInstanceParams();
+ NameValuePairs saveParams = new NameValuePairs();
+
+ // implName is always required so always include it it.
+ saveParams.put("pluginName", implname);
+ if (oldConfigParms != null) {
+ for (int i = 0; i < oldConfigParms.size(); i++) {
+ String kv = oldConfigParms.elementAt(i);
+ int index = kv.indexOf('=');
+
+ saveParams.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ }
+ }
+
+ // on to the new instance.
+
+ // remove old substore.
+
+ IConfigStore destStore =
+ mConfig.getSubStore(mAuth.getId() +
+ ".publish.mapper");
+ IConfigStore instancesConfig = destStore.getSubStore("instance");
+
+ // create new substore.
+
+ Vector<String> configParams = mProcessor.getMapperInstanceParams(id);
+
+ instancesConfig.removeSubStore(id);
+
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ substore.put("pluginName", implname);
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+ String key = kv.substring(0, index);
+ String val = req.getParameter(key);
+
+ if (val != null) {
+ substore.put(key, val);
+ }
+ }
+ }
+
+ // Instantiate an object for new implementation
+
+ String className = plugin.getClassPath();
+ ILdapMapper newMgrInst = null;
+
+ try {
+ newMgrInst = (ILdapMapper)
+ Class.forName(className).newInstance();
+ } catch (ClassNotFoundException e) {
+ // cleanup
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (InstantiationException e) {
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (IllegalAccessException e) {
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ }
+ // initialize the mapper
+
+ try {
+ newMgrInst.init(substore);
+ } catch (EBaseException e) {
+ // don't commit in this case and cleanup the new substore.
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR, e.toString(getLocale(req)), null,
+ resp);
+ return;
+ } catch (Throwable e) {
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR, e.toString(), null,
+ resp);
+ return;
+ }
+
+ // initialized ok. commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // clean up.
+ restore(instancesConfig, id, saveParams);
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // commited ok. replace instance.
+
+ mProcessor.getMapperInsts().put(id, new MapperProxy(true, newMgrInst));
+
+ mProcessor.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_MAPPER_REPLACED", id));
+ NameValuePairs params = new NameValuePairs();
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void addRulePlugin(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // is the rule id unique?
+ if (mProcessor.getRulePlugins().containsKey(id)) {
+ sendResponse(
+ ERROR,
+ new ELdapException(CMS.getUserMessage("CMS_LDAP_SRVLT_ILL_PLUGIN_ID", id)).toString(getLocale(req)),
+ null, resp);
+ return;
+ }
+
+ String classPath = req.getParameter(Constants.PR_RULE_CLASS);
+
+ if (classPath == null) {
+ sendResponse(ERROR, CMS.getUserMessage("CMS_LDAP_SRVLT_NULL_CLASS"), null, resp);
+ return;
+ }
+
+ IConfigStore destStore = null;
+
+ destStore = mConfig.getSubStore(
+ mAuth.getId() + ".publish.rule");
+ IConfigStore instancesConfig = destStore.getSubStore("impl");
+
+ // Does the class exist?
+ Class<?> newImpl = null;
+
+ try {
+ newImpl = Class.forName(classPath);
+ } catch (ClassNotFoundException e) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NO_CLASS"), null, resp);
+ return;
+ } catch (IllegalArgumentException e) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NO_CLASS"), null, resp);
+ return;
+ }
+
+ // is the class an ILdapRule?
+ try {
+ if (ILdapRule.class.isAssignableFrom(newImpl) == false) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_CLASS", classPath), null,
+ resp);
+ return;
+ }
+ } catch (NullPointerException e) { // unlikely, only if newImpl null.
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_CLASS", classPath), null, resp);
+ return;
+ }
+
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ substore.put(Constants.PR_RULE_CLASS, classPath);
+
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // add rule to registry.
+ RulePlugin plugin = new RulePlugin(id, classPath);
+
+ mProcessor.getRulePlugins().put(id, plugin);
+ mProcessor.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_RULE_PLUG_ADDED", id));
+
+ NameValuePairs params = new NameValuePairs();
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void addRuleInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+ if (!isValidID(id)) {
+ sendResponse(ERROR, "Invalid ID '" + id + "'",
+ null, resp);
+ return;
+ }
+
+ if (mProcessor.getRuleInsts().containsKey(id)) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_INST_ID", id),
+ null, resp);
+ return;
+ }
+
+ // get required parameters
+ String implname = req.getParameter(
+ Constants.PR_RULE_IMPL_NAME);
+
+ if (implname == null) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ADD_MISSING_PARAMS"), null, resp);
+ return;
+ }
+
+ // check if implementation exists.
+ RulePlugin plugin =
+ mProcessor.getRulePlugins().get(implname);
+
+ if (plugin == null) {
+ sendResponse(
+ ERROR,
+ new EPublisherPluginNotFound(CMS.getUserMessage(getLocale(req),
+ "CMS_LDAP_PUBLISHER_PLUGIN_NOT_FOUND", implname)).toString(),
+ null, resp);
+ return;
+ }
+
+ Vector<String> configParams = mProcessor.getRuleDefaultParams(implname);
+
+ IConfigStore destStore =
+ mConfig.getSubStore(mAuth.getId()
+ + ".publish.rule");
+ IConfigStore instancesConfig =
+ destStore.getSubStore("instance");
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+ String val = req.getParameter(kv.substring(0, index));
+
+ if (val == null) {
+ substore.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ } else {
+ if (val.equals(NOMAPPER))
+ val = "";
+ substore.put(kv.substring(0, index),
+ val);
+ }
+ }
+ }
+ substore.put("pluginName", implname);
+
+ // Instantiate an object for this implementation
+ String className = plugin.getClassPath();
+ ILdapRule ruleInst = null;
+
+ try {
+ ruleInst = (ILdapRule) Class.forName(className).newInstance();
+ } catch (ClassNotFoundException e) {
+ // cleanup
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (InstantiationException e) {
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (IllegalAccessException e) {
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ // initialize the rule
+ try {
+ ruleInst.init(mProcessor, substore);
+ ruleInst.setInstanceName(id);
+ } catch (EBaseException e) {
+ // don't commit in this case and cleanup the new substore.
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ } catch (Throwable e) {
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR, e.toString(), null, resp);
+ return;
+ }
+
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // clean up.
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+ // inited and commited ok. now add manager instance to list.
+ mProcessor.getRuleInsts().put(id, ruleInst);
+
+ mProcessor.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_RULE_INST_ADDED", id));
+
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_RULE_IMPL_NAME, implname);
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void listRulePlugins(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = mProcessor.getRulePlugins().keys();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+ RulePlugin value = mProcessor.getRulePlugins().get(name);
+ // get Description
+ String c = value.getClassPath();
+ String desc = "unknown";
+
+ try {
+ ILdapRule lp = (ILdapRule)
+ Class.forName(c).newInstance();
+
+ desc = lp.getDescription();
+ } catch (Exception exp) {
+ }
+ params.put(name, value.getClassPath() + "," + desc);
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void listRuleInsts(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = mProcessor.getRuleInsts().keys();
+
+ for (; e.hasMoreElements();) {
+ String name = e.nextElement();
+ ILdapRule value = mProcessor.getRuleInsts().get(name);
+ String enabled = value.enabled() ? "enabled" : "disabled";
+
+ params.put(name, value.getInstanceName() + ";visible;" + enabled);
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ public String getRulePluginName(ILdapRule rule) {
+ IConfigStore cs = rule.getConfigStore();
+
+ try {
+ return cs.getString("pluginName", "");
+ } catch (EBaseException e) {
+ return "";
+ }
+ }
+
+ private synchronized void delRulePlugin(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // does rule exist?
+ if (mProcessor.getRulePlugins().containsKey(id) == false) {
+ sendResponse(ERROR,
+ new ERulePluginNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_RULE_PLUGIN_NOT_FOUND", id))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ // first check if any instances from this rule
+ // DON'T remove rule if any instance
+ for (Enumeration<ILdapRule> e = mProcessor.getRuleInsts().elements(); e.hasMoreElements();) {
+ ILdapRule rule = e.nextElement();
+
+ if (id.equals(getRulePluginName(rule))) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_IN_USE"), null, resp);
+ return;
+ }
+ }
+
+ // then delete this rule
+ mProcessor.getRulePlugins().remove(id);
+
+ IConfigStore destStore =
+ mConfig.getSubStore(
+ mAuth.getId() + ".rule");
+ IConfigStore instancesConfig = destStore.getSubStore("impl");
+
+ instancesConfig.removeSubStore(id);
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void delRuleInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // prevent deletion of admin and agent.
+
+ // does rule instance exist?
+ if (mProcessor.getRuleInsts().containsKey(id) == false) {
+ sendResponse(ERROR,
+ new ERuleNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_RULE_NOT_FOUND", id)).toString(),
+ null, resp);
+ return;
+ }
+
+ // only remove from memory
+ // cannot shutdown because we don't keep track of whether it's
+ // being used.
+ mProcessor.getRuleInsts().remove(id);
+
+ // remove the configuration.
+ IConfigStore destStore =
+ mConfig.getSubStore(
+ mAuth.getId() + ".publish.rule");
+ IConfigStore instancesConfig = destStore.getSubStore("instance");
+
+ instancesConfig.removeSubStore(id);
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void getRuleConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+ String implname = req.getParameter(Constants.RS_ID);
+
+ if (implname == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ Vector<String> configParams = mProcessor.getRuleDefaultParams(implname);
+ NameValuePairs params = new NameValuePairs();
+
+ // implName is always required so always send it.
+ params.put(Constants.PR_RULE_IMPL_NAME, "");
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+
+ params.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ }
+ }
+ sendResponse(0, null, params, resp);
+ return;
+ }
+
+ private synchronized void getRuleInstConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // does rule instance exist?
+ if (mProcessor.getRuleInsts().containsKey(id) == false) {
+ sendResponse(ERROR,
+ new ERuleNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_RULE_NOT_FOUND", id)).toString(),
+ null, resp);
+ return;
+ }
+
+ ILdapRule ruleInst = mProcessor.getRuleInsts().get(id);
+ Vector<String> configParams = ruleInst.getInstanceParams();
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_RULE_IMPL_NAME,
+ getRulePluginName(ruleInst));
+ // implName is always required so always send it.
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+
+ params.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ }
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void modRuleInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // Does the manager instance exist?
+ if (!mProcessor.getRuleInsts().containsKey(id)) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_INST_ID", id),
+ null, resp);
+ return;
+ }
+
+ // get new implementation (same or different.)
+ String implname = req.getParameter(Constants.PR_RULE_IMPL_NAME);
+
+ if (implname == null) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ADD_MISSING_PARAMS"), null, resp);
+ return;
+ }
+
+ // get plugin for implementation
+ RulePlugin plugin =
+ mProcessor.getRulePlugins().get(implname);
+
+ if (plugin == null) {
+ sendResponse(ERROR,
+ //new ERulePluginNotFound(implname).toString(getLocale(req)),
+ "",
+ null, resp);
+ return;
+ }
+
+ // save old instance substore params in case new one fails.
+
+ ILdapRule oldinst =
+ mProcessor.getRuleInsts().get(id);
+ Vector<String> oldConfigParms = oldinst.getInstanceParams();
+ NameValuePairs saveParams = new NameValuePairs();
+
+ // implName is always required so always include it it.
+ saveParams.put("pluginName", implname);
+ if (oldConfigParms != null) {
+ for (int i = 0; i < oldConfigParms.size(); i++) {
+ String kv = oldConfigParms.elementAt(i);
+ int index = kv.indexOf('=');
+
+ saveParams.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ }
+ }
+
+ // on to the new instance.
+
+ // remove old substore.
+
+ IConfigStore destStore =
+ mConfig.getSubStore(
+ mAuth.getId() + ".publish.rule");
+ IConfigStore instancesConfig = destStore.getSubStore("instance");
+
+ // create new substore.
+
+ Vector<String> configParams = mProcessor.getRuleDefaultParams(implname);
+
+ instancesConfig.removeSubStore(id);
+
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ substore.put("pluginName", implname);
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+ String key = kv.substring(0, index);
+ String val = req.getParameter(key);
+
+ if (val == null) {
+ substore.put(key,
+ kv.substring(index + 1));
+ } else {
+ if (val.equals(NOMAPPER))
+ val = "";
+ substore.put(key, val);
+ }
+ }
+ }
+
+ // Instantiate an object for new implementation
+
+ String className = plugin.getClassPath();
+ ILdapRule newRuleInst = null;
+
+ try {
+ newRuleInst = (ILdapRule) Class.forName(className).newInstance();
+ } catch (ClassNotFoundException e) {
+ // cleanup
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (InstantiationException e) {
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (IllegalAccessException e) {
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ // initialize the rule
+
+ try {
+ newRuleInst.init(mProcessor, substore);
+ } catch (EBaseException e) {
+ // don't commit in this case and cleanup the new substore.
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ } catch (Throwable e) {
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR, e.toString(), null, resp);
+ return;
+ }
+
+ // initialized ok. commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // clean up.
+ restore(instancesConfig, id, saveParams);
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // commited ok. replace instance.
+
+ mProcessor.getRuleInsts().put(id, newRuleInst);
+
+ mProcessor.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_RULE_INST_REP", id));
+ NameValuePairs params = new NameValuePairs();
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void addPublisherPlugin(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // is the manager id unique?
+ if (mProcessor.getPublisherPlugins().containsKey(id)) {
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_PLUGIN_ID", id))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ String classPath = req.getParameter(Constants.PR_PUBLISHER_CLASS);
+
+ if (classPath == null) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NULL_CLASS"), null, resp);
+ return;
+ }
+
+ IConfigStore destStore = null;
+
+ destStore = mConfig.getSubStore(
+ mAuth.getId() + ".publish.publisher");
+ IConfigStore instancesConfig = destStore.getSubStore("impl");
+
+ // Does the class exist?
+ Class<?> newImpl = null;
+
+ try {
+ newImpl = Class.forName(classPath);
+ } catch (ClassNotFoundException e) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NO_CLASS"), null, resp);
+ return;
+ } catch (IllegalArgumentException e) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NO_CLASS"), null, resp);
+ return;
+ }
+
+ // is the class an ILdapPublisher?
+ try {
+ if (ILdapPublisher.class.isAssignableFrom(newImpl) == false) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_CLASS", classPath), null,
+ resp);
+ return;
+ }
+ } catch (NullPointerException e) { // unlikely, only if newImpl null.
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_CLASS", classPath), null, resp);
+ return;
+ }
+
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ substore.put(Constants.PR_PUBLISHER_CLASS, classPath);
+
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // add publisher to registry.
+ PublisherPlugin plugin = new PublisherPlugin(id, classPath);
+
+ mProcessor.getPublisherPlugins().put(id, plugin);
+ mProcessor.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_PUB_PLUG_ADDED", id));
+
+ NameValuePairs params = new NameValuePairs();
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void addPublisherInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ if (!isValidID(id)) {
+ sendResponse(ERROR, "Invalid ID '" + id + "'",
+ null, resp);
+ return;
+ }
+
+ if (mProcessor.getPublisherInsts().containsKey(id)) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_INST_ID", id),
+ null, resp);
+ return;
+ }
+
+ // get required parameters
+ String implname = req.getParameter(
+ Constants.PR_PUBLISHER_IMPL_NAME);
+
+ if (implname == null) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ADD_MISSING_PARAMS"), null, resp);
+ return;
+ }
+
+ // check if implementation exists.
+ PublisherPlugin plugin =
+ mProcessor.getPublisherPlugins().get(implname);
+
+ if (plugin == null) {
+ sendResponse(
+ ERROR,
+ new EPublisherPluginNotFound(CMS.getUserMessage(getLocale(req),
+ "CMS_LDAP_PUBLISHER_PLUGIN_NOT_FOUND", implname)).toString(),
+ null, resp);
+ return;
+ }
+
+ Vector<String> configParams = mProcessor.getPublisherDefaultParams(implname);
+
+ IConfigStore destStore =
+ mConfig.getSubStore(mAuth.getId() + ".publish.publisher");
+ IConfigStore instancesConfig = destStore.getSubStore("instance");
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+ String val = null;
+
+ if (index == -1) {
+ val = req.getParameter(kv);
+ } else {
+ val = req.getParameter(kv.substring(0, index));
+ }
+ if (val == null) {
+ if (index == -1) {
+ substore.put(kv, "");
+ } else {
+ substore.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ }
+ } else {
+ if (index == -1) {
+ substore.put(kv, val);
+ } else {
+ substore.put(kv.substring(0, index),
+ val);
+ }
+ }
+ }
+ }
+ substore.put("pluginName", implname);
+
+ // Instantiate an object for this implementation
+ String className = plugin.getClassPath();
+ ILdapPublisher publisherInst = null;
+
+ try {
+ publisherInst = (ILdapPublisher) Class.forName(className).newInstance();
+ } catch (ClassNotFoundException e) {
+ // cleanup
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (InstantiationException e) {
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (IllegalAccessException e) {
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ // initialize the publisher
+ try {
+ publisherInst.init(substore);
+ } catch (EBaseException e) {
+ // don't commit in this case and cleanup the new substore.
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ } catch (Throwable e) {
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR, e.toString(), null, resp);
+ return;
+ }
+
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // clean up.
+ instancesConfig.removeSubStore(id);
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // inited and commited ok. now add manager instance to list.
+ mProcessor.getPublisherInsts().put(id, new PublisherProxy(true, publisherInst));
+
+ mProcessor.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_PUB_INST_ADDED", id));
+
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_PUBLISHER_IMPL_NAME, implname);
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void listPublisherPlugins(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = mProcessor.getPublisherPlugins().keys();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+ PublisherPlugin value = mProcessor.getPublisherPlugins().get(name);
+ // get Description
+ String c = value.getClassPath();
+ String desc = "unknown";
+
+ try {
+ ILdapPublisher lp = (ILdapPublisher)
+ Class.forName(c).newInstance();
+
+ desc = lp.getDescription();
+ } catch (Exception exp) {
+ }
+ params.put(name, value.getClassPath() + "," + desc);
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ public String getPublisherPluginName(ILdapPublisher pub) {
+ IConfigStore cs = pub.getConfigStore();
+
+ try {
+ return cs.getString("pluginName", "");
+ } catch (EBaseException e) {
+ return "";
+ }
+ }
+
+ private synchronized void listPublisherInsts(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = mProcessor.getPublisherInsts().keys();
+
+ for (; e.hasMoreElements();) {
+ String name = e.nextElement();
+ ILdapPublisher value = mProcessor.getPublisherInstance(name);
+
+ if (value == null)
+ continue;
+ params.put(name, getPublisherPluginName(value) + ";visible");
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void delPublisherPlugin(HttpServletRequest req,
+ HttpServletResponse resp, String scope) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // does publisher exist?
+ if (mProcessor.getPublisherPlugins().containsKey(id) == false) {
+ sendResponse(
+ ERROR,
+ new EPublisherPluginNotFound(CMS.getUserMessage(getLocale(req),
+ "CMS_LDAP_PUBLISHER_PLUGIN_NOT_FOUND", id)).toString(),
+ null, resp);
+ return;
+ }
+
+ // first check if any instances from this publisher
+ // DON'T remove publisher if any instance
+ for (Enumeration<String> e = mProcessor.getPublisherInsts().keys(); e.hasMoreElements();) {
+ String name = e.nextElement();
+ ILdapPublisher publisher =
+ mProcessor.getPublisherInstance(name);
+
+ if (id.equals(getPublisherPluginName(publisher))) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_IN_USE"), null, resp);
+ return;
+ }
+ }
+
+ // then delete this publisher
+ mProcessor.getPublisherPlugins().remove(id);
+
+ IConfigStore destStore =
+ mConfig.getSubStore(mAuth.getId() + ".publish.publisher");
+ IConfigStore instancesConfig = destStore.getSubStore("impl");
+
+ instancesConfig.removeSubStore(id);
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ private synchronized void delPublisherInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // prevent deletion of admin and agent.
+
+ // does publisher instance exist?
+ if (mProcessor.getPublisherInsts().containsKey(id) == false) {
+ sendResponse(ERROR,
+ new EPublisherNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_PUBLISHER_NOT_FOUND", id))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ // only remove from memory
+ // cannot shutdown because we don't keep track of whether it's
+ // being used.
+ mProcessor.getPublisherInsts().remove(id);
+
+ // remove the configuration.
+ IConfigStore destStore =
+ mConfig.getSubStore(mAuth.getId() + ".publish.publisher");
+ IConfigStore instancesConfig = destStore.getSubStore("instance");
+
+ instancesConfig.removeSubStore(id);
+ // commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ /**
+ * used for getting the required configuration parameters (with
+ * possible default values) for a particular plugin
+ * implementation name specified in the RS_ID. Actually, there is
+ * no logic in here to set any default value here...there's no
+ * default value for any parameter in this publishing subsystem
+ * at this point. Later, if we do have one (or some), it can be
+ * added. The interface remains the same.
+ */
+ private synchronized void getConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException, EBaseException {
+
+ String implname = req.getParameter(Constants.RS_ID);
+
+ if (implname == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ Vector<String> configParams = mProcessor.getPublisherDefaultParams(implname);
+ NameValuePairs params = new NameValuePairs();
+
+ // implName is always required so always send it.
+ params.put(Constants.PR_PUBLISHER_IMPL_NAME, "");
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+
+ if (index == -1) {
+ params.put(kv, "");
+ } else {
+ params.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ }
+ }
+ }
+ sendResponse(0, null, params, resp);
+ return;
+ }
+
+ private synchronized void getInstConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // does publisher instance exist?
+ if (mProcessor.getPublisherInsts().containsKey(id) == false) {
+ sendResponse(ERROR,
+ new EPublisherNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_PUBLISHER_NOT_FOUND", id))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ ILdapPublisher publisherInst = mProcessor.getPublisherInstance(id);
+ Vector<String> configParams = publisherInst.getInstanceParams();
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_PUBLISHER_IMPL_NAME,
+ getPublisherPluginName(publisherInst));
+ // implName is always required so always send it.
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+
+ params.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ }
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ /**
+ * Modify publisher instance.
+ * This will actually create a new instance with new configuration
+ * parameters and replace the old instance, if the new instance
+ * created and initialized successfully.
+ * The old instance is left running. so this is very expensive.
+ * Restart of server recommended.
+ */
+ private synchronized void modPublisherInst(HttpServletRequest req,
+ HttpServletResponse resp, String scope)
+ throws ServletException, IOException, EBaseException {
+
+ // expensive operation.
+
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ //System.out.println("SRVLT_NULL_RS_ID");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // Does the manager instance exist?
+ if (!mProcessor.getPublisherInsts().containsKey(id)) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_INST_ID", id),
+ null, resp);
+ return;
+ }
+
+ // get new implementation (same or different.)
+ String implname = req.getParameter(Constants.PR_PUBLISHER_IMPL_NAME);
+
+ if (implname == null) {
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ADD_MISSING_PARAMS"), null, resp);
+ return;
+ }
+
+ // get plugin for implementation
+ PublisherPlugin plugin =
+ mProcessor.getPublisherPlugins().get(implname);
+
+ if (plugin == null) {
+ sendResponse(
+ ERROR,
+ new EPublisherPluginNotFound(CMS.getUserMessage(getLocale(req),
+ "CMS_LDAP_PUBLISHER_PLUGIN_NOT_FOUND", implname)).toString(),
+ null, resp);
+ return;
+ }
+
+ // save old instance substore params in case new one fails.
+
+ ILdapPublisher oldinst = mProcessor.getPublisherInstance(id);
+ Vector<String> oldConfigParms = oldinst.getInstanceParams();
+ NameValuePairs saveParams = new NameValuePairs();
+ String pubType = "";
+
+ // implName is always required so always include it it.
+ saveParams.put("pluginName", implname);
+ if (oldConfigParms != null) {
+ for (int i = 0; i < oldConfigParms.size(); i++) {
+ String kv = oldConfigParms.elementAt(i);
+ int index = kv.indexOf('=');
+ if (index > -1) {
+ if (kv.substring(0, index).equalsIgnoreCase("caObjectClass")) {
+ pubType = "cacert";
+ } else if (kv.substring(0, index).equalsIgnoreCase("crlObjectClass")) {
+ pubType = "crl";
+ }
+
+ saveParams.put(kv.substring(0, index),
+ kv.substring(index + 1));
+ }
+ }
+ }
+
+ // on to the new instance.
+
+ // remove old substore.
+
+ IConfigStore destStore =
+ mConfig.getSubStore(mAuth.getId() + ".publish.publisher");
+ IConfigStore instancesConfig = destStore.getSubStore("instance");
+
+ // get objects added and deleted
+ if (pubType.equals("cacert")) {
+ saveParams.put("caObjectClassAdded", instancesConfig.getString(id + ".caObjectClassAdded", ""));
+ saveParams.put("caObjectClassDeleted", instancesConfig.getString(id + ".caObjectClassDeleted", ""));
+ } else if (pubType.equals("crl")) {
+ saveParams.put("crlObjectClassAdded", instancesConfig.getString(id + ".crlObjectClassAdded", ""));
+ saveParams.put("crlObjectClassDeleted", instancesConfig.getString(id + ".crlObjectClassDeleted", ""));
+ }
+
+ // create new substore.
+
+ Vector<String> configParams = mProcessor.getPublisherInstanceParams(id);
+
+ instancesConfig.removeSubStore(id);
+
+ IConfigStore substore = instancesConfig.makeSubStore(id);
+
+ substore.put("pluginName", implname);
+ if (configParams != null) {
+ for (int i = 0; i < configParams.size(); i++) {
+ String kv = configParams.elementAt(i);
+ int index = kv.indexOf('=');
+ String key = kv.substring(0, index);
+ String val = req.getParameter(key);
+
+ if (val != null) {
+ substore.put(key, val);
+ }
+ }
+ }
+
+ // process any changes to the ldap object class definitions
+ if (pubType.equals("cacert")) {
+ processChangedOC(saveParams, substore, "caObjectClass");
+ substore.put("pubtype", "cacert");
+ }
+
+ if (pubType.equals("crl")) {
+ processChangedOC(saveParams, substore, "crlObjectClass");
+ substore.put("pubtype", "crl");
+ }
+
+ // Instantiate an object for new implementation
+
+ String className = plugin.getClassPath();
+ ILdapPublisher newMgrInst = null;
+
+ try {
+ newMgrInst = (ILdapPublisher) Class.forName(className).newInstance();
+ } catch (ClassNotFoundException e) {
+ // cleanup
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (InstantiationException e) {
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ } catch (IllegalAccessException e) {
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR,
+ new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className))
+ .toString(),
+ null, resp);
+ return;
+ }
+
+ // initialize the publisher
+
+ try {
+ newMgrInst.init(substore);
+ } catch (EBaseException e) {
+ // don't commit in this case and cleanup the new substore.
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
+ return;
+ } catch (Throwable e) {
+ restore(instancesConfig, id, saveParams);
+ sendResponse(ERROR, e.toString(), null, resp);
+ return;
+ }
+
+ // initialized ok. commiting
+ try {
+ mConfig.commit(true);
+ } catch (EBaseException e) {
+ // clean up.
+ restore(instancesConfig, id, saveParams);
+ //System.out.println("SRVLT_FAIL_COMMIT");
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // commited ok. replace instance.
+
+ mProcessor.getPublisherInsts().put(id, new PublisherProxy(true, newMgrInst));
+
+ mProcessor.log(ILogger.LL_INFO,
+ CMS.getLogMessage("ADMIN_SRVLT_PUB_INST_REP", id));
+
+ NameValuePairs params = new NameValuePairs();
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ // convenience function - takes list1, list2. Returns what is in list1
+ // but not in list2
+ private String[] getExtras(String[] list1, String[] list2) {
+ Vector<String> extras = new Vector<String>();
+ for (int i = 0; i < list1.length; i++) {
+ boolean match = false;
+ for (int j = 0; j < list2.length; j++) {
+ if ((list1[i].trim()).equalsIgnoreCase(list2[j].trim())) {
+ match = true;
+ break;
+ }
+ }
+ if (!match)
+ extras.add(list1[i].trim());
+ }
+
+ return extras.toArray(new String[extras.size()]);
+ }
+
+ // convenience function - takes list1, list2. Concatenates the two
+ // lists removing duplicates
+ private String[] joinLists(String[] list1, String[] list2) {
+ Vector<String> sum = new Vector<String>();
+ for (int i = 0; i < list1.length; i++) {
+ sum.add(list1[i]);
+ }
+
+ for (int i = 0; i < list2.length; i++) {
+ boolean match = false;
+ for (int j = 0; j < list1.length; j++) {
+ if ((list2[i].trim()).equalsIgnoreCase(list1[j].trim())) {
+ match = true;
+ break;
+ }
+ }
+ if (!match)
+ sum.add(list2[i].trim());
+ }
+
+ return sum.toArray(new String[sum.size()]);
+ }
+
+ // convenience funtion. Takes a string array and delimiter
+ // and returns a String with the concatenation
+ private static String join(String[] s, String delimiter) {
+ if (s.length == 0)
+ return "";
+
+ StringBuffer buffer = new StringBuffer(s[0]);
+ if (s.length > 1) {
+ for (int i = 1; i < s.length; i++) {
+ buffer.append(delimiter + s[i].trim());
+ }
+ }
+ return buffer.toString();
+ }
+
+ private void processChangedOC(NameValuePairs saveParams, IConfigStore newstore, String objName) {
+ String newOC = null, oldOC = null;
+ String oldAdded = null, oldDeleted = null;
+
+ try {
+ newOC = newstore.getString(objName);
+ } catch (Exception e) {
+ }
+
+ oldOC = saveParams.get(objName);
+ oldAdded = saveParams.get(objName + "Added");
+ oldDeleted = saveParams.get(objName + "Deleted");
+
+ if ((oldOC == null) || (newOC == null))
+ return;
+ if (oldOC.equalsIgnoreCase(newOC))
+ return;
+
+ String[] oldList = oldOC.split(",");
+ String[] newList = newOC.split(",");
+ String[] deletedList = getExtras(oldList, newList);
+ String[] addedList = getExtras(newList, oldList);
+
+ // CMS.debug("addedList = " + join(addedList, ","));
+ // CMS.debug("deletedList = " + join(deletedList, ","));
+
+ if ((addedList.length == 0) && (deletedList.length == 0))
+ return; // no changes
+
+ if (oldAdded != null) {
+ // CMS.debug("oldAdded is " + oldAdded);
+ String[] oldAddedList = oldAdded.split(",");
+ addedList = joinLists(addedList, oldAddedList);
+ }
+
+ if (oldDeleted != null) {
+ // CMS.debug("oldDeleted is " + oldDeleted);
+ String[] oldDeletedList = oldDeleted.split(",");
+ deletedList = joinLists(deletedList, oldDeletedList);
+ }
+
+ String[] addedList1 = getExtras(addedList, deletedList);
+ String[] deletedList1 = getExtras(deletedList, addedList);
+
+ //create the final strings and write to config
+ String addedListStr = join(addedList1, ",");
+ String deletedListStr = join(deletedList1, ",");
+
+ CMS.debug("processChangedOC: added list is " + addedListStr);
+ CMS.debug("processChangedOC: deleted list is " + deletedListStr);
+
+ newstore.put(objName + "Added", addedListStr);
+ newstore.put(objName + "Deleted", deletedListStr);
+ }
+
+ // convenience routine.
+ private static void restore(IConfigStore store,
+ String id, NameValuePairs saveParams) {
+ store.removeSubStore(id);
+ IConfigStore rstore = store.makeSubStore(id);
+
+ for (String key : saveParams.keySet()) {
+ String value = saveParams.get(key);
+
+ if (value != null)
+ rstore.put(key, value);
+ }
+ }
+
+ private String dashes(int len) {
+ String dashes = "...................................................";
+
+ if (len <= 0)
+ return "";
+ String new1 = dashes.substring(0, len);
+
+ return new1;
+ }
+
+ /**
+ * logs an entry in the log file.
+ */
+ public void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM,
+ ILogger.S_LDAP, level, "PublishingAdminServlet: " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/RAAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/RAAdminServlet.java
new file mode 100644
index 000000000..763f421fb
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/RAAdminServlet.java
@@ -0,0 +1,575 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequestListener;
+
+/**
+ * A class representings an administration servlet for Registration
+ * Authority. This servlet is responsible to serve RA
+ * administrative operations such as configuration parameter
+ * updates.
+ *
+ * @version $Revision$, $Date$
+ */
+public class RAAdminServlet extends AdminServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8417319111438832435L;
+
+ protected static final String PROP_ENABLED = "enabled";
+
+ /*==========================================================
+ * variables
+ *==========================================================*/
+ private final static String INFO = "RAAdminServlet";
+ private IRegistrationAuthority mRA = null;
+
+ /*==========================================================
+ * constructors
+ *==========================================================*/
+
+ /**
+ * Constructs RA servlet.
+ */
+ public RAAdminServlet() {
+ super();
+ }
+
+ /*==========================================================
+ * public methods
+ *==========================================================*/
+
+ /**
+ * Initializes this servlet.
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ mRA = (IRegistrationAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_RA);
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Serves HTTP request. Each request is authenticated to
+ * the authenticate manager.
+ */
+ public void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+
+ //get all operational flags
+ String op = req.getParameter(Constants.OP_TYPE);
+ String scope = req.getParameter(Constants.OP_SCOPE);
+
+ //check operational flags
+ if ((op == null) || (scope == null)) {
+ sendResponse(1, "Invalid Protocol", null, resp);
+ return;
+ }
+
+ //authenticate the user
+ super.authenticate(req);
+
+ //perform services
+ try {
+ AUTHZ_RES_NAME = "certServer.ra.configuration";
+ if (op.equals(OpDef.OP_READ)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_GENERAL)) {
+ readGeneralConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_CONNECTOR)) {
+ getConnectorConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_NOTIFICATION_REQ_COMP)) {
+ getNotificationReqCompConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_NOTIFICATION_REV_COMP)) {
+ getNotificationRevCompConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_NOTIFICATION_RIQ)) {
+ getNotificationRIQConfig(req, resp);
+ return;
+ } else {
+ sendResponse(1, "Unknown operation", null, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_GENERAL)) {
+ modifyGeneralConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_CONNECTOR)) {
+ setConnectorConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_NOTIFICATION_REQ_COMP)) {
+ setNotificationReqCompConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_NOTIFICATION_REV_COMP)) {
+ setNotificationRevCompConfig(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_NOTIFICATION_RIQ)) {
+ setNotificationRIQConfig(req, resp);
+ return;
+ } else {
+ sendResponse(1, "Unknown operation", null, resp);
+ return;
+ }
+ }
+ } catch (Exception e) {
+ //System.out.println("XXX >>>" + e.toString() + "<<<");
+ sendResponse(1, "Unknown operation", null, resp);
+ }
+
+ return;
+ }
+
+ /*==========================================================
+ * private methods
+ *==========================================================*/
+
+ /*
+ * handle getting completion (cert issued) notification config info
+ */
+ private void getNotificationCompConfig(HttpServletRequest req,
+ HttpServletResponse resp, IConfigStore rc) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_ENABLE))
+ continue;
+ params.put(name, rc.getString(name, ""));
+ }
+
+ params.put(Constants.PR_ENABLE,
+ rc.getString(PROP_ENABLED, Constants.FALSE));
+ //System.out.println("Send: "+params.toString());
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void getNotificationReqCompConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ IConfigStore config = mRA.getConfigStore();
+ IConfigStore nc =
+ config.getSubStore(IRegistrationAuthority.PROP_NOTIFY_SUBSTORE);
+
+ IConfigStore rc = nc.getSubStore(IRegistrationAuthority.PROP_CERT_ISSUED_SUBSTORE);
+
+ getNotificationCompConfig(req, resp, rc);
+
+ }
+
+ private void getNotificationRevCompConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ IConfigStore config = mRA.getConfigStore();
+ IConfigStore nc =
+ config.getSubStore(IRegistrationAuthority.PROP_NOTIFY_SUBSTORE);
+
+ IConfigStore rc = nc.getSubStore(IRegistrationAuthority.PROP_CERT_REVOKED_SUBSTORE);
+
+ getNotificationCompConfig(req, resp, rc);
+
+ }
+
+ /*
+ * handle getting request in queue notification config info
+ */
+ private void getNotificationRIQConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+
+ IConfigStore config = mRA.getConfigStore();
+ IConfigStore nc =
+ config.getSubStore(IRegistrationAuthority.PROP_NOTIFY_SUBSTORE);
+
+ IConfigStore riq = nc.getSubStore(IRegistrationAuthority.PROP_REQ_IN_Q_SUBSTORE);
+
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_ENABLE))
+ continue;
+ params.put(name, riq.getString(name, ""));
+ }
+
+ params.put(Constants.PR_ENABLE,
+ riq.getString(PROP_ENABLED, Constants.FALSE));
+ //System.out.println("Send: "+params.toString());
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /*
+ * handle setting request in queue notification config info
+ */
+ private void setNotificationRIQConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ IConfigStore config = mRA.getConfigStore();
+ IConfigStore nc =
+ config.getSubStore(IRegistrationAuthority.PROP_NOTIFY_SUBSTORE);
+
+ IConfigStore riq = nc.getSubStore(IRegistrationAuthority.PROP_REQ_IN_Q_SUBSTORE);
+
+ //set rest of the parameters
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_ENABLE))
+ continue;
+ String val = req.getParameter(name);
+
+ riq.putString(name, val);
+ mRA.getRequestInQListener().set(name, val);
+ }
+
+ // set enable flag
+ String enabledString = req.getParameter(Constants.PR_ENABLE);
+
+ riq.putString(PROP_ENABLED, enabledString);
+ mRA.getRequestInQListener().set(PROP_ENABLED, enabledString);
+
+ commit(true);
+
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ /*
+ * handle setting request complete notification config info
+ */
+ private void setNotificationCompConfig(HttpServletRequest req,
+ HttpServletResponse resp, IConfigStore rc, IRequestListener thisListener) throws ServletException,
+ IOException, EBaseException {
+ //set rest of the parameters
+ Enumeration<String> e = req.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.PR_ENABLE))
+ continue;
+ String val = req.getParameter(name);
+
+ rc.putString(name, val);
+ thisListener.set(name, val);
+ }
+
+ // set enable flag
+ String enabledString = req.getParameter(Constants.PR_ENABLE);
+
+ rc.putString(PROP_ENABLED, enabledString);
+ thisListener.set(PROP_ENABLED, enabledString);
+
+ commit(true);
+
+ sendResponse(SUCCESS, null, null, resp);
+ }
+
+ private void setNotificationReqCompConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ IConfigStore config = mRA.getConfigStore();
+ IConfigStore nc =
+ config.getSubStore(IRegistrationAuthority.PROP_NOTIFY_SUBSTORE);
+
+ IConfigStore rc = nc.getSubStore(IRegistrationAuthority.PROP_CERT_ISSUED_SUBSTORE);
+
+ setNotificationCompConfig(req, resp, rc, mRA.getCertIssuedListener());
+
+ }
+
+ private void setNotificationRevCompConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ IConfigStore config = mRA.getConfigStore();
+ IConfigStore nc =
+ config.getSubStore(IRegistrationAuthority.PROP_NOTIFY_SUBSTORE);
+
+ IConfigStore rc = nc.getSubStore(IRegistrationAuthority.PROP_CERT_REVOKED_SUBSTORE);
+
+ setNotificationCompConfig(req, resp, rc, mRA.getCertRevokedListener());
+ }
+
+ private void getConnectorConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ IConfigStore raConfig = mRA.getConfigStore();
+ IConfigStore connectorConfig = raConfig.getSubStore("connector");
+ IConfigStore caConnectorConfig = null;
+
+ if (isCAConnector(req)) {
+ caConnectorConfig = connectorConfig.getSubStore("CA");
+ } else if (isRAConnector(req)) {
+ caConnectorConfig = connectorConfig.getSubStore("RA");
+ } else if (isKRAConnector(req)) {
+ caConnectorConfig = connectorConfig.getSubStore("KRA");
+ }
+
+ /*
+ Enumeration enum = req.getParameterNames();
+ NameValuePairs params = new NameValuePairs();
+ while (enum.hasMoreElements()) {
+ String key = (String)enum.nextElement();
+ if (key.equals("RS_ID")) {
+ String val = req.getParameter(key);
+ if (val.equals("CA Connector"))
+ }
+ }
+ */
+
+ Enumeration<String> enum1 = req.getParameterNames();
+ NameValuePairs params = new NameValuePairs();
+
+ if (caConnectorConfig != null) {
+ while (enum1.hasMoreElements()) {
+ String name = enum1.nextElement();
+
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+
+ params.put(name, caConnectorConfig.getString(name, ""));
+ }
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ private void setConnectorConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ IConfigStore raConfig = mRA.getConfigStore();
+ IConfigStore connectorConfig = raConfig.getSubStore("connector");
+ IConfigStore caConnectorConfig = null;
+ // String nickname = raConfig.getString("certNickname", "");
+
+ if (isCAConnector(req)) {
+ caConnectorConfig = connectorConfig.getSubStore("CA");
+ } else if (isRAConnector(req)) {
+ caConnectorConfig = connectorConfig.getSubStore("RA");
+ } else if (isKRAConnector(req)) {
+ caConnectorConfig = connectorConfig.getSubStore("KRA");
+ }
+
+ Enumeration<String> enum1 = req.getParameterNames();
+
+ if (caConnectorConfig != null) {
+ while (enum1.hasMoreElements()) {
+ String name = enum1.nextElement();
+
+ if (name.equals(Constants.OP_TYPE))
+ continue;
+ if (name.equals(Constants.RS_ID))
+ continue;
+ if (name.equals(Constants.OP_SCOPE))
+ continue;
+ /*
+ if (name.equals("nickName")) {
+ caConnectorConfig.putString(name, nickname);
+ continue;
+ }
+ */
+ caConnectorConfig.putString(name, req.getParameter(name));
+ }
+ }
+
+ commit(true);
+ sendResponse(RESTART, null, null, resp);
+ }
+
+ private boolean isCAConnector(HttpServletRequest req) {
+
+ Enumeration<String> enum1 = req.getParameterNames();
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+
+ if (key.equals("RS_ID")) {
+ String val = req.getParameter(key);
+
+ if (val.equals("Certificate Manager Connector"))
+ return true;
+ else
+ return false;
+ }
+ }
+ return false;
+ }
+
+ private boolean isRAConnector(HttpServletRequest req) {
+
+ Enumeration<String> enum1 = req.getParameterNames();
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+
+ if (key.equals("RS_ID")) {
+ String val = req.getParameter(key);
+
+ if (val.equals("Registration Manager Connector"))
+ return true;
+ else
+ return false;
+ }
+ }
+ return false;
+ }
+
+ private boolean isKRAConnector(HttpServletRequest req) {
+
+ Enumeration<String> enum1 = req.getParameterNames();
+
+ while (enum1.hasMoreElements()) {
+ String key = enum1.nextElement();
+
+ if (key.equals("RS_ID")) {
+ String val = req.getParameter(key);
+
+ if (val.equals("Data Recovery Manager Connector"))
+ return true;
+ else
+ return false;
+ }
+ }
+ return false;
+ }
+
+ //reading the RA general information
+ private void readGeneralConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+
+ /*
+ ISubsystem eeGateway =
+ SubsystemRegistry.getInstance().get("eeGateway");
+ String value = "false";
+ if (eeGateway != null) {
+ IConfigStore eeConfig = eeGateway.getConfigStore();
+ if (eeConfig != null)
+ value = eeConfig.getString("enabled", "true");
+ }
+ params.add(Constants.PR_EE_ENABLED, value);
+ */
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ //mdify RA General Information
+ private void modifyGeneralConfig(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ /*
+ ISubsystem eeGateway =
+ SubsystemRegistry.getInstance().get("eeGateway");
+ IConfigStore eeConfig = null;
+ if (eeGateway != null)
+ eeConfig = eeGateway.getConfigStore();
+
+ Enumeration enum = req.getParameterNames();
+ while (enum.hasMoreElements()) {
+ String key = (String)enum.nextElement();
+ if (key.equals(Constants.PR_EE_ENABLED)) {
+ if (eeConfig != null)
+ eeConfig.putString("enabled",
+ req.getParameter(Constants.PR_EE_ENABLED));
+ }
+ }
+
+ */
+ sendResponse(RESTART, null, null, resp);
+ commit(true);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/RegistryAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/RegistryAdminServlet.java
new file mode 100644
index 000000000..4d47d318f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/RegistryAdminServlet.java
@@ -0,0 +1,365 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.profile.IPolicyConstraint;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.property.IConfigTemplate;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.registry.IPluginInfo;
+import com.netscape.certsrv.registry.IPluginRegistry;
+
+/**
+ * This implements the administration servlet for registry subsystem.
+ *
+ * @version $Revision$, $Date$
+ */
+public class RegistryAdminServlet extends AdminServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2104924641665675578L;
+
+ public final static String PROP_AUTHORITY = "authority";
+
+ private final static String INFO = "RegistryAdminServlet";
+
+ public final static String PROP_PREDICATE = "predicate";
+ private IPluginRegistry mRegistry = null;
+
+ // These will be moved to PolicyResources
+ public static String INVALID_POLICY_SCOPE = "Invalid policy administration scope";
+ public static String INVALID_POLICY_IMPL_OP = "Invalid operation for policy implementation management";
+ public static String NYI = "Not Yet Implemented";
+ public static String INVALID_POLICY_IMPL_CONFIG = "Invalid policy implementation configuration";
+ public static String INVALID_POLICY_INSTANCE_CONFIG = "Invalid policy instance configuration";
+ public static String MISSING_POLICY_IMPL_ID = "Missing policy impl id in request";
+ public static String MISSING_POLICY_IMPL_CLASS = "Missing policy impl class in request";
+ public static String INVALID_POLICY_IMPL_ID = "Invalid policy impl id in request";
+ public static String MISSING_POLICY_INST_ID = "Missing policy impl id in request";
+ public static String INVALID_POLICY_INST_ID = "Invalid policy impl id in request";
+ public static String COMMA = ",";
+ public static String MISSING_POLICY_ORDERING = "Missing policy ordering";
+
+ /**
+ * Constructs administration servlet.
+ */
+ public RegistryAdminServlet() {
+ super();
+ }
+
+ /**
+ * Initializes this servlet.
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ mRegistry = (IPluginRegistry) CMS.getSubsystem(CMS.SUBSYSTEM_REGISTRY);
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Serves HTTP admin request.
+ */
+ public void service(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+
+ super.authenticate(req);
+
+ AUTHZ_RES_NAME = "certServer.registry.configuration";
+ String scope = req.getParameter(Constants.OP_SCOPE);
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (scope.equals(ScopeDef.SC_SUPPORTED_CONSTRAINTPOLICIES)) {
+ if (op.equals(OpDef.OP_READ))
+ if (!readAuthorize(req, resp))
+ return;
+ getSupportedConstraintPolicies(req, resp);
+ } else {
+ processImplMgmt(req, resp);
+ }
+ }
+
+ private boolean readAuthorize(HttpServletRequest req,
+ HttpServletResponse resp) throws IOException {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return false;
+ }
+ return true;
+ }
+
+ private boolean modifyAuthorize(HttpServletRequest req,
+ HttpServletResponse resp) throws IOException {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Process Policy Implementation Management.
+ */
+ public void processImplMgmt(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Get operation type
+ String op = req.getParameter(Constants.OP_TYPE);
+
+ if (op.equals(OpDef.OP_SEARCH)) {
+ if (!readAuthorize(req, resp))
+ return;
+ listImpls(req, resp);
+ } else if (op.equals(OpDef.OP_READ)) {
+ if (!readAuthorize(req, resp))
+ return;
+ getProfileImplConfig(req, resp);
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ deleteImpl(req, resp);
+ } else if (op.equals(OpDef.OP_ADD)) {
+ if (!modifyAuthorize(req, resp))
+ return;
+ addImpl(req, resp);
+ } else
+ sendResponse(ERROR, INVALID_POLICY_IMPL_OP,
+ null, resp);
+ }
+
+ public void addImpl(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ // Get the policy impl id.
+ String id = req.getParameter(Constants.RS_ID);
+ String scope = req.getParameter(Constants.OP_SCOPE);
+ String classPath = req.getParameter(Constants.PR_POLICY_CLASS);
+ String desc = req.getParameter(Constants.PR_POLICY_DESC);
+
+ if (id == null) {
+ sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp);
+ return;
+ }
+
+ NameValuePairs nvp = new NameValuePairs();
+
+ IPluginInfo info = mRegistry.createPluginInfo(id, desc, classPath);
+ try {
+ mRegistry.addPluginInfo(scope, id, info);
+ } catch (Exception e) {
+ CMS.debug(e.toString());
+ }
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ public void deleteImpl(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ // Get the policy impl id.
+ String id = req.getParameter(Constants.RS_ID);
+ String scope = req.getParameter(Constants.OP_SCOPE);
+
+ if (id == null) {
+ sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp);
+ return;
+ }
+
+ IPluginInfo info = mRegistry.getPluginInfo(scope, id);
+
+ if (info == null) {
+ sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp);
+ return;
+ }
+
+ NameValuePairs nvp = new NameValuePairs();
+
+ try {
+ mRegistry.removePluginInfo(scope, id);
+ } catch (Exception e) {
+ CMS.debug(e.toString());
+ }
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ /**
+ * Lists all registered profile impementations
+ */
+ public void listImpls(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ String scope = req.getParameter(Constants.OP_SCOPE);
+ Enumeration<String> impls = mRegistry.getIds(scope);
+ NameValuePairs nvp = new NameValuePairs();
+
+ while (impls.hasMoreElements()) {
+ String id = impls.nextElement();
+ IPluginInfo info = mRegistry.getPluginInfo(scope, id);
+
+ nvp.put(id, info.getClassName() + "," +
+ info.getDescription(getLocale(req)) + "," + info.getName(getLocale(req)));
+ }
+
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ public void getSupportedConstraintPolicies(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException, IOException {
+ String id = req.getParameter(Constants.RS_ID);
+
+ if (id == null) {
+ sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp);
+ return;
+ }
+ NameValuePairs nvp = new NameValuePairs();
+
+ try {
+ IPluginInfo info = mRegistry.getPluginInfo("defaultPolicy", id);
+ String className = info.getClassName();
+ IPolicyDefault policyDefaultClass = (IPolicyDefault)
+ Class.forName(className).newInstance();
+
+ if (policyDefaultClass != null) {
+ Enumeration<String> impls = mRegistry.getIds("constraintPolicy");
+
+ while (impls.hasMoreElements()) {
+ String constraintID = impls.nextElement();
+ IPluginInfo constraintInfo = mRegistry.getPluginInfo(
+ "constraintPolicy", constraintID);
+ IPolicyConstraint policyConstraintClass = (IPolicyConstraint)
+ Class.forName(constraintInfo.getClassName()).newInstance();
+
+ CMS.debug("RegistryAdminServlet: getSUpportedConstraint " + constraintInfo.getClassName());
+
+ if (policyConstraintClass.isApplicable(policyDefaultClass)) {
+ CMS.debug("RegistryAdminServlet: getSUpportedConstraint isApplicable "
+ + constraintInfo.getClassName());
+ nvp.put(constraintID,
+ constraintInfo.getClassName()
+ + "," +
+ constraintInfo.getDescription(getLocale(req)) + ","
+ + constraintInfo.getName(getLocale(req)));
+ }
+ }
+ }
+ } catch (Exception ex) {
+ CMS.debug("RegistyAdminServlet: getSupportConstraintPolicies: " + ex.toString());
+ CMS.debug(ex);
+ }
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ public void getProfileImplConfig(HttpServletRequest req,
+ HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ // Get the policy impl id.
+ String id = req.getParameter(Constants.RS_ID);
+ String scope = req.getParameter(Constants.OP_SCOPE);
+
+ if (id == null) {
+ sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp);
+ return;
+ }
+
+ IPluginInfo info = mRegistry.getPluginInfo(scope, id);
+
+ if (info == null) {
+ sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp);
+ return;
+ }
+
+ NameValuePairs nvp = new NameValuePairs();
+
+ String className = info.getClassName();
+ IConfigTemplate template = null;
+
+ try {
+ template = (IConfigTemplate)
+ Class.forName(className).newInstance();
+ } catch (Exception e) {
+ }
+ if (template != null) {
+ Enumeration<String> names = template.getConfigNames();
+
+ if (names != null) {
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ CMS.debug("RegistryAdminServlet: getProfileImpl descriptor " + name);
+ IDescriptor desc = template.getConfigDescriptor(getLocale(req), name);
+
+ if (desc != null) {
+ try {
+ String value =
+ getNonNull(desc.getSyntax())
+ + ";" + getNonNull(desc.getConstraint()) + ";"
+ + desc.getDescription(getLocale(req)) + ";"
+ + getNonNull(desc.getDefaultValue());
+
+ CMS.debug("RegistryAdminServlet: getProfileImpl " + value);
+ nvp.put(name, value);
+ } catch (Exception e) {
+
+ CMS.debug("RegistryAdminServlet: getProfileImpl skipped descriptor for " + name);
+ }
+ } else {
+ CMS.debug("RegistryAdminServlet: getProfileImpl cannot find descriptor for " + name);
+ }
+ }
+ }
+ }
+ sendResponse(SUCCESS, null, nvp, resp);
+ }
+
+ protected String getNonNull(String s) {
+ if (s == null)
+ return "";
+ return s;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/SystemCertService.java b/base/server/cms/src/com/netscape/cms/servlet/admin/SystemCertService.java
new file mode 100644
index 000000000..50df221f9
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/SystemCertService.java
@@ -0,0 +1,98 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.admin;
+
+import java.security.cert.CertificateEncodingException;
+
+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 com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.base.ResourceNotFoundException;
+import com.netscape.certsrv.cert.CertData;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.security.ITransportKeyUnit;
+import com.netscape.certsrv.system.SystemCertResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * This is the class used to list, retrieve and modify system certificates for all Java subsystems.
+ *
+ * @author alee
+ *
+ */
+public class SystemCertService extends PKIService implements SystemCertResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public SystemCertService() {
+ CMS.debug("SystemCertService.<init>()");
+ }
+
+ /**
+ * Used to retrieve the transport certificate
+ */
+ public Response getTransportCert() {
+ CertData cert = null;
+ IKeyRecoveryAuthority kra = null;
+
+ // auth and authz
+
+ kra = (IKeyRecoveryAuthority) CMS.getSubsystem("kra");
+ if (kra == null) {
+ // no KRA
+ throw new ResourceNotFoundException("KRA subsystem not found.");
+ }
+
+ ITransportKeyUnit tu = kra.getTransportKeyUnit();
+ if (tu == null) {
+ CMS.debug("getTransportCert: transport key unit is null");
+ throw new PKIException("No transport key unit.");
+ }
+ org.mozilla.jss.crypto.X509Certificate transportCert = tu.getCertificate();
+ if (transportCert == null) {
+ CMS.debug("getTransportCert: transport cert is null");
+ throw new PKIException("Transport cert not found.");
+ }
+ try {
+ cert = createCertificateData(transportCert);
+ } catch (CertificateEncodingException e) {
+ CMS.debug("getTransportCert: certificate encoding exception with transport cert");
+ e.printStackTrace();
+ throw new PKIException("Unable to encode transport cert");
+ }
+ return sendConditionalGetResponse(DEFAULT_LONG_CACHE_LIFETIME, cert, request);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/UserService.java b/base/server/cms/src/com/netscape/cms/servlet/admin/UserService.java
new file mode 100644
index 000000000..c14605c54
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/UserService.java
@@ -0,0 +1,1101 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.admin;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.List;
+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.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import netscape.ldap.LDAPException;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.x509.X509CertImpl;
+
+import org.apache.commons.lang.StringUtils;
+import org.jboss.resteasy.plugins.providers.atom.Link;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.InternalCertificate;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestDataException;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.ForbiddenException;
+import com.netscape.certsrv.base.ICertPrettyPrint;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.base.ResourceNotFoundException;
+import com.netscape.certsrv.base.UserNotFoundException;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.dbs.certdb.CertId;
+import com.netscape.certsrv.group.GroupMemberData;
+import com.netscape.certsrv.ldap.LDAPExceptionConverter;
+import com.netscape.certsrv.logging.IAuditor;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.password.IPasswordCheck;
+import com.netscape.certsrv.user.UserCertCollection;
+import com.netscape.certsrv.user.UserCertData;
+import com.netscape.certsrv.user.UserCollection;
+import com.netscape.certsrv.user.UserData;
+import com.netscape.certsrv.user.UserMembershipCollection;
+import com.netscape.certsrv.user.UserMembershipData;
+import com.netscape.certsrv.user.UserResource;
+import com.netscape.certsrv.usrgrp.EUsrGrpException;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cms.servlet.base.PKIService;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+import com.netscape.cmsutil.util.Cert;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class UserService extends PKIService implements UserResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public final static int DEFAULT_SIZE = 20;
+
+ public final static String BACK_SLASH = "\\";
+ public final static String SYSTEM_USER = "$System$";
+
+ public IUGSubsystem userGroupManager = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+
+ public UserData createUserData(IUser user) throws Exception {
+
+ UserData userData = new UserData();
+
+ String id = user.getUserID();
+ if (!StringUtils.isEmpty(id)) userData.setID(id);
+
+ String fullName = user.getFullName();
+ if (!StringUtils.isEmpty(fullName)) userData.setFullName(fullName);
+
+ String userID = URLEncoder.encode(id, "UTF-8");
+ URI uri = uriInfo.getBaseUriBuilder().path(UserResource.class).path("{userID}").build(userID);
+ userData.setLink(new Link("self", uri));
+
+ return userData;
+ }
+
+ /**
+ * Searches for users in LDAP directory.
+ *
+ * Request/Response Syntax:
+ * http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ */
+ @Override
+ public UserCollection findUsers(String filter, Integer start, Integer size) {
+ try {
+ filter = StringUtils.isEmpty(filter) ? "*" : "*"+LDAPUtil.escapeFilter(filter)+"*";
+ start = start == null ? 0 : start;
+ size = size == null ? DEFAULT_SIZE : size;
+
+ Enumeration<IUser> users = userGroupManager.findUsers(filter);
+
+ UserCollection response = new UserCollection();
+
+ int i = 0;
+
+ // skip to the start of the page
+ for ( ; i<start && users.hasMoreElements(); i++) users.nextElement();
+
+ // return entries up to the page size
+ for ( ; i<start+size && users.hasMoreElements(); i++) {
+ IUser user = users.nextElement();
+ response.addUser(createUserData(user));
+ }
+
+ // count the total entries
+ for ( ; users.hasMoreElements(); i++) users.nextElement();
+
+ 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 response;
+
+ } catch (Exception e) {
+ throw new PKIException(getUserMessage("CMS_INTERNAL_ERROR", headers));
+ }
+ }
+
+ /**
+ * List user information. Certificates covered in a separate
+ * protocol for findUserCerts(). List of group memberships are
+ * also provided.
+ *
+ * Request/Response Syntax:
+ * http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ */
+ @Override
+ public UserData getUser(String userID) {
+ try {
+ if (userID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ throw new BadRequestDataException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID", headers));
+ }
+
+ IUser user;
+
+ try {
+ user = userGroupManager.getUser(userID);
+ } catch (Exception e) {
+ throw new PKIException(getUserMessage("CMS_INTERNAL_ERROR", headers));
+ }
+
+ if (user == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_USER_NOT_EXIST"));
+
+ throw new UserNotFoundException(userID);
+ }
+
+ UserData userData = createUserData(user);
+
+ String email = user.getEmail();
+ if (!StringUtils.isEmpty(email)) userData.setEmail(email);
+
+ String phone = user.getPhone();
+ if (!StringUtils.isEmpty(phone)) userData.setPhone(phone);
+
+ String state = user.getState();
+ if (!StringUtils.isEmpty(state)) userData.setState(state);
+
+ String type = user.getUserType();
+ if (!StringUtils.isEmpty(type)) userData.setType(type);
+
+ List<String> profiles = user.getTpsProfiles();
+ if (profiles != null) {
+ StringBuilder sb = new StringBuilder();
+ String prefix = "";
+ for (String profile: profiles) {
+ sb.append(prefix);
+ prefix = ",";
+ sb.append(profile);
+ }
+
+ userData.setAttribute(ATTR_TPS_PROFILES, sb.toString());
+ }
+
+ return userData;
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ /**
+ * Adds a new user to LDAP server
+ * <P>
+ *
+ * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ */
+
+ @Override
+ public Response addUser(UserData userData) {
+
+ IConfigStore cs = CMS.getConfigStore();
+ String userID = userData.getID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ if (userID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestDataException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID", headers));
+ }
+
+ if (userID.indexOf(BACK_SLASH) != -1) {
+ // backslashes (BS) are not allowed
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_RS_ID_BS"));
+ throw new BadRequestDataException(getUserMessage("CMS_ADMIN_SRVLT_RS_ID_BS", headers));
+ }
+
+ if (userID.equals(SYSTEM_USER)) {
+ // backslashes (BS) are not allowed
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_SPECIAL_ID", userID));
+ throw new ForbiddenException(getUserMessage("CMS_ADMIN_SRVLT_SPECIAL_ID", headers, userID));
+ }
+
+ IUser user = userGroupManager.createUser(userID);
+
+ String fname = userData.getFullName();
+ if (fname == null || fname.length() == 0) {
+ String msg = getUserMessage("CMS_USRGRP_USER_ADD_FAILED_1", headers, "full name");
+
+ log(ILogger.LL_FAILURE, msg);
+ throw new BadRequestDataException(msg);
+
+ } else {
+ user.setFullName(fname);
+ }
+
+ String email = userData.getEmail();
+ if (email != null) {
+ user.setEmail(email);
+ } else {
+ user.setEmail("");
+ }
+
+ String pword = userData.getPassword();
+ if (pword != null && !pword.equals("")) {
+ IPasswordCheck passwdCheck = CMS.getPasswordChecker();
+
+ if (!passwdCheck.isGoodPassword(pword)) {
+ throw new EUsrGrpException(passwdCheck.getReason(pword));
+ }
+
+ user.setPassword(pword);
+ } else {
+ user.setPassword("");
+ }
+
+ String phone = userData.getPhone();
+ if (phone != null) {
+ user.setPhone(phone);
+ } else {
+ user.setPhone("");
+ }
+
+ String type = userData.getType();
+ if (type != null) {
+ user.setUserType(type);
+ } else {
+ user.setUserType("");
+ }
+
+ String state = userData.getState();
+ if (state != null) {
+ user.setState(state);
+ }
+
+ String tpsProfiles = userData.getAttribute(ATTR_TPS_PROFILES);
+ String csType = cs.getString("cs.type");
+ if (tpsProfiles != null) {
+ if (!csType.equals("TPS")) {
+ throw new BadRequestDataException("Cannot set tpsProfiles on a non-TPS subsystem");
+ }
+ String[] profiles = tpsProfiles.split(",");
+ user.setTpsProfiles(Arrays.asList(profiles));
+ }
+
+ try {
+ userGroupManager.addUser(user);
+
+ auditAddUser(userID, userData, ILogger.SUCCESS);
+
+ // read the data back
+ userData = getUser(userID);
+
+ return Response
+ .created(userData.getLink().getHref())
+ .entity(userData)
+ .type(MediaType.APPLICATION_XML)
+ .build();
+
+ } catch (EUsrGrpException e) {
+ log(ILogger.LL_FAILURE, e.toString());
+
+ if (user.getUserID() == null) {
+ throw new BadRequestDataException(getUserMessage("CMS_USRGRP_USER_ADD_FAILED_1", headers, "uid"));
+ } else {
+ throw new PKIException(e.getMessage(), e);
+ }
+
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_ADD_USER_FAIL", e.toString()));
+ throw LDAPExceptionConverter.toPKIException(e);
+
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ throw new PKIException(e.getMessage(), e);
+ }
+
+ } catch (PKIException e) {
+ auditAddUser(userID, userData, ILogger.FAILURE);
+ throw e;
+
+ } catch (EBaseException e) {
+ auditAddUser(userID, userData, ILogger.FAILURE);
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ /**
+ * Modifies an existing user in local scope.
+ * <P>
+ *
+ * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ */
+ @Override
+ public Response modifyUser(String userID, UserData userData) {
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ if (userID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestDataException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID", headers));
+ }
+
+ IUser user = userGroupManager.createUser(userID);
+
+ String fullName = userData.getFullName();
+ if (fullName != null) {
+ user.setFullName(fullName);
+ }
+
+ String email = userData.getEmail();
+ if (email != null) {
+ user.setEmail(email);
+ }
+
+ String pword = userData.getPassword();
+ if (pword != null && !pword.equals("")) {
+ IPasswordCheck passwdCheck = CMS.getPasswordChecker();
+
+ if (!passwdCheck.isGoodPassword(pword)) {
+ throw new EUsrGrpException(passwdCheck.getReason(pword));
+ }
+
+ user.setPassword(pword);
+ }
+
+ String phone = userData.getPhone();
+ if (phone != null) {
+ user.setPhone(phone);
+ }
+
+ String state = userData.getState();
+ if (state != null) {
+ user.setState(state);
+ }
+
+ String tpsProfiles = userData.getAttribute(ATTR_TPS_PROFILES);
+ String csType = cs.getString("cs.type");
+ if (tpsProfiles != null) {
+ if (!csType.equals("TPS")) {
+ throw new BadRequestDataException("Cannot set tpsProfiles on a non-TPS subsystem");
+ }
+ String[] profiles = tpsProfiles.split(",");
+ user.setTpsProfiles(Arrays.asList(profiles));
+ }
+
+ try {
+ userGroupManager.modifyUser(user);
+
+ auditModifyUser(userID, userData, ILogger.SUCCESS);
+
+ // read the data back
+ userData = getUser(userID);
+
+ return Response
+ .ok(userData)
+ .type(MediaType.APPLICATION_XML)
+ .build();
+
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ throw new PKIException(getUserMessage("CMS_USRGRP_USER_MOD_FAILED", headers));
+ }
+
+ } catch (PKIException e) {
+ auditModifyUser(userID, userData, ILogger.FAILURE);
+ throw e;
+
+ } catch (EBaseException e) {
+ auditModifyUser(userID, userData, ILogger.FAILURE);
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ /**
+ * removes a user. user not removed if belongs to any group
+ * (Administrators should remove the user from "uniquemember" of
+ * any group he/she belongs to before trying to remove the user
+ * itself.
+ * <P>
+ *
+ * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ */
+ @Override
+ public void removeUser(String userID) {
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ if (userID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID", headers));
+ }
+
+ // get list of groups, and see if uid belongs to any
+ Enumeration<IGroup> groups;
+
+ try {
+ groups = userGroupManager.findGroups("*");
+
+ } catch (Exception e) {
+ throw new PKIException(getUserMessage("CMS_INTERNAL_ERROR", headers));
+ }
+
+ try {
+ while (groups.hasMoreElements()) {
+ IGroup group = groups.nextElement();
+ if (!group.isMember(userID)) continue;
+
+ userGroupManager.removeUserFromGroup(group, userID);
+ }
+
+ // comes out clean of group membership...now remove user
+ userGroupManager.removeUser(userID);
+
+ auditDeleteUser(userID, ILogger.SUCCESS);
+
+ } catch (Exception e) {
+ throw new PKIException(getUserMessage("CMS_USRGRP_SRVLT_FAIL_USER_RMV", headers));
+ }
+
+ } catch (PKIException e) {
+ auditDeleteUser(userID, ILogger.FAILURE);
+ throw e;
+ }
+ }
+
+ public UserCertData createUserCertData(String userID, X509Certificate cert) throws Exception {
+
+ UserCertData userCertData = new UserCertData();
+
+ userCertData.setVersion(cert.getVersion());
+ userCertData.setSerialNumber(new CertId(cert.getSerialNumber()));
+ userCertData.setIssuerDN(cert.getIssuerDN().toString());
+ userCertData.setSubjectDN(cert.getSubjectDN().toString());
+
+ userID = URLEncoder.encode(userID, "UTF-8");
+ String certID = URLEncoder.encode(userCertData.getID(), "UTF-8");
+ URI uri = uriInfo.getBaseUriBuilder()
+ .path(UserResource.class)
+ .path("{userID}/certs/{certID}")
+ .build(userID, certID);
+ userCertData.setLink(new Link("self", uri));
+
+ return userCertData;
+ }
+
+ /**
+ * List user certificate(s)
+ *
+ * Request/Response Syntax:
+ * http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ */
+ @Override
+ public UserCertCollection findUserCerts(String userID, Integer start, Integer size) {
+ try {
+ start = start == null ? 0 : start;
+ size = size == null ? DEFAULT_SIZE : size;
+
+ if (userID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID", headers));
+ }
+
+ IUser user = null;
+
+ try {
+ user = userGroupManager.getUser(userID);
+ } catch (Exception e) {
+ throw new PKIException(getUserMessage("CMS_USRGRP_SRVLT_USER_NOT_EXIST", headers));
+ }
+
+ if (user == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_USER_NOT_EXIST"));
+ throw new UserNotFoundException(userID);
+ }
+
+ UserCertCollection response = new UserCertCollection();
+
+ X509Certificate[] certs = user.getX509Certificates();
+ if (certs != null) {
+ for (int i=start; i<start+size && i<certs.length; i++) {
+ X509Certificate cert = certs[i];
+ response.addCert(createUserCertData(userID, cert));
+ }
+
+ if (start > 0) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+ response.addLink(new Link("prev", uri));
+ }
+
+ if (start+size < certs.length) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+ response.addLink(new Link("next", uri));
+ }
+ }
+
+ return response;
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public UserCertData getUserCert(String userID, String certID) {
+ try {
+ if (userID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ throw new BadRequestException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID", headers));
+ }
+
+ IUser user = null;
+
+ try {
+ user = userGroupManager.getUser(userID);
+ } catch (Exception e) {
+ throw new PKIException(getUserMessage("CMS_USRGRP_SRVLT_USER_NOT_EXIST", headers));
+ }
+
+ if (user == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_USER_NOT_EXIST"));
+ throw new UserNotFoundException(userID);
+ }
+
+ X509Certificate[] certs = user.getX509Certificates();
+
+ if (certs == null) {
+ throw new ResourceNotFoundException("No certificates found for " + userID);
+ }
+
+ try {
+ certID = URLDecoder.decode(certID, "UTF-8");
+ } catch (Exception e) {
+ throw new PKIException(e.getMessage());
+ }
+
+ for (X509Certificate cert : certs) {
+
+ UserCertData userCertData = createUserCertData(userID, cert);
+
+ if (!userCertData.getID().equals(certID)) continue;
+
+ ICertPrettyPrint print = CMS.getCertPrettyPrint(cert);
+ userCertData.setPrettyPrint(print.toString(getLocale(headers)));
+
+ // add base64 encoding
+ String base64 = CMS.getEncodedCert(cert);
+ userCertData.setEncoded(base64);
+
+ return userCertData;
+ }
+
+ throw new ResourceNotFoundException("No certificates found for " + userID);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ /**
+ * Adds a certificate to a user
+ * <P>
+ *
+ * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ */
+ @Override
+ public Response addUserCert(String userID, UserCertData userCertData) {
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ if (userID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID", headers));
+ }
+
+ IUser user = userGroupManager.createUser(userID);
+
+ String encoded = userCertData.getEncoded();
+ encoded = Cert.normalizeCertStrAndReq(encoded);
+ encoded = Cert.stripBrackets(encoded);
+
+ // no cert is a success
+ if (encoded == null) {
+ auditAddUserCert(userID, userCertData, ILogger.SUCCESS);
+ return Response.ok().build();
+ }
+
+ // only one cert added per operation
+ X509Certificate cert = null;
+
+ // Base64 decode cert
+ byte binaryCert[] = Utils.base64decode(encoded);
+
+ try {
+ cert = new X509CertImpl(binaryCert);
+
+ } catch (CertificateException e) {
+ // ignore
+ }
+
+ if (cert == null) {
+ // cert chain direction
+ boolean assending = true;
+
+ // could it be a pkcs7 blob?
+ CMS.debug("UserCertResourceService: " + CMS.getLogMessage("ADMIN_SRVLT_IS_PK_BLOB"));
+
+ try {
+ CryptoManager manager = CryptoManager.getInstance();
+
+ PKCS7 pkcs7 = new PKCS7(binaryCert);
+
+ X509Certificate p7certs[] = pkcs7.getCertificates();
+
+ if (p7certs.length == 0) {
+ throw new BadRequestException(getUserMessage("CMS_USRGRP_SRVLT_CERT_ERROR", headers));
+ }
+
+ // fix for 370099 - cert ordering can not be assumed
+ // find out the ordering ...
+
+ // self-signed and alone? take it. otherwise test
+ // the ordering
+ if (p7certs[0].getSubjectDN().toString().equals(
+ p7certs[0].getIssuerDN().toString()) &&
+ (p7certs.length == 1)) {
+ cert = p7certs[0];
+ CMS.debug("UserCertResourceService: " + CMS.getLogMessage("ADMIN_SRVLT_SINGLE_CERT_IMPORT"));
+
+ } else if (p7certs[0].getIssuerDN().toString().equals(p7certs[1].getSubjectDN().toString())) {
+ cert = p7certs[0];
+ CMS.debug("UserCertResourceService: " + CMS.getLogMessage("ADMIN_SRVLT_CERT_CHAIN_ACEND_ORD"));
+
+ } else if (p7certs[1].getIssuerDN().toString().equals(p7certs[0].getSubjectDN().toString())) {
+ assending = false;
+ CMS.debug("UserCertResourceService: " + CMS.getLogMessage("ADMIN_SRVLT_CERT_CHAIN_DESC_ORD"));
+ cert = p7certs[p7certs.length - 1];
+
+ } else {
+ // not a chain, or in random order
+ CMS.debug("UserCertResourceService: " + CMS.getLogMessage("ADMIN_SRVLT_CERT_BAD_CHAIN"));
+ throw new BadRequestException(getUserMessage("CMS_USRGRP_SRVLT_CERT_ERROR", headers));
+ }
+
+ CMS.debug("UserCertResourceService: "
+ + CMS.getLogMessage("ADMIN_SRVLT_CHAIN_STORED_DB", String.valueOf(p7certs.length)));
+
+ int j = 0;
+ int jBegin = 0;
+ int jEnd = 0;
+
+ if (assending == true) {
+ jBegin = 1;
+ jEnd = p7certs.length;
+ } else {
+ jBegin = 0;
+ jEnd = p7certs.length - 1;
+ }
+
+ // store the chain into cert db, except for the user cert
+ for (j = jBegin; j < jEnd; j++) {
+ CMS.debug("UserCertResourceService: "
+ + CMS.getLogMessage("ADMIN_SRVLT_CERT_IN_CHAIN", String.valueOf(j),
+ String.valueOf(p7certs[j].getSubjectDN())));
+ org.mozilla.jss.crypto.X509Certificate leafCert =
+ manager.importCACertPackage(p7certs[j].getEncoded());
+
+ if (leafCert == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_LEAF_CERT_NULL"));
+ } else {
+ CMS.debug("UserCertResourceService: " + CMS.getLogMessage("ADMIN_SRVLT_LEAF_CERT_NON_NULL"));
+ }
+
+ if (leafCert instanceof InternalCertificate) {
+ ((InternalCertificate) leafCert).setSSLTrust(
+ InternalCertificate.VALID_CA |
+ InternalCertificate.TRUSTED_CA |
+ InternalCertificate.TRUSTED_CLIENT_CA);
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NOT_INTERNAL_CERT",
+ String.valueOf(p7certs[j].getSubjectDN())));
+ }
+ }
+
+ /*
+ } catch (CryptoManager.UserCertConflictException e) {
+ // got a "user cert" in the chain, most likely the CA
+ // cert of this instance, which has a private key. Ignore
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_PKS7_IGNORED", e.toString()));
+ */
+ } catch (PKIException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_CERT_ERROR", e.toString()));
+ throw e;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_CERT_ERROR", e.toString()));
+ throw new PKIException(getUserMessage("CMS_USRGRP_SRVLT_CERT_ERROR", headers));
+ }
+ }
+
+ try {
+ CMS.debug("UserCertResourceService: " + CMS.getLogMessage("ADMIN_SRVLT_BEFORE_VALIDITY"));
+ cert.checkValidity(); // throw exception if fails
+
+ user.setX509Certificates(new X509Certificate[] { cert });
+ userGroupManager.addUserCert(user);
+
+ auditAddUserCert(userID, userCertData, ILogger.SUCCESS);
+
+ // read the data back
+
+ userCertData.setVersion(cert.getVersion());
+ userCertData.setSerialNumber(new CertId(cert.getSerialNumber()));
+ userCertData.setIssuerDN(cert.getIssuerDN().toString());
+ userCertData.setSubjectDN(cert.getSubjectDN().toString());
+ String certID = userCertData.getID();
+
+ userCertData = getUserCert(userID, URLEncoder.encode(certID, "UTF-8"));
+
+ return Response
+ .created(userCertData.getLink().getHref())
+ .entity(userCertData)
+ .type(MediaType.APPLICATION_XML)
+ .build();
+
+ } catch (CertificateExpiredException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_ADD_CERT_EXPIRED",
+ String.valueOf(cert.getSubjectDN())));
+ throw new BadRequestException(getUserMessage("CMS_USRGRP_SRVLT_CERT_EXPIRED", headers));
+
+ } catch (CertificateNotYetValidException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_CERT_NOT_YET_VALID",
+ String.valueOf(cert.getSubjectDN())));
+ throw new BadRequestException(getUserMessage("CMS_USRGRP_SRVLT_CERT_NOT_YET_VALID", headers));
+
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.ATTRIBUTE_OR_VALUE_EXISTS) {
+ throw new PKIException(getUserMessage("CMS_USRGRP_SRVLT_USER_CERT_EXISTS", headers));
+ } else {
+ throw new PKIException(getUserMessage("CMS_USRGRP_USER_MOD_FAILED", headers));
+ }
+ }
+
+ } catch (PKIException e) {
+ auditAddUserCert(userID, userCertData, ILogger.FAILURE);
+ throw e;
+
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ auditAddUserCert(userID, userCertData, ILogger.FAILURE);
+ throw new PKIException(getUserMessage("CMS_USRGRP_USER_MOD_FAILED", headers));
+ }
+ }
+
+ /**
+ * Removes a certificate for a user
+ * <P>
+ *
+ * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ * <P>
+ *
+ * In this method, "certDN" is actually a combination of version, serialNumber, issuerDN, and SubjectDN.
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ */
+ @Override
+ public void removeUserCert(String userID, String certID) {
+
+ try {
+ certID = URLDecoder.decode(certID, "UTF-8");
+ } catch (Exception e) {
+ throw new PKIException(e.getMessage());
+ }
+
+ UserCertData userCertData = new UserCertData();
+ userCertData.setID(certID);
+ removeUserCert(userID, userCertData);
+ }
+
+ public void removeUserCert(String userID, UserCertData userCertData) {
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ if (userID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID", headers));
+ }
+
+ IUser user = userGroupManager.createUser(userID);
+ String certID = userCertData.getID();
+
+ // no certDN is a success
+ if (certID == null) {
+ auditDeleteUserCert(userID, userCertData, ILogger.SUCCESS);
+ return;
+ }
+
+ user.setCertDN(certID);
+
+ userGroupManager.removeUserCert(user);
+
+ auditDeleteUserCert(userID, userCertData, ILogger.SUCCESS);
+
+ } catch (PKIException e) {
+ auditDeleteUserCert(userID, userCertData, ILogger.FAILURE);
+ throw e;
+
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ auditDeleteUserCert(userID, userCertData, ILogger.FAILURE);
+ throw new PKIException(getUserMessage("CMS_USRGRP_USER_MOD_FAILED", headers));
+ }
+ }
+
+
+ public UserMembershipData createUserMembershipData(String userID, String groupID) throws UnsupportedEncodingException {
+
+ UserMembershipData userMembershipData = new UserMembershipData();
+ userMembershipData.setID(groupID);
+ userMembershipData.setUserID(userID);
+
+ URI uri = uriInfo.getBaseUriBuilder()
+ .path(UserResource.class)
+ .path("{userID}/memberships/{groupID}")
+ .build(
+ URLEncoder.encode(userID, "UTF-8"),
+ URLEncoder.encode(groupID, "UTF-8"));
+
+ userMembershipData.setLink(new Link("self", uri));
+
+ return userMembershipData;
+ }
+
+ @Override
+ public UserMembershipCollection findUserMemberships(String userID, Integer start, Integer size) {
+ try {
+ start = start == null ? 0 : start;
+ size = size == null ? DEFAULT_SIZE : size;
+
+ if (userID == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+ throw new BadRequestException(getUserMessage("CMS_ADMIN_SRVLT_NULL_RS_ID", headers));
+ }
+
+ IUser user = userGroupManager.getUser(userID);
+
+ if (user == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_USER_NOT_EXIST"));
+ throw new UserNotFoundException(userID);
+ }
+
+ UserMembershipCollection response = new UserMembershipCollection();
+
+ Enumeration<IGroup> groups = userGroupManager.findGroupsByUser(user.getUserDN());
+
+ int i = 0;
+
+ // skip to the start of the page
+ for ( ; i<start && groups.hasMoreElements(); i++) groups.nextElement();
+
+ // return entries up to the page size
+ for ( ; i<start+size && groups.hasMoreElements(); i++) {
+ IGroup group = groups.nextElement();
+ response.addMembership(createUserMembershipData(userID, group.getName()));
+ }
+
+ // count the total entries
+ for ( ; groups.hasMoreElements(); i++) groups.nextElement();
+
+ 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 response;
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ throw new PKIException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public Response addUserMembership(String userID, String groupID) {
+ try {
+ GroupMemberData groupMemberData = new GroupMemberData();
+ groupMemberData.setID(userID);
+ groupMemberData.setGroupID(groupID);
+
+ GroupMemberProcessor processor = new GroupMemberProcessor(getLocale(headers));
+ processor.setUriInfo(uriInfo);
+ processor.addGroupMember(groupMemberData);
+
+ UserMembershipData userMembershipData = createUserMembershipData(userID, groupID);
+
+ return Response
+ .created(userMembershipData.getLink().getHref())
+ .entity(userMembershipData)
+ .type(MediaType.APPLICATION_XML)
+ .build();
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ throw new PKIException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public void removeUserMembership(String userID, String groupID) {
+ try {
+ GroupMemberProcessor processor = new GroupMemberProcessor(getLocale(headers));
+ processor.setUriInfo(uriInfo);
+ processor.removeGroupMember(groupID, userID);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ throw new PKIException(e.getMessage(), e);
+ }
+ }
+
+ public void log(int level, String message) {
+ log(ILogger.S_USRGRP, level, message);
+ }
+
+ public void auditAddUser(String id, UserData userData, String status) {
+ auditUser(OpDef.OP_ADD, id, getParams(userData), status);
+ }
+
+ public void auditModifyUser(String id, UserData userData, String status) {
+ auditUser(OpDef.OP_MODIFY, id, getParams(userData), status);
+ }
+
+ public void auditDeleteUser(String id, String status) {
+ auditUser(OpDef.OP_DELETE, id, null, status);
+ }
+
+ public void auditAddUserCert(String id, UserCertData userCertData, String status) {
+ auditUserCert(OpDef.OP_ADD, id, getParams(userCertData), status);
+ }
+
+ public void auditDeleteUserCert(String id, UserCertData userCertData, String status) {
+ auditUserCert(OpDef.OP_DELETE, id, getParams(userCertData), status);
+ }
+
+ public void auditUser(String type, String id, Map<String, String> params, String status) {
+ audit(IAuditor.LOGGING_SIGNED_AUDIT_CONFIG_ROLE, ScopeDef.SC_USERS, type, id, params, status);
+ }
+
+ public void auditUserCert(String type, String id, Map<String, String> params, String status) {
+ audit(IAuditor.LOGGING_SIGNED_AUDIT_CONFIG_ROLE, ScopeDef.SC_USER_CERTS, type, id, params, status);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/UsrGrpAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/UsrGrpAdminServlet.java
new file mode 100644
index 000000000..2cd337123
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/UsrGrpAdminServlet.java
@@ -0,0 +1,2313 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.admin;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.ldap.LDAPException;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.x509.X509CertImpl;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.InternalCertificate;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authorization.IAuthzSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.ICertPrettyPrint;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.password.IPasswordCheck;
+import com.netscape.certsrv.usrgrp.EUsrGrpException;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cmsutil.util.Cert;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * A class representing an administration servlet for
+ * User/Group Manager. It communicates with client
+ * SDK to allow remote administration of User/Group
+ * manager.
+ *
+ * This servlet will be registered to remote
+ * administration subsystem by usrgrp manager.
+ *
+ * @version $Revision$, $Date$
+ */
+public class UsrGrpAdminServlet extends AdminServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4341817607402387714L;
+ private final static String INFO = "UsrGrpAdminServlet";
+ private final static String RES_CA_GROUP = "certServer.ca.group";
+ private final static String RES_RA_GROUP = "certServer.ra.group";
+ private final static String RES_KRA_GROUP = "certServer.kra.group";
+ private final static String RES_OCSP_GROUP = "certServer.ocsp.group";
+ private final static String RES_TKS_GROUP = "certServer.tks.group";
+ private final static String SYSTEM_USER = "$System$";
+ // private final static String RES_GROUP = "root.common.goldfish";
+
+ private final static String BACK_SLASH = "\\";
+
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_ROLE =
+ "LOGGING_SIGNED_AUDIT_CONFIG_ROLE_3";
+
+ private IUGSubsystem mMgr = null;
+
+ private static String[] mMultiRoleGroupEnforceList = null;
+ private final static String MULTI_ROLE_ENABLE = "multiroles.enable";
+ private final static String MULTI_ROLE_ENFORCE_GROUP_LIST = "multiroles.false.groupEnforceList";
+
+ /**
+ * Constructs User/Group manager servlet.
+ */
+ public UsrGrpAdminServlet() {
+ super();
+ mAuthz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ);
+ }
+
+ /**
+ * Initializes this servlet.
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ mMgr = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Serves incoming User/Group management request.
+ */
+ public void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+
+ String scope = super.getParameter(req, Constants.OP_SCOPE);
+ String op = super.getParameter(req, Constants.OP_TYPE);
+
+ if (op == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_INVALID_PROTOCOL"));
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"),
+ null, resp);
+ return;
+ }
+
+ Locale clientLocale = super.getLocale(req);
+
+ try {
+ super.authenticate(req);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_FAIL_AUTHS"));
+
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHS_FAILED"),
+ null, resp);
+ return;
+ }
+
+ // authorization
+ // temporary test before servlets are exposed with authtoken
+ /*
+ SessionContext sc = SessionContext.getContext();
+ AuthToken authToken = (AuthToken) sc.get(SessionContext.AUTH_TOKEN);
+
+ AuthzToken authzTok = null;
+ CMS.debug("UserGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_CHECK_AUTHZ_SUB"));
+ // hardcoded for now .. just testing
+ try {
+ authzTok = mAuthz.authorize("DirAclAuthz", authToken, RES_GROUP, "read");
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_CALL_FAIL",e.toString()));
+ }
+ if (AuthzToken.AUTHZ_STATUS_FAIL.equals(authzTok.get(AuthzToken.TOKEN_AUTHZ_STATUS))) {
+ // audit would have been needed here if this weren't just a test...
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_FAIL_AUTHS"));
+
+ sendResponse(ERROR,
+ MessageFormatter.getLocalizedString(
+ getLocale(req),
+ AdminResources.class.getName(),
+ AdminResources.SRVLT_FAIL_AUTHS),
+ null, resp);
+ return;
+ }
+ */
+
+ try {
+ ISubsystem subsystem = CMS.getSubsystem("ca");
+ if (subsystem != null)
+ AUTHZ_RES_NAME = RES_CA_GROUP;
+ subsystem = CMS.getSubsystem("ra");
+ if (subsystem != null)
+ AUTHZ_RES_NAME = RES_RA_GROUP;
+ subsystem = CMS.getSubsystem("kra");
+ if (subsystem != null)
+ AUTHZ_RES_NAME = RES_KRA_GROUP;
+ subsystem = CMS.getSubsystem("ocsp");
+ if (subsystem != null)
+ AUTHZ_RES_NAME = RES_OCSP_GROUP;
+ subsystem = CMS.getSubsystem("tks");
+ if (subsystem != null)
+ AUTHZ_RES_NAME = RES_TKS_GROUP;
+ if (scope != null) {
+ if (scope.equals(ScopeDef.SC_USER_TYPE)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+
+ getUserType(req, resp);
+ return;
+ }
+
+ if (op.equals(OpDef.OP_READ)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_GROUPS)) {
+ findGroup(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_USERS)) {
+ findUser(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_USER_CERTS)) {
+ findUserCerts(req, resp, clientLocale);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_MODIFY)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_GROUPS)) {
+ modifyGroup(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_USERS)) {
+ modifyUser(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_USER_CERTS)) {
+ modifyUserCert(req, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_ADD)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_GROUPS)) {
+ addGroup(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_USERS)) {
+ addUser(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_USER_CERTS)) {
+ addUserCert(req, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_DELETE)) {
+ mOp = "modify";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_GROUPS)) {
+ removeGroup(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_USERS)) {
+ removeUser(req, resp);
+ return;
+ }
+ } else if (op.equals(OpDef.OP_SEARCH)) {
+ mOp = "read";
+ if ((mToken = super.authorize(req)) == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"),
+ null, resp);
+ return;
+ }
+ if (scope.equals(ScopeDef.SC_GROUPS)) {
+ findGroups(req, resp);
+ return;
+ } else if (scope.equals(ScopeDef.SC_USERS)) {
+ findUsers(req, resp);
+ return;
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_INVALID_OP_SCOPE"));
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"),
+ null, resp);
+ return;
+ }
+ }
+ } // if
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ sendResponse(ERROR, e.toString(getLocale(req)),
+ null, resp);
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ log(ILogger.LL_FAILURE, CMS.getLogMessage(" ADMIN_SRVLT_FAIL_PERFORM"));
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_PERFORM_FAILED"),
+ null, resp);
+ return;
+ }
+ }
+
+ private void getUserType(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String id = super.getParameter(req, Constants.RS_ID);
+ IUser user = mMgr.getUser(id);
+ String val = user.getUserType();
+
+ if (val == null || val.equals(""))
+ val = "noType";
+ NameValuePairs params = new NameValuePairs();
+
+ params.put(Constants.PR_USER_TYPE, val);
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * Searches for users in LDAP directory. List uids only
+ *
+ * Request/Response Syntax:
+ * http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ */
+ private synchronized void findUsers(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ NameValuePairs params = new NameValuePairs();
+
+ Enumeration<IUser> e = null;
+
+ try {
+ e = mMgr.listUsers("*");
+ } catch (Exception ex) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_INTERNAL_ERROR"), null, resp);
+ return;
+ }
+
+ StringBuffer sb = new StringBuffer();
+ int i = 0;
+
+ while (e.hasMoreElements()) {
+ IUser user = e.nextElement();
+
+ if (i > 0) {
+ sb.append(";");
+ sb.append(user.getUserID());
+ sb.append(":");
+ sb.append(user.getFullName());
+ } else {
+ sb.append(user.getUserID());
+ sb.append(":");
+ sb.append(user.getFullName());
+ }
+ i++;
+ }
+ params.put("userInfo", sb.toString());
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * List user information. Certificates covered in a separate
+ * protocol for findUserCerts(). List of group memberships are
+ * also provided.
+ *
+ * Request/Response Syntax:
+ * http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ */
+ private synchronized void findUser(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ //get id first
+ String id = super.getParameter(req, Constants.RS_ID);
+
+ if (id == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ NameValuePairs params = new NameValuePairs();
+
+ IUser user = null;
+
+ try {
+ user = mMgr.getUser(id);
+ } catch (Exception e) {
+ e.printStackTrace();
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_INTERNAL_ERROR"), null, resp);
+ return;
+ }
+
+ if (user != null) {
+ params.put(Constants.PR_USER_FULLNAME, user.getFullName());
+ params.put(Constants.PR_USER_EMAIL, user.getEmail());
+ params.put(Constants.PR_USER_PHONE, user.getPhone());
+ params.put(Constants.PR_USER_STATE, user.getState());
+
+ // get list of groups, and get a list of those that this
+ // uid belongs to
+ Enumeration<IGroup> e = null;
+
+ try {
+ e = mMgr.findGroups("*");
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_INTERNAL_ERROR"), null, resp);
+ return;
+ }
+
+ StringBuffer grpString = new StringBuffer();
+
+ while (e.hasMoreElements()) {
+ IGroup group = e.nextElement();
+
+ if (group.isMember(id) == true) {
+ if (grpString.length() != 0) {
+ grpString.append(",");
+ }
+ grpString.append(group.getGroupID());
+ }
+ }
+
+ params.put(Constants.PR_USER_GROUP, grpString.toString());
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_USER_NOT_EXIST"));
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_USER_NOT_EXIST"), null, resp);
+ return;
+ }
+
+ /**
+ * List user certificate(s)
+ *
+ * Request/Response Syntax:
+ * http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ */
+ private synchronized void findUserCerts(HttpServletRequest req,
+ HttpServletResponse resp, Locale clientLocale)
+ throws ServletException,
+ IOException, EBaseException {
+
+ //get id first
+ String id = super.getParameter(req, Constants.RS_ID);
+
+ if (id == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ NameValuePairs params = new NameValuePairs();
+
+ IUser user = null;
+
+ try {
+ user = mMgr.getUser(id);
+ } catch (Exception e) {
+ e.printStackTrace();
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_USER_NOT_EXIST"), null, resp);
+ return;
+ }
+
+ if (user == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_USER_NOT_EXIST"));
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_USER_NOT_EXIST"), null, resp);
+ return;
+ }
+
+ X509Certificate[] certs =
+ user.getX509Certificates();
+
+ if (certs != null) {
+ for (int i = 0; i < certs.length; i++) {
+ ICertPrettyPrint print = CMS.getCertPrettyPrint(certs[i]);
+
+ // add base64 encoding
+ String base64 = CMS.getEncodedCert(certs[i]);
+
+ // pretty print certs
+ params.put(getCertificateString(certs[i]),
+ print.toString(clientLocale) + "\n" + base64);
+ }
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ /**
+ * Converts certificate into string format.
+ */
+ protected String getCertificateString(X509Certificate cert) {
+ if (cert == null) {
+ return null;
+ }
+
+ // note that it did not represent a certificate fully
+ return cert.getVersion() + ";" + cert.getSerialNumber().toString() +
+ ";" + cert.getIssuerDN() + ";" + cert.getSubjectDN();
+ }
+
+ /**
+ * Searchess for groups in LDAP server
+ *
+ * Request/Response Syntax:
+ * http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#group
+ */
+ private synchronized void findGroups(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+
+ Enumeration<IGroup> e = null;
+
+ try {
+ e = mMgr.listGroups("*");
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_INTERNAL_ERROR"), null, resp);
+ return;
+ }
+
+ while (e.hasMoreElements()) {
+ IGroup group = e.nextElement();
+ String desc = group.getDescription();
+
+ if (desc != null) {
+ params.put(group.getGroupID(), desc);
+ } else {
+ params.put(group.getGroupID(), "");
+ }
+ }
+
+ sendResponse(SUCCESS, null, params, resp);
+ }
+
+ /**
+ * finds a group
+ * Request/Response Syntax:
+ * http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ */
+ private synchronized void findGroup(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+ NameValuePairs params = new NameValuePairs();
+
+ //get id first
+ String id = super.getParameter(req, Constants.RS_ID);
+
+ if (id == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ Enumeration<IGroup> e = null;
+
+ try {
+ e = mMgr.findGroups(id);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_INTERNAL_ERROR"), null, resp);
+ return;
+ }
+
+ if (e.hasMoreElements()) {
+ IGroup group = e.nextElement();
+
+ params.put(Constants.PR_GROUP_GROUP, group.getGroupID());
+ params.put(Constants.PR_GROUP_DESC,
+ group.getDescription());
+
+ Enumeration<String> members = group.getMemberNames();
+ StringBuffer membersString = new StringBuffer();
+
+ if (members != null) {
+ while (members.hasMoreElements()) {
+ if (membersString.length() != 0) {
+ membersString.append(", ");
+ }
+
+ String mn = members.nextElement();
+
+ membersString.append(mn);
+ }
+ }
+
+ params.put(Constants.PR_GROUP_USER, membersString.toString());
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_GROUP_NOT_EXIST"));
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_GROUP_NOT_EXIST"), null, resp);
+ return;
+
+ }
+ }
+
+ /**
+ * Adds a new user to LDAP server
+ * <P>
+ *
+ * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void addUser(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = super.getParameter(req, Constants.RS_ID);
+
+ if (id == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ if (id.indexOf(BACK_SLASH) != -1) {
+ // backslashes (BS) are not allowed
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_RS_ID_BS"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_RS_ID_BS"),
+ null, resp);
+ return;
+ }
+
+ if (id.equals(SYSTEM_USER)) {
+ // backslashes (BS) are not allowed
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_SPECIAL_ID", id));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_SPECIAL_ID", id),
+ null, resp);
+ return;
+ }
+
+ IUser user = mMgr.createUser(id);
+ String fname = super.getParameter(req, Constants.PR_USER_FULLNAME);
+
+ if ((fname == null) || (fname.length() == 0)) {
+ String msg = CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED_1", "full name");
+
+ log(ILogger.LL_FAILURE, msg);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, msg, null, resp);
+ return;
+ } else
+ user.setFullName(fname);
+
+ String email = super.getParameter(req, Constants.PR_USER_EMAIL);
+
+ if (email != null) {
+ user.setEmail(email);
+ } else {
+ user.setEmail("");
+ }
+ String pword = super.getParameter(req, Constants.PR_USER_PASSWORD);
+
+ if (pword != null && !pword.equals("")) {
+ IPasswordCheck passwdCheck = CMS.getPasswordChecker();
+
+ if (!passwdCheck.isGoodPassword(pword)) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ throw new EUsrGrpException(passwdCheck.getReason(pword));
+
+ //UsrGrpResources.BAD_PASSWD);
+ }
+
+ user.setPassword(pword);
+ } else {
+ user.setPassword("");
+ }
+ String phone = super.getParameter(req, Constants.PR_USER_PHONE);
+
+ if (phone != null) {
+ user.setPhone(phone);
+ } else {
+ user.setPhone("");
+ }
+ String userType = super.getParameter(req, Constants.PR_USER_TYPE);
+
+ if (userType != null) {
+ user.setUserType(userType);
+ } else {
+ user.setUserType("");
+ }
+ String userState = super.getParameter(req, Constants.PR_USER_STATE);
+
+ if (userState != null) {
+ user.setState(userState);
+ }
+
+ try {
+ mMgr.addUser(user);
+
+ // if group is specified, add user to group
+ String groupName = super.getParameter(req,
+ Constants.PR_USER_GROUP);
+
+ if (groupName != null) {
+ Enumeration<IGroup> e = null;
+
+ try {
+ e = mMgr.findGroups(groupName);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED"), null, resp);
+ return;
+ }
+
+ if (e.hasMoreElements()) {
+ IGroup group = e.nextElement();
+
+ group.addMemberName(id);
+ try {
+ mMgr.modifyGroup(group);
+ } catch (Exception ex) {
+ log(ILogger.LL_FAILURE, ex.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED"), null, resp);
+ return;
+ }
+ }
+ // for audit log
+ SessionContext sContext = SessionContext.getContext();
+ String adminId = (String) sContext.get(SessionContext.USER_ID);
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP,
+ AuditFormat.LEVEL, AuditFormat.ADDUSERGROUPFORMAT,
+ new Object[] { adminId, id, groupName }
+ );
+ }
+
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ } catch (EUsrGrpException e) {
+ log(ILogger.LL_FAILURE, e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ if (user.getUserID() == null) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED_1", "uid"), null, resp);
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED"), null, resp);
+ }
+ return;
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_ADD_USER_FAIL", e.toString()));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED"), null, resp);
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED"), null, resp);
+ return;
+ }
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * Adds a certificate to a user
+ * <P>
+ *
+ * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void addUserCert(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = super.getParameter(req, Constants.RS_ID);
+
+ if (id == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ IUser user = mMgr.createUser(id);
+ String certS = super.getParameter(req, Constants.PR_USER_CERT);
+ String certsString = Cert.stripBrackets(certS);
+
+ // no cert is a success
+ if (certsString == null) {
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ // only one cert added per operation
+ X509Certificate certs[] = null;
+
+ // Base64 decode cert
+
+ try {
+ byte bCert[] = Utils.base64decode(certsString);
+ X509Certificate cert = new X509CertImpl(bCert);
+
+ certs = new X509Certificate[1];
+ certs[0] = cert;
+ } catch (CertificateException e) {
+ // cert chain direction
+ boolean assending = true;
+
+ // could it be a pkcs7 blob?
+ CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_IS_PK_BLOB"));
+ byte p7Cert[] = Utils.base64decode(certsString);
+
+ try {
+ CryptoManager manager = CryptoManager.getInstance();
+
+ PKCS7 pkcs7 = new PKCS7(p7Cert);
+
+ X509Certificate p7certs[] = pkcs7.getCertificates();
+
+ if (p7certs.length == 0) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_ERROR"), null, resp);
+ return;
+ }
+ // fix for 370099 - cert ordering can not be assumed
+ // find out the ordering ...
+ certs = new X509Certificate[p7Cert.length];
+
+ // self-signed and alone? take it. otherwise test
+ // the ordering
+ if (p7certs[0].getSubjectDN().toString().equals(
+ p7certs[0].getIssuerDN().toString()) &&
+ (p7certs.length == 1)) {
+ certs[0] = p7certs[0];
+ CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_SINGLE_CERT_IMPORT"));
+ } else if (p7certs[0].getIssuerDN().toString().equals(p7certs[1].getSubjectDN().toString())) {
+ certs[0] = p7certs[0];
+ CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_CERT_CHAIN_ACEND_ORD"));
+ } else if (p7certs[1].getIssuerDN().toString().equals(p7certs[0].getSubjectDN().toString())) {
+ assending = false;
+ CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_CERT_CHAIN_DESC_ORD"));
+ certs[0] = p7certs[p7certs.length - 1];
+ } else {
+ // not a chain, or in random order
+ CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_CERT_BAD_CHAIN"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_ERROR"), null, resp);
+ return;
+ }
+
+ CMS.debug("UsrGrpAdminServlet: "
+ + CMS.getLogMessage("ADMIN_SRVLT_CHAIN_STORED_DB", String.valueOf(p7certs.length)));
+
+ int j = 0;
+ int jBegin = 0;
+ int jEnd = 0;
+
+ if (assending == true) {
+ jBegin = 1;
+ jEnd = p7certs.length;
+ } else {
+ jBegin = 0;
+ jEnd = p7certs.length - 1;
+ }
+ // store the chain into cert db, except for the user cert
+ for (j = jBegin; j < jEnd; j++) {
+ CMS.debug("UsrGrpAdminServlet: "
+ + CMS.getLogMessage("ADMIN_SRVLT_CERT_IN_CHAIN", String.valueOf(j),
+ String.valueOf(p7certs[j].getSubjectDN())));
+ org.mozilla.jss.crypto.X509Certificate leafCert =
+ null;
+
+ leafCert =
+ manager.importCACertPackage(p7certs[j].getEncoded());
+
+ if (leafCert == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_LEAF_CERT_NULL"));
+ } else {
+ CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_LEAF_CERT_NON_NULL"));
+ }
+
+ if (leafCert instanceof InternalCertificate) {
+ ((InternalCertificate) leafCert).setSSLTrust(
+ InternalCertificate.VALID_CA |
+ InternalCertificate.TRUSTED_CA |
+ InternalCertificate.TRUSTED_CLIENT_CA);
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NOT_INTERNAL_CERT",
+ String.valueOf(p7certs[j].getSubjectDN())));
+ }
+ }
+
+ /*
+ } catch (CryptoManager.UserCertConflictException ex) {
+ // got a "user cert" in the chain, most likely the CA
+ // cert of this instance, which has a private key. Ignore
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_PKS7_IGNORED", ex.toString()));
+ */
+ } catch (Exception ex) {
+ //-----
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_CERT_ERROR", ex.toString()));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_ERROR"), null, resp);
+ return;
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_CERT_O_ERROR", e.toString()));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_O_ERROR"), null, resp);
+ return;
+ }
+
+ try {
+ CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_BEFORE_VALIDITY"));
+ certs[0].checkValidity(); // throw exception if fails
+
+ user.setX509Certificates(certs);
+ mMgr.addUserCert(user);
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+
+ } catch (CertificateExpiredException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_ADD_CERT_EXPIRED",
+ String.valueOf(certs[0].getSubjectDN())));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_EXPIRED"), null, resp);
+ return;
+ } catch (CertificateNotYetValidException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_CERT_NOT_YET_VALID",
+ String.valueOf(certs[0].getSubjectDN())));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_NOT_YET_VALID"), null, resp);
+ return;
+
+ } catch (LDAPException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ if (e.getLDAPResultCode() == LDAPException.ATTRIBUTE_OR_VALUE_EXISTS) {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_USER_CERT_EXISTS"), null, resp);
+ } else {
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_MOD_FAILED"), null, resp);
+ }
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_MOD_FAILED"), null, resp);
+ return;
+ }
+ // } catch( EBaseException eAudit1 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * Removes a certificate for a user
+ * <P>
+ *
+ * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ * <P>
+ *
+ * In this method, "certDN" is actually a combination of version, serialNumber, issuerDN, and SubjectDN.
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void modifyUserCert(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String id = super.getParameter(req, Constants.RS_ID);
+
+ if (id == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ IUser user = mMgr.createUser(id);
+ String certDN = super.getParameter(req, Constants.PR_USER_CERT);
+
+ // no certDN is a success
+ if (certDN == null) {
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ }
+
+ user.setCertDN(certDN);
+ try {
+ mMgr.removeUserCert(user);
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_MOD_FAILED"), null, resp);
+ return;
+ }
+ // } catch( EBaseException eAudit1 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * removes a user. user not removed if belongs to any group
+ * (Administrators should remove the user from "uniquemember" of
+ * any group he/she belongs to before trying to remove the user
+ * itself.
+ * <P>
+ *
+ * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void removeUser(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ //get id first
+ String id = super.getParameter(req, Constants.RS_ID);
+ boolean mustDelete = false;
+ int index = 0;
+
+ if ((index = id.lastIndexOf(":true")) != -1) {
+ id = id.substring(0, index);
+ mustDelete = true;
+ }
+
+ if (id == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+ // get list of groups, and see if uid belongs to any
+ Enumeration<IGroup> e = null;
+
+ try {
+ e = mMgr.findGroups("*");
+ } catch (Exception ex) {
+ ex.printStackTrace();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_INTERNAL_ERROR"), null, resp);
+ return;
+ }
+
+ while (e.hasMoreElements()) {
+ IGroup group = e.nextElement();
+
+ if (group.isMember(id) == true) {
+ if (mustDelete) {
+ mMgr.removeUserFromGroup(group, id);
+ } else {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_FAIL_USER_RMV_G"),
+ null, resp);
+ return;
+ }
+ }
+ }
+
+ // comes out clean of group membership...now remove user
+ try {
+ mMgr.removeUser(id);
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ } catch (Exception ex) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_FAIL_USER_RMV"), null, resp);
+ return;
+ }
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * Adds a new group in local scope.
+ * <P>
+ *
+ * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#group
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void addGroup(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ //get id first
+ String id = super.getParameter(req, Constants.RS_ID);
+
+ if (id == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ IGroup group = mMgr.createGroup(id);
+ String members = super.getParameter(req,
+ Constants.PR_GROUP_USER);
+ String desc = super.getParameter(req,
+ Constants.PR_GROUP_DESC);
+
+ if (desc != null) {
+ group.set("description", desc);
+ } else {
+ group.set("description", "");
+ }
+
+ if (members != null) {
+ StringTokenizer st = new StringTokenizer(members, ",");
+
+ while (st.hasMoreTokens()) {
+ group.addMemberName(st.nextToken());
+ }
+ }
+
+ // allow adding a group with no members
+ try {
+ mMgr.addGroup(group);
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ } catch (Exception e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_GROUP_ADD_FAILED"),
+ null, resp);
+ return;
+ }
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * removes a group
+ * <P>
+ *
+ * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#group
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void removeGroup(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ //get id first
+ String id = super.getParameter(req, Constants.RS_ID);
+
+ if (id == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ // if fails, let the exception fall through
+ mMgr.removeGroup(id);
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ /**
+ * modifies a group
+ * <P>
+ *
+ * last person of the super power group "Certificate Server Administrators" can never be removed.
+ * <P>
+ *
+ * http://warp.mcom.com/server/certificate/columbo/design/ ui/admin-protocol-definition.html#group
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void modifyGroup(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ //get id first
+ String id = super.getParameter(req, Constants.RS_ID);
+
+ if (id == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ IGroup group = mMgr.createGroup(id);
+
+ String desc = super.getParameter(req,
+ Constants.PR_GROUP_DESC);
+
+ if (desc != null) {
+ group.set("description", desc);
+ }
+
+ String members = super.getParameter(req, Constants.PR_GROUP_USER);
+
+ if (members != null) {
+ StringTokenizer st = new StringTokenizer(members, ",");
+
+ String groupName = group.getName();
+ boolean multiRole = true;
+
+ try {
+ multiRole = mConfig.getBoolean(MULTI_ROLE_ENABLE);
+ } catch (Exception eee) {
+ }
+ while (st.hasMoreTokens()) {
+ String memberName = st.nextToken();
+ if (multiRole) {
+ group.addMemberName(memberName);
+ } else {
+ if (isGroupInMultiRoleEnforceList(groupName)) {
+ if (!isDuplicate(groupName, memberName)) {
+ group.addMemberName(memberName);
+ } else {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_DUPLICATE_ROLES", memberName));
+ }
+ } else {
+ group.addMemberName(memberName);
+ }
+ }
+ }
+ }
+
+ // allow adding a group with no members, except "Certificate
+ // Server Administrators"
+ try {
+ mMgr.modifyGroup(group);
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_GROUP_MODIFY_FAILED"),
+ null, resp);
+ return;
+ }
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ private boolean isGroupInMultiRoleEnforceList(String groupName) {
+ String groupList = null;
+
+ if (groupName == null || groupName.equals("")) {
+ return true;
+ }
+ if (mMultiRoleGroupEnforceList == null) {
+ try {
+ groupList = mConfig.getString(MULTI_ROLE_ENFORCE_GROUP_LIST);
+ } catch (Exception e) {
+ }
+
+ if (groupList != null && !groupList.equals("")) {
+ mMultiRoleGroupEnforceList = groupList.split(",");
+ for (int j = 0; j < mMultiRoleGroupEnforceList.length; j++) {
+ mMultiRoleGroupEnforceList[j] = mMultiRoleGroupEnforceList[j].trim();
+ }
+ }
+ }
+
+ if (mMultiRoleGroupEnforceList == null)
+ return true;
+
+ for (int i = 0; i < mMultiRoleGroupEnforceList.length; i++) {
+ if (groupName.equals(mMultiRoleGroupEnforceList[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isDuplicate(String groupName, String memberName) {
+ Enumeration<IGroup> groups = null;
+
+ // Let's not mess with users that are already a member of this group
+ boolean isMember = false;
+ try {
+ isMember = mMgr.isMemberOf(memberName, groupName);
+ } catch (Exception e) {
+ }
+
+ if (isMember == true) {
+ return false;
+ }
+ try {
+ groups = mMgr.listGroups("*");
+ while (groups.hasMoreElements()) {
+ IGroup group = groups.nextElement();
+ String name = group.getName();
+ Enumeration<IGroup> g = mMgr.findGroups(name);
+ IGroup g1 = g.nextElement();
+ if (!name.equals(groupName)) {
+ if (isGroupInMultiRoleEnforceList(name)) {
+ Enumeration<String> members = g1.getMemberNames();
+ while (members.hasMoreElements()) {
+ String m1 = members.nextElement();
+ if (m1.equals(memberName))
+ return true;
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ }
+
+ return false;
+ }
+
+ /**
+ * Modifies an existing user in local scope.
+ * <P>
+ *
+ * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/
+ * ui/admin-protocol-definition.html#user-admin
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under
+ * users/groups)
+ * </ul>
+ *
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @exception ServletException a servlet error has occurred
+ * @exception IOException an input/output error has occurred
+ * @exception EBaseException an error has occurred
+ */
+ private synchronized void modifyUser(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException,
+ IOException, EBaseException {
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ //get id first
+ String id = super.getParameter(req, Constants.RS_ID);
+
+ if (id == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
+ null, resp);
+ return;
+ }
+
+ IUser user = mMgr.createUser(id);
+ String fname = super.getParameter(req, Constants.PR_USER_FULLNAME);
+
+ if ((fname == null) || (fname.length() == 0)) {
+ String msg =
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_MOD_FAILED", "full name");
+
+ log(ILogger.LL_FAILURE, msg);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR, msg, null, resp);
+ return;
+ } else
+ user.setFullName(fname);
+
+ String email = super.getParameter(req, Constants.PR_USER_EMAIL);
+
+ if (email != null) {
+ user.setEmail(email);
+ }
+ String pword = super.getParameter(req, Constants.PR_USER_PASSWORD);
+
+ if ((pword != null) && (!pword.equals(""))) {
+ IPasswordCheck passwdCheck = CMS.getPasswordChecker();
+
+ if (!passwdCheck.isGoodPassword(pword)) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ throw new EUsrGrpException(passwdCheck.getReason(pword));
+
+ //UsrGrpResources.BAD_PASSWD);
+ }
+
+ user.setPassword(pword);
+ }
+ String phone = super.getParameter(req, Constants.PR_USER_PHONE);
+
+ if (phone != null) {
+ user.setPhone(phone);
+ }
+
+ String userState = super.getParameter(req, Constants.PR_USER_STATE);
+ if (userState != null) {
+ user.setState(userState);
+ }
+
+ try {
+ mMgr.modifyUser(user);
+ NameValuePairs params = new NameValuePairs();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(SUCCESS, null, params, resp);
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ sendResponse(ERROR,
+ CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_MOD_FAILED"), null, resp);
+ return;
+ }
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ } catch (IOException eAudit2) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams(req));
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit2;
+ // } catch( ServletException eAudit3 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditParams( req ) );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit3;
+ }
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_USRGRP,
+ level, "UsrGrpAdminServlet: " + msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
new file mode 100644
index 000000000..56a37b34d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
@@ -0,0 +1,2264 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.base;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Random;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.pkcs.ContentInfo;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.pkcs.SignerInfo;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.X509CertImpl;
+
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.apps.ICommandQueue;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.IAuthzSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.cms.servlet.common.AuthCredentials;
+import com.netscape.cms.servlet.common.CMSFileLoader;
+import com.netscape.cms.servlet.common.CMSGateway;
+import com.netscape.cms.servlet.common.CMSLoadTemplate;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cms.servlet.common.GenErrorTemplateFiller;
+import com.netscape.cms.servlet.common.GenPendingTemplateFiller;
+import com.netscape.cms.servlet.common.GenRejectedTemplateFiller;
+import com.netscape.cms.servlet.common.GenSuccessTemplateFiller;
+import com.netscape.cms.servlet.common.GenSvcPendingTemplateFiller;
+import com.netscape.cms.servlet.common.GenUnexpectedErrorTemplateFiller;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+import com.netscape.cms.servlet.common.ServletUtils;
+import com.netscape.cmsutil.util.Utils;
+import com.netscape.cmsutil.xml.XMLObject;
+
+/**
+ * This is the base class of all CS servlet.
+ *
+ * @version $Revision$, $Date$
+ */
+public abstract class CMSServlet extends HttpServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3886300199374147160L;
+ // servlet init params
+ // xxxx todo:Should enforce init param value checking!
+ public final static String SUCCESS = "0";
+ public final static String FAILURE = "1";
+ public final static String AUTH_FAILURE = "2";
+
+ public final static String PROP_ID = "ID";
+ public final static String PROP_AUTHORITY = "authority";
+ public final static String PROP_AUTHORITYID = "authorityId";
+ public final static String PROP_AUTHMGR = "AuthMgr";
+ public final static String PROP_CLIENTAUTH = "GetClientCert";
+ public final static String PROP_RESOURCEID = "resourceID";
+
+ public final static String AUTHZ_SRC_LDAP = "ldap";
+ public final static String AUTHZ_SRC_TYPE = "sourceType";
+ public final static String AUTHZ_CONFIG_STORE = "authz";
+ public final static String AUTHZ_SRC_XML = "web.xml";
+ public final static String PROP_AUTHZ_MGR = "AuthzMgr";
+ public final static String PROP_ACL = "ACLinfo";
+ public final static String AUTHZ_MGR_BASIC = "BasicAclAuthz";
+ public final static String AUTHZ_MGR_LDAP = "DirAclAuthz";
+ private final static String HDR_LANG = "accept-language";
+
+ // final error message - if error and exception templates don't work
+ // send out this text string directly to output.
+
+ public final static String PROP_FINAL_ERROR_MSG = "finalErrorMsg";
+ public final static String ERROR_MSG_TOKEN = "$ERROR_MSG";
+ public final static String FINAL_ERROR_MSG =
+ "<HTML>\n" +
+ "<BODY BGCOLOR=white>\n" +
+ "<P>\n" +
+ "The Certificate System has encountered " +
+ "an unrecoverable error.\n" +
+ "<P>\n" +
+ "Error Message:<BR>\n" +
+ "<I>$ERROR_MSG</I>\n" +
+ "<P>\n" +
+ "Please contact your local administrator for assistance.\n" +
+ "</BODY>\n" +
+ "</HTML>\n";
+
+ // properties from configuration.
+
+ protected final static String PROP_UNAUTHORIZED_TEMPLATE = "unauthorizedTemplate";
+ protected final static String UNAUTHORIZED_TEMPLATE = "/GenUnauthorized.template";
+ protected final static String PROP_SUCCESS_TEMPLATE = "successTemplate";
+ protected final static String SUCCESS_TEMPLATE = "/GenSuccess.template";
+ protected final static String PROP_PENDING_TEMPLATE = "pendingTemplate";
+ protected final static String PENDING_TEMPLATE = "/GenPending.template";
+ protected final static String PROP_SVC_PENDING_TEMPLATE = "svcpendingTemplate";
+ protected final static String SVC_PENDING_TEMPLATE = "/GenSvcPending.template";
+ protected final static String PROP_REJECTED_TEMPLATE = "rejectedTemplate";
+ protected final static String REJECTED_TEMPLATE = "/GenRejected.template";
+ protected final static String PROP_ERROR_TEMPLATE = "errorTemplate";
+ protected final static String ERROR_TEMPLATE = "/GenError.template";
+ protected final static String PROP_EXCEPTION_TEMPLATE = "unexpectedErrorTemplate";
+ protected final static String EXCEPTION_TEMPLATE = "/GenUnexpectedError.template";
+
+ private final static String PROP_UNAUTHOR_TEMPLATE_FILLER = "unauthorizedTemplateFiller";
+ protected final static String PROP_SUCCESS_TEMPLATE_FILLER = "successTemplateFiller";
+ private final static String PROP_ERROR_TEMPLATE_FILLER = "errorTemplateFiller";
+ private final static String PROP_PENDING_TEMPLATE_FILLER = "pendingTemplateFiller";
+ private final static String PROP_SVC_PENDING_TEMPLATE_FILLER = "svcpendingTemplateFiller";
+ private final static String PROP_REJECTED_TEMPLATE_FILLER = "rejectedTemplateFiller";
+ private final static String PROP_EXCEPTION_TEMPLATE_FILLER = "exceptionTemplateFiller";
+
+ protected final static String RA_AGENT_GROUP = "Registration Manager Agents";
+ protected final static String CA_AGENT_GROUP = "Certificate Manager Agents";
+ protected final static String KRA_AGENT_GROUP = "Data Recovery Manager Agents";
+ protected final static String OCSP_AGENT_GROUP = "Online Certificate Status Manager Agents";
+ protected final static String TRUSTED_RA_GROUP = "Trusted Managers";
+ protected final static String ADMIN_GROUP = "Administrators";
+
+ // default http params NOT to save in request.(config values added to list )
+ private static final String PROP_DONT_SAVE_HTTP_PARAMS = "dontSaveHttpParams";
+ private static final String[] DONT_SAVE_HTTP_PARAMS = { "pwd", "password", "passwd",
+ "challengePassword", "confirmChallengePassword" };
+
+ // default http headers to save in request. (config values added to list)
+ private static final String PROP_SAVE_HTTP_HEADERS = "saveHttpHeaders";
+ private static final String[] SAVE_HTTP_HEADERS = { "accept-language", "user-agent", };
+
+ // request prefixes to distinguish from other request attributes.
+ public static final String PFX_HTTP_HEADER = "HTTP_HEADER";
+ public static final String PFX_HTTP_PARAM = "HTTP_PARAM";
+ public static final String PFX_AUTH_TOKEN = "AUTH_TOKEN";
+
+ /* input http params */
+ protected final static String AUTHMGR_PARAM = "authenticator";
+
+ /* fixed credential passed to auth managers */
+ protected final static String CERT_AUTH_CRED = "sslClientCert";
+
+ public static final String CERT_ATTR =
+ "javax.servlet.request.X509Certificate";
+
+ // members.
+
+ protected ServletConfig servletConfig;
+
+ protected boolean mRenderResult = true;
+ protected String mFinalErrorMsg = FINAL_ERROR_MSG;
+ protected Hashtable<Integer, CMSLoadTemplate> mTemplates = new Hashtable<Integer, CMSLoadTemplate>();
+
+ protected ServletConfig mServletConfig = null;
+ protected ServletContext mServletContext = null;
+ private CMSFileLoader mFileLoader = null;
+
+ protected Vector<String> mDontSaveHttpParams = new Vector<String>();
+ protected Vector<String> mSaveHttpHeaders = new Vector<String>();
+
+ protected String mId = null;
+ protected IConfigStore mConfig = null;
+
+ // the authority, RA, CA, KRA this servlet is serving.
+ protected IAuthority mAuthority = null;
+ protected ICertificateAuthority certAuthority;
+ protected IRequestQueue mRequestQueue = null;
+
+ // system logger.
+ protected ILogger mLogger = CMS.getLogger();
+ protected int mLogCategory = ILogger.S_OTHER;
+ private MessageDigest mSHADigest = null;
+
+ protected String mGetClientCert = "false";
+ protected String mAuthMgr = null;
+ protected IAuthzSubsystem mAuthz = null;
+
+ protected String mAclMethod = null;
+ protected String mAuthzResourceName = null;
+
+ protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+ protected String mOutputTemplatePath = null;
+ private IUGSubsystem mUG = (IUGSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+
+ private final static String LOGGING_SIGNED_AUDIT_AUTH_FAIL =
+ "LOGGING_SIGNED_AUDIT_AUTH_FAIL_4";
+ private final static String LOGGING_SIGNED_AUDIT_AUTH_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_AUTH_SUCCESS_3";
+ private final static String LOGGING_SIGNED_AUDIT_AUTHZ_FAIL =
+ "LOGGING_SIGNED_AUDIT_AUTHZ_FAIL_4";
+ private final static String LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS_4";
+ private final static String LOGGING_SIGNED_AUDIT_ROLE_ASSUME =
+ "LOGGING_SIGNED_AUDIT_ROLE_ASSUME_3";
+
+ public CMSServlet() {
+ }
+
+ public static Hashtable<String, String> toHashtable(HttpServletRequest req) {
+ Hashtable<String, String> httpReqHash = new Hashtable<String, String>();
+ Enumeration<?> names = req.getParameterNames();
+
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+
+ httpReqHash.put(name, req.getParameter(name));
+ }
+ return httpReqHash;
+ }
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+
+ this.servletConfig = sc;
+
+ mAuthz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ);
+ mId = sc.getInitParameter(PROP_ID);
+
+ try {
+ mAclMethod = ServletUtils.initializeAuthz(sc, mAuthz, mId);
+ } catch (ServletException e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ throw e;
+ }
+
+ mConfig = CMS.getConfigStore().getSubStore(CMSGateway.PROP_CMSGATEWAY);
+ mServletConfig = sc;
+ mServletContext = sc.getServletContext();
+ mFileLoader = new CMSFileLoader();
+
+ mGetClientCert = sc.getInitParameter(PROP_CLIENTAUTH);
+ mAuthMgr = sc.getInitParameter(PROP_AUTHMGR);
+ mAuthzResourceName = sc.getInitParameter(PROP_RESOURCEID);
+ mOutputTemplatePath = sc.getInitParameter("templatePath");
+
+ String authority = sc.getInitParameter(PROP_AUTHORITY);
+ if (authority == null) {
+ authority = sc.getInitParameter(PROP_AUTHORITYID);
+ }
+
+ if (authority != null) {
+ mAuthority = (IAuthority) CMS.getSubsystem(authority);
+ if (mAuthority instanceof ICertificateAuthority)
+ certAuthority = (ICertificateAuthority) mAuthority;
+ }
+ if (mAuthority != null)
+ mRequestQueue = mAuthority.getRequestQueue();
+
+ // set default templates.
+ setDefaultTemplates(sc);
+
+ // for logging to the right authority category.
+ if (mAuthority == null) {
+ mLogCategory = ILogger.S_OTHER;
+ } else {
+ if (mAuthority instanceof ICertificateAuthority)
+ mLogCategory = ILogger.S_CA;
+ else if (mAuthority instanceof IRegistrationAuthority)
+ mLogCategory = ILogger.S_RA;
+ else if (mAuthority instanceof IKeyRecoveryAuthority)
+ mLogCategory = ILogger.S_KRA;
+ else
+ mLogCategory = ILogger.S_OTHER;
+ }
+
+ try {
+ // get final error message.
+ // used when templates can't even be loaded.
+ String eMsg =
+ sc.getInitParameter(PROP_FINAL_ERROR_MSG);
+
+ if (eMsg != null)
+ mFinalErrorMsg = eMsg;
+
+ // get any configured templates.
+ Enumeration<CMSLoadTemplate> templs = mTemplates.elements();
+
+ while (templs.hasMoreElements()) {
+ CMSLoadTemplate templ = templs.nextElement();
+
+ if (templ == null || templ.mPropName == null) {
+ continue;
+ }
+ String tName =
+ sc.getInitParameter(templ.mPropName);
+
+ if (tName != null)
+ templ.mTemplateName = tName;
+ String fillerName =
+ sc.getInitParameter(templ.mFillerPropName);
+
+ if (fillerName != null) {
+ ICMSTemplateFiller filler = newFillerObject(fillerName);
+
+ if (filler != null)
+ templ.mFiller = filler;
+ }
+ }
+
+ // get http params NOT to store in a IRequest and
+ // get http headers TO store in a IRequest.
+ getDontSaveHttpParams(sc);
+ getSaveHttpHeaders(sc);
+ } catch (Exception e) {
+ // should never occur since we provide defaults above.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_CONF_TEMP_PARAMS",
+ e.toString()));
+ throw new ServletException(e.toString());
+ }
+
+ try {
+ mSHADigest = MessageDigest.getInstance("SHA1");
+ } catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_CONF_TEMP_PARAMS",
+ e.toString()));
+ throw new ServletException(e.toString());
+ }
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ public String getAuthMgr() {
+ return mAuthMgr;
+ }
+
+ public boolean isClientCertRequired() {
+ if (mGetClientCert != null && mGetClientCert.equals("true"))
+ return true;
+ else
+ return false;
+ }
+
+ public void outputHttpParameters(HttpServletRequest httpReq) {
+ CMS.debug("CMSServlet:service() uri = " + httpReq.getRequestURI());
+ Enumeration<?> paramNames = httpReq.getParameterNames();
+ while (paramNames.hasMoreElements()) {
+ String pn = (String) paramNames.nextElement();
+ // added this facility so that password can be hidden,
+ // all sensitive parameters should be prefixed with
+ // __ (double underscores); however, in the event that
+ // a security parameter slips through, we perform multiple
+ // additional checks to insure that it is NOT displayed
+ if (pn.startsWith("__") ||
+ pn.endsWith("password") ||
+ pn.endsWith("passwd") ||
+ pn.endsWith("pwd") ||
+ pn.equalsIgnoreCase("admin_password_again") ||
+ pn.equalsIgnoreCase("directoryManagerPwd") ||
+ pn.equalsIgnoreCase("bindpassword") ||
+ pn.equalsIgnoreCase("bindpwd") ||
+ pn.equalsIgnoreCase("passwd") ||
+ pn.equalsIgnoreCase("password") ||
+ pn.equalsIgnoreCase("pin") ||
+ pn.equalsIgnoreCase("pwd") ||
+ pn.equalsIgnoreCase("pwdagain") ||
+ pn.startsWith("p12Password") ||
+ pn.equalsIgnoreCase("uPasswd")) {
+ CMS.debug("CMSServlet::service() param name='" + pn +
+ "' value='(sensitive)'");
+ } else {
+ CMS.debug("CMSServlet::service() param name='" + pn +
+ "' value='" + httpReq.getParameter(pn) + "'");
+ }
+ }
+ }
+
+ public void service(HttpServletRequest httpReq,
+ HttpServletResponse httpResp)
+ throws ServletException, IOException {
+
+ boolean running_state = CMS.isInRunningState();
+
+ if (!running_state)
+ throw new IOException(
+ "CS server is not ready to serve.");
+
+ try {
+ if (CMS.getConfigStore().getBoolean("useThreadNaming", false)) {
+ String currentName = Thread.currentThread().getName();
+
+ Thread.currentThread().setName(currentName + "-" + httpReq.getServletPath());
+ }
+ } catch (Exception e) {
+ }
+
+ httpReq.setCharacterEncoding("UTF-8");
+
+ if (CMS.debugOn()) {
+ outputHttpParameters(httpReq);
+ }
+ CMS.debug("CMSServlet: " + mId + " start to service.");
+
+ // get a cms request
+ CMSRequest cmsRequest = newCMSRequest();
+
+ // set argblock
+ cmsRequest.setHttpParams(CMS.createArgBlock("http-request-params", toHashtable(httpReq)));
+
+ // set http request
+ cmsRequest.setHttpReq(httpReq);
+
+ // set http response
+ cmsRequest.setHttpResp(httpResp);
+
+ // set servlet config.
+ cmsRequest.setServletConfig(mServletConfig);
+
+ // set servlet context.
+ cmsRequest.setServletContext(mServletContext);
+
+ IArgBlock httpArgs = cmsRequest.getHttpParams();
+
+ // authenticator value from http overrides the value in web.xml.
+ String authMgr_http = httpArgs.getValueAsString(AUTHMGR_PARAM, null);
+
+ if (authMgr_http != null) {
+ mAuthMgr = authMgr_http;
+ } else {
+ mAuthMgr = mServletConfig.getInitParameter(PROP_AUTHMGR);
+ }
+
+ // process request.
+ ICommandQueue iCommandQueue = CMS.getCommandQueue();
+
+ try {
+ if (iCommandQueue.registerProcess(cmsRequest, this) == false) {
+ cmsRequest.setStatus(ICMSRequest.ERROR);
+ renderResult(cmsRequest);
+ SessionContext.releaseContext();
+ return;
+ }
+ long startTime = CMS.getCurrentDate().getTime();
+ process(cmsRequest);
+ renderResult(cmsRequest);
+ Date endDate = CMS.getCurrentDate();
+ long endTime = endDate.getTime();
+ if (CMS.debugOn()) {
+ CMS.debug(CMS.DEBUG_INFORM, "CMSServlet: curDate="
+ + endDate + " id=" + mId + " time=" + (endTime - startTime));
+ }
+ iCommandQueue.unRegisterProccess(cmsRequest, this);
+ } catch (EBaseException e) {
+ iCommandQueue.unRegisterProccess(cmsRequest, this);
+ // ByteArrayOutputStream os = new ByteArrayOutputStream(); for debugging only
+ // PrintStream ps = new PrintStream(os);
+ //e.printStackTrace(ps);
+ log(e.toString());
+ renderException(cmsRequest, e);
+ } catch (Exception ex) {
+ iCommandQueue.unRegisterProccess(cmsRequest, this);
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(os);
+
+ ex.printStackTrace(ps);
+ log(os.toString());
+ renderFinalError(cmsRequest, ex);
+ }
+
+ // destroy SessionContext
+ SessionContext.releaseContext();
+
+ return;
+ }
+
+ /**
+ * Create a new CMSRequest object. This should be overriden by servlets
+ * implementing different types of request
+ *
+ * @return a new CMSRequest object
+ */
+ protected CMSRequest newCMSRequest() {
+ return new CMSRequest();
+ }
+
+ /**
+ * process an HTTP request. Servlets must override this with their
+ * own implementation
+ *
+ * @throws EBaseException if the servlet was unable to satisfactorily
+ * process the request
+ */
+ protected void process(CMSRequest cmsRequest)
+ throws EBaseException {
+ }
+
+ /**
+ * Output a template.
+ * If an error occurs while outputing the template the exception template
+ * is used to display the error.
+ *
+ * @param cmsReq the CS request
+ */
+ protected void renderResult(CMSRequest cmsReq)
+ throws IOException {
+
+ if (!mRenderResult)
+ return;
+ Integer status = cmsReq.getStatus();
+
+ CMSLoadTemplate ltempl = mTemplates.get(status);
+
+ if (ltempl == null || ltempl.mTemplateName == null) {
+ // result is previously outputed.
+ return;
+ }
+ ICMSTemplateFiller filler = ltempl.mFiller;
+
+ renderTemplate(cmsReq, ltempl.mTemplateName, filler);
+ }
+
+ private static final String PRESERVED = "preserved";
+ public static final String TEMPLATE_NAME = "templateName";
+
+ protected void outputArgBlockAsXML(XMLObject xmlObj, Node parent,
+ String argBlockName, IArgBlock argBlock) {
+ Node argBlockContainer = xmlObj.createContainer(parent, argBlockName);
+
+ if (argBlock != null) {
+ Enumeration<String> names = argBlock.getElements();
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ String val = argBlock.get(name).toString();
+ val = val.trim();
+ xmlObj.addItemToContainer(argBlockContainer, name, val);
+ }
+ }
+ }
+
+ protected void outputXML(HttpServletResponse httpResp, CMSTemplateParams params) {
+ XMLObject xmlObj = null;
+ try {
+ xmlObj = new XMLObject();
+
+ Node root = xmlObj.createRoot("xml");
+ outputArgBlockAsXML(xmlObj, root, "header", params.getHeader());
+ outputArgBlockAsXML(xmlObj, root, "fixed", params.getFixed());
+
+ Enumeration<IArgBlock> records = params.queryRecords();
+ Node recordsNode = xmlObj.createContainer(root, "records");
+ if (records != null) {
+ while (records.hasMoreElements()) {
+ IArgBlock record = records.nextElement();
+ outputArgBlockAsXML(xmlObj, recordsNode, "record", record);
+ }
+ }
+
+ byte[] cb = xmlObj.toByteArray();
+ OutputStream os = httpResp.getOutputStream();
+ httpResp.setContentType("application/xml");
+ httpResp.setContentLength(cb.length);
+ os.write(cb);
+ os.flush();
+ } catch (Exception e) {
+ CMS.debug("failed in outputing XML " + e);
+ }
+ }
+
+ protected void renderTemplate(
+ CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler)
+ throws IOException {
+ try {
+ IArgBlock httpParams = cmsReq.getHttpParams();
+
+ Locale[] locale = new Locale[1];
+ CMSTemplate template =
+ getTemplate(templateName, cmsReq.getHttpReq(), locale);
+ CMSTemplateParams templateParams = null;
+
+ if (filler != null) {
+ templateParams = filler.getTemplateParams(
+ cmsReq, mAuthority, locale[0], null);
+ }
+
+ // just output arg blocks as XML
+ CMS.debug("CMSServlet.java: renderTemplate");
+ String xmlOutput = cmsReq.getHttpReq().getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ CMS.debug("CMSServlet.java: xml parameter detected, returning xml");
+ outputXML(cmsReq.getHttpResp(), templateParams);
+ return;
+ }
+
+ if (httpParams != null) {
+ String httpTemplateName =
+ httpParams.getValueAsString(
+ TEMPLATE_NAME, null);
+
+ if (httpTemplateName != null) {
+ templateName = httpTemplateName;
+ }
+ }
+
+ if (templateParams == null)
+ templateParams = new CMSTemplateParams(null, null);
+
+ // #359630
+ // inject preserved http parameter into the template
+ if (httpParams != null) {
+ String preserved = httpParams.getValueAsString(
+ PRESERVED, null);
+
+ if (preserved != null) {
+ IArgBlock fixed = templateParams.getFixed();
+
+ if (fixed != null) {
+ fixed.set(PRESERVED, preserved);
+ }
+ }
+ }
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ template.renderOutput(bos, templateParams);
+ cmsReq.getHttpResp().setContentType("text/html");
+ cmsReq.getHttpResp().setContentLength(bos.size());
+ bos.writeTo(cmsReq.getHttpResp().getOutputStream());
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_OUT_TEMPLATE", templateName, e.toString()));
+ renderException(cmsReq,
+ new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")));
+ return;
+ }
+ }
+
+ /**
+ * Output exception (unexpected error) template
+ * This is different from other templates in that if an exception occurs
+ * while rendering the exception a message is printed out directly.
+ * If the message gets an error an IOException is thrown.
+ * In others if an exception occurs while rendering the template the
+ * exception template (this) is called.
+ * <p>
+ *
+ * @param cmsReq the CS request to pass to template filler if any.
+ * @param e the unexpected exception
+ */
+ protected void renderException(CMSRequest cmsReq, EBaseException e)
+ throws IOException {
+ try {
+ Locale[] locale = new Locale[1];
+ CMSLoadTemplate loadTempl =
+ mTemplates.get(ICMSRequest.EXCEPTION);
+ CMSTemplate template = getTemplate(loadTempl.mTemplateName,
+ cmsReq.getHttpReq(), locale);
+ ICMSTemplateFiller filler = loadTempl.mFiller;
+ CMSTemplateParams templateParams = null;
+
+ // When an exception occurs the exit is non-local which probably
+ // will leave the requestStatus value set to something other
+ // than CMSRequest.EXCEPTION, so force the requestStatus to
+ // EXCEPTION since it must be that if we're here.
+ cmsReq.setStatus(ICMSRequest.EXCEPTION);
+
+ if (filler != null) {
+ templateParams = filler.getTemplateParams(
+ cmsReq, mAuthority, locale[0], e);
+ }
+ if (templateParams == null) {
+ templateParams = new CMSTemplateParams(null, CMS.createArgBlock());
+ }
+ if (e != null) {
+ templateParams.getFixed().set(
+ ICMSTemplateFiller.EXCEPTION, e.toString(locale[0]));
+ }
+
+ // just output arg blocks as XML
+ CMS.debug("CMSServlet.java: renderTemplate");
+ String xmlOutput = cmsReq.getHttpReq().getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ CMS.debug("CMSServlet.java: xml parameter detected, returning xml");
+ outputXML(cmsReq.getHttpResp(), templateParams);
+ return;
+ }
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ template.renderOutput(bos, templateParams);
+ cmsReq.getHttpResp().setContentType("text/html");
+ cmsReq.getHttpResp().setContentLength(bos.size());
+ bos.writeTo(cmsReq.getHttpResp().getOutputStream());
+ } catch (Exception ex) {
+ renderFinalError(cmsReq, ex);
+ }
+ }
+
+ public void renderFinalError(CMSRequest cmsReq, Exception ex)
+ throws IOException {
+ // this template is the last resort for all other unexpected
+ // errors in other templates so we can only output text.
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ httpResp.setContentType("text/html");
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ // replace $ERRORMSG with exception message if included.
+ String finalErrMsg = mFinalErrorMsg;
+ int tokenIdx = mFinalErrorMsg.indexOf(ERROR_MSG_TOKEN);
+
+ if (tokenIdx != -1) {
+ finalErrMsg =
+ mFinalErrorMsg.substring(0, tokenIdx) +
+ ex.toString() +
+ mFinalErrorMsg.substring(
+ tokenIdx + ERROR_MSG_TOKEN.length());
+ }
+ out.println(finalErrMsg);
+ return;
+ }
+
+ /**
+ * Invalidates a SSL Session. So client auth will happen again.
+ */
+ protected static void invalidateSSLSession(HttpServletRequest httpReq) {
+
+ /*
+ try {
+ s = (SSLSocket) ((HTTPRequest) httpReq).getConnection().getSocket();
+ } catch (ClassCastException e) {
+ CMS.getLogger().log(
+ ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_SSL_NO_INVALIDATE"));
+ // ignore.
+ return;
+ }
+ try {
+ s.invalidateSession();
+ s.resetHandshake();
+ }catch (SocketException se) {
+ }
+ */
+ return;
+ }
+
+ /**
+ * construct a authentication credentials to pass into authentication
+ * manager.
+ */
+ public static AuthCredentials getAuthCreds(
+ IAuthManager authMgr, IArgBlock argBlock, X509Certificate clientCert)
+ throws EBaseException {
+ // get credentials from http parameters.
+ String[] reqCreds = authMgr.getRequiredCreds();
+ AuthCredentials creds = new AuthCredentials();
+
+ for (int i = 0; i < reqCreds.length; i++) {
+ String reqCred = reqCreds[i];
+
+ if (reqCred.equals(IAuthManager.CRED_SSL_CLIENT_CERT)) {
+ // cert could be null;
+ creds.set(reqCred, new X509Certificate[] { clientCert }
+ );
+ } else {
+ String value = argBlock.getValueAsString(reqCred);
+
+ creds.set(reqCred, value); // value could be null;
+ }
+ }
+ // Inserted by bskim
+ creds.setArgBlock(argBlock);
+ // Insert end
+ return creds;
+ }
+
+ /**
+ * get ssl client authenticated certificate
+ */
+ protected X509Certificate getSSLClientCertificate(HttpServletRequest httpReq) throws EBaseException {
+
+ X509Certificate cert = null;
+
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_INFO,
+ CMS.getLogMessage("CMSGW_GETTING_SSL_CLIENT_CERT"));
+
+ // iws60 support Java Servlet Spec V2.2, attribute
+ // javax.servlet.request.X509Certificate now contains array
+ // of X509Certificates instead of one X509Certificate object
+ X509Certificate[] allCerts = (X509Certificate[]) httpReq.getAttribute(CERT_ATTR);
+
+ if (allCerts == null || allCerts.length == 0) {
+ throw new EBaseException("You did not provide a valid certificate for this operation");
+ }
+
+ cert = allCerts[0];
+
+ if (cert == null) {
+ // just don't have a cert.
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL"));
+ return null;
+ }
+
+ // convert to sun's x509 cert interface.
+ try {
+ byte[] certEncoded = cert.getEncoded();
+
+ cert = new X509CertImpl(certEncoded);
+ } catch (CertificateEncodingException e) {
+ mLogger.log(
+ ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL_ENCODE", e.getMessage()));
+ return null;
+ } catch (CertificateException e) {
+ mLogger.log(
+ ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL_DECODE", e.getMessage()));
+ return null;
+ }
+ return cert;
+ }
+
+ /**
+ * get a template based on result status.
+ */
+ protected CMSTemplate getTemplate(
+ String templateName, HttpServletRequest httpReq, Locale[] locale)
+ throws EBaseException, IOException {
+ // this converts to system dependent file seperator char.
+ if (mServletConfig == null) {
+ CMS.debug("CMSServlet:getTemplate() - mServletConfig is null!");
+ return null;
+ }
+ if (mServletConfig.getServletContext() == null) {
+ }
+ if (templateName == null) {
+ }
+ String realpath =
+ mServletConfig.getServletContext().getRealPath("/" + templateName);
+
+ if (realpath == null) {
+ mLogger.log(
+ ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_NO_FIND_TEMPLATE", templateName));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+
+ File realpathFile = new File(realpath);
+ File templateFile =
+ getLangFile(httpReq, realpathFile, locale);
+ String charSet = httpReq.getCharacterEncoding();
+
+ if (charSet == null) {
+ charSet = "UTF8";
+ }
+ CMSTemplate template =
+ (CMSTemplate) mFileLoader.getCMSFile(templateFile, charSet);
+
+ return template;
+ }
+
+ /**
+ * log according to authority category.
+ */
+ protected void log(int event, int level, String msg) {
+ mLogger.log(event, mLogCategory, level,
+ "Servlet " + mId + ": " + msg);
+ }
+
+ protected void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, mLogCategory, level,
+ "Servlet " + mId + ": " + msg);
+ }
+
+ /**
+ * get http parameters not to save from configuration.
+ */
+ protected void getDontSaveHttpParams(ServletConfig sc) {
+ String dontSaveParams = null;
+
+ try {
+ for (int i = 0; i < DONT_SAVE_HTTP_PARAMS.length; i++) {
+ mDontSaveHttpParams.addElement(DONT_SAVE_HTTP_PARAMS[i]);
+ }
+ dontSaveParams = sc.getInitParameter(
+ PROP_DONT_SAVE_HTTP_PARAMS);
+ if (dontSaveParams != null) {
+ StringTokenizer params =
+ new StringTokenizer(dontSaveParams, ",");
+
+ while (params.hasMoreTokens()) {
+ String param = params.nextToken();
+
+ mDontSaveHttpParams.addElement(param);
+ }
+ }
+ } catch (Exception e) {
+ // should never happen
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_NO_CONFIG_VALUE", PROP_DONT_SAVE_HTTP_PARAMS, e.toString()));
+ // default just in case.
+ for (int i = 0; i < DONT_SAVE_HTTP_PARAMS.length; i++) {
+ mDontSaveHttpParams.addElement(DONT_SAVE_HTTP_PARAMS[i]);
+ }
+ return;
+ }
+ }
+
+ /**
+ * get http headers to save from configuration.
+ */
+ protected void getSaveHttpHeaders(ServletConfig sc) {
+ try {
+ // init save http headers. default will always be saved.
+ for (int i = 0; i < SAVE_HTTP_HEADERS.length; i++) {
+ mSaveHttpHeaders.addElement(SAVE_HTTP_HEADERS[i]);
+ }
+
+ // now get from config file if there's more.
+ String saveHeaders =
+ sc.getInitParameter(PROP_SAVE_HTTP_HEADERS);
+
+ if (saveHeaders != null) {
+ StringTokenizer headers =
+ new StringTokenizer(saveHeaders, ",");
+
+ while (headers.hasMoreTokens()) {
+ String hdr = headers.nextToken();
+
+ mSaveHttpHeaders.addElement(hdr);
+ }
+ }
+ } catch (Exception e) {
+ // should never happen
+ log(ILogger.LL_WARN, CMS.getLogMessage("CMSGW_NO_CONFIG_VALUE", PROP_SAVE_HTTP_HEADERS, e.toString()));
+ return;
+ }
+ }
+
+ /**
+ * save http headers in a IRequest.
+ */
+ protected void saveHttpHeaders(
+ HttpServletRequest httpReq, IRequest req)
+ throws EBaseException {
+ Hashtable<String, String> headers = new Hashtable<String, String>();
+ Enumeration<String> hdrs = mSaveHttpHeaders.elements();
+
+ while (hdrs.hasMoreElements()) {
+ String hdr = hdrs.nextElement();
+ String val = httpReq.getHeader(hdr);
+
+ if (val != null) {
+ headers.put(hdr, val);
+ }
+ }
+ req.setExtData(IRequest.HTTP_HEADERS, headers);
+ }
+
+ /**
+ * save http headers in a IRequest.
+ */
+ protected void saveHttpParams(
+ IArgBlock httpParams, IRequest req) {
+ Hashtable<String, String> saveParams = new Hashtable<String, String>();
+
+ Enumeration<String> names = httpParams.elements();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ Enumeration<String> params = mDontSaveHttpParams.elements();
+ boolean dosave = true;
+
+ while (params.hasMoreElements()) {
+ String param = params.nextElement();
+
+ if (name.equalsIgnoreCase(param)) {
+ dosave = false;
+ break;
+ }
+ }
+ if (dosave) {
+ // kmccarth
+ // fear not - service() calls toHashtable() which only
+ // retrieves string values.
+ // TODO - when we can use JDK5 features we should typecast
+ // the params until they get here
+ saveParams.put(name, (String) httpParams.get(name));
+ }
+ }
+ req.setExtData(IRequest.HTTP_PARAMS, saveParams);
+ }
+
+ /**
+ * handy routine for getting a cert record given a serial number.
+ */
+ protected ICertRecord getCertRecord(BigInteger serialNo) {
+ if (mAuthority == null ||
+ !(mAuthority instanceof ICertificateAuthority)) {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_NON_CERT_AUTH"));
+ return null;
+ }
+ ICertificateRepository certdb =
+ ((ICertificateAuthority) mAuthority).getCertificateRepository();
+
+ if (certdb == null) {
+ log(ILogger.LL_WARN, CMS.getLogMessage("CMSGW_CERT_DB_NULL", mAuthority.toString()));
+ return null;
+ }
+ ICertRecord certRecord = null;
+
+ try {
+ certRecord = certdb.readCertificateRecord(serialNo);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_NO_CERT_REC", serialNo.toString(16), e.toString()));
+ return null;
+ }
+ return certRecord;
+ }
+
+ /**
+ * handy routine for validating if a cert is from this CA.
+ * mAuthority must be a CA.
+ */
+ protected boolean isCertFromCA(X509Certificate cert) {
+ BigInteger serialno = cert.getSerialNumber();
+ X509CertImpl certInDB = (X509CertImpl) getX509Certificate(serialno);
+
+ if (certInDB == null || !certInDB.equals(cert))
+ return false;
+ return true;
+ }
+
+ /**
+ * handy routine for checking if a list of certs is from this CA.
+ * mAuthortiy must be a CA.
+ */
+ protected boolean areCertsFromCA(X509Certificate[] certs) {
+ for (int i = certs.length - 1; i >= 0; i--) {
+ if (!isCertFromCA(certs[i]))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * handy routine for getting a certificate from the certificate
+ * repository. mAuthority must be a CA.
+ */
+ protected X509Certificate getX509Certificate(BigInteger serialNo) {
+ if (mAuthority == null ||
+ !(mAuthority instanceof ICertificateAuthority)) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_NOT_CERT_AUTH"));
+ return null;
+ }
+ ICertificateRepository certdb =
+ ((ICertificateAuthority) mAuthority).getCertificateRepository();
+
+ if (certdb == null) {
+ log(ILogger.LL_WARN, CMS.getLogMessage("CMSGW_CERT_DB_NULL", mAuthority.toString()));
+ return null;
+ }
+ X509Certificate cert = null;
+
+ try {
+ cert = certdb.getX509Certificate(serialNo);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_NO_CERT_REC", serialNo.toString(16), e.toString()));
+ return null;
+ }
+ return cert;
+ }
+
+ /**
+ * instantiate a new filler from a class name,
+ *
+ * @return null if can't be instantiated, new instance otherwise.
+ */
+ protected ICMSTemplateFiller newFillerObject(String fillerClass) {
+ ICMSTemplateFiller filler = null;
+
+ try {
+ filler = (ICMSTemplateFiller)
+ Class.forName(fillerClass).newInstance();
+ } catch (Exception e) {
+ if ((e instanceof RuntimeException)) {
+ throw (RuntimeException) e;
+ } else {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_CANT_LOAD_FILLER", fillerClass, e.toString()));
+ return null;
+ }
+ }
+ return filler;
+ }
+
+ /**
+ * set default templates.
+ * subclasses can override, and should override at least the success
+ * template
+ */
+ protected void setDefaultTemplates(ServletConfig sc) {
+ // Subclasses should override these for diff templates and params in
+ // their constructors.
+ // Set a template name to null to not use these standard ones.
+ // When template name is set to null nothing will be displayed.
+ // Servlet is assumed to have rendered its own output.
+ // The only exception is the unexpected error template where the
+ // default one will always be used if template name is null.
+ String successTemplate = null;
+ String errorTemplate = null;
+ String unauthorizedTemplate = null;
+ String pendingTemplate = null;
+ String svcpendingTemplate = null;
+ String rejectedTemplate = null;
+ String unexpectedErrorTemplate = null;
+
+ String gateway = sc.getInitParameter("interface");
+ String authority = sc.getInitParameter(PROP_AUTHORITY);
+ if (authority == null) {
+ authority = sc.getInitParameter("authorityId");
+ }
+
+ try {
+ successTemplate = sc.getInitParameter(
+ PROP_SUCCESS_TEMPLATE);
+ if (successTemplate == null) {
+ successTemplate = SUCCESS_TEMPLATE;
+ if (gateway != null)
+ //successTemplate = "/"+gateway+successTemplate;
+ successTemplate = "/" + gateway + successTemplate;
+ }
+
+ errorTemplate = sc.getInitParameter(
+ PROP_ERROR_TEMPLATE);
+ if (errorTemplate == null) {
+ errorTemplate = ERROR_TEMPLATE;
+ if (gateway != null)
+ //errorTemplate = "/"+gateway+errorTemplate;
+ errorTemplate = "/" + gateway + errorTemplate;
+ }
+
+ unauthorizedTemplate = sc.getInitParameter(
+ PROP_UNAUTHORIZED_TEMPLATE);
+ if (unauthorizedTemplate == null) {
+ unauthorizedTemplate = UNAUTHORIZED_TEMPLATE;
+ if (gateway != null)
+ //unauthorizedTemplate = "/"+gateway+unauthorizedTemplate;
+ unauthorizedTemplate = "/" + gateway + unauthorizedTemplate;
+ }
+
+ pendingTemplate = sc.getInitParameter(
+ PROP_PENDING_TEMPLATE);
+ if (pendingTemplate == null) {
+ pendingTemplate = PENDING_TEMPLATE;
+ if (gateway != null)
+ //pendingTemplate = "/"+gateway+pendingTemplate;
+ pendingTemplate = "/" + gateway + pendingTemplate;
+ }
+
+ svcpendingTemplate = sc.getInitParameter(
+ PROP_SVC_PENDING_TEMPLATE);
+ if (svcpendingTemplate == null) {
+ svcpendingTemplate = SVC_PENDING_TEMPLATE;
+ if (gateway != null)
+ //svcpendingTemplate = "/"+gateway+svcpendingTemplate;
+ svcpendingTemplate = "/" + gateway + svcpendingTemplate;
+ }
+
+ rejectedTemplate = sc.getInitParameter(
+ PROP_REJECTED_TEMPLATE);
+ if (rejectedTemplate == null) {
+ rejectedTemplate = REJECTED_TEMPLATE;
+ if (gateway != null)
+ //rejectedTemplate = "/"+gateway+rejectedTemplate;
+ rejectedTemplate = "/" + gateway + rejectedTemplate;
+ }
+
+ unexpectedErrorTemplate = sc.getInitParameter(
+ PROP_EXCEPTION_TEMPLATE);
+ if (unexpectedErrorTemplate == null) {
+ unexpectedErrorTemplate = EXCEPTION_TEMPLATE;
+ if (gateway != null)
+ //unexpectedErrorTemplate = "/"+gateway+unexpectedErrorTemplate;
+ unexpectedErrorTemplate = "/" + gateway + unexpectedErrorTemplate;
+ }
+ } catch (Exception e) {
+ // this should never happen.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_IMP_INIT_SERV_ERR", e.toString(),
+ mId));
+ }
+
+ mTemplates.put(
+ ICMSRequest.UNAUTHORIZED,
+ new CMSLoadTemplate(
+ PROP_UNAUTHORIZED_TEMPLATE, PROP_UNAUTHOR_TEMPLATE_FILLER,
+ unauthorizedTemplate, null));
+ mTemplates.put(
+ ICMSRequest.SUCCESS,
+ new CMSLoadTemplate(
+ PROP_SUCCESS_TEMPLATE, PROP_SUCCESS_TEMPLATE_FILLER,
+ successTemplate, new GenSuccessTemplateFiller()));
+ mTemplates.put(
+ ICMSRequest.PENDING,
+ new CMSLoadTemplate(
+ PROP_PENDING_TEMPLATE, PROP_PENDING_TEMPLATE_FILLER,
+ pendingTemplate, new GenPendingTemplateFiller()));
+ mTemplates.put(
+ ICMSRequest.SVC_PENDING,
+ new CMSLoadTemplate(
+ PROP_SVC_PENDING_TEMPLATE, PROP_SVC_PENDING_TEMPLATE_FILLER,
+ svcpendingTemplate, new GenSvcPendingTemplateFiller()));
+ mTemplates.put(
+ ICMSRequest.REJECTED,
+ new CMSLoadTemplate(
+ PROP_REJECTED_TEMPLATE, PROP_REJECTED_TEMPLATE_FILLER,
+ rejectedTemplate, new GenRejectedTemplateFiller()));
+ mTemplates.put(
+ ICMSRequest.ERROR,
+ new CMSLoadTemplate(
+ PROP_ERROR_TEMPLATE, PROP_ERROR_TEMPLATE_FILLER,
+ errorTemplate, new GenErrorTemplateFiller()));
+ mTemplates.put(
+ ICMSRequest.EXCEPTION,
+ new CMSLoadTemplate(
+ PROP_EXCEPTION_TEMPLATE, PROP_EXCEPTION_TEMPLATE_FILLER,
+ unexpectedErrorTemplate, new GenUnexpectedErrorTemplateFiller()));
+ }
+
+ /**
+ * handy routine to check if client is navigator based on user-agent.
+ */
+ public static boolean clientIsNav(HttpServletRequest httpReq) {
+ String useragent = httpReq.getHeader("user-agent");
+
+ if (useragent.startsWith("Mozilla") &&
+ useragent.indexOf("MSIE") == -1)
+ return true;
+ return false;
+ }
+
+ /**
+ * handy routine to check if client is msie based on user-agent.
+ */
+ public static boolean clientIsMSIE(HttpServletRequest httpReq) {
+ String useragent = httpReq.getHeader("user-agent");
+
+ if (useragent != null && useragent.indexOf("MSIE") != -1)
+ return true;
+ return false;
+ }
+
+ /**
+ * handy routine to check if client is cartman based on hidden http input
+ * set using cartman JS. (no other way to tell)
+ */
+ private static String CMMF_RESPONSE = "cmmfResponse";
+
+ public static boolean doCMMFResponse(IArgBlock httpParams) {
+ if (httpParams.getValueAsBoolean(CMMF_RESPONSE, false))
+ return true;
+ else
+ return false;
+ }
+
+ private static final String IMPORT_CERT = "importCert";
+ private static final String IMPORT_CHAIN = "importCAChain";
+ private static final String IMPORT_CERT_MIME_TYPE = "importCertMimeType";
+ // default mime type
+ private static final String NS_X509_USER_CERT = "application/x-x509-user-cert";
+ private static final String NS_X509_EMAIL_CERT = "application/x-x509-email-cert";
+
+ // CMC mime types
+ public static final String SIMPLE_ENROLLMENT_REQUEST = "application/pkcs10";
+ public static final String SIMPLE_ENROLLMENT_RESPONSE = "application/pkcs7-mime";
+ public static final String FULL_ENROLLMENT_REQUEST = "application/pkcs7-mime";
+ public static final String FULL_ENROLLMENT_RESPONSE = "application/pkcs7-mime";
+
+ /**
+ * handy routine to check if client want full enrollment response
+ */
+ public static String FULL_RESPONSE = "fullResponse";
+
+ public static boolean doFullResponse(IArgBlock httpParams) {
+ if (httpParams.getValueAsBoolean(FULL_RESPONSE, false))
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * @return false if import cert directly set to false.
+ * @return true if import cert directly is true and import cert.
+ */
+ protected boolean checkImportCertToNav(
+ HttpServletResponse httpResp, IArgBlock httpParams, X509CertImpl cert)
+ throws EBaseException {
+ if (!httpParams.getValueAsBoolean(IMPORT_CERT, false)) {
+ return false;
+ }
+ boolean importCAChain =
+ httpParams.getValueAsBoolean(IMPORT_CHAIN, true);
+ // XXX Temporary workaround because of problem with passing Mime type
+ boolean emailCert =
+ httpParams.getValueAsBoolean("emailCert", false);
+ String importMimeType = (emailCert) ?
+ httpParams.getValueAsString(IMPORT_CERT_MIME_TYPE, NS_X509_EMAIL_CERT) :
+ httpParams.getValueAsString(IMPORT_CERT_MIME_TYPE, NS_X509_USER_CERT);
+
+ // String importMimeType =
+ // httpParams.getValueAsString(
+ // IMPORT_CERT_MIME_TYPE, NS_X509_USER_CERT);
+ importCertToNav(httpResp, cert, importMimeType, importCAChain);
+ return true;
+ }
+
+ /**
+ * handy routine to import cert to old navigator in nav mime type.
+ */
+ public void importCertToNav(
+ HttpServletResponse httpResp, X509CertImpl cert,
+ String contentType, boolean importCAChain)
+ throws EBaseException {
+ ServletOutputStream out = null;
+ byte[] encoding = null;
+
+ CMS.debug("CMSServlet: importCertToNav " +
+ "contentType=" + contentType + " " +
+ "importCAChain=" + importCAChain);
+ try {
+ out = httpResp.getOutputStream();
+ // CA chain.
+ if (importCAChain) {
+ CertificateChain caChain = null;
+ X509Certificate[] caCerts = null;
+ PKCS7 p7 = null;
+
+ caChain = ((ICertAuthority) mAuthority).getCACertChain();
+ caCerts = caChain.getChain();
+
+ // set user + CA cert chain in pkcs7
+ X509CertImpl[] userChain =
+ new X509CertImpl[caCerts.length + 1];
+
+ userChain[0] = cert;
+ int m = 1, n = 0;
+
+ for (; n < caCerts.length; m++, n++) {
+ userChain[m] = (X509CertImpl) caCerts[n];
+
+ /*
+ System.out.println(
+ m+"th Cert "+userChain[m].toString());
+ */
+ }
+ p7 = new PKCS7(new AlgorithmId[0],
+ new ContentInfo(new byte[0]),
+ userChain,
+ new SignerInfo[0]);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ p7.encodeSignedData(bos, false);
+ encoding = bos.toByteArray();
+ CMS.debug("CMServlet: return P7 " + CMS.BtoA(encoding));
+ } else {
+ encoding = cert.getEncoded();
+ CMS.debug("CMServlet: return Certificate " + CMS.BtoA(encoding));
+ }
+ httpResp.setContentType(contentType);
+ out.write(encoding);
+ } catch (IOException e) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_RET_CERT_IMPORT_ERR", e.toString()));
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_RETURNING_CERT"));
+ } catch (CertificateEncodingException e) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_NO_ENCODED_IMP_CERT", e.toString()));
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_ENCODING_ISSUED_CERT"));
+ }
+ }
+
+ protected static void saveAuthToken(IAuthToken token, IRequest req) {
+ if (token != null && req != null)
+ req.setExtData(IRequest.AUTH_TOKEN, token);
+
+ // # 56230 - expose auth token parameters to the policy predicate
+ if (token != null && req != null) {
+ Enumeration<String> e = token.getElements();
+ while (e.hasMoreElements()) {
+ String n = e.nextElement();
+ String[] x1 = token.getInStringArray(n);
+ if (x1 != null) {
+ for (int i = 0; i < x1.length; i++) {
+ CMS.debug("Setting " + IRequest.AUTH_TOKEN + "-" + n +
+ "(" + i + ")=" + x1[i]);
+ req.setExtData(IRequest.AUTH_TOKEN + "-" + n + "(" + i + ")",
+ x1[i]);
+ }
+ } else {
+ String x = token.getInString(n);
+ if (x != null) {
+ CMS.debug("Setting " + IRequest.AUTH_TOKEN + "-" + n + "=" + x);
+ req.setExtData(IRequest.AUTH_TOKEN + "-" + n, x);
+ }
+ }
+ } // while
+ } // if
+ }
+
+ protected IAuthToken getAuthToken(IRequest req) {
+ return req.getExtDataInAuthToken(IRequest.AUTH_TOKEN);
+ }
+
+ protected static boolean connectionIsSSL(HttpServletRequest httpReq) {
+ return httpReq.isSecure();
+ }
+
+ /**
+ * handy routine for getting agent's relative path
+ */
+ protected String getRelPath(IAuthority authority) {
+ if (authority instanceof ICertificateAuthority)
+ return "ca/";
+ else if (authority instanceof IRegistrationAuthority)
+ return "ra/";
+ else if (authority instanceof IKeyRecoveryAuthority)
+ return "kra/";
+ else
+ return "/";
+ }
+
+ /**
+ * A system certificate such as the CA signing certificate
+ * should not be allowed to delete.
+ * The main purpose is to avoid revoking the self signed
+ * CA certificate accidentially.
+ */
+ protected boolean isSystemCertificate(BigInteger serialNo) {
+ if (!(mAuthority instanceof ICertificateAuthority)) {
+ return false;
+ }
+ X509Certificate caCert =
+ ((ICertificateAuthority) mAuthority).getCACert();
+ if (caCert != null) {
+ /* only check this if we are self-signed */
+ if (caCert.getSubjectDN().equals(caCert.getIssuerDN())) {
+ if (caCert.getSerialNumber().equals(serialNo)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * make a CRL entry from a serial number and revocation reason.
+ *
+ * @return a RevokedCertImpl that can be entered in a CRL.
+ */
+ protected RevokedCertImpl formCRLEntry(
+ BigInteger serialNo, RevocationReason reason)
+ throws EBaseException {
+ CRLReasonExtension reasonExt = new CRLReasonExtension(reason);
+ CRLExtensions crlentryexts = new CRLExtensions();
+
+ try {
+ crlentryexts.set(CRLReasonExtension.NAME, reasonExt);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_CRL_REASON", reason.toString(), e.toString()));
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_SETTING_CRLREASON"));
+ }
+ RevokedCertImpl crlentry =
+ new RevokedCertImpl(serialNo, CMS.getCurrentDate(), crlentryexts);
+
+ return crlentry;
+ }
+
+ /**
+ * check if a certificate (serial number) is revoked on a CA.
+ *
+ * @return true if cert is marked revoked in the CA's database.
+ * @return false if cert is not marked revoked.
+ */
+ protected boolean certIsRevoked(BigInteger serialNum)
+ throws EBaseException {
+ ICertRecord certRecord = getCertRecord(serialNum);
+
+ if (certRecord == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_BAD_CERT_SER_NUM", String.valueOf(serialNum)));
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_INVALID_CERT"));
+ }
+ if (certRecord.getStatus().equals(ICertRecord.STATUS_REVOKED))
+ return true;
+ return false;
+ }
+
+ public static String generateSalt() {
+ Random rnd = new Random();
+ String salt = new Integer(rnd.nextInt()).toString();
+ return salt;
+ }
+
+ protected String hashPassword(String pwd) {
+ String salt = generateSalt();
+ byte[] pwdDigest = mSHADigest.digest((salt + pwd).getBytes());
+ String b64E = Utils.base64encode(pwdDigest);
+
+ return "{SHA}" + salt + ";" + b64E;
+ }
+
+ /**
+ * @param req http servlet request
+ * @param realpathFile the file to get.
+ * @param locale array of at least one to be filled with locale found.
+ */
+ public static File getLangFile(
+ HttpServletRequest req, File realpathFile, Locale[] locale)
+ throws IOException {
+ File file = null;
+ String acceptLang = req.getHeader("accept-language");
+
+ if (acceptLang != null && !acceptLang.equals("")) {
+ StringTokenizer tokenizer = new StringTokenizer(acceptLang, ",");
+ int numLangs = tokenizer.countTokens();
+
+ if (numLangs > 0) {
+ // languages are searched in order.
+ String parent = realpathFile.getParent();
+
+ if (parent == null) {
+ parent = "." + File.separatorChar;
+ }
+ String name = realpathFile.getName();
+
+ if (name == null) { // filename should never be null.
+ throw new IOException("file has no name");
+ }
+ int i;
+
+ for (i = 0; i < numLangs; i++) {
+ String lang = null;
+ String token = tokenizer.nextToken();
+
+ int semicolon = token.indexOf(';');
+
+ if (semicolon == -1) {
+ lang = token.trim();
+ } else {
+ if (semicolon < 2)
+ continue; // protocol error.
+ lang = token.substring(0, semicolon).trim();
+ }
+ // if browser locale is the same as default locale,
+ // use the default form. (is this the right thing to do ?)
+ Locale l = getLocale(lang);
+
+ if (Locale.getDefault().equals(l)) {
+ locale[0] = l;
+ file = realpathFile;
+ break;
+ }
+
+ String langfilepath =
+ parent + File.separatorChar +
+ lang + File.separatorChar + name;
+
+ file = new File(langfilepath);
+ if (file.exists()) {
+ locale[0] = getLocale(lang);
+ break;
+ }
+ }
+ // if no file for lang was found use default
+ if (i == numLangs) {
+ file = realpathFile;
+ locale[0] = Locale.getDefault();
+ }
+ }
+ } else {
+ // use default if accept-language is not availabe
+ file = realpathFile;
+ locale[0] = Locale.getDefault();
+ }
+ return file;
+ }
+
+ public static Locale getLocale(String lang) {
+ int dash = lang.indexOf('-');
+
+ if (dash == -1)
+ return new Locale(lang, "");
+ else
+ return new Locale(lang.substring(0, dash), lang.substring(dash + 1));
+ }
+
+ public IAuthToken authenticate(CMSRequest req)
+ throws EBaseException {
+ return authenticate(req, mAuthMgr);
+ }
+
+ public IAuthToken authenticate(HttpServletRequest httpReq)
+ throws EBaseException {
+ return authenticate(httpReq, mAuthMgr);
+ }
+
+ public IAuthToken authenticate(CMSRequest req, String authMgrName)
+ throws EBaseException {
+ IAuthToken authToken = authenticate(req.getHttpReq(),
+ authMgrName);
+
+ saveAuthToken(authToken, req.getIRequest());
+ return authToken;
+ }
+
+ /**
+ * Authentication
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTH_FAIL used when authentication fails (in case of SSL-client auth, only
+ * webserver env can pick up the SSL violation; CS authMgr can pick up cert mis-match, so this event is used)
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTH_SUCCESS used when authentication succeeded
+ * </ul>
+ *
+ * @exception EBaseException an error has occurred
+ */
+ public IAuthToken authenticate(HttpServletRequest httpReq, String authMgrName)
+ throws EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = ILogger.UNIDENTIFIED;
+ String auditAuthMgrID = ILogger.UNIDENTIFIED;
+ String auditUID = ILogger.UNIDENTIFIED;
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ String getClientCert = mGetClientCert;
+
+ IArgBlock httpArgs = CMS.createArgBlock(toHashtable(httpReq));
+ SessionContext ctx = SessionContext.getContext();
+ String ip = httpReq.getRemoteAddr();
+ CMS.debug("IP: " + ip);
+
+ if (ip != null) {
+ ctx.put(SessionContext.IPADDRESS, ip);
+ }
+ if (authMgrName != null) {
+ CMS.debug("AuthMgrName: " + authMgrName);
+ ctx.put(SessionContext.AUTH_MANAGER_ID, authMgrName);
+ }
+ // put locale into session context
+ ctx.put(SessionContext.LOCALE, getLocale(httpReq));
+
+ //
+ // check ssl client authentication if specified.
+ //
+ X509Certificate clientCert = null;
+
+ if (getClientCert != null && getClientCert.equals("true")) {
+ CMS.debug("CMSServlet: retrieving SSL certificate");
+ clientCert = getSSLClientCertificate(httpReq);
+ }
+
+ //
+ // check authentication by auth manager if any.
+ //
+ if (authMgrName == null) {
+
+ // Fixed Blackflag Bug #613900: Since this code block does
+ // NOT actually constitute an authentication failure, but
+ // rather the case in which a given servlet has been correctly
+ // configured to NOT require an authentication manager, the
+ // audit message called LOGGING_SIGNED_AUDIT_AUTH_FAIL has
+ // been removed.
+
+ CMS.debug("CMSServlet: no authMgrName");
+ return null;
+ } else {
+ // save the "Subject DN" of this certificate in case it
+ // must be audited as an authentication failure
+ if (clientCert == null) {
+ CMS.debug("CMSServlet: no client certificate found");
+ } else {
+ String certUID = clientCert.getSubjectDN().getName();
+ CMS.debug("CMSServlet: certUID=" + certUID);
+
+ if (certUID != null) {
+ certUID = certUID.trim();
+
+ if (!(certUID.equals(""))) {
+ // reset the "auditUID"
+ auditUID = certUID;
+ }
+ }
+ }
+
+ // reset the "auditAuthMgrID"
+ auditAuthMgrID = authMgrName;
+ }
+ AuthToken authToken = CMSGateway.checkAuthManager(httpReq,
+ httpArgs,
+ clientCert,
+ authMgrName);
+ if (authToken == null) {
+ return null;
+ }
+ String userid = authToken.getInString(IAuthToken.USER_ID);
+
+ CMS.debug("CMSServlet: userid=" + userid);
+
+ if (userid != null) {
+ ctx.put(SessionContext.USER_ID, userid);
+ }
+
+ // reset the "auditSubjectID"
+ auditSubjectID = auditSubjectID();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditAuthMgrID);
+
+ audit(auditMessage);
+
+ return authToken;
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditAuthMgrID,
+ auditUID);
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ }
+ }
+
+ public AuthzToken authorize(String authzMgrName, String resource, IAuthToken authToken,
+ String exp) throws EBaseException {
+ AuthzToken authzToken = null;
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditGroupID = auditGroupID();
+ String auditACLResource = resource;
+ String auditOperation = "enroll";
+
+ try {
+ authzToken = mAuthz.authorize(authzMgrName, authToken, exp);
+ if (authzToken != null) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditGroupID);
+
+ audit(auditMessage);
+ } else {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditGroupID);
+
+ audit(auditMessage);
+ }
+ return authzToken;
+ } catch (Exception e) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditGroupID);
+
+ audit(auditMessage);
+ throw new EBaseException(e.toString());
+ }
+ }
+
+ /**
+ * Authorize must occur after Authenticate
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_FAIL used when authorization has failed
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS used when authorization is successful
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_ROLE_ASSUME used when user assumes a role (in current CS that's when one
+ * accesses a role port)
+ * </ul>
+ *
+ * @param authzMgrName string representing the name of the authorization
+ * manager
+ * @param authToken the authentication token
+ * @param resource a string representing the ACL resource id as defined in
+ * the ACL resource list
+ * @param operation a string representing one of the operations as defined
+ * within the ACL statement (e. g. - "read" for an ACL statement containing
+ * "(read,write)")
+ * @exception EBaseException an error has occurred
+ * @return the authorization token
+ */
+ public AuthzToken authorize(String authzMgrName, IAuthToken authToken,
+ String resource, String operation)
+ throws EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditGroupID = auditGroupID();
+ String auditID = auditSubjectID;
+ String auditACLResource = resource;
+ String auditOperation = operation;
+
+ SessionContext auditContext = SessionContext.getExistingContext();
+ String authManagerId = null;
+
+ if (auditContext != null) {
+ authManagerId = (String) auditContext.get(SessionContext.AUTH_MANAGER_ID);
+
+ if (authManagerId != null && authManagerId.equals("TokenAuth")) {
+ if (auditSubjectID.equals(ILogger.NONROLEUSER) ||
+ auditSubjectID.equals(ILogger.UNIDENTIFIED)) {
+ CMS.debug("CMSServlet: in authorize... TokenAuth auditSubjectID unavailable, changing to auditGroupID");
+ auditID = auditGroupID;
+ }
+ }
+ }
+
+ // "normalize" the "auditACLResource" value
+ if (auditACLResource != null) {
+ auditACLResource = auditACLResource.trim();
+ }
+
+ // "normalize" the "auditOperation" value
+ if (auditOperation != null) {
+ auditOperation = auditOperation.trim();
+ }
+
+ if (authzMgrName == null) {
+ // Fixed Blackflag Bug #613900: Since this code block does
+ // NOT actually constitute an authorization failure, but
+ // rather the case in which a given servlet has been correctly
+ // configured to NOT require an authorization manager, the
+ // audit message called LOGGING_SIGNED_AUDIT_AUTHZ_FAIL and
+ // the audit message called LOGGING_SIGNED_AUDIT_ROLE_ASSUME
+ // (marked as a failure) have been removed.
+
+ return null;
+ }
+
+ try {
+ AuthzToken authzTok = mAuthz.authorize(authzMgrName,
+ authToken,
+ resource,
+ operation);
+
+ if (authzTok != null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditID,
+ ILogger.SUCCESS,
+ auditGroups(auditSubjectID));
+
+ audit(auditMessage);
+ } else {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditID,
+ ILogger.FAILURE,
+ auditGroups(auditSubjectID));
+
+ audit(auditMessage);
+ }
+
+ return authzTok;
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditID,
+ ILogger.FAILURE,
+ auditGroups(auditSubjectID));
+
+ audit(auditMessage);
+
+ return null;
+ } catch (Exception eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditGroups(auditSubjectID));
+
+ audit(auditMessage);
+
+ return null;
+ }
+ }
+
+ /**
+ * Signed Audit Log
+ *
+ * This method is inherited by all extended "CMSServlet"s,
+ * and is called to store messages to the signed audit log.
+ * <P>
+ *
+ * @param msg signed audit log message
+ */
+ protected void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+
+ if (mSignedAuditLogger == null) {
+ return;
+ }
+
+ mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+
+ /**
+ * Signed Audit Log Subject ID
+ *
+ * This method is inherited by all extended "CMSServlet"s,
+ * and is called to obtain the "SubjectID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @return id string containing the signed audit log message SubjectID
+ */
+ protected String auditSubjectID() {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ CMS.debug("CMSServlet: in auditSubjectID");
+ String subjectID = null;
+
+ // Initialize subjectID
+ SessionContext auditContext = SessionContext.getExistingContext();
+
+ CMS.debug("CMSServlet: auditSubjectID auditContext " + auditContext);
+ if (auditContext != null) {
+ subjectID = (String)
+ auditContext.get(SessionContext.USER_ID);
+
+ CMS.debug("CMSServlet auditSubjectID: subjectID: " + subjectID);
+ if (subjectID != null) {
+ subjectID = subjectID.trim();
+ } else {
+ subjectID = ILogger.NONROLEUSER;
+ }
+ } else {
+ subjectID = ILogger.UNIDENTIFIED;
+ }
+
+ return subjectID;
+ }
+
+ /**
+ * Signed Audit Log Group ID
+ *
+ * This method is inherited by all extended "CMSServlet"s,
+ * and is called to obtain the "gid" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @return id string containing the signed audit log message SubjectID
+ */
+ protected String auditGroupID() {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ CMS.debug("CMSServlet: in auditGroupID");
+ String groupID = null;
+
+ // Initialize groupID
+ SessionContext auditContext = SessionContext.getExistingContext();
+
+ CMS.debug("CMSServlet: auditGroupID auditContext " + auditContext);
+ if (auditContext != null) {
+ groupID = (String)
+ auditContext.get(SessionContext.GROUP_ID);
+
+ CMS.debug("CMSServlet auditGroupID: groupID: " + groupID);
+ if (groupID != null) {
+ groupID = groupID.trim();
+ } else {
+ groupID = ILogger.NONROLEUSER;
+ }
+ } else {
+ groupID = ILogger.UNIDENTIFIED;
+ }
+
+ return groupID;
+ }
+
+ /**
+ * Signed Audit Groups
+ *
+ * This method is called to extract all "groups" associated
+ * with the "auditSubjectID()".
+ * <P>
+ *
+ * @param SubjectID string containing the signed audit log message SubjectID
+ * @return a delimited string of groups associated
+ * with the "auditSubjectID()"
+ */
+ private String auditGroups(String SubjectID) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ if ((SubjectID == null) ||
+ (SubjectID.equals(ILogger.UNIDENTIFIED))) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ Enumeration<IGroup> groups = null;
+
+ try {
+ groups = mUG.findGroups("*");
+ } catch (Exception e) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ StringBuffer membersString = new StringBuffer();
+
+ while (groups.hasMoreElements()) {
+ IGroup group = groups.nextElement();
+
+ if (group.isMember(SubjectID) == true) {
+ if (membersString.length() != 0) {
+ membersString.append(", ");
+ }
+
+ membersString.append(group.getGroupID());
+ }
+ }
+
+ if (membersString.length() != 0) {
+ return membersString.toString();
+ } else {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader(HDR_LANG);
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+
+ protected void outputResult(HttpServletResponse httpResp,
+ String contentType, byte[] content) {
+ try {
+ OutputStream os = httpResp.getOutputStream();
+
+ httpResp.setContentType(contentType);
+ httpResp.setContentLength(content.length);
+ os.write(content);
+ os.flush();
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", e.toString()));
+ return;
+ }
+ }
+
+ protected void outputError(HttpServletResponse httpResp, String errorString) {
+ outputError(httpResp, FAILURE, errorString, null);
+ }
+
+ protected void outputError(HttpServletResponse httpResp, String errorString, String requestId) {
+ outputError(httpResp, FAILURE, errorString, null);
+ }
+
+ protected void outputError(HttpServletResponse httpResp, String status, String errorString, String requestId) {
+ XMLObject xmlObj = null;
+ try {
+ xmlObj = new XMLObject();
+ Node root = xmlObj.createRoot("XMLResponse");
+ xmlObj.addItemToContainer(root, "Status", status);
+ xmlObj.addItemToContainer(root, "Error", errorString);
+ if (requestId != null) {
+ xmlObj.addItemToContainer(root, "RequestId", requestId);
+ }
+ byte[] cb = xmlObj.toByteArray();
+
+ OutputStream os = httpResp.getOutputStream();
+ httpResp.setContentType("application/xml");
+ httpResp.setContentLength(cb.length);
+ os.write(cb);
+ os.flush();
+ return;
+ } catch (Exception ee) {
+ CMS.debug("Failed to send XML output to the server.");
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", ee.toString()));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/CMSStartServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/CMSStartServlet.java
new file mode 100644
index 000000000..8e3a4b5ba
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/CMSStartServlet.java
@@ -0,0 +1,127 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.base;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cms.realm.PKIRealm;
+import com.netscape.cms.tomcat.ProxyRealm;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * This servlet is started by the web server at startup, and
+ * it starts the CMS framework.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSStartServlet extends HttpServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 515623839479425172L;
+ public final static String PROP_CMS_CFG = "cfgPath";
+
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ String path = config.getInitParameter(PROP_CMS_CFG);
+
+ File f = new File(path);
+ String old_path = "";
+ if (!f.exists()) {
+ int index = path.lastIndexOf("CS.cfg");
+ if (index != -1) {
+ old_path = path.substring(0, index) + "CMS.cfg";
+ }
+ File f1 = new File(old_path);
+ if (f1.exists()) {
+ // The following block of code moves "CMS.cfg" to "CS.cfg".
+ try {
+ if (Utils.isNT()) {
+ // NT is very picky on the path
+ Utils.exec("copy " +
+ f1.getAbsolutePath().replace('/', '\\') +
+ " " +
+ f.getAbsolutePath().replace('/', '\\'));
+ } else {
+ // Create a copy of the original file which
+ // preserves the original file permissions.
+ Utils.exec("cp -p " + f1.getAbsolutePath() + " " +
+ f.getAbsolutePath());
+ }
+
+ // Remove the original file if and only if
+ // the backup copy was successful.
+ if (f.exists()) {
+ if (!f1.delete()) {
+ CMS.debug("CMSStartServlet: init: Cannot delete file : " + old_path);
+ }
+
+ // Make certain that the new file has
+ // the correct permissions.
+ if (!Utils.isNT()) {
+ Utils.exec("chmod 00660 " + f.getAbsolutePath());
+ }
+ }
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ try {
+ CMS.start(path);
+ } catch (EBaseException e) {
+ }
+
+ // Register realm for this subsystem
+ String context = getServletContext().getContextPath();
+ if (context.startsWith("/")) context = context.substring(1);
+ ProxyRealm.registerRealm(context, new PKIRealm());
+ }
+
+ public void doGet(HttpServletRequest req, HttpServletResponse res)
+ throws ServletException, IOException {
+ res.setContentType("text/html");
+
+ PrintWriter out = res.getWriter();
+
+ out.print("<html>");
+ out.print("<head><title>CMS is started!</title></head>");
+ out.print("<body>");
+ out.print("<h1>CMS is started!</h1>");
+ out.print("</body></html>");
+ }
+
+ public String getServletInfo() {
+ return "CMS startup servlet";
+ }
+
+ public void destroy() {
+ CMS.shutdown();
+ super.destroy();
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/DisplayHtmlServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/DisplayHtmlServlet.java
new file mode 100644
index 000000000..52b1258eb
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/DisplayHtmlServlet.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.base;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * This is the servlet that displays the html page for the corresponding input id.
+ *
+ * @version $Revision$, $Date$
+ */
+public class DisplayHtmlServlet extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4343458180370708327L;
+ public final static String PROP_TEMPLATE = "template";
+ public final static String PROP_HTML_PATH = "htmlPath";
+
+ private String mHTMLPath = null;
+
+ public DisplayHtmlServlet() {
+ super();
+ }
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mHTMLPath = sc.getInitParameter(PROP_HTML_PATH);
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Serves HTTP request.
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ CMS.debug("DisplayHtmlServlet about to service ");
+ authenticate(cmsReq);
+ try {
+ String realpath =
+ mServletConfig.getServletContext().getRealPath("/" + mHTMLPath);
+
+ if (realpath == null) {
+ mLogger.log(
+ ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_NO_FIND_TEMPLATE", mHTMLPath));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+ File file = new File(realpath);
+ long flen = file.length();
+ byte[] bin = new byte[(int) flen];
+ FileInputStream ins = new FileInputStream(file);
+
+ int len = 0;
+ if (ins.available() > 0) {
+ len = ins.read(bin);
+ }
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ bos.write(bin, 0, len);
+ bos.writeTo(cmsReq.getHttpResp().getOutputStream());
+ ins.close();
+ bos.close();
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_OUT_TEMPLATE", mHTMLPath, e.toString()));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/DynamicVariablesServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/DynamicVariablesServlet.java
new file mode 100644
index 000000000..357c901c3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/DynamicVariablesServlet.java
@@ -0,0 +1,332 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.base;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthMgrPlugin;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+
+/**
+ * Return some javascript to the request which contains the list of
+ * dynamic data in the CMS system.
+ * <p>
+ * This allows the requestor (browser) to make decisions about what to present in the UI, depending on how CMS is
+ * configured
+ *
+ * @version $Revision$, $Date$
+ */
+public class DynamicVariablesServlet extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7246774978153039460L;
+ public final static String PROP_ACCESS = "ServletAccess";
+ public final static String PROP_AUTHMGR = "AuthMgr";
+ public final static String PROP_CLIENTAUTH = "GetClientCert";
+
+ public final static String PROP_AUTHORITY = "authority";
+ public final static String PROP_CLONING = "cloning";
+
+ private final static String INFO = "dynamicVariables";
+
+ private static final String PROP_DYNVAR = "dynamicVariables";
+ private static final String PROP_CRLURL = "cloneMasterCrlUrl";
+ private static final String VAR_SERVERDATE_STRING = "serverdate()";
+ private static final Integer VAR_SERVERDATE = Integer.valueOf(1);
+
+ private static final String VAR_SUBSYSTEMNAME_STRING = "subsystemname()";
+ private static final Integer VAR_SUBSYSTEMNAME = Integer.valueOf(2);
+ private String VAR_SUBSYSTEMNAME_VALUE = null;
+
+ private static final String VAR_HTTP_STRING = "http()";
+ private static final Integer VAR_HTTP = Integer.valueOf(3);
+
+ private static final String VAR_AUTHMGRS_STRING = "authmgrs()";
+ private static final Integer VAR_AUTHMGRS = Integer.valueOf(4);
+
+ private static final String VAR_CLA_CRL_URL_STRING = "clacrlurl()";
+ private static final Integer VAR_CLA_CRL_URL = Integer.valueOf(6);
+
+ private String mAuthMgrCacheString = "";
+ private long mAuthMgrCacheTime = 0;
+ private final int AUTHMGRCACHE = 10; //number of seconds to cache list of
+ // authmanagers for
+ private Hashtable<Integer, String> dynvars = null;
+ @SuppressWarnings("unused")
+ private String mGetClientCert = "false";
+ private String mAuthMgr = null;
+
+ @SuppressWarnings("unused")
+ private ServletConfig mServletCfg;
+ private ServletContext mServletCtx = null;
+ private static String mCrlurl = "";
+ static {
+ IConfigStore config = CMS.getConfigStore().getSubStore(PROP_CLONING);
+
+ try {
+ mCrlurl =
+ config.getString(PROP_CRLURL, "");
+ } catch (EBaseException e) {
+ }
+ }
+
+ public DynamicVariablesServlet() {
+ super();
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Reads the following variables from the servlet config:
+ * <ul>
+ * <li><strong>AuthMgr</strong> - the authentication manager to use to authenticate the request
+ * <li><strong>GetClientCert</strong> - whether to request client auth for this request
+ * <li><strong>authority</strong> - the authority (ca, ra, drm) to return to the client
+ * <li><strong>dynamicVariables</strong> - a string of the form:
+ * serverdate=serverdate(),subsystemname=subsystemname(), http=http(),authmgrs=authmgrs(),clacrlurl=clacrlurl()
+ * </ul>
+ * The dynamicVariables string is parsed by splitting on commas.
+ * When services, the HTTP request provides a piece of javascript
+ * code as follows.
+ * <p>
+ * Each sub expression "lhs=rhs()" forms a javascript statement of the form <i>lhs=xxx;</i> Where lhs is xxx is the
+ * result of 'evaluating' the rhs. The possible values for the rhs() function are:
+ * <ul>
+ * <li><strong>serverdate()</strong> - the timestamp of the server (used to ensure that the client clock is set
+ * correctly)
+ * <li><strong>subsystemname()</strong>
+ * <li><strong>http()</strong> - "true" or "false" - is this an http connection (as opposed to https)
+ * <li>authmgrs() - a comma separated list of authentication managers
+ * <li>clacrlurl() - the URL to get the CRL from, in the case of a Clone CA. This is defined in the CMS
+ * configuration parameter 'cloning.cloneMasterCrlUrl'
+ * </ul>
+ *
+ * @see javax.servlet.Servlet#init(ServletConfig)
+ */
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mAuthMgr = sc.getInitParameter(PROP_AUTHMGR);
+ mGetClientCert = sc.getInitParameter(PROP_CLIENTAUTH);
+ mServletCfg = sc;
+
+ mServletCtx = sc.getServletContext();
+
+ VAR_SUBSYSTEMNAME_VALUE = sc.getInitParameter(PROP_AUTHORITY);
+
+ try {
+ String dynvarconfig = sc.getInitParameter(PROP_DYNVAR);
+ StringTokenizer s = new StringTokenizer(dynvarconfig, ",");
+
+ dynvars = new Hashtable<Integer, String>();
+
+ while (s.hasMoreTokens()) {
+ String token = s.nextToken();
+
+ int i = token.indexOf('=');
+ String varname = token.substring(0, i);
+ String varvalue = token.substring(i + 1);
+
+ Integer varcode = null;
+
+ if (varvalue.equalsIgnoreCase(VAR_SERVERDATE_STRING)) {
+ varcode = VAR_SERVERDATE;
+ } else if (varvalue.equalsIgnoreCase(VAR_SUBSYSTEMNAME_STRING)) {
+ varcode = VAR_SUBSYSTEMNAME;
+ } else if (varvalue.equalsIgnoreCase(VAR_HTTP_STRING)) {
+ varcode = VAR_HTTP;
+ } else if (varvalue.equalsIgnoreCase(VAR_AUTHMGRS_STRING)) {
+ varcode = VAR_AUTHMGRS;
+ } else if (varvalue.equalsIgnoreCase(VAR_CLA_CRL_URL_STRING)) {
+ varcode = VAR_CLA_CRL_URL;
+ } else {
+ throw new ServletException("bad configuration parameter in " + PROP_DYNVAR);
+ }
+ if (varcode != null) {
+ dynvars.put(varcode, varname);
+ }
+ }
+ } catch (Exception e) {
+ dynvars = null;
+ }
+ }
+
+ public void service(HttpServletRequest httpReq,
+ HttpServletResponse httpResp)
+ throws ServletException, IOException {
+ boolean running_state = CMS.isInRunningState();
+
+ if (!running_state)
+ throw new IOException(
+ "CMS server is not ready to serve.");
+
+ if (mAuthMgr != null) {
+ try {
+ authenticate(httpReq);
+ } catch (EBaseException e) {
+ mServletCtx.log(CMS.getLogMessage("CMSGW_FILE_NO_ACCESS", e.toString()));
+ httpResp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+ }
+
+ httpResp.setContentType("application/x-javascript");
+ httpResp.setHeader("Pragma", "no-cache");
+
+ try {
+ ServletOutputStream os = httpResp.getOutputStream();
+
+ if (os != null) {
+ if (dynvars != null) {
+ Enumeration<Integer> k = dynvars.keys();
+
+ while (k.hasMoreElements()) {
+ String toBeWritten;
+ Integer varcode = k.nextElement();
+
+ if (varcode.equals(VAR_SERVERDATE)) {
+ toBeWritten = dynvars.get(varcode) +
+ "=" +
+ getServerDate() +
+ ";\n";
+
+ os.print(toBeWritten);
+ }
+
+ if (varcode.equals(VAR_SUBSYSTEMNAME)) {
+ if (getSubsystemName() != null) {
+ toBeWritten = dynvars.get(varcode) +
+ "=" + "\"" +
+ getSubsystemName() + "\"" +
+ ";\n";
+ os.print(toBeWritten);
+ }
+ }
+
+ if (varcode.equals(VAR_HTTP)) {
+ if (getHttp(httpReq) != null) {
+ toBeWritten = dynvars.get(varcode) +
+ "=" + "\"" +
+ getHttp(httpReq) + "\"" +
+ ";\n";
+ os.print(toBeWritten);
+ }
+ }
+
+ if (varcode.equals(VAR_CLA_CRL_URL)) {
+ if (getImportCrlUrl() != null) {
+ toBeWritten = dynvars.get(varcode) +
+ "=" + "\"" +
+ getImportCrlUrl() + "\"" +
+ ";\n";
+ os.print(toBeWritten);
+ }
+ }
+
+ if (varcode.equals(VAR_AUTHMGRS)) {
+ toBeWritten = "";
+ IAuthSubsystem as = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ Enumeration<IAuthManager> ame = as.getAuthManagers();
+
+ Date d = CMS.getCurrentDate();
+ long now = d.getTime();
+
+ if (now > (mAuthMgrCacheTime + 1000 * AUTHMGRCACHE)) {
+ int i = 0;
+
+ StringBuffer sb = new StringBuffer();
+ while (ame.hasMoreElements()) {
+ IAuthManager am = ame.nextElement();
+ String amName = am.getImplName();
+
+ AuthMgrPlugin ap = as.getAuthManagerPluginImpl(amName);
+
+ if (ap.isVisible()) {
+ sb.append("authmanager[");
+ sb.append(i);
+ sb.append("]=\"");
+ sb.append(amName);
+ sb.append("\";\n");
+ i++;
+ }
+ }
+ toBeWritten = sb.toString();
+ mAuthMgrCacheString = toBeWritten;
+ mAuthMgrCacheTime = now;
+ } else {
+ toBeWritten = mAuthMgrCacheString;
+ }
+ if (toBeWritten.length() != 0) {
+ os.print("authmanager = new Array();\n");
+ os.print(toBeWritten);
+ }
+ }
+
+ }
+ }
+ os.close();
+ }
+
+ } catch (IOException e) {
+ throw new ServletException("couldn't get outputstream");
+ }
+ }
+
+ private String getServerDate() {
+ Date d = new Date();
+ String now = Long.toString(d.getTime());
+
+ return now;
+ }
+
+ private String getSubsystemName() {
+ return VAR_SUBSYSTEMNAME_VALUE;
+ }
+
+ private String getHttp(HttpServletRequest httpReq) {
+ if (httpReq.isSecure())
+ return "false";
+ else
+ return "true";
+ }
+
+ private String getImportCrlUrl() {
+ return mCrlurl;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/GetStats.java b/base/server/cms/src/com/netscape/cms/servlet/base/GetStats.java
new file mode 100644
index 000000000..5fbed7bbc
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/GetStats.java
@@ -0,0 +1,185 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.base;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.util.IStatsSubsystem;
+import com.netscape.certsrv.util.StatsEvent;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Retrieve information.
+ *
+ * @version $Revision$, $Date$
+ */
+public class GetStats extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3336253558044271816L;
+ private final static String TPL_FILE = "getStats.template";
+ private String mFormPath = null;
+
+ public GetStats() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template
+ * file "getOCSPInfo.template" to render the result page.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success to display own output.
+
+ // coming from agent
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, httpReq, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+ StatsEvent st = statsSub.getMainStatsEvent();
+
+ String op = httpReq.getParameter("op");
+ if (op != null && op.equals("clear")) {
+ statsSub.resetCounters();
+ }
+
+ header.addStringValue("startTime", statsSub.getStartTime().toString());
+ header.addStringValue("curTime", (new Date()).toString());
+ parse(argSet, st, 0);
+
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+ public String getSep(int level) {
+ StringBuffer s = new StringBuffer();
+ for (int i = 0; i < level; i++) {
+ s.append("-");
+ }
+ return s.toString();
+ }
+
+ public void parse(CMSTemplateParams argSet, StatsEvent st, int level) {
+ Enumeration<String> names = st.getSubEventNames();
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ StatsEvent subSt = st.getSubEvent(name);
+
+ IArgBlock rarg = CMS.createArgBlock();
+ rarg.addStringValue("name", getSep(level) + " " + subSt.getName());
+ rarg.addLongValue("noOfOp", subSt.getNoOfOperations());
+ rarg.addLongValue("timeTaken", subSt.getTimeTaken());
+ rarg.addLongValue("max", subSt.getMax());
+ rarg.addLongValue("min", subSt.getMin());
+ rarg.addLongValue("percentage", subSt.getPercentage());
+ rarg.addLongValue("avg", subSt.getAvg());
+ rarg.addLongValue("stddev", subSt.getStdDev());
+ argSet.addRepeatRecord(rarg);
+
+ parse(argSet, subSt, level + 1);
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/IndexServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/IndexServlet.java
new file mode 100644
index 000000000..c81005b3b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/IndexServlet.java
@@ -0,0 +1,111 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.base;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.common.CMSGateway;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cms.servlet.common.IndexTemplateFiller;
+
+/**
+ * This is the servlet that builds the index page in
+ * various ports.
+ *
+ * @version $Revision$, $Date$
+ */
+public class IndexServlet extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -8632685610380549L;
+
+ public final static String PROP_TEMPLATE = "template";
+
+ private final static String INFO = "indexServlet";
+
+ private String mTemplateName = null;
+
+ public IndexServlet() {
+ super();
+ }
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mTemplateName = sc.getInitParameter(PROP_TEMPLATE);
+
+ /*
+ mTemplates.put(CMSRequest.SUCCESS,
+ new CMSLoadTemplate(
+ PROP_SUCCESS_TEMPLATE, PROP_SUCCESS_TEMPLATE_FILLER,
+ mTemplateName, new IndexTemplateFiller()));
+ */
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ public CMSRequest newCMSRequest() {
+ return new CMSRequest();
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Serves HTTP request.
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ if (CMSGateway.getEnableAdminEnroll() &&
+ mAuthority != null &&
+ mAuthority instanceof ICertificateAuthority) {
+ try {
+ cmsReq.getHttpResp().sendRedirect("/ca/adminEnroll.html");
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAIL_REDIRECT_ADMIN_ENROLL", e.toString()));
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_REDIRECTING_ADMINENROLL1",
+ e.toString()));
+ }
+ return;
+ } else {
+ try {
+ renderTemplate(
+ cmsReq, mTemplateName, new IndexTemplateFiller());
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAIL_RENDER_TEMPLATE", mTemplateName, e.toString()));
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSG_ERROR_DISPLAY_TEMPLATE"));
+ }
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java b/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java
new file mode 100644
index 000000000..23e540f0e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.base;
+
+import java.lang.reflect.Method;
+import java.security.cert.CertificateEncodingException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.cert.CertData;
+import com.netscape.certsrv.logging.IAuditor;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * Base class for CMS RESTful resources
+ *
+ * @author alee
+ *
+ */
+public class PKIService {
+
+ public static final String HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----";
+ public static final String TRAILER = "-----END NEW CERTIFICATE REQUEST-----";
+
+ // caching parameters
+ public static final int DEFAULT_LONG_CACHE_LIFETIME = 1000;
+
+ public ILogger logger = CMS.getLogger();
+ public IAuditor auditor = CMS.getAuditor();
+
+ public Response createOKResponse(Object object) {
+ return Response.ok(object).build();
+ }
+
+ public Response sendConditionalGetResponse(int ctime, Object object, Request request) {
+ CacheControl cc = new CacheControl();
+ cc.setMaxAge(ctime);
+ EntityTag tag = new EntityTag(Integer.toString(object.hashCode()));
+
+ ResponseBuilder builder = request.evaluatePreconditions(tag);
+ if (builder != null) {
+ builder.cacheControl(cc);
+ return builder.build();
+ }
+
+ builder = Response.ok(object);
+ builder.cacheControl(cc);
+ builder.tag(tag);
+ return builder.build();
+ }
+
+ public CertData createCertificateData(org.mozilla.jss.crypto.X509Certificate cert)
+ throws CertificateEncodingException {
+ CertData data = new CertData();
+ String b64 = HEADER + CMS.BtoA(cert.getEncoded()) + TRAILER;
+ data.setEncoded(b64);
+ return data;
+ }
+
+ public Locale getLocale(HttpHeaders headers) {
+
+ if (headers == null) return Locale.getDefault();
+
+ List<Locale> locales = headers.getAcceptableLanguages();
+ if (locales == null || locales.isEmpty()) return Locale.getDefault();
+
+ return locales.get(0);
+ }
+
+ public String getUserMessage(String messageId, HttpHeaders headers, String... params) {
+ return CMS.getUserMessage(getLocale(headers), messageId, params);
+ }
+
+ public void log(int source, int level, String message) {
+
+ if (logger == null) return;
+
+ logger.log(ILogger.EV_SYSTEM,
+ null,
+ source,
+ level,
+ getClass().getSimpleName() + ": " + message);
+ }
+
+ public void audit(String message, String scope, String type, String id, Map<String, String> params, String status) {
+
+ if (auditor == null) return;
+
+ String auditMessage = CMS.getLogMessage(
+ message,
+ auditor.getSubjectID(),
+ status,
+ auditor.getParamString(scope, type, id, params));
+
+ auditor.log(auditMessage);
+ }
+
+ /**
+ * Get the values of the fields annotated with @FormParam.
+ */
+ public Map<String, String> getParams(Object object) {
+
+ Map<String, String> map = new HashMap<String, String>();
+
+ // for each fields in the object
+ for (Method method : object.getClass().getMethods()) {
+ FormParam element = method.getAnnotation(FormParam.class);
+ if (element == null) continue;
+
+ String name = element.value();
+
+ try {
+ // get the value from the object
+ Object value = method.invoke(object);
+
+ // put the value in the map
+ map.put(name, value == null ? null : value.toString());
+
+ } catch (Exception e) {
+ // ignore inaccessible fields
+ e.printStackTrace();
+ }
+ }
+
+ return map;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/PortsServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/PortsServlet.java
new file mode 100644
index 000000000..4b1b48108
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/PortsServlet.java
@@ -0,0 +1,90 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.base;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cmsutil.xml.XMLObject;
+
+/**
+ * This servlet returns port information.
+ *
+ * @version $Revision$, $Date$
+ */
+public class PortsServlet extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3750153734073658934L;
+
+ public PortsServlet() {
+ }
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override these to output directly ourselves.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ mTemplates.remove(ICMSRequest.ERROR);
+ }
+
+ /**
+ * Serves HTTP request.
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ // process query if authentication is successful
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ String secure = req.getParameter("secure");
+ String port = null;
+
+ if (secure.equals("true"))
+ port = CMS.getEESSLPort();
+ else
+ port = CMS.getEENonSSLPort();
+
+ try {
+ XMLObject xmlObj = null;
+ xmlObj = new XMLObject();
+
+ Node root = xmlObj.createRoot("XMLResponse");
+ xmlObj.addItemToContainer(root, "Status", SUCCESS);
+ xmlObj.addItemToContainer(root, "Port", port);
+ byte[] cb = xmlObj.toByteArray();
+ outputResult(resp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("Failed to send the XML output");
+ }
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {
+ // do nothing, ie, it will not return the default javascript.
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/ProxyServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/ProxyServlet.java
new file mode 100644
index 000000000..315d330a9
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/ProxyServlet.java
@@ -0,0 +1,247 @@
+/* CMS_SDK_LICENSE_TEXT */
+
+package com.netscape.cms.servlet.base;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+
+/**
+ * This is a servlet that proxies request to another servlet.
+ *
+ * SERVLET REDIRECTION
+ * Specify the URL of a servlet to forward the request to
+ * destServlet: /ee/ca/newservlet
+ *
+ * PARAMETER MAPPING
+ * In the servlet configuration (as an init-param in web.xml) you
+ * can optionally specify a value for the parameter 'parameterMap'
+ * which contains a list of HTTP parameters which should be
+ * translated to new names.
+ *
+ * parameterMap: name1->newname1,name2->newname2
+ *
+ * Optionally, names can be set to static values:
+ *
+ * parameterMap: name1->name2=value
+ *
+ * Examples:
+ * Consider the following HTTP input parameters:
+ * vehicle:car make:ford model:explorer
+ *
+ * The following config strings will have this effect:
+ * parameterMap: make->manufacturer,model->name=expedition,->suv=true
+ * output: vehicle:car manufactuer:ford model:expedition suv:true
+ *
+ * @version $Revision$, $Date$
+ */
+public class ProxyServlet extends HttpServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2535349161521094539L;
+ private String mDest = null;
+ private String mDestContext = null;
+ private String mSrcContext = null;
+ private String mAppendPathInfo = null;
+ private Vector<String> mMatchStrings = new Vector<String>();
+ private String mDestServletOnNoMatch = null;
+ private String mAppendPathInfoOnNoMatch = null;
+ private Map<String, String> mParamMap = new HashMap<String, String>();
+ private Map<String, String[]> mParamValue = new HashMap<String, String[]>();
+
+ public ProxyServlet() {
+ }
+
+ private void parseParamTable(String s) {
+ if (s == null)
+ return;
+
+ String[] params = s.split(",");
+ for (int i = 0; i < params.length; i++) {
+ String p = params[i];
+ if (p != null) {
+ String[] paramNames = p.split("->");
+ if (paramNames.length != 2) {
+ }
+ String from = paramNames[0];
+ String to = paramNames[1];
+ if (from != null && to != null) {
+ String[] splitTo = to.split("=");
+ String toName = splitTo[0];
+ if (from.length() > 0) {
+ mParamMap.put(from, toName);
+ }
+ if (splitTo.length == 2) {
+ String toValue = splitTo[1];
+ String toValues[] = new String[1];
+ toValues[0] = toValue;
+ mParamValue.put(toName, toValues);
+ }
+ }
+ }
+ }
+ }
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ String mMatchStrs = sc.getInitParameter("matchURIStrings");
+ if (mMatchStrs != null && (!mMatchStrs.equals(""))) {
+ StringTokenizer st = new StringTokenizer(mMatchStrs, ",");
+ while (st.hasMoreTokens()) {
+ mMatchStrings.addElement(st.nextToken());
+ }
+ }
+ mDestServletOnNoMatch = sc.getInitParameter("destServletOnNoMatch");
+ mDestContext = sc.getInitParameter("destContext");
+ mDest = sc.getInitParameter("destServlet");
+ mSrcContext = sc.getInitParameter("srcContext");
+ mAppendPathInfo = sc.getInitParameter("appendPathInfo");
+ mAppendPathInfoOnNoMatch = sc.getInitParameter("appendPathInfoOnNoMatch");
+ String map = sc.getInitParameter("parameterMap");
+ if (map != null) {
+ parseParamTable(map);
+ }
+ }
+
+ public void service(HttpServletRequest req, HttpServletResponse res) throws
+ IOException, ServletException {
+ RequestDispatcher dispatcher = null;
+ String dest = mDest;
+ String uri = req.getRequestURI();
+
+ // check if match strings are specified. If it is, we need
+ // to deal with the alternate dest
+ if (mMatchStrings.size() != 0) {
+ boolean matched = false;
+ for (int i = 0; i < mMatchStrings.size(); i++) {
+ String t = mMatchStrings.elementAt(i);
+ if (uri.indexOf(t) != -1) {
+ matched = true;
+ }
+ }
+ if (!matched) {
+ dest = mDestServletOnNoMatch;
+ // append Path info for OCSP request in Get method
+ if (mAppendPathInfoOnNoMatch != null &&
+ !mAppendPathInfoOnNoMatch.equals("")) {
+ dest = dest + uri.replace(mAppendPathInfoOnNoMatch, "");
+ }
+ }
+ }
+ if (dest == null || dest.equals("")) {
+ // mapping everything
+ dest = uri;
+ dest = dest.replaceFirst(mSrcContext, "");
+ }
+ if (mAppendPathInfo != null && !mAppendPathInfo.equals("")) {
+ dest = dest + uri.replace(mAppendPathInfo, "");
+ }
+ if (mDestContext != null && !mDestContext.equals("")) {
+ dispatcher = getServletContext().getContext(mDestContext).getRequestDispatcher(dest);
+ } else {
+ dispatcher = req.getRequestDispatcher(dest);
+ }
+
+ // If a parameter map was specified
+ if (mParamMap != null && !mParamMap.isEmpty()) {
+ // Make a new wrapper with the new parameters
+ ProxyWrapper r = new ProxyWrapper(req);
+ r.setParameterMapAndValue(mParamMap, mParamValue);
+ req = r;
+ }
+
+ dispatcher.forward(req, res);
+ }
+}
+
+class ProxyWrapper extends HttpServletRequestWrapper {
+ private Map<String, String> mMap = null;
+ private Map<String, String[]> mValueMap = null;
+
+ public ProxyWrapper(HttpServletRequest req) {
+ super(req);
+ }
+
+ public void setParameterMapAndValue(Map<String, String> m, Map<String, String[]> v) {
+ if (m != null)
+ mMap = m;
+ if (v != null)
+ mValueMap = v;
+ }
+
+ public Map<String, String[]> getParameterMap() {
+ try {
+ // If we haven't specified any parameter mapping, just
+ // use the regular implementation
+ if (mMap == null)
+ return super.getParameterMap();
+ else {
+ // Make a new Map for us to put stuff in
+ Map<String, String[]> n = new HashMap<String, String[]>();
+ // get the HTTP parameters the user supplied.
+ Map<String, String[]> m = super.getParameterMap();
+ Set<Map.Entry<String, String[]>> s = m.entrySet();
+ Iterator<Map.Entry<String, String[]>> i = s.iterator();
+ while (i.hasNext()) {
+ Map.Entry<String, String[]> me = i.next();
+ String name = me.getKey();
+ String[] values = me.getValue();
+ String newname = null;
+ if (name != null) {
+ newname = mMap.get(name);
+ }
+
+ // No mapping specified, just use existing name/value
+ if (newname == null || mValueMap == null) {
+ n.put(name, values);
+ } else { // new name specified
+ Object o = mValueMap.get(newname);
+ // check if new (static) value specified
+ if (o == null) {
+ n.put(newname, values);
+ } else {
+ String newvalues[] = mValueMap.get(newname);
+ n.put(newname, newvalues);
+ }
+ }
+ }
+ // Now, deal with static values set in the config
+ // which weren't set in the HTTP request
+ Set<Map.Entry<String, String[]>> s2 = mValueMap.entrySet();
+ Iterator<Map.Entry<String, String[]>> i2 = s2.iterator();
+ // Cycle through all the static values
+ while (i2.hasNext()) {
+ Map.Entry<String, String[]> me2 = i2.next();
+ String name2 = me2.getKey();
+ if (n.get(name2) == null) {
+ String[] values2 = me2.getValue();
+ // If the parameter is not set in the map
+ // Set it now
+ n.put(name2, values2);
+ }
+ }
+
+ return n;
+ }
+ } catch (NullPointerException npe) {
+ CMS.debug(npe);
+ return null;
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/RESTServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/RESTServlet.java
new file mode 100644
index 000000000..050c0920a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/RESTServlet.java
@@ -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.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.base;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+
+public class RESTServlet extends HttpServlet {
+
+ private static final long serialVersionUID = -466592331169846158L;
+
+ public void service(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ CMS.debug("RESTServlet: Attempt to access REST services using " + request.getRequestURI());
+ CMS.debug("RESTServlet: sending 501 (not implemented)");
+
+ String error =
+ "The REST services are not available because this server is a legacy \n" +
+ "Dogtag 9 server. To access the REST services this server must be \n" +
+ "migrated into a new Dogtag 10 server.";
+
+ response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, error);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/SystemInfoServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/SystemInfoServlet.java
new file mode 100644
index 000000000..24210f377
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/SystemInfoServlet.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.base;
+
+import java.io.IOException;
+import java.util.Date;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+
+/**
+ * Displays detailed information about java VM internals, including
+ * current JVM memory usage, and detailed information about each
+ * thread.
+ * <p>
+ * Also allows user to trigger a new garbage collection
+ *
+ * @version $Revision$, $Date$
+ */
+public class SystemInfoServlet extends HttpServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -438134935001530607L;
+
+ public SystemInfoServlet() {
+ }
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ }
+
+ /**
+ * service the request, returning HTML to the client.
+ * This method has different behaviour depending on the
+ * value of the 'op' HTTP parameter.
+ * <UL>
+ * <LI>op = <i>undefined</i> - display a menu with links to the other functionality of this servlet
+ * <li>op = gc - tell the JVM that we want to do a garbage collection and to run finalizers (@see
+ * java.lang.Runtime.getRuntime#gc() )
+ * <li>op = general - display information about memory, and other JVM informatino
+ * <li>op = thread - display details about each thread.
+ * </UL>
+ *
+ * @see javax.servlet.http.HttpServlet#service(HttpServletRequest, HttpServletResponse)
+ */
+ public void service(HttpServletRequest request,
+ HttpServletResponse response)
+ throws ServletException, IOException {
+ String op = request.getParameter("op");
+
+ response.setContentType("text/html");
+ if (op == null) {
+ mainMenu(request, response);
+ } else if (op.equals("gc")) {
+ gc(request, response);
+ } else if (op.equals("general")) {
+ general(request, response);
+ } else if (op.equals("thread")) {
+ thread(request, response);
+ }
+ }
+
+ private void mainMenu(HttpServletRequest request,
+ HttpServletResponse response)
+ throws ServletException, IOException {
+ response.getWriter().println("<HTML>");
+ response.getWriter().println("<H1>");
+ response.getWriter().println("<a href=" + request.getServletPath() + ">");
+ response.getWriter().println("Main");
+ response.getWriter().println("</a>");
+ response.getWriter().println("</H1>");
+ response.getWriter().println("<p>");
+ response.getWriter().println("<table>");
+ response.getWriter().println("<tr>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("<li>");
+ response.getWriter().println("<a href=" + request.getServletPath() + "?op=general>");
+ response.getWriter().println("General");
+ response.getWriter().println("</a>");
+ response.getWriter().println("</td>");
+ response.getWriter().println("</tr>");
+ response.getWriter().println("<tr>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("<li>");
+ response.getWriter().println("<a href=" + request.getServletPath() + "?op=gc>");
+ response.getWriter().println("Garbage Collection");
+ response.getWriter().println("</a>");
+ response.getWriter().println("</td>");
+ response.getWriter().println("</tr>");
+ response.getWriter().println("<tr>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("<li>");
+ response.getWriter().println("<a href=" + request.getServletPath() + "?op=thread>");
+ response.getWriter().println("Thread Listing");
+ response.getWriter().println("</a>");
+ response.getWriter().println("</td>");
+ response.getWriter().println("</tr>");
+ response.getWriter().println("</table>");
+ response.getWriter().println("</HTML>");
+ }
+
+ private void gc(HttpServletRequest request,
+ HttpServletResponse response)
+ throws ServletException, IOException {
+ java.lang.Runtime.getRuntime().gc();
+ java.lang.Runtime.getRuntime().runFinalization();
+ response.getWriter().println("<HTML>");
+ response.getWriter().println("<H1>");
+ response.getWriter().println("<a href=" + request.getServletPath() + ">");
+ response.getWriter().println("Main");
+ response.getWriter().println("</a>");
+ response.getWriter().println(" : ");
+ response.getWriter().println("Garbage Collection");
+ response.getWriter().println("</H1>");
+ response.getWriter().println("<p>");
+ response.getWriter().println("The garbage collector has been executed.");
+ response.getWriter().println("</HTML>");
+ }
+
+ private void general(HttpServletRequest request,
+ HttpServletResponse response)
+ throws ServletException, IOException {
+ response.getWriter().println("<HTML>");
+ response.getWriter().println("<H1>");
+ response.getWriter().println("<a href=" + request.getServletPath() + ">");
+ response.getWriter().println("Main");
+ response.getWriter().println("</a>");
+ response.getWriter().println(" : ");
+ response.getWriter().println("General");
+ response.getWriter().println("</H1>");
+ response.getWriter().println("<p>");
+ response.getWriter().println("<table>");
+ response.getWriter().println("<tr>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("Server Started Time:");
+ response.getWriter().println("</td>");
+ response.getWriter().println("<td>");
+ response.getWriter().println(new Date(CMS.getStartupTime()));
+ response.getWriter().println("</td>");
+ response.getWriter().println("</tr>");
+ response.getWriter().println("<tr>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("Current Time:");
+ response.getWriter().println("</td>");
+ response.getWriter().println("<td>");
+ response.getWriter().println(new Date());
+ response.getWriter().println("</td>");
+ response.getWriter().println("</tr>");
+ response.getWriter().println("<tr>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("Available Processors:");
+ response.getWriter().println("</td>");
+ response.getWriter().println("<td>");
+ response.getWriter().println(Runtime.getRuntime().availableProcessors());
+ response.getWriter().println("</td>");
+ response.getWriter().println("</tr>");
+ response.getWriter().println("<tr>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("Active Threads:");
+ response.getWriter().println("</td>");
+ response.getWriter().println("<td>");
+ response.getWriter().println(Thread.activeCount());
+ response.getWriter().println("</td>");
+ response.getWriter().println("</tr>");
+ response.getWriter().println("<tr>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("Max Memory (in Bytes):");
+ response.getWriter().println("</td>");
+ response.getWriter().println("<td>");
+ response.getWriter().println(Runtime.getRuntime().maxMemory());
+ response.getWriter().println("</td>");
+ response.getWriter().println("</tr>");
+ response.getWriter().println("<tr>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("Total Memory (in Bytes):");
+ response.getWriter().println("</td>");
+ response.getWriter().println("<td>");
+ response.getWriter().println(Runtime.getRuntime().totalMemory());
+ response.getWriter().println("</td>");
+ response.getWriter().println("</tr>");
+ response.getWriter().println("<tr>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("Free Memory (in Bytes):");
+ response.getWriter().println("</td>");
+ response.getWriter().println("<td>");
+ response.getWriter().println(Runtime.getRuntime().freeMemory());
+ response.getWriter().println("</td>");
+ response.getWriter().println("</tr>");
+ response.getWriter().println("<tr>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("Free Memory / Total Memory:");
+ response.getWriter().println("</td>");
+ response.getWriter().println("<td>");
+ response.getWriter().println(
+ (Runtime.getRuntime().freeMemory() * 100) / Runtime.getRuntime().totalMemory() + "%");
+ response.getWriter().println("</td>");
+ response.getWriter().println("</tr>");
+ response.getWriter().println("</table>");
+ response.getWriter().println("</HTML>");
+ }
+
+ private void thread(HttpServletRequest request,
+ HttpServletResponse response)
+ throws ServletException, IOException {
+ response.getWriter().println("</table>");
+ response.getWriter().println("<HTML>");
+ response.getWriter().println("<H1>");
+ response.getWriter().println("<a href=" + request.getServletPath() + ">");
+ response.getWriter().println("Main");
+ response.getWriter().println("</a>");
+ response.getWriter().println(" : ");
+ response.getWriter().println("Thread Listing");
+ response.getWriter().println("</H1>");
+ response.getWriter().println("<p>");
+ response.getWriter().println("<table width=100% border=1>");
+ response.getWriter().println("<tr>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("<b>");
+ response.getWriter().println("#");
+ response.getWriter().println("</b>");
+ response.getWriter().println("</td>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("<b>");
+ response.getWriter().println("Name");
+ response.getWriter().println("</b>");
+ response.getWriter().println("</td>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("<b>");
+ response.getWriter().println("Priority");
+ response.getWriter().println("</b>");
+ response.getWriter().println("</td>");
+ response.getWriter().println("<td>");
+ response.getWriter().println("<b>");
+ response.getWriter().println("isDaemon");
+ response.getWriter().println("</b>");
+ response.getWriter().println("</td>");
+ response.getWriter().println("</tr>");
+ int active = Thread.activeCount();
+ Thread threads[] = new Thread[active];
+ int c = Thread.enumerate(threads);
+
+ for (int i = 0; i < c; i++) {
+ response.getWriter().println("<tr>");
+ response.getWriter().println("<td>");
+ response.getWriter().println(i);
+ response.getWriter().println("</td>");
+ response.getWriter().println("<td>");
+ response.getWriter().println(threads[i].getName());
+ response.getWriter().println("</td>");
+ response.getWriter().println("<td>");
+ response.getWriter().println(threads[i].getPriority());
+ response.getWriter().println("</td>");
+ response.getWriter().println("<td>");
+ if (threads[i].isDaemon()) {
+ response.getWriter().println("true");
+ } else {
+ response.getWriter().println("false");
+ }
+ response.getWriter().println("</td>");
+ response.getWriter().println("</tr>");
+ }
+ response.getWriter().println("</table>");
+ response.getWriter().println("</HTML>");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/UserInfo.java b/base/server/cms/src/com/netscape/cms/servlet/base/UserInfo.java
new file mode 100644
index 000000000..b509409da
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/UserInfo.java
@@ -0,0 +1,90 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.base;
+
+/**
+ * This class represents information about the client e.g. version,
+ * langauge, vendor.
+ *
+ * @version $Revision$, $Date$
+ */
+public class UserInfo {
+ public final static String MSIE = "MSIE";
+ public final static String MOZILLA = "Mozilla";
+
+ /**
+ * Constructs a user information object.
+ */
+ public UserInfo() {
+ }
+
+ /**
+ * Returns the user language.
+ *
+ * @param s user language info from the browser
+ * @return user language
+ */
+ public static String getUserLanguage(String s) {
+ // Does this contain a country code?
+ int pos = s.indexOf("-");
+
+ if (pos != -1) {
+ // Yes it does
+ return s.substring(0, pos);
+ }
+ return s;
+ }
+
+ /**
+ * Returns the user country.
+ *
+ * @param s user language info from the browser
+ * @return user country
+ */
+ public static String getUserCountry(String s) {
+ // Does this contain a country code?
+ int pos = s.indexOf("-");
+
+ if (pos != -1) {
+ // Yes it does
+ return s.substring(pos + 1);
+ }
+ return "";
+ }
+
+ /**
+ * Returns the users agent.
+ *
+ * @param s user language info from the browser
+ * @return user agent
+ */
+ public static String getUserAgent(String s) {
+ // Check for MSIE
+ if (s.indexOf(MSIE) != -1) {
+ return MSIE;
+ }
+
+ // Check for Netscape i.e. Mozilla
+ if (s.indexOf(MOZILLA) != -1) {
+ return MOZILLA;
+ }
+
+ // Don't know agent. Return empty string.
+ return "";
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java
new file mode 100644
index 000000000..71c10ead9
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java
@@ -0,0 +1,1074 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CertificateException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.InvalidityDateExtension;
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EMissingCredential;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertRecordList;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Revoke a certificate with a CMC-formatted revocation request
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMCRevReqServlet extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 4731070386698127770L;
+ public final static String GETCERTS_FOR_CHALLENGE_REQUEST = "getCertsForChallenge";
+ public static final String TOKEN_CERT_SERIAL = "certSerialToRevoke";
+ // revocation templates.
+ private final static String TPL_FILE = "revocationResult.template";
+ public static final String CRED_CMC = "cmcRequest";
+
+ private ICertificateRepository mCertDB = null;
+ private String mFormPath = null;
+ private IRequestQueue mQueue = null;
+ private IPublisherProcessor mPublisherProcessor = null;
+ private String mRequestID = null;
+ private final static String REVOKE = "revoke";
+ private final static String ON_HOLD = "on-hold";
+ private final static int ON_HOLD_REASON = 6;
+ private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST =
+ "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_5";
+ private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED =
+ "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED_7";
+
+ // http params
+ public static final String SERIAL_NO = TOKEN_CERT_SERIAL;
+ public static final String REASON_CODE = "reasonCode";
+ public static final String CHALLENGE_PHRASE = "challengePhrase";
+
+ // request attributes
+ public static final String SERIALNO_ARRAY = "serialNoArray";
+
+ public CMCRevReqServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+
+ super.init(sc);
+
+ String authorityId = mAuthority.getId();
+
+ mFormPath = "/" + authorityId + "/" + TPL_FILE;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mAuthority instanceof ICertificateAuthority) {
+ mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository();
+ }
+
+ if (mAuthority instanceof ICertAuthority) {
+ mPublisherProcessor = ((ICertAuthority) mAuthority).getPublisherProcessor();
+ }
+ mQueue = mAuthority.getRequestQueue();
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * <ul>
+ * <li>http.param cmcRequest the base-64 encoded CMC request
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+
+ String cmcAgentSerialNumber = null;
+ IArgBlock httpParams = cmsReq.getHttpParams();
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ CMS.debug("**** mFormPath = " + mFormPath);
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ String cmc = (String) httpParams.get(CRED_CMC);
+ if (cmc == null) {
+ throw new EMissingCredential(
+ CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_CMC));
+ }
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+ try {
+ authzToken = authorize(mAclMethod, authToken, mAuthzResourceName, "revoke");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ //IAuthToken authToken = getAuthToken(cmsReq);
+ //Object subject = authToken.get(CMCAuth.TOKEN_CERT_SERIAL);
+ //Object uid = authToken.get("uid");
+ //===========================
+ String authMgr = AuditFormat.NOAUTH;
+ BigInteger[] serialNoArray = null;
+
+ if (authToken != null) {
+ serialNoArray = authToken.getInBigIntegerArray(TOKEN_CERT_SERIAL);
+ }
+
+ Integer reasonCode = Integer.valueOf(0);
+ if (authToken != null) {
+ reasonCode = authToken.getInInteger(REASON_CODE);
+ }
+
+ String comments = "";
+ Date invalidityDate = null;
+ String revokeAll = null;
+ int verifiedRecordCount = 0;
+ int totalRecordCount = 0;
+
+ if (serialNoArray != null) {
+ totalRecordCount = serialNoArray.length;
+ verifiedRecordCount = serialNoArray.length;
+ }
+
+ X509CertImpl[] certs = null;
+
+ //for audit log.
+ String initiative = null;
+
+ if (mAuthMgr != null && mAuthMgr.equals("CMCAuth")) {
+ // request is from agent
+ if (authToken != null) {
+ authMgr = authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ String agentID = authToken.getInString("userid");
+
+ initiative = AuditFormat.FROMAGENT + " agentID: " + agentID +
+ " authenticated by " + authMgr;
+ }
+ } else {
+ initiative = AuditFormat.FROMUSER;
+ }
+
+ if ((serialNoArray != null) && (serialNoArray.length > 0)) {
+ if (mAuthority instanceof ICertificateAuthority) {
+ certs = new X509CertImpl[serialNoArray.length];
+
+ for (int i = 0; i < serialNoArray.length; i++) {
+ certs[i] =
+ ((ICertificateAuthority) mAuthority).getCertificateRepository().getX509Certificate(
+ serialNoArray[i]);
+ }
+
+ } else if (mAuthority instanceof IRegistrationAuthority) {
+ IRequest getCertsChallengeReq = null;
+
+ getCertsChallengeReq = mQueue.newRequest(
+ GETCERTS_FOR_CHALLENGE_REQUEST);
+ getCertsChallengeReq.setExtData(SERIALNO_ARRAY, serialNoArray);
+ mQueue.processRequest(getCertsChallengeReq);
+ RequestStatus status = getCertsChallengeReq.getRequestStatus();
+
+ if (status == RequestStatus.COMPLETE) {
+ certs = getCertsChallengeReq.getExtDataInCertArray(IRequest.OLD_CERTS);
+ header.addStringValue("request", getCertsChallengeReq.getRequestId().toString());
+ mRequestID = getCertsChallengeReq.getRequestId().toString();
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_FAIL_GET_CERT_CHALL_PWRD"));
+ }
+ }
+
+ header.addIntegerValue("totalRecordCount", serialNoArray.length);
+ header.addIntegerValue("verifiedRecordCount", serialNoArray.length);
+
+ for (int i = 0; i < serialNoArray.length; i++) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ serialNoArray[i], 16);
+ rarg.addStringValue("subject",
+ certs[i].getSubjectDN().toString());
+ rarg.addLongValue("validNotBefore",
+ certs[i].getNotBefore().getTime() / 1000);
+ rarg.addLongValue("validNotAfter",
+ certs[i].getNotAfter().getTime() / 1000);
+ //argSet.addRepeatRecord(rarg);
+ }
+
+ revokeAll = "(|(certRecordId=" + serialNoArray[0].toString() + "))";
+ cmcAgentSerialNumber = authToken.getInString(IAuthManager.CRED_SSL_CLIENT_CERT);
+ process(argSet, header, reasonCode.intValue(), invalidityDate, initiative, req, resp,
+ verifiedRecordCount, revokeAll, totalRecordCount,
+ comments, locale[0], cmcAgentSerialNumber);
+
+ } else {
+ header.addIntegerValue("totalRecordCount", 0);
+ header.addIntegerValue("verifiedRecordCount", 0);
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if ((serialNoArray == null) || (serialNoArray.length == 0)) {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ EBaseException ee = new EBaseException("No matched certificate is found");
+
+ cmsReq.setError(ee);
+ } else {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+ }
+
+ /**
+ * Process cert status change request using the Certificate Management
+ * protocol using CMS (CMC)
+ * <P>
+ *
+ * (Certificate Request - an "EE" cert status change request)
+ * <P>
+ *
+ * (Certificate Request Processed - an "EE" cert status change request)
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST used when a cert status change request (e. g. -
+ * "revocation") is made (before approval process)
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED used when a certificate status is
+ * changed (revoked, expired, on-hold, off-hold)
+ * </ul>
+ *
+ * @param argSet CMS template parameters
+ * @param header argument block
+ * @param reason revocation reason (0 - Unspecified, 1 - Key compromised,
+ * 2 - CA key compromised; should not be used, 3 - Affiliation changed,
+ * 4 - Certificate superceded, 5 - Cessation of operation, or
+ * 6 - Certificate is on hold)
+ * @param invalidityDate certificate validity date
+ * @param initiative string containing the audit format
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param verifiedRecordCount number of verified records
+ * @param revokeAll string containing information on all of the
+ * certificates to be revoked
+ * @param totalRecordCount total number of records (verified and unverified)
+ * @param comments string containing certificate comments
+ * @param locale the system locale
+ * @exception EBaseException an error has occurred
+ */
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ int reason, Date invalidityDate,
+ String initiative,
+ HttpServletRequest req,
+ HttpServletResponse resp,
+ int verifiedRecordCount,
+ String revokeAll,
+ int totalRecordCount,
+ String comments,
+ Locale locale, String cmcAgentSerialNumber)
+ throws EBaseException {
+ String eeSerialNumber = null;
+ if (cmcAgentSerialNumber != null) {
+ eeSerialNumber = cmcAgentSerialNumber;
+ } else {
+ X509CertImpl sslCert = (X509CertImpl) getSSLClientCertificate(req);
+ if (sslCert != null) {
+ eeSerialNumber = sslCert.getSerialNumber().toString();
+ }
+ }
+
+ boolean auditRequest = true;
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRequesterID = auditRequesterID(req);
+ String auditSerialNumber = auditSerialNumber(eeSerialNumber);
+ String auditRequestType = auditRequestType(reason);
+ RequestStatus auditApprovalStatus = null;
+ String auditReasonNum = String.valueOf(reason);
+
+ try {
+ int count = 0;
+ Vector<X509CertImpl> oldCertsV = new Vector<X509CertImpl>();
+ Vector<RevokedCertImpl> revCertImplsV = new Vector<RevokedCertImpl>();
+
+ // Construct a CRL reason code extension.
+ RevocationReason revReason = RevocationReason.fromInt(reason);
+ header.addIntegerValue("reasonCode", reason);
+ if (revReason != null) {
+ header.addStringValue("reason", revReason.toString());
+ } else {
+ header.addStringValue("error", "Invalid revocation reason: "+reason);
+ }
+ CRLReasonExtension crlReasonExtn = new CRLReasonExtension(revReason);
+
+ // Construct a CRL invalidity date extension.
+ InvalidityDateExtension invalidityDateExtn = null;
+
+ if (invalidityDate != null) {
+ invalidityDateExtn = new InvalidityDateExtension(invalidityDate);
+ }
+
+ // Construct a CRL extension for this request.
+ CRLExtensions entryExtn = new CRLExtensions();
+
+ if (crlReasonExtn != null) {
+ entryExtn.set(crlReasonExtn.getName(), crlReasonExtn);
+ }
+ if (invalidityDateExtn != null) {
+ entryExtn.set(invalidityDateExtn.getName(), invalidityDateExtn);
+ }
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ ICertRecordList list = mCertDB.findCertRecordsInList(
+ revokeAll, null, totalRecordCount);
+ Enumeration<ICertRecord> e = list.getCertRecords(0, totalRecordCount - 1);
+
+ while (e != null && e.hasMoreElements()) {
+ ICertRecord rec = e.nextElement();
+ X509CertImpl cert = rec.getCertificate();
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ cert.getSerialNumber(), 16);
+
+ if ((rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) &&
+ (revReason == null || revReason != RevocationReason.REMOVE_FROM_CRL)) {
+ rarg.addStringValue("error", "Certificate " +
+ cert.getSerialNumber().toString() +
+ " is already revoked.");
+ } else {
+ oldCertsV.addElement(cert);
+
+ RevokedCertImpl revCertImpl =
+ new RevokedCertImpl(cert.getSerialNumber(),
+ CMS.getCurrentDate(), entryExtn);
+
+ revCertImplsV.addElement(revCertImpl);
+ count++;
+ rarg.addStringValue("error", null);
+ }
+ argSet.addRepeatRecord(rarg);
+ }
+
+ } else if (mAuthority instanceof IRegistrationAuthority) {
+ String reqIdStr = null;
+
+ if (mRequestID != null && mRequestID.length() > 0)
+ reqIdStr = mRequestID;
+ Vector<String> serialNumbers = new Vector<String>();
+
+ if (revokeAll != null && revokeAll.length() > 0) {
+ for (int i = revokeAll.indexOf('='); i < revokeAll.length() && i > -1; i =
+ revokeAll.indexOf('=', i)) {
+ if (i > -1) {
+ i++;
+ while (i < revokeAll.length() && revokeAll.charAt(i) == ' ') {
+ i++;
+ }
+ String legalDigits = "0123456789";
+ int j = i;
+
+ while (j < revokeAll.length() &&
+ legalDigits.indexOf(revokeAll.charAt(j)) != -1) {
+ j++;
+ }
+ if (j > i) {
+ serialNumbers.addElement(revokeAll.substring(i, j));
+ }
+ }
+ }
+ }
+ if (reqIdStr != null && reqIdStr.length() > 0 && serialNumbers.size() > 0) {
+ IRequest certReq = mRequestQueue.findRequest(new RequestId(reqIdStr));
+ X509CertImpl[] certs = certReq.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ for (int i = 0; i < certs.length; i++) {
+ boolean addToList = false;
+
+ for (int j = 0; j < serialNumbers.size(); j++) {
+ if (certs[i].getSerialNumber().toString().equals(
+ serialNumbers.elementAt(j))) {
+ addToList = true;
+ break;
+ }
+ }
+ if (addToList) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ certs[i].getSerialNumber(), 16);
+ oldCertsV.addElement(certs[i]);
+
+ RevokedCertImpl revCertImpl =
+ new RevokedCertImpl(certs[i].getSerialNumber(),
+ CMS.getCurrentDate(), entryExtn);
+
+ revCertImplsV.addElement(revCertImpl);
+ count++;
+ rarg.addStringValue("error", null);
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ } else {
+ String b64eCert = req.getParameter("b64eCertificate");
+
+ if (b64eCert != null) {
+ byte[] certBytes = Utils.base64decode(b64eCert);
+ X509CertImpl cert = new X509CertImpl(certBytes);
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ cert.getSerialNumber(), 16);
+ oldCertsV.addElement(cert);
+
+ RevokedCertImpl revCertImpl =
+ new RevokedCertImpl(cert.getSerialNumber(),
+ CMS.getCurrentDate(), entryExtn);
+
+ revCertImplsV.addElement(revCertImpl);
+ count++;
+ rarg.addStringValue("error", null);
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ }
+
+ header.addIntegerValue("totalRecordCount", count);
+
+ X509CertImpl[] oldCerts = new X509CertImpl[count];
+ RevokedCertImpl[] revCertImpls = new RevokedCertImpl[count];
+ BigInteger[] certSerialNumbers = new BigInteger[count];
+
+ for (int i = 0; i < count; i++) {
+ oldCerts[i] = oldCertsV.elementAt(i);
+ revCertImpls[i] = revCertImplsV.elementAt(i);
+ certSerialNumbers[i] = oldCerts[i].getSerialNumber();
+ }
+
+ IRequest revReq = null;
+ if (revReason != null && revReason == RevocationReason.REMOVE_FROM_CRL) {
+ revReq = mQueue.newRequest(IRequest.UNREVOCATION_REQUEST);
+ } else {
+ revReq = mQueue.newRequest(IRequest.REVOCATION_REQUEST);
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType);
+
+ audit(auditMessage);
+
+ revReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_AGENT);
+ if (revReason != null && revReason == RevocationReason.REMOVE_FROM_CRL) {
+ revReq.setExtData(IRequest.REQ_TYPE, IRequest.UNREVOCATION_REQUEST);
+ revReq.setExtData(IRequest.OLD_SERIALS, certSerialNumbers);
+ } else {
+ revReq.setExtData(IRequest.CERT_INFO, revCertImpls);
+ revReq.setExtData(IRequest.REQ_TYPE, IRequest.REVOCATION_REQUEST);
+ revReq.setExtData(IRequest.REVOKED_REASON, reason);
+ revReq.setExtData(IRequest.OLD_CERTS, oldCerts);
+ if (comments != null) {
+ revReq.setExtData(IRequest.REQUESTOR_COMMENTS, comments);
+ }
+ }
+
+ // change audit processing from "REQUEST" to "REQUEST_PROCESSED"
+ // to distinguish which type of signed audit log message to save
+ // as a failure outcome in case an exception occurs
+ auditRequest = false;
+
+ mQueue.processRequest(revReq);
+
+ // retrieve the request status
+ auditApprovalStatus = revReq.getRequestStatus();
+
+ RequestStatus stat = revReq.getRequestStatus();
+
+ if (stat == RequestStatus.COMPLETE) {
+ // audit log the error
+ Integer result = revReq.getExtDataInInteger(IRequest.RESULT);
+
+ if (result.equals(IRequest.RES_ERROR)) {
+ String[] svcErrors =
+ revReq.getExtDataInStringArray(IRequest.SVCERRORS);
+
+ if (svcErrors != null && svcErrors.length > 0) {
+ for (int i = 0; i < svcErrors.length; i++) {
+ String err = svcErrors[i];
+
+ if (err != null) {
+ //cmsReq.setErrorDescription(err);
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ revReq.getRequestId(),
+ initiative,
+ "completed with error: " +
+ err,
+ oldCerts[j].getSubjectDN(),
+ oldCerts[j].getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString() }
+ );
+ }
+ }
+ }
+ }
+ }
+ return;
+ }
+
+ // audit log the success.
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ revReq.getRequestId(),
+ initiative,
+ "completed",
+ oldCerts[j].getSubjectDN(),
+ oldCerts[j].getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString() }
+ );
+ }
+ }
+
+ header.addStringValue("revoked", "yes");
+
+ Integer updateCRLResult =
+ revReq.getExtDataInInteger(IRequest.CRL_UPDATE_STATUS);
+
+ if (updateCRLResult != null) {
+ header.addStringValue("updateCRL", "yes");
+ if (updateCRLResult.equals(IRequest.RES_SUCCESS)) {
+ header.addStringValue("updateCRLSuccess", "yes");
+ } else {
+ header.addStringValue("updateCRLSuccess", "no");
+ String crlError =
+ revReq.getExtDataInString(IRequest.CRL_UPDATE_ERROR);
+
+ if (crlError != null)
+ header.addStringValue("updateCRLError",
+ crlError);
+ }
+ // let known crl publishing status too.
+ Integer publishCRLResult =
+ revReq.getExtDataInInteger(IRequest.CRL_PUBLISH_STATUS);
+
+ if (publishCRLResult != null) {
+ if (publishCRLResult.equals(IRequest.RES_SUCCESS)) {
+ header.addStringValue("publishCRLSuccess", "yes");
+ } else {
+ header.addStringValue("publishCRLSuccess", "no");
+ String publError =
+ revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR);
+
+ if (publError != null)
+ header.addStringValue("publishCRLError",
+ publError);
+ }
+ }
+ }
+ if (mAuthority instanceof ICertificateAuthority) {
+ // let known update and publish status of all crls.
+ Enumeration<ICRLIssuingPoint> otherCRLs =
+ ((ICertificateAuthority) mAuthority).getCRLIssuingPoints();
+
+ while (otherCRLs.hasMoreElements()) {
+ ICRLIssuingPoint crl = otherCRLs.nextElement();
+ String crlId = crl.getId();
+
+ if (crlId.equals(ICertificateAuthority.PROP_MASTER_CRL))
+ continue;
+ String updateStatusStr = crl.getCrlUpdateStatusStr();
+ Integer updateResult = revReq.getExtDataInInteger(updateStatusStr);
+
+ if (updateResult != null) {
+ if (updateResult.equals(IRequest.RES_SUCCESS)) {
+ CMS.debug("CMCRevReqServlet: " + CMS.getLogMessage("ADMIN_SRVLT_ADDING_HEADER",
+ updateStatusStr));
+ header.addStringValue(updateStatusStr, "yes");
+ } else {
+ String updateErrorStr = crl.getCrlUpdateErrorStr();
+
+ CMS.debug("CMCRevReqServlet: " + CMS.getLogMessage("ADMIN_SRVLT_ADDING_HEADER_NO",
+ updateStatusStr));
+ header.addStringValue(updateStatusStr, "no");
+ String error =
+ revReq.getExtDataInString(updateErrorStr);
+
+ if (error != null)
+ header.addStringValue(updateErrorStr,
+ error);
+ }
+ String publishStatusStr = crl.getCrlPublishStatusStr();
+ Integer publishResult =
+ revReq.getExtDataInInteger(publishStatusStr);
+
+ if (publishResult == null)
+ continue;
+ if (publishResult.equals(IRequest.RES_SUCCESS)) {
+ header.addStringValue(publishStatusStr, "yes");
+ } else {
+ String publishErrorStr =
+ crl.getCrlPublishErrorStr();
+
+ header.addStringValue(publishStatusStr, "no");
+ String error =
+ revReq.getExtDataInString(publishErrorStr);
+
+ if (error != null)
+ header.addStringValue(
+ publishErrorStr, error);
+ }
+ }
+ }
+ }
+
+ if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) {
+ header.addStringValue("dirEnabled", "yes");
+ Integer[] ldapPublishStatus =
+ revReq.getExtDataInIntegerArray("ldapPublishStatus");
+ int certsToUpdate = 0;
+ int certsUpdated = 0;
+
+ if (ldapPublishStatus != null) {
+ certsToUpdate = ldapPublishStatus.length;
+ for (int i = 0; i < certsToUpdate; i++) {
+ if (ldapPublishStatus[i] == IRequest.RES_SUCCESS) {
+ certsUpdated++;
+ }
+ }
+ }
+ header.addIntegerValue("certsUpdated", certsUpdated);
+ header.addIntegerValue("certsToUpdate", certsToUpdate);
+
+ // add crl publishing status.
+ String publError =
+ revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR);
+
+ if (publError != null) {
+ header.addStringValue("crlPublishError",
+ publError);
+ }
+ } else {
+ header.addStringValue("dirEnabled", "no");
+ }
+ header.addStringValue("error", null);
+
+ } else if (stat == RequestStatus.PENDING) {
+ header.addStringValue("error", "Request Pending");
+ header.addStringValue("revoked", "pending");
+ // audit log the pending
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ revReq.getRequestId(),
+ initiative,
+ "pending",
+ oldCerts[j].getSubjectDN(),
+ oldCerts[j].getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString() }
+ );
+ }
+ }
+
+ } else {
+ Vector<String> errors = revReq.getExtDataInStringVector(IRequest.ERRORS);
+ StringBuffer errorStr = new StringBuffer();
+
+ if (errors != null && errors.size() > 0) {
+ for (int ii = 0; ii < errors.size(); ii++) {
+ errorStr.append(errors.elementAt(ii));
+ ;
+ }
+ }
+ header.addStringValue("error", errorStr.toString());
+ header.addStringValue("revoked", "no");
+ // audit log the error
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ revReq.getRequestId(),
+ initiative,
+ stat.toString(),
+ oldCerts[j].getSubjectDN(),
+ oldCerts[j].getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString() }
+ );
+ }
+ }
+ }
+
+ // store a message in the signed audit log file
+ // if and only if "auditApprovalStatus" is
+ // "complete", "revoked", or "canceled"
+ if (auditApprovalStatus == RequestStatus.COMPLETE ||
+ auditApprovalStatus == RequestStatus.REJECTED ||
+ auditApprovalStatus == RequestStatus.CANCELED) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus == null ? ILogger.SIGNED_AUDIT_EMPTY_VALUE : auditApprovalStatus.toString());
+
+ audit(auditMessage);
+ }
+
+ } catch (CertificateException e) {
+ if (auditRequest) {
+ // store a "CERT_STATUS_CHANGE_REQUEST" failure
+ // message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType);
+
+ audit(auditMessage);
+ } else {
+ // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure
+ // message in the signed audit log file
+ // if and only if "auditApprovalStatus" is
+ // "complete", "revoked", or "canceled"
+ if (auditApprovalStatus == RequestStatus.COMPLETE ||
+ auditApprovalStatus == RequestStatus.REJECTED ||
+ auditApprovalStatus == RequestStatus.CANCELED) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus == null ? ILogger.SIGNED_AUDIT_EMPTY_VALUE : auditApprovalStatus.toString());
+
+ audit(auditMessage);
+ }
+ }
+
+ log(ILogger.LL_FAILURE, "error " + e);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, "error " + e);
+
+ if (auditRequest) {
+ // store a "CERT_STATUS_CHANGE_REQUEST" failure
+ // message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType);
+
+ audit(auditMessage);
+ } else {
+ // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure
+ // message in the signed audit log file
+ // if and only if "auditApprovalStatus" is
+ // "complete", "revoked", or "canceled"
+ if (auditApprovalStatus == RequestStatus.COMPLETE ||
+ auditApprovalStatus == RequestStatus.REJECTED ||
+ auditApprovalStatus == RequestStatus.CANCELED) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus == null ? ILogger.SIGNED_AUDIT_EMPTY_VALUE : auditApprovalStatus.toString());
+
+ audit(auditMessage);
+ }
+ }
+
+ throw e;
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED", e.toString()));
+
+ if (auditRequest) {
+ // store a "CERT_STATUS_CHANGE_REQUEST" failure
+ // message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType);
+
+ audit(auditMessage);
+ } else {
+ // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure
+ // message in the signed audit log file
+ // if and only if "auditApprovalStatus" is
+ // "complete", "revoked", or "canceled"
+ if (auditApprovalStatus == RequestStatus.COMPLETE ||
+ auditApprovalStatus == RequestStatus.REJECTED ||
+ auditApprovalStatus == RequestStatus.CANCELED) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus == null ? ILogger.SIGNED_AUDIT_EMPTY_VALUE : auditApprovalStatus.toString());
+
+ audit(auditMessage);
+ }
+ }
+
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED"));
+ } catch (Exception e) {
+ if (auditRequest) {
+ // store a "CERT_STATUS_CHANGE_REQUEST" failure
+ // message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType);
+
+ audit(auditMessage);
+ } else {
+ // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure
+ // message in the signed audit log file
+ // if and only if "auditApprovalStatus" is
+ // "complete", "revoked", or "canceled"
+ if (auditApprovalStatus == RequestStatus.COMPLETE ||
+ auditApprovalStatus == RequestStatus.REJECTED ||
+ auditApprovalStatus == RequestStatus.CANCELED) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus == null ? ILogger.SIGNED_AUDIT_EMPTY_VALUE : auditApprovalStatus.toString());
+
+ audit(auditMessage);
+ }
+ }
+
+ e.printStackTrace();
+ }
+
+ return;
+ }
+
+ /**
+ * Signed Audit Log Requester ID
+ *
+ * This method is called to obtain the "RequesterID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param req HTTP request
+ * @return id string containing the signed audit log message RequesterID
+ */
+ private String auditRequesterID(HttpServletRequest req) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String requesterID = null;
+
+ // Obtain the requesterID
+ requesterID = req.getParameter("requestId");
+
+ if (requesterID != null) {
+ requesterID = requesterID.trim();
+ } else {
+ requesterID = ILogger.UNIDENTIFIED;
+ }
+
+ return requesterID;
+ }
+
+ /**
+ * Signed Audit Log Serial Number
+ *
+ * This method is called to obtain the serial number of the certificate
+ * whose status is to be changed for a signed audit log message.
+ * <P>
+ *
+ * @param eeSerialNumber a string containing the un-normalized serialNumber
+ * @return id string containing the signed audit log message RequesterID
+ */
+ private String auditSerialNumber(String eeSerialNumber) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String serialNumber = null;
+
+ // Normalize the serialNumber
+ if (eeSerialNumber != null) {
+ serialNumber = eeSerialNumber.trim();
+
+ // convert it to hexadecimal
+ serialNumber = "0x"
+ + Integer.toHexString(
+ Integer.valueOf(serialNumber).intValue());
+ } else {
+ serialNumber = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ return serialNumber;
+ }
+
+ /**
+ * Signed Audit Log Request Type
+ *
+ * This method is called to obtain the "Request Type" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param reason an integer denoting the revocation reason
+ * @return string containing REVOKE or ON_HOLD
+ */
+ private String auditRequestType(int reason) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String requestType = null;
+
+ // Determine the revocation type based upon the revocation reason
+ if (reason == ON_HOLD_REASON) {
+ requestType = ON_HOLD;
+ } else {
+ requestType = REVOKE;
+ }
+
+ return requestType;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CertEnrollmentRequestFactory.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CertEnrollmentRequestFactory.java
new file mode 100644
index 000000000..7a26e8e21
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CertEnrollmentRequestFactory.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) 2012 Red Hat, Inc.
+//All rights reserved.
+//--- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.util.Enumeration;
+import java.util.Locale;
+
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.cert.CertEnrollmentRequest;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.ProfileInput;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.profile.ProfileInputFactory;
+
+public class CertEnrollmentRequestFactory {
+
+ public static CertEnrollmentRequest create(CMSRequest cmsReq, IProfile profile, Locale locale)
+ throws EProfileException {
+ IArgBlock params = cmsReq.getHttpParams();
+
+ CertEnrollmentRequest ret = new CertEnrollmentRequest();
+ ret.setProfileId(profile.getId());
+
+ // populate profile inputs
+ Enumeration<String> inputIds = profile.getProfileInputIds();
+ while (inputIds.hasMoreElements()) {
+ IProfileInput input = profile.getProfileInput(inputIds.nextElement());
+ ProfileInput addInput = ProfileInputFactory.create(input, params, locale);
+ ret.addInput(addInput);
+ }
+
+ return ret;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java
new file mode 100644
index 000000000..8ffa65d9b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Locale;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.cert.CertEnrollmentRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EDeferException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.ProfileAttribute;
+import com.netscape.certsrv.profile.ProfileInput;
+import com.netscape.certsrv.request.INotify;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.processors.Processor;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+public class CertProcessor extends Processor {
+
+ public CertProcessor(String id, Locale locale) throws EPropertyNotFound, EBaseException {
+ super(id, locale);
+ }
+
+ protected void setCredentialsIntoContext(HttpServletRequest request, IProfileAuthenticator authenticator,
+ IProfileContext ctx) {
+ Enumeration<String> authIds = authenticator.getValueNames();
+
+ if (authIds != null) {
+ CMS.debug("CertRequestSubmitter:setCredentialsIntoContext() authNames not null");
+ while (authIds.hasMoreElements()) {
+ String authName = authIds.nextElement();
+
+ CMS.debug("CertRequestSubmitter:setCredentialsIntoContext() authName:" +
+ authName);
+ if (request.getParameter(authName) != null) {
+ CMS.debug("CertRequestSubmitter:setCredentialsIntoContext() authName found in request");
+ ctx.set(authName, request.getParameter(authName));
+ } else {
+ CMS.debug("CertRequestSubmitter:setCredentialsIntoContext() authName not found in request");
+ }
+ }
+ } else {
+ CMS.debug("CertRequestSubmitter:setCredentialsIntoContext() authIds` null");
+ }
+ }
+
+ private void setInputsIntoRequest(CertEnrollmentRequest data, IProfile profile, IRequest req) {
+ // put profile inputs into a local map
+ HashMap<String, String> dataInputs = new HashMap<String, String>();
+ for (ProfileInput input : data.getInputs()) {
+ for (ProfileAttribute attr: input.getAttrs()) {
+ dataInputs.put(attr.getName(), attr.getValue());
+ }
+ }
+
+ // iterate over inputs in profile
+ Enumeration<String> inputIds = profile.getProfileInputIds();
+ if (inputIds != null) {
+ while (inputIds.hasMoreElements()) {
+ String inputId = inputIds.nextElement();
+ IProfileInput profileInput = profile.getProfileInput(inputId);
+ Enumeration<String> inputNames = profileInput.getValueNames();
+
+ if (inputNames != null) {
+ while (inputNames.hasMoreElements()) {
+ String inputName = inputNames.nextElement();
+ if (dataInputs.containsKey(inputName)) {
+ // special characters in subject names parameters must be escaped
+ if (inputName.matches("^sn_.*")) {
+ req.setExtData(inputName,
+ LDAPUtil.escapeRDNValue(dataInputs.get(inputName)));
+ } else {
+ req.setExtData(inputName, dataInputs.get(inputName));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * fill input info from orig request to the renew request.
+ * This is expected to be used by renewal where the request
+ * is retrieved from request record
+ */
+ private void setInputsIntoRequest(IRequest request, IProfile profile, IRequest req, Locale locale) {
+ // passing inputs into request
+ Enumeration<String> inputIds = profile.getProfileInputIds();
+
+ if (inputIds != null) {
+ while (inputIds.hasMoreElements()) {
+ String inputId = inputIds.nextElement();
+ IProfileInput profileInput = profile.getProfileInput(inputId);
+ Enumeration<String> inputNames = profileInput.getValueNames();
+
+ while (inputNames.hasMoreElements()) {
+ String inputName = inputNames.nextElement();
+ String inputValue = "";
+ CMS.debug("CertRequestSubmitter: setInputsIntoRequest() getting input name= " + inputName);
+ try {
+ inputValue = profileInput.getValue(inputName, locale, request);
+ } catch (Exception e) {
+ CMS.debug("CertRequestSubmitter: setInputsIntoRequest() getvalue() failed: " + e.toString());
+ }
+
+ if (inputValue != null) {
+ CMS.debug("CertRequestSubmitter: setInputsIntoRequest() setting value in ctx:" + inputValue);
+ req.setExtData(inputName, inputValue);
+ } else {
+ CMS.debug("CertRequestSubmitter: setInputsIntoRequest() value null");
+ }
+ }
+ }
+ }
+
+ }
+
+ protected String codeToReason(Locale locale, String errorCode) {
+ if (errorCode == null) return null;
+ if (errorCode.equals("1")) {
+ return CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR");
+ } else if (errorCode.equals("2")) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_DEFERRED");
+ } else if (errorCode.equals("3")) {
+ return CMS.getUserMessage(locale, "CMS_PROFILE_REJECTED");
+ }
+ return null;
+ }
+
+ protected String submitRequests(Locale locale, IProfile profile, IAuthToken authToken, IRequest[] reqs) {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRequesterID = ILogger.UNIDENTIFIED;
+ String auditInfoCertValue = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ String errorCode = null;
+ String errorReason = null;
+
+ for (IRequest req : reqs) {
+ try {
+ // reset the "auditRequesterID"
+ auditRequesterID = auditRequesterID(req);
+
+ // print request debug
+ if (req != null) {
+ Enumeration<String> reqKeys = req.getExtDataKeys();
+ while (reqKeys.hasMoreElements()) {
+ String reqKey = reqKeys.nextElement();
+ String reqVal = req.getExtDataInString(reqKey);
+ if (reqVal != null) {
+ CMS.debug("CertRequestSubmitter: key=$request." + reqKey + "$ value=" + reqVal);
+ }
+ }
+ }
+
+ profile.submit(authToken, req);
+ req.setRequestStatus(RequestStatus.COMPLETE);
+
+ // reset the "auditInfoCertValue"
+ auditInfoCertValue = auditInfoCertValue(req);
+
+ if (auditInfoCertValue != null) {
+ if (!(auditInfoCertValue.equals(
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE))) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_ACCEPTANCE,
+ auditInfoCertValue);
+
+ audit(auditMessage);
+ }
+ }
+ } catch (EDeferException e) {
+ // return defer message to the user
+ req.setRequestStatus(RequestStatus.PENDING);
+ // need to notify
+ INotify notify = profile.getRequestQueue().getPendingNotify();
+ if (notify != null) {
+ notify.notify(req);
+ }
+
+ CMS.debug("CertRequestSubmitter: submit " + e.toString());
+ errorCode = "2";
+ errorReason = CMS.getUserMessage(locale, "CMS_PROFILE_DEFERRED", e.toString());
+
+ // do NOT store a message in the signed audit log file
+ // as this errorCode indicates that a process has been
+ // deferred for manual acceptance/cancellation/rejection
+ } catch (ERejectException e) {
+ // return error to the user
+ req.setRequestStatus(RequestStatus.REJECTED);
+ CMS.debug("CertRequestSubmitter: submit " + e.toString());
+ errorCode = "3";
+ errorReason = CMS.getUserMessage(locale, "CMS_PROFILE_REJECTED", e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_REJECTION,
+ errorReason);
+
+ audit(auditMessage);
+ } catch (Throwable e) {
+ // return error to the user
+ e.printStackTrace();
+ CMS.debug("CertRequestSubmitter: submit " + e.toString());
+ errorCode = "1";
+ errorReason = CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR");
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_REJECTION,
+ errorReason);
+
+ audit(auditMessage);
+ }
+
+ try {
+ if (errorCode == null) {
+ profile.getRequestQueue().markAsServiced(req);
+ } else {
+ profile.getRequestQueue().updateRequest(req);
+ }
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ CMS.debug("CertRequestSubmitter: updateRequest " + e.toString());
+ }
+ }
+ return errorCode;
+ }
+
+ protected void populateRequests(CertEnrollmentRequest data, boolean isRenewal,
+ Locale locale, Date origNotAfter, String origSubjectDN, IRequest origReq, String profileId,
+ IProfile profile, IProfileContext ctx, IProfileAuthenticator authenticator, IAuthToken authToken,
+ IRequest[] reqs) throws EBaseException {
+ for (IRequest req : reqs) {
+ boolean fromRA = false;
+ String uid = "";
+
+ // adding parameters to request
+ if (isRenewal) {
+ setInputsIntoRequest(origReq, profile, req, locale);
+ req.setExtData("origNotAfter", BigInteger.valueOf(origNotAfter.getTime()));
+ req.setExtData(IProfileAuthenticator.AUTHENTICATED_NAME, origSubjectDN);
+ req.setRequestType("renewal");
+ } else {
+ setInputsIntoRequest(data, profile, req);
+ }
+
+ // serial auth token into request
+ if (authToken != null) {
+ Enumeration<String> tokenNames = authToken.getElements();
+ while (tokenNames.hasMoreElements()) {
+ String tokenName = tokenNames.nextElement();
+ String[] tokenVals = authToken.getInStringArray(tokenName);
+ if (tokenVals != null) {
+ for (int i = 0; i < tokenVals.length; i++) {
+ req.setExtData(ARG_AUTH_TOKEN + "." + tokenName + "[" + i + "]", tokenVals[i]);
+ }
+ } else {
+ String tokenVal = authToken.getInString(tokenName);
+ if (tokenVal != null) {
+ req.setExtData(ARG_AUTH_TOKEN + "." + tokenName, tokenVal);
+ // if RA agent, auto assign the request
+ if (tokenName.equals("uid"))
+ uid = tokenVal;
+ if (tokenName.equals("group") && tokenVal.equals("Registration Manager Agents")) {
+ fromRA = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (fromRA) {
+ CMS.debug("CertRequestSubmitter: request from RA: " + uid);
+ req.setExtData(ARG_REQUEST_OWNER, uid);
+ }
+
+ // put profile framework parameters into the request
+ req.setExtData(ARG_PROFILE, "true");
+ req.setExtData(ARG_PROFILE_ID, profileId);
+ if (isRenewal)
+ req.setExtData(ARG_RENEWAL_PROFILE_ID, data.getProfileId());
+ req.setExtData(ARG_PROFILE_APPROVED_BY, profile.getApprovedBy());
+ String setId = profile.getPolicySetId(req);
+
+ if (setId == null) {
+ // no profile set found
+ CMS.debug("CertRequestSubmitter: no profile policy set found");
+ throw new EBaseException(CMS.getUserMessage(locale, "CMS_PROFILE_NO_POLICY_SET_FOUND"));
+ }
+
+ CMS.debug("CertRequestSubmitter profileSetid=" + setId);
+ req.setExtData(ARG_PROFILE_SET_ID, setId);
+ req.setExtData(ARG_PROFILE_REMOTE_HOST, data.getRemoteHost());
+ req.setExtData(ARG_PROFILE_REMOTE_ADDR, data.getRemoteAddr());
+
+ CMS.debug("CertRequestSubmitter: request " + req.getRequestId().toString());
+
+ CMS.debug("CertRequestSubmitter: populating request inputs");
+ // give authenticator a chance to populate the request
+ if (authenticator != null) {
+ authenticator.populate(authToken, req);
+ }
+ profile.populateInput(ctx, req);
+ profile.populate(req);
+ }
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CertRequestDAO.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CertRequestDAO.java
new file mode 100644
index 000000000..d4785e957
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CertRequestDAO.java
@@ -0,0 +1,206 @@
+// --- 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) 2011 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Random;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.UriInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.cert.CertEnrollmentRequest;
+import com.netscape.certsrv.cert.CertRequestInfo;
+import com.netscape.certsrv.cert.CertRequestInfos;
+import com.netscape.certsrv.cert.CertReviewResponse;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.request.CMSRequestInfo;
+import com.netscape.certsrv.request.CMSRequestInfos;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestNotFoundException;
+import com.netscape.cms.servlet.processors.Processor;
+import com.netscape.cms.servlet.request.CMSRequestDAO;
+
+/**
+ * @author alee
+ *
+ */
+public class CertRequestDAO extends CMSRequestDAO {
+ private IRequestQueue queue;
+ private ICertificateAuthority ca;
+ IProfileSubsystem ps;
+ private Random random = null;
+
+ public static final String ATTR_SERIALNO = "serialNumber";
+
+ public CertRequestDAO() {
+ super("ca");
+ ca = (ICertificateAuthority) CMS.getSubsystem("ca");
+ queue = ca.getRequestQueue();
+ if (ca.noncesEnabled()) {
+ random = new Random();
+ }
+ ps = (IProfileSubsystem) CMS.getSubsystem(IProfileSubsystem.ID);
+ }
+
+ /**
+ * Finds list of requests matching the specified search filter.
+ *
+ * If the filter corresponds to a VLV search, then that search is executed and the pageSize
+ * and start parameters are used. Otherwise, the maxResults and maxTime parameters are
+ * used in the regularly indexed search.
+ *
+ * @param filter - ldap search filter
+ * @param start - start position for VLV search
+ * @param pageSize - page size for VLV search
+ * @param maxResults - max results to be returned in normal search
+ * @param maxTime - max time for normal search
+ * @param uriInfo - uri context of request
+ * @return collection of key request info
+ * @throws EBaseException
+ */
+
+ @SuppressWarnings("unchecked")
+ public CertRequestInfos listRequests(String filter, RequestId start, int pageSize, int maxResults, int maxTime,
+ UriInfo uriInfo) throws EBaseException {
+
+ CertRequestInfos ret = new CertRequestInfos();
+
+ CMSRequestInfos cmsInfos = listCMSRequests(filter, start, pageSize, maxResults, maxTime, uriInfo);
+
+ Collection<? extends CMSRequestInfo> cmsList = cmsInfos.getRequests();
+
+ // We absolutely know 100% that this list is a list
+ // of CertRequestInfo objects. This is because the method
+ // createCMSRequestInfo. Is the only one adding to it
+
+ List<CertRequestInfo> list = (List<CertRequestInfo>) cmsList;
+ ret.setRequests(list);
+
+ ret.setLinks(cmsInfos.getLinks());
+
+ return ret;
+ }
+
+ /**
+ * Gets info for a specific request
+ *
+ * @param id
+ * @return info for specific request
+ * @throws EBaseException
+ */
+ public CertRequestInfo getRequest(RequestId id, UriInfo uriInfo) throws EBaseException {
+ IRequest request = queue.findRequest(id);
+ if (request == null) {
+ return null;
+ }
+ CertRequestInfo info = createCMSRequestInfo(request, uriInfo);
+ return info;
+ }
+
+ /**
+ * Gets info for a specific request
+ *
+ * @param id
+ * @return info for specific request
+ * @throws EBaseException
+ */
+ public CertReviewResponse reviewRequest(HttpServletRequest servletRequest, RequestId id,
+ UriInfo uriInfo, Locale locale) throws EBaseException {
+ IRequest request = queue.findRequest(id);
+ if (request == null) {
+ return null;
+ }
+ String profileId = request.getExtDataInString("profileId");
+ IProfile profile = ps.getProfile(profileId);
+ CertReviewResponse info = CertReviewResponseFactory.create(request, profile, uriInfo, locale);
+
+ if (ca.noncesEnabled()) {
+ // generate nonce
+ long n = random.nextLong();
+
+ // store nonce in session
+ Map<Object, Long> nonces = ca.getNonces(servletRequest, "cert-request");
+ nonces.put(info.getRequestId().toBigInteger(), n);
+
+ // return nonce to client
+ info.setNonce(Long.toString(n));
+ }
+ return info;
+ }
+
+ /**
+ * Submits an enrollment request and processes it.
+ *
+ * @param data
+ * @return info for the request submitted.
+ * @throws EBaseException
+ * @throws ServletException
+ */
+ public CertRequestInfos submitRequest(CertEnrollmentRequest data, HttpServletRequest request, UriInfo uriInfo,
+ Locale locale) throws EBaseException {
+
+ CertRequestInfos ret = new CertRequestInfos();
+
+ HashMap<String, Object> results = null;
+ if (data.getIsRenewal()) {
+ RenewalProcessor processor = new RenewalProcessor("caProfileSubmit", locale);
+ results = processor.processRenewal(data, request);
+ } else {
+ EnrollmentProcessor processor = new EnrollmentProcessor("caProfileSubmit", locale);
+ results = processor.processEnrollment(data, request);
+ }
+
+ IRequest reqs[] = (IRequest[]) results.get(Processor.ARG_REQUESTS);
+ for (IRequest req : reqs) {
+ CertRequestInfo info = CertRequestInfoFactory.create(req, uriInfo);
+ ret.addRequest(info);
+ }
+
+ // TODO - what happens if the errorCode is internal error ?
+
+ return ret;
+ }
+
+ public void changeRequestState(RequestId id, HttpServletRequest request, CertReviewResponse data,
+ Locale locale, String op) throws EBaseException {
+ IRequest ireq = queue.findRequest(id);
+ if (ireq == null) {
+ throw new RequestNotFoundException(id);
+ }
+
+ RequestProcessor processor = new RequestProcessor("caProfileProcess", locale);
+ processor.processRequest(request, data, ireq, op);
+ }
+
+ @Override
+ public CertRequestInfo createCMSRequestInfo(IRequest request, UriInfo uriInfo) {
+ return CertRequestInfoFactory.create(request, uriInfo);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CertRequestInfoFactory.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CertRequestInfoFactory.java
new file mode 100644
index 000000000..64e045d0d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CertRequestInfoFactory.java
@@ -0,0 +1,86 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.cert;
+
+import java.math.BigInteger;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.cert.CertRequestInfo;
+import com.netscape.certsrv.cert.CertRequestResource;
+import com.netscape.certsrv.cert.CertResource;
+import com.netscape.certsrv.dbs.certdb.CertId;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+
+public class CertRequestInfoFactory {
+
+ public static CertRequestInfo create(IRequest request, UriInfo uriInfo) {
+
+ CertRequestInfo info = new CertRequestInfo();
+
+ String requestType = request.getRequestType();
+ RequestStatus requestStatus = request.getRequestStatus();
+
+ info.setRequestType(requestType);
+ info.setRequestStatus(requestStatus);
+
+ info.setCertRequestType(request.getExtDataInString("cert_request_type"));
+
+ Path certRequestPath = CertRequestResource.class.getAnnotation(Path.class);
+ RequestId requestId = request.getRequestId();
+
+ UriBuilder reqBuilder = uriInfo.getBaseUriBuilder();
+ reqBuilder.path(certRequestPath.value() + "/" + requestId);
+ info.setRequestURL(reqBuilder.build().toString());
+
+ Integer result = request.getExtDataInInteger(IRequest.RESULT);
+ if (result == null || result.equals(IRequest.RES_SUCCESS)) {
+ info.setOperationResult(CertRequestInfo.RES_SUCCESS);
+ } else {
+ info.setOperationResult(CertRequestInfo.RES_ERROR);
+ String error = request.getExtDataInString(IRequest.ERROR);
+ info.setErrorMessage(error);
+ }
+
+ if (requestType == null || requestStatus != RequestStatus.COMPLETE)
+ return info;
+
+ X509CertImpl impl = request.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
+ if (impl == null)
+ return info;
+
+ BigInteger serialNo = impl.getSerialNumber();
+ info.setCertId(new CertId(serialNo));
+
+ Path certPath = CertResource.class.getAnnotation(Path.class);
+ UriBuilder certBuilder = uriInfo.getBaseUriBuilder();
+ certBuilder.path(certPath.value() + "/" + serialNo);
+
+ info.setCertURL(certBuilder.build().toString());
+
+ return info;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CertReviewResponseFactory.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CertReviewResponseFactory.java
new file mode 100644
index 000000000..6071b1dcb
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CertReviewResponseFactory.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) 2012 Red Hat, Inc.
+//All rights reserved.
+//--- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.UriInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.cert.CertReviewResponse;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.IProfilePolicy;
+import com.netscape.certsrv.profile.PolicyConstraint;
+import com.netscape.certsrv.profile.PolicyDefault;
+import com.netscape.certsrv.profile.ProfileInput;
+import com.netscape.certsrv.profile.ProfilePolicy;
+import com.netscape.certsrv.profile.ProfilePolicySet;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.processors.Processor;
+import com.netscape.cms.servlet.profile.PolicyConstraintFactory;
+import com.netscape.cms.servlet.profile.PolicyDefaultFactory;
+import com.netscape.cms.servlet.profile.ProfileInputFactory;
+
+public class CertReviewResponseFactory {
+
+ public static CertReviewResponse create(IRequest request, IProfile profile, UriInfo uriInfo, Locale locale) throws EBaseException {
+ CertReviewResponse ret = new CertReviewResponse();
+
+ if (request.getRequestType().equals("renewal")) {
+ ret.setIsRenewal(true);
+ } else {
+ ret.setIsRenewal(false);
+ }
+
+ ret.setRequestId(request.getRequestId());
+ ret.setRequestType(request.getRequestType());
+ ret.setRequestStatus(request.getRequestStatus().toString());
+ if (request.getRequestOwner() == null) {
+ ret.setRequestOwner("");
+ } else {
+ ret.setRequestOwner(request.getRequestOwner());
+ }
+ ret.setRequestCreationTime(request.getCreationTime().toString());
+ ret.setRequestModificationTime(request.getModificationTime().toString());
+
+ ret.setProfileId(profile.getId());
+ ret.setProfileApprovedBy(request.getExtDataInString("profileApprovedBy"));
+ ret.setProfileSetId(request.getExtDataInString("profileSetId"));
+ if (profile.isVisible()) {
+ ret.setProfileIsVisible("true");
+ } else {
+ ret.setProfileIsVisible("false");
+ }
+
+ ret.setProfileName(profile.getName(locale));
+ ret.setProfileDescription(profile.getDescription(locale));
+ ret.setProfileRemoteHost(request.getExtDataInString("profileRemoteHost"));
+ ret.setProfileRemoteAddr(request.getExtDataInString("profileRemoteAddr"));
+ if (request.getExtDataInString("requestNotes") == null) {
+ ret.setRequestNotes("");
+ } else {
+ ret.setRequestNotes(request.getExtDataInString("requestNotes"));
+ }
+
+ // populate profile inputs
+ Enumeration<String> inputIds = profile.getProfileInputIds();
+ while (inputIds.hasMoreElements()) {
+ IProfileInput input = profile.getProfileInput(inputIds.nextElement());
+ ProfileInput addInput = ProfileInputFactory.create(input, request, locale);
+ ret.addInput(addInput);
+ }
+
+ String profileSetId = request.getExtDataInString("profileSetId");
+ CMS.debug("createAgentCertRequestInfo: profileSetId=" + profileSetId);
+ Enumeration<String> policyIds = (profileSetId != null && profileSetId.length() > 0) ?
+ profile.getProfilePolicyIds(profileSetId) : null;
+ ProfilePolicySet dataPolicySet = new ProfilePolicySet();
+
+ if (policyIds != null) {
+ while (policyIds.hasMoreElements()) {
+ String id = policyIds.nextElement();
+ CMS.debug("policyId:" + id);
+ IProfilePolicy policy = profile.getProfilePolicy(profileSetId, id);
+ ProfilePolicy dataPolicy = new ProfilePolicy();
+
+ //populate defaults
+ IPolicyDefault def = policy.getDefault();
+ PolicyDefault dataDef = PolicyDefaultFactory.create(request, locale, def);
+ dataPolicy.setDef(dataDef);
+
+ //populate constraints
+ // TODO - fix this.
+ PolicyConstraint dataCons = PolicyConstraintFactory.create(locale, policy.getConstraint(),
+ policy.getConstraint().getClass().getSimpleName());
+ dataPolicy.setConstraint(dataCons);
+
+ dataPolicySet.addPolicy(dataPolicy);
+ }
+ }
+
+
+ ret.addProfilePolicySet(dataPolicySet);
+
+ // TODO populate profile outputs
+ return ret;
+ }
+
+ public static CertReviewResponse create(
+ CMSRequest cmsReq, IProfile profile, boolean noncesEnabled, Locale locale)
+ throws EPropertyException, EProfileException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ IRequest ireq = cmsReq.getIRequest();
+ IArgBlock params = cmsReq.getHttpParams();
+
+ CertReviewResponse ret = new CertReviewResponse();
+ ret.setProfileId(profile.getId());
+ ret.setRequestNotes(req.getParameter("requestNotes"));
+ ret.setRequestId(ireq.getRequestId());
+
+ if (noncesEnabled) {
+ ret.setNonce(req.getParameter(Processor.ARG_REQUEST_NONCE));
+ }
+
+ // populate profile policy values
+ String profileSetId = ireq.getExtDataInString("profileSetId");
+ Enumeration<String> policyIds = (profileSetId != null && profileSetId.length() > 0) ?
+ profile.getProfilePolicyIds(profileSetId) : null;
+ ProfilePolicySet dataPolicySet = new ProfilePolicySet();
+
+ if (policyIds != null) {
+ while (policyIds.hasMoreElements()) {
+ String id = policyIds.nextElement();
+ CMS.debug("policyId:" + id);
+ IProfilePolicy policy = profile.getProfilePolicy(profileSetId, id);
+ com.netscape.certsrv.profile.ProfilePolicy dataPolicy =
+ new com.netscape.certsrv.profile.ProfilePolicy();
+
+ //populate defaults
+ IPolicyDefault def = policy.getDefault();
+ PolicyDefault dataDef = PolicyDefaultFactory.create(params, locale, def);
+ dataPolicy.setDef(dataDef);
+
+ dataPolicySet.addPolicy(dataPolicy);
+ CMS.debug(dataPolicy.toString());
+ }
+ }
+
+ ret.addProfilePolicySet(dataPolicySet);
+
+ return ret;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CertService.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CertService.java
new file mode 100644
index 000000000..6f46d9eb5
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CertService.java
@@ -0,0 +1,618 @@
+// --- 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) 2011 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.cert;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.URI;
+import java.security.InvalidKeyException;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+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.UriInfo;
+
+import netscape.security.pkcs.ContentInfo;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.pkcs.SignerInfo;
+import netscape.security.provider.RSAPublicKey;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509Key;
+
+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.EBaseException;
+import com.netscape.certsrv.base.ICertPrettyPrint;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.base.UnauthorizedException;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.cert.CertData;
+import com.netscape.certsrv.cert.CertDataInfo;
+import com.netscape.certsrv.cert.CertDataInfos;
+import com.netscape.certsrv.cert.CertNotFoundException;
+import com.netscape.certsrv.cert.CertRequestInfo;
+import com.netscape.certsrv.cert.CertResource;
+import com.netscape.certsrv.cert.CertRetrievalRequest;
+import com.netscape.certsrv.cert.CertRevokeRequest;
+import com.netscape.certsrv.cert.CertSearchRequest;
+import com.netscape.certsrv.cert.CertUnrevokeRequest;
+import com.netscape.certsrv.dbs.EDBRecordNotFoundException;
+import com.netscape.certsrv.dbs.certdb.CertId;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.realm.PKIPrincipal;
+import com.netscape.cms.servlet.base.PKIService;
+import com.netscape.cms.servlet.processors.Processor;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * @author alee
+ *
+ */
+public class CertService extends PKIService implements CertResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ ICertificateAuthority authority;
+ ICertificateRepository repo;
+ Random random;
+
+ public final static int DEFAULT_SIZE = 20;
+
+ public CertService() {
+ authority = (ICertificateAuthority) CMS.getSubsystem("ca");
+ if (authority.noncesEnabled()) {
+ random = new Random();
+ }
+ repo = authority.getCertificateRepository();
+ }
+
+ private void validateRequest(CertId id) {
+ if (id == null) {
+ throw new BadRequestException("Invalid id in CertResourceService.validateRequest.");
+ }
+ }
+
+ @Override
+ public CertData getCert(CertId id) {
+ return getCert(id, false);
+ }
+
+ @Override
+ public CertData reviewCert(CertId id) {
+ return getCert(id, true);
+ }
+
+ public CertData getCert(CertId id, boolean generateNonce) {
+ validateRequest(id);
+
+ CertRetrievalRequest data = new CertRetrievalRequest();
+ data.setCertId(id);
+
+ CertData certData = null;
+
+ try {
+ certData = getCert(data, generateNonce);
+ } catch (EDBRecordNotFoundException e) {
+ throw new CertNotFoundException(id);
+ } catch (EBaseException e) {
+ throw new PKIException(e.getMessage(), e);
+ } catch (CertificateEncodingException e) {
+ throw new PKIException(e.getMessage(), e);
+ }
+
+ return certData;
+ }
+
+ @Override
+ public CertRequestInfo revokeCACert(CertId id, CertRevokeRequest request) {
+ return revokeCert(id, request, true);
+ }
+
+ @Override
+ public CertRequestInfo revokeCert(CertId id, CertRevokeRequest request) {
+ return revokeCert(id, request, false);
+ }
+
+ public CertRequestInfo revokeCert(CertId id, CertRevokeRequest request, boolean caCert) {
+ RevocationReason revReason = request.getReason();
+ if (revReason == RevocationReason.REMOVE_FROM_CRL) {
+ CertUnrevokeRequest unrevRequest = new CertUnrevokeRequest();
+ unrevRequest.setRequestID(request.getRequestID());
+ return unrevokeCert(id, unrevRequest);
+ }
+
+ RevocationProcessor processor;
+ try {
+ processor = new RevocationProcessor("caDoRevoke-agent", getLocale(headers));
+ processor.setStartTime(CMS.getCurrentDate().getTime());
+
+ // TODO: set initiative based on auth info
+ processor.setInitiative(AuditFormat.FROMAGENT);
+
+ processor.setSerialNumber(id);
+ processor.setRequestID(request.getRequestID());
+
+ processor.setRevocationReason(revReason);
+ processor.setRequestType(revReason == RevocationReason.CERTIFICATE_HOLD
+ ? RevocationProcessor.ON_HOLD : RevocationProcessor.REVOKE);
+ processor.setInvalidityDate(request.getInvalidityDate());
+ processor.setComments(request.getComments());
+
+ processor.setAuthority(authority);
+
+ } catch (EBaseException e) {
+ throw new PKIException(e.getMessage());
+ }
+
+ try {
+ X509Certificate clientCert = null;
+ try {
+ clientCert = Processor.getSSLClientCertificate(servletRequest);
+ } catch (EBaseException e) {
+ // No client certificate, ignore.
+ }
+
+ ICertRecord clientRecord = null;
+ BigInteger clientSerialNumber = null;
+ String clientSubjectDN = null;
+
+ if (clientCert != null) {
+ clientSerialNumber = clientCert.getSerialNumber();
+ clientSubjectDN = clientCert.getSubjectDN().toString();
+ clientRecord = processor.getCertificateRecord(clientSerialNumber);
+
+ // Verify client cert is not revoked.
+ // TODO: This should be checked during authentication.
+ if (clientRecord.getStatus().equals(ICertRecord.STATUS_REVOKED)) {
+ throw new UnauthorizedException(CMS.getLogMessage("CMSGW_UNAUTHORIZED"));
+ }
+ }
+
+ if (authority.noncesEnabled() &&
+ !processor.isMemberOfSubsystemGroup(clientCert)) {
+ processor.validateNonce(servletRequest, "cert-revoke", id.toBigInteger(), request.getNonce());
+
+ }
+
+ // Find target cert record if different from client cert.
+ ICertRecord targetRecord = id.equals(clientSerialNumber) ? clientRecord : processor.getCertificateRecord(id);
+ X509CertImpl targetCert = targetRecord.getCertificate();
+
+ processor.createCRLExtension();
+
+ PKIPrincipal principal = (PKIPrincipal)servletRequest.getUserPrincipal();
+ // TODO: do not hard-code role name
+ String subjectDN = principal.hasRole("Certificate Manager Agents") ?
+ null : clientSubjectDN;
+
+ processor.validateCertificateToRevoke(subjectDN, targetRecord, caCert);
+ processor.addCertificateToRevoke(targetCert);
+ processor.createRevocationRequest();
+
+ processor.auditChangeRequest(ILogger.SUCCESS);
+
+ } catch (PKIException e) {
+ processor.log(ILogger.LL_FAILURE, e.getMessage());
+ processor.auditChangeRequest(ILogger.FAILURE);
+ throw e;
+
+ } catch (EBaseException e) {
+ processor.log(ILogger.LL_FAILURE, "Error " + e);
+ processor.auditChangeRequest(ILogger.FAILURE);
+
+ throw new PKIException(e.getMessage());
+
+ } catch (IOException e) {
+ processor.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED_1", e.toString()));
+ processor.auditChangeRequest(ILogger.FAILURE);
+
+ throw new PKIException(CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED"));
+ }
+
+ // change audit processing from "REQUEST" to "REQUEST_PROCESSED"
+ // to distinguish which type of signed audit log message to save
+ // as a failure outcome in case an exception occurs
+
+ try {
+ processor.processRevocationRequest();
+
+ processor.auditChangeRequestProcessed(ILogger.SUCCESS);
+
+ } catch (EBaseException e) {
+ processor.log(ILogger.LL_FAILURE, "Error " + e);
+ processor.auditChangeRequestProcessed(ILogger.FAILURE);
+
+ throw new PKIException(e.getMessage());
+ }
+
+ try {
+ IRequest certRequest = processor.getRequest();
+ CertRequestDAO dao = new CertRequestDAO();
+ return dao.getRequest(certRequest.getRequestId(), uriInfo);
+
+ } catch (EBaseException e) {
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public CertRequestInfo unrevokeCert(CertId id, CertUnrevokeRequest request) {
+ RevocationProcessor processor;
+ try {
+ processor = new RevocationProcessor("caDoUnrevoke", getLocale(headers));
+
+ // TODO: set initiative based on auth info
+ processor.setInitiative(AuditFormat.FROMAGENT);
+
+ processor.setSerialNumber(id);
+ processor.setRequestID(request.getRequestID());
+ processor.setRevocationReason(RevocationReason.CERTIFICATE_HOLD);
+ processor.setAuthority(authority);
+
+ } catch (EBaseException e) {
+ throw new PKIException(e.getMessage());
+ }
+
+ try {
+ processor.addSerialNumberToUnrevoke(id.toBigInteger());
+ processor.createUnrevocationRequest();
+
+ processor.auditChangeRequest(ILogger.SUCCESS);
+
+ } catch (EBaseException e) {
+ processor.log(ILogger.LL_FAILURE, "Error " + e);
+ processor.auditChangeRequest(ILogger.FAILURE);
+
+ throw new PKIException(e.getMessage());
+ }
+
+ // change audit processing from "REQUEST" to "REQUEST_PROCESSED"
+ // to distinguish which type of signed audit log message to save
+ // as a failure outcome in case an exception occurs
+
+ try {
+ processor.processUnrevocationRequest();
+
+ processor.auditChangeRequestProcessed(ILogger.SUCCESS);
+
+ } catch (EBaseException e) {
+ processor.log(ILogger.LL_FAILURE, "Error " + e);
+ processor.auditChangeRequestProcessed(ILogger.FAILURE);
+
+ throw new PKIException(e.getMessage());
+ }
+
+ try {
+ IRequest certRequest = processor.getRequest();
+ CertRequestDAO dao = new CertRequestDAO();
+ return dao.getRequest(certRequest.getRequestId(), uriInfo);
+
+ } catch (EBaseException e) {
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ private String createSearchFilter(String status) {
+ String filter = "";
+
+ if ((status == null)) {
+ filter = "(serialno=*)";
+ return filter;
+ }
+
+ if (status != null) {
+ filter += "(certStatus=" + LDAPUtil.escapeFilter(status) + ")";
+ }
+
+ return filter;
+ }
+
+ private String createSearchFilter(CertSearchRequest data) {
+ if (data == null) {
+ return null;
+ }
+ FilterBuilder builder = new FilterBuilder(data);
+ return builder.buildFilter();
+ }
+
+ @Override
+ public CertDataInfos listCerts(String status, int maxResults, int maxTime) {
+ // get ldap filter
+ String filter = createSearchFilter(status);
+ CMS.debug("listKeys: filter is " + filter);
+
+ CertDataInfos infos;
+ try {
+ infos = getCertList(filter, maxResults, maxTime);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Error listing certs in CertsResourceService.listCerts!", e);
+ }
+ return infos;
+ }
+
+ @Override
+ public CertDataInfos searchCerts(CertSearchRequest data, Integer start, Integer size) {
+ if (data == null) {
+ throw new BadRequestException("Search request is null.");
+ }
+ start = start == null ? 0 : start;
+ size = size == null ? DEFAULT_SIZE : size;
+ String filter = createSearchFilter(data);
+
+ CertDataInfos infos = new CertDataInfos();
+
+ Enumeration<ICertRecord> e = null;
+ try {
+
+ e = repo.findCertRecords(filter);
+
+ int i = 0;
+
+ // skip to the start of the page
+ for (; i < start && e.hasMoreElements(); i++)
+ e.nextElement();
+
+ // return entries up to the page size
+ for (; i < start + size && e.hasMoreElements(); i++) {
+ ICertRecord user = e.nextElement();
+ infos.addCertData(createCertDataInfo(user));
+ }
+
+ // count the total entries
+ for (; e.hasMoreElements(); i++)
+ e.nextElement();
+
+ if (start > 0) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start - size, 0)).build();
+ infos.addLink(new Link("prev", uri));
+ }
+
+ if (start + size < i) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start + size).build();
+ infos.addLink(new Link("next", uri));
+ }
+ } catch (Exception e1) {
+ throw new PKIException("Error listing certs in CertsResourceService.listCerts!", e1);
+ }
+
+ return infos;
+ }
+
+ /**
+ * Returns list of certs meeting specified search filter.
+ * Currently, vlv searches are not used for certs.
+ *
+ * @param filter
+ * @param maxResults
+ * @param maxTime
+ * @param uriInfo
+ * @return
+ * @throws EBaseException
+ * @throws InvalidKeyException
+ */
+ private CertDataInfos getCertList(String filter, int maxResults, int maxTime)
+ throws EBaseException, InvalidKeyException {
+ List<CertDataInfo> list = new ArrayList<CertDataInfo>();
+ Enumeration<ICertRecord> e = null;
+
+ e = repo.searchCertificates(filter, maxResults, maxTime);
+ if (e == null) {
+ throw new EBaseException("search results are null");
+ }
+
+ while (e.hasMoreElements()) {
+ ICertRecord rec = e.nextElement();
+ if (rec != null) {
+ list.add(createCertDataInfo(rec));
+ }
+ }
+
+ CertDataInfos ret = new CertDataInfos();
+ ret.setCertInfos(list);
+
+ return ret;
+ }
+
+ public CertData getCert(CertRetrievalRequest data, boolean generateNonce) throws EBaseException, CertificateEncodingException {
+ CertId certId = data.getCertId();
+
+ //find the cert in question
+ ICertRecord record = repo.readCertificateRecord(certId.toBigInteger());
+ X509CertImpl cert = record.getCertificate();
+
+ CertData certData = new CertData();
+
+ certData.setSerialNumber(certId);
+
+ Principal issuerDN = cert.getIssuerDN();
+ if (issuerDN != null) certData.setIssuerDN(issuerDN.toString());
+
+ Principal subjectDN = cert.getSubjectDN();
+ if (subjectDN != null) certData.setSubjectDN(subjectDN.toString());
+
+ String base64 = CMS.getEncodedCert(cert);
+ certData.setEncoded(base64);
+
+ ICertPrettyPrint print = CMS.getCertPrettyPrint(cert);
+ certData.setPrettyPrint(print.toString(getLocale(headers)));
+
+ String p7Str = getCertChainData(cert);
+ certData.setPkcs7CertChain(p7Str);
+
+ Date notBefore = cert.getNotBefore();
+ if (notBefore != null) certData.setNotBefore(notBefore.toString());
+
+ Date notAfter = cert.getNotAfter();
+ if (notAfter != null) certData.setNotAfter(notAfter.toString());
+
+ certData.setStatus(record.getStatus());
+
+ if (authority.noncesEnabled() && generateNonce) {
+ // generate nonce
+ long n = random.nextLong();
+ // store nonce in session
+ Map<Object, Long> nonces = authority.getNonces(servletRequest, "cert-revoke");
+ nonces.put(certId.toBigInteger(), n);
+ // return nonce to client
+ certData.setNonce(n);
+ }
+
+ URI uri = uriInfo.getBaseUriBuilder().path(CertResource.class).path("{id}").build(certId.toHexString());
+ certData.setLink(new Link("self", uri));
+
+ return certData;
+ }
+
+ private CertDataInfo createCertDataInfo(ICertRecord record) throws EBaseException, InvalidKeyException {
+ CertDataInfo info = new CertDataInfo();
+
+ CertId id = new CertId(record.getSerialNumber());
+ info.setID(id);
+
+ X509Certificate cert = record.getCertificate();
+ info.setSubjectDN(cert.getSubjectDN().toString());
+ info.setStatus(record.getStatus());
+ info.setVersion(cert.getVersion());
+ info.setType(cert.getType());
+
+ PublicKey key = cert.getPublicKey();
+ if (key instanceof X509Key) {
+ X509Key x509Key = (X509Key)key;
+ info.setKeyAlgorithmOID(x509Key.getAlgorithmId().getOID().toString());
+
+ if (x509Key.getAlgorithmId().toString().equalsIgnoreCase("RSA")) {
+ RSAPublicKey rsaKey = new RSAPublicKey(x509Key.getEncoded());
+ info.setKeyLength(rsaKey.getKeySize());
+ }
+ }
+
+ info.setNotValidBefore(cert.getNotBefore());
+ info.setNotValidAfter(cert.getNotAfter());
+
+ info.setIssuedOn(record.getCreateTime());
+ info.setIssuedBy(record.getIssuedBy());
+
+ URI uri = uriInfo.getBaseUriBuilder().path(CertResource.class).path("{id}").build(id.toHexString());
+ info.setLink(new Link("self", uri));
+
+ return info;
+ }
+
+ private String getCertChainData(X509CertImpl x509cert) {
+ X509Certificate mCACerts[];
+
+ if (x509cert == null) {
+ return null;
+ }
+
+ try {
+ mCACerts = authority.getCACertChain().getChain();
+ } catch (Exception e) {
+ mCACerts = null;
+ }
+
+ X509CertImpl[] certsInChain = new X509CertImpl[1];
+
+ int mCACertsLength = 0;
+ boolean certAlreadyInChain = false;
+ int certsInChainLength = 0;
+ if (mCACerts != null) {
+ mCACertsLength = mCACerts.length;
+ for (int i = 0; i < mCACertsLength; i++) {
+ if (x509cert.equals(mCACerts[i])) {
+ certAlreadyInChain = true;
+ break;
+ }
+ }
+
+ if (certAlreadyInChain == true) {
+ certsInChainLength = mCACertsLength;
+ } else {
+ certsInChainLength = mCACertsLength + 1;
+ }
+
+ certsInChain = new X509CertImpl[certsInChainLength];
+
+ }
+
+ certsInChain[0] = x509cert;
+
+ if (mCACerts != null) {
+ int curCount = 1;
+ for (int i = 0; i < mCACertsLength; i++) {
+ if (!x509cert.equals(mCACerts[i])) {
+ certsInChain[curCount] = (X509CertImpl) mCACerts[i];
+ curCount++;
+ }
+
+ }
+ }
+
+ String p7Str;
+
+ try {
+ PKCS7 p7 = new PKCS7(new AlgorithmId[0],
+ new ContentInfo(new byte[0]),
+ certsInChain,
+ new SignerInfo[0]);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ p7.encodeSignedData(bos, false);
+ byte[] p7Bytes = bos.toByteArray();
+
+ p7Str = Utils.base64encode(p7Bytes);
+ } catch (Exception e) {
+ p7Str = null;
+ }
+
+ return p7Str;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/ChallengeRevocationServlet1.java b/base/server/cms/src/com/netscape/cms/servlet/cert/ChallengeRevocationServlet1.java
new file mode 100644
index 000000000..097035be1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/ChallengeRevocationServlet1.java
@@ -0,0 +1,716 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CertificateException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.InvalidityDateExtension;
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertRecordList;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Takes the certificate info (serial number) and optional challenge phrase, creates a
+ * revocation request and submits it to the authority subsystem for processing
+ *
+ * @version $Revision$, $Date$
+ */
+public class ChallengeRevocationServlet1 extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1253319999546210407L;
+ public final static String GETCERTS_FOR_CHALLENGE_REQUEST = "getCertsForChallenge";
+ public static final String TOKEN_CERT_SERIAL = "certSerialToRevoke";
+ // revocation templates.
+ private final static String TPL_FILE = "revocationResult.template";
+
+ private ICertificateRepository mCertDB = null;
+ private String mFormPath = null;
+ private IRequestQueue mQueue = null;
+ private IPublisherProcessor mPublisherProcessor = null;
+ private String mRequestID = null;
+
+ // http params
+ public static final String SERIAL_NO = TOKEN_CERT_SERIAL;
+ public static final String REASON_CODE = "reasonCode";
+ public static final String CHALLENGE_PHRASE = "challengePhrase";
+
+ // request attributes
+ public static final String SERIALNO_ARRAY = "serialNoArray";
+
+ public ChallengeRevocationServlet1() {
+ super();
+ }
+
+ /**
+ * Initialize the servlet. This servlet uses the file
+ * revocationResult.template for the response
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+
+ String authorityId = mAuthority.getId();
+
+ mFormPath = "/" + authorityId + "/" + TPL_FILE;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mAuthority instanceof ICertificateAuthority) {
+ mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository();
+ }
+
+ if (mAuthority instanceof ICertAuthority) {
+ mPublisherProcessor = ((ICertAuthority) mAuthority).getPublisherProcessor();
+ }
+ mQueue = mAuthority.getRequestQueue();
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param REASON_CODE the revocation reason
+ * <li>http.param b64eCertificate the base-64 encoded certificate to revoke
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ * @throws EBaseException
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ IArgBlock httpParams = cmsReq.getHttpParams();
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ // for audit log
+ IAuthToken authToken = authenticate(cmsReq);
+ String authMgr = AuditFormat.NOAUTH;
+
+ BigInteger[] serialNoArray = null;
+
+ if (authToken != null) {
+ serialNoArray = authToken.getInBigIntegerArray(SERIAL_NO);
+ }
+ // set revocation reason, default to unspecified if not set.
+ int reasonCode =
+ httpParams.getValueAsInt(REASON_CODE, 0);
+ // header.addIntegerValue("reason", reasonCode);
+
+ String comments = req.getParameter(IRequest.REQUESTOR_COMMENTS);
+ Date invalidityDate = null;
+ String revokeAll = null;
+ int totalRecordCount = (serialNoArray != null) ? serialNoArray.length : 0;
+ int verifiedRecordCount = (serialNoArray != null) ? serialNoArray.length : 0;
+
+ X509CertImpl[] certs = null;
+
+ //for audit log.
+ String initiative = null;
+
+ if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) {
+ // request is from agent
+ if (authToken != null) {
+ authMgr = authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ String agentID = authToken.getInString("userid");
+
+ initiative = AuditFormat.FROMAGENT + " agentID: " + agentID +
+ " authenticated by " + authMgr;
+ }
+ } else {
+ initiative = AuditFormat.FROMUSER;
+ }
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "revoke");
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ if (serialNoArray != null && serialNoArray.length > 0) {
+ if (mAuthority instanceof ICertificateAuthority) {
+ certs = new X509CertImpl[serialNoArray.length];
+
+ for (int i = 0; i < serialNoArray.length; i++) {
+ certs[i] =
+ ((ICertificateAuthority) mAuthority).getCertificateRepository().getX509Certificate(
+ serialNoArray[i]);
+ }
+
+ } else if (mAuthority instanceof IRegistrationAuthority) {
+ IRequest getCertsChallengeReq = null;
+
+ getCertsChallengeReq = mQueue.newRequest(
+ GETCERTS_FOR_CHALLENGE_REQUEST);
+ getCertsChallengeReq.setExtData(SERIALNO_ARRAY, serialNoArray);
+ mQueue.processRequest(getCertsChallengeReq);
+ RequestStatus status = getCertsChallengeReq.getRequestStatus();
+
+ if (status == RequestStatus.COMPLETE) {
+ certs = getCertsChallengeReq.getExtDataInCertArray(IRequest.OLD_CERTS);
+ header.addStringValue("request", getCertsChallengeReq.getRequestId().toString());
+ mRequestID = getCertsChallengeReq.getRequestId().toString();
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_FAIL_GET_CERT_CHALL_PWRD"));
+ }
+ }
+
+ header.addIntegerValue("totalRecordCount", serialNoArray.length);
+ header.addIntegerValue("verifiedRecordCount", serialNoArray.length);
+
+ for (int i = 0; i < serialNoArray.length; i++) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ serialNoArray[i], 16);
+ rarg.addStringValue("subject",
+ certs[i].getSubjectDN().toString());
+ rarg.addLongValue("validNotBefore",
+ certs[i].getNotBefore().getTime() / 1000);
+ rarg.addLongValue("validNotAfter",
+ certs[i].getNotAfter().getTime() / 1000);
+ //argSet.addRepeatRecord(rarg);
+ }
+
+ revokeAll = "(|(certRecordId=" + serialNoArray[0].toString() + "))";
+ process(argSet, header, reasonCode, invalidityDate, initiative, req, resp,
+ verifiedRecordCount, revokeAll, totalRecordCount,
+ comments, locale[0]);
+ } else {
+ header.addIntegerValue("totalRecordCount", 0);
+ header.addIntegerValue("verifiedRecordCount", 0);
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (serialNoArray == null) {
+ CMS.debug("ChallengeRevcationServlet1::process() - " +
+ " serialNoArray is null!");
+ EBaseException ee = new EBaseException("No matched certificate is found");
+
+ cmsReq.setError(ee);
+ return;
+ }
+
+ if (serialNoArray.length == 0) {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ EBaseException ee = new EBaseException("No matched certificate is found");
+
+ cmsReq.setError(ee);
+ } else {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+ }
+
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ int reason, Date invalidityDate,
+ String initiative,
+ HttpServletRequest req,
+ HttpServletResponse resp,
+ int verifiedRecordCount,
+ String revokeAll,
+ int totalRecordCount,
+ String comments,
+ Locale locale)
+ throws EBaseException {
+ try {
+ int count = 0;
+ Vector<X509CertImpl> oldCertsV = new Vector<X509CertImpl>();
+ Vector<RevokedCertImpl> revCertImplsV = new Vector<RevokedCertImpl>();
+
+ // Construct a CRL reason code extension.
+ RevocationReason revReason = RevocationReason.fromInt(reason);
+ CRLReasonExtension crlReasonExtn = new CRLReasonExtension(revReason);
+
+ // Construct a CRL invalidity date extension.
+ InvalidityDateExtension invalidityDateExtn = null;
+
+ if (invalidityDate != null) {
+ invalidityDateExtn = new InvalidityDateExtension(invalidityDate);
+ }
+
+ // Construct a CRL extension for this request.
+ CRLExtensions entryExtn = new CRLExtensions();
+
+ if (crlReasonExtn != null) {
+ entryExtn.set(crlReasonExtn.getName(), crlReasonExtn);
+ }
+ if (invalidityDateExtn != null) {
+ entryExtn.set(invalidityDateExtn.getName(), invalidityDateExtn);
+ }
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ ICertRecordList list = mCertDB.findCertRecordsInList(
+ revokeAll, null, totalRecordCount);
+ Enumeration<ICertRecord> e = list.getCertRecords(0, totalRecordCount - 1);
+
+ while (e != null && e.hasMoreElements()) {
+ ICertRecord rec = e.nextElement();
+ X509CertImpl cert = rec.getCertificate();
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ cert.getSerialNumber(), 16);
+
+ if (rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) {
+ rarg.addStringValue("error", "Certificate " +
+ cert.getSerialNumber().toString() +
+ " is already revoked.");
+ } else {
+ oldCertsV.addElement(cert);
+
+ RevokedCertImpl revCertImpl =
+ new RevokedCertImpl(cert.getSerialNumber(),
+ CMS.getCurrentDate(), entryExtn);
+
+ revCertImplsV.addElement(revCertImpl);
+ count++;
+ rarg.addStringValue("error", null);
+ }
+ argSet.addRepeatRecord(rarg);
+ }
+
+ } else if (mAuthority instanceof IRegistrationAuthority) {
+ String reqIdStr = null;
+
+ if (mRequestID != null && mRequestID.length() > 0)
+ reqIdStr = mRequestID;
+ Vector<String> serialNumbers = new Vector<String>();
+
+ if (revokeAll != null && revokeAll.length() > 0) {
+ for (int i = revokeAll.indexOf('='); i < revokeAll.length() && i > -1;
+ i = revokeAll.indexOf('=', i)) {
+ if (i > -1) {
+ i++;
+ while (i < revokeAll.length() && revokeAll.charAt(i) == ' ') {
+ i++;
+ }
+ String legalDigits = "0123456789";
+ int j = i;
+
+ while (j < revokeAll.length() &&
+ legalDigits.indexOf(revokeAll.charAt(j)) != -1) {
+ j++;
+ }
+ if (j > i) {
+ serialNumbers.addElement(revokeAll.substring(i, j));
+ }
+ }
+ }
+ }
+ if (reqIdStr != null && reqIdStr.length() > 0 && serialNumbers.size() > 0) {
+ IRequest certReq = mRequestQueue.findRequest(new RequestId(reqIdStr));
+ X509CertImpl[] certs = certReq.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ for (int i = 0; i < certs.length; i++) {
+ boolean addToList = false;
+
+ for (int j = 0; j < serialNumbers.size(); j++) {
+ if (certs[i].getSerialNumber().toString().equals(
+ serialNumbers.elementAt(j))) {
+ addToList = true;
+ break;
+ }
+ }
+ if (addToList) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ certs[i].getSerialNumber(), 16);
+ oldCertsV.addElement(certs[i]);
+
+ RevokedCertImpl revCertImpl =
+ new RevokedCertImpl(certs[i].getSerialNumber(),
+ CMS.getCurrentDate(), entryExtn);
+
+ revCertImplsV.addElement(revCertImpl);
+ count++;
+ rarg.addStringValue("error", null);
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ } else {
+ String b64eCert = req.getParameter("b64eCertificate");
+
+ if (b64eCert != null) {
+ byte[] certBytes = Utils.base64decode(b64eCert);
+ X509CertImpl cert = new X509CertImpl(certBytes);
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ cert.getSerialNumber(), 16);
+ oldCertsV.addElement(cert);
+
+ RevokedCertImpl revCertImpl =
+ new RevokedCertImpl(cert.getSerialNumber(),
+ CMS.getCurrentDate(), entryExtn);
+
+ revCertImplsV.addElement(revCertImpl);
+ count++;
+ rarg.addStringValue("error", null);
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ }
+
+ header.addIntegerValue("totalRecordCount", count);
+
+ X509CertImpl[] oldCerts = new X509CertImpl[count];
+ RevokedCertImpl[] revCertImpls = new RevokedCertImpl[count];
+
+ for (int i = 0; i < count; i++) {
+ oldCerts[i] = oldCertsV.elementAt(i);
+ revCertImpls[i] = revCertImplsV.elementAt(i);
+ }
+
+ IRequest revReq =
+ mQueue.newRequest(IRequest.REVOCATION_REQUEST);
+
+ revReq.setExtData(IRequest.CERT_INFO, revCertImpls);
+ revReq.setExtData(IRequest.REQ_TYPE, IRequest.REVOCATION_REQUEST);
+ revReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_AGENT);
+
+ revReq.setExtData(IRequest.OLD_CERTS, oldCerts);
+ if (comments != null) {
+ revReq.setExtData(IRequest.REQUESTOR_COMMENTS, comments);
+ }
+
+ mQueue.processRequest(revReq);
+ RequestStatus stat = revReq.getRequestStatus();
+
+ if (stat == RequestStatus.COMPLETE) {
+ // audit log the error
+ Integer result = revReq.getExtDataInInteger(IRequest.RESULT);
+
+ if (result.equals(IRequest.RES_ERROR)) {
+ String[] svcErrors =
+ revReq.getExtDataInStringArray(IRequest.SVCERRORS);
+
+ if (svcErrors != null && svcErrors.length > 0) {
+ for (int i = 0; i < svcErrors.length; i++) {
+ String err = svcErrors[i];
+
+ if (err != null) {
+ //cmsReq.setErrorDescription(err);
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ revReq.getRequestId(),
+ initiative,
+ "completed with error: " +
+ err,
+ oldCerts[j].getSubjectDN(),
+ oldCerts[j].getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString() }
+ );
+ }
+ }
+ }
+ }
+ }
+ return;
+ }
+
+ // audit log the success.
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ revReq.getRequestId(),
+ initiative,
+ "completed",
+ oldCerts[j].getSubjectDN(),
+ oldCerts[j].getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString() }
+ );
+ }
+ }
+
+ header.addStringValue("revoked", "yes");
+
+ Integer updateCRLResult =
+ revReq.getExtDataInInteger(IRequest.CRL_UPDATE_STATUS);
+
+ if (updateCRLResult != null) {
+ header.addStringValue("updateCRL", "yes");
+ if (updateCRLResult.equals(IRequest.RES_SUCCESS)) {
+ header.addStringValue("updateCRLSuccess", "yes");
+ } else {
+ header.addStringValue("updateCRLSuccess", "no");
+ String crlError =
+ revReq.getExtDataInString(IRequest.CRL_UPDATE_ERROR);
+
+ if (crlError != null)
+ header.addStringValue("updateCRLError",
+ crlError);
+ }
+ // let known crl publishing status too.
+ Integer publishCRLResult =
+ revReq.getExtDataInInteger(IRequest.CRL_PUBLISH_STATUS);
+
+ if (publishCRLResult != null) {
+ if (publishCRLResult.equals(IRequest.RES_SUCCESS)) {
+ header.addStringValue("publishCRLSuccess", "yes");
+ } else {
+ header.addStringValue("publishCRLSuccess", "no");
+ String publError =
+ revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR);
+
+ if (publError != null)
+ header.addStringValue("publishCRLError",
+ publError);
+ }
+ }
+ }
+ if (mAuthority instanceof ICertificateAuthority) {
+ // let known update and publish status of all crls.
+ Enumeration<ICRLIssuingPoint> otherCRLs =
+ ((ICertificateAuthority) mAuthority).getCRLIssuingPoints();
+
+ while (otherCRLs.hasMoreElements()) {
+ ICRLIssuingPoint crl = otherCRLs.nextElement();
+ String crlId = crl.getId();
+
+ if (crlId.equals(ICertificateAuthority.PROP_MASTER_CRL))
+ continue;
+ String updateStatusStr = crl.getCrlUpdateStatusStr();
+ Integer updateResult = revReq.getExtDataInInteger(updateStatusStr);
+
+ if (updateResult != null) {
+ if (updateResult.equals(IRequest.RES_SUCCESS)) {
+ CMS.debug("ChallengeRevcationServlet1: "
+ + CMS.getLogMessage("ADMIN_SRVLT_ADDING_HEADER",
+ updateStatusStr));
+ header.addStringValue(updateStatusStr, "yes");
+ } else {
+ String updateErrorStr = crl.getCrlUpdateErrorStr();
+
+ CMS.debug("ChallengeRevcationServlet1: "
+ + CMS.getLogMessage("ADMIN_SRVLT_ADDING_HEADER_NO",
+ updateStatusStr));
+ header.addStringValue(updateStatusStr, "no");
+ String error =
+ revReq.getExtDataInString(updateErrorStr);
+
+ if (error != null)
+ header.addStringValue(updateErrorStr,
+ error);
+ }
+ String publishStatusStr = crl.getCrlPublishStatusStr();
+ Integer publishResult =
+ revReq.getExtDataInInteger(publishStatusStr);
+
+ if (publishResult == null)
+ continue;
+ if (publishResult.equals(IRequest.RES_SUCCESS)) {
+ header.addStringValue(publishStatusStr, "yes");
+ } else {
+ String publishErrorStr =
+ crl.getCrlPublishErrorStr();
+
+ header.addStringValue(publishStatusStr, "no");
+ String error =
+ revReq.getExtDataInString(publishErrorStr);
+
+ if (error != null)
+ header.addStringValue(
+ publishErrorStr, error);
+ }
+ }
+ }
+ }
+
+ if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) {
+ header.addStringValue("dirEnabled", "yes");
+ Integer[] ldapPublishStatus =
+ revReq.getExtDataInIntegerArray("ldapPublishStatus");
+ int certsToUpdate = 0;
+ int certsUpdated = 0;
+
+ if (ldapPublishStatus != null) {
+ certsToUpdate = ldapPublishStatus.length;
+ for (int i = 0; i < certsToUpdate; i++) {
+ if (ldapPublishStatus[i] == IRequest.RES_SUCCESS) {
+ certsUpdated++;
+ }
+ }
+ }
+ header.addIntegerValue("certsUpdated", certsUpdated);
+ header.addIntegerValue("certsToUpdate", certsToUpdate);
+
+ // add crl publishing status.
+ String publError =
+ revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR);
+
+ if (publError != null) {
+ header.addStringValue("crlPublishError",
+ publError);
+ }
+ } else {
+ header.addStringValue("dirEnabled", "no");
+ }
+ header.addStringValue("error", null);
+
+ } else if (stat == RequestStatus.PENDING) {
+ header.addStringValue("error", "Request Pending");
+ header.addStringValue("revoked", "pending");
+ // audit log the pending
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ revReq.getRequestId(),
+ initiative,
+ "pending",
+ oldCerts[j].getSubjectDN(),
+ oldCerts[j].getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString() }
+ );
+ }
+ }
+
+ } else {
+ Vector<String> errors = revReq.getExtDataInStringVector(IRequest.ERRORS);
+ StringBuffer errorStr = new StringBuffer();
+
+ if (errors != null && errors.size() > 0) {
+ for (int ii = 0; ii < errors.size(); ii++) {
+ errorStr.append(errors.elementAt(ii));
+ }
+ }
+ header.addStringValue("error", errorStr.toString());
+ header.addStringValue("revoked", "no");
+ // audit log the error
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ revReq.getRequestId(),
+ initiative,
+ stat.toString(),
+ oldCerts[j].getSubjectDN(),
+ oldCerts[j].getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString() }
+ );
+ }
+ }
+ }
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, "error " + e);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, "error " + e);
+ throw e;
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED", e.toString()));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CloneRedirect.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CloneRedirect.java
new file mode 100644
index 000000000..bf5fc490f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CloneRedirect.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Redirect a request to the Master. This servlet is used in
+ * a clone when a requested service (such as CRL) is not available.
+ * It redirects the user to the master.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CloneRedirect extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3217967115281965166L;
+ private final static String PROP_REDIRECT_URL = "masterURL";
+ private final static String TPL_FILE = "cloneRedirect.template";
+
+ private String mNewUrl = null;
+ private String mFormPath = null;
+
+ private ICertificateAuthority mCA = null;
+
+ /**
+ * Constructs CloneRedirect servlet.
+ */
+ public CloneRedirect() {
+ super();
+
+ }
+
+ /**
+ * Initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ mCA = (ICertificateAuthority) mAuthority;
+ IConfigStore authConfig = mCA.getConfigStore();
+
+ if (authConfig != null) {
+ try {
+ mNewUrl = authConfig.getString(PROP_REDIRECT_URL,
+ "*** master URL unavailable, check your configuration ***");
+ } catch (EBaseException e) {
+ // do nothing
+ }
+ }
+ }
+
+ if (mAuthority instanceof ICertificateAuthority)
+ mCA = (ICertificateAuthority) mAuthority;
+
+ // override success to do output with our own template.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Serves HTTP request.
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+
+ CMS.debug("CloneRedirect: " + CMS.getLogMessage("ADMIN_SRVLT_ADD_MASTER_URL", mNewUrl));
+ header.addStringValue("masterURL", mNewUrl);
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/DirAuthServlet.java b/base/server/cms/src/com/netscape/cms/servlet/cert/DirAuthServlet.java
new file mode 100644
index 000000000..66c2aa268
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/DirAuthServlet.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.cms.authentication.HashAuthentication;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * 'Face-to-face' certificate enrollment.
+ *
+ * @version $Revision$, $Date$
+ */
+public class DirAuthServlet extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3906057586972768401L;
+ private final static String TPL_FILE = "/ra/hashEnrollmentSubmit.template";
+ private final static String TPL_ERROR_FILE = "/ra/GenErrorHashDirEnroll.template";
+ private String mFormPath = null;
+
+ public DirAuthServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ try {
+ mFormPath = sc.getInitParameter(
+ PROP_SUCCESS_TEMPLATE);
+ if (mFormPath == null)
+ mFormPath = TPL_FILE;
+ } catch (Exception e) {
+ }
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Process the HTTP request. This servlet reads configuration information
+ * from the hashDirEnrollment configuration substore
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ String reqHost = httpReq.getRemoteHost();
+
+ // Construct an ArgBlock
+ IArgBlock args = cmsReq.getHttpParams();
+
+ if (!(mAuthority instanceof IRegistrationAuthority)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_CA_FROM_RA_NOT_IMP"));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getLogMessage("CMSGW_NOT_YET_IMPLEMENTED")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, httpReq, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "submit");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String val = configStore.getString("hashDirEnrollment.name");
+ IAuthSubsystem authSS = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ IAuthManager authMgr = authSS.get(val);
+ HashAuthentication mgr = (HashAuthentication) authMgr;
+
+ Date date = new Date();
+ long currTime = date.getTime();
+ long timeout = mgr.getTimeout(reqHost);
+ long lastlogin = mgr.getLastLogin(reqHost);
+ long diff = currTime - lastlogin;
+
+ boolean enable = mgr.isEnable(reqHost);
+
+ if (!enable) {
+ printError(cmsReq, "0");
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+ if (lastlogin == 0)
+ mgr.setLastLogin(reqHost, currTime);
+ else if (diff > timeout) {
+ mgr.disable(reqHost);
+ printError(cmsReq, "2");
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+ mgr.setLastLogin(reqHost, currTime);
+
+ String uid = args.getValueAsString("uid");
+ long pageid = mgr.getPageID();
+ String pageID = pageid + "";
+
+ mgr.addAuthToken(pageID, authToken);
+
+ header.addStringValue("pageID", pageID);
+ header.addStringValue("uid", uid);
+ header.addStringValue("fingerprint", mgr.hashFingerprint(reqHost, pageID, uid));
+ header.addStringValue("hostname", reqHost);
+
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+ private void printError(CMSRequest cmsReq, String errorCode)
+ throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ header.addStringValue("authority", "Registration Manager");
+ header.addStringValue("errorCode", errorCode);
+ String formPath = TPL_ERROR_FILE;
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(formPath, httpReq, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_ERR_GET_TEMPLATE", formPath, e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ }
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/DisableEnrollResult.java b/base/server/cms/src/com/netscape/cms/servlet/cert/DisableEnrollResult.java
new file mode 100644
index 000000000..4b195c282
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/DisableEnrollResult.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.cms.authentication.HashAuthentication;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * For Face-to-face enrollment, disable EE enrollment feature
+ *
+ * @version $Revision$, $Date$
+ * @see com.netscape.cms.servlet.cert.EnableEnrollResult
+ */
+public class DisableEnrollResult extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 4307655310299723974L;
+ private final static String TPL_FILE = "enableEnrollResult.template";
+ private String mFormPath = null;
+
+ public DisableEnrollResult() {
+ super();
+ }
+
+ /**
+ * Initializes the servlet.
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // coming from agent
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ protected CMSRequest newCMSRequest() {
+ return new CMSRequest();
+ }
+
+ /**
+ * Services the request
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IAuthToken token = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, token,
+ mAuthzResourceName, "disable");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ X509Certificate sslClientCert = null;
+
+ sslClientCert = getSSLClientCertificate(httpReq);
+ String dn = sslClientCert.getSubjectDN().toString();
+
+ // Construct an ArgBlock
+ IArgBlock args = cmsReq.getHttpParams();
+
+ if (!(mAuthority instanceof IRegistrationAuthority)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_CA_FROM_RA_NOT_IMP"));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getLogMessage("CMSGW_NOT_YET_IMPLEMENTED")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, httpReq, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String val = configStore.getString("hashDirEnrollment.name");
+ IAuthSubsystem authSS = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ IAuthManager authMgr = authSS.get(val);
+ HashAuthentication mgr = (HashAuthentication) authMgr;
+
+ String host = args.getValueAsString("hosts", null);
+ String name = mgr.getAgentName(host);
+
+ if (name == null) {
+ header.addStringValue("code", "2");
+ } else if (name.equals(dn)) {
+ mgr.disable(host);
+ header.addStringValue("code", "2");
+ } else {
+ header.addStringValue("code", "3");
+ }
+
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/DisplayBySerial.java b/base/server/cms/src/com/netscape/cms/servlet/cert/DisplayBySerial.java
new file mode 100644
index 000000000..da7f01ca5
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/DisplayBySerial.java
@@ -0,0 +1,488 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.extensions.NSCertTypeExtension;
+import netscape.security.pkcs.ContentInfo;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.pkcs.SignerInfo;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.Extension;
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.ICertPrettyPrint;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.EDBRecordNotFoundException;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.dbs.certdb.IRevocationInfo;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Display detailed information about a certificate
+ *
+ * The template 'displayBySerial.template' is used to
+ * render the response for this servlet.
+ *
+ * @version $Revision$, $Date$
+ */
+public class DisplayBySerial extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4143700762995036597L;
+ private final static String TPL_FILE1 = "displayBySerial.template";
+ private final static BigInteger MINUS_ONE = new BigInteger("-1");
+
+ private ICertificateRepository mCertDB = null;
+ private String mForm1Path = null;
+ private X509Certificate mCACerts[] = null;
+
+ /**
+ * Constructs DisplayBySerial servlet.
+ */
+ public DisplayBySerial() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ if (mAuthority instanceof ICertificateAuthority) {
+ mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository();
+ }
+ try {
+ mCACerts = ((ICertAuthority) mAuthority).getCACertChain().getChain();
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CA_CHAIN_NOT_AVAILABLE"));
+ }
+ // coming from ee
+ mForm1Path = "/" + mAuthority.getId() + "/" + TPL_FILE1;
+
+ if (mOutputTemplatePath != null)
+ mForm1Path = mOutputTemplatePath;
+
+ // override success and error templates to null -
+ // handle templates locally.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Serves HTTP request. The format of this request is as follows:
+ * <ul>
+ * <li>http.param serialNumber Decimal serial number of certificate to display (or hex if serialNumber preceded by
+ * 0x)
+ * </ul>
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ BigInteger serialNumber = MINUS_ONE;
+ EBaseException error = null;
+ String certType[] = new String[1];
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ serialNumber = getSerialNumber(req);
+ getCertRecord(serialNumber, certType); //throw exception on error
+
+ if (certType[0].equalsIgnoreCase("x509")) {
+ form = getTemplate(mForm1Path, req, locale);
+ }
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT_1", String.valueOf(serialNumber)));
+
+ error = new ECMSGWException(CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT"));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mForm1Path, e.toString()));
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ } catch (EDBRecordNotFoundException e) {
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_CERT_SERIAL_NOT_FOUND_1", "0x" + serialNumber.toString(16)));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ try {
+ if (serialNumber.compareTo(MINUS_ONE) > 0) {
+ process(argSet, header, serialNumber,
+ req, resp, locale[0]);
+ } else {
+ error = new ECMSGWException(
+ CMS.getLogMessage("CMSGW_INVALID_SERIAL_NUMBER"));
+ }
+ } catch (EBaseException e) {
+ error = e;
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", e.toString()));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+
+ }
+
+ /**
+ * Display information about a particular certificate
+ */
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ BigInteger seq, HttpServletRequest req,
+ HttpServletResponse resp,
+ Locale locale)
+ throws EBaseException {
+ String certType[] = new String[1];
+
+ try {
+ getCertRecord(seq, certType); // throw exception on error
+
+ if (certType[0].equalsIgnoreCase("x509")) {
+ processX509(argSet, header, seq, req, resp, locale);
+ return;
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_DISP_BY_SERIAL", e.toString()));
+ throw e;
+ }
+
+ return;
+ }
+
+ private void processX509(CMSTemplateParams argSet, IArgBlock header,
+ BigInteger seq, HttpServletRequest req,
+ HttpServletResponse resp,
+ Locale locale)
+ throws EBaseException {
+ try {
+ ICertRecord rec = mCertDB.readCertificateRecord(seq);
+ if (rec == null) {
+ CMS.debug("DisplayBySerial: failed to read record");
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_ENCODING_ISSUED_CERT"));
+ }
+ X509CertImpl cert = rec.getCertificate();
+ if (cert == null) {
+ CMS.debug("DisplayBySerial: no certificate in record");
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_ENCODING_ISSUED_CERT"));
+ }
+
+ try {
+ X509CertInfo info = (X509CertInfo) cert.get(X509CertImpl.NAME + "." + X509CertImpl.INFO);
+ if (info == null) {
+ CMS.debug("DisplayBySerial: no info found");
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_ENCODING_ISSUED_CERT"));
+ }
+ CertificateExtensions extensions = (CertificateExtensions) info.get(X509CertInfo.EXTENSIONS);
+
+ boolean emailCert = false;
+
+ if (extensions != null) {
+ for (int i = 0; i < extensions.size(); i++) {
+ Extension ext = extensions.elementAt(i);
+
+ if (ext instanceof NSCertTypeExtension) {
+ NSCertTypeExtension type = (NSCertTypeExtension) ext;
+
+ if (((Boolean) type.get(NSCertTypeExtension.EMAIL)).booleanValue())
+ emailCert = true;
+ }
+ if (ext instanceof KeyUsageExtension) {
+ KeyUsageExtension usage =
+ (KeyUsageExtension) ext;
+
+ try {
+ if (((Boolean) usage.get(KeyUsageExtension.DIGITAL_SIGNATURE)).booleanValue() ||
+ ((Boolean) usage.get(KeyUsageExtension.DATA_ENCIPHERMENT)).booleanValue())
+ emailCert = true;
+ } catch (ArrayIndexOutOfBoundsException e) {
+ // bug356108:
+ // In case there is only DIGITAL_SIGNATURE,
+ // don't report error
+ }
+ }
+ }
+ }
+ header.addBooleanValue("emailCert", emailCert);
+
+ boolean noCertImport = true;
+ MetaInfo metaInfo = (MetaInfo) rec.get(ICertRecord.ATTR_META_INFO);
+
+ if (metaInfo != null) {
+ String rid = (String) metaInfo.get(ICertRecord.META_REQUEST_ID);
+
+ if (rid != null && mAuthority instanceof ICertificateAuthority) {
+ IRequest r =
+ ((ICertificateAuthority) mAuthority).getRequestQueue().findRequest(new RequestId(rid));
+ String certType = r.getExtDataInString(IRequest.HTTP_PARAMS, IRequest.CERT_TYPE);
+
+ if (certType != null && certType.equals(IRequest.CLIENT_CERT)) {
+ noCertImport = false;
+ }
+ }
+ }
+ header.addBooleanValue("noCertImport", noCertImport);
+
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_PARSING_EXTENS", e.toString()));
+ }
+
+ IRevocationInfo revocationInfo = rec.getRevocationInfo();
+
+ if (revocationInfo != null) {
+ CRLExtensions crlExts = revocationInfo.getCRLEntryExtensions();
+
+ if (crlExts != null) {
+ Enumeration<Extension> enumx = crlExts.getElements();
+ int reason = 0;
+
+ while (enumx.hasMoreElements()) {
+ Extension ext = enumx.nextElement();
+
+ if (ext instanceof CRLReasonExtension) {
+ reason = ((CRLReasonExtension) ext).getReason().toInt();
+ }
+ }
+ header.addIntegerValue("revocationReason", reason);
+ }
+ }
+
+ ICertPrettyPrint certDetails = CMS.getCertPrettyPrint(cert);
+
+ header.addStringValue("certPrettyPrint",
+ certDetails.toString(locale));
+
+ /*
+ String scheme = req.getScheme();
+ if (scheme.equals("http") && connectionIsSSL(req))
+ scheme = "https";
+ String requestURI = req.getRequestURI();
+ int i = requestURI.indexOf('?');
+ String newRequestURI =
+ (i > -1)? requestURI.substring(0, i): requestURI;
+ header.addStringValue("serviceURL", scheme +"://"+
+ req.getServerName() + ":"+
+ req.getServerPort() + newRequestURI);
+ */
+ header.addStringValue("authorityid", mAuthority.getId());
+
+ String certFingerprints = "";
+
+ try {
+ certFingerprints = CMS.getFingerPrints(cert);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_DIGESTING_CERT", e.toString()));
+ }
+ if (certFingerprints.length() > 0)
+ header.addStringValue("certFingerprint", certFingerprints);
+
+ byte[] ba = cert.getEncoded();
+ // Do base 64 encoding
+
+ header.addStringValue("certChainBase64", Utils.base64encode(ba));
+ header.addStringValue("serialNumber", seq.toString(16));
+
+ /*
+ String userAgent = req.getHeader("user-agent");
+ String agent =
+ (userAgent != null)? UserInfo.getUserAgent(userAgent): "";
+ */
+ // Now formulate a PKCS#7 blob
+ X509CertImpl[] certsInChain = new X509CertImpl[1];
+ ;
+ if (mCACerts != null) {
+ for (int i = 0; i < mCACerts.length; i++) {
+ if (cert.equals(mCACerts[i])) {
+ certsInChain = new
+ X509CertImpl[mCACerts.length];
+ break;
+ }
+ certsInChain = new X509CertImpl[mCACerts.length + 1];
+ }
+ }
+
+ // Set the EE cert
+ certsInChain[0] = cert;
+
+ // Set the Ca certificate chain
+ if (mCACerts != null) {
+ for (int i = 0; i < mCACerts.length; i++) {
+ if (!cert.equals(mCACerts[i]))
+ certsInChain[i + 1] = (X509CertImpl) mCACerts[i];
+ }
+ }
+
+ // Wrap the chain into a degenerate P7 object
+ String p7Str;
+
+ try {
+ PKCS7 p7 = new PKCS7(new AlgorithmId[0],
+ new ContentInfo(new byte[0]),
+ certsInChain,
+ new SignerInfo[0]);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ p7.encodeSignedData(bos, false);
+ byte[] p7Bytes = bos.toByteArray();
+
+ p7Str = Utils.base64encode(p7Bytes);
+ header.addStringValue("pkcs7ChainBase64", p7Str);
+ } catch (Exception e) {
+ //p7Str = "PKCS#7 B64 Encoding error - " + e.toString()
+ //+ "; Please contact your administrator";
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_FORMING_PKCS7_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_FORMING_PKCS7"));
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("MSGW_ERR_DISP_BY_SERIAL", e.toString()));
+ throw e;
+ } catch (CertificateEncodingException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_ENCODE_CERT", e.toString()));
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_ENCODING_ISSUED_CERT"));
+ }
+
+ return;
+ }
+
+ private ICertRecord getCertRecord(BigInteger seq, String certtype[])
+ throws EBaseException {
+ ICertRecord rec = null;
+
+ try {
+ rec = mCertDB.readCertificateRecord(seq);
+ X509CertImpl x509cert = rec.getCertificate();
+
+ if (x509cert != null) {
+ certtype[0] = "x509";
+ return rec;
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_DISP_BY_SERIAL", e.toString()));
+ throw e;
+ }
+
+ return rec;
+ }
+
+ private BigInteger getSerialNumber(HttpServletRequest req)
+ throws NumberFormatException {
+ String serialNumString = req.getParameter("serialNumber");
+
+ if (serialNumString != null) {
+ serialNumString = serialNumString.trim();
+ if (serialNumString.startsWith("0x") || serialNumString.startsWith("0X")) {
+ return new BigInteger(serialNumString.substring(2), 16);
+ } else {
+ return new BigInteger(serialNumString);
+ }
+ } else {
+ throw new NumberFormatException();
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/DisplayCRL.java b/base/server/cms/src/com/netscape/cms/servlet/cert/DisplayCRL.java
new file mode 100644
index 000000000..3c9d5778c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/DisplayCRL.java
@@ -0,0 +1,491 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CRLException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X509CRLImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.ICRLPrettyPrint;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+import com.netscape.certsrv.dbs.crldb.ICRLRepository;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Decode the CRL and display it to the requester.
+ *
+ * @version $Revision$, $Date$
+ */
+public class DisplayCRL extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1152016798229054027L;
+ private final static String TPL_FILE = "displayCRL.template";
+ //private final static String E_TPL_FILE = "error.template";
+ //private final static String OUT_ERROR = "errorDetails";
+
+ private String mFormPath = null;
+ private ICertificateAuthority mCA = null;
+
+ /**
+ * Constructs DisplayCRL servlet.
+ */
+ public DisplayCRL() {
+ super();
+ }
+
+ /**
+ * Initialize the servlet. This servlet uses the 'displayCRL.template' file to
+ * to render the response to the client.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ if (mAuthority instanceof ICertificateAuthority) {
+ mCA = (ICertificateAuthority) mAuthority;
+ }
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Process the HTTP request
+ * <ul>
+ * <li>http.param crlIssuingPoint number
+ * <li>http.param crlDisplayType entireCRL or crlHeader or base64Encoded or deltaCRL
+ * <li>http.param pageStart which page to start displaying from
+ * <li>http.param pageSize number of entries to show per page
+ * </ul>
+ *
+ * @param cmsReq the Request to service.
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE_1", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ // Note error is covered in the same template as success.
+
+ String crlIssuingPointId = req.getParameter("crlIssuingPoint");
+
+ process(argSet, header, req, resp, crlIssuingPointId,
+ locale[0]);
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", e.toString()));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+ }
+
+ /**
+ * Display information about a particular CRL.
+ */
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ HttpServletRequest req,
+ HttpServletResponse resp,
+ String crlIssuingPointId,
+ Locale locale) {
+ ICRLIssuingPoint crlIP = null;
+ X509CRLImpl crl = null;
+ boolean clonedCA = false;
+ boolean isCRLCacheEnabled = false;
+ String masterHost = null;
+ String masterPort = null;
+ Vector<String> ipNames = null;
+ String ipId = crlIssuingPointId;
+ ICRLRepository crlRepository = mCA.getCRLRepository();
+
+ try {
+ masterHost = CMS.getConfigStore().getString("master.ca.agent.host", "");
+ masterPort = CMS.getConfigStore().getString("master.ca.agent.port", "");
+ if (masterHost != null && masterHost.length() > 0 &&
+ masterPort != null && masterPort.length() > 0) {
+ clonedCA = true;
+ ipNames = crlRepository.getIssuingPointsNames();
+ }
+ } catch (EBaseException e) {
+ }
+
+ if (clonedCA) {
+ if (crlIssuingPointId != null) {
+ if (ipNames != null && ipNames.size() > 0) {
+ int i;
+ for (i = 0; i < ipNames.size(); i++) {
+ String ipName = ipNames.elementAt(i);
+ if (crlIssuingPointId.equals(ipName)) {
+ break;
+ }
+ }
+ if (i >= ipNames.size())
+ crlIssuingPointId = null;
+ } else {
+ crlIssuingPointId = null;
+ }
+ }
+ } else {
+ if (crlIssuingPointId != null) {
+ Enumeration<ICRLIssuingPoint> ips = mCA.getCRLIssuingPoints();
+
+ while (ips.hasMoreElements()) {
+ ICRLIssuingPoint ip = ips.nextElement();
+
+ if (crlIssuingPointId.equals(ip.getId())) {
+ crlIP = ip;
+ isCRLCacheEnabled = ip.isCRLCacheEnabled();
+ break;
+ }
+ if (!ips.hasMoreElements())
+ crlIssuingPointId = null;
+ }
+ }
+ }
+ if (crlIssuingPointId == null) {
+ header.addStringValue("error",
+ "Request to unspecified or non-existing CRL issuing point: " + ipId);
+ return;
+ }
+
+ ICRLIssuingPointRecord crlRecord = null;
+
+ String crlDisplayType = req.getParameter("crlDisplayType");
+
+ if (crlDisplayType == null)
+ crlDisplayType = "cachedCRL";
+ header.addStringValue("crlDisplayType", crlDisplayType);
+
+ try {
+ crlRecord =
+ mCA.getCRLRepository().readCRLIssuingPointRecord(crlIssuingPointId);
+ } catch (EBaseException e) {
+ header.addStringValue("error", e.toString(locale));
+ return;
+ }
+ if (crlRecord == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CRL_NOT_YET_UPDATED_1", crlIssuingPointId));
+ header.addStringValue("error",
+ new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_CRL_NOT_YET_UPDATED")).toString());
+ return;
+ }
+
+ header.addStringValue("crlIssuingPoint", crlIssuingPointId);
+ if (crlDisplayType.equals("deltaCRL")) {
+ if (clonedCA) {
+ header.addStringValue("crlNumber", crlRecord.getDeltaCRLNumber().toString());
+ } else {
+ header.addStringValue("crlNumber", crlIP.getDeltaCRLNumber().toString());
+ }
+ } else {
+ if (clonedCA) {
+ header.addStringValue("crlNumber", crlRecord.getCRLNumber().toString());
+ } else {
+ header.addStringValue("crlNumber", crlIP.getCRLNumber().toString());
+ }
+ }
+ long lCRLSize = crlRecord.getCRLSize().longValue();
+ header.addLongValue("crlSize", lCRLSize);
+
+ if (crlIP != null) {
+ header.addStringValue("crlDescription", crlIP.getDescription());
+ }
+
+ if (!crlDisplayType.equals("cachedCRL")) {
+ byte[] crlbytes = crlRecord.getCRL();
+
+ if (crlbytes == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CRL_NOT_YET_UPDATED_1", crlIssuingPointId));
+ header.addStringValue("error",
+ new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_CRL_NOT_YET_UPDATED")).toString());
+ return;
+ }
+
+ try {
+ if (crlDisplayType.equals("crlHeader")) {
+ crl = new X509CRLImpl(crlbytes, false);
+ } else {
+ crl = new X509CRLImpl(crlbytes);
+ }
+
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_DECODE_CRL", e.toString()));
+ header.addStringValue("error",
+ new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_DECODE_CRL_FAILED")).toString());
+ }
+ }
+
+ if (crl != null || (isCRLCacheEnabled && crlDisplayType.equals("cachedCRL"))) {
+ if (crlDisplayType.equals("entireCRL") || crlDisplayType.equals("cachedCRL")) {
+ ICRLPrettyPrint crlDetails = null;
+ if (crlDisplayType.equals("entireCRL")) {
+ crlDetails = CMS.getCRLPrettyPrint(crl);
+ } else {
+ crlDetails = CMS.getCRLCachePrettyPrint(crlIP);
+ }
+
+ String pageStart = req.getParameter("pageStart");
+ String pageSize = req.getParameter("pageSize");
+
+ if (pageStart != null && pageSize != null) {
+ long lPageStart = 0L;
+ long lPageSize = 0L;
+ try {
+ lPageStart = new Long(pageStart).longValue();
+ } catch (NumberFormatException e) {
+ }
+ try {
+ lPageSize = new Long(pageSize).longValue();
+ } catch (NumberFormatException e) {
+ }
+
+ if (lPageStart < 1)
+ lPageStart = 1;
+ // if (lPageStart + lPageSize - lCRLSize > 1)
+ // lPageStart = lCRLSize - lPageSize + 1;
+ if (lPageSize < 1)
+ lPageSize = 10;
+
+ header.addStringValue(
+ "crlPrettyPrint", crlDetails.toString(locale,
+ lCRLSize, lPageStart, lPageSize));
+ header.addLongValue("pageStart", lPageStart);
+ header.addLongValue("pageSize", lPageSize);
+ } else {
+ header.addStringValue(
+ "crlPrettyPrint", crlDetails.toString(locale));
+ }
+ } else if (crlDisplayType.equals("crlHeader")) {
+ ICRLPrettyPrint crlDetails = CMS.getCRLPrettyPrint(crl);
+
+ header.addStringValue(
+ "crlPrettyPrint", crlDetails.toString(locale, lCRLSize, 0, 0));
+ } else if (crlDisplayType.equals("base64Encoded")) {
+ try {
+ byte[] ba = crl.getEncoded();
+ String crlBase64Encoded = Utils.base64encode(ba);
+ int length = crlBase64Encoded.length();
+ int i = 0;
+ int j = 0;
+ int n = 1;
+
+ while (i < length) {
+ int k = crlBase64Encoded.indexOf('\n', i);
+
+ if (n < 100 && k > -1) {
+ n++;
+ i = k + 1;
+ if (i >= length) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addStringValue("crlBase64Encoded", crlBase64Encoded.substring(j, k));
+ argSet.addRepeatRecord(rarg);
+ }
+ } else {
+ n = 1;
+ IArgBlock rarg = CMS.createArgBlock();
+
+ if (k > -1) {
+ rarg.addStringValue("crlBase64Encoded", crlBase64Encoded.substring(j, k));
+ i = k + 1;
+ j = i;
+ } else {
+ rarg.addStringValue("crlBase64Encoded", crlBase64Encoded.substring(j, length));
+ i = length;
+ }
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ } catch (CRLException e) {
+ }
+ } else if (crlDisplayType.equals("deltaCRL")) {
+ if ((clonedCA && crlRecord.getDeltaCRLSize() != null &&
+ crlRecord.getDeltaCRLSize().longValue() > -1) ||
+ (crlIP != null && crlIP.isDeltaCRLEnabled())) {
+ byte[] deltaCRLBytes = crlRecord.getDeltaCRL();
+
+ if (deltaCRLBytes == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_NO_DELTA_CRL", crlIssuingPointId));
+ header.addStringValue("error", "Delta CRL is not available");
+ } else {
+ X509CRLImpl deltaCRL = null;
+
+ try {
+ deltaCRL = new X509CRLImpl(deltaCRLBytes);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_DECODE_DELTA_CRL", e.toString()));
+ header.addStringValue("error",
+ new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_DECODE_CRL_FAILED"))
+ .toString());
+ }
+ if (deltaCRL != null) {
+ BigInteger crlNumber = crlRecord.getCRLNumber();
+ BigInteger deltaNumber = crlRecord.getDeltaCRLNumber();
+ if ((clonedCA && crlNumber != null && deltaNumber != null &&
+ deltaNumber.compareTo(crlNumber) >= 0) ||
+ (crlIP != null && crlIP.isThisCurrentDeltaCRL(deltaCRL))) {
+
+ header.addIntegerValue("deltaCRLSize",
+ deltaCRL.getNumberOfRevokedCertificates());
+
+ ICRLPrettyPrint crlDetails = CMS.getCRLPrettyPrint(deltaCRL);
+
+ header.addStringValue(
+ "crlPrettyPrint", crlDetails.toString(locale, 0, 0, 0));
+
+ try {
+ byte[] ba = deltaCRL.getEncoded();
+ String crlBase64Encoded = Utils.base64encode(ba);
+ int length = crlBase64Encoded.length();
+ int i = 0;
+ int j = 0;
+ int n = 1;
+
+ while (i < length) {
+ int k = crlBase64Encoded.indexOf('\n', i);
+
+ if (n < 100 && k > -1) {
+ n++;
+ i = k + 1;
+ if (i >= length) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addStringValue("crlBase64Encoded",
+ crlBase64Encoded.substring(j, k));
+ argSet.addRepeatRecord(rarg);
+ }
+ } else {
+ n = 1;
+ IArgBlock rarg = CMS.createArgBlock();
+
+ if (k > -1) {
+ rarg.addStringValue("crlBase64Encoded",
+ crlBase64Encoded.substring(j, k));
+ i = k + 1;
+ j = i;
+ } else {
+ rarg.addStringValue("crlBase64Encoded",
+ crlBase64Encoded.substring(j, length));
+ i = length;
+ }
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ } catch (CRLException e) {
+ }
+ } else {
+ header.addStringValue("error", "Current Delta CRL is not available.");
+ }
+ }
+ }
+ } else {
+ header.addStringValue("error", "Delta CRL is not enabled for " +
+ crlIssuingPointId +
+ " issuing point");
+ }
+ }
+
+ } else if (!isCRLCacheEnabled && crlDisplayType.equals("cachedCRL")) {
+ header.addStringValue("error",
+ CMS.getUserMessage(locale, "CMS_GW_CRL_CACHE_IS_NOT_ENABLED", crlIssuingPointId));
+ header.addStringValue("crlPrettyPrint",
+ CMS.getUserMessage(locale, "CMS_GW_CRL_CACHE_IS_NOT_ENABLED", crlIssuingPointId));
+ } else {
+ header.addStringValue("error",
+ new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_DECODE_CRL_FAILED")).toString());
+ header.addStringValue("crlPrettyPrint",
+ new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_DECODE_CRL_FAILED")).toString());
+ }
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/DisplayHashUserEnroll.java b/base/server/cms/src/com/netscape/cms/servlet/cert/DisplayHashUserEnroll.java
new file mode 100644
index 000000000..6c1d6f5f4
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/DisplayHashUserEnroll.java
@@ -0,0 +1,228 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.cms.authentication.HashAuthentication;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Servlet to report the status, ie, the agent-initiated user
+ * enrollment is enabled or disabled.
+ *
+ * @version $Revision$, $Date$
+ */
+public class DisplayHashUserEnroll extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7063912475278810362L;
+ private final static String TPL_FILE = "/ra/hashDirUserEnroll.template";
+ private final static String TPL_ERROR_FILE = "/ra/GenErrorHashDirEnroll.template";
+ private String mFormPath = null;
+
+ public DisplayHashUserEnroll() {
+ super();
+ }
+
+ /**
+ * Initializes the servlet.
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+
+ try {
+ mFormPath = sc.getInitParameter(
+ PROP_SUCCESS_TEMPLATE);
+ if (mFormPath == null)
+ mFormPath = TPL_FILE;
+ } catch (Exception e) {
+ }
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ protected CMSRequest newCMSRequest() {
+ return new CMSRequest();
+ }
+
+ /**
+ * Services the request
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ String reqHost = httpReq.getRemoteHost();
+
+ if (!(mAuthority instanceof IRegistrationAuthority)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_ERR_GET_TEMPLATE"));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_NOT_YET_IMPLEMENTED")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String val = configStore.getString("hashDirEnrollment.name");
+ IAuthSubsystem authSS = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ IAuthManager authMgr = authSS.get(val);
+ HashAuthentication mgr = (HashAuthentication) authMgr;
+ boolean isEnable = mgr.isEnable(reqHost);
+
+ if (!isEnable) {
+ printError(cmsReq, "0");
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+ Date date = new Date();
+ long currTime = date.getTime();
+ long timeout = mgr.getTimeout(reqHost);
+ long lastlogin = mgr.getLastLogin(reqHost);
+ long diff = currTime - lastlogin;
+
+ if (lastlogin == 0)
+ mgr.setLastLogin(reqHost, currTime);
+ else if (diff > timeout) {
+ mgr.disable(reqHost);
+ printError(cmsReq, "2");
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+ mgr.setLastLogin(reqHost, currTime);
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, httpReq, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+ private void printError(CMSRequest cmsReq, String errorCode)
+ throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ header.addStringValue("authority", "Registration Manager");
+ header.addStringValue("errorCode", errorCode);
+ String formPath = TPL_ERROR_FILE;
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(formPath, httpReq, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_ERR_GET_TEMPLATE", formPath, e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", e.toString()));
+
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/DoRevoke.java b/base/server/cms/src/com/netscape/cms/servlet/cert/DoRevoke.java
new file mode 100644
index 000000000..64a9856fc
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/DoRevoke.java
@@ -0,0 +1,812 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.X509CertImpl;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.authorization.EAuthzException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.ForbiddenException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.CertId;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.certsrv.usrgrp.ICertUserLocator;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Revoke a Certificate
+ *
+ * @version $Revision$, $Date$
+ */
+public class DoRevoke extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1693115906265904238L;
+ private final static String TPL_FILE = "revocationResult.template";
+
+ private ICertificateRepository mCertDB = null;
+ private String mFormPath = null;
+ private IPublisherProcessor mPublisherProcessor = null;
+ private int mTimeLimits = 30; /* in seconds */
+ private IUGSubsystem mUG = null;
+ private ICertUserLocator mUL = null;
+
+ public DoRevoke() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template
+ * file "revocationResult.template" to render the result
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ mUG = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+ mUL = mUG.getCertUserLocator();
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository();
+ }
+ if (mAuthority instanceof ICertAuthority) {
+ mPublisherProcessor = ((ICertAuthority) mAuthority).getPublisherProcessor();
+ }
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+
+ /* Server-Side time limit */
+ try {
+ mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits"));
+ } catch (Exception e) {
+ /* do nothing, just use the default if integer parsing failed */
+ }
+ }
+
+ /**
+ * Serves HTTP request. The http parameters used by this request are as follows:
+ *
+ * <pre>
+ * serialNumber Serial number of certificate to revoke (in HEX)
+ * revocationReason Revocation reason (Described below)
+ * totalRecordCount [number]
+ * verifiedRecordCount [number]
+ * invalidityDate [number of seconds in Jan 1,1970]
+ *
+ * </pre>
+ *
+ * revocationReason can be one of these values:
+ *
+ * <pre>
+ * 0 = Unspecified (default)
+ * 1 = Key compromised
+ * 2 = CA key compromised
+ * 3 = Affiliation changed
+ * 4 = Certificate superseded
+ * 5 = Cessation of operation
+ * 6 = Certificate is on hold
+ * </pre>
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ String revokeAll = null;
+ int totalRecordCount = -1;
+ int verifiedRecordCount = -1;
+ EBaseException error = null;
+ int reason = -1;
+ boolean authorized = true;
+ Date invalidityDate = null;
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ try {
+ if (req.getParameter("revocationReason") != null) {
+ reason = Integer.parseInt(req.getParameter(
+ "revocationReason"));
+ }
+ if (req.getParameter("totalRecordCount") != null) {
+ totalRecordCount = Integer.parseInt(req.getParameter(
+ "totalRecordCount"));
+ }
+ if (req.getParameter("verifiedRecordCount") != null) {
+ verifiedRecordCount = Integer.parseInt(
+ req.getParameter(
+ "verifiedRecordCount"));
+ }
+ if (req.getParameter("invalidityDate") != null) {
+ long l = Long.parseLong(req.getParameter(
+ "invalidityDate"));
+
+ if (l > 0) {
+ invalidityDate = new Date(l);
+ }
+ }
+ revokeAll = req.getParameter("revokeAll");
+
+ String comments = req.getParameter(IRequest.REQUESTOR_COMMENTS);
+ String eeSubjectDN = null;
+ String eeSerialNumber = null;
+
+ //for audit log.
+ String initiative = null;
+
+ String authMgr = AuditFormat.NOAUTH;
+
+ authToken = authenticate(req);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "revoke");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) {
+ if (authToken != null) {
+ // Request is from agent.
+
+ String serialNumber = req.getParameter("serialNumber");
+ getSSLClientCertificate(req); // throw exception on error
+
+ if (serialNumber != null) {
+ // Agent has null subject DN.
+ eeSerialNumber = serialNumber;
+ }
+
+ authMgr = authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ String agentID = authToken.getInString("userid");
+
+ initiative = AuditFormat.FROMAGENT + " agentID: " + agentID +
+ " authenticated by " + authMgr;
+ }
+ } else {
+ // Request is from user.
+ initiative = AuditFormat.FROMUSER;
+
+ String serialNumber = req.getParameter("serialNumber");
+ X509CertImpl sslCert = (X509CertImpl) getSSLClientCertificate(req);
+
+ if (serialNumber == null || sslCert == null ||
+ !(serialNumber.equals(sslCert.getSerialNumber().toString(16)))) {
+ throw new ForbiddenException("Invalid serial number.");
+
+ } else {
+ eeSubjectDN = sslCert.getSubjectDN().toString();
+ eeSerialNumber = sslCert.getSerialNumber().toString();
+ }
+
+ }
+
+ BigInteger serialNumber = parseSerialNumber(eeSerialNumber);
+
+ process(argSet, header, reason, invalidityDate, initiative,
+ req, resp, verifiedRecordCount, revokeAll,
+ totalRecordCount, serialNumber, eeSubjectDN,
+ comments, locale[0]);
+
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT"));
+ error = new EBaseException(CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT"));
+
+ } catch (ForbiddenException e) {
+ authorized = false;
+
+ } catch (EBaseException e) {
+ error = e;
+ }
+
+ /*
+ catch (Exception e) {
+ noError = false;
+ header.addStringValue(OUT_ERROR,
+ MessageFormatter.getLocalizedString(
+ errorlocale[0],
+ BaseResources.class.getName(),
+ BaseResources.INTERNAL_ERROR_1,
+ e.toString()));
+ }
+ */
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (error == null && authorized) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } else if (!authorized) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+ }
+
+ /**
+ * Process cert status change request
+ * <P>
+ *
+ * (Certificate Request - either an "agent" cert status change request, or an "EE" cert status change request)
+ * <P>
+ *
+ * (Certificate Request Processed - either an "agent" cert status change request, or an "EE" cert status change
+ * request)
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST used when a cert status change request (e. g. -
+ * "revocation") is made (before approval process)
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED used when a certificate status is
+ * changed (revoked, expired, on-hold, off-hold)
+ * </ul>
+ *
+ * @param argSet CMS template parameters
+ * @param header argument block
+ * @param reason revocation reason (0 - Unspecified, 1 - Key compromised,
+ * 2 - CA key compromised; should not be used, 3 - Affiliation changed,
+ * 4 - Certificate superceded, 5 - Cessation of operation, or
+ * 6 - Certificate is on hold)
+ * @param invalidityDate certificate validity date
+ * @param initiative string containing the audit format
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param verifiedRecordCount number of verified records
+ * @param revokeAll string containing information on all of the
+ * certificates to be revoked
+ * @param totalRecordCount total number of records (verified and unverified)
+ * @param eeSerialNumber BigInteger containing the end-entity certificate
+ * serial number
+ * @param eeSubjectDN string containing the end-entity certificate subject
+ * distinguished name (DN)
+ * @param comments string containing certificate comments
+ * @param locale the system locale
+ * @exception EBaseException an error has occurred
+ */
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ int reason, Date invalidityDate,
+ String initiative,
+ HttpServletRequest req,
+ HttpServletResponse resp,
+ int verifiedRecordCount,
+ String revokeAll,
+ int totalRecordCount,
+ BigInteger eeSerialNumber,
+ String eeSubjectDN,
+ String comments,
+ Locale locale)
+ throws EBaseException {
+
+ CMS.debug("DoRevoke: eeSerialNumber: " + eeSerialNumber);
+ long startTime = CMS.getCurrentDate().getTime();
+
+ RevocationProcessor processor =
+ new RevocationProcessor(servletConfig.getServletName(), getLocale(req));
+
+ processor.setStartTime(startTime);
+ processor.setInitiative(initiative);
+ processor.setSerialNumber(eeSerialNumber == null ? null : new CertId(eeSerialNumber));
+ processor.setRequestID(auditRequesterID(req));
+
+ RevocationReason revReason = RevocationReason.fromInt(reason);
+ processor.setRevocationReason(revReason);
+ processor.setRequestType(
+ processor.getRevocationReason() == RevocationReason.CERTIFICATE_HOLD
+ ? RevocationProcessor.ON_HOLD : RevocationProcessor.REVOKE);
+
+ processor.setInvalidityDate(invalidityDate);
+ processor.setComments(comments);
+
+ Hashtable<BigInteger, Long> nonceMap = new Hashtable<BigInteger, Long>();
+ X509Certificate clientCert = getSSLClientCertificate(req);
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ processor.setAuthority(certAuthority);
+
+ if (certAuthority.noncesEnabled()) {
+ String nonces = req.getParameter("nonce");
+ if (nonces == null) {
+ throw new ForbiddenException("Missing nonce.");
+ }
+
+ // parse serial numbers and nonces
+ for (String s : nonces.split(",")) {
+ String[] elements = s.split(":");
+ BigInteger serialNumber = new BigInteger(elements[0].trim());
+ Long nonce = new Long(elements[1].trim());
+ nonceMap.put(serialNumber, nonce);
+ }
+ }
+ }
+
+ try {
+ processor.createCRLExtension();
+
+ if (mAuthority instanceof ICertificateAuthority) {
+
+ Enumeration<ICertRecord> e = mCertDB.searchCertificates(revokeAll, totalRecordCount, mTimeLimits);
+
+ while (e != null && e.hasMoreElements()) {
+ ICertRecord targetRecord = e.nextElement();
+ X509CertImpl targetCert = targetRecord.getCertificate();
+
+ // Verify end-entity cert is not revoked.
+ // TODO: This should be checked during authentication.
+ if (eeSerialNumber != null &&
+ eeSerialNumber.equals(targetCert.getSerialNumber()) &&
+ targetRecord.getStatus().equals(ICertRecord.STATUS_REVOKED)) {
+ processor.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CA_CERTIFICATE_ALREADY_REVOKED_1",
+ targetRecord.getSerialNumber().toString(16)));
+
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_UNAUTHORIZED"));
+ }
+
+ IArgBlock rarg = CMS.createArgBlock();
+ rarg.addStringValue("serialNumber", targetCert.getSerialNumber().toString(16));
+
+ try {
+ if (mAuthority instanceof ICertificateAuthority &&
+ certAuthority.noncesEnabled() &&
+ !processor.isMemberOfSubsystemGroup(clientCert)) {
+ // validate nonce for each certificate
+ Long nonce = nonceMap.get(targetRecord.getSerialNumber());
+ processor.validateNonce(req, "cert-revoke", targetRecord.getSerialNumber(), nonce);
+ }
+
+ processor.validateCertificateToRevoke(eeSubjectDN, targetRecord, false);
+ processor.addCertificateToRevoke(targetCert);
+ rarg.addStringValue("error", null);
+
+ } catch (PKIException ex) {
+ rarg.addStringValue("error", ex.getMessage());
+ }
+
+ argSet.addRepeatRecord(rarg);
+ }
+
+ } else if (mAuthority instanceof IRegistrationAuthority) {
+ String reqIdStr = req.getParameter("requestId");
+ Collection<CertId> certSerialNumbers = new ArrayList<CertId>();
+
+ if (revokeAll != null && revokeAll.length() > 0) {
+ for (int i = revokeAll.indexOf('='); i > -1; i = revokeAll.indexOf('=', i)) {
+ i++;
+ // skip spaces
+ while (i < revokeAll.length() && revokeAll.charAt(i) == ' ') {
+ i++;
+ }
+ // xxxx decimal serial number?
+ String legalDigits = "0123456789";
+ int j = i;
+
+ // find legal digits
+ while (j < revokeAll.length() && legalDigits.indexOf(revokeAll.charAt(j)) != -1) {
+ j++;
+ }
+ if (j > i) {
+ certSerialNumbers.add(new CertId(revokeAll.substring(i, j)));
+ }
+ }
+ }
+
+ if (reqIdStr != null && reqIdStr.length() > 0 && certSerialNumbers.size() > 0) {
+ IRequest certReq = mRequestQueue.findRequest(new RequestId(reqIdStr));
+ X509CertImpl[] certs = certReq.getExtDataInCertArray(IRequest.OLD_CERTS);
+ boolean authorized = false;
+
+ for (int i = 0; i < certs.length; i++) {
+ boolean addToList = false;
+
+ for (CertId certSerialNumber : certSerialNumbers) {
+ //xxxxx serial number in decimal?
+ if (certs[i].getSerialNumber().equals(certSerialNumber.toBigInteger()) &&
+ eeSubjectDN != null && eeSubjectDN.equals(certs[i].getSubjectDN().toString())) {
+ addToList = true;
+ break;
+ }
+ }
+
+ if (eeSerialNumber != null && eeSerialNumber.equals(certs[i].getSerialNumber())) {
+ authorized = true;
+ }
+
+ if (addToList) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addStringValue("serialNumber", certs[i].getSerialNumber().toString(16));
+
+ processor.addCertificateToRevoke(certs[i]);
+
+ rarg.addStringValue("error", null);
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+
+ if (!authorized) {
+ processor.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_REQ_AUTH_REVOKED_CERT"));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_UNAUTHORIZED"));
+ }
+
+ } else {
+ String b64eCert = req.getParameter("b64eCertificate");
+
+ if (b64eCert != null) {
+ // BASE64Decoder decoder = new BASE64Decoder();
+ // byte[] certBytes = decoder.decodeBuffer(b64eCert);
+ byte[] certBytes = CMS.AtoB(b64eCert);
+ X509CertImpl cert = new X509CertImpl(certBytes);
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addStringValue("serialNumber", cert.getSerialNumber().toString(16));
+
+ processor.addCertificateToRevoke(cert);
+
+ rarg.addStringValue("error", null);
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ }
+
+ int count = processor.getCertificates().size();
+ if (count == 0) {
+ processor.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_REV_CERTS_ZERO"));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_REVOCATION_ERROR_CERT_NOT_FOUND"));
+ }
+
+ header.addIntegerValue("totalRecordCount", count);
+
+ processor.createRevocationRequest();
+
+ processor.auditChangeRequest(ILogger.SUCCESS);
+
+ } catch (ForbiddenException e) {
+ throw new EAuthzException(CMS.getUserMessage(locale, "CMS_AUTHORIZATION_ERROR"));
+
+ } catch (CertificateException e) {
+ processor.log(ILogger.LL_FAILURE, "Error " + e);
+ processor.auditChangeRequest(ILogger.FAILURE);
+
+ // TODO: throw exception or return?
+ // throw new EBaseException(e.getMessage());
+ return;
+
+ } catch (EBaseException e) {
+ processor.log(ILogger.LL_FAILURE, "Error " + e);
+ processor.auditChangeRequest(ILogger.FAILURE);
+
+ throw e;
+
+ } catch (IOException e) {
+ processor.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED_1", e.toString()));
+ processor.auditChangeRequest(ILogger.FAILURE);
+
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED"));
+ }
+
+ // change audit processing from "REQUEST" to "REQUEST_PROCESSED"
+ // to distinguish which type of signed audit log message to save
+ // as a failure outcome in case an exception occurs
+
+ try {
+ processor.processRevocationRequest();
+ IRequest revReq = processor.getRequest();
+
+ // retrieve the request status
+ RequestStatus status = revReq.getRequestStatus();
+ processor.setRequestStatus(status);
+
+ String type = revReq.getRequestType();
+
+ // The SVC_PENDING check has been added for the Cloned CA request
+ // that is meant for the Master CA. From Clone's point of view
+ // the request is complete
+
+ if (status == RequestStatus.COMPLETE
+ || status == RequestStatus.SVC_PENDING
+ && type.equals(IRequest.CLA_CERT4CRL_REQUEST)) {
+
+ header.addStringValue("revoked", "yes");
+
+ Integer updateCRLResult = revReq.getExtDataInInteger(IRequest.CRL_UPDATE_STATUS);
+
+ if (updateCRLResult != null) {
+ header.addStringValue("updateCRL", "yes");
+ if (updateCRLResult.equals(IRequest.RES_SUCCESS)) {
+ header.addStringValue("updateCRLSuccess", "yes");
+ } else {
+ header.addStringValue("updateCRLSuccess", "no");
+ String crlError = revReq.getExtDataInString(IRequest.CRL_UPDATE_ERROR);
+
+ if (crlError != null)
+ header.addStringValue("updateCRLError", crlError);
+ }
+
+ // let known crl publishing status too.
+ Integer publishCRLResult = revReq.getExtDataInInteger(IRequest.CRL_PUBLISH_STATUS);
+
+ if (publishCRLResult != null) {
+ if (publishCRLResult.equals(IRequest.RES_SUCCESS)) {
+ header.addStringValue("publishCRLSuccess", "yes");
+ } else {
+ header.addStringValue("publishCRLSuccess", "no");
+ String publError = revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR);
+
+ if (publError != null)
+ header.addStringValue("publishCRLError", publError);
+ }
+ }
+ }
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ // let known update and publish status of all crls.
+ Enumeration<ICRLIssuingPoint> otherCRLs =
+ ((ICertificateAuthority) mAuthority).getCRLIssuingPoints();
+
+ while (otherCRLs.hasMoreElements()) {
+ ICRLIssuingPoint crl = otherCRLs.nextElement();
+ String crlId = crl.getId();
+
+ if (crlId.equals(ICertificateAuthority.PROP_MASTER_CRL))
+ continue;
+
+ String updateStatusStr = crl.getCrlUpdateStatusStr();
+ Integer updateResult = revReq.getExtDataInInteger(updateStatusStr);
+
+ if (updateResult != null) {
+ if (updateResult.equals(IRequest.RES_SUCCESS)) {
+ CMS.debug("DoRevoke: "
+ + CMS.getLogMessage("ADMIN_SRVLT_ADDING_HEADER", updateStatusStr));
+ header.addStringValue(updateStatusStr, "yes");
+
+ } else {
+ String updateErrorStr = crl.getCrlUpdateErrorStr();
+
+ CMS.debug("DoRevoke: " + CMS.getLogMessage("ADMIN_SRVLT_ADDING_HEADER_NO",
+ updateStatusStr));
+ header.addStringValue(updateStatusStr, "no");
+ String error = revReq.getExtDataInString(updateErrorStr);
+
+ if (error != null)
+ header.addStringValue(updateErrorStr, error);
+ }
+
+ String publishStatusStr = crl.getCrlPublishStatusStr();
+ Integer publishResult = revReq.getExtDataInInteger(publishStatusStr);
+
+ if (publishResult == null)
+ continue;
+
+ if (publishResult.equals(IRequest.RES_SUCCESS)) {
+ header.addStringValue(publishStatusStr, "yes");
+
+ } else {
+ String publishErrorStr = crl.getCrlPublishErrorStr();
+ header.addStringValue(publishStatusStr, "no");
+ String error = revReq.getExtDataInString(publishErrorStr);
+
+ if (error != null)
+ header.addStringValue(publishErrorStr, error);
+ }
+ }
+ }
+ }
+
+ if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) {
+ header.addStringValue("dirEnabled", "yes");
+ Integer[] ldapPublishStatus = revReq.getExtDataInIntegerArray("ldapPublishStatus");
+ int certsToUpdate = 0;
+ int certsUpdated = 0;
+
+ if (ldapPublishStatus != null) {
+ certsToUpdate = ldapPublishStatus.length;
+ for (int i = 0; i < certsToUpdate; i++) {
+ if (ldapPublishStatus[i] == IRequest.RES_SUCCESS) {
+ certsUpdated++;
+ }
+ }
+ }
+
+ header.addIntegerValue("certsUpdated", certsUpdated);
+ header.addIntegerValue("certsToUpdate", certsToUpdate);
+
+ // add crl publishing status.
+ String publError = revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR);
+
+ if (publError != null) {
+ header.addStringValue("crlPublishError", publError);
+ }
+
+ } else {
+ header.addStringValue("dirEnabled", "no");
+ }
+
+ header.addStringValue("error", null);
+
+ } else {
+ if (status == RequestStatus.PENDING || status == RequestStatus.REJECTED) {
+ header.addStringValue("revoked", status.toString());
+ } else {
+ header.addStringValue("revoked", "no");
+ }
+
+ Vector<String> errors = revReq.getExtDataInStringVector(IRequest.ERRORS);
+ if (errors != null) {
+ StringBuilder errInfo = new StringBuilder();
+ for (int i = 0; i < errors.size(); i++) {
+ errInfo.append(errors.elementAt(i));
+ errInfo.append("\n");
+ }
+ header.addStringValue("error", errInfo.toString());
+
+ } else if (status == RequestStatus.PENDING) {
+ header.addStringValue("error", "Request Pending");
+
+ } else {
+ header.addStringValue("error", null);
+ }
+ }
+
+ processor.auditChangeRequestProcessed(ILogger.SUCCESS);
+
+ } catch (EBaseException e) {
+ processor.log(ILogger.LL_FAILURE, "Error " + e);
+ processor.auditChangeRequestProcessed(ILogger.FAILURE);
+
+ throw e;
+ }
+ }
+
+ /**
+ * Signed Audit Log Requester ID
+ *
+ * This method is called to obtain the "RequesterID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param req HTTP request
+ * @return id string containing the signed audit log message RequesterID
+ */
+ private RequestId auditRequesterID(HttpServletRequest req) {
+ String requesterID = req.getParameter("requestId");
+
+ if (requesterID != null) {
+ return new RequestId(requesterID.trim());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * This method parses a String serial number into BigInteger.
+ *
+ * @param serialNumber a String containing the un-normalized serial number
+ * @return a BigInteger containing the serial number
+ */
+ private BigInteger parseSerialNumber(String serialNumber) {
+
+ if (StringUtils.isEmpty(serialNumber)) return null;
+
+ // Normalize the serialNumber
+ serialNumber = serialNumber.trim();
+
+ // find out if the value is hex or decimal
+
+ //try decimal
+ try {
+ return new BigInteger(serialNumber, 10);
+ } catch (NumberFormatException e) {
+ }
+
+ //try hex
+ try {
+ return new BigInteger(serialNumber, 16);
+ } catch (NumberFormatException e) {
+ }
+
+ // give up if it isn't hex or dec
+ throw new NumberFormatException("Invalid serial number: "+serialNumber);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/DoRevokeTPS.java b/base/server/cms/src/com/netscape/cms/servlet/cert/DoRevokeTPS.java
new file mode 100644
index 000000000..63806e659
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/DoRevokeTPS.java
@@ -0,0 +1,930 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.InvalidityDateExtension;
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Revoke a Certificate
+ *
+ * @version $Revision$, $Date$
+ */
+public class DoRevokeTPS extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2980600514636454836L;
+ private final static String TPL_FILE = "revocationResult.template";
+
+ private ICertificateRepository mCertDB = null;
+ private String mFormPath = null;
+ private IRequestQueue mQueue = null;
+ private IPublisherProcessor mPublisherProcessor = null;
+ private String errorString = "error=";
+ private String o_status = "status=0";
+ private int mTimeLimits = 30; /* in seconds */
+
+ private final static String REVOKE = "revoke";
+ private final static String ON_HOLD = "on-hold";
+ private final static int ON_HOLD_REASON = 6;
+ private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST =
+ "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_5";
+ private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED =
+ "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED_7";
+
+ public DoRevokeTPS() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template
+ * file "revocationResult.template" to render the result
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository();
+ }
+ if (mAuthority instanceof ICertAuthority) {
+ mPublisherProcessor = ((ICertAuthority) mAuthority).getPublisherProcessor();
+ }
+ mQueue = mAuthority.getRequestQueue();
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ mRenderResult = false;
+
+ /* Server-Side time limit */
+ try {
+ mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits"));
+ } catch (Exception e) {
+ /* do nothing, just use the default if integer parsing failed */
+ }
+ }
+
+ /**
+ * Serves HTTP request. The http parameters used by this request are as follows:
+ *
+ * <pre>
+ * serialNumber Serial number of certificate to revoke (in HEX)
+ * revocationReason Revocation reason (Described below)
+ * totalRecordCount [number]
+ * verifiedRecordCount [number]
+ * invalidityDate [number of seconds in Jan 1,1970]
+ *
+ * </pre>
+ *
+ * revocationReason can be one of these values:
+ *
+ * <pre>
+ * 0 = Unspecified (default)
+ * 1 = Key compromised
+ * 2 = CA key compromised
+ * 3 = Affiliation changed
+ * 4 = Certificate superseded
+ * 5 = Cessation of operation
+ * 6 = Certificate is on hold
+ * </pre>
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+ CMS.debug("DoRevokeTPS after authenticate");
+
+ String revokeAll = null;
+ int totalRecordCount = -1;
+ EBaseException error = null;
+ int reason = -1;
+ boolean authorized = true;
+ Date invalidityDate = null;
+ Locale[] locale = new Locale[1];
+
+ CMS.debug("DoRevokeTPS before getTemplate");
+ try {
+ @SuppressWarnings("unused")
+ CMSTemplate form = getTemplate(mFormPath, req, locale); // check for errors
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ } catch (Exception e) {
+ CMS.debug("DoRevokeTPS getTemplate failed");
+ throw new EBaseException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+
+ CMS.debug("DoRevokeTPS after getTemplate");
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ try {
+ if (req.getParameter("revocationReason") != null) {
+ reason = Integer.parseInt(req.getParameter(
+ "revocationReason"));
+ }
+ if (req.getParameter("totalRecordCount") != null) {
+ totalRecordCount = Integer.parseInt(req.getParameter(
+ "totalRecordCount"));
+ }
+ if (req.getParameter("invalidityDate") != null) {
+ long l = Long.parseLong(req.getParameter(
+ "invalidityDate"));
+
+ if (l > 0) {
+ invalidityDate = new Date(l);
+ }
+ }
+ revokeAll = req.getParameter("revokeAll");
+ String comments = req.getParameter(IRequest.REQUESTOR_COMMENTS);
+
+ //for audit log.
+ String initiative = null;
+
+ String authMgr = AuditFormat.NOAUTH;
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "revoke");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) {
+ if (authToken != null) {
+ authMgr = authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ String agentID = authToken.getInString("userid");
+
+ initiative = AuditFormat.FROMAGENT + " agentID: " + agentID +
+ " authenticated by " + authMgr;
+ }
+ } else {
+ CMS.debug("DoRevokeTPS: Missing authentication manager");
+ o_status = "status=1";
+ errorString = "errorString=Missing authentication manager.";
+ }
+
+ if (authorized) {
+ process(argSet, header, reason, invalidityDate, initiative, req,
+ resp, revokeAll, totalRecordCount, comments, locale[0]);
+ }
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT"));
+ error = new EBaseException(CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT"));
+ } catch (EBaseException e) {
+ error = e;
+ }
+
+ try {
+ if (!authorized) {
+ o_status = "status=3";
+ errorString = "error=unauthorized";
+ } else if (error != null) {
+ o_status = "status=3";
+ errorString = "error=" + error.toString();
+ }
+
+ String pp = o_status + "\n" + errorString;
+ byte[] b = pp.getBytes();
+ resp.setContentType("text/html");
+ resp.setContentLength(b.length);
+ OutputStream os = resp.getOutputStream();
+ os.write(b);
+ os.flush();
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ }
+ }
+
+ /**
+ * Process cert status change request
+ * <P>
+ *
+ * (Certificate Request - either an "agent" cert status change request, or an "EE" cert status change request)
+ * <P>
+ *
+ * (Certificate Request Processed - either an "agent" cert status change request, or an "EE" cert status change
+ * request)
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST used when a cert status change request (e. g. -
+ * "revocation") is made (before approval process)
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED used when a certificate status is
+ * changed (revoked, expired, on-hold, off-hold)
+ * </ul>
+ *
+ * @param argSet CMS template parameters
+ * @param header argument block
+ * @param reason revocation reason (0 - Unspecified, 1 - Key compromised,
+ * 2 - CA key compromised; should not be used, 3 - Affiliation changed,
+ * 4 - Certificate superceded, 5 - Cessation of operation, or
+ * 6 - Certificate is on hold)
+ * @param invalidityDate certificate validity date
+ * @param initiative string containing the audit format
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param revokeAll string containing information on all of the
+ * certificates to be revoked
+ * @param totalRecordCount total number of records (verified and unverified)
+ * @param comments string containing certificate comments
+ * @param locale the system locale
+ * @exception EBaseException an error has occurred
+ */
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ int reason, Date invalidityDate,
+ String initiative,
+ HttpServletRequest req,
+ HttpServletResponse resp,
+ String revokeAll,
+ int totalRecordCount,
+ String comments,
+ Locale locale)
+ throws EBaseException {
+ boolean auditRequest = true;
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRequesterID = auditRequesterID(req);
+ String auditSerialNumber = auditSerialNumber(null);
+ String auditRequestType = auditRequestType(reason);
+ RequestStatus auditApprovalStatus = null;
+ String auditReasonNum = String.valueOf(reason);
+
+ if (revokeAll != null) {
+ CMS.debug("DoRevokeTPS.process revokeAll" + revokeAll);
+
+ String serial = "";
+ String[] tokens;
+ tokens = revokeAll.split("=");
+
+ if (tokens.length == 2) {
+ serial = tokens[1];
+ //remove the trailing paren
+ if (serial.endsWith(")")) {
+ serial = serial.substring(0, serial.length() - 1);
+ }
+ auditSerialNumber = serial;
+ }
+ }
+
+ long startTime = CMS.getCurrentDate().getTime();
+
+ try {
+ int count = 0;
+ Vector<X509CertImpl> oldCertsV = new Vector<X509CertImpl>();
+ Vector<RevokedCertImpl> revCertImplsV = new Vector<RevokedCertImpl>();
+
+ // Construct a CRL reason code extension.
+ RevocationReason revReason = RevocationReason.fromInt(reason);
+ CRLReasonExtension crlReasonExtn = new CRLReasonExtension(revReason);
+
+ // Construct a CRL invalidity date extension.
+ InvalidityDateExtension invalidityDateExtn = null;
+
+ if (invalidityDate != null) {
+ invalidityDateExtn = new InvalidityDateExtension(invalidityDate);
+ }
+
+ // Construct a CRL extension for this request.
+ CRLExtensions entryExtn = new CRLExtensions();
+
+ if (crlReasonExtn != null) {
+ entryExtn.set(crlReasonExtn.getName(), crlReasonExtn);
+ }
+ if (invalidityDateExtn != null) {
+ entryExtn.set(invalidityDateExtn.getName(), invalidityDateExtn);
+ }
+
+ Enumeration<ICertRecord> e = mCertDB.searchCertificates(revokeAll,
+ totalRecordCount, mTimeLimits);
+
+ boolean alreadyRevokedCertFound = false;
+ boolean badCertsRequested = false;
+ while (e != null && e.hasMoreElements()) {
+ ICertRecord rec = e.nextElement();
+
+ if (rec == null) {
+ badCertsRequested = true;
+ continue;
+ }
+ X509CertImpl xcert = rec.getCertificate();
+ IArgBlock rarg = CMS.createArgBlock();
+
+ // we do not want to revoke the CA certificate accidentially
+ if (xcert != null && isSystemCertificate(xcert.getSerialNumber())) {
+ CMS.debug("DoRevokeTPS: skipped revocation request for system certificate "
+ + xcert.getSerialNumber());
+ badCertsRequested = true;
+ continue;
+ }
+
+ if (xcert != null) {
+ rarg.addStringValue("serialNumber",
+ xcert.getSerialNumber().toString(16));
+
+ if (rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) {
+ alreadyRevokedCertFound = true;
+ CMS.debug("Certificate 0x" + xcert.getSerialNumber().toString(16) + " has been revoked.");
+ } else {
+ oldCertsV.addElement(xcert);
+
+ RevokedCertImpl revCertImpl =
+ new RevokedCertImpl(xcert.getSerialNumber(),
+ CMS.getCurrentDate(), entryExtn);
+
+ revCertImplsV.addElement(revCertImpl);
+ CMS.debug("Certificate 0x" + xcert.getSerialNumber().toString(16) + " is going to be revoked.");
+ count++;
+ }
+ } else {
+ badCertsRequested = true;
+ }
+ }
+
+ if (count == 0) {
+ // Situation where no certs were reoked here, but some certs
+ // requested happened to be already revoked. Don't return error.
+ if (alreadyRevokedCertFound == true && badCertsRequested == false) {
+ CMS.debug("Only have previously revoked certs in the list.");
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType);
+
+ audit(auditMessage);
+ return;
+ }
+
+ errorString = "error=No certificates are revoked.";
+ o_status = "status=2";
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_REV_CERTS_ZERO"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED"));
+ }
+
+ X509CertImpl[] oldCerts = new X509CertImpl[count];
+ RevokedCertImpl[] revCertImpls = new RevokedCertImpl[count];
+
+ for (int i = 0; i < count; i++) {
+ oldCerts[i] = oldCertsV.elementAt(i);
+ revCertImpls[i] = revCertImplsV.elementAt(i);
+ }
+
+ IRequest revReq =
+ mQueue.newRequest(IRequest.REVOCATION_REQUEST);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType);
+
+ audit(auditMessage);
+
+ revReq.setExtData(IRequest.CERT_INFO, revCertImpls);
+ revReq.setExtData(IRequest.REQ_TYPE, IRequest.REVOCATION_REQUEST);
+ if (initiative.equals(AuditFormat.FROMUSER)) {
+ revReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_EE);
+ } else {
+ revReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_AGENT);
+ }
+ revReq.setExtData(IRequest.OLD_CERTS, oldCerts);
+ if (comments != null) {
+ revReq.setExtData(IRequest.REQUESTOR_COMMENTS, comments);
+ }
+ revReq.setExtData(IRequest.REVOKED_REASON,
+ Integer.valueOf(reason));
+
+ // change audit processing from "REQUEST" to "REQUEST_PROCESSED"
+ // to distinguish which type of signed audit log message to save
+ // as a failure outcome in case an exception occurs
+ auditRequest = false;
+
+ mQueue.processRequest(revReq);
+
+ // retrieve the request status
+ auditApprovalStatus = revReq.getRequestStatus();
+
+ RequestStatus stat = revReq.getRequestStatus();
+ String type = revReq.getRequestType();
+
+ // The SVC_PENDING check has been added for the Cloned CA request
+ // that is meant for the Master CA. From Clone's point of view
+ // the request is complete
+ if ((stat == RequestStatus.COMPLETE)
+ || ((type.equals(IRequest.CLA_CERT4CRL_REQUEST)) && (stat == RequestStatus.SVC_PENDING))) {
+ // audit log the error
+ Integer result = revReq.getExtDataInInteger(IRequest.RESULT);
+
+ if (result.equals(IRequest.RES_ERROR)) {
+ String[] svcErrors =
+ revReq.getExtDataInStringArray(IRequest.SVCERRORS);
+
+ if (svcErrors != null && svcErrors.length > 0) {
+ for (int i = 0; i < svcErrors.length; i++) {
+ String err = svcErrors[i];
+
+ if (err != null) {
+ //cmsReq.setErrorDescription(err);
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] instanceof X509CertImpl) {
+ X509CertImpl cert = oldCerts[j];
+
+ if (oldCerts[j] != null) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ revReq.getRequestId(),
+ initiative,
+ "completed with error: " +
+ err,
+ cert.getSubjectDN(),
+ cert.getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString() }
+ );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // store a message in the signed audit log file
+ // if and only if "auditApprovalStatus" is
+ // "complete", "revoked", or "canceled"
+ if (auditApprovalStatus == RequestStatus.COMPLETE ||
+ auditApprovalStatus == RequestStatus.REJECTED ||
+ auditApprovalStatus == RequestStatus.CANCELED) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus == null ? ILogger.SIGNED_AUDIT_EMPTY_VALUE : auditApprovalStatus.toString());
+
+ audit(auditMessage);
+ }
+
+ return;
+ }
+
+ long endTime = CMS.getCurrentDate().getTime();
+
+ // audit log the success.
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ if (oldCerts[j] instanceof X509CertImpl) {
+ X509CertImpl cert = oldCerts[j];
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ revReq.getRequestId(),
+ initiative,
+ "completed",
+ cert.getSubjectDN(),
+ cert.getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString()
+ + " time: " + (endTime - startTime) }
+ );
+ }
+ }
+ }
+
+ header.addStringValue("revoked", "yes");
+
+ Integer updateCRLResult =
+ revReq.getExtDataInInteger(IRequest.CRL_UPDATE_STATUS);
+
+ if (updateCRLResult != null) {
+ if (!updateCRLResult.equals(IRequest.RES_SUCCESS)) {
+
+ o_status = "status=3";
+ if (revReq.getExtDataInString(IRequest.CRL_UPDATE_ERROR) != null) {
+ errorString = "error=Update CRL Error.";
+ // 3 means miscellaneous
+ }
+ }
+ // let known crl publishing status too.
+ Integer publishCRLResult =
+ revReq.getExtDataInInteger(IRequest.CRL_PUBLISH_STATUS);
+
+ if (publishCRLResult != null) {
+ if (!publishCRLResult.equals(IRequest.RES_SUCCESS)) {
+ String publError =
+ revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR);
+
+ o_status = "status=3";
+ if (publError != null) {
+ errorString = "error=" + publError;
+ }
+ }
+ }
+ }
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ // let known update and publish status of all crls.
+ Enumeration<ICRLIssuingPoint> otherCRLs =
+ ((ICertificateAuthority) mAuthority).getCRLIssuingPoints();
+
+ while (otherCRLs.hasMoreElements()) {
+ ICRLIssuingPoint crl = otherCRLs.nextElement();
+ String crlId = crl.getId();
+
+ if (crlId.equals(ICertificateAuthority.PROP_MASTER_CRL))
+ continue;
+ String updateStatusStr = crl.getCrlUpdateStatusStr();
+ Integer updateResult = revReq.getExtDataInInteger(updateStatusStr);
+
+ if (updateResult != null) {
+ if (!updateResult.equals(IRequest.RES_SUCCESS)) {
+ String updateErrorStr = crl.getCrlUpdateErrorStr();
+
+ CMS.debug("DoRevoke: " + CMS.getLogMessage("ADMIN_SRVLT_ADDING_HEADER_NO",
+ updateStatusStr));
+ String error =
+ revReq.getExtDataInString(updateErrorStr);
+
+ o_status = "status=3";
+ if (error != null) {
+ errorString = "error=" + error;
+ }
+ }
+ String publishStatusStr = crl.getCrlPublishStatusStr();
+ Integer publishResult =
+ revReq.getExtDataInInteger(publishStatusStr);
+
+ if (publishResult == null)
+ continue;
+ if (!publishResult.equals(IRequest.RES_SUCCESS)) {
+ String publishErrorStr =
+ crl.getCrlPublishErrorStr();
+
+ String error =
+ revReq.getExtDataInString(publishErrorStr);
+
+ o_status = "status=3";
+ if (error != null) {
+ errorString = "error=Publish CRL Status Error.";
+ }
+ }
+ }
+ }
+ }
+
+ if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) {
+ header.addStringValue("dirEnabled", "yes");
+
+ // add crl publishing status.
+ String publError =
+ revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR);
+
+ if (publError != null) {
+ errorString = "error=" + publError;
+ o_status = "status=3";
+ }
+ } else if (mPublisherProcessor == null && mPublisherProcessor.ldapEnabled()) {
+ errorString = "error=LDAP publishing not enabled.";
+ o_status = "status=3";
+ }
+ } else {
+ if (stat == RequestStatus.PENDING || stat == RequestStatus.REJECTED) {
+ o_status = "status=2";
+ errorString = "error=" + stat.toString();
+ } else {
+ o_status = "status=2";
+ errorString = "error=Undefined request status";
+ }
+ Vector<String> errors = revReq.getExtDataInStringVector(IRequest.ERRORS);
+ if (errors != null) {
+ StringBuffer errInfo = new StringBuffer();
+
+ for (int i = 0; i < errors.size(); i++) {
+ errInfo.append(errors.elementAt(i));
+ errInfo.append("\n");
+ }
+ o_status = "status=2";
+ errorString = "error=" + errInfo.toString();
+
+ } else if (stat == RequestStatus.PENDING) {
+ o_status = "status=2";
+ errorString = "error=Request pending";
+ } else {
+ o_status = "status=2";
+ errorString = "error=Undefined request status";
+ }
+
+ // audit log the pending, revoked and rest
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ if (oldCerts[j] instanceof X509CertImpl) {
+ X509CertImpl cert = oldCerts[j];
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ revReq.getRequestId(),
+ initiative,
+ stat.toString(),
+ cert.getSubjectDN(),
+ cert.getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString() }
+ );
+ }
+ }
+ }
+ }
+
+ // store a message in the signed audit log file
+ // if and only if "auditApprovalStatus" is
+ // "complete", "revoked", or "canceled"
+ if (auditApprovalStatus == RequestStatus.COMPLETE ||
+ auditApprovalStatus == RequestStatus.REJECTED ||
+ auditApprovalStatus == RequestStatus.CANCELED) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus == null ? ILogger.SIGNED_AUDIT_EMPTY_VALUE : auditApprovalStatus.toString());
+
+ audit(auditMessage);
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, "error " + e);
+
+ if (auditRequest) {
+ // store a "CERT_STATUS_CHANGE_REQUEST" failure
+ // message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType);
+
+ audit(auditMessage);
+ } else {
+ // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure
+ // message in the signed audit log file
+ // if and only if "auditApprovalStatus" is
+ // "complete", "revoked", or "canceled"
+ if (auditApprovalStatus == RequestStatus.COMPLETE ||
+ auditApprovalStatus == RequestStatus.REJECTED ||
+ auditApprovalStatus == RequestStatus.CANCELED) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus == null ? ILogger.SIGNED_AUDIT_EMPTY_VALUE : auditApprovalStatus.toString());
+
+ audit(auditMessage);
+ }
+ }
+
+ throw e;
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED_1", e.toString()));
+
+ if (auditRequest) {
+ // store a "CERT_STATUS_CHANGE_REQUEST" failure
+ // message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType);
+
+ audit(auditMessage);
+ } else {
+ // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure
+ // message in the signed audit log file
+ // if and only if "auditApprovalStatus" is
+ // "complete", "revoked", or "canceled"
+ if (auditApprovalStatus == RequestStatus.COMPLETE ||
+ auditApprovalStatus == RequestStatus.REJECTED ||
+ auditApprovalStatus == RequestStatus.CANCELED) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus == null ? ILogger.SIGNED_AUDIT_EMPTY_VALUE : auditApprovalStatus.toString());
+
+ audit(auditMessage);
+ }
+ }
+
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED"));
+ }
+
+ return;
+ }
+
+ /**
+ * Signed Audit Log Requester ID
+ *
+ * This method is called to obtain the "RequesterID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param req HTTP request
+ * @return id string containing the signed audit log message RequesterID
+ */
+ private String auditRequesterID(HttpServletRequest req) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String requesterID = null;
+
+ // Obtain the requesterID
+ requesterID = req.getParameter("requestId");
+
+ if (requesterID != null) {
+ requesterID = requesterID.trim();
+ } else {
+ requesterID = ILogger.UNIDENTIFIED;
+ }
+
+ return requesterID;
+ }
+
+ /**
+ * Signed Audit Log Serial Number
+ *
+ * This method is called to obtain the serial number of the certificate
+ * whose status is to be changed for a signed audit log message.
+ * <P>
+ *
+ * @param eeSerialNumber a string containing the un-normalized serialNumber
+ * @return id string containing the signed audit log message RequesterID
+ */
+ private String auditSerialNumber(String eeSerialNumber) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String serialNumber = null;
+
+ // Normalize the serialNumber
+ if (eeSerialNumber != null) {
+ serialNumber = eeSerialNumber.trim();
+
+ // convert it to hexadecimal
+ serialNumber = "0x" + (new BigInteger(serialNumber)).toString(16);
+ } else {
+ serialNumber = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ return serialNumber;
+ }
+
+ /**
+ * Signed Audit Log Request Type
+ *
+ * This method is called to obtain the "Request Type" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param reason an integer denoting the revocation reason
+ * @return string containing REVOKE or ON_HOLD
+ */
+ private String auditRequestType(int reason) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String requestType = null;
+
+ // Determine the revocation type based upon the revocation reason
+ if (reason == ON_HOLD_REASON) {
+ requestType = ON_HOLD;
+ } else {
+ requestType = REVOKE;
+ }
+
+ return requestType;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/DoUnrevoke.java b/base/server/cms/src/com/netscape/cms/servlet/cert/DoUnrevoke.java
new file mode 100644
index 000000000..142fea3c8
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/DoUnrevoke.java
@@ -0,0 +1,499 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.RevocationReason;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.CertId;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * 'Unrevoke' a certificate. (For certificates that are on-hold only,
+ * take them off-hold)
+ *
+ * @version $Revision$, $Date$
+ */
+public class DoUnrevoke extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7978703730006036625L;
+ private final static String TPL_FILE = "unrevocationResult.template";
+
+ @SuppressWarnings("unused")
+ private ICertificateRepository mCertDB;
+
+ private String mFormPath = null;
+ private IPublisherProcessor mPublisherProcessor = null;
+
+ public DoUnrevoke() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ if (mAuthority instanceof ICertificateAuthority) {
+ mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository();
+ }
+ if (mAuthority instanceof ICertAuthority) {
+ mPublisherProcessor = ((ICertAuthority) mAuthority).getPublisherProcessor();
+ }
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param serialNumber Decimal serial number of certificate to unrevoke. The certificate must be revoked
+ * with a revovcation reason 'on hold' for this operation to succeed. The serial number may be expressed as a hex
+ * number by prefixing '0x' to the serialNumber string
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ BigInteger[] serialNumber;
+ EBaseException error = null;
+
+ CMSTemplate form = null;
+
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ try {
+ serialNumber = getSerialNumbers(req);
+
+ //for audit log.
+ IAuthToken authToken = authenticate(cmsReq);
+ String authMgr = AuditFormat.NOAUTH;
+
+ if (authToken != null) {
+ authMgr =
+ authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ } else {
+ CMS.debug("DoUnrevoke::process() - authToken is null!");
+ return;
+ }
+ String agentID = authToken.getInString("userid");
+ String initiative = AuditFormat.FROMAGENT + " agentID: " + agentID
+ + " authenticated by " + authMgr;
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "unrevoke");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ process(argSet, header, serialNumber, req, resp, locale[0], initiative);
+
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_SERIAL_NUM_FORMAT"));
+ error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT"));
+ } catch (EBaseException e) {
+ error = e;
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ /**
+ * Process X509 cert status change request
+ * <P>
+ *
+ * (Certificate Request - an "agent" cert status change request to take a certificate off-hold)
+ * <P>
+ *
+ * (Certificate Request Processed - an "agent" cert status change request to take a certificate off-hold)
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST used when a cert status change request (e. g. -
+ * "revocation") is made (before approval process)
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED used when a certificate status is
+ * changed (taken off-hold)
+ * </ul>
+ *
+ * @param argSet CMS template parameters
+ * @param header argument block
+ * @param serialNumbers the serial number of the certificate
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param locale the system locale
+ * @param initiative string containing the audit format
+ * @exception EBaseException an error has occurred
+ */
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ BigInteger[] serialNumbers,
+ HttpServletRequest req,
+ HttpServletResponse resp,
+ Locale locale, String initiative)
+ throws EBaseException {
+
+ RevocationProcessor processor = new RevocationProcessor(
+ servletConfig.getServletName(), getLocale(req));
+
+ processor.setInitiative(initiative);
+ processor.setSerialNumber(auditSerialNumber(serialNumbers[0].toString()));
+ processor.setRequestID(auditRequesterID(req));
+
+ processor.setRevocationReason(RevocationReason.CERTIFICATE_HOLD);
+ processor.setRequestType(RevocationProcessor.OFF_HOLD);
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ processor.setAuthority((ICertificateAuthority) mAuthority);
+ }
+
+ try {
+ StringBuilder snList = new StringBuilder();
+
+ for (BigInteger serialNumber : serialNumbers) {
+
+ processor.addSerialNumberToUnrevoke(serialNumber);
+
+ if (snList.length() > 0)
+ snList.append(", ");
+ snList.append("0x");
+ snList.append(serialNumber.toString(16));
+ }
+
+ header.addStringValue("serialNumber", snList.toString());
+
+ processor.createUnrevocationRequest();
+
+ processor.auditChangeRequest(ILogger.SUCCESS);
+
+ } catch (EBaseException e) {
+ processor.log(ILogger.LL_FAILURE, "Error " + e);
+ processor.auditChangeRequest(ILogger.FAILURE);
+
+ throw new PKIException(e.getMessage());
+ }
+
+ // change audit processing from "REQUEST" to "REQUEST_PROCESSED"
+ // to distinguish which type of signed audit log message to save
+ // as a failure outcome in case an exception occurs
+
+ try {
+ processor.processUnrevocationRequest();
+ IRequest unrevReq = processor.getRequest();
+
+ RequestStatus status = unrevReq.getRequestStatus();
+ String type = unrevReq.getRequestType();
+
+ if (status == RequestStatus.COMPLETE
+ || status == RequestStatus.SVC_PENDING && type.equals(IRequest.CLA_UNCERT4CRL_REQUEST)) {
+
+ Integer result = unrevReq.getExtDataInInteger(IRequest.RESULT);
+
+ if (result != null && result.equals(IRequest.RES_SUCCESS)) {
+ header.addStringValue("unrevoked", "yes");
+
+ } else {
+ header.addStringValue("unrevoked", "no");
+ String error = unrevReq.getExtDataInString(IRequest.ERROR);
+
+ if (error != null) {
+ header.addStringValue("error", error);
+
+ // TODO: throw exception on error?
+ // throw new EBaseException(error);
+ }
+ }
+
+ Integer updateCRLResult = unrevReq.getExtDataInInteger(IRequest.CRL_UPDATE_STATUS);
+
+ if (updateCRLResult != null) {
+ header.addStringValue("updateCRL", "yes");
+
+ if (updateCRLResult.equals(IRequest.RES_SUCCESS)) {
+ header.addStringValue("updateCRLSuccess", "yes");
+
+ } else {
+ header.addStringValue("updateCRLSuccess", "no");
+ String crlError = unrevReq.getExtDataInString(IRequest.CRL_UPDATE_ERROR);
+
+ if (crlError != null)
+ header.addStringValue("updateCRLError", crlError);
+ }
+
+ // let known crl publishing status too.
+ Integer publishCRLResult = unrevReq.getExtDataInInteger(IRequest.CRL_PUBLISH_STATUS);
+
+ if (publishCRLResult != null) {
+ if (publishCRLResult.equals(IRequest.RES_SUCCESS)) {
+ header.addStringValue("publishCRLSuccess", "yes");
+
+ } else {
+ header.addStringValue("publishCRLSuccess", "no");
+ String publError = unrevReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR);
+
+ if (publError != null)
+ header.addStringValue("publishCRLError", publError);
+ }
+ }
+ }
+
+ // let known update and publish status of all crls.
+ Enumeration<ICRLIssuingPoint> otherCRLs = ((ICertificateAuthority) mAuthority).getCRLIssuingPoints();
+
+ while (otherCRLs.hasMoreElements()) {
+ ICRLIssuingPoint crl = otherCRLs.nextElement();
+ String crlId = crl.getId();
+
+ if (crlId.equals(ICertificateAuthority.PROP_MASTER_CRL))
+ continue;
+
+ String updateStatusStr = crl.getCrlUpdateStatusStr();
+ Integer updateResult = unrevReq.getExtDataInInteger(updateStatusStr);
+
+ if (updateResult != null) {
+ if (updateResult.equals(IRequest.RES_SUCCESS)) {
+ CMS.debug("DoUnrevoke: adding header " + updateStatusStr + " yes");
+ header.addStringValue(updateStatusStr, "yes");
+
+ } else {
+ String updateErrorStr = crl.getCrlUpdateErrorStr();
+
+ CMS.debug("DoUnrevoke: adding header " + updateStatusStr + " no");
+ header.addStringValue(updateStatusStr, "no");
+ String error = unrevReq.getExtDataInString(updateErrorStr);
+
+ if (error != null)
+ header.addStringValue(updateErrorStr, error);
+ }
+
+ String publishStatusStr = crl.getCrlPublishStatusStr();
+ Integer publishResult = unrevReq.getExtDataInInteger(publishStatusStr);
+
+ if (publishResult == null)
+ continue;
+
+ if (publishResult.equals(IRequest.RES_SUCCESS)) {
+ header.addStringValue(publishStatusStr, "yes");
+
+ } else {
+ String publishErrorStr = crl.getCrlPublishErrorStr();
+ header.addStringValue(publishStatusStr, "no");
+ String error = unrevReq.getExtDataInString(publishErrorStr);
+
+ if (error != null)
+ header.addStringValue(publishErrorStr, error);
+ }
+ }
+ }
+
+ if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) {
+ header.addStringValue("dirEnabled", "yes");
+ Integer[] ldapPublishStatus = unrevReq.getExtDataInIntegerArray("ldapPublishStatus");
+
+ if (ldapPublishStatus != null) {
+ if (ldapPublishStatus[0] == IRequest.RES_SUCCESS) {
+ header.addStringValue("dirUpdated", "yes");
+ } else {
+ header.addStringValue("dirUpdated", "no");
+ }
+ }
+ } else {
+ header.addStringValue("dirEnabled", "no");
+ }
+
+ } else if (status == RequestStatus.PENDING) {
+ header.addStringValue("error", "Request Pending");
+ header.addStringValue("unrevoked", "pending");
+
+ } else {
+ header.addStringValue("error", "Request Status.Error");
+ header.addStringValue("unrevoked", "no");
+ }
+
+ processor.auditChangeRequestProcessed(ILogger.SUCCESS);
+
+ } catch (EBaseException e) {
+ processor.log(ILogger.LL_FAILURE, "Error " + e);
+ processor.auditChangeRequestProcessed(ILogger.FAILURE);
+ }
+ }
+
+ private BigInteger[] getSerialNumbers(HttpServletRequest req)
+ throws NumberFormatException {
+ String serialNumString = req.getParameter("serialNumber");
+
+ StringTokenizer snList = new StringTokenizer(serialNumString, " ");
+ Vector<BigInteger> biList = new Vector<BigInteger>();
+ while (snList.hasMoreTokens()) {
+ String snStr = snList.nextToken();
+ if (snStr != null) {
+ snStr = snStr.trim();
+ BigInteger bi;
+ if (snStr.startsWith("0x") || snStr.startsWith("0X")) {
+ bi = new BigInteger(snStr.substring(2), 16);
+ } else {
+ bi = new BigInteger(snStr);
+ }
+ if (bi.compareTo(BigInteger.ZERO) < 0) {
+ throw new NumberFormatException();
+ }
+ biList.addElement(bi);
+ } else {
+ throw new NumberFormatException();
+ }
+ }
+ if (biList.size() < 1) {
+ throw new NumberFormatException();
+ }
+
+ BigInteger[] biNumbers = new BigInteger[biList.size()];
+ for (int i = 0; i < biList.size(); i++) {
+ biNumbers[i] = biList.elementAt(i);
+ }
+
+ return biNumbers;
+ }
+
+ /**
+ * Signed Audit Log Requester ID
+ *
+ * This method is called to obtain the "RequesterID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param req HTTP request
+ * @return id string containing the signed audit log message RequesterID
+ */
+ private RequestId auditRequesterID(HttpServletRequest req) {
+ String requesterID = req.getParameter("requestId");
+
+ if (requesterID != null) {
+ return new RequestId(requesterID.trim());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Signed Audit Log Serial Number
+ *
+ * This method is called to obtain the serial number of the certificate
+ * whose status is to be changed for a signed audit log message.
+ * <P>
+ *
+ * @param eeSerialNumber a string containing the un-normalized serialNumber
+ * @return id string containing the signed audit log message RequesterID
+ */
+ private CertId auditSerialNumber(String eeSerialNumber) {
+ if (eeSerialNumber != null) {
+ return new CertId(eeSerialNumber.trim());
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/DoUnrevokeTPS.java b/base/server/cms/src/com/netscape/cms/servlet/cert/DoUnrevokeTPS.java
new file mode 100644
index 000000000..0437a2e0e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/DoUnrevokeTPS.java
@@ -0,0 +1,613 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * 'Unrevoke' a certificate. (For certificates that are on-hold only,
+ * take them off-hold)
+ *
+ * @version $Revision$, $Date$
+ */
+public class DoUnrevokeTPS extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6245049221697655642L;
+
+ @SuppressWarnings("unused")
+ private ICertificateRepository mCertDB;
+
+ private IRequestQueue mQueue = null;
+ private IPublisherProcessor mPublisherProcessor = null;
+ private String errorString = "error=";
+ private String o_status = "status=0";
+
+ private final static String OFF_HOLD = "off-hold";
+ private final static int OFF_HOLD_REASON = 6;
+ private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST =
+ "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_5";
+ private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED =
+ "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED_7";
+
+ public DoUnrevokeTPS() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ if (mAuthority instanceof ICertificateAuthority) {
+ mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository();
+ }
+ if (mAuthority instanceof ICertAuthority) {
+ mPublisherProcessor = ((ICertAuthority) mAuthority).getPublisherProcessor();
+ }
+ mQueue = mAuthority.getRequestQueue();
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ mRenderResult = false;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param serialNumber Decimal serial number of certificate to unrevoke. The certificate must be revoked
+ * with a revovcation reason 'on hold' for this operation to succeed. The serial number may be expressed as a hex
+ * number by prefixing '0x' to the serialNumber string
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ BigInteger[] serialNumbers;
+ EBaseException error = null;
+
+ Locale[] locale = new Locale[1];
+
+ /*
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ */
+
+ try {
+ serialNumbers = getSerialNumbers(req);
+
+ //for audit log.
+ IAuthToken authToken = authenticate(cmsReq);
+ String authMgr = AuditFormat.NOAUTH;
+
+ if (authToken != null) {
+ authMgr =
+ authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ } else {
+ CMS.debug("DoUnrevokeTPS::process() - authToken is null!");
+ return;
+ }
+ String agentID = authToken.getInString("userid");
+ String initiative = AuditFormat.FROMAGENT + " agentID: " + agentID
+ + " authenticated by " + authMgr;
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "unrevoke");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ o_status = "status=3";
+ errorString = "error=unauthorized";
+ String pp = o_status + "\n" + errorString;
+ byte[] b = pp.getBytes();
+ resp.setContentType("text/html");
+ resp.setContentLength(b.length);
+ OutputStream os = resp.getOutputStream();
+ os.write(b);
+ os.flush();
+ return;
+ }
+
+ process(serialNumbers, req, resp, locale[0], initiative);
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_SERIAL_NUM_FORMAT"));
+ error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT"));
+ } catch (EBaseException e) {
+ error = e;
+ } catch (IOException e) {
+ }
+
+ try {
+ if (error == null) {
+ o_status = "status=0";
+ errorString = "error=";
+ } else {
+ o_status = "status=3";
+ errorString = "error=" + error.toString();
+ }
+
+ String pp = o_status + "\n" + errorString;
+ byte[] b = pp.getBytes();
+ resp.setContentType("text/html");
+ resp.setContentLength(b.length);
+ OutputStream os = resp.getOutputStream();
+ os.write(b);
+ os.flush();
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ /**
+ * Process X509 cert status change request
+ * <P>
+ *
+ * (Certificate Request - an "agent" cert status change request to take a certificate off-hold)
+ * <P>
+ *
+ * (Certificate Request Processed - an "agent" cert status change request to take a certificate off-hold)
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST used when a cert status change request (e. g. -
+ * "revocation") is made (before approval process)
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED used when a certificate status is
+ * changed (taken off-hold)
+ * </ul>
+ *
+ * @param serialNumbers the serial number of the certificate
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param locale the system locale
+ * @param initiative string containing the audit format
+ * @exception EBaseException an error has occurred
+ */
+ private void process(BigInteger[] serialNumbers,
+ HttpServletRequest req,
+ HttpServletResponse resp,
+ Locale locale, String initiative)
+ throws EBaseException {
+ boolean auditRequest = true;
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRequesterID = auditRequesterID(req);
+ String auditSerialNumber = auditSerialNumber(serialNumbers[0].toString());
+ String auditRequestType = OFF_HOLD;
+ RequestStatus auditApprovalStatus = null;
+ String auditReasonNum = String.valueOf(OFF_HOLD_REASON);
+
+ try {
+ String snList = "";
+
+ // certs are for old cloning and they should be removed as soon as possible
+ X509CertImpl[] certs = new X509CertImpl[serialNumbers.length];
+ for (int i = 0; i < serialNumbers.length; i++) {
+ certs[i] = (X509CertImpl) getX509Certificate(serialNumbers[i]);
+ if (snList.length() > 0)
+ snList += ", ";
+ snList += "0x" + serialNumbers[i].toString(16);
+ }
+
+ IRequest unrevReq = mQueue.newRequest(IRequest.UNREVOCATION_REQUEST);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType);
+
+ audit(auditMessage);
+
+ unrevReq.setExtData(IRequest.REQ_TYPE, IRequest.UNREVOCATION_REQUEST);
+ unrevReq.setExtData(IRequest.OLD_SERIALS, serialNumbers);
+ unrevReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_AGENT);
+
+ // change audit processing from "REQUEST" to "REQUEST_PROCESSED"
+ // to distinguish which type of signed audit log message to save
+ // as a failure outcome in case an exception occurs
+ auditRequest = false;
+
+ mQueue.processRequest(unrevReq);
+
+ // retrieve the request status
+ auditApprovalStatus = unrevReq.getRequestStatus();
+
+ RequestStatus status = unrevReq.getRequestStatus();
+ String type = unrevReq.getRequestType();
+
+ if ((status == RequestStatus.COMPLETE)
+ || ((type.equals(IRequest.CLA_UNCERT4CRL_REQUEST)) && (status == RequestStatus.SVC_PENDING))) {
+
+ Integer result = unrevReq.getExtDataInInteger(IRequest.RESULT);
+
+ if (result != null && result.equals(IRequest.RES_SUCCESS)) {
+ if (certs[0] != null) {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOUNREVOKEFORMAT,
+ new Object[] {
+ unrevReq.getRequestId(),
+ initiative,
+ "completed",
+ certs[0].getSubjectDN(),
+ "0x" + serialNumbers[0].toString(16) }
+ );
+ }
+ } else {
+ String error = unrevReq.getExtDataInString(IRequest.ERROR);
+
+ if (error != null) {
+ o_status = "status=3";
+ errorString = "error=" + error;
+ if (certs[0] != null) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOUNREVOKEFORMAT,
+ new Object[] {
+ unrevReq.getRequestId(),
+ initiative,
+ "completed with error: " +
+ error,
+ certs[0].getSubjectDN(),
+ "0x" + serialNumbers[0].toString(16) }
+ );
+ }
+ }
+ }
+
+ Integer updateCRLResult =
+ unrevReq.getExtDataInInteger(IRequest.CRL_UPDATE_STATUS);
+
+ if (updateCRLResult != null) {
+ if (!updateCRLResult.equals(IRequest.RES_SUCCESS)) {
+ String crlError =
+ unrevReq.getExtDataInString(IRequest.CRL_UPDATE_ERROR);
+
+ if (crlError != null) {
+ o_status = "status=3";
+ errorString = "error=" + crlError;
+ }
+ }
+ // let known crl publishing status too.
+ Integer publishCRLResult =
+ unrevReq.getExtDataInInteger(IRequest.CRL_PUBLISH_STATUS);
+
+ if (publishCRLResult != null) {
+ if (!publishCRLResult.equals(IRequest.RES_SUCCESS)) {
+ String publError =
+ unrevReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR);
+
+ if (publError != null) {
+ o_status = "status=3";
+ errorString = "error=" + publError;
+ }
+ }
+ }
+ }
+
+ // let known update and publish status of all crls.
+ Enumeration<ICRLIssuingPoint> otherCRLs =
+ ((ICertificateAuthority) mAuthority).getCRLIssuingPoints();
+
+ while (otherCRLs.hasMoreElements()) {
+ ICRLIssuingPoint crl = otherCRLs.nextElement();
+ String crlId = crl.getId();
+
+ if (crlId.equals(ICertificateAuthority.PROP_MASTER_CRL))
+ continue;
+ String updateStatusStr = crl.getCrlUpdateStatusStr();
+ Integer updateResult = unrevReq.getExtDataInInteger(updateStatusStr);
+
+ if (updateResult != null) {
+ if (!updateResult.equals(IRequest.RES_SUCCESS)) {
+ String updateErrorStr = crl.getCrlUpdateErrorStr();
+ String error =
+ unrevReq.getExtDataInString(updateErrorStr);
+
+ if (error != null) {
+ o_status = "status=3";
+ errorString = "error=" + error;
+ }
+ }
+ String publishStatusStr = crl.getCrlPublishStatusStr();
+ Integer publishResult =
+ unrevReq.getExtDataInInteger(publishStatusStr);
+
+ if (publishResult == null)
+ continue;
+ if (!publishResult.equals(IRequest.RES_SUCCESS)) {
+ String publishErrorStr =
+ crl.getCrlPublishErrorStr();
+
+ String error =
+ unrevReq.getExtDataInString(publishErrorStr);
+
+ if (error != null) {
+ o_status = "status=3";
+ errorString = "error=" + error;
+ }
+ }
+ }
+ }
+
+ if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) {
+ Integer[] ldapPublishStatus =
+ unrevReq.getExtDataInIntegerArray("ldapPublishStatus");
+
+ if (ldapPublishStatus != null) {
+ if (ldapPublishStatus[0] != IRequest.RES_SUCCESS) {
+ o_status = "status=3";
+ errorString = "error=Problem in publishing to LDAP";
+ }
+ }
+ } else if (mPublisherProcessor == null || (!mPublisherProcessor.ldapEnabled())) {
+ o_status = "status=3";
+ errorString = "error=LDAP Publisher not enabled";
+ }
+
+ } else if (status == RequestStatus.PENDING) {
+ o_status = "status=2";
+ errorString = "error=" + status.toString();
+ if (certs[0] != null) {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOUNREVOKEFORMAT,
+ new Object[] {
+ unrevReq.getRequestId(),
+ initiative,
+ "pending",
+ certs[0].getSubjectDN(),
+ "0x" + serialNumbers[0].toString(16) }
+ );
+ }
+ } else {
+ o_status = "status=2";
+ errorString = "error=Undefined request status";
+
+ if (certs[0] != null) {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOUNREVOKEFORMAT,
+ new Object[] {
+ unrevReq.getRequestId(),
+ initiative,
+ status.toString(),
+ certs[0].getSubjectDN(),
+ "0x" + serialNumbers[0].toString(16) }
+ );
+ }
+ }
+
+ // store a message in the signed audit log file
+ // if and only if "auditApprovalStatus" is
+ // "complete", "revoked", or "canceled"
+ if (auditApprovalStatus == RequestStatus.COMPLETE ||
+ auditApprovalStatus == RequestStatus.REJECTED ||
+ auditApprovalStatus == RequestStatus.CANCELED) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus == null ? ILogger.SIGNED_AUDIT_EMPTY_VALUE : auditApprovalStatus.toString());
+
+ audit(auditMessage);
+ }
+
+ } catch (EBaseException eAudit1) {
+ if (auditRequest) {
+ // store a "CERT_STATUS_CHANGE_REQUEST" failure
+ // message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType);
+
+ audit(auditMessage);
+ } else {
+ // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure
+ // message in the signed audit log file
+ // if and only if "auditApprovalStatus" is
+ // "complete", "revoked", or "canceled"
+ if (auditApprovalStatus == RequestStatus.COMPLETE ||
+ auditApprovalStatus == RequestStatus.REJECTED ||
+ auditApprovalStatus == RequestStatus.CANCELED) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus == null ? ILogger.SIGNED_AUDIT_EMPTY_VALUE : auditApprovalStatus.toString());
+
+ audit(auditMessage);
+ }
+ }
+ }
+
+ return;
+ }
+
+ private BigInteger[] getSerialNumbers(HttpServletRequest req)
+ throws NumberFormatException {
+ String serialNumString = req.getParameter("serialNumber");
+
+ StringTokenizer snList = new StringTokenizer(serialNumString, " ");
+ Vector<BigInteger> biList = new Vector<BigInteger>();
+ while (snList.hasMoreTokens()) {
+ String snStr = snList.nextToken();
+ if (snStr != null) {
+ snStr = snStr.trim();
+ BigInteger bi;
+ if (snStr.startsWith("0x") || snStr.startsWith("0X")) {
+ bi = new BigInteger(snStr.substring(2), 16);
+ } else {
+ bi = new BigInteger(snStr);
+ }
+ if (bi.compareTo(BigInteger.ZERO) < 0) {
+ throw new NumberFormatException();
+ }
+ biList.addElement(bi);
+ } else {
+ throw new NumberFormatException();
+ }
+ }
+ if (biList.size() < 1) {
+ throw new NumberFormatException();
+ }
+
+ BigInteger[] biNumbers = new BigInteger[biList.size()];
+ for (int i = 0; i < biList.size(); i++) {
+ biNumbers[i] = biList.elementAt(i);
+ }
+
+ return biNumbers;
+ }
+
+ /**
+ * Signed Audit Log Requester ID
+ *
+ * This method is called to obtain the "RequesterID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param req HTTP request
+ * @return id string containing the signed audit log message RequesterID
+ */
+ private String auditRequesterID(HttpServletRequest req) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String requesterID = null;
+
+ // Obtain the requesterID
+ requesterID = req.getParameter("requestId");
+
+ if (requesterID != null) {
+ requesterID = requesterID.trim();
+ } else {
+ requesterID = ILogger.UNIDENTIFIED;
+ }
+
+ return requesterID;
+ }
+
+ /**
+ * Signed Audit Log Serial Number
+ *
+ * This method is called to obtain the serial number of the certificate
+ * whose status is to be changed for a signed audit log message.
+ * <P>
+ *
+ * @param eeSerialNumber a string containing the un-normalized serialNumber
+ * @return id string containing the signed audit log message RequesterID
+ */
+ private String auditSerialNumber(String eeSerialNumber) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String serialNumber = null;
+
+ // Normalize the serialNumber
+ if (eeSerialNumber != null) {
+ serialNumber = eeSerialNumber.trim();
+
+ // convert it to hexadecimal
+ serialNumber = "0x" + (new BigInteger(serialNumber)).toString(16);
+ } else {
+ serialNumber = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ return serialNumber;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/EnableEnrollResult.java b/base/server/cms/src/com/netscape/cms/servlet/cert/EnableEnrollResult.java
new file mode 100644
index 000000000..4904ec9b7
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/EnableEnrollResult.java
@@ -0,0 +1,185 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+import java.util.Random;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.cms.authentication.HashAuthentication;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * For Face-to-face enrollment, enable EE enrollment feature
+ *
+ * @version $Revision$, $Date$
+ * @see com.netscape.cms.servlet.cert.DisableEnrollResult
+ */
+public class EnableEnrollResult extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2646998784859783012L;
+ private final static String TPL_FILE = "enableEnrollResult.template";
+ private String mFormPath = null;
+ private Random random = null;
+
+ public EnableEnrollResult() {
+ super();
+ }
+
+ /**
+ * Initializes the servlet.
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success to display own output.
+
+ // coming from agent
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ random = new Random();
+ }
+
+ protected CMSRequest newCMSRequest() {
+ return new CMSRequest();
+ }
+
+ /**
+ * Services the request
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "enable");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ X509Certificate sslClientCert = null;
+
+ sslClientCert = getSSLClientCertificate(httpReq);
+ String dn = sslClientCert.getSubjectDN().toString();
+
+ // Construct an ArgBlock
+ IArgBlock args = cmsReq.getHttpParams();
+
+ if (!(mAuthority instanceof IRegistrationAuthority)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CA_FROM_RA_NOT_IMP"));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_NOT_YET_IMPLEMENTED")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, httpReq, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String machine = configStore.getString("machineName");
+ String port = CMS.getEESSLPort();
+
+ header.addStringValue("machineName", machine);
+ header.addStringValue("port", port);
+ String val = configStore.getString("hashDirEnrollment.name");
+ IAuthSubsystem authSS = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ IAuthManager authMgr = authSS.get(val);
+ HashAuthentication mgr = (HashAuthentication) authMgr;
+
+ String host = args.getValueAsString("hostname", null);
+ boolean isEnable = mgr.isEnable(host);
+
+ if (isEnable) {
+ header.addStringValue("code", "1");
+ } else {
+ String timeout = args.getValueAsString("timeout", "600");
+
+ mgr.createEntry(host, dn, Long.parseLong(timeout) * 1000,
+ random.nextLong() + "", 0);
+ header.addStringValue("code", "0");
+ }
+
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java
new file mode 100644
index 000000000..16e2ab840
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java
@@ -0,0 +1,1767 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.pkcs.PKCS10;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.KeyGenInfo;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertRecordList;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSGateway;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+import com.netscape.cms.servlet.processors.CMCProcessor;
+import com.netscape.cms.servlet.processors.CRMFProcessor;
+import com.netscape.cms.servlet.processors.KeyGenProcessor;
+import com.netscape.cms.servlet.processors.PKCS10Processor;
+import com.netscape.cms.servlet.processors.PKIProcessor;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Submit a Certificate Enrollment request
+ *
+ * @version $Revision$, $Date$
+ */
+public class EnrollServlet extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6983729702665630013L;
+
+ public final static String ADMIN_ENROLL_SERVLET_ID = "caadminEnroll";
+
+ // enrollment templates.
+ public static final String ENROLL_SUCCESS_TEMPLATE = "EnrollSuccess.template";
+
+ // http params
+ public static final String OLD_CERT_TYPE = "csrCertType";
+ public static final String CERT_TYPE = "certType";
+ // same as in ConfigConstant.java
+ public static final String REQUEST_FORMAT = "reqFormat";
+ public static final String REQUEST_FORMAT_PKCS10 = "PKCS10";
+ public static final String REQUEST_FORMAT_CMC = "CMC";
+ public static final String REQUEST_CONTENT = "requestContent";
+ public static final String SUBJECT_KEYGEN_INFO = "subjectKeyGenInfo";
+ public static final String PKCS10_REQUEST = "pkcs10Request";
+ public static final String CMC_REQUEST = "cmcRequest";
+ public static final String CRMF_REQUEST = "CRMFRequest";
+ public static final String SUBJECT_NAME = "subject";
+ public static final String CRMF_REQID = "crmfReqId";
+ public static final String CHALLENGE_PASSWORD = "challengePhrase";
+
+ private static final String CERT_AUTH_DUAL = "dual";
+ private static final String CERT_AUTH_ENCRYPTION = "encryption";
+ private static final String CERT_AUTH_SINGLE = "single";
+ private static final String CLIENT_ISSUER = "clientIssuer";
+
+ private String mEnrollSuccessTemplate = null;
+ private ICMSTemplateFiller mEnrollSuccessFiller = new ImportCertsTemplateFiller();
+
+ ICertificateAuthority mCa = null;
+ ICertificateRepository mRepository = null;
+
+ private boolean enforcePop = false;
+
+ private String auditServiceID = ILogger.UNIDENTIFIED;
+ private final static String ADMIN_CA_ENROLLMENT_SERVLET =
+ "caadminEnroll";
+ private final static String AGENT_CA_BULK_ENROLLMENT_SERVLET =
+ "cabulkissuance";
+ private final static String AGENT_RA_BULK_ENROLLMENT_SERVLET =
+ "rabulkissuance";
+ private final static String EE_CA_CERT_BASED_ENROLLMENT_SERVLET =
+ "cacertbasedenrollment";
+ private final static String EE_CA_ENROLLMENT_SERVLET =
+ "caenrollment";
+ private final static String EE_RA_CERT_BASED_ENROLLMENT_SERVLET =
+ "racertbasedenrollment";
+ private final static String EE_RA_ENROLLMENT_SERVLET =
+ "raenrollment";
+ private final static byte EOL[] = { Character.LINE_SEPARATOR };
+ private final static String[] SIGNED_AUDIT_AUTOMATED_REJECTION_REASON = new String[] {
+
+ /* 0 */"automated non-profile cert request rejection: "
+ + "unable to render OLD_CERT_TYPE response",
+
+ /* 1 */"automated non-profile cert request rejection: "
+ + "unable to complete handleEnrollAuditLog() method",
+
+ /* 2 */"automated non-profile cert request rejection: "
+ + "unable to render success template",
+
+ /* 3 */"automated non-profile cert request rejection: "
+ + "indeterminate reason for inability to process "
+ + "cert request due to an EBaseException"
+ };
+ private final static String LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST =
+ "LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST_5";
+ private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED =
+ "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5";
+
+ private static final String HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----";
+ private static final String TRAILER = "-----END NEW CERTIFICATE REQUEST-----";
+
+ public EnrollServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ * <p>
+ * the following parameters are read from the servlet config:
+ * <ul>
+ * <li>CMSServlet.PROP_ID - ID for signed audit log messages
+ * <li>CMSServlet.PROP_SUCCESS_TEMPLATE - success template file
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ try {
+ super.init(sc);
+
+ CMS.debug("EnrollServlet: In Enroll Servlet init!");
+
+ try {
+ IConfigStore configStore = CMS.getConfigStore();
+ String PKI_Subsystem = configStore.getString("subsystem.0.id",
+ null);
+
+ // CMS 6.1 began utilizing the "Certificate Profiles" framework
+ // instead of the legacy "Certificate Policies" framework.
+ //
+ // Beginning with CS 8.1, to meet the Common Criteria
+ // evaluation performed on this version of the product, it
+ // was determined that this legacy "Certificate Policies"
+ // framework would be deprecated and disabled by default
+ // (see Bugzilla Bug #472597).
+ //
+ // NOTE: The "Certificate Policies" framework ONLY applied to
+ // to CA, KRA, and legacy RA (pre-CMS 7.0) subsystems.
+ //
+ // Further, the "EnrollServlet.java" servlet is ONLY
+ // used by the CA for the following:
+ //
+ // SERVLET-NAME URL-PATTERN
+ // ====================================================
+ // caadminEnroll ca/admin/ca/adminEnroll.html
+ // cabulkissuance ca/agent/ca/bulkissuance.html
+ // cacertbasedenrollment ca/certbasedenrollment.html
+ // caenrollment ca/enrollment.html
+ //
+ // The "EnrollServlet.java" servlet is NOT used by
+ // the KRA.
+ //
+ if (PKI_Subsystem.trim().equalsIgnoreCase("ca")) {
+ String policyStatus = PKI_Subsystem.trim().toLowerCase()
+ + "." + "Policy"
+ + "." + IPolicyProcessor.PROP_ENABLE;
+
+ if (configStore.getBoolean(policyStatus, true) == true) {
+ // NOTE: If "<subsystem>.Policy.enable=<boolean>"
+ // is missing, then the referenced instance
+ // existed prior to this name=value pair
+ // existing in its 'CS.cfg' file, and thus
+ // we err on the side that the user may
+ // still need to use the policy framework.
+ CMS.debug("EnrollServlet::init Certificate "
+ + "Policy Framework (deprecated) "
+ + "is ENABLED");
+ } else {
+ // CS 8.1 Default: <subsystem>.Policy.enable=false
+ CMS.debug("EnrollServlet::init Certificate "
+ + "Policy Framework (deprecated) "
+ + "is DISABLED");
+ return;
+ }
+ }
+ } catch (EBaseException e) {
+ throw new ServletException("EnrollServlet::init - "
+ + "EBaseException: "
+ + "Unable to initialize "
+ + "Certificate Policy Framework "
+ + "(deprecated)");
+ }
+
+ // override success template to allow direct import of keygen certs.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+
+ try {
+ // determine the service ID for signed audit log messages
+ String id = sc.getInitParameter(CMSServlet.PROP_ID);
+
+ if (id != null) {
+ if (!(auditServiceID.equals(
+ ADMIN_CA_ENROLLMENT_SERVLET))
+ && !(auditServiceID.equals(
+ AGENT_CA_BULK_ENROLLMENT_SERVLET))
+ && !(auditServiceID.equals(
+ AGENT_RA_BULK_ENROLLMENT_SERVLET))
+ && !(auditServiceID.equals(
+ EE_CA_CERT_BASED_ENROLLMENT_SERVLET))
+ && !(auditServiceID.equals(
+ EE_CA_ENROLLMENT_SERVLET))
+ && !(auditServiceID.equals(
+ EE_RA_CERT_BASED_ENROLLMENT_SERVLET))
+ && !(auditServiceID.equals(
+ EE_RA_ENROLLMENT_SERVLET))) {
+ auditServiceID = ILogger.UNIDENTIFIED;
+ } else {
+ auditServiceID = id.trim();
+ }
+ }
+
+ mEnrollSuccessTemplate = sc.getInitParameter(
+ CMSServlet.PROP_SUCCESS_TEMPLATE);
+ if (mEnrollSuccessTemplate == null)
+ mEnrollSuccessTemplate = ENROLL_SUCCESS_TEMPLATE;
+ String fillername = sc.getInitParameter(
+ PROP_SUCCESS_TEMPLATE_FILLER);
+
+ if (fillername != null) {
+ ICMSTemplateFiller filler = newFillerObject(fillername);
+
+ if (filler != null)
+ mEnrollSuccessFiller = filler;
+ }
+
+ // cfu
+ mCa = (ICertificateAuthority) CMS.getSubsystem("ca");
+
+ init_testbed_hack(mConfig);
+ } catch (Exception e) {
+ // this should never happen.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_IMP_INIT_SERV_ERR",
+ e.toString(), mId));
+ }
+ } catch (ServletException eAudit1) {
+ // rethrow caught exception
+ throw eAudit1;
+ }
+ }
+
+ /**
+ * XXX (SHOULD CHANGE TO READ FROM Servletconfig)
+ * Getter method to see if Proof of Posession checking is enabled.
+ * this value is set in the CMS.cfg filem with the parameter
+ * "enrollment.enforcePop". It defaults to false
+ *
+ * @return true if user is required to Prove that they possess the
+ * private key corresponding to the public key in the certificate
+ * request they are submitting
+ */
+ public boolean getEnforcePop() {
+ return enforcePop;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <UL>
+ * <LI>If the request is coming through the admin port, it is only allowed to continue if 'admin enrollment' is
+ * enabled in the CMS.cfg file
+ * <LI>If the CMS.cfg parameter useThreadNaming is true, the current thread is renamed with more information about
+ * the current request ID
+ * <LI>The request is preprocessed, then processed further in one of the cert request processor classes:
+ * KeyGenProcessor, PKCS10Processor, CMCProcessor, CRMFProcessor
+ * </UL>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ // SPECIAL CASE:
+ // if it is adminEnroll servlet,check if it's enabled
+ if (mId.equals(ADMIN_ENROLL_SERVLET_ID) &&
+ !CMSGateway.getEnableAdminEnroll()) {
+ log(ILogger.LL_SECURITY,
+ CMS.getLogMessage("ADMIN_SRVLT_ENROLL_ACCESS_AFTER_SETUP"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_REDIRECTING_ADMINENROLL_ERROR",
+ "Attempt to access adminEnroll after already setup."));
+ }
+
+ processX509(cmsReq);
+ }
+
+ private boolean getCertAuthEnrollStatus(IArgBlock httpParams) {
+
+ /*
+ * === certAuth based enroll ===
+ * "certAuthEnroll" is on.
+ * "certauthEnrollType can be one of the three:
+ * single - it's for single cert enrollment
+ * dual - it's for dual certs enrollment
+ * encryption - getting the encryption cert only via
+ * authentication of the signing cert
+ * (crmf or keyGenInfo)
+ */
+ boolean certAuthEnroll = false;
+
+ String certAuthEnrollOn =
+ httpParams.getValueAsString("certauthEnroll", null);
+
+ if ((certAuthEnrollOn != null) && (certAuthEnrollOn.equals("on"))) {
+ certAuthEnroll = true;
+ CMS.debug("EnrollServlet: certAuthEnroll is on");
+ }
+
+ return certAuthEnroll;
+
+ }
+
+ private String getCertAuthEnrollType(IArgBlock httpParams, boolean certAuthEnroll)
+ throws EBaseException {
+
+ String certauthEnrollType = null;
+
+ if (certAuthEnroll == true) {
+ certauthEnrollType =
+ httpParams.getValueAsString("certauthEnrollType", null);
+ if (certauthEnrollType != null) {
+ if (certauthEnrollType.equals("dual")) {
+ CMS.debug("EnrollServlet: certauthEnrollType is dual");
+ } else if (certauthEnrollType.equals("encryption")) {
+ CMS.debug("EnrollServlet: certauthEnrollType is encryption");
+ } else if (certauthEnrollType.equals("single")) {
+ CMS.debug("EnrollServlet: certauthEnrollType is single");
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_INVALID_CERTAUTH_ENROLL_TYPE_1", certauthEnrollType));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_CERTAUTH_ENROLL_TYPE"));
+ }
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("MSGW_MISSING_CERTAUTH_ENROLL_TYPE"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_CERTAUTH_ENROLL_TYPE"));
+ }
+ }
+
+ return certauthEnrollType;
+
+ }
+
+ private boolean checkClientCertSigningOnly(X509Certificate sslClientCert)
+ throws EBaseException {
+ if ((CMS.isSigningCert(sslClientCert) ==
+ false) ||
+ ((CMS.isSigningCert(sslClientCert) ==
+ true) &&
+ (CMS.isEncryptionCert(sslClientCert) ==
+ true))) {
+
+ // either it's not a signing cert, or it's a dual cert
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_INVALID_CERT_TYPE"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_CERT_TYPE"));
+ }
+
+ return true;
+ }
+
+ private X509CertInfo[] handleCertAuthDual(X509CertInfo certInfo, IAuthToken authToken,
+ X509Certificate sslClientCert,
+ ICertificateAuthority mCa, String certBasedOldSubjectDN,
+ BigInteger certBasedOldSerialNum)
+ throws EBaseException {
+
+ CMS.debug("EnrollServlet: In handleCertAuthDual!");
+
+ if (mCa == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_NOT_A_CA"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_NOT_A_CA"));
+ }
+
+ // first, make sure the client cert is indeed a
+ // signing only cert
+
+ try {
+
+ checkClientCertSigningOnly(sslClientCert);
+ } catch (ECMSGWException e) {
+
+ throw new ECMSGWException(e.toString());
+
+ }
+
+ X509Key key = null;
+
+ // for signing cert
+ key = (X509Key) sslClientCert.getPublicKey();
+ try {
+ certInfo.set(X509CertInfo.KEY, new CertificateX509Key(key));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_IO", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString()));
+ }
+
+ String filter =
+ "(&(x509cert.subject="
+ + certBasedOldSubjectDN + ")(!(x509cert.serialNumber=" + certBasedOldSerialNum
+ + "))(certStatus=VALID))";
+ ICertRecordList list =
+ mCa.getCertificateRepository().findCertRecordsInList(filter, null, 10);
+ int size = list.getSize();
+ Enumeration<ICertRecord> en = list.getCertRecords(0, size - 1);
+
+ CMS.debug("EnrollServlet: signing cert filter " + filter);
+
+ if (!en.hasMoreElements()) {
+ CMS.debug("EnrollServlet: pairing encryption cert not found!");
+ return null;
+ // pairing encryption cert not found
+ } else {
+ X509CertInfo encCertInfo = CMS.getDefaultX509CertInfo();
+ X509CertInfo[] cInfoArray = new X509CertInfo[] { certInfo,
+ encCertInfo };
+ int i = 1;
+
+ boolean encCertFound = false;
+
+ while (en.hasMoreElements()) {
+ ICertRecord record = en.nextElement();
+ X509CertImpl cert = record.getCertificate();
+
+ // if not encryption cert only, try next one
+ if ((CMS.isEncryptionCert(cert) == false) ||
+ ((CMS.isEncryptionCert(cert) == true) &&
+ (CMS.isSigningCert(cert) == true))) {
+
+ CMS.debug("EnrollServlet: Not encryption only cert, will try next one.");
+ continue;
+ }
+
+ key = (X509Key) cert.getPublicKey();
+ CMS.debug("EnrollServlet: Found key for encryption cert.");
+ encCertFound = true;
+
+ try {
+ encCertInfo = (X509CertInfo)
+ cert.get(
+ X509CertImpl.NAME + "." + X509CertImpl.INFO);
+
+ } catch (CertificateParsingException ex) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_CERTINFO_ENCRYPT_CERT"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_CERTINFO"));
+ }
+
+ try {
+ encCertInfo.set(X509CertInfo.KEY, new CertificateX509Key(key));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString()));
+ }
+
+ CMS.debug("EnrollServlet: About to fillCertInfoFromAuthToken!");
+ PKIProcessor.fillCertInfoFromAuthToken(encCertInfo, authToken);
+
+ cInfoArray[i++] = encCertInfo;
+ break;
+
+ }
+ if (encCertFound == false) {
+ CMS.debug("EnrollServlet: Leaving because Enc Cert not found.");
+ return null;
+ }
+
+ CMS.debug("EnrollServlet: returning cInfoArray of length " + cInfoArray.length);
+ return cInfoArray;
+ }
+
+ }
+
+ private boolean handleEnrollAuditLog(IRequest req, CMSRequest cmsReq, String authMgr, IAuthToken authToken,
+ X509CertInfo certInfo, long startTime)
+ throws EBaseException {
+ //for audit log
+
+ String initiative = null;
+ String agentID = null;
+
+ if (authToken == null) {
+ // request is from eegateway, so fromUser.
+ initiative = AuditFormat.FROMUSER;
+ } else {
+ agentID = authToken.getInString("userid");
+ initiative = AuditFormat.FROMAGENT + " agentID: " + agentID;
+ }
+
+ // if service not complete return standard templates.
+ RequestStatus status = req.getRequestStatus();
+
+ if (status != RequestStatus.COMPLETE) {
+ cmsReq.setIRequestStatus(); // set status acc. to IRequest status.
+ // audit log the status
+ try {
+ if (status == RequestStatus.REJECTED) {
+ Vector<String> messages = req.getExtDataInStringVector(IRequest.ERRORS);
+
+ if (messages != null) {
+ Enumeration<String> msgs = messages.elements();
+ StringBuffer wholeMsg = new StringBuffer();
+
+ while (msgs.hasMoreElements()) {
+ wholeMsg.append("\n");
+ wholeMsg.append(msgs.nextElement());
+ }
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.ENROLLMENTFORMAT,
+ new Object[] {
+ req.getRequestId(),
+ initiative,
+ authMgr,
+ status.toString(),
+ certInfo.get(X509CertInfo.SUBJECT),
+ " violation: " +
+ wholeMsg.toString() }
+ );
+ } else { // no policy violation, from agent
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.ENROLLMENTFORMAT,
+ new Object[] {
+ req.getRequestId(),
+ initiative,
+ authMgr,
+ status.toString(),
+ certInfo.get(X509CertInfo.SUBJECT), "" }
+ );
+ }
+ } else { // other imcomplete status
+ long endTime = CMS.getCurrentDate().getTime();
+
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.ENROLLMENTFORMAT,
+ new Object[] {
+ req.getRequestId(),
+ initiative,
+ authMgr,
+ status.toString(),
+ certInfo.get(X509CertInfo.SUBJECT) + " time: " + (endTime - startTime), "" }
+ );
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING",
+ e.toString()));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING",
+ e.toString()));
+ }
+ return false;
+ }
+ // if service error use standard error templates.
+ Integer result = req.getExtDataInInteger(IRequest.RESULT);
+
+ if (result.equals(IRequest.RES_ERROR)) {
+
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(req.getExtDataInString(IRequest.ERROR));
+ String[] svcErrors =
+ req.getExtDataInStringArray(IRequest.SVCERRORS);
+
+ if (svcErrors != null && svcErrors.length > 0) {
+ for (int i = 0; i < svcErrors.length; i++) {
+ String err = svcErrors[i];
+
+ if (err != null) {
+ //System.out.println(
+ //"revocation servlet: setting error description "+
+ //err.toString());
+ cmsReq.setErrorDescription(err);
+ // audit log the error
+ try {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.ENROLLMENTFORMAT,
+ new Object[] {
+ req.getRequestId(),
+ initiative,
+ authMgr,
+ "completed with error: " +
+ err,
+ certInfo.get(X509CertInfo.SUBJECT), ""
+ }
+ );
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING",
+ e.toString()));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING",
+ e.toString()));
+ }
+
+ }
+ }
+ }
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+ /**
+ * Process X509 certificate enrollment request
+ * <P>
+ *
+ * (Certificate Request - either an "admin" cert request for an admin certificate, an "agent" cert request for
+ * "bulk enrollment", or an "EE" standard cert request)
+ * <P>
+ *
+ * (Certificate Request Processed - either an automated "admin" non-profile based CA admin cert acceptance, an
+ * automated "admin" non-profile based CA admin cert rejection, an automated "EE" non-profile based cert acceptance,
+ * or an automated "EE" non-profile based cert rejection)
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST used when a non-profile cert request is made
+ * (before approval process)
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been
+ * through the approval process
+ * </ul>
+ *
+ * @param cmsReq a certificate enrollment request
+ * @exception EBaseException an error has occurred
+ */
+ protected void processX509(CMSRequest cmsReq)
+ throws EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRequesterID = ILogger.UNIDENTIFIED;
+ String auditCertificateSubjectName = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ String id = null;
+
+ // define variables common to try-catch-blocks
+ long startTime = 0;
+ IArgBlock httpParams = null;
+ HttpServletRequest httpReq = null;
+ IAuthToken authToken = null;
+ AuthzToken authzToken = null;
+ IRequest req = null;
+ X509CertInfo certInfo = null;
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ /* XXX shouldn't we read this from ServletConfig at init time? */
+ enforcePop = configStore.getBoolean("enrollment.enforcePop", false);
+ CMS.debug("EnrollServlet: enforcePop " + enforcePop);
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ startTime = CMS.getCurrentDate().getTime();
+ httpParams = cmsReq.getHttpParams();
+ httpReq = cmsReq.getHttpReq();
+ if (mAuthMgr != null) {
+ authToken = authenticate(cmsReq);
+ }
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "submit");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+
+ // store a message in the signed audit log file
+ // (either an "admin" cert request for an admin certificate,
+ // an "agent" cert request for "bulk enrollment", or
+ // an "EE" standard cert request)
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+
+ return;
+ }
+
+ // create enrollment request in request queue.
+ req = mRequestQueue.newRequest(IRequest.ENROLLMENT_REQUEST);
+
+ // retrieve the actual "auditRequesterID"
+ if (req != null) {
+ // overwrite "auditRequesterID" if and only if "id" != null
+ id = req.getRequestId().toString();
+ if (id != null) {
+ auditRequesterID = id.trim();
+ }
+ }
+
+ try {
+ if (CMS.getConfigStore().getBoolean("useThreadNaming", false)) {
+ String currentName = Thread.currentThread().getName();
+
+ Thread.currentThread().setName(currentName
+ + "-request-"
+ + req.getRequestId().toString()
+ + "-"
+ + (new Date()).getTime());
+ }
+ } catch (Exception e) {
+ }
+
+ /*
+ * === certAuth based enroll ===
+ * "certAuthEnroll" is on.
+ * "certauthEnrollType can be one of the three:
+ * single - it's for single cert enrollment
+ * dual - it's for dual certs enrollment
+ * encryption - getting the encryption cert only via
+ * authentication of the signing cert
+ * (crmf or keyGenInfo)
+ */
+ boolean certAuthEnroll = false;
+ String certauthEnrollType = null;
+
+ certAuthEnroll = getCertAuthEnrollStatus(httpParams);
+
+ try {
+ if (certAuthEnroll == true) {
+ certauthEnrollType = getCertAuthEnrollType(httpParams,
+ certAuthEnroll);
+ }
+ } catch (ECMSGWException e) {
+ // store a message in the signed audit log file
+ // (either an "admin" cert request for an admin certificate,
+ // an "agent" cert request for "bulk enrollment", or
+ // an "EE" standard cert request)
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(e.toString());
+ }
+
+ CMS.debug("EnrollServlet: In EnrollServlet.processX509!");
+ CMS.debug("EnrollServlet: certAuthEnroll " + certAuthEnroll);
+ CMS.debug("EnrollServlet: certauthEnrollType " + certauthEnrollType);
+
+ String challengePassword = httpParams.getValueAsString(
+ "challengePassword", "");
+
+ cmsReq.setIRequest(req);
+ saveHttpHeaders(httpReq, req);
+ saveHttpParams(httpParams, req);
+
+ X509Certificate sslClientCert = null;
+
+ // cert auth enroll
+ String certBasedOldSubjectDN = null;
+ BigInteger certBasedOldSerialNum = null;
+
+ // check if request was authenticated, if so set authtoken &
+ // certInfo. also if authenticated, take certInfo from authToken.
+ certInfo = null;
+ if (certAuthEnroll == true) {
+ sslClientCert = getSSLClientCertificate(httpReq);
+ if (sslClientCert == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_SSL_CLIENT_CERT"));
+
+ // store a message in the signed audit log file
+ // (either an "admin" cert request for an admin certificate,
+ // an "agent" cert request for "bulk enrollment", or
+ // an "EE" standard cert request)
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_SSL_CLIENT_CERT"));
+ }
+
+ certBasedOldSubjectDN = sslClientCert.getSubjectDN().toString();
+ certBasedOldSerialNum = sslClientCert.getSerialNumber();
+
+ CMS.debug("EnrollServlet: certBasedOldSubjectDN " + certBasedOldSubjectDN);
+ CMS.debug("EnrollServlet: certBasedOldSerialNum " + certBasedOldSerialNum);
+
+ // if the cert subject name is NOT MISSING, retrieve the
+ // actual "auditCertificateSubjectName" and "normalize" it
+ if (certBasedOldSubjectDN != null) {
+ // NOTE: This is ok even if the cert subject name
+ // is "" (empty)!
+ auditCertificateSubjectName = certBasedOldSubjectDN.trim();
+ }
+
+ try {
+ certInfo = (X509CertInfo)
+ ((X509CertImpl) sslClientCert).get(
+ X509CertImpl.NAME + "." + X509CertImpl.INFO);
+ } catch (CertificateParsingException ex) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_CERTINFO"));
+
+ // store a message in the signed audit log file
+ // (either an "admin" cert request for an admin certificate,
+ // an "agent" cert request for "bulk enrollment", or
+ // an "EE" standard cert request)
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(
+ CMS.getUserMessage(getLocale(httpReq), "CMS_GW_MISSING_CERTINFO"));
+ }
+ } else {
+ CMS.debug("EnrollServlet: No CertAuthEnroll.");
+ certInfo = CMS.getDefaultX509CertInfo();
+ }
+
+ X509CertInfo[] certInfoArray = new X509CertInfo[] { certInfo };
+
+ String authMgr = AuditFormat.NOAUTH;
+
+ // if authentication
+ if (authToken != null) {
+ authMgr =
+ authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ // don't store agent token in request.
+ // agent currently used for bulk issuance.
+ // if (!authMgr.equals(AuthSubsystem.CERTUSERDB_AUTHMGR_ID)) {
+ log(ILogger.LL_INFO,
+ "Enrollment request was authenticated by " +
+ authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME));
+
+ PKIProcessor.fillCertInfoFromAuthToken(certInfo,
+ authToken);
+ // save authtoken attrs to request directly
+ // (for policy use)
+ saveAuthToken(authToken, req);
+ // req.set(IRequest.AUTH_TOKEN, authToken);
+ // }
+ }
+
+ CMS.debug("EnrollServlet: Enroll authMgr " + authMgr);
+
+ if (certAuthEnroll == true) {
+ // log(ILogger.LL_DEBUG,
+ // "just gotten subjectDN and serialNumber " +
+ // "from ssl client cert");
+ if (authToken == null) {
+ // authToken is null, can't match to anyone; bail!
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_PROCESS_ENROLL_NO_AUTH"));
+
+ // store a message in the signed audit log file
+ // (either an "admin" cert request for an admin certificate,
+ // an "agent" cert request for "bulk enrollment", or
+ // an "EE" standard cert request)
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+
+ return;
+ }
+ }
+
+ // fill certInfo from input types: keygen, cmc, pkcs10 or crmf
+ KeyGenInfo keyGenInfo = httpParams.getValueAsKeyGenInfo(
+ SUBJECT_KEYGEN_INFO, null);
+ PKCS10 pkcs10 = null;
+
+ // support Enterprise 3.5.1 server where CERT_TYPE=csrCertType
+ // instead of certType
+ String certType = httpParams.getValueAsString(OLD_CERT_TYPE, null);
+ CMS.debug("EnrollServlet: certType " + certType);
+
+ if (certType == null) {
+ certType = httpParams.getValueAsString(CERT_TYPE, "client");
+ CMS.debug("EnrollServlet: certType " + certType);
+ } else {
+ // some policies may rely on the fact that
+ // CERT_TYPE is set. So for 3.5.1 or eariler
+ // we need to set CERT_TYPE here.
+ req.setExtData(IRequest.HTTP_PARAMS, CERT_TYPE, certType);
+ }
+ if (certType.equals("client")) {
+ // coming from MSIE
+ String p10b64 = httpParams.getValueAsString(PKCS10_REQUEST,
+ null);
+
+ if (p10b64 != null) {
+ try {
+ byte[] bytes = CMS.AtoB(p10b64);
+
+ pkcs10 = new PKCS10(bytes);
+ } catch (Exception e) {
+ // ok, if the above fails, it could
+ // be a PKCS10 with header
+ pkcs10 = httpParams.getValueAsPKCS10(PKCS10_REQUEST,
+ false, null);
+ // e.printStackTrace();
+ }
+ }
+
+ //pkcs10 = httpParams.getValuePKCS10(PKCS10_REQUEST, null);
+
+ } else {
+ try {
+ // coming from server cut & paste blob.
+ pkcs10 = httpParams.getValueAsPKCS10(PKCS10_REQUEST,
+ false, null);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ String cmc = null;
+ String asciiBASE64Blob = httpParams.getValueAsString(CMC_REQUEST, null);
+
+ if (asciiBASE64Blob != null) {
+ int startIndex = asciiBASE64Blob.indexOf(HEADER);
+ int endIndex = asciiBASE64Blob.indexOf(TRAILER);
+ if (startIndex != -1 && endIndex != -1) {
+ startIndex = startIndex + HEADER.length();
+ cmc = asciiBASE64Blob.substring(startIndex, endIndex);
+ } else
+ cmc = asciiBASE64Blob;
+ CMS.debug("EnrollServlet: cmc " + cmc);
+ }
+
+ String crmf = httpParams.getValueAsString(CRMF_REQUEST, null);
+
+ CMS.debug("EnrollServlet: crmf " + crmf);
+
+ if (certAuthEnroll == true) {
+
+ PKIProcessor.fillCertInfoFromAuthToken(certInfo, authToken);
+
+ // for dual certs
+ if (certauthEnrollType.equals(CERT_AUTH_DUAL)) {
+
+ CMS.debug("EnrollServlet: Attempting CERT_AUTH_DUAL");
+ boolean gotEncCert = false;
+ X509CertInfo[] cInfoArray = null;
+
+ try {
+ cInfoArray = handleCertAuthDual(certInfo, authToken,
+ sslClientCert, mCa,
+ certBasedOldSubjectDN,
+ certBasedOldSerialNum);
+ } catch (ECMSGWException e) {
+ // store a message in the signed audit log file
+ // (either an "admin" cert request for an admin
+ // certificate, an "agent" cert request for
+ // "bulk enrollment", or an "EE" standard cert request)
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(e.toString());
+ }
+
+ if (cInfoArray != null && cInfoArray.length != 0) {
+ CMS.debug("EnrollServlet: cInfoArray Length " + cInfoArray.length);
+
+ certInfoArray = cInfoArray;
+ gotEncCert = true;
+ }
+
+ if (gotEncCert == false) {
+ // encryption cert not found, bail
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage(
+ "CMSGW_ENCRYPTION_CERT_NOT_FOUND"));
+
+ // store a message in the signed audit log file
+ // (either an "admin" cert request for an admin
+ // certificate, an "agent" cert request for
+ // "bulk enrollment", or an "EE" standard cert request)
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_ENCRYPTION_CERT_NOT_FOUND"));
+ }
+
+ } else if (certauthEnrollType.equals(CERT_AUTH_ENCRYPTION)) {
+
+ // first, make sure the client cert is indeed a
+ // signing only cert
+
+ try {
+
+ checkClientCertSigningOnly(sslClientCert);
+ } catch (ECMSGWException e) {
+ // store a message in the signed audit log file
+ // (either an "admin" cert request for an admin
+ // certificate, an "agent" cert request for
+ // "bulk enrollment", or an "EE" standard cert request)
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(e.toString());
+ }
+
+ /*
+ * either crmf or keyGenInfo
+ */
+ if (keyGenInfo != null) {
+ KeyGenProcessor keyGenProc = new KeyGenProcessor(cmsReq,
+ this);
+
+ keyGenProc.fillCertInfo(null, certInfo,
+ authToken, httpParams);
+
+ req.setExtData(CLIENT_ISSUER,
+ sslClientCert.getIssuerDN().toString());
+ CMS.debug("EnrollServlet: sslClientCert issuerDN = " +
+ sslClientCert.getIssuerDN().toString());
+ } else if (crmf != null && crmf != "") {
+ CRMFProcessor crmfProc = new CRMFProcessor(cmsReq, this, enforcePop);
+
+ certInfoArray = crmfProc.fillCertInfoArray(crmf,
+ authToken,
+ httpParams,
+ req);
+
+ req.setExtData(CLIENT_ISSUER,
+ sslClientCert.getIssuerDN().toString());
+ CMS.debug("EnrollServlet: sslClientCert issuerDN = " +
+ sslClientCert.getIssuerDN().toString());
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CANT_PROCESS_ENROLL_REQ") +
+ CMS.getLogMessage("CMSGW_MISSING_KEYGEN_INFO"));
+
+ // store a message in the signed audit log file
+ // (either an "admin" cert request for an admin
+ // certificate, an "agent" cert request for
+ // "bulk enrollment", or an "EE" standard cert request)
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(
+ CMS.getUserMessage(getLocale(httpReq), "CMS_GW_MISSING_KEYGEN_INFO"));
+ }
+
+ } else if (certauthEnrollType.equals(CERT_AUTH_SINGLE)) {
+
+ // have to be buried here to handle the issuer
+
+ if (keyGenInfo != null) {
+ KeyGenProcessor keyGenProc = new KeyGenProcessor(cmsReq,
+ this);
+
+ keyGenProc.fillCertInfo(null, certInfo,
+ authToken, httpParams);
+ } else if (pkcs10 != null) {
+ PKCS10Processor pkcs10Proc = new PKCS10Processor(cmsReq,
+ this);
+
+ pkcs10Proc.fillCertInfo(pkcs10, certInfo,
+ authToken, httpParams);
+ } else if (cmc != null && cmc != "") {
+ CMCProcessor cmcProc = new CMCProcessor(cmsReq, this, enforcePop);
+
+ certInfoArray = cmcProc.fillCertInfoArray(cmc,
+ authToken,
+ httpParams,
+ req);
+ } else if (crmf != null && crmf != "") {
+ CRMFProcessor crmfProc = new CRMFProcessor(cmsReq, this, enforcePop);
+
+ certInfoArray = crmfProc.fillCertInfoArray(crmf,
+ authToken,
+ httpParams,
+ req);
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CANT_PROCESS_ENROLL_REQ") +
+ CMS.getLogMessage("CMSGW_MISSING_KEYGEN_INFO"));
+
+ // store a message in the signed audit log file
+ // (either an "admin" cert request for an admin
+ // certificate, an "agent" cert request for
+ // "bulk enrollment", or an "EE" standard cert request)
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(
+ CMS.getUserMessage(getLocale(httpReq), "CMS_GW_MISSING_KEYGEN_INFO"));
+ }
+ req.setExtData(CLIENT_ISSUER,
+ sslClientCert.getIssuerDN().toString());
+ }
+
+ } else if (keyGenInfo != null) {
+
+ CMS.debug("EnrollServlet: Trying KeyGen with no cert auth.");
+ KeyGenProcessor keyGenProc = new KeyGenProcessor(cmsReq, this);
+
+ keyGenProc.fillCertInfo(null, certInfo, authToken, httpParams);
+ } else if (pkcs10 != null) {
+ CMS.debug("EnrollServlet: Trying PKCS10 with no cert auth.");
+ PKCS10Processor pkcs10Proc = new PKCS10Processor(cmsReq, this);
+
+ pkcs10Proc.fillCertInfo(pkcs10, certInfo, authToken, httpParams);
+ } else if (cmc != null) {
+ CMS.debug("EnrollServlet: Trying CMC with no cert auth.");
+ CMCProcessor cmcProc = new CMCProcessor(cmsReq, this, enforcePop);
+
+ certInfoArray = cmcProc.fillCertInfoArray(cmc, authToken,
+ httpParams, req);
+ } else if (crmf != null && crmf != "") {
+ CMS.debug("EnrollServlet: Trying CRMF with no cert auth.");
+ CRMFProcessor crmfProc = new CRMFProcessor(cmsReq, this, enforcePop);
+
+ certInfoArray = crmfProc.fillCertInfoArray(crmf, authToken,
+ httpParams, req);
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CANT_PROCESS_ENROLL_REQ") +
+ CMS.getLogMessage("CMSGW_MISSING_KEYGEN_INFO"));
+
+ // store a message in the signed audit log file
+ // (either an "admin" cert request for an admin certificate,
+ // an "agent" cert request for "bulk enrollment", or
+ // an "EE" standard cert request)
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(CMS.getUserMessage(getLocale(httpReq), "CMS_GW_MISSING_KEYGEN_INFO"));
+ }
+
+ // if ca, fill in default signing alg here
+
+ try {
+ ICertificateAuthority caSub =
+ (ICertificateAuthority) CMS.getSubsystem("ca");
+ if (certInfoArray != null && caSub != null) {
+ for (int ix = 0; ix < certInfoArray.length; ix++) {
+ X509CertInfo ci = certInfoArray[ix];
+ String defaultSig = caSub.getDefaultAlgorithm();
+ AlgorithmId algid = AlgorithmId.get(defaultSig);
+ ci.set(X509CertInfo.ALGORITHM_ID,
+ new CertificateAlgorithmId(algid));
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("Failed to set signing alg to certinfo " + e.toString());
+ }
+
+ req.setExtData(IRequest.CERT_INFO, certInfoArray);
+
+ if (challengePassword != null && !challengePassword.equals("")) {
+ String pwd = hashPassword(challengePassword);
+
+ req.setExtData(CHALLENGE_PASSWORD, pwd);
+ }
+
+ // store a message in the signed audit log file
+ // (either an "admin" cert request for an admin certificate,
+ // an "agent" cert request for "bulk enrollment", or
+ // an "EE" standard cert request)
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ // (either an "admin" cert request for an admin certificate,
+ // an "agent" cert request for "bulk enrollment", or
+ // an "EE" standard cert request)
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+
+ throw eAudit1;
+ }
+
+ X509CertImpl[] issuedCerts = null;
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ // send request to request queue.
+ mRequestQueue.processRequest(req);
+ // process result.
+
+ // render OLD_CERT_TYPE's response differently, we
+ // do not want any javascript in HTML, and need to
+ // override the default render.
+ if (httpParams.getValueAsString(OLD_CERT_TYPE, null) != null) {
+ try {
+ renderServerEnrollResult(cmsReq);
+ cmsReq.setStatus(ICMSRequest.SUCCESS); // no default render
+
+ issuedCerts =
+ cmsReq.getIRequest().getExtDataInCertArray(
+ IRequest.ISSUED_CERTS);
+
+ for (int i = 0; i < issuedCerts.length; i++) {
+ // (automated "agent" cert request processed
+ // - "accepted")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_ACCEPTANCE,
+ auditInfoCertValue(issuedCerts[i]));
+
+ audit(auditMessage);
+ }
+ } catch (IOException ex) {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+
+ // (automated "agent" cert request processed - "rejected")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_REJECTION,
+ SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[0]);
+
+ audit(auditMessage);
+ }
+
+ return;
+ }
+
+ boolean completed = handleEnrollAuditLog(req, cmsReq,
+ mAuthMgr, authToken,
+ certInfo, startTime);
+
+ if (completed == false) {
+ // (automated "agent" cert request processed - "rejected")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_REJECTION,
+ SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[1]);
+
+ audit(auditMessage);
+
+ return;
+ }
+
+ // service success
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ issuedCerts = req.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ String initiative = null;
+ String agentID;
+
+ if (authToken == null) {
+ // request is from eegateway, so fromUser.
+ initiative = AuditFormat.FROMUSER;
+ } else {
+ agentID = authToken.getInString("userid");
+ initiative = AuditFormat.FROMAGENT + " agentID: " + agentID;
+ }
+
+ // audit log the success.
+ long endTime = CMS.getCurrentDate().getTime();
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.ENROLLMENTFORMAT,
+ new Object[]
+ { req.getRequestId(),
+ initiative,
+ mAuthMgr,
+ "completed",
+ issuedCerts[0].getSubjectDN(),
+ "cert issued serial number: 0x" +
+ issuedCerts[0].getSerialNumber().toString(16) +
+ " time: " +
+ (endTime - startTime) }
+ );
+
+ // handle initial admin enrollment if in adminEnroll mode.
+ checkAdminEnroll(cmsReq, issuedCerts);
+
+ // return cert as mime type binary if requested.
+ if (checkImportCertToNav(cmsReq.getHttpResp(),
+ httpParams, issuedCerts[0])) {
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+
+ for (int i = 0; i < issuedCerts.length; i++) {
+ // (automated "agent" cert request processed - "accepted")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_ACCEPTANCE,
+ auditInfoCertValue(issuedCerts[i]));
+
+ audit(auditMessage);
+ }
+
+ return;
+ }
+
+ // use success template.
+ try {
+ cmsReq.setResult(issuedCerts);
+ renderTemplate(cmsReq, mEnrollSuccessTemplate,
+ mEnrollSuccessFiller);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+
+ for (int i = 0; i < issuedCerts.length; i++) {
+ // (automated "agent" cert request processed - "accepted")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_ACCEPTANCE,
+ auditInfoCertValue(issuedCerts[i]));
+
+ audit(auditMessage);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_TEMP_REND_ERR",
+ mEnrollSuccessFiller.toString(),
+ e.toString()));
+
+ // (automated "agent" cert request processed - "rejected")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_REJECTION,
+ SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[2]);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_RETURNING_RESULT_ERROR"));
+ }
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ // (automated "agent" cert request processed - "rejected")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_REJECTION,
+ SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[3]);
+
+ audit(auditMessage);
+
+ throw eAudit1;
+ }
+
+ return;
+ }
+
+ /**
+ * check if this is first enroll from admin enroll.
+ * If so disable admin enroll from here on.
+ */
+ protected void checkAdminEnroll(CMSRequest cmsReq, X509CertImpl[] issuedCerts)
+ throws EBaseException {
+ // this is special case, get the admin certificate
+ if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID)) {
+ addAdminAgent(cmsReq, issuedCerts);
+ CMSGateway.disableAdminEnroll();
+ }
+ }
+
+ protected void addAdminAgent(CMSRequest cmsReq, X509CertImpl[] issuedCerts)
+ throws EBaseException {
+ String userid = cmsReq.getHttpParams().getValueAsString("uid");
+ IUGSubsystem ug = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+
+ IUser adminuser = ug.createUser(userid);
+
+ adminuser.setX509Certificates(issuedCerts);
+ try {
+ ug.addUserCert(adminuser);
+ } catch (netscape.ldap.LDAPException e) {
+ CMS.debug(
+ "EnrollServlet: Cannot add admin's certificate to its entry in the " +
+ "user group database. Error " + e);
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_ADDING_ADMIN_CERT_ERROR", e.toString()));
+ }
+ IGroup agentGroup =
+ ug.getGroupFromName(CA_AGENT_GROUP);
+
+ if (agentGroup != null) {
+ // add user to the group if necessary
+ if (!agentGroup.isMember(userid)) {
+ agentGroup.addMemberName(userid);
+ ug.modifyGroup(agentGroup);
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP,
+ AuditFormat.LEVEL, AuditFormat.ADDUSERGROUPFORMAT,
+ new Object[] { userid, userid, CA_AGENT_GROUP }
+ );
+
+ }
+ } else {
+ String msg = "Cannot add admin to the " +
+ CA_AGENT_GROUP +
+ " group: Group does not exist.";
+
+ CMS.debug("EnrollServlet: " + msg);
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_ADDING_ADMIN_ERROR"));
+ }
+ }
+
+ protected void renderServerEnrollResult(CMSRequest cmsReq) throws
+ IOException {
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ httpResp.setContentType("text/html");
+ ServletOutputStream out = null;
+
+ out = httpResp.getOutputStream();
+
+ // get template based on request status
+ out.println("<HTML>");
+ out.println("<TITLE>");
+ out.println("Server Enrollment");
+ out.println("</TITLE>");
+ // out.println("<BODY BGCOLOR=white>");
+
+ if (cmsReq.getIRequest().getRequestStatus().equals(RequestStatus.COMPLETE)) {
+ out.println("<H1>");
+ out.println("SUCCESS");
+ out.println("</H1>");
+ out.println("Your request is submitted and approved. Please cut and paste the certificate into your server."); // XXX - localize the message
+ out.println("<P>");
+ out.println("Request Creation Time: ");
+ out.println(cmsReq.getIRequest().getCreationTime().toString());
+ out.println("<P>");
+ out.println("Request Status: ");
+ out.println(cmsReq.getStatus().toString());
+ out.println("<P>");
+ out.println("Request ID: ");
+ out.println(cmsReq.getIRequest().getRequestId().toString());
+ out.println("<P>");
+ out.println("Certificate: ");
+ out.println("<P>");
+ out.println("<PRE>");
+ X509CertImpl certs[] =
+ cmsReq.getIRequest().getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ out.println(CMS.getEncodedCert(certs[0]));
+ out.println("</PRE>");
+ out.println("<P>");
+ out.println("<!HTTP_OUTPUT REQUEST_CREATION_TIME=" +
+ cmsReq.getIRequest().getCreationTime().toString() + ">");
+ out.println("<!HTTP_OUTPUT REQUEST_STATUS=" +
+ cmsReq.getStatus().toString() + ">");
+ out.println("<!HTTP_OUTPUT REQUEST_ID=" +
+ cmsReq.getIRequest().getRequestId().toString() + ">");
+ out.println("<!HTTP_OUTPUT X509_CERTIFICATE=" +
+ CMS.getEncodedCert(certs[0]) + ">");
+ } else if (cmsReq.getIRequest().getRequestStatus().equals(RequestStatus.PENDING)) {
+ out.println("<H1>");
+ out.println("PENDING");
+ out.println("</H1>");
+ out.println("Your request is submitted. You can check on the status of your request with an authorized agent or local administrator by referring to the request ID."); // XXX - localize the message
+ out.println("<P>");
+ out.println("Request Creation Time: ");
+ out.println(cmsReq.getIRequest().getCreationTime().toString());
+ out.println("<P>");
+ out.println("Request Status: ");
+ out.println(cmsReq.getStatus().toString());
+ out.println("<P>");
+ out.println("Request ID: ");
+ out.println(cmsReq.getIRequest().getRequestId().toString());
+ out.println("<P>");
+ out.println("<!HTTP_OUTPUT REQUEST_CREATION_TIME=" +
+ cmsReq.getIRequest().getCreationTime().toString() + ">");
+ out.println("<!HTTP_OUTPUT REQUEST_STATUS=" +
+ cmsReq.getStatus().toString() + ">");
+ out.println("<!HTTP_OUTPUT REQUEST_ID=" +
+ cmsReq.getIRequest().getRequestId().toString() + ">");
+ } else {
+ out.println("<H1>");
+ out.println("ERROR");
+ out.println("</H1>");
+ out.println("<!INFO>");
+ out.println("Please consult your local administrator for assistance."); // XXX - localize the message
+ out.println("<!/INFO>");
+ out.println("<P>");
+ out.println("Request Status: ");
+ out.println(cmsReq.getStatus().toString());
+ out.println("<P>");
+ out.println("Error: ");
+ out.println(cmsReq.getError()); // XXX - need to parse in Locale
+ out.println("<P>");
+ out.println("<!HTTP_OUTPUT REQUEST_STATUS=" +
+ cmsReq.getStatus().toString() + ">");
+ out.println("<!HTTP_OUTPUT ERROR=" +
+ cmsReq.getError() + ">");
+ }
+
+ /**
+ * // include all the input data
+ * ArgBlock args = cmsReq.getHttpParams();
+ * Enumeration ele = args.getElements();
+ * while (ele.hasMoreElements()) {
+ * String eleT = (String)ele.nextElement();
+ * out.println("<!HTTP_INPUT " + eleT + "=" +
+ * args.get(eleT) + ">");
+ * }
+ **/
+
+ out.println("</HTML>");
+ }
+
+ // XXX ALERT !!
+ // Remove the following and calls to them when we bundle a cartman
+ // later than alpha1.
+ // These are here to cover up problem in cartman where the
+ // key usage extension always ends up being digital signature only
+ // and for rsa-ex ends up having no bits set.
+
+ @SuppressWarnings("unused")
+ private boolean mIsTestBed;
+
+ private void init_testbed_hack(IConfigStore config)
+ throws EBaseException {
+ mIsTestBed = config.getBoolean("isTestBed", true);
+ }
+
+ /**
+ * Signed Audit Log Info Certificate Value
+ *
+ * This method is called to obtain the certificate from the passed in
+ * "X509CertImpl" for a signed audit log message.
+ * <P>
+ *
+ * @param x509cert an X509CertImpl
+ * @return cert string containing the certificate
+ */
+ private String auditInfoCertValue(X509CertImpl x509cert) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ if (x509cert == null) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ byte rawData[] = null;
+
+ try {
+ rawData = x509cert.getEncoded();
+ } catch (CertificateEncodingException e) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ String cert = null;
+
+ // convert "rawData" into "base64Data"
+ if (rawData != null) {
+ String base64Data = null;
+
+ base64Data = Utils.base64encode(rawData).trim();
+
+ StringBuffer sb = new StringBuffer();
+ // extract all line separators from the "base64Data"
+ for (int i = 0; i < base64Data.length(); i++) {
+ if (base64Data.substring(i, i).getBytes() != EOL) {
+ sb.append(base64Data.substring(i, i));
+ }
+ }
+ cert = sb.toString();
+ }
+
+ if (cert != null) {
+ cert = cert.trim();
+
+ if (cert.equals("")) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ } else {
+ return cert;
+ }
+ } else {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
new file mode 100644
index 000000000..31b235d2a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
@@ -0,0 +1,204 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Locale;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.BadRequestDataException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.cert.CertEnrollmentRequest;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.ProfileAttribute;
+import com.netscape.certsrv.profile.ProfileInput;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.profile.SSLClientCertProvider;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+public class EnrollmentProcessor extends CertProcessor {
+
+ public EnrollmentProcessor(String id, Locale locale) throws EPropertyNotFound, EBaseException {
+ super(id, locale);
+ }
+
+ private void setInputsIntoContext(CertEnrollmentRequest data, IProfile profile, IProfileContext ctx) {
+ // put profile inputs into a local map
+ HashMap<String, String> dataInputs = new HashMap<String, String>();
+ for (ProfileInput input : data.getInputs()) {
+ for (ProfileAttribute attr: input.getAttrs()) {
+ dataInputs.put(attr.getName(), attr.getValue());
+ }
+ }
+
+ // iterate through inputs in profile and put those in context
+ Enumeration<String> inputIds = profile.getProfileInputIds();
+ if (inputIds != null) {
+ while (inputIds.hasMoreElements()) {
+ String inputId = inputIds.nextElement();
+ IProfileInput profileInput = profile.getProfileInput(inputId);
+ Enumeration<String> inputNames = profileInput.getValueNames();
+
+ while (inputNames.hasMoreElements()) {
+ String inputName = inputNames.nextElement();
+ if (dataInputs.containsKey(inputName)) {
+ // all subject name parameters start with sn_, no other input parameters do
+ if (inputName.matches("^sn_.*")) {
+ ctx.set(inputName, LDAPUtil.escapeRDNValue(dataInputs.get(inputName)));
+ } else {
+ ctx.set(inputName, dataInputs.get(inputName));
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Called by the legacy servlets to access the Processor function
+ * @param request
+ * @return
+ * @throws EBaseException
+ */
+ public HashMap<String, Object> processEnrollment(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ String profileId = (this.profileID == null) ? req.getParameter("profileId") : this.profileID;
+ IProfile profile = ps.getProfile(profileId);
+
+ if (profile == null) {
+ CMS.debug(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId));
+ throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId));
+ }
+
+ CertEnrollmentRequest data = CertEnrollmentRequestFactory.create(cmsReq, profile, locale);
+ return processEnrollment(data, cmsReq.getHttpReq());
+ }
+
+ /**
+ * Process the HTTP request
+ * <P>
+ *
+ * (Certificate Request Processed - either an automated "EE" profile based cert acceptance, or an automated "EE"
+ * profile based cert rejection)
+ * <P>
+ *
+ * <ul>
+ * <li>http.param profileId ID of profile to use to process request
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been
+ * through the approval process
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ * @exception EBaseException an error has occurred
+ */
+ public HashMap<String, Object> processEnrollment(CertEnrollmentRequest data, HttpServletRequest request)
+ throws EBaseException {
+
+ try {
+ if (CMS.debugOn()) {
+ HashMap<String,String> params = data.toParams();
+ printParameterValues(params);
+ }
+
+ CMS.debug("EnrollmentSubmitter: isRenewal false");
+ startTiming("enrollment");
+
+ // if we did not configure profileId in xml file,
+ // then accept the user-provided one
+ String profileId = (this.profileID == null) ? data.getProfileId() : this.profileID;
+ CMS.debug("EnrollmentSubmitter: profileId " + profileId);
+
+ IProfile profile = ps.getProfile(profileId);
+ if (profile == null) {
+ CMS.debug(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId));
+ throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId));
+ }
+ if (!ps.isProfileEnable(profileId)) {
+ CMS.debug("EnrollmentSubmitter: Profile " + profileId + " not enabled");
+ throw new BadRequestDataException("Profile " + profileId + " not enabled");
+ }
+
+ IProfileContext ctx = profile.createContext();
+ CMS.debug("EnrollmentSubmitter: set Inputs into profile Context");
+ setInputsIntoContext(data, profile, ctx);
+
+ IProfileAuthenticator authenticator = profile.getAuthenticator();
+ if (authenticator != null) {
+ CMS.debug("EnrollmentSubmitter: authenticator " + authenticator.getName() + " found");
+ setCredentialsIntoContext(request, authenticator, ctx);
+ }
+
+ // for ssl authentication; pass in servlet for retrieving ssl client certificates
+ // insert profile context so that input parameter can be retrieved
+ SessionContext context = SessionContext.getContext();
+ context.put("profileContext", ctx);
+ context.put("sslClientCertProvider", new SSLClientCertProvider(request));
+ CMS.debug("EnrollmentSubmitter: set sslClientCertProvider");
+
+ // before creating the request, authenticate the request
+ IAuthToken authToken = authenticate(request, null, authenticator, context, false);
+
+ // authentication success, now authorize
+ authorize(profileId, profile, authToken);
+
+ ///////////////////////////////////////////////
+ // create and populate request
+ ///////////////////////////////////////////////
+ startTiming("request_population");
+ IRequest[] reqs = profile.createRequests(ctx, locale);
+ populateRequests(data, false, locale, null, null, null, profileId, profile,
+ ctx, authenticator, authToken, reqs);
+ endTiming("request_population");
+
+ ///////////////////////////////////////////////
+ // submit request
+ ///////////////////////////////////////////////
+ String errorCode = submitRequests(locale, profile, authToken, reqs);
+ String errorReason = codeToReason(locale, errorCode);
+
+ HashMap<String, Object> ret = new HashMap<String, Object>();
+ ret.put(ARG_REQUESTS, reqs);
+ ret.put(ARG_ERROR_CODE, errorCode);
+ ret.put(ARG_ERROR_REASON, errorReason);
+ ret.put(ARG_PROFILE, profile);
+
+ CMS.debug("EnrollmentSubmitter: done serving");
+ endTiming("enrollment");
+
+ return ret;
+ } finally {
+ SessionContext.releaseContext();
+ endAllEvents();
+ }
+ }
+
+
+
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/FilterBuilder.java b/base/server/cms/src/com/netscape/cms/servlet/cert/FilterBuilder.java
new file mode 100644
index 000000000..5c337afee
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/FilterBuilder.java
@@ -0,0 +1,332 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.cert;
+
+import java.util.Calendar;
+import java.util.StringTokenizer;
+
+import com.netscape.certsrv.cert.CertSearchRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+/**
+ * @author jmagne
+ *
+ */
+public class FilterBuilder {
+ private final static String MATCH_EXACTLY = "exact";
+ private String searchFilter = null;
+ private CertSearchRequest request = null;
+
+ public FilterBuilder(CertSearchRequest request) {
+ this.request = request;
+ }
+
+ public String buildFilter() {
+ StringBuffer filter = new StringBuffer();
+ buildSerialNumberRangeFilter(filter);
+ buildSubjectFilter(filter);
+ buildStatusFilter(filter);
+ buildRevokedByFilter(filter);
+ buildRevokedOnFilter(filter);
+ buildRevocationReasonFilter(filter);
+ buildIssuedByFilter(filter);
+ buildIssuedOnFilter(filter);
+ buildValidNotBeforeFilter(filter);
+ buildValidNotAfterFilter(filter);
+ buildValidityLengthFilter(filter);
+ buildCertTypeFilter(filter);
+
+ searchFilter = filter.toString();
+
+ if (searchFilter != null && !searchFilter.equals("")) {
+ searchFilter = "(&" + searchFilter + ")";
+ }
+
+ return searchFilter;
+ }
+
+ private void buildSerialNumberRangeFilter(StringBuffer filter) {
+
+ if (!request.getSerialNumberRangeInUse()) {
+ return;
+ }
+ boolean changed = false;
+ String serialFrom = request.getSerialFrom();
+ if (serialFrom != null && !serialFrom.equals("")) {
+ filter.append("(certRecordId>=" + LDAPUtil.escapeFilter(serialFrom) + ")");
+ changed = true;
+ }
+ String serialTo = request.getSerialTo();
+ if (serialTo != null && !serialTo.equals("")) {
+ filter.append("(certRecordId<=" + LDAPUtil.escapeFilter(serialTo) + ")");
+ changed = true;
+ }
+ if (!changed) {
+ filter.append("(certRecordId=*)");
+ }
+
+ }
+
+ private void buildSubjectFilter(StringBuffer filter) {
+ if (!request.getSubjectInUse()) {
+ return;
+ }
+ StringBuffer lf = new StringBuffer();
+
+ String matchStr = null;
+ boolean match = request.getMatchExactly();
+
+ if (match == true) {
+ matchStr = MATCH_EXACTLY;
+ }
+
+ buildAVAFilter(request.getEmail(), "E", lf, matchStr);
+ buildAVAFilter(request.getCommonName(), "CN", lf, matchStr);
+ buildAVAFilter(request.getUserID(), "UID", lf, matchStr);
+ buildAVAFilter(request.getOrgUnit(), "OU", lf, matchStr);
+ buildAVAFilter(request.getOrg(), "O", lf, matchStr);
+ buildAVAFilter(request.getLocality(), "L", lf, matchStr);
+ buildAVAFilter(request.getState(), "ST", lf, matchStr);
+ buildAVAFilter(request.getCountry(), "C", lf, matchStr);
+
+ if (lf.length() == 0) {
+ filter.append("("+ICertRecord.ATTR_X509CERT_SUBJECT+"=*)");
+ return;
+ }
+ if (matchStr != null && matchStr.equals(MATCH_EXACTLY)) {
+ filter.append("(&");
+ filter.append(lf);
+ filter.append(")");
+ } else {
+ filter.append("(|");
+ filter.append(lf);
+ filter.append(")");
+ }
+ }
+
+ private void buildStatusFilter(StringBuffer filter) {
+ String status = request.getStatus();
+ if (status == null || status.equals("")) {
+ return;
+ }
+ filter.append("(certStatus=");
+ filter.append(LDAPUtil.escapeFilter(status));
+ filter.append(")");
+ }
+
+ private void buildRevokedByFilter(StringBuffer filter) {
+ if (!request.getRevokedByInUse()) {
+ return;
+ }
+
+ String revokedBy = request.getRevokedBy();
+ if (revokedBy == null || revokedBy.equals("")) {
+ filter.append("(certRevokedBy=*)");
+ } else {
+ filter.append("(certRevokedBy=");
+ filter.append(LDAPUtil.escapeFilter(revokedBy));
+ filter.append(")");
+ }
+ }
+
+ private void buildDateFilter(String prefix,
+ String outStr, long adjustment,
+ StringBuffer filter) {
+ if (prefix == null || prefix.length() == 0) return;
+ long epoch = Long.parseLong(prefix);
+ Calendar from = Calendar.getInstance();
+ from.setTimeInMillis(epoch);
+ filter.append("(");
+ filter.append(LDAPUtil.escapeFilter(outStr));
+ filter.append(Long.toString(from.getTimeInMillis() + adjustment));
+ filter.append(")");
+ }
+
+ private void buildRevokedOnFilter(StringBuffer filter) {
+ if (!request.getRevokedOnInUse()) {
+ return;
+ }
+ buildDateFilter(request.getRevokedOnFrom(), "certRevokedOn>=", 0, filter);
+ buildDateFilter(request.getRevokedOnTo(), "certRevokedOn<=", 86399999, filter);
+ }
+
+ private void buildRevocationReasonFilter(StringBuffer filter) {
+ if (!request.getRevocationReasonInUse()) {
+ return;
+ }
+ String reasons = request.getRevocationReason();
+ if (reasons == null) {
+ return;
+ }
+ String queryCertFilter = null;
+ StringTokenizer st = new StringTokenizer(reasons, ",");
+ int count = st.countTokens();
+ if (st.hasMoreTokens()) {
+ if (count >=2) filter.append("(|");
+ while (st.hasMoreTokens()) {
+ String token = st.nextToken();
+ if (queryCertFilter == null) {
+ queryCertFilter = "";
+ }
+ filter.append("(x509cert.certRevoInfo=");
+ filter.append(LDAPUtil.escapeFilter(token));
+ filter.append(")");
+ }
+ if (count >= 2) filter.append(")");
+ }
+ }
+
+ private void buildIssuedByFilter(StringBuffer filter) {
+ if (!request.getIssuedByInUse()) {
+ return;
+ }
+ String issuedBy = request.getIssuedBy();
+ if (issuedBy == null || issuedBy.equals("")) {
+ filter.append("(certIssuedBy=*)");
+ } else {
+ filter.append("(certIssuedBy=");
+ filter.append(LDAPUtil.escapeFilter(issuedBy));
+ filter.append(")");
+ }
+ }
+
+ private void buildIssuedOnFilter(StringBuffer filter) {
+ if (!request.getIssuedOnInUse()) {
+ return;
+ }
+ buildDateFilter(request.getIssuedOnFrom(), "certCreateTime>=", 0, filter);
+ buildDateFilter(request.getIssuedOnTo(), "certCreateTime<=", 86399999, filter);
+ }
+
+ private void buildValidNotBeforeFilter(StringBuffer filter) {
+ if (!request.getValidNotBeforeInUse()) {
+ return;
+ }
+ buildDateFilter(request.getValidNotBeforeFrom(), ICertRecord.ATTR_X509CERT_NOT_BEFORE+">=", 0, filter);
+ buildDateFilter(request.getValidNotBeforeTo(), ICertRecord.ATTR_X509CERT_NOT_BEFORE+"<=", 86399999, filter);
+
+ }
+
+ private void buildValidNotAfterFilter(StringBuffer filter) {
+ if (!request.getValidNotAfterInUse()) {
+ return;
+ }
+ buildDateFilter(request.getValidNotAfterFrom(), ICertRecord.ATTR_X509CERT_NOT_AFTER+">=", 0, filter);
+ buildDateFilter(request.getValidNotAfterTo(), ICertRecord.ATTR_X509CERT_NOT_AFTER+"<=", 86399999, filter);
+
+ }
+
+ private void buildValidityLengthFilter(StringBuffer filter) {
+ if (!request.getValidityLengthInUse()) {
+ return;
+ }
+
+ String op = request.getValidityOperation();
+ Integer count = request.getValidityCount();
+ Long unit = request.getValidityUnit();
+
+ filter.append("(");
+ filter.append(ICertRecord.ATTR_X509CERT_DURATION);
+ filter.append(LDAPUtil.escapeFilter(op));
+ filter.append(count * unit);
+ filter.append(")");
+ }
+
+ private void buildCertTypeFilter(StringBuffer filter) {
+ if (!request.getCertTypeInUse()) {
+ return;
+ }
+ if (isOn(request.getCertTypeSSLClient())) {
+ filter.append("(x509cert.nsExtension.SSLClient=on)");
+ } else if (isOff(request.getCertTypeSSLClient())) {
+ filter.append("(x509cert.nsExtension.SSLClient=off)");
+ }
+ if (isOn(request.getCertTypeSSLServer())) {
+ filter.append("(x509cert.nsExtension.SSLServer=on)");
+ } else if (isOff(request.getCertTypeSSLServer())) {
+ filter.append("(x509cert.nsExtension.SSLServer=off)");
+ }
+ if (isOn(request.getCertTypeSecureEmail())) {
+ filter.append("(x509cert.nsExtension.SecureEmail=on)");
+ } else if (isOff(request.getCertTypeSecureEmail())) {
+ filter.append("(x509cert.nsExtension.SecureEmail=off)");
+ }
+ if (isOn(request.getCertTypeSubSSLCA())) {
+ filter.append("(x509cert.nsExtension.SubordinateSSLCA=on)");
+ } else if (isOff(request.getCertTypeSubSSLCA())) {
+ filter.append("(x509cert.nsExtension.SubordinateSSLCA=off)");
+ }
+ if (isOn(request.getCertTypeSubEmailCA())) {
+ filter.append("(x509cert.nsExtension.SubordinateEmailCA=on)");
+ } else if (isOff(request.getCertTypeSubEmailCA())) {
+ filter.append("(x509cert.nsExtension.SubordinateEmailCA=off)");
+ }
+ }
+
+ private boolean isOn(String value) {
+ String inUse = value;
+ if (inUse == null) {
+ return false;
+ }
+ if (inUse.equals("on")) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isOff(String value) {
+ String inUse = value;
+ if (inUse == null) {
+ return false;
+ }
+ if (inUse.equals("off")) {
+ return true;
+ }
+ return false;
+ }
+
+ private void buildAVAFilter(String param,
+ String avaName, StringBuffer lf, String match) {
+ if (param != null && !param.equals("")) {
+ if (match != null && match.equals(MATCH_EXACTLY)) {
+ lf.append("(|");
+ lf.append("("+ICertRecord.ATTR_X509CERT_SUBJECT+"=*");
+ lf.append(avaName);
+ lf.append("=");
+ lf.append(LDAPUtil.escapeFilter(LDAPUtil.escapeRDNValue(param)));
+ lf.append(",*)");
+ lf.append("("+ICertRecord.ATTR_X509CERT_SUBJECT+"=*");
+ lf.append(avaName);
+ lf.append("=");
+ lf.append(LDAPUtil.escapeFilter(LDAPUtil.escapeRDNValue(param)));
+ lf.append(")");
+ lf.append(")");
+ } else {
+ lf.append("("+ICertRecord.ATTR_X509CERT_SUBJECT+"=*");
+ lf.append(avaName);
+ lf.append("=");
+ lf.append("*");
+ lf.append(LDAPUtil.escapeFilter(LDAPUtil.escapeRDNValue(param)));
+ lf.append("*)");
+ }
+ }
+
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/GetBySerial.java b/base/server/cms/src/com/netscape/cms/servlet/cert/GetBySerial.java
new file mode 100644
index 000000000..2ea7da7c6
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/GetBySerial.java
@@ -0,0 +1,295 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.pkcs.ContentInfo;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.pkcs.SignerInfo;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+
+/**
+ * Retrieve certificate by serial number.
+ *
+ * @version $Revision$, $Date$
+ */
+public class GetBySerial extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2276677839178370838L;
+
+ private final static String IMPORT_CERT_TEMPLATE = "ImportCert.template";
+ private String mImportTemplate = null;
+ private String mIETemplate = null;
+ private ICMSTemplateFiller mImportTemplateFiller = null;
+ IRequestQueue mReqQ = null;
+
+ public GetBySerial() {
+ super();
+ }
+
+ /**
+ * Initialize the servlet. This servlet uses the template file
+ * "ImportCert.template" to import the cert to the users browser,
+ * if that is what the user requested
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ try {
+ mImportTemplate = sc.getInitParameter(
+ PROP_SUCCESS_TEMPLATE);
+ mIETemplate = sc.getInitParameter("importCertTemplate");
+ if (mImportTemplate == null)
+ mImportTemplate = IMPORT_CERT_TEMPLATE;
+ } catch (Exception e) {
+ mImportTemplate = null;
+ }
+ mImportTemplateFiller = new ImportCertsTemplateFiller();
+
+ // override success and error templates to null -
+ // handle templates locally.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+
+ ICertificateAuthority mCa = (ICertificateAuthority) CMS.getSubsystem("ca");
+ if (mCa == null) {
+ return;
+ }
+
+ mReqQ = mCa.getRequestQueue();
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param serialNumber serial number of certificate in HEX
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse response = cmsReq.getHttpResp();
+ IArgBlock args = cmsReq.getHttpParams();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "import");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ String serial = args.getValueAsString("serialNumber", null);
+ String browser = args.getValueAsString("browser", null);
+ BigInteger serialNo = null;
+
+ try {
+ serialNo = new BigInteger(serial, 16);
+ } catch (NumberFormatException e) {
+ serialNo = null;
+ }
+ if (serial == null || serialNo == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_INVALID_SERIAL_NUMBER"));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_SERIAL_NUMBER")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ ICertRecord certRecord = getCertRecord(serialNo);
+ if (certRecord == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CERT_SERIAL_NOT_FOUND_1", serialNo.toString(16)));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CERT_SERIAL_NOT_FOUND", "0x" + serialNo.toString(16))));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ // if RA, needs requestOwner to match
+ // first, find the user's group
+ if (authToken != null) {
+ String group = authToken.getInString("group");
+
+ if ((group != null) && (group != "")) {
+ CMS.debug("GetBySerial process: auth group=" + group);
+ if (group.equals("Registration Manager Agents")) {
+ boolean groupMatched = false;
+ // find the cert record's orig. requestor's group
+ MetaInfo metai = certRecord.getMetaInfo();
+ if (metai != null) {
+ String reqId = (String) metai.get(ICertRecord.META_REQUEST_ID);
+ RequestId rid = new RequestId(reqId);
+ IRequest creq = mReqQ.findRequest(rid);
+ if (creq != null) {
+ String reqOwner = creq.getRequestOwner();
+ if (reqOwner != null) {
+ CMS.debug("GetBySerial process: req owner=" + reqOwner);
+ if (reqOwner.equals(group))
+ groupMatched = true;
+ }
+ }
+ }
+ if (groupMatched == false) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CERT_SERIAL_NOT_FOUND_1", serialNo.toString(16)));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CERT_SERIAL_NOT_FOUND", "0x" + serialNo.toString(16))));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+ }
+ }
+ }
+
+ X509CertImpl cert = certRecord.getCertificate();
+
+ if (cert != null) {
+ // if there's a crmf request id, set that too.
+ if (browser != null && browser.equals("ie")) {
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ Locale[] locale = new Locale[1];
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca");
+ CertificateChain cachain = ca.getCACertChain();
+ X509Certificate[] cacerts = cachain.getChain();
+ X509CertImpl[] userChain = new X509CertImpl[cacerts.length + 1];
+ int m = 1, n = 0;
+
+ for (; n < cacerts.length; m++, n++) {
+ userChain[m] = (X509CertImpl) cacerts[n];
+ }
+
+ userChain[0] = cert;
+ PKCS7 p7 = new PKCS7(new AlgorithmId[0],
+ new ContentInfo(new byte[0]), userChain, new SignerInfo[0]);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ try {
+ p7.encodeSignedData(bos);
+ } catch (Exception eee) {
+ }
+
+ byte[] p7Bytes = bos.toByteArray();
+ String p7Str = CMS.BtoA(p7Bytes);
+
+ header.addStringValue("pkcs7", CryptoUtil.normalizeCertStr(p7Str));
+ try {
+ CMSTemplate form = getTemplate(mIETemplate, req, locale);
+ ServletOutputStream out = response.getOutputStream();
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ response.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ return;
+ } catch (Exception ee) {
+ CMS.debug("GetBySerial process: Exception=" + ee.toString());
+ }
+ } //browser is IE
+
+ MetaInfo metai = certRecord.getMetaInfo();
+ String crmfReqId = null;
+
+ if (metai != null) {
+ crmfReqId = (String) metai.get(ICertRecord.META_CRMF_REQID);
+ if (crmfReqId != null)
+ cmsReq.setResult(IRequest.CRMF_REQID, crmfReqId);
+ }
+
+ if (crmfReqId == null && checkImportCertToNav(
+ cmsReq.getHttpResp(), cmsReq.getHttpParams(), cert)) {
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+ // use import cert template to return cert.
+ X509CertImpl[] certs = new X509CertImpl[] { cert };
+
+ cmsReq.setResult(certs);
+
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+
+ // XXX follow request in cert record to set certtype, which will
+ // import cert only if it's client. For now assume "client" if
+ // someone clicked to import this cert.
+ cmsReq.getHttpParams().set("certType", "client");
+
+ try {
+ renderTemplate(cmsReq, mImportTemplate, mImportTemplateFiller);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"));
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/GetCAChain.java b/base/server/cms/src/com/netscape/cms/servlet/cert/GetCAChain.java
new file mode 100644
index 000000000..9ffb54671
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/GetCAChain.java
@@ -0,0 +1,406 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.CertificateChain;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.ICertPrettyPrint;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Retrieve the Certificates comprising the CA Chain for this CA.
+ *
+ * @version $Revision$, $Date$
+ */
+public class GetCAChain extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -8189048155415074581L;
+ private final static String TPL_FILE = "displayCaCert.template";
+ private String mFormPath = null;
+
+ public GetCAChain() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+
+ // override success to display own output.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ // coming from ee
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param op 'downloadBIN' - return the binary certificate chain
+ * <li>http.param op 'displayIND' - display pretty-print of certificate chain components
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ // Construct an ArgBlock
+ IArgBlock args = cmsReq.getHttpParams();
+
+ // Get the operation code
+ String op = null;
+
+ op = args.getValueAsString("op", null);
+ if (op == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_NO_OPTIONS_SELECTED"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_NO_OPTIONS_SELECTED"));
+ }
+
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+
+ AuthzToken authzToken = null;
+
+ if (op.startsWith("download")) {
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "download");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ downloadChain(op, args, httpReq, httpResp, cmsReq);
+ } else if (op.startsWith("display")) {
+ try {
+ authzToken = mAuthz.authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ displayChain(op, args, httpReq, httpResp, cmsReq);
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_INVALID_OPTIONS_CA_CHAIN"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_OPTIONS_SELECTED"));
+ }
+ // cmsReq.setResult(null);
+ return;
+ }
+
+ private void downloadChain(String op,
+ IArgBlock args,
+ HttpServletRequest httpReq,
+ HttpServletResponse httpResp,
+ CMSRequest cmsReq)
+ throws EBaseException {
+
+ /* check browser info ? */
+
+ /* check if pkcs7 will work for both nav and ie */
+
+ byte[] bytes = null;
+
+ /*
+ * Some IE actions - IE doesn't want PKCS7 for "download" CA Cert.
+ * This means that we can only hand out the root CA, and not
+ * the whole chain.
+ */
+
+ if (clientIsMSIE(httpReq) && (op.equals("download") || op.equals("downloadBIN"))) {
+ X509Certificate[] caCerts =
+ ((ICertAuthority) mAuthority).getCACertChain().getChain();
+
+ try {
+ bytes = caCerts[0].getEncoded();
+ } catch (CertificateEncodingException e) {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_GETTING_CACERT_ENCODED", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_GETTING_CA_CERT_ERROR"));
+ }
+ } else {
+ CertificateChain certChain =
+ ((ICertAuthority) mAuthority).getCACertChain();
+
+ if (certChain == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CA_CHAIN_EMPTY"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CA_CHAIN_EMPTY"));
+ }
+
+ try {
+ ByteArrayOutputStream encoded = new ByteArrayOutputStream();
+
+ certChain.encode(encoded, false);
+ bytes = encoded.toByteArray();
+ } catch (IOException e) {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_ENCODING_CA_CHAIN_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_ENCODING_CA_CHAIN_ERROR"));
+ }
+ }
+
+ String mimeType = null;
+
+ if (op.equals("downloadBIN")) {
+ mimeType = "application/octet-stream";
+ } else {
+ try {
+ mimeType = args.getValueAsString("mimeType");
+ } catch (EBaseException e) {
+ mimeType = "application/octet-stream";
+ }
+ }
+
+ try {
+ if (op.equals("downloadBIN")) {
+ // file suffixes changed to comply with RFC 5280
+ // requirements for AIA extensions
+ if (clientIsMSIE(httpReq)) {
+ httpResp.setHeader("Content-disposition",
+ "attachment; filename=ca.cer");
+ } else {
+ httpResp.setHeader("Content-disposition",
+ "attachment; filename=ca.p7c");
+ }
+ }
+ httpResp.setContentType(mimeType);
+ httpResp.getOutputStream().write(bytes);
+ httpResp.setContentLength(bytes.length);
+ httpResp.getOutputStream().flush();
+ } catch (IOException e) {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_DISPLAYING_CACHAIN_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAYING_CACHAIN_ERROR"));
+ }
+ }
+
+ private void displayChain(String op,
+ IArgBlock args,
+ HttpServletRequest httpReq,
+ HttpServletResponse httpResp,
+ CMSRequest cmsReq)
+ throws EBaseException {
+
+ CertificateChain certChain =
+ ((ICertAuthority) mAuthority).getCACertChain();
+
+ if (certChain == null) {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CA_CHAIN_NOT_AVAILABLE"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CA_CHAIN_NOT_AVAILABLE"));
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ try {
+ form = getTemplate(mFormPath, httpReq, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ String displayFormat = null;
+
+ if (op.equals("displayIND")) {
+ displayFormat = "individual";
+ } else {
+ try {
+ displayFormat = args.getValueAsString("displayFormat");
+ } catch (EBaseException e) {
+ displayFormat = "chain";
+ }
+ }
+
+ header.addStringValue("displayFormat", displayFormat);
+
+ if (displayFormat.equals("chain")) {
+ String subjectdn = null;
+ byte[] bytes = null;
+
+ try {
+ subjectdn =
+ certChain.getFirstCertificate().getSubjectDN().toString();
+ ByteArrayOutputStream encoded = new ByteArrayOutputStream();
+
+ certChain.encode(encoded);
+ bytes = encoded.toByteArray();
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_ENCODING_CA_CHAIN_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_ENCODING_CA_CHAIN_ERROR"));
+ }
+
+ String chainBase64 = getBase64(bytes);
+
+ header.addStringValue("subjectdn", subjectdn);
+ header.addStringValue("chainBase64", chainBase64);
+ } else {
+ try {
+ X509Certificate[] certs = certChain.getChain();
+
+ header.addIntegerValue("length", certs.length);
+ locale[0] = getLocale(httpReq);
+ for (int i = 0; i < certs.length; i++) {
+ byte[] bytes = null;
+
+ try {
+ bytes = certs[i].getEncoded();
+ } catch (CertificateEncodingException e) {
+ throw new IOException("Internal Error");
+ }
+ String subjectdn = certs[i].getSubjectDN().toString();
+ String finger = null;
+ try {
+ finger = CMS.getFingerPrints(certs[i]);
+ } catch (Exception e) {
+ throw new IOException("Internal Error");
+ }
+
+ ICertPrettyPrint certDetails = CMS.getCertPrettyPrint(certs[i]);
+
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addStringValue("fingerprints", finger);
+ rarg.addStringValue("subjectdn", subjectdn);
+ rarg.addStringValue("base64", getBase64(bytes));
+ rarg.addStringValue("certDetails",
+ certDetails.toString(locale[0]));
+ argSet.addRepeatRecord(rarg);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_DISPLAYING_CACHAIN_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAYING_CACHAIN_ERROR"));
+ }
+ }
+
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ }
+
+ }
+
+ /**
+ * gets base 64 encoded cert
+ */
+ private String getBase64(byte[] certBytes) {
+ String certBase64 = CMS.BtoA(certBytes);
+
+ return certBase64;
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/GetCRL.java b/base/server/cms/src/com/netscape/cms/servlet/cert/GetCRL.java
new file mode 100644
index 000000000..3ea2297db
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/GetCRL.java
@@ -0,0 +1,479 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CRLException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X509CRLImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.ICRLPrettyPrint;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Retrieve CRL for a Certificate Authority
+ *
+ * @version $Revision$, $Date$
+ */
+public class GetCRL extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7132206924070383013L;
+ private final static String TPL_FILE = "displayCRL.template";
+ private String mFormPath = null;
+
+ public GetCRL() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param cmsReq the object holding the request and response information
+ * @see DisplayCRL#process
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ // Construct an ArgBlock
+ IArgBlock args = cmsReq.getHttpParams();
+
+ if (!(mAuthority instanceof ICertificateAuthority)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CA_FROM_RA_NOT_IMP"));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_NOT_YET_IMPLEMENTED")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ CMS.debug("**** mFormPath before getTemplate = " + mFormPath);
+ try {
+ form = getTemplate(mFormPath, httpReq, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ // Get the operation code
+ String op = null;
+ String crlId = null;
+
+ op = args.getValueAsString("op", null);
+ crlId = args.getValueAsString("crlIssuingPoint", null);
+ if (op == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_NO_OPTIONS_SELECTED"));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_NO_OPTIONS_SELECTED")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+ if (crlId == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_NO_CRL_ISSUING_POINT"));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_NO_CRL_SELECTED")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ ICRLIssuingPointRecord crlRecord = null;
+ ICertificateAuthority ca = (ICertificateAuthority) mAuthority;
+ ICRLIssuingPoint crlIP = null;
+ if (ca != null)
+ crlIP = ca.getCRLIssuingPoint(crlId);
+
+ try {
+ crlRecord = ca.getCRLRepository().readCRLIssuingPointRecord(crlId);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_NO_CRL_ISSUING_POINT_FOUND", crlId));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CRL_NOT_FOUND")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+ if (crlRecord == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CRL_NOT_YET_UPDATED_1", crlId));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CRL_NOT_UPDATED")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ header.addStringValue("crlIssuingPoint", crlId);
+ header.addStringValue("crlNumber", crlRecord.getCRLNumber().toString());
+ long lCRLSize = crlRecord.getCRLSize().longValue();
+
+ header.addLongValue("crlSize", lCRLSize);
+ if (crlIP != null) {
+ header.addStringValue("crlDescription", crlIP.getDescription());
+ }
+
+ String crlDisplayType = args.getValueAsString("crlDisplayType", null);
+ if (crlDisplayType != null) {
+ header.addStringValue("crlDisplayType", crlDisplayType);
+ }
+
+ if ((op.equals("checkCRLcache") ||
+ (op.equals("displayCRL") && crlDisplayType != null && crlDisplayType.equals("cachedCRL"))) &&
+ (crlIP == null || (!crlIP.isCRLCacheEnabled()) || crlIP.isCRLCacheEmpty())) {
+ cmsReq.setError(
+ CMS.getUserMessage(
+ ((crlIP != null && crlIP.isCRLCacheEnabled() && crlIP.isCRLCacheEmpty()) ?
+ "CMS_GW_CRL_CACHE_IS_EMPTY" : "CMS_GW_CRL_CACHE_IS_NOT_ENABLED"), crlId));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ byte[] crlbytes = null;
+
+ if (op.equals("importDeltaCRL") || op.equals("getDeltaCRL") ||
+ (op.equals("displayCRL") && crlDisplayType != null &&
+ crlDisplayType.equals("deltaCRL"))) {
+ crlbytes = crlRecord.getDeltaCRL();
+ } else if (op.equals("importCRL") || op.equals("getCRL") ||
+ op.equals("checkCRL") ||
+ (op.equals("displayCRL") &&
+ crlDisplayType != null &&
+ (crlDisplayType.equals("entireCRL") ||
+ crlDisplayType.equals("crlHeader") ||
+ crlDisplayType.equals("base64Encoded")))) {
+ crlbytes = crlRecord.getCRL();
+ }
+
+ if (crlbytes == null && (!op.equals("checkCRLcache")) &&
+ (!(op.equals("displayCRL") && crlDisplayType != null &&
+ crlDisplayType.equals("cachedCRL")))) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CRL_NOT_YET_UPDATED_1", crlId));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CRL_NOT_UPDATED")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+ byte[] bytes = crlbytes;
+
+ X509CRLImpl crl = null;
+
+ if (op.equals("checkCRL") || op.equals("importCRL") ||
+ op.equals("importDeltaCRL") ||
+ (op.equals("displayCRL") && crlDisplayType != null &&
+ (crlDisplayType.equals("entireCRL") ||
+ crlDisplayType.equals("crlHeader") ||
+ crlDisplayType.equals("base64Encoded") ||
+ crlDisplayType.equals("deltaCRL")))) {
+ try {
+ if (op.equals("displayCRL") && crlDisplayType != null &&
+ crlDisplayType.equals("crlHeader")) {
+ crl = new X509CRLImpl(crlbytes, false);
+ } else {
+ crl = new X509CRLImpl(crlbytes);
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_FAILED_DECODE_CRL_1", e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DECODE_CRL_FAILED")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+ if ((op.equals("importDeltaCRL") || (op.equals("displayCRL") &&
+ crlDisplayType != null && crlDisplayType.equals("deltaCRL"))) &&
+ ((!(crlIP != null && crlIP.isThisCurrentDeltaCRL(crl))) &&
+ (crlRecord.getCRLNumber() == null ||
+ crlRecord.getDeltaCRLNumber() == null ||
+ crlRecord.getDeltaCRLNumber().compareTo(crlRecord.getCRLNumber()) < 0 ||
+ crlRecord.getDeltaCRLSize() == null ||
+ crlRecord.getDeltaCRLSize().longValue() == -1))) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_NO_DELTA_CRL_1"));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CRL_NOT_UPDATED")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+ }
+
+ String mimeType = "application/x-pkcs7-crl";
+
+ if (op.equals("checkCRLcache") || op.equals("checkCRL") || op.equals("displayCRL")) {
+ header.addStringValue("toDo", op);
+ String certSerialNumber = args.getValueAsString("certSerialNumber", "");
+
+ header.addStringValue("certSerialNumber", certSerialNumber);
+ if (certSerialNumber.startsWith("0x")) {
+ certSerialNumber = hexToDecimal(certSerialNumber);
+ }
+
+ if (op.equals("checkCRLcache")) {
+ if (crlIP.getRevocationDateFromCache(
+ new BigInteger(certSerialNumber), false, false) != null) {
+ header.addBooleanValue("isOnCRL", true);
+ } else {
+ header.addBooleanValue("isOnCRL", false);
+ }
+ }
+
+ if (op.equals("checkCRL")) {
+ header.addBooleanValue("isOnCRL",
+ crl.isRevoked(new BigInteger(certSerialNumber)));
+ }
+
+ if (op.equals("displayCRL")) {
+ if (crlDisplayType.equals("entireCRL") || crlDisplayType.equals("cachedCRL")) {
+ ICRLPrettyPrint crlDetails = (crlDisplayType.equals("entireCRL")) ?
+ CMS.getCRLPrettyPrint(crl) :
+ CMS.getCRLCachePrettyPrint(crlIP);
+ String pageStart = args.getValueAsString("pageStart", null);
+ String pageSize = args.getValueAsString("pageSize", null);
+
+ if (pageStart != null && pageSize != null) {
+ long lPageStart = 0L;
+ long lPageSize = 0L;
+ try {
+ lPageStart = new Long(pageStart).longValue();
+ } catch (NumberFormatException e) {
+ }
+ try {
+ lPageSize = new Long(pageSize).longValue();
+ } catch (NumberFormatException e) {
+ }
+
+ if (lPageStart < 1)
+ lPageStart = 1;
+ if (lPageSize < 1)
+ lPageSize = 10;
+
+ header.addStringValue("crlPrettyPrint",
+ crlDetails.toString(locale[0],
+ lCRLSize, lPageStart, lPageSize));
+ header.addLongValue("pageStart", lPageStart);
+ header.addLongValue("pageSize", lPageSize);
+ } else {
+ header.addStringValue(
+ "crlPrettyPrint", crlDetails.toString(locale[0]));
+ }
+ } else if (crlDisplayType.equals("crlHeader")) {
+ ICRLPrettyPrint crlDetails = CMS.getCRLPrettyPrint(crl);
+
+ header.addStringValue(
+ "crlPrettyPrint", crlDetails.toString(locale[0], lCRLSize, 0, 0));
+ } else if (crlDisplayType.equals("base64Encoded")) {
+ try {
+ byte[] ba = crl.getEncoded();
+ String crlBase64Encoded = Utils.base64encode(ba);
+ int length = crlBase64Encoded.length();
+ int i = 0;
+ int j = 0;
+ int n = 1;
+
+ while (i < length) {
+ int k = crlBase64Encoded.indexOf('\n', i);
+ if (k < 0)
+ break;
+
+ if (n < 100) {
+ n++;
+ i = k + 1;
+ } else {
+ n = 1;
+ IArgBlock rarg = CMS.createArgBlock();
+ rarg.addStringValue("crlBase64Encoded", crlBase64Encoded.substring(j, k));
+ i = k + 1;
+ j = i;
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ if (j < length) {
+ IArgBlock rarg = CMS.createArgBlock();
+ rarg.addStringValue("crlBase64Encoded", crlBase64Encoded.substring(j, length));
+ argSet.addRepeatRecord(rarg);
+ }
+ } catch (CRLException e) {
+ }
+ } else if (crlDisplayType.equals("deltaCRL")) {
+ header.addIntegerValue("deltaCRLSize",
+ crl.getNumberOfRevokedCertificates());
+
+ ICRLPrettyPrint crlDetails = CMS.getCRLPrettyPrint(crl);
+
+ header.addStringValue(
+ "crlPrettyPrint", crlDetails.toString(locale[0], 0, 0, 0));
+
+ try {
+ byte[] ba = crl.getEncoded();
+ String crlBase64Encoded = Utils.base64encode(ba);
+ int length = crlBase64Encoded.length();
+ int i = 0;
+ int j = 0;
+ int n = 1;
+
+ while (i < length) {
+ int k = crlBase64Encoded.indexOf('\n', i);
+ if (k < 0)
+ break;
+ if (n < 100) {
+ n++;
+ i = k + 1;
+ } else {
+ n = 1;
+ IArgBlock rarg = CMS.createArgBlock();
+ rarg.addStringValue("crlBase64Encoded", crlBase64Encoded.substring(j, k));
+ i = k + 1;
+ j = i;
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ if (j < length) {
+ IArgBlock rarg = CMS.createArgBlock();
+ rarg.addStringValue("crlBase64Encoded", crlBase64Encoded.substring(j, length));
+ argSet.addRepeatRecord(rarg);
+ }
+ } catch (CRLException e) {
+ }
+ }
+ }
+
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ }
+ return;
+ } else if (op.equals("importCRL") || op.equals("importDeltaCRL")) {
+ if (clientIsMSIE(httpReq))
+ mimeType = "application/pkix-crl";
+ else
+ mimeType = "application/x-pkcs7-crl";
+ } else if (op.equals("getCRL")) {
+ mimeType = "application/octet-stream";
+ httpResp.setHeader("Content-disposition",
+ "attachment; filename=" + crlId + ".crl");
+ } else if (op.equals("getDeltaCRL")) {
+ mimeType = "application/octet-stream";
+ httpResp.setHeader("Content-disposition",
+ "attachment; filename=delta-" + crlId + ".crl");
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_OPTIONS_SELECTED"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_OPTIONS_SELECTED"));
+ }
+
+ try {
+ // if (clientIsMSIE(httpReq) && op.equals("getCRL"))
+ // httpResp.setHeader("Content-disposition",
+ // "attachment; filename=getCRL.crl");
+ httpResp.setContentType(mimeType);
+ httpResp.setContentLength(bytes.length);
+ httpResp.getOutputStream().write(bytes);
+ httpResp.getOutputStream().flush();
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_DISPLAYING_CRLINFO"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAYING_CRLINFO_ERROR"));
+ }
+ // cmsReq.setResult(null);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+ private String hexToDecimal(String hex) {
+ String newHex = hex.substring(2);
+ BigInteger bi = new BigInteger(newHex, 16);
+
+ return bi.toString();
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/GetCertFromRequest.java b/base/server/cms/src/com/netscape/cms/servlet/cert/GetCertFromRequest.java
new file mode 100644
index 000000000..af8b3cc02
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/GetCertFromRequest.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.math.BigInteger;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+import netscape.security.extensions.NSCertTypeExtension;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.Extension;
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+
+/**
+ * Gets a issued certificate from a request id.
+ *
+ * @version $Revision$, $Date$
+ */
+public class GetCertFromRequest extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5310646832256611066L;
+ private final static String PROP_IMPORT = "importCert";
+ protected static final String GET_CERT_FROM_REQUEST_TEMPLATE = "ImportCert.template";
+ protected static final String DISPLAY_CERT_FROM_REQUEST_TEMPLATE = "displayCertFromRequest.template";
+
+ protected static final String REQUEST_ID = "requestId";
+ protected static final String CERT_TYPE = "certtype";
+
+ protected String mCertFrReqSuccessTemplate = null;
+ protected ICMSTemplateFiller mCertFrReqFiller = null;
+
+ protected IRequestQueue mQueue = null;
+ protected boolean mImportCert = true;
+
+ public GetCertFromRequest() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template files
+ * "displayCertFromRequest.template" and "ImportCert.template"
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ mQueue = mAuthority.getRequestQueue();
+ try {
+ String tmp = sc.getInitParameter(
+ PROP_IMPORT);
+
+ if (tmp != null && tmp.trim().equalsIgnoreCase("false"))
+ mImportCert = false;
+
+ String defTemplate = null;
+
+ if (mImportCert)
+ defTemplate = GET_CERT_FROM_REQUEST_TEMPLATE;
+ else
+ defTemplate = DISPLAY_CERT_FROM_REQUEST_TEMPLATE;
+ if (mAuthority instanceof IRegistrationAuthority)
+ defTemplate = "/ra/" + defTemplate;
+ else
+ defTemplate = "/ca/" + defTemplate;
+ mCertFrReqSuccessTemplate = sc.getInitParameter(
+ PROP_SUCCESS_TEMPLATE);
+ if (mCertFrReqSuccessTemplate == null)
+ mCertFrReqSuccessTemplate = defTemplate;
+ String fillername =
+ sc.getInitParameter(PROP_SUCCESS_TEMPLATE_FILLER);
+
+ if (fillername != null) {
+ ICMSTemplateFiller filler = newFillerObject(fillername);
+
+ if (filler != null)
+ mCertFrReqFiller = filler;
+ } else {
+ mCertFrReqFiller = new CertFrRequestFiller();
+ }
+ } catch (Exception e) {
+ // should never happen.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_IMP_INIT_SERV_ERR", e.toString(),
+ mId));
+ }
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param requestId The request ID to search on
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ IArgBlock httpParams = cmsReq.getHttpParams();
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ String requestId = httpParams.getValueAsString(REQUEST_ID, null);
+
+ if (requestId == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_NO_REQUEST_ID_PROVIDED"));
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_REQUEST_ID_PROVIDED"));
+ }
+ // check if request Id is valid.
+ try {
+ new BigInteger(requestId);
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_REQ_ID_FORMAT", requestId));
+ throw new EBaseException(
+ CMS.getUserMessage(getLocale(httpReq), "CMS_BASE_INVALID_NUMBER_FORMAT_1", requestId));
+ }
+
+ IRequest r = mQueue.findRequest(new RequestId(requestId));
+
+ if (r == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_REQUEST_ID_NOT_FOUND", requestId));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_REQUEST_ID_NOT_FOUND", requestId));
+ }
+
+ if (authToken != null) {
+ //if RA, group and requestOwner must match
+ String group = authToken.getInString("group");
+ if ((group != null) && (group != "") &&
+ group.equals("Registration Manager Agents")) {
+ boolean groupMatched = false;
+ String reqOwner = r.getRequestOwner();
+ if (reqOwner != null) {
+ CMS.debug("GetCertFromRequest process: req owner=" + reqOwner);
+ if (reqOwner.equals(group))
+ groupMatched = true;
+ }
+ if (groupMatched == false) {
+ CMS.debug("RA group unmatched");
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_REQUEST_ID_NOT_FOUND", requestId));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_REQUEST_ID_NOT_FOUND", requestId));
+ }
+ }
+ }
+
+ if (!((r.getRequestType().equals(IRequest.ENROLLMENT_REQUEST)) ||
+ (r.getRequestType().equals(IRequest.RENEWAL_REQUEST)))) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_REQUEST_NOT_ENROLLMENT_1", requestId));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_REQUEST_NOT_ENROLLMENT", requestId));
+ }
+ RequestStatus status = r.getRequestStatus();
+
+ if (!status.equals(RequestStatus.COMPLETE)) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_REQUEST_NOT_COMPLETED_1", requestId));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_REQUEST_NOT_COMPLETED", requestId));
+ }
+ Integer result = r.getExtDataInInteger(IRequest.RESULT);
+
+ if (result != null && !result.equals(IRequest.RES_SUCCESS)) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_REQUEST_HAD_ERROR_1", requestId));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_REQUEST_HAD_ERROR", requestId));
+ }
+ Object o = r.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ if (r.getExtDataInString("profile") != null) {
+ // handle profile-based request
+ X509CertImpl cert = r.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
+ X509CertImpl certs[] = new X509CertImpl[1];
+
+ certs[0] = cert;
+ o = certs;
+ }
+ if (o == null || !(o instanceof X509CertImpl[])) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_REQUEST_HAD_NO_CERTS_1", requestId));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_REQUEST_HAD_NO_CERTS", requestId));
+ }
+ if (o instanceof X509CertImpl[]) {
+ X509CertImpl[] certs = (X509CertImpl[]) o;
+
+ if (certs == null || certs.length == 0 || certs[0] == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_REQUEST_HAD_NO_CERTS_1", requestId));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_REQUEST_HAD_NO_CERTS", requestId));
+ }
+
+ // for importsCert to get the crmf_reqid.
+ cmsReq.setIRequest(r);
+
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+
+ if (mImportCert &&
+ checkImportCertToNav(cmsReq.getHttpResp(), httpParams, certs[0])) {
+ return;
+ }
+ try {
+ cmsReq.setResult(certs);
+ renderTemplate(cmsReq, mCertFrReqSuccessTemplate, mCertFrReqFiller);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGE_ERROR_DISPLAY_TEMPLATE_1",
+ mCertFrReqSuccessTemplate, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+ return;
+ }
+}
+
+class CertFrRequestFiller extends ImportCertsTemplateFiller {
+ public CertFrRequestFiller() {
+ }
+
+ public CMSTemplateParams getTemplateParams(
+ CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e)
+ throws Exception {
+ CMSTemplateParams tparams =
+ super.getTemplateParams(cmsReq, authority, locale, e);
+ String reqId = cmsReq.getHttpParams().getValueAsString(
+ GetCertFromRequest.REQUEST_ID);
+
+ tparams.getHeader().addStringValue(GetCertFromRequest.REQUEST_ID, reqId);
+
+ if (reqId != null) {
+ IRequest r = authority.getRequestQueue().findRequest(new RequestId(reqId));
+ if (r != null) {
+ boolean noCertImport = true;
+ String certType = r.getExtDataInString(IRequest.HTTP_PARAMS, IRequest.CERT_TYPE);
+
+ if (certType != null && certType.equals(IRequest.CLIENT_CERT)) {
+ noCertImport = false;
+ }
+ tparams.getHeader().addBooleanValue("noCertImport", noCertImport);
+
+ X509CertImpl[] certs = r.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ if (certs != null) {
+ X509CertInfo info = (X509CertInfo) certs[0].get(X509CertImpl.NAME + "." + X509CertImpl.INFO);
+ CertificateExtensions extensions = (CertificateExtensions) info.get(X509CertInfo.EXTENSIONS);
+
+ tparams.getHeader().addStringValue(GetCertFromRequest.CERT_TYPE, "x509");
+
+ boolean emailCert = false;
+
+ if (extensions != null) {
+ for (int i = 0; i < extensions.size(); i++) {
+ Extension ext = extensions.elementAt(i);
+
+ if (ext instanceof NSCertTypeExtension) {
+ NSCertTypeExtension type = (NSCertTypeExtension) ext;
+
+ if (((Boolean) type.get(NSCertTypeExtension.EMAIL)).booleanValue())
+ emailCert = true;
+ }
+ if (ext instanceof KeyUsageExtension) {
+ KeyUsageExtension usage =
+ (KeyUsageExtension) ext;
+
+ try {
+ if (((Boolean) usage.get(KeyUsageExtension.DIGITAL_SIGNATURE)).booleanValue() ||
+ ((Boolean) usage.get(KeyUsageExtension.DATA_ENCIPHERMENT)).booleanValue())
+ emailCert = true;
+ } catch (ArrayIndexOutOfBoundsException e0) {
+ // bug356108:
+ // In case there is only DIGITAL_SIGNATURE,
+ // don't report error
+ }
+ }
+ }
+ }
+ tparams.getHeader().addBooleanValue("emailCert", emailCert);
+ }
+ }
+ }
+
+ return tparams;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/GetEnableStatus.java b/base/server/cms/src/com/netscape/cms/servlet/cert/GetEnableStatus.java
new file mode 100644
index 000000000..0c650cf69
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/GetEnableStatus.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.cms.authentication.HashAuthentication;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Servlet to get the enrollment status, enable or disable.
+ *
+ * @version $Revision$, $Date$
+ */
+public class GetEnableStatus extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3879769989681379834L;
+ private final static String TPL_FILE = "userEnroll.template";
+ private String mFormPath = null;
+
+ public GetEnableStatus() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // coming from agent
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ protected CMSRequest newCMSRequest() {
+ return new CMSRequest();
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ String reqHost = httpReq.getRemoteHost();
+
+ if (!(mAuthority instanceof IRegistrationAuthority)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CA_FROM_RA_NOT_IMP"));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_NOT_YET_IMPLEMENTED")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, httpReq, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE",
+ mFormPath, e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String val = configStore.getString("hashDirEnrollment.name");
+ IAuthSubsystem authSS = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ IAuthManager authMgr = authSS.get(val);
+ HashAuthentication mgr = (HashAuthentication) authMgr;
+ long timeout = HashAuthentication.DEFAULT_TIMEOUT / 1000;
+
+ header.addStringValue("timeout", "" + timeout);
+ header.addStringValue("reqHost", reqHost);
+
+ for (Enumeration<String> hosts = mgr.getHosts(); hosts.hasMoreElements();) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addStringValue("hosts", hosts.nextElement());
+ argSet.addRepeatRecord(rarg);
+ }
+
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/GetInfo.java b/base/server/cms/src/com/netscape/cms/servlet/cert/GetInfo.java
new file mode 100644
index 000000000..e82b2046f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/GetInfo.java
@@ -0,0 +1,374 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.AlgorithmId;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+import com.netscape.certsrv.dbs.crldb.ICRLRepository;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Get detailed information about CA CRL processing
+ *
+ * @version $Revision$, $Date$
+ */
+public class GetInfo extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1909881831730252799L;
+
+ private ICertificateAuthority mCA = null;
+
+ /**
+ * Constructs GetInfo servlet.
+ */
+ public GetInfo() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+
+ if (mAuthority instanceof ICertificateAuthority)
+ mCA = (ICertificateAuthority) mAuthority;
+
+ // override success to do output our own template.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * XXX Process the HTTP request.
+ * <ul>
+ * <li>http.param template filename of template to use to render the result
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ EBaseException error = null;
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ String template = req.getParameter("template");
+ String formFile = "";
+
+ /*
+ for (int i = 0; ((template != null) && (i < template.length())); i++) {
+ char c = template.charAt(i);
+ if (!Character.isLetterOrDigit(c) && c != '_' && c != '-') {
+ template = null;
+ break;
+ }
+ }
+ */
+
+ if (template != null) {
+ formFile = template + ".template";
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE_1"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ CMS.debug("*** formFile = " + formFile);
+ try {
+ form = getTemplate(formFile, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", formFile, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ try {
+ process(argSet, header, req, resp, locale[0]);
+ } catch (EBaseException e) {
+ error = e;
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ HttpServletRequest req,
+ HttpServletResponse resp,
+ Locale locale)
+ throws EBaseException {
+ if (mCA != null) {
+ String crlIssuingPoints = "";
+ String crlNumbers = "";
+ String deltaNumbers = "";
+ String crlSizes = "";
+ String deltaSizes = "";
+ String crlDescriptions = "";
+ StringBuffer crlSplits = new StringBuffer();
+ String recentChanges = "";
+ String crlTesting = "";
+ boolean isDeltaCRLEnabled = false;
+
+ String masterHost = CMS.getConfigStore().getString("master.ca.agent.host", "");
+ String masterPort = CMS.getConfigStore().getString("master.ca.agent.port", "");
+
+ if (masterHost != null && masterHost.length() > 0 &&
+ masterPort != null && masterPort.length() > 0) {
+
+ ICRLRepository crlRepository = mCA.getCRLRepository();
+
+ Vector<String> ipNames = crlRepository.getIssuingPointsNames();
+ for (int i = 0; i < ipNames.size(); i++) {
+ String ipName = ipNames.elementAt(i);
+ ICRLIssuingPointRecord crlRecord = null;
+ try {
+ crlRecord = crlRepository.readCRLIssuingPointRecord(ipName);
+ } catch (Exception e) {
+ }
+ if (crlRecord != null) {
+ if (crlIssuingPoints.length() > 0)
+ crlIssuingPoints += "+";
+ crlIssuingPoints += ipName;
+
+ BigInteger crlNumber = crlRecord.getCRLNumber();
+ if (crlNumbers.length() > 0)
+ crlNumbers += "+";
+ if (crlNumber != null)
+ crlNumbers += crlNumber.toString();
+
+ if (crlSizes.length() > 0)
+ crlSizes += "+";
+ crlSizes += ((crlRecord.getCRLSize() != null) ?
+ crlRecord.getCRLSize().toString() : "-1");
+
+ if (deltaSizes.length() > 0)
+ deltaSizes += "+";
+ long dSize = -1;
+ if (crlRecord.getDeltaCRLSize() != null)
+ dSize = crlRecord.getDeltaCRLSize().longValue();
+ deltaSizes += dSize;
+
+ BigInteger deltaNumber = crlRecord.getDeltaCRLNumber();
+ if (deltaNumbers.length() > 0)
+ deltaNumbers += "+";
+ if (deltaNumber != null && dSize > -1) {
+ deltaNumbers += deltaNumber.toString();
+ isDeltaCRLEnabled |= true;
+ } else {
+ deltaNumbers += "0";
+ }
+
+ if (recentChanges.length() > 0)
+ recentChanges += "+";
+ recentChanges += "-, -, -";
+
+ if (crlTesting.length() > 0)
+ crlTesting += "+";
+ crlTesting += "0";
+ }
+ }
+
+ } else {
+ Enumeration<ICRLIssuingPoint> ips = mCA.getCRLIssuingPoints();
+
+ while (ips.hasMoreElements()) {
+ ICRLIssuingPoint ip = ips.nextElement();
+
+ if (ip.isCRLIssuingPointEnabled()) {
+ if (crlIssuingPoints.length() > 0)
+ crlIssuingPoints += "+";
+ crlIssuingPoints += ip.getId();
+
+ BigInteger crlNumber = ip.getCRLNumber();
+ if (crlNumbers.length() > 0)
+ crlNumbers += "+";
+ if (crlNumber != null)
+ crlNumbers += crlNumber.toString();
+
+ BigInteger deltaNumber = ip.getDeltaCRLNumber();
+ if (deltaNumbers.length() > 0)
+ deltaNumbers += "+";
+ if (deltaNumber != null)
+ deltaNumbers += deltaNumber.toString();
+
+ if (crlSizes.length() > 0)
+ crlSizes += "+";
+ crlSizes += ip.getCRLSize();
+
+ if (deltaSizes.length() > 0)
+ deltaSizes += "+";
+ deltaSizes += ip.getDeltaCRLSize();
+
+ if (crlDescriptions.length() > 0)
+ crlDescriptions += "+";
+ crlDescriptions += ip.getDescription();
+
+ if (recentChanges.length() > 0)
+ recentChanges += "+";
+ if (ip.isCRLUpdateInProgress() == ICRLIssuingPoint.CRL_PUBLISHING_STARTED) {
+ recentChanges += "Publishing CRL #" + ip.getCRLNumber();
+ } else if (ip.isCRLUpdateInProgress() == ICRLIssuingPoint.CRL_UPDATE_STARTED) {
+ recentChanges += "Creating CRL #" + ip.getNextCRLNumber();
+ } else { // ip.CRL_UPDATE_DONE
+ recentChanges += ip.getNumberOfRecentlyRevokedCerts() + ", " +
+ ip.getNumberOfRecentlyUnrevokedCerts() + ", " +
+ ip.getNumberOfRecentlyExpiredCerts();
+ }
+ isDeltaCRLEnabled |= ip.isDeltaCRLEnabled();
+
+ if (crlSplits.length() > 0)
+ crlSplits.append("+");
+ Vector<Long> splits = ip.getSplitTimes();
+
+ for (int i = 0; i < splits.size(); i++) {
+ crlSplits.append(splits.elementAt(i));
+ if (i + 1 < splits.size())
+ crlSplits.append(",");
+ }
+
+ if (crlTesting.length() > 0)
+ crlTesting += "+";
+ crlTesting += ((ip.isCRLCacheTestingEnabled()) ? "1" : "0");
+ }
+ }
+
+ }
+
+ header.addStringValue("crlIssuingPoints", crlIssuingPoints);
+ header.addStringValue("crlDescriptions", crlDescriptions);
+ header.addStringValue("crlNumbers", crlNumbers);
+ header.addStringValue("deltaNumbers", deltaNumbers);
+ header.addStringValue("crlSizes", crlSizes);
+ header.addStringValue("deltaSizes", deltaSizes);
+ header.addStringValue("crlSplits", crlSplits.toString());
+ header.addStringValue("crlTesting", crlTesting);
+ header.addBooleanValue("isDeltaCRLEnabled", isDeltaCRLEnabled);
+
+ header.addStringValue("master_host", masterHost);
+ header.addStringValue("master_port", masterPort);
+
+ header.addStringValue("masterCRLIssuingPoint", ICertificateAuthority.PROP_MASTER_CRL);
+ ICRLIssuingPoint ip0 = mCA.getCRLIssuingPoint(ICertificateAuthority.PROP_MASTER_CRL);
+
+ if (ip0 != null) {
+ header.addStringValue("defaultAlgorithm", ip0.getSigningAlgorithm());
+ }
+
+ if (recentChanges.length() > 0)
+ header.addStringValue("recentChanges", recentChanges);
+
+ String validAlgorithms = null;
+ String[] allAlgorithms = mCA.getCASigningAlgorithms();
+
+ if (allAlgorithms == null) {
+ CMS.debug("GetInfo: signing algorithms set to All algorithms");
+ allAlgorithms = AlgorithmId.ALL_SIGNING_ALGORITHMS;
+ }
+
+ for (int i = 0; i < allAlgorithms.length; i++) {
+ if (i > 0) {
+ validAlgorithms += "+" + allAlgorithms[i];
+ } else {
+ validAlgorithms = allAlgorithms[i];
+ }
+ }
+ if (validAlgorithms != null)
+ header.addStringValue("validAlgorithms", validAlgorithms);
+ }
+
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/HashEnrollServlet.java b/base/server/cms/src/com/netscape/cms/servlet/cert/HashEnrollServlet.java
new file mode 100644
index 000000000..a6e9d832e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/HashEnrollServlet.java
@@ -0,0 +1,1234 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.Extension;
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.pkix.crmf.CertReqMsg;
+import org.mozilla.jss.pkix.crmf.CertRequest;
+import org.mozilla.jss.pkix.crmf.CertTemplate;
+import org.mozilla.jss.pkix.primitive.Name;
+import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertRecordList;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.authentication.HashAuthentication;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+
+/**
+ * performs face-to-face enrollment.
+ *
+ * @version $Revision$, $Date$
+ */
+public class HashEnrollServlet extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5532936020515258333L;
+
+ public final static String ADMIN_ENROLL_SERVLET_ID = "adminEnroll";
+
+ // enrollment templates.
+ public static final String ENROLL_SUCCESS_TEMPLATE = "/ra/HashEnrollSuccess.template";
+
+ // http params
+ public static final String OLD_CERT_TYPE = "csrCertType";
+ public static final String CERT_TYPE = "certType";
+ // same as in ConfigConstant.java
+ public static final String REQUEST_FORMAT = "reqFormat";
+ public static final String REQUEST_CONTENT = "requestContent";
+ public static final String SUBJECT_KEYGEN_INFO = "subjectKeyGenInfo";
+ public static final String CRMF_REQUEST = "CRMFRequest";
+ public static final String SUBJECT_NAME = "subject";
+ public static final String CRMF_REQID = "crmfReqId";
+ public static final String CHALLENGE_PASSWORD = "challengePhrase";
+
+ private static final String CERT_AUTH_DUAL = "dual";
+ private static final String CERT_AUTH_ENCRYPTION = "encryption";
+ private static final String CERT_AUTH_SINGLE = "single";
+ private static final String CLIENT_ISSUER = "clientIssuer";
+ public static final String TPL_ERROR_FILE = "/ra/GenErrorHashDirEnroll.template";
+
+ private String mEnrollSuccessTemplate = null;
+ private ICMSTemplateFiller mEnrollSuccessFiller = new ImportCertsTemplateFiller();
+
+ ICertificateAuthority mCa = null;
+ ICertificateRepository mRepository = null;
+
+ public HashEnrollServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success template to allow direct import of keygen certs.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ try {
+ mEnrollSuccessTemplate = sc.getInitParameter(
+ CMSServlet.PROP_SUCCESS_TEMPLATE);
+ if (mEnrollSuccessTemplate == null)
+ mEnrollSuccessTemplate = ENROLL_SUCCESS_TEMPLATE;
+ String fillername =
+ sc.getInitParameter(PROP_SUCCESS_TEMPLATE_FILLER);
+
+ if (fillername != null) {
+ ICMSTemplateFiller filler = newFillerObject(fillername);
+
+ if (filler != null)
+ mEnrollSuccessFiller = filler;
+ }
+
+ // cfu
+ mCa = (ICertificateAuthority) CMS.getSubsystem("ca");
+
+ init_testbed_hack(mConfig);
+ } catch (Exception e) {
+ // this should never happen.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_IMP_INIT_SERV_ERR", e.toString(), mId));
+ }
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ IArgBlock httpParams = cmsReq.getHttpParams();
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ String certType = null;
+
+ String reqHost = httpReq.getRemoteHost();
+
+ String host = httpParams.getValueAsString("hostname", null);
+
+ if (host == null || !host.equals(reqHost)) {
+ printError(cmsReq, "0");
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String val = configStore.getString("hashDirEnrollment.name");
+ IAuthSubsystem authSS = (IAuthSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ IAuthManager authMgr = authSS.get(val);
+ HashAuthentication mgr = (HashAuthentication) authMgr;
+
+ Date date = new Date();
+ long currTime = date.getTime();
+ long timeout = mgr.getTimeout(reqHost);
+ long lastlogin = mgr.getLastLogin(reqHost);
+ long diff = currTime - lastlogin;
+
+ boolean enable = mgr.isEnable(reqHost);
+
+ if (!enable) {
+ printError(cmsReq, "0");
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+ if (lastlogin == 0)
+ mgr.setLastLogin(reqHost, currTime);
+ else if (diff > timeout) {
+ mgr.disable(reqHost);
+ printError(cmsReq, "2");
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+ mgr.setLastLogin(reqHost, currTime);
+
+ // support Enterprise 3.5.1 server where CERT_TYPE=csrCertType
+ // instead of certType
+ certType = httpParams.getValueAsString(OLD_CERT_TYPE, null);
+ if (certType == null) {
+ certType = httpParams.getValueAsString(CERT_TYPE, "client");
+ } else {
+ ;
+ }
+
+ processX509(cmsReq);
+ }
+
+ private void printError(CMSRequest cmsReq, String errorCode)
+ throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ header.addStringValue("authority", "Registration Manager");
+ header.addStringValue("errorCode", errorCode);
+ String formPath = TPL_ERROR_FILE;
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(formPath, httpReq, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", formPath, e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM",
+ e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ }
+ }
+
+ protected void processX509(CMSRequest cmsReq)
+ throws EBaseException {
+ IArgBlock httpParams = cmsReq.getHttpParams();
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+
+ // create enrollment request in request queue.
+ IRequest req = mRequestQueue.newRequest(IRequest.ENROLLMENT_REQUEST);
+
+ /*
+ * === certAuth based enroll ===
+ * "certAuthEnroll" is on.
+ * "certauthEnrollType can be one of the three:
+ * single - it's for single cert enrollment
+ * dual - it's for dual certs enrollment
+ * encryption - getting the encryption cert only via
+ * authentication of the signing cert
+ * (crmf or keyGenInfo)
+ */
+ boolean certAuthEnroll = false;
+
+ String certAuthEnrollOn =
+ httpParams.getValueAsString("certauthEnroll", null);
+
+ if ((certAuthEnrollOn != null) && (certAuthEnrollOn.equals("on"))) {
+ certAuthEnroll = true;
+ CMS.debug("HashEnrollServlet: certAuthEnroll is on");
+ }
+
+ String certauthEnrollType = null;
+
+ if (certAuthEnroll == true) {
+ certauthEnrollType =
+ httpParams.getValueAsString("certauthEnrollType", null);
+ if (certauthEnrollType != null) {
+ if (certauthEnrollType.equals("dual")) {
+ CMS.debug("HashEnrollServlet: certauthEnrollType is dual");
+ } else if (certauthEnrollType.equals("encryption")) {
+ CMS.debug("HashEnrollServlet: certauthEnrollType is encryption");
+ } else if (certauthEnrollType.equals("single")) {
+ CMS.debug("HashEnrollServlet: certauthEnrollType is single");
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_INVALID_CERTAUTH_ENROLL_TYPE_1", certauthEnrollType));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_CERTAUTH_ENROLL_TYPE"));
+ }
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_CERTAUTH_ENROLL_TYPE"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_CERTAUTH_ENROLL_TYPE"));
+ }
+ }
+
+ String challengePassword = httpParams.getValueAsString("challengePassword", "");
+
+ cmsReq.setIRequest(req);
+ saveHttpHeaders(httpReq, req);
+ saveHttpParams(httpParams, req);
+ IAuthToken token = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, token,
+ mAuthzResourceName, "import");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ X509Certificate sslClientCert = null;
+ // cert auth enroll
+ String certBasedOldSubjectDN = null;
+ BigInteger certBasedOldSerialNum = null;
+
+ // check if request was authenticated, if so set authtoken & certInfo.
+ // also if authenticated, take certInfo from authToken.
+ X509CertInfo certInfo = null;
+
+ if (certAuthEnroll == true) {
+ sslClientCert = getSSLClientCertificate(httpReq);
+ if (sslClientCert == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_MISSING_SSL_CLIENT_CERT"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_SSL_CLIENT_CERT"));
+ }
+
+ certBasedOldSubjectDN = sslClientCert.getSubjectDN().toString();
+ certBasedOldSerialNum = sslClientCert.getSerialNumber();
+ try {
+ certInfo = (X509CertInfo)
+ ((X509CertImpl) sslClientCert).get(
+ X509CertImpl.NAME + "." + X509CertImpl.INFO);
+ } catch (CertificateParsingException ex) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_CERTINFO_ENCRYPT_CERT"));
+ throw new ECMSGWException(
+ CMS.getUserMessage(getLocale(httpReq), "CMS_GW_MISSING_CERTINFO"));
+ }
+ } else {
+ certInfo = CMS.getDefaultX509CertInfo();
+ }
+
+ X509CertInfo[] certInfoArray = new X509CertInfo[] { certInfo };
+
+ //AuthToken authToken = access.getAuthToken();
+ IConfigStore configStore = CMS.getConfigStore();
+ String val = configStore.getString("hashDirEnrollment.name");
+ IAuthSubsystem authSS = (IAuthSubsystem)
+ CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ IAuthManager authMgr1 = authSS.get(val);
+ HashAuthentication mgr = (HashAuthentication) authMgr1;
+ String pageID = httpParams.getValueAsString("pageID", null);
+
+ IAuthToken authToken = mgr.getAuthToken(pageID);
+
+ String authMgr = AuditFormat.NOAUTH;
+
+ if (authToken == null) {
+ printError(cmsReq, "3");
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ } else {
+ authMgr =
+ authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ // don't store agent token in request.
+ // agent currently used for bulk issuance.
+ // if (!authMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) {
+ log(ILogger.LL_INFO,
+ "Enrollment request was authenticated by " +
+ authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME));
+ fillCertInfoFromAuthToken(certInfo, authToken);
+ // save authtoken attrs to request directly (for policy use)
+ saveAuthToken(authToken, req);
+ // req.set(IRequest.AUTH_TOKEN, authToken);
+ // }
+ }
+
+ // support Enterprise 3.5.1 server where CERT_TYPE=csrCertType
+ // instead of certType
+ String certType = httpParams.getValueAsString(OLD_CERT_TYPE, null);
+ if (certType == null) {
+ certType = httpParams.getValueAsString(CERT_TYPE, "client");
+ } else {
+ // some policies may rely on the fact that
+ // CERT_TYPE is set. So for 3.5.1 or eariler
+ // we need to set CERT_TYPE here.
+ req.setExtData(IRequest.HTTP_PARAMS, CERT_TYPE, certType);
+ }
+
+ String crmf =
+ httpParams.getValueAsString(CRMF_REQUEST, null);
+
+ if (certAuthEnroll == true) {
+
+ fillCertInfoFromAuthToken(certInfo, authToken);
+
+ // for dual certs
+ if (certauthEnrollType.equals(CERT_AUTH_DUAL)) {
+ if (mCa == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_NOT_A_CA"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_NOT_A_CA"));
+ }
+
+ // first, make sure the client cert is indeed a
+ // signing only cert
+ if ((CMS.isSigningCert(sslClientCert) == false) ||
+ ((CMS.isSigningCert(sslClientCert) == true) &&
+ (CMS.isEncryptionCert(sslClientCert) == true))) {
+ // either it's not a signing cert, or it's a dual cert
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_INVALID_CERT_TYPE"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_CERT_TYPE"));
+ }
+ X509Key key = null;
+
+ // for signing cert
+ key = (X509Key) sslClientCert.getPublicKey();
+ try {
+ certInfo.set(X509CertInfo.KEY, new CertificateX509Key(key));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString()));
+ }
+
+ String filter =
+ "(&(x509cert.subject="
+ + certBasedOldSubjectDN + ")(!(x509cert.serialNumber=" + certBasedOldSerialNum
+ + "))(certStatus=VALID))";
+ ICertRecordList list =
+ mCa.getCertificateRepository().findCertRecordsInList(filter,
+ null, 10);
+ int size = list.getSize();
+ Enumeration<ICertRecord> en = list.getCertRecords(0, size - 1);
+ boolean gotEncCert = false;
+
+ if (!en.hasMoreElements()) {
+ // pairing encryption cert not found
+ } else {
+ X509CertInfo encCertInfo = CMS.getDefaultX509CertInfo();
+ X509CertInfo[] cInfoArray = new X509CertInfo[] { certInfo,
+ encCertInfo };
+ int i = 1;
+
+ while (en.hasMoreElements()) {
+ ICertRecord record = en.nextElement();
+ X509CertImpl cert = record.getCertificate();
+
+ // if not encryption cert only, try next one
+ if ((CMS.isEncryptionCert(cert) == false) ||
+ ((CMS.isEncryptionCert(cert) == true) &&
+ (CMS.isSigningCert(cert) == true))) {
+ continue;
+ }
+
+ key = (X509Key) cert.getPublicKey();
+ try {
+ encCertInfo = (X509CertInfo)
+ cert.get(
+ X509CertImpl.NAME + "." + X509CertImpl.INFO);
+
+ } catch (CertificateParsingException ex) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_CERTINFO_ENCRYPT_CERT"));
+ throw new ECMSGWException(
+ CMS.getUserMessage(getLocale(httpReq), "CMS_GW_MISSING_CERTINFO"));
+ }
+
+ try {
+ encCertInfo.set(X509CertInfo.KEY, new CertificateX509Key(key));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString()));
+ }
+ fillCertInfoFromAuthToken(encCertInfo, authToken);
+
+ cInfoArray[i++] = encCertInfo;
+ certInfoArray = cInfoArray;
+ gotEncCert = true;
+ break;
+ }
+ }
+
+ if (gotEncCert == false) {
+ // encryption cert not found, bail
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ENCRYPTION_CERT_NOT_FOUND"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_ENCRYPTION_CERT_NOT_FOUND"));
+ }
+ } else if (certauthEnrollType.equals(CERT_AUTH_ENCRYPTION)) {
+ // first, make sure the client cert is indeed a
+ // signing only cert
+ if ((CMS.isSigningCert(sslClientCert) == false) ||
+ ((CMS.isSigningCert(sslClientCert) == true) &&
+ (CMS.isEncryptionCert(sslClientCert) == true))) {
+ // either it's not a signing cert, or it's a dual cert
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_INVALID_CERT_TYPE"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_CERT_TYPE"));
+ }
+
+ /*
+ * crmf
+ */
+ if (crmf != null && crmf != "") {
+ certInfoArray = fillCRMF(crmf, authToken, httpParams, req);
+ req.setExtData(CLIENT_ISSUER,
+ sslClientCert.getIssuerDN().toString());
+ CMS.debug(
+ "HashEnrollServlet: sslClientCert issuerDN = " + sslClientCert.getIssuerDN().toString());
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_KEYGEN_INFO"));
+ throw new ECMSGWException(CMS.getUserMessage(getLocale(httpReq),
+ "CMS_GW_MISSING_KEYGEN_INFO"));
+ }
+ } else if (certauthEnrollType.equals(CERT_AUTH_SINGLE)) {
+ // have to be buried here to handle the issuer
+
+ if (crmf != null && crmf != "") {
+ certInfoArray = fillCRMF(crmf, authToken, httpParams, req);
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_KEYGEN_INFO"));
+ throw new ECMSGWException(CMS.getUserMessage(getLocale(httpReq),
+ "CMS_GW_MISSING_KEYGEN_INFO"));
+ }
+ req.setExtData(CLIENT_ISSUER,
+ sslClientCert.getIssuerDN().toString());
+ }
+ } else if (crmf != null && crmf != "") {
+ certInfoArray = fillCRMF(crmf, authToken, httpParams, req);
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_KEYGEN_INFO"));
+ throw new ECMSGWException(CMS.getUserMessage(getLocale(httpReq),
+ "CMS_GW_MISSING_KEYGEN_INFO"));
+ }
+
+ req.setExtData(IRequest.CERT_INFO, certInfoArray);
+
+ if (challengePassword != null && !challengePassword.equals("")) {
+ String pwd = hashPassword(challengePassword);
+
+ req.setExtData(CHALLENGE_PASSWORD, pwd);
+ }
+
+ // send request to request queue.
+ mRequestQueue.processRequest(req);
+ // process result.
+
+ // render OLD_CERT_TYPE's response differently, we
+ // dont want any javascript in HTML, and need to
+ // override the default render.
+ if (httpParams.getValueAsString(OLD_CERT_TYPE, null) != null) {
+ try {
+ renderServerEnrollResult(cmsReq);
+ cmsReq.setStatus(ICMSRequest.SUCCESS); // no default render
+ } catch (IOException ex) {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ }
+ return;
+ }
+
+ //for audit log
+ String initiative = null;
+ String agentID = null;
+
+ if (!authMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) {
+ // request is from eegateway, so fromUser.
+ initiative = AuditFormat.FROMUSER;
+ } else {
+ agentID = authToken.getInString("userid");
+ initiative = AuditFormat.FROMAGENT + " agentID: " + agentID;
+ }
+
+ // if service not complete return standard templates.
+ RequestStatus status = req.getRequestStatus();
+
+ if (status != RequestStatus.COMPLETE) {
+ cmsReq.setIRequestStatus(); // set status acc. to IRequest status.
+ // audit log the status
+ try {
+ if (status == RequestStatus.REJECTED) {
+ Vector<String> messages = req.getExtDataInStringVector(IRequest.ERRORS);
+
+ if (messages != null) {
+ Enumeration<String> msgs = messages.elements();
+ StringBuffer wholeMsg = new StringBuffer();
+
+ while (msgs.hasMoreElements()) {
+ wholeMsg.append("\n");
+ wholeMsg.append(msgs.nextElement());
+ }
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.ENROLLMENTFORMAT,
+ new Object[] {
+ req.getRequestId(),
+ initiative,
+ authMgr,
+ status.toString(),
+ certInfo.get(X509CertInfo.SUBJECT),
+ " violation: " +
+ wholeMsg.toString() },
+ ILogger.L_MULTILINE
+ );
+ } else { // no policy violation, from agent
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.ENROLLMENTFORMAT,
+ new Object[] {
+ req.getRequestId(),
+ initiative,
+ authMgr,
+ status.toString(),
+ certInfo.get(X509CertInfo.SUBJECT), "" }
+ );
+ }
+ } else { // other imcomplete status
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.ENROLLMENTFORMAT,
+ new Object[] {
+ req.getRequestId(),
+ initiative,
+ authMgr,
+ status.toString(),
+ certInfo.get(X509CertInfo.SUBJECT), "" }
+ );
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING", e.toString()));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING", e.toString()));
+ }
+ return;
+ }
+ // if service error use standard error templates.
+ Integer result = req.getExtDataInInteger(IRequest.RESULT);
+
+ if (result.equals(IRequest.RES_ERROR)) {
+
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(req.getExtDataInString(IRequest.ERROR));
+ String[] svcErrors =
+ req.getExtDataInStringArray(IRequest.SVCERRORS);
+
+ if (svcErrors != null && svcErrors.length > 0) {
+ for (int i = 0; i < svcErrors.length; i++) {
+ String err = svcErrors[i];
+
+ if (err != null) {
+ //System.out.println(
+ //"revocation servlet: setting error description "+
+ //err.toString());
+ cmsReq.setErrorDescription(err);
+ // audit log the error
+ try {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.ENROLLMENTFORMAT,
+ new Object[] {
+ req.getRequestId(),
+ initiative,
+ authMgr,
+ "completed with error: " +
+ err,
+ certInfo.get(X509CertInfo.SUBJECT), "" }
+ );
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING",
+ e.toString()));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING",
+ e.toString()));
+ }
+ }
+ }
+ }
+ return;
+ }
+
+ // service success
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ X509CertImpl[] issuedCerts =
+ req.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ // audit log the success.
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.ENROLLMENTFORMAT,
+ new Object[] {
+ req.getRequestId(),
+ initiative,
+ authMgr,
+ "completed",
+ issuedCerts[0].getSubjectDN(),
+ "cert issued serial number: 0x" +
+ issuedCerts[0].getSerialNumber().toString(16) }
+ );
+
+ // return cert as mime type binary if requested.
+ if (checkImportCertToNav(
+ cmsReq.getHttpResp(), httpParams, issuedCerts[0])) {
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+ // use success template.
+ try {
+ cmsReq.setResult(issuedCerts);
+ renderTemplate(cmsReq, mEnrollSuccessTemplate,
+ mEnrollSuccessFiller);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_TEMP_REND_ERR", mEnrollSuccessFiller.toString(), e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_RETURNING_RESULT_ERROR"));
+ }
+ return;
+ }
+
+ /**
+ * fill subject name, validity, extensions from authoken if any,
+ * overriding what was in pkcs10.
+ * fill subject name, extensions from http input if not authenticated.
+ * requests not authenticated will need to be approved by an agent.
+ */
+ protected void fillCertInfoFromAuthToken(
+ X509CertInfo certInfo, IAuthToken authToken)
+ throws EBaseException {
+ // override subject, validity and extensions from auth token
+ // CA determines algorithm, version and issuer.
+ // take key from keygen, cmc, pkcs10 or crmf.
+
+ // subject name.
+ try {
+ String subjectname =
+ authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT);
+
+ if (subjectname != null) {
+ CertificateSubjectName certSubject = new CertificateSubjectName(new X500Name(subjectname));
+
+ certInfo.set(X509CertInfo.SUBJECT, certSubject);
+ log(ILogger.LL_INFO,
+ "cert subject set to " + certSubject + " from authtoken");
+ }
+ } catch (CertificateException e) {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR"));
+ } catch (IOException e) {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1",
+ e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR"));
+ }
+
+ // validity
+ try {
+ CertificateValidity validity = null;
+ Date notBefore =
+ authToken.getInDate(AuthToken.TOKEN_CERT_NOTBEFORE);
+ Date notAfter =
+ authToken.getInDate(AuthToken.TOKEN_CERT_NOTAFTER);
+
+ if (notBefore != null && notAfter != null) {
+ validity = new CertificateValidity(notBefore, notAfter);
+ certInfo.set(X509CertInfo.VALIDITY, validity);
+ log(ILogger.LL_INFO,
+ "cert validity set to " + validity + " from authtoken");
+ }
+ } catch (CertificateException e) {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_ERROR_SET_VALIDITY_1",
+ e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_VALIDITY_ERROR"));
+ } catch (IOException e) {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_ERROR_SET_VALIDITY_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_VALIDITY_ERROR"));
+ }
+
+ // extensions
+ try {
+ CertificateExtensions extensions =
+ authToken.getInCertExts(X509CertInfo.EXTENSIONS);
+
+ if (extensions != null) {
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ log(ILogger.LL_INFO, "cert extensions set from authtoken");
+ }
+ } catch (CertificateException e) {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_ERROR_SET_EXTENSIONS_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_EXTENSIONS_ERROR"));
+ } catch (IOException e) {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_ERROR_SET_EXTENSIONS_1",
+ e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_EXTENSIONS_ERROR"));
+ }
+ }
+
+ protected X509CertInfo[] fillCRMF(
+ String crmf, IAuthToken authToken, IArgBlock httpParams, IRequest req)
+ throws EBaseException {
+ try {
+ byte[] crmfBlob = CMS.AtoB(crmf);
+ ByteArrayInputStream crmfBlobIn =
+ new ByteArrayInputStream(crmfBlob);
+
+ SEQUENCE crmfMsgs = (SEQUENCE)
+ new SEQUENCE.OF_Template(new CertReqMsg.Template()).decode(crmfBlobIn);
+
+ int nummsgs = crmfMsgs.size();
+ X509CertInfo[] certInfoArray = new X509CertInfo[nummsgs];
+
+ for (int i = 0; i < nummsgs; i++) {
+ // decode message.
+ CertReqMsg certReqMsg = (CertReqMsg) crmfMsgs.elementAt(i);
+
+ /*
+ if (certReqMsg.hasPop()) {
+ try {
+ certReqMsg.verify();
+ } catch (ChallengeResponseException ex) {
+ // create and save the challenge
+ // construct the cmmf message together
+ // in a sequence to challenge the requestor
+ } catch (Exception e) {
+ // failed, should only affect one request
+ }
+ }
+ */
+ CertRequest certReq = certReqMsg.getCertReq();
+ INTEGER certReqId = certReq.getCertReqId();
+ int srcId = certReqId.intValue();
+
+ req.setExtData(IRequest.CRMF_REQID, String.valueOf(srcId));
+
+ CertTemplate certTemplate = certReq.getCertTemplate();
+ X509CertInfo certInfo = CMS.getDefaultX509CertInfo();
+
+ // get key
+ SubjectPublicKeyInfo spki = certTemplate.getPublicKey();
+ ByteArrayOutputStream keyout = new ByteArrayOutputStream();
+
+ spki.encode(keyout);
+ byte[] keybytes = keyout.toByteArray();
+ X509Key key = new X509Key();
+
+ key.decode(keybytes);
+ certInfo.set(X509CertInfo.KEY, new CertificateX509Key(key));
+
+ // field suggested notBefore and notAfter in CRMF
+ // Tech Support #383184
+ if (certTemplate.getNotBefore() != null || certTemplate.getNotAfter() != null) {
+ CertificateValidity certValidity =
+ new CertificateValidity(certTemplate.getNotBefore(), certTemplate.getNotAfter());
+
+ certInfo.set(X509CertInfo.VALIDITY, certValidity);
+ }
+
+ if (certTemplate.hasSubject()) {
+ Name subjectdn = certTemplate.getSubject();
+ ByteArrayOutputStream subjectEncStream =
+ new ByteArrayOutputStream();
+
+ subjectdn.encode(subjectEncStream);
+ byte[] subjectEnc = subjectEncStream.toByteArray();
+ X500Name subject = new X500Name(subjectEnc);
+
+ certInfo.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(subject));
+ } else if (authToken == null ||
+ authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) == null) {
+ // No subject name - error!
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN"));
+ }
+
+ // get extensions
+ CertificateExtensions extensions = null;
+
+ try {
+ extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+ } catch (CertificateException e) {
+ extensions = null;
+ } catch (IOException e) {
+ extensions = null;
+ }
+ if (certTemplate.hasExtensions()) {
+ // put each extension from CRMF into CertInfo.
+ // index by extension name, consistent with
+ // CertificateExtensions.parseExtension() method.
+ if (extensions == null)
+ extensions = new CertificateExtensions();
+ int numexts = certTemplate.numExtensions();
+
+ for (int j = 0; j < numexts; j++) {
+ org.mozilla.jss.pkix.cert.Extension jssext =
+ certTemplate.extensionAt(j);
+ boolean isCritical = jssext.getCritical();
+ org.mozilla.jss.asn1.OBJECT_IDENTIFIER jssoid =
+ jssext.getExtnId();
+ long[] numbers = jssoid.getNumbers();
+ int[] oidNumbers = new int[numbers.length];
+
+ for (int k = numbers.length - 1; k >= 0; k--) {
+ oidNumbers[k] = (int) numbers[k];
+ }
+ ObjectIdentifier oid =
+ new ObjectIdentifier(oidNumbers);
+ org.mozilla.jss.asn1.OCTET_STRING jssvalue =
+ jssext.getExtnValue();
+ ByteArrayOutputStream jssvalueout =
+ new ByteArrayOutputStream();
+
+ jssvalue.encode(jssvalueout);
+ byte[] extValue = jssvalueout.toByteArray();
+
+ Extension ext =
+ new Extension(oid, isCritical, extValue);
+
+ extensions.parseExtension(ext);
+ }
+
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+
+ }
+
+ // Added a new configuration parameter
+ // eeGateway.Enrollment.authTokenOverride=[true|false]
+ // By default, it is set to true. In most
+ // of the case, administrator would want
+ // to have the control of the subject name
+ // formulation.
+ // -- CRMFfillCert
+ if (authToken != null &&
+ authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) != null) {
+ // if authenticated override subect name, validity and
+ // extensions if any from authtoken.
+ fillCertInfoFromAuthToken(certInfo, authToken);
+ }
+
+ certInfoArray[i] = certInfo;
+ }
+
+ do_testbed_hack(nummsgs, certInfoArray, httpParams);
+
+ return certInfoArray;
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR"));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1",
+ e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR"));
+ } catch (InvalidBERException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR"));
+ } catch (InvalidKeyException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1",
+ e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR"));
+ }
+ }
+
+ protected void renderServerEnrollResult(CMSRequest cmsReq) throws
+ IOException {
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ httpResp.setContentType("text/html");
+ ServletOutputStream out = null;
+
+ out = httpResp.getOutputStream();
+
+ // get template based on request status
+ out.println("<HTML>");
+ out.println("<TITLE>");
+ out.println("Server Enrollment");
+ out.println("</TITLE>");
+ // out.println("<BODY BGCOLOR=white>");
+
+ if (cmsReq.getIRequest().getRequestStatus().equals(RequestStatus.COMPLETE)) {
+ out.println("<H1>");
+ out.println("SUCCESS");
+ out.println("</H1>");
+ out.println("Your request is submitted and approved. Please cut and paste the certificate into your server."); // XXX - localize the message
+ out.println("<P>");
+ out.println("Request Creation Time: ");
+ out.println(cmsReq.getIRequest().getCreationTime().toString());
+ out.println("<P>");
+ out.println("Request Status: ");
+ out.println(cmsReq.getStatus().toString());
+ out.println("<P>");
+ out.println("Request ID: ");
+ out.println(cmsReq.getIRequest().getRequestId().toString());
+ out.println("<P>");
+ out.println("Certificate: ");
+ out.println("<P>");
+ out.println("<PRE>");
+ X509CertImpl certs[] =
+ cmsReq.getIRequest().getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ out.println(CMS.getEncodedCert(certs[0]));
+ out.println("</PRE>");
+ out.println("<P>");
+ out.println("<!HTTP_OUTPUT REQUEST_CREATION_TIME=" +
+ cmsReq.getIRequest().getCreationTime().toString() + ">");
+ out.println("<!HTTP_OUTPUT REQUEST_STATUS=" +
+ cmsReq.getStatus().toString() + ">");
+ out.println("<!HTTP_OUTPUT REQUEST_ID=" +
+ cmsReq.getIRequest().getRequestId().toString() + ">");
+ out.println("<!HTTP_OUTPUT X509_CERTIFICATE=" +
+ CMS.getEncodedCert(certs[0]) + ">");
+ } else if (cmsReq.getIRequest().getRequestStatus().equals(RequestStatus.PENDING)) {
+ out.println("<H1>");
+ out.println("PENDING");
+ out.println("</H1>");
+ out.println("Your request is submitted. You can check on the status of your request with an authorized agent or local administrator by referring to the request ID."); // XXX - localize the message
+ out.println("<P>");
+ out.println("Request Creation Time: ");
+ out.println(cmsReq.getIRequest().getCreationTime().toString());
+ out.println("<P>");
+ out.println("Request Status: ");
+ out.println(cmsReq.getStatus().toString());
+ out.println("<P>");
+ out.println("Request ID: ");
+ out.println(cmsReq.getIRequest().getRequestId().toString());
+ out.println("<P>");
+ out.println("<!HTTP_OUTPUT REQUEST_CREATION_TIME=" +
+ cmsReq.getIRequest().getCreationTime().toString() + ">");
+ out.println("<!HTTP_OUTPUT REQUEST_STATUS=" +
+ cmsReq.getStatus().toString() + ">");
+ out.println("<!HTTP_OUTPUT REQUEST_ID=" +
+ cmsReq.getIRequest().getRequestId().toString() + ">");
+ } else {
+ out.println("<H1>");
+ out.println("ERROR");
+ out.println("</H1>");
+ out.println("<!INFO>");
+ out.println("Please consult your local administrator for assistance."); // XXX - localize the message
+ out.println("<!/INFO>");
+ out.println("<P>");
+ out.println("Request Status: ");
+ out.println(cmsReq.getStatus().toString());
+ out.println("<P>");
+ out.println("Error: ");
+ out.println(cmsReq.getError()); // XXX - need to parse in Locale
+ out.println("<P>");
+ out.println("<!HTTP_OUTPUT REQUEST_STATUS=" +
+ cmsReq.getStatus().toString() + ">");
+ out.println("<!HTTP_OUTPUT ERROR=" +
+ cmsReq.getError() + ">");
+ }
+
+ /**
+ * // include all the input data
+ * IArgBlock args = cmsReq.getHttpParams();
+ * Enumeration ele = args.getElements();
+ * while (ele.hasMoreElements()) {
+ * String eleT = (String)ele.nextElement();
+ * out.println("<!HTTP_INPUT " + eleT + "=" +
+ * args.get(eleT) + ">");
+ * }
+ **/
+
+ out.println("</HTML>");
+ }
+
+ // XXX ALERT !!
+ // Remove the following and calls to them when we bundle a cartman
+ // later than alpha1.
+ // These are here to cover up problem in cartman where the
+ // key usage extension always ends up being digital signature only
+ // and for rsa-ex ends up having no bits set.
+
+ private boolean mIsTestBed = false;
+
+ private void init_testbed_hack(IConfigStore config)
+ throws EBaseException {
+ mIsTestBed = config.getBoolean("isTestBed", true);
+ }
+
+ private void do_testbed_hack(
+ int nummsgs, X509CertInfo[] certinfo, IArgBlock httpParams)
+ throws EBaseException {
+ if (!mIsTestBed)
+ return;
+
+ // get around bug in cartman - bits are off by one byte.
+ for (int i = 0; i < certinfo.length; i++) {
+ try {
+ X509CertInfo cert = certinfo[i];
+ CertificateExtensions exts = (CertificateExtensions)
+ cert.get(CertificateExtensions.NAME);
+
+ if (exts == null) {
+ // should not happen.
+ continue;
+ }
+ KeyUsageExtension ext = (KeyUsageExtension)
+ exts.get(KeyUsageExtension.NAME);
+
+ if (ext == null)
+ // should not happen
+ continue;
+ byte[] value = ext.getExtensionValue();
+
+ if (value[0] == 0x03 && value[1] == 0x02 && value[2] == 0x07) {
+ byte[] newvalue = new byte[value.length + 1];
+
+ newvalue[0] = 0x03;
+ newvalue[1] = 0x03;
+ newvalue[2] = 0x07;
+ newvalue[3] = value[3];
+ // force encryption certs to have digitial signature
+ // set too so smime can find the cert for encryption.
+ if (value[3] == 0x20) {
+
+ /*
+ newvalue[3] = 0x3f;
+ newvalue[4] = (byte)0x80;
+ */
+ if (httpParams.getValueAsBoolean(
+ "dual-use-hack", true)) {
+ newvalue[3] = (byte) 0xE0; // same as rsa-dual-use.
+ }
+ }
+ newvalue[4] = 0;
+ KeyUsageExtension newext =
+ new KeyUsageExtension(Boolean.valueOf(true),
+ newvalue);
+
+ exts.delete(KeyUsageExtension.NAME);
+ exts.set(KeyUsageExtension.NAME, newext);
+ }
+ } catch (IOException e) {
+ // should never happen
+ continue;
+ } catch (CertificateException e) {
+ // should never happen
+ continue;
+ }
+ }
+
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/ImportCertsTemplateFiller.java b/base/server/cms/src/com/netscape/cms/servlet/cert/ImportCertsTemplateFiller.java
new file mode 100644
index 000000000..a56ac1d88
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/ImportCertsTemplateFiller.java
@@ -0,0 +1,380 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.math.BigInteger;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+
+import javax.servlet.http.HttpServletRequest;
+
+import netscape.security.pkcs.ContentInfo;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.pkcs.SignerInfo;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.X509CertImpl;
+
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.pkix.cmmf.CertOrEncCert;
+import org.mozilla.jss.pkix.cmmf.CertRepContent;
+import org.mozilla.jss.pkix.cmmf.CertResponse;
+import org.mozilla.jss.pkix.cmmf.CertifiedKeyPair;
+import org.mozilla.jss.pkix.cmmf.PKIStatusInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.ICertPrettyPrint;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Set up HTTP response to import certificate into browsers
+ *
+ * The result must have been populate with the set of certificates
+ * to return.
+ *
+ * <pre>
+ * inputs: certtype.
+ * outputs:
+ * - cert type from http input (if any)
+ * - CA chain
+ * - authority name (RM, CM, DRM)
+ * - scheme:host:port of server.
+ * array of one or more
+ * - cert serial number
+ * - cert pretty print
+ * - cert in base 64 encoding.
+ * - cmmf blob to import
+ * </pre>
+ *
+ * @version $Revision$, $Date$
+ */
+public class ImportCertsTemplateFiller implements ICMSTemplateFiller {
+ public static final String CRMF_REQID = "crmfReqId";
+ public static final String ISSUED_CERT_SERIAL = "serialNo";
+ public static final String CERT_TYPE = "certType";
+ public static final String BASE64_CERT = "base64Cert";
+ public static final String CERT_PRETTYPRINT = "certPrettyPrint";
+ public static final String CERT_FINGERPRINT = "certFingerprint"; // cisco
+ public static final String CERT_NICKNAME = "certNickname";
+ public static final String CMMF_RESP = "cmmfResponse";
+ public static final String PKCS7_RESP = "pkcs7ChainBase64"; // for MSIE
+
+ public ImportCertsTemplateFiller() {
+ }
+
+ /**
+ * @param cmsReq CMS Request
+ * @param authority this authority
+ * @param locale locale of template.
+ * @param e unexpected exception e. ignored.
+ */
+ public CMSTemplateParams getTemplateParams(
+ CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e)
+ throws Exception {
+ Certificate[] certs = (Certificate[]) cmsReq.getResult();
+
+ if (certs instanceof X509CertImpl[])
+ return getX509TemplateParams(cmsReq, authority, locale, e);
+ else
+ return null;
+ }
+
+ public CMSTemplateParams getX509TemplateParams(
+ CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e)
+ throws Exception {
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams params = new CMSTemplateParams(header, fixed);
+
+ // set host name and port.
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ String host = httpReq.getServerName();
+ int port = httpReq.getServerPort();
+ String scheme = httpReq.getScheme();
+ String format = httpReq.getParameter("format");
+ if (format != null && format.equals("cmc"))
+ fixed.set("importCMC", "false");
+ String agentPort = "" + port;
+ fixed.set("agentHost", host);
+ fixed.set("agentPort", agentPort);
+ fixed.set(ICMSTemplateFiller.HOST, host);
+ fixed.set(ICMSTemplateFiller.PORT, Integer.valueOf(port));
+ fixed.set(ICMSTemplateFiller.SCHEME, scheme);
+ IRequest r = cmsReq.getIRequest();
+
+ if (r != null) {
+ fixed.set(ICMSTemplateFiller.REQUEST_ID, r.getRequestId().toString());
+ }
+
+ // set key record (if KRA enabled)
+ if (r != null) {
+ BigInteger keyRecSerialNo = r.getExtDataInBigInteger("keyRecord");
+
+ if (keyRecSerialNo != null) {
+ fixed.set(ICMSTemplateFiller.KEYREC_ID, keyRecSerialNo.toString());
+ }
+ }
+
+ // set cert type.
+ IArgBlock httpParams = cmsReq.getHttpParams();
+ String certType =
+ httpParams.getValueAsString(CERT_TYPE, null);
+
+ if (certType != null)
+ fixed.set(CERT_TYPE, certType);
+
+ // this authority
+ fixed.set(ICMSTemplateFiller.AUTHORITY, authority.getOfficialName());
+
+ // CA chain.
+ CertificateChain cachain =
+ ((ICertAuthority) authority).getCACertChain();
+ X509Certificate[] cacerts = cachain.getChain();
+
+ String replyTo = httpParams.getValueAsString("replyTo", null);
+
+ if (replyTo != null)
+ fixed.set("replyTo", replyTo);
+
+ // set user + CA cert chain and pkcs7 for MSIE.
+ X509CertImpl[] userChain = new X509CertImpl[cacerts.length + 1];
+ int m = 1, n = 0;
+
+ for (; n < cacerts.length; m++, n++)
+ userChain[m] = (X509CertImpl) cacerts[n];
+
+ // certs.
+ X509CertImpl[] certs = (X509CertImpl[]) cmsReq.getResult();
+
+ // expose CRMF request id
+ String crmfReqId = cmsReq.getExtData(IRequest.CRMF_REQID);
+
+ if (crmfReqId == null) {
+ crmfReqId = (String) cmsReq.getResult(
+ IRequest.CRMF_REQID);
+ }
+ if (crmfReqId != null) {
+ fixed.set(CRMF_REQID, crmfReqId);
+ }
+
+ // set CA certs in cmmf, initialize CertRepContent
+ // note cartman can't trust ca certs yet but it'll import them.
+ // also set cert nickname for cartman.
+ CertRepContent certRepContent = null;
+
+ if (CMSServlet.doCMMFResponse(httpParams)) {
+ byte[][] caPubs = new byte[cacerts.length][];
+
+ for (int j = 0; j < cacerts.length; j++)
+ caPubs[j] = ((X509CertImpl) cacerts[j]).getEncoded();
+ certRepContent = new CertRepContent(caPubs);
+
+ String certnickname =
+ cmsReq.getHttpParams().getValueAsString(CERT_NICKNAME, null);
+
+ // if nickname is not requested set to subject name by default.
+ if (certnickname == null)
+ fixed.set(CERT_NICKNAME, certs[0].getSubjectDN().toString());
+ else
+ fixed.set(CERT_NICKNAME, certnickname);
+ }
+
+ // make pkcs7 for MSIE
+ if (CMSServlet.clientIsMSIE(cmsReq.getHttpReq()) &&
+ (certType == null || certType.equals("client"))) {
+ userChain[0] = certs[0];
+ PKCS7 p7 = new PKCS7(new AlgorithmId[0],
+ new ContentInfo(new byte[0]),
+ userChain,
+ new SignerInfo[0]);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ p7.encodeSignedData(bos);
+ byte[] p7Bytes = bos.toByteArray();
+ // String p7Str = encoder.encodeBuffer(p7Bytes);
+ String p7Str = CMS.BtoA(p7Bytes);
+
+ header.set(PKCS7_RESP, p7Str);
+ }
+
+ // set base 64, pretty print and cmmf response for each issued cert.
+ for (int i = 0; i < certs.length; i++) {
+ IArgBlock repeat = CMS.createArgBlock();
+ X509CertImpl cert = certs[i];
+
+ // set serial number.
+ BigInteger serialNo =
+ ((X509Certificate) cert).getSerialNumber();
+
+ repeat.addBigIntegerValue(ISSUED_CERT_SERIAL, serialNo, 16);
+
+ // set base64 encoded blob.
+ byte[] certEncoded = cert.getEncoded();
+ // String b64 = encoder.encodeBuffer(certEncoded);
+ String b64 = CMS.BtoA(certEncoded);
+ String b64cert = "-----BEGIN CERTIFICATE-----\n" +
+ b64 + "\n-----END CERTIFICATE-----";
+
+ repeat.set(BASE64_CERT, b64cert);
+
+ // set cert pretty print.
+
+ String prettyPrintRequested =
+ cmsReq.getHttpParams().getValueAsString(CERT_PRETTYPRINT, null);
+
+ if (prettyPrintRequested == null) {
+ prettyPrintRequested = "true";
+ }
+ String ppStr = "";
+
+ if (!prettyPrintRequested.equals("false")) {
+ ICertPrettyPrint pp = CMS.getCertPrettyPrint(cert);
+
+ ppStr = pp.toString(locale);
+ }
+ repeat.set(CERT_PRETTYPRINT, ppStr);
+
+ // Now formulate a PKCS#7 blob
+ X509CertImpl[] certsInChain = new X509CertImpl[1];
+ ;
+ if (cacerts != null) {
+ for (int j = 0; j < cacerts.length; j++) {
+ if (cert.equals(cacerts[j])) {
+ certsInChain = new
+ X509CertImpl[cacerts.length];
+ break;
+ }
+ certsInChain = new X509CertImpl[cacerts.length + 1];
+ }
+ }
+
+ // Set the EE cert
+ certsInChain[0] = cert;
+
+ // Set the Ca certificate chain
+ if (cacerts != null) {
+ for (int j = 0; j < cacerts.length; j++) {
+ if (!cert.equals(cacerts[j]))
+ certsInChain[j + 1] = (X509CertImpl) cacerts[j];
+ }
+ }
+ // Wrap the chain into a degenerate P7 object
+ String p7Str;
+
+ try {
+ PKCS7 p7 = new PKCS7(new AlgorithmId[0],
+ new ContentInfo(new byte[0]),
+ certsInChain,
+ new SignerInfo[0]);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ p7.encodeSignedData(bos);
+ byte[] p7Bytes = bos.toByteArray();
+
+ //p7Str = encoder.encodeBuffer(p7Bytes);
+ p7Str = CMS.BtoA(p7Bytes);
+ repeat.addStringValue("pkcs7ChainBase64", p7Str);
+ } catch (Exception ex) {
+ //p7Str = "PKCS#7 B64 Encoding error - " + ex.toString()
+ //+ "; Please contact your administrator";
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_FORMING_PKCS7_ERROR"));
+ }
+
+ // set cert fingerprint (for Cisco routers)
+ String fingerprint = null;
+
+ try {
+ fingerprint = CMS.getFingerPrints(cert);
+ } catch (CertificateEncodingException ex) {
+ // should never happen
+ throw new EBaseException(
+ CMS.getUserMessage(locale, "CMS_BASE_INTERNAL_ERROR", ex.toString()));
+ } catch (NoSuchAlgorithmException ex) {
+ // should never happen
+ throw new EBaseException(
+ CMS.getUserMessage(locale, "CMS_BASE_INTERNAL_ERROR", ex.toString()));
+ }
+ if (fingerprint != null && fingerprint.length() > 0)
+ repeat.set(CERT_FINGERPRINT, fingerprint);
+
+ // cmmf response for this cert.
+ if (CMSServlet.doCMMFResponse(httpParams) && crmfReqId != null &&
+ (certType == null || certType.equals("client"))) {
+ PKIStatusInfo status = new PKIStatusInfo(PKIStatusInfo.granted);
+ CertifiedKeyPair certifiedKP =
+ new CertifiedKeyPair(new CertOrEncCert(certEncoded));
+ CertResponse resp =
+ new CertResponse(new INTEGER(crmfReqId), status,
+ certifiedKP);
+
+ certRepContent.addCertResponse(resp);
+ }
+
+ params.addRepeatRecord(repeat);
+ }
+
+ // if cartman set whole cmmf response (CertRepContent) string.
+ if (CMSServlet.doCMMFResponse(httpParams)) {
+ ByteArrayOutputStream certRepOut = new ByteArrayOutputStream();
+
+ certRepContent.encode(certRepOut);
+ byte[] certRepBytes = certRepOut.toByteArray();
+ String certRepB64 = Utils.base64encode(certRepBytes);
+ // add CR to each return as required by cartman
+ BufferedReader certRepB64lines =
+ new BufferedReader(new StringReader(certRepB64));
+ StringWriter certRepStringOut = new StringWriter();
+ String oneLine = null;
+ boolean first = true;
+
+ while ((oneLine = certRepB64lines.readLine()) != null) {
+ if (first) {
+ //certRepStringOut.write("\""+oneLine+"\"");
+ certRepStringOut.write(oneLine);
+ first = false;
+ } else {
+ //certRepStringOut.write("+\"\\n"+oneLine+"\"");
+ certRepStringOut.write("\n" + oneLine);
+ }
+ }
+ String certRepString = certRepStringOut.toString();
+
+ fixed.set(CMMF_RESP, certRepString);
+ }
+
+ return params;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/ListCerts.java b/base/server/cms/src/com/netscape/cms/servlet/cert/ListCerts.java
new file mode 100644
index 000000000..185e1fa8e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/ListCerts.java
@@ -0,0 +1,673 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.provider.RSAPublicKey;
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.Extension;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertRecordList;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.dbs.certdb.IRevocationInfo;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Retrieve a paged list of certs matching the specified query
+ *
+ * @version $Revision$, $Date$
+ */
+public class ListCerts extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3568155814023099576L;
+ private final static String TPL_FILE = "queryCert.template";
+ private final static BigInteger MINUS_ONE = new BigInteger("-1");
+
+ private final static String USE_CLIENT_FILTER = "useClientFilter";
+ private final static String ALLOWED_CLIENT_FILTERS = "allowedClientFilters";
+
+ private ICertificateRepository mCertDB = null;
+ private X500Name mAuthName = null;
+ private String mFormPath = null;
+ private boolean mReverse = false;
+ private boolean mHardJumpTo = false; //jump to the end
+ private String mDirection = null;
+ private boolean mUseClientFilter = false;
+ private Vector<String> mAllowedClientFilters = new Vector<String>();
+ private int mMaxReturns = 2000;
+
+ /**
+ * Constructs query key servlet.
+ */
+ public ListCerts() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "queryCert.template" to render the response
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success to render own template.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ ICertificateAuthority ca = (ICertificateAuthority) mAuthority;
+
+ mCertDB = ca.getCertificateRepository();
+ mAuthName = ca.getX500Name();
+ }
+
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+
+ try {
+ mMaxReturns = Integer.parseInt(sc.getInitParameter("maxResults"));
+ } catch (Exception e) {
+ /* do nothing, just use the default if integer parsing failed */
+ }
+
+ /* useClientFilter should be off by default. We keep
+ this parameter around so that we do not break
+ the client applications that submits raw LDAP
+ filter into this servlet. */
+ if (sc.getInitParameter(USE_CLIENT_FILTER) != null &&
+ sc.getInitParameter(USE_CLIENT_FILTER).equalsIgnoreCase("true")) {
+ mUseClientFilter = true;
+ }
+ if (sc.getInitParameter(ALLOWED_CLIENT_FILTERS) == null
+ || sc.getInitParameter(ALLOWED_CLIENT_FILTERS).equals("")) {
+ mAllowedClientFilters.addElement("(certStatus=*)");
+ mAllowedClientFilters.addElement("(certStatus=VALID)");
+ mAllowedClientFilters.addElement("(|(certStatus=VALID)(certStatus=INVALID)(certStatus=EXPIRED))");
+ mAllowedClientFilters.addElement("(|(certStatus=VALID)(certStatus=REVOKED))");
+ } else {
+ StringTokenizer st = new StringTokenizer(sc.getInitParameter(ALLOWED_CLIENT_FILTERS), ",");
+ while (st.hasMoreTokens()) {
+ mAllowedClientFilters.addElement(st.nextToken());
+ }
+ }
+ }
+
+ public String buildFilter(HttpServletRequest req) {
+ String queryCertFilter = req.getParameter("queryCertFilter");
+
+ com.netscape.certsrv.apps.CMS.debug("client queryCertFilter=" + queryCertFilter);
+
+ if (mUseClientFilter) {
+ com.netscape.certsrv.apps.CMS.debug("useClientFilter=true");
+ Enumeration<String> filters = mAllowedClientFilters.elements();
+ // check to see if the filter is allowed
+ while (filters.hasMoreElements()) {
+ String filter = filters.nextElement();
+ com.netscape.certsrv.apps.CMS.debug("Comparing filter="
+ + filter + " queryCertFilter=" + queryCertFilter);
+ if (filter.equals(queryCertFilter)) {
+ return queryCertFilter;
+ }
+ }
+ com.netscape.certsrv.apps.CMS.debug("Requested filter '"
+ + queryCertFilter + "' is not allowed. Please check the " + ALLOWED_CLIENT_FILTERS + "parameter");
+ return null;
+ } else {
+ com.netscape.certsrv.apps.CMS.debug("useClientFilter=false");
+ }
+
+ boolean skipRevoked = false;
+ boolean skipNonValid = false;
+ if (req.getParameter("skipRevoked") != null &&
+ req.getParameter("skipRevoked").equals("on")) {
+ skipRevoked = true;
+ }
+ if (req.getParameter("skipNonValid") != null &&
+ req.getParameter("skipNonValid").equals("on")) {
+ skipNonValid = true;
+ }
+
+ if (!skipRevoked && !skipNonValid) {
+ queryCertFilter = "(certStatus=*)";
+ } else if (skipRevoked && skipNonValid) {
+ queryCertFilter = "(certStatus=VALID)";
+ } else if (skipRevoked) {
+ queryCertFilter = "(|(certStatus=VALID)(certStatus=INVALID)(certStatus=EXPIRED))";
+ } else if (skipNonValid) {
+ queryCertFilter = "(|(certStatus=VALID)(certStatus=REVOKED))";
+ }
+ return queryCertFilter;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param maxCount Number of certificates to show
+ * <li>http.param queryFilter and ldap style filter specifying the certificates to show
+ * <li>http.param querySentinelDown the serial number of the first certificate to show (default decimal, or hex if
+ * prefixed with 0x) when paging down
+ * <li>http.param querySentinelUp the serial number of the first certificate to show (default decimal, or hex if
+ * prefixed with 0x) when paging up
+ * <li>http.param direction "up", "down", "begin", or "end"
+ * </ul>
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "list");
+ } catch (Exception e) {
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ String revokeAll = null;
+ EBaseException error = null;
+
+ int maxCount = -1;
+ BigInteger sentinel = new BigInteger("0");
+
+ IArgBlock header = com.netscape.certsrv.apps.CMS.createArgBlock();
+ IArgBlock ctx = com.netscape.certsrv.apps.CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ com.netscape.certsrv.apps.CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ com.netscape.certsrv.apps.CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ mHardJumpTo = false;
+ try {
+
+ if (req.getParameter("direction") != null) {
+ mDirection = req.getParameter("direction").trim();
+ mReverse = mDirection.equals("up");
+ if (mReverse)
+ com.netscape.certsrv.apps.CMS.debug("reverse is true");
+ else
+ com.netscape.certsrv.apps.CMS.debug("reverse is false");
+
+ }
+
+ if (req.getParameter("maxCount") != null) {
+ maxCount = Integer.parseInt(req.getParameter("maxCount"));
+ }
+ if (maxCount == -1 || maxCount > mMaxReturns) {
+ com.netscape.certsrv.apps.CMS.debug("Resetting page size from " + maxCount + " to " + mMaxReturns);
+ maxCount = mMaxReturns;
+ }
+
+ String sentinelStr = "";
+ if (mReverse) {
+ sentinelStr = req.getParameter("querySentinelUp");
+ } else if (mDirection.equals("end")) {
+ // this servlet will figure out the end
+ sentinelStr = "0";
+ mReverse = true;
+ mHardJumpTo = true;
+ } else if (mDirection.equals("down")) {
+ sentinelStr = req.getParameter("querySentinelDown");
+ } else
+ sentinelStr = "0";
+ //begin and non-specified have sentinel default "0"
+
+ if (sentinelStr != null) {
+ if (sentinelStr.trim().startsWith("0x")) {
+ sentinel = new BigInteger(sentinelStr.trim().substring(2), 16);
+ } else {
+ sentinel = new BigInteger(sentinelStr, 10);
+ }
+ }
+
+ revokeAll = req.getParameter("revokeAll");
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ X509CertImpl caCert = ((ICertificateAuthority) mAuthority).getSigningUnit().getCertImpl();
+
+ //if (isCertFromCA(caCert))
+ header.addStringValue("caSerialNumber",
+ caCert.getSerialNumber().toString(16));
+ }
+
+ // constructs the ldap filter on the server side
+ String queryCertFilter = buildFilter(req);
+
+ if (queryCertFilter == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ com.netscape.certsrv.apps.CMS.debug("queryCertFilter=" + queryCertFilter);
+
+ int totalRecordCount = -1;
+
+ try {
+ totalRecordCount = Integer.parseInt(req.getParameter("totalRecordCount"));
+ } catch (Exception e) {
+ }
+ processCertFilter(argSet, header, maxCount,
+ sentinel,
+ totalRecordCount,
+ req.getParameter("serialTo"),
+ queryCertFilter,
+ req, resp, revokeAll, locale[0]);
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE, com.netscape.certsrv.apps.CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT"));
+
+ error =
+ new EBaseException(com.netscape.certsrv.apps.CMS.getUserMessage(getLocale(req),
+ "CMS_BASE_INVALID_NUMBER_FORMAT"));
+ } catch (EBaseException e) {
+ error = e;
+ }
+
+ ctx.addIntegerValue("maxCount", maxCount);
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ }
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ com.netscape.certsrv.apps.CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ com.netscape.certsrv.apps.CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ private void processCertFilter(CMSTemplateParams argSet,
+ IArgBlock header,
+ int maxCount,
+ BigInteger sentinel,
+ int totalRecordCount,
+ String serialTo,
+ String filter,
+ HttpServletRequest req,
+ HttpServletResponse resp,
+ String revokeAll,
+ Locale locale
+ ) throws EBaseException {
+ BigInteger serialToVal = MINUS_ONE;
+
+ try {
+ if (serialTo != null) {
+ serialTo = serialTo.trim();
+ if (serialTo.startsWith("0x")) {
+ serialToVal = new BigInteger
+ (serialTo.substring(2), 16);
+ serialTo = serialToVal.toString();
+ } else {
+ serialToVal = new BigInteger(serialTo);
+ }
+ }
+ } catch (Exception e) {
+ }
+
+ String jumpTo = sentinel.toString();
+ int pSize = 0;
+ if (mReverse) {
+ if (!mHardJumpTo) //reverse gets one more
+ pSize = -1 * maxCount - 1;
+ else
+ pSize = -1 * maxCount;
+ } else
+ pSize = maxCount;
+
+ ICertRecordList list = mCertDB.findCertRecordsInList(
+ filter, (String[]) null, jumpTo, mHardJumpTo, "serialno",
+ pSize);
+ // retrive maxCount + 1 entries
+
+ Enumeration<ICertRecord> e = list.getCertRecords(0, maxCount);
+
+ ICertRecordList tolist = null;
+ int toCurIndex = 0;
+
+ if (!serialToVal.equals(MINUS_ONE)) {
+ // if user specify a range, we need to
+ // calculate the totalRecordCount
+ tolist = mCertDB.findCertRecordsInList(
+ filter,
+ (String[]) null, serialTo,
+ "serialno", maxCount);
+ Enumeration<ICertRecord> en = tolist.getCertRecords(0, 0);
+
+ if (en == null || (!en.hasMoreElements())) {
+ toCurIndex = list.getSize() - 1;
+ } else {
+ toCurIndex = tolist.getCurrentIndex();
+ ICertRecord rx = en.nextElement();
+ BigInteger curToSerial = rx.getSerialNumber();
+
+ if (curToSerial.compareTo(serialToVal) == -1) {
+ toCurIndex = list.getSize() - 1;
+ } else {
+ if (!rx.getSerialNumber().toString().equals(serialTo.trim())) {
+ toCurIndex = toCurIndex - 1;
+ }
+ }
+ }
+ }
+
+ int curIndex = list.getCurrentIndex();
+
+ int count = 0;
+ BigInteger firstSerial = new BigInteger("0");
+ BigInteger curSerial = new BigInteger("0");
+ ICertRecord[] recs = new ICertRecord[maxCount];
+ int rcount = 0;
+
+ if (e != null) {
+ /* in reverse (page up), because the sentinel is the one after the
+ * last item to be displayed, we need to skip it
+ */
+ while ((count < ((mReverse && !mHardJumpTo) ? (maxCount + 1) : maxCount)) && e.hasMoreElements()) {
+ ICertRecord rec = e.nextElement();
+
+ if (rec == null) {
+ com.netscape.certsrv.apps.CMS.debug("record " + count + " is null");
+ break;
+ }
+ curSerial = rec.getSerialNumber();
+ com.netscape.certsrv.apps.CMS.debug("record " + count + " is serial#" + curSerial);
+
+ if (count == 0) {
+ firstSerial = curSerial;
+ if (mReverse && !mHardJumpTo) {//reverse got one more, skip
+ count++;
+ continue;
+ }
+ }
+
+ // DS has a problem where last record will be returned
+ // even though the filter is not matched.
+ /*cfu - is this necessary? it breaks when paging up
+ if (curSerial.compareTo(sentinel) == -1) {
+ com.netscape.certsrv.apps.CMS.debug("curSerial compare sentinel -1 break...");
+
+ break;
+ }
+ */
+ if (!serialToVal.equals(MINUS_ONE)) {
+ // check if we go over the limit
+ if (curSerial.compareTo(serialToVal) == 1) {
+ com.netscape.certsrv.apps.CMS.debug("curSerial compare serialToVal 1 breaking...");
+ break;
+ }
+ }
+
+ if (mReverse) {
+ recs[rcount++] = rec;
+ } else {
+
+ IArgBlock rarg = com.netscape.certsrv.apps.CMS.createArgBlock();
+
+ fillRecordIntoArg(rec, rarg);
+ argSet.addRepeatRecord(rarg);
+ }
+ count++;
+ }
+ } else {
+ com.netscape.certsrv.apps.CMS.debug(
+ "ListCerts::processCertFilter() - no Cert Records found!");
+ return;
+ }
+
+ if (mReverse) {
+ // fill records into arg block and argSet
+ for (int ii = rcount - 1; ii >= 0; ii--) {
+ if (recs[ii] != null) {
+ IArgBlock rarg = com.netscape.certsrv.apps.CMS.createArgBlock();
+ //com.netscape.certsrv.apps.CMS.debug("item "+ii+" is serial # "+ recs[ii].getSerialNumber());
+ fillRecordIntoArg(recs[ii], rarg);
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ }
+
+ // peek ahead
+ ICertRecord nextRec = null;
+
+ if (e.hasMoreElements()) {
+ nextRec = e.nextElement();
+ }
+
+ header.addStringValue("op", req.getParameter("op"));
+ if (revokeAll != null)
+ header.addStringValue("revokeAll", revokeAll);
+ if (mAuthName != null)
+ header.addStringValue("issuerName", mAuthName.toString());
+ if (!serialToVal.equals(MINUS_ONE))
+ header.addStringValue("serialTo", serialToVal.toString());
+ header.addStringValue("serviceURL", req.getRequestURI());
+ header.addStringValue("queryCertFilter", filter);
+ header.addStringValue("templateName", "queryCert");
+ header.addStringValue("queryFilter", filter);
+ header.addIntegerValue("maxCount", maxCount);
+ if (totalRecordCount == -1) {
+ if (!serialToVal.equals(MINUS_ONE)) {
+ totalRecordCount = toCurIndex - curIndex + 1;
+ com.netscape.certsrv.apps.CMS.debug("totalRecordCount=" + totalRecordCount);
+ } else {
+ totalRecordCount = list.getSize() -
+ list.getCurrentIndex();
+ com.netscape.certsrv.apps.CMS.debug("totalRecordCount=" + totalRecordCount);
+ }
+ }
+
+ header.addIntegerValue("totalRecordCount", totalRecordCount);
+ header.addIntegerValue("currentRecordCount", list.getSize() -
+ list.getCurrentIndex());
+
+ String qs = "";
+ if (mReverse)
+ qs = "querySentinelUp";
+ else
+ qs = "querySentinelDown";
+
+ if (mHardJumpTo) {
+ com.netscape.certsrv.apps.CMS.debug("curSerial added to querySentinelUp:" + curSerial.toString());
+
+ header.addStringValue("querySentinelUp", curSerial.toString());
+ } else {
+ if (nextRec == null) {
+ header.addStringValue(qs, null);
+ com.netscape.certsrv.apps.CMS.debug("nextRec is null");
+ if (mReverse) {
+ com.netscape.certsrv.apps.CMS.debug("curSerial added to querySentinelUp:" + curSerial.toString());
+
+ header.addStringValue("querySentinelUp", curSerial.toString());
+ }
+ } else {
+ BigInteger nextRecNo = nextRec.getSerialNumber();
+
+ if (serialToVal.equals(MINUS_ONE)) {
+ header.addStringValue(
+ qs, nextRecNo.toString());
+ } else {
+ if (nextRecNo.compareTo(serialToVal) <= 0) {
+ header.addStringValue(
+ qs, nextRecNo.toString());
+ } else {
+ header.addStringValue(qs,
+ null);
+ }
+ }
+ com.netscape.certsrv.apps.CMS.debug("querySentinel " + qs + " = " + nextRecNo.toString());
+ }
+ } // !mHardJumpto
+
+ header.addStringValue(!mReverse ? "querySentinelUp" : "querySentinelDown",
+ firstSerial.toString());
+
+ }
+
+ /**
+ * Fills cert record into argument block.
+ */
+ private void fillRecordIntoArg(ICertRecord rec, IArgBlock rarg)
+ throws EBaseException {
+
+ X509CertImpl xcert = rec.getCertificate();
+
+ if (xcert != null) {
+ fillX509RecordIntoArg(rec, rarg);
+ }
+ }
+
+ private void fillX509RecordIntoArg(ICertRecord rec, IArgBlock rarg)
+ throws EBaseException {
+
+ X509CertImpl cert = rec.getCertificate();
+
+ rarg.addIntegerValue("version", cert.getVersion());
+ rarg.addStringValue("serialNumber", cert.getSerialNumber().toString(16));
+ rarg.addStringValue("serialNumberDecimal", cert.getSerialNumber().toString());
+
+ if (cert.getSubjectDN().toString().equals("")) {
+ rarg.addStringValue("subject", " ");
+ } else
+ rarg.addStringValue("subject", cert.getSubjectDN().toString());
+
+ rarg.addStringValue("type", "X.509");
+
+ try {
+ PublicKey pKey = cert.getPublicKey();
+ X509Key key = null;
+
+ if (pKey instanceof CertificateX509Key) {
+ CertificateX509Key certKey = (CertificateX509Key) pKey;
+
+ key = (X509Key) certKey.get(CertificateX509Key.KEY);
+ }
+ if (pKey instanceof X509Key) {
+ key = (X509Key) pKey;
+ }
+ rarg.addStringValue("subjectPublicKeyAlgorithm", key.getAlgorithmId().getOID().toString());
+ if (key.getAlgorithmId().toString().equalsIgnoreCase("RSA")) {
+ RSAPublicKey rsaKey = new RSAPublicKey(key.getEncoded());
+
+ rarg.addIntegerValue("subjectPublicKeyLength", rsaKey.getKeySize());
+ }
+ } catch (Exception e) {
+ rarg.addStringValue("subjectPublicKeyAlgorithm", null);
+ rarg.addIntegerValue("subjectPublicKeyLength", 0);
+ }
+
+ rarg.addLongValue("validNotBefore", cert.getNotBefore().getTime() / 1000);
+ rarg.addLongValue("validNotAfter", cert.getNotAfter().getTime() / 1000);
+ rarg.addStringValue("signatureAlgorithm", cert.getSigAlgOID());
+ String issuedBy = rec.getIssuedBy();
+
+ if (issuedBy == null)
+ issuedBy = "";
+ rarg.addStringValue("issuedBy", issuedBy); // cert.getIssuerDN().toString()
+ rarg.addLongValue("issuedOn", rec.getCreateTime().getTime() / 1000);
+
+ rarg.addStringValue("revokedBy",
+ ((rec.getRevokedBy() == null) ? "" : rec.getRevokedBy()));
+ if (rec.getRevokedOn() == null) {
+ rarg.addStringValue("revokedOn", null);
+ } else {
+ rarg.addLongValue("revokedOn", rec.getRevokedOn().getTime() / 1000);
+
+ IRevocationInfo revocationInfo = rec.getRevocationInfo();
+
+ if (revocationInfo != null) {
+ CRLExtensions crlExts = revocationInfo.getCRLEntryExtensions();
+
+ if (crlExts != null) {
+ Enumeration<Extension> enum1 = crlExts.getElements();
+ int reason = 0;
+
+ while (enum1.hasMoreElements()) {
+ Extension ext = enum1.nextElement();
+
+ if (ext instanceof CRLReasonExtension) {
+ reason = ((CRLReasonExtension) ext).getReason().toInt();
+ break;
+ }
+ }
+ rarg.addIntegerValue("revocationReason", reason);
+ }
+ }
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/Monitor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/Monitor.java
new file mode 100644
index 000000000..305620580
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/Monitor.java
@@ -0,0 +1,405 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X500Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequestList;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.IRequestRecord;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Provide statistical queries of request and certificate records.
+ *
+ * @version $Revision$, $Date$
+ */
+public class Monitor extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -8492837942132357692L;
+ private final static String TPL_FILE = "monitor.template";
+
+ private ICertificateRepository mCertDB = null;
+ private IRequestQueue mQueue = null;
+ private X500Name mAuthName = null;
+ private String mFormPath = null;
+
+ private int mTotalCerts = 0;
+ private int mTotalReqs = 0;
+
+ /**
+ * Constructs query servlet.
+ */
+ public Monitor() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * 'monitor.template' to render the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success to render own template.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ ICertificateAuthority ca = (ICertificateAuthority) mAuthority;
+
+ mCertDB = ca.getCertificateRepository();
+ mAuthName = ca.getX500Name();
+ }
+ mQueue = mAuthority.getRequestQueue();
+
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param startTime start of time period to query
+ * <li>http.param endTime end of time period to query
+ * <li>http.param interval time between queries
+ * <li>http.param numberOfIntervals number of queries to run
+ * <li>http.param maxResults =number
+ * <li>http.param timeLimit =time
+ * </ul>
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ String startTime = null;
+ String endTime = null;
+ String interval = null;
+ String numberOfIntervals = null;
+
+ EBaseException error = null;
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ try {
+ startTime = req.getParameter("startTime");
+ endTime = req.getParameter("endTime");
+ interval = req.getParameter("interval");
+ numberOfIntervals = req.getParameter("numberOfIntervals");
+
+ process(argSet, header, startTime, endTime, interval, numberOfIntervals, locale[0]);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_PROCESSING_REQ", e.toString()));
+ error = e;
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE",
+ e.toString()));
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ String startTime, String endTime,
+ String interval, String numberOfIntervals,
+ Locale locale)
+ throws EBaseException {
+ if (interval == null || interval.length() == 0) {
+ header.addStringValue("error", "Invalid interval: " + interval);
+ return;
+ }
+ if (numberOfIntervals == null || numberOfIntervals.length() == 0) {
+ header.addStringValue("error", "Invalid number of intervals: " + numberOfIntervals);
+ return;
+ }
+
+ Date startDate = StringToDate(startTime);
+
+ if (startDate == null) {
+ header.addStringValue("error", "Invalid start time: " + startTime);
+ return;
+ }
+
+ int iInterval = 0;
+
+ try {
+ iInterval = Integer.parseInt(interval);
+ } catch (NumberFormatException nfe) {
+ header.addStringValue("error", "Invalid interval: " + interval);
+ return;
+ }
+
+ int iNumberOfIntervals = 0;
+
+ try {
+ iNumberOfIntervals = Integer.parseInt(numberOfIntervals);
+ } catch (NumberFormatException nfe) {
+ header.addStringValue("error", "Invalid number of intervals: " + numberOfIntervals);
+ return;
+ }
+
+ header.addStringValue("startDate", startDate.toString());
+ header.addStringValue("startTime", startTime);
+ header.addIntegerValue("interval", iInterval);
+ header.addIntegerValue("numberOfIntervals", iNumberOfIntervals);
+
+ mTotalCerts = 0;
+ mTotalReqs = 0;
+
+ Date d1 = startDate;
+
+ for (int i = 0; i < iNumberOfIntervals; i++) {
+ Date d2 = nextDate(d1, iInterval - 1);
+ IArgBlock rarg = CMS.createArgBlock();
+ String e = getIntervalInfo(rarg, d1, d2);
+
+ if (e != null) {
+ header.addStringValue("error", e);
+ return;
+ }
+ argSet.addRepeatRecord(rarg);
+ d1 = nextDate(d2, 1);
+ }
+
+ header.addIntegerValue("totalNumberOfCertificates", mTotalCerts);
+ header.addIntegerValue("totalNumberOfRequests", mTotalReqs);
+
+ if (mAuthName != null)
+ header.addStringValue("issuerName", mAuthName.toString());
+
+ return;
+ }
+
+ Date nextDate(Date d, int seconds) {
+ return new Date(d.getTime() + seconds * 1000);
+ }
+
+ String getIntervalInfo(IArgBlock arg, Date startDate, Date endDate) {
+ if (startDate != null && endDate != null) {
+ String startTime = DateToZString(startDate);
+ String endTime = DateToZString(endDate);
+ String filter = null;
+
+ arg.addStringValue("startTime", startTime);
+ arg.addStringValue("endTime", endTime);
+
+ try {
+ if (mCertDB != null) {
+ filter = Filter(ICertRecord.ATTR_CREATE_TIME, startTime, endTime);
+
+ Enumeration<Object> e = mCertDB.findCertRecs(filter);
+
+ int count = 0;
+
+ while (e != null && e.hasMoreElements()) {
+ ICertRecord rec = (ICertRecord) e.nextElement();
+
+ if (rec != null) {
+ count++;
+ }
+ }
+ arg.addIntegerValue("numberOfCertificates", count);
+ mTotalCerts += count;
+ }
+
+ if (mQueue != null) {
+ filter = Filter(IRequestRecord.ATTR_CREATE_TIME, startTime, endTime);
+
+ IRequestList reqList = mQueue.listRequestsByFilter(filter);
+
+ int count = 0;
+
+ while (reqList != null && reqList.hasMoreElements()) {
+ IRequestRecord rec = (IRequestRecord) reqList.nextRequest();
+
+ if (rec != null) {
+ if (count == 0) {
+ arg.addStringValue("firstRequest", rec.getRequestId().toString());
+ }
+ count++;
+ }
+ }
+ arg.addIntegerValue("numberOfRequests", count);
+ mTotalReqs += count;
+ }
+ } catch (Exception ex) {
+ return "Exception: " + ex;
+ }
+
+ return null;
+ } else {
+ return "Missing start or end date";
+ }
+ }
+
+ Date StringToDate(String z) {
+ Date d = null;
+
+ if (z != null && (z.length() == 14 ||
+ z.length() == 15 && (z.charAt(14) == 'Z' || z.charAt(14) == 'z'))) {
+ // 20020516132030Z or 20020516132030
+ try {
+ int year = Integer.parseInt(z.substring(0, 4));
+ int month = Integer.parseInt(z.substring(4, 6)) - 1;
+ int date = Integer.parseInt(z.substring(6, 8));
+ int hour = Integer.parseInt(z.substring(8, 10));
+ int minute = Integer.parseInt(z.substring(10, 12));
+ int second = Integer.parseInt(z.substring(12, 14));
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(year, month, date, hour, minute, second);
+ d = calendar.getTime();
+ } catch (NumberFormatException nfe) {
+ }
+ } else if (z != null && z.length() > 1 && z.charAt(0) == '-') { // -5
+ try {
+ int i = Integer.parseInt(z);
+
+ d = new Date();
+ d = nextDate(d, i);
+ } catch (NumberFormatException nfe) {
+ }
+ }
+
+ return d;
+ }
+
+ String DateToZString(Date d) {
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(d);
+
+ String time = "" + (calendar.get(Calendar.YEAR));
+ int i = calendar.get(Calendar.MONTH) + 1;
+
+ if (i < 10)
+ time += "0";
+ time += i;
+ i = calendar.get(Calendar.DAY_OF_MONTH);
+ if (i < 10)
+ time += "0";
+ time += i;
+ i = calendar.get(Calendar.HOUR_OF_DAY);
+ if (i < 10)
+ time += "0";
+ time += i;
+ i = calendar.get(Calendar.MINUTE);
+ if (i < 10)
+ time += "0";
+ time += i;
+ i = calendar.get(Calendar.SECOND);
+ if (i < 10)
+ time += "0";
+ time += i + "Z";
+ return time;
+ }
+
+ String Filter(String name, String start, String end) {
+ String filter = "(&(" + name + ">=" + start + ")(" + name + "<=" + end + "))";
+
+ return filter;
+ }
+
+ String uriFilter(String name, String start, String end) {
+ String filter = "(%26(" + name + "%3e%3d" + start + ")(" + name + "%3c%3d" + end + "))";
+
+ return filter;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java b/base/server/cms/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java
new file mode 100644
index 000000000..c65c482b1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java
@@ -0,0 +1,298 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Random;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X509CertImpl;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Specify the RevocationReason when revoking a certificate
+ *
+ * @version $Revision$, $Date$
+ */
+public class ReasonToRevoke extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -8447580860330758660L;
+ private final static String TPL_FILE = "reasonToRevoke.template";
+ private final static String INFO = "ReasonToRevoke";
+
+ private ICertificateRepository mCertDB = null;
+ private String mFormPath = null;
+ private ICertificateAuthority mCA = null;
+ private Random mRandom = null;
+ private int mTimeLimits = 30; /* in seconds */
+
+ public ReasonToRevoke() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * 'reasonToRevoke.template' to render the response
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ if (mAuthority instanceof ICertificateAuthority) {
+ mCA = (ICertificateAuthority) mAuthority;
+ mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository();
+ }
+
+ if (mCA != null && mCA.noncesEnabled()) {
+ mRandom = new Random();
+ }
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+
+ /* Server-Side time limit */
+ try {
+ mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits"));
+ } catch (Exception e) {
+ /* do nothing, just use the default if integer parsing failed */
+ }
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "revoke");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ String revokeAll = null;
+ int totalRecordCount = 1;
+ EBaseException error = null;
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ try {
+ if (req.getParameter("totalRecordCount") != null) {
+ totalRecordCount =
+ Integer.parseInt(req.getParameter("totalRecordCount"));
+ }
+
+ revokeAll = req.getParameter("revokeAll");
+
+ process(argSet, header, req, resp,
+ revokeAll, totalRecordCount, locale[0]);
+ } catch (EBaseException e) {
+ error = e;
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_RECORD_COUNT_FORMAT"));
+ error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT"));
+ }
+
+ /*
+ catch (Exception e) {
+ noError = false;
+ header.addStringValue(OUT_ERROR,
+ MessageFormatter.getLocalizedString(
+ errorlocale[0],
+ BaseResources.class.getName(),
+ BaseResources.INTERNAL_ERROR_1,
+ e.toString()));
+ }
+ */
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ HttpServletRequest req,
+ HttpServletResponse resp,
+ String revokeAll, int totalRecordCount,
+ Locale locale)
+ throws EBaseException {
+
+ header.addStringValue("revokeAll", revokeAll);
+ header.addIntegerValue("totalRecordCount", totalRecordCount);
+
+ try {
+ if (mCA != null) {
+ X509CertImpl caCert = mCA.getSigningUnit().getCertImpl();
+
+ if (isCertFromCA(caCert)) {
+ header.addStringValue("caSerialNumber",
+ caCert.getSerialNumber().toString(16));
+ }
+ }
+
+ /**
+ * ICertRecordList list = mCertDB.findCertRecordsInList(
+ * revokeAll, null, totalRecordCount);
+ * Enumeration e = list.getCertRecords(0, totalRecordCount - 1);
+ **/
+ Enumeration<ICertRecord> e = mCertDB.searchCertificates(revokeAll,
+ totalRecordCount, mTimeLimits);
+
+ ArrayList<String> noncesList = new ArrayList<String>();
+ int count = 0;
+
+ while (e != null && e.hasMoreElements()) {
+ ICertRecord rec = e.nextElement();
+
+ if (rec == null)
+ continue;
+ X509CertImpl xcert = rec.getCertificate();
+
+ if (xcert != null)
+
+ if (mCA != null && mCA.noncesEnabled()) {
+ // generate nonce
+ long n = mRandom.nextLong();
+ // store nonce in session
+ Map<Object, Long> nonces = mCA.getNonces(req, "cert-revoke");
+ nonces.put(xcert.getSerialNumber(), n);
+ // store serial number and nonce
+ noncesList.add(xcert.getSerialNumber()+":"+n);
+ }
+
+ if (!(rec.getStatus().equals(ICertRecord.STATUS_REVOKED))) {
+ count++;
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addStringValue("serialNumber",
+ xcert.getSerialNumber().toString(16));
+ rarg.addStringValue("serialNumberDecimal",
+ xcert.getSerialNumber().toString());
+ rarg.addStringValue("subject",
+ xcert.getSubjectDN().toString());
+ rarg.addLongValue("validNotBefore",
+ xcert.getNotBefore().getTime() / 1000);
+ rarg.addLongValue("validNotAfter",
+ xcert.getNotAfter().getTime() / 1000);
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+
+ header.addIntegerValue("verifiedRecordCount", count);
+
+ if (mCA != null && mCA.noncesEnabled()) {
+ // return serial numbers and nonces to client
+ header.addStringValue("nonce", StringUtils.join(noncesList.toArray(), ","));
+ }
+
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, "Error " + e);
+ throw e;
+ }
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/RemoteAuthConfig.java b/base/server/cms/src/com/netscape/cms/servlet/cert/RemoteAuthConfig.java
new file mode 100644
index 000000000..3f5434d9e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/RemoteAuthConfig.java
@@ -0,0 +1,624 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthMgrPlugin;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Allow agent to turn on/off authentication managers
+ *
+ * @version $Revision$, $Date$
+ */
+public class RemoteAuthConfig extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5803015919915253940L;
+ private final static String TPL_FILE = "remoteAuthConfig.template";
+ private final static String ENABLE_REMOTE_CONFIG = "enableRemoteConfiguration";
+ private final static String REMOTELY_SET_INSTANCES = "remotelySetInstances";
+ private final static String MEMBER_OF = "memberOf";
+ private final static String UNIQUE_MEMBER = "uniqueMember";
+
+ private String mFormPath = null;
+ private IAuthSubsystem mAuthSubsystem = null;
+ private IConfigStore mAuthConfig = null;
+ private IConfigStore mFileConfig = null;
+ private Vector<String> mRemotelySetInstances = new Vector<String>();
+ private boolean mEnableRemoteConfiguration = false;
+
+ /**
+ * Constructs RemoteAuthConfig servlet.
+ */
+ public RemoteAuthConfig() {
+ super();
+ }
+
+ /**
+ * Initializes the servlet.
+ *
+ * Presence of "auths.enableRemoteConfiguration=true" in CMS.cfg
+ * enables remote configuration for authentication plugins.
+ * List of remotely set instances can be found in CMS.cfg
+ * at "auths.remotelySetInstances=<name1>,<name2>,...,<nameN>"
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ mFileConfig = CMS.getConfigStore();
+ mAuthConfig = mFileConfig.getSubStore("auths");
+ try {
+ mEnableRemoteConfiguration = mAuthConfig.getBoolean(ENABLE_REMOTE_CONFIG, false);
+ } catch (EBaseException eb) {
+ // Thanks to design of getBoolean we have to catch but we will never get anything.
+ }
+
+ String remoteList = null;
+
+ try {
+ remoteList = mAuthConfig.getString(REMOTELY_SET_INSTANCES, null);
+ } catch (EBaseException eb) {
+ // Thanks to design of getString we have to catch but we will never get anything.
+ }
+ if (remoteList != null) {
+ StringTokenizer s = new StringTokenizer(remoteList, ",");
+
+ while (s.hasMoreTokens()) {
+ String token = s.nextToken();
+
+ if (token != null && token.trim().length() > 0) {
+ mRemotelySetInstances.add(token.trim());
+ }
+ }
+ }
+
+ mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Serves HTTPS request. The format of this request is as follows:
+ * https://host:ee-port/remoteAuthConfig?
+ * op="add"|"delete"&
+ * instance=<instanceName>&
+ * of=<authPluginName>&
+ * host=<hostName>&
+ * port=<portNumber>&
+ * password=<password>&
+ * [adminDN=<adminDN>]&
+ * [uid=<uid>]&
+ * [baseDN=<baseDN>]
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ authenticate(cmsReq);
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ String host = req.getParameter("host");
+ String port = req.getParameter("port");
+
+ String adminDN = req.getParameter("adminDN");
+ String uid = req.getParameter("uid");
+ String baseDN = req.getParameter("baseDN");
+ String password = req.getParameter("password");
+
+ String replyTo = req.getParameter("replyTo");
+
+ if (replyTo != null && replyTo.length() > 0) {
+ ctx.addStringValue("replyTo", replyTo);
+ }
+
+ if (mEnableRemoteConfiguration) {
+ String errMsg = null;
+
+ if (adminDN != null && adminDN.length() > 0) {
+ errMsg = authenticateRemoteAdmin(host, port, adminDN, password);
+ } else {
+ errMsg = authenticateRemoteAdmin(host, port, uid, baseDN, password);
+ }
+ if (errMsg == null || errMsg.length() == 0) {
+ if (mAuthSubsystem != null && mAuthConfig != null) {
+ String op = req.getParameter("op");
+
+ if (op == null || op.length() == 0) {
+ header.addStringValue("error", "Undefined operation");
+ } else {
+ header.addStringValue("op", op);
+
+ if (op.equals("delete")) {
+ String plugin = req.getParameter("of");
+
+ if (isPluginListed(plugin)) {
+ String instance = req.getParameter("instance");
+
+ if (isInstanceListed(instance)) {
+ errMsg = deleteInstance(instance);
+ if (errMsg != null && errMsg.length() > 0) {
+ header.addStringValue("error", errMsg);
+ } else {
+ header.addStringValue("plugin", plugin);
+ header.addStringValue("instance", instance);
+ }
+ } else {
+ header.addStringValue("error", "Unknown instance " +
+ instance + ".");
+ }
+ } else {
+ header.addStringValue("error", "Unknown plugin name: " + plugin);
+ }
+ } else if (op.equals("add")) {
+ String plugin = req.getParameter("of");
+
+ if (isPluginListed(plugin)) {
+ String instance = req.getParameter("instance");
+
+ if (instance == null || instance.length() == 0) {
+ instance = makeInstanceName();
+ }
+ if (isInstanceListed(instance)) {
+ header.addStringValue("error", "Instance name " +
+ instance + " is already in use.");
+ } else {
+ errMsg = addInstance(instance, plugin,
+ host, port, baseDN,
+ req.getParameter("dnPattern"));
+ if (errMsg != null && errMsg.length() > 0) {
+ header.addStringValue("error", errMsg);
+ } else {
+ header.addStringValue("plugin", plugin);
+ header.addStringValue("instance", instance);
+ }
+ }
+ } else {
+ header.addStringValue("error", "Unknown plugin name: " + plugin);
+ }
+ } else {
+ header.addStringValue("error", "Unsupported operation: " + op);
+ }
+ }
+ } else {
+ header.addStringValue("error", "Invalid configuration data.");
+ }
+ } else {
+ header.addStringValue("error", errMsg);
+ }
+ } else {
+ header.addStringValue("error", "Remote configuration is disabled.");
+ }
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ private String authenticateRemoteAdmin(String host, String port,
+ String adminDN, String password) {
+ if (host == null || host.length() == 0) {
+ return "Missing host name.";
+ }
+ if (port == null || port.length() == 0 || port.trim().length() == 0) {
+ return "Missing port number.";
+ }
+ if (adminDN == null || adminDN.length() == 0) {
+ return "Missing admin DN.";
+ }
+ if (password == null || password.length() == 0) {
+ return "Missing password.";
+ }
+ int p = 0;
+
+ try {
+ p = Integer.parseInt(port.trim());
+ } catch (NumberFormatException e) {
+ return "Invalid port number: " + port + " (" + e.toString() + ")";
+ }
+
+ boolean connected = false;
+ LDAPConnection c = new LDAPConnection();
+
+ try {
+ c.connect(host, p);
+ connected = true;
+ try {
+ c.authenticate(adminDN, password);
+ LDAPEntry entry = c.read(adminDN);
+ LDAPAttribute attr = entry.getAttribute(MEMBER_OF);
+
+ if (attr != null) {
+ @SuppressWarnings("unchecked")
+ Enumeration<String> eVals = attr.getStringValues();
+
+ while (eVals.hasMoreElements()) {
+ String nextValue = eVals.nextElement();
+
+ if (nextValue.indexOf("Administrator") > -1) {
+ LDAPEntry groupEntry = c.read(nextValue);
+
+ if (groupEntry != null) {
+ LDAPAttribute gAttr = groupEntry.getAttribute(UNIQUE_MEMBER);
+
+ if (gAttr != null) {
+ @SuppressWarnings("unchecked")
+ Enumeration<String> eValues = gAttr.getStringValues();
+
+ while (eValues.hasMoreElements()) {
+ String value = eValues.nextElement();
+
+ if (value.equals(entry.getDN())) {
+ c.disconnect();
+ return null;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ } else {
+ c.disconnect();
+ return null;
+ }
+
+ } catch (LDAPException e) {
+
+ /*
+ switch (e.getLDAPResultCode()) {
+ case LDAPException.NO_SUCH_OBJECT:
+ case LDAPException.INVALID_CREDENTIALS:
+ case LDAPException.INSUFFICIENT_ACCESS_RIGHTS:
+ case LDAPException.LDAP_PARTIAL_RESULTS:
+ default:
+ }
+ */
+ c.disconnect();
+ return "LDAP error: " + e.toString();
+ }
+
+ if (connected) {
+ c.disconnect();
+ }
+ } catch (LDAPException e) {
+ return "LDAP error: " + e.toString();
+ }
+
+ return "Access unauthorized";
+ }
+
+ private String authenticateRemoteAdmin(String host, String port,
+ String uid, String baseDN,
+ String password) {
+ if (host == null || host.length() == 0) {
+ return "Missing host name.";
+ }
+ if (port == null || port.length() == 0 || port.trim().length() == 0) {
+ return "Missing port number.";
+ }
+ if (uid == null || uid.length() == 0) {
+ return "Missing UID.";
+ }
+ if (uid.indexOf('*') > -1) {
+ return "Invalid UID: " + uid;
+ }
+ if (password == null || password.length() == 0) {
+ return "Missing password.";
+ }
+ int p = 0;
+
+ try {
+ p = Integer.parseInt(port.trim());
+ } catch (NumberFormatException e) {
+ return "Invalid port number: " + port + " (" + e.toString() + ")";
+ }
+ if (baseDN == null || baseDN.length() == 0) {
+ return "Missing base DN.";
+ }
+
+ boolean connected = false;
+ LDAPConnection c = new LDAPConnection();
+
+ try {
+ c.connect(host, p);
+ connected = true;
+ boolean memberOf = false;
+ LDAPSearchResults results = c.search(baseDN, LDAPv2.SCOPE_SUB,
+ "(uid=" + uid + ")",
+ null, false);
+
+ while (results.hasMoreElements()) {
+ LDAPEntry entry = null;
+
+ try {
+ entry = results.next();
+ c.authenticate(entry.getDN(), password);
+ LDAPAttribute attr = entry.getAttribute(MEMBER_OF);
+
+ if (attr != null) {
+ memberOf = true;
+ @SuppressWarnings("unchecked")
+ Enumeration<String> eVals = attr.getStringValues();
+
+ while (eVals.hasMoreElements()) {
+ String nextValue = eVals.nextElement();
+
+ if (nextValue.indexOf("Administrator") > -1) {
+ LDAPEntry groupEntry = c.read(nextValue);
+
+ if (groupEntry != null) {
+ LDAPAttribute gAttr = groupEntry.getAttribute(UNIQUE_MEMBER);
+
+ if (gAttr != null) {
+ @SuppressWarnings("unchecked")
+ Enumeration<String> eValues = gAttr.getStringValues();
+
+ while (eValues.hasMoreElements()) {
+ String value = eValues.nextElement();
+
+ if (value.equals(entry.getDN())) {
+ c.disconnect();
+ return null;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ } catch (LDAPException e) {
+ switch (e.getLDAPResultCode()) {
+ case LDAPException.NO_SUCH_OBJECT:
+ continue;
+
+ case LDAPException.INVALID_CREDENTIALS:
+ break;
+
+ case LDAPException.INSUFFICIENT_ACCESS_RIGHTS:
+ break;
+
+ case LDAPException.LDAP_PARTIAL_RESULTS:
+ break;
+
+ default:
+ continue;
+ }
+ }
+ }
+ if (connected) {
+ c.disconnect();
+ }
+
+ if (!memberOf) {
+ return null;
+ }
+ } catch (LDAPException e) {
+ return "LDAP error: " + e.toString();
+ }
+
+ return "Access unauthorized";
+ }
+
+ private String addInstance(String instance, String plugin,
+ String host, String port,
+ String baseDN, String dnPattern) {
+ if (host == null || host.length() == 0) {
+ return "Missing host name.";
+ }
+ if (port == null || port.length() == 0) {
+ return "Missing port number.";
+ }
+
+ IConfigStore c0 = mAuthConfig.getSubStore("instance");
+ IConfigStore c1 = c0.makeSubStore(instance);
+
+ c1.putString("dnpattern", dnPattern);
+ c1.putString("ldapByteAttributes", "");
+ c1.putString("ldapStringAttributes", "");
+ c1.putString("pluginName", plugin);
+ if (baseDN != null && baseDN.length() > 0)
+ c1.putString("ldap.basedn", baseDN);
+ c1.putString("ldap.minConns", "");
+ c1.putString("ldap.maxConns", "");
+ c1.putString("ldap.ldapconn.host", host);
+ c1.putString("ldap.ldapconn.port", port);
+ c1.putString("ldap.ldapconn.secureConn", "false");
+ c1.putString("ldap.ldapconn.version", "3");
+
+ mRemotelySetInstances.add(instance);
+
+ IAuthManager authMgrInst = mAuthSubsystem.getAuthManagerPlugin(plugin);
+
+ if (authMgrInst != null) {
+ try {
+ authMgrInst.init(instance, plugin, c1);
+ } catch (EBaseException e) {
+ c0.removeSubStore(instance);
+ mRemotelySetInstances.remove(instance);
+ return e.toString();
+ }
+ mAuthSubsystem.add(instance, authMgrInst);
+ }
+
+ StringBuffer list = new StringBuffer();
+
+ for (int i = 0; i < mRemotelySetInstances.size(); i++) {
+ if (i > 0)
+ list.append(",");
+ list.append(mRemotelySetInstances.elementAt(i));
+ }
+
+ mAuthConfig.putString(REMOTELY_SET_INSTANCES, list.toString());
+
+ try {
+ mFileConfig.commit(false);
+ } catch (EBaseException e) {
+ c0.removeSubStore(instance);
+ mRemotelySetInstances.remove(instance);
+ return e.toString();
+ }
+
+ return null;
+ }
+
+ private String deleteInstance(String instance) {
+ IConfigStore c = mAuthConfig.getSubStore("instance");
+
+ c.removeSubStore(instance);
+
+ if (mRemotelySetInstances.remove(instance)) {
+ StringBuffer list = new StringBuffer();
+
+ for (int i = 0; i < mRemotelySetInstances.size(); i++) {
+ if (i > 0)
+ list.append(",");
+ list.append(mRemotelySetInstances.elementAt(i));
+ }
+
+ mAuthConfig.putString(REMOTELY_SET_INSTANCES, list.toString());
+ }
+
+ try {
+ mFileConfig.commit(false);
+ } catch (EBaseException e) {
+ return e.toString();
+ }
+ mAuthSubsystem.delete(instance);
+
+ return null;
+ }
+
+ private boolean isPluginListed(String pluginName) {
+ boolean isListed = false;
+
+ if (pluginName != null && pluginName.length() > 0) {
+ Enumeration<AuthMgrPlugin> e = mAuthSubsystem.getAuthManagerPlugins();
+
+ while (e.hasMoreElements()) {
+ AuthMgrPlugin plugin = e.nextElement();
+
+ if (pluginName.equals(plugin.getId())) {
+ isListed = true;
+ break;
+ }
+ }
+ }
+
+ return isListed;
+ }
+
+ private boolean isInstanceListed(String instanceName) {
+ boolean isListed = false;
+
+ if (instanceName != null && instanceName.length() > 0) {
+ Enumeration<IAuthManager> e = mAuthSubsystem.getAuthManagers();
+
+ while (e.hasMoreElements()) {
+ IAuthManager authManager = e.nextElement();
+
+ if (instanceName.equals(authManager.getName())) {
+ isListed = true;
+ break;
+ }
+ }
+ }
+
+ return isListed;
+ }
+
+ private String makeInstanceName() {
+ Calendar now = Calendar.getInstance();
+ int y = now.get(Calendar.YEAR);
+ String name = "R" + y;
+
+ if (now.get(Calendar.MONTH) < 10)
+ name += "0";
+ name += now.get(Calendar.MONTH);
+ if (now.get(Calendar.DAY_OF_MONTH) < 10)
+ name += "0";
+ name += now.get(Calendar.DAY_OF_MONTH);
+ if (now.get(Calendar.HOUR_OF_DAY) < 10)
+ name += "0";
+ name += now.get(Calendar.HOUR_OF_DAY);
+ if (now.get(Calendar.MINUTE) < 10)
+ name += "0";
+ name += now.get(Calendar.MINUTE);
+ if (now.get(Calendar.SECOND) < 10)
+ name += "0";
+ name += now.get(Calendar.SECOND);
+ return name;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/RenewalProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/RenewalProcessor.java
new file mode 100644
index 000000000..a13a305b8
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/RenewalProcessor.java
@@ -0,0 +1,344 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.math.BigInteger;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Locale;
+
+import javax.servlet.http.HttpServletRequest;
+
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.BadRequestDataException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.cert.CertEnrollmentRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.profile.SSLClientCertProvider;
+
+public class RenewalProcessor extends CertProcessor {
+
+ public RenewalProcessor(String id, Locale locale) throws EPropertyNotFound, EBaseException {
+ super(id, locale);
+ }
+
+ public HashMap<String, Object> processRenewal(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ String profileId = (this.profileID == null) ? req.getParameter("profileId") : this.profileID;
+ IProfile profile = ps.getProfile(profileId);
+ if (profile == null) {
+ throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId));
+ }
+
+ CertEnrollmentRequest data = CertEnrollmentRequestFactory.create(cmsReq, profile, locale);
+
+ //only used in renewal
+ data.setSerialNum(req.getParameter("serial_num"));
+
+ return processRenewal(data, req);
+ }
+
+ /*
+ * Renewal - Renewal is retrofitted into the Profile Enrollment
+ * Framework. The authentication and authorization are taken from
+ * the renewal profile, while the input (with requests) and grace
+ * period constraint are taken from the original cert's request record.
+ *
+ * Things to note:
+ * * the renew request will contain the original profile instead of the new
+ */
+ public HashMap<String, Object> processRenewal(CertEnrollmentRequest data, HttpServletRequest request)
+ throws EBaseException {
+ try {
+ if (CMS.debugOn()) {
+ HashMap<String,String> params = data.toParams();
+ printParameterValues(params);
+ }
+ CMS.debug("RenewalSubmitter: isRenewal true");
+
+ startTiming("enrollment");
+ request.setAttribute("reqType", "renewal");
+
+ // in case of renew, "profile" is the orig profile
+ // while "renewProfile" is the current profile used for renewal
+ String renewProfileId = (this.profileID == null) ? data.getProfileId() : this.profileID;
+ CMS.debug("processRenewal: renewProfileId " + renewProfileId);
+
+ IProfile renewProfile = ps.getProfile(renewProfileId);
+ if (renewProfile == null) {
+ CMS.debug(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", renewProfileId));
+ throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", renewProfileId));
+ }
+ if (!ps.isProfileEnable(renewProfileId)) {
+ CMS.debug("RenewalSubmitter: Profile " + renewProfileId + " not enabled");
+ throw new BadRequestDataException("Profile " + renewProfileId + " not enabled");
+ }
+
+ String serial = data.getSerialNum();
+ BigInteger certSerial = null;
+
+ if (serial != null) {
+ // if serial number is sent with request, then the authentication
+ // method is not ssl client auth. In this case, an alternative
+ // authentication method is used (default: ldap based)
+ // usr_origreq evaluator should be used to authorize ownership
+ // of the cert
+ CMS.debug("RenewalSubmitter: renewal: found serial_num");
+ certSerial = new BigInteger(serial);
+ } else {
+ // ssl client auth is to be used
+ // this is not authentication. Just use the cert to search
+ // for orig request and find the right profile
+ CMS.debug("RenewalSubmitter: renewal: serial_num not found, must do ssl client auth");
+ certSerial = getSerialNumberFromCert(request);
+ if (certSerial == null) {
+ CMS.debug(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR"));
+ throw new EBaseException(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR"));
+ }
+ }
+ CMS.debug("processRenewal: serial number of cert to renew:" + certSerial.toString());
+ ICertRecord rec = certdb.readCertificateRecord(certSerial);
+ if (rec == null) {
+ CMS.debug("processRenewal: cert record not found for serial number " + certSerial.toString());
+ throw new EBaseException(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR"));
+ }
+
+ // check to see if the cert is revoked or revoked_expired
+ if ((rec.getStatus().equals(ICertRecord.STATUS_REVOKED))
+ || (rec.getStatus().equals(ICertRecord.STATUS_REVOKED_EXPIRED))) {
+ CMS.debug("processRenewal: cert found to be revoked. Serial number = "
+ + certSerial.toString());
+ throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_CA_CANNOT_RENEW_REVOKED_CERT"));
+ }
+
+ X509CertImpl origCert = rec.getCertificate();
+ if (origCert == null) {
+ CMS.debug("processRenewal: original cert not found in cert record for serial number "
+ + certSerial.toString());
+ throw new EBaseException(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR"));
+ }
+
+ Date origNotAfter = origCert.getNotAfter();
+ CMS.debug("processRenewal: origNotAfter =" + origNotAfter.toString());
+
+ String origSubjectDN = origCert.getSubjectDN().getName();
+ CMS.debug("processRenewal: orig subj dn =" + origSubjectDN);
+
+ IRequest origReq = getOriginalRequest(certSerial, rec);
+ if (origReq == null) {
+ CMS.debug("processRenewal: original request not found");
+ throw new EBaseException(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR"));
+ }
+
+ String profileId = origReq.getExtDataInString("profileId");
+ CMS.debug("RenewalSubmitter: renewal original profileId=" + profileId);
+
+ Integer origSeqNum = origReq.getExtDataInInteger(IEnrollProfile.REQUEST_SEQ_NUM);
+ IProfile profile = ps.getProfile(profileId);
+ if (profile == null) {
+ CMS.debug(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId));
+ throw new EBaseException(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId));
+ }
+ if (!ps.isProfileEnable(profileId)) {
+ CMS.debug("RenewalSubmitter: Profile " + profileId + " not enabled");
+ throw new BadRequestDataException("Profile " + profileId + " not enabled");
+ }
+
+ IProfileContext ctx = profile.createContext();
+ IProfileAuthenticator authenticator = renewProfile.getAuthenticator();
+ IProfileAuthenticator origAuthenticator = profile.getAuthenticator();
+
+ if (authenticator != null) {
+ CMS.debug("RenewalSubmitter: authenticator " + authenticator.getName() + " found");
+ setCredentialsIntoContext(request, authenticator, ctx);
+ }
+
+ // for renewal, this will override or add auth info to the profile context
+ if (origAuthenticator != null) {
+ CMS.debug("RenewalSubmitter: for renewal, original authenticator " +
+ origAuthenticator.getName() + " found");
+ setCredentialsIntoContext(request, origAuthenticator, ctx);
+ }
+
+ // for renewal, input needs to be retrieved from the orig req record
+ CMS.debug("processRenewal: set original Inputs into profile Context");
+ setInputsIntoContext(origReq, profile, ctx, locale);
+ ctx.set(IEnrollProfile.CTX_RENEWAL, "true");
+ ctx.set("renewProfileId", renewProfileId);
+ ctx.set(IEnrollProfile.CTX_RENEWAL_SEQ_NUM, origSeqNum.toString());
+
+ // for ssl authentication; pass in servlet for retrieving
+ // ssl client certificates
+ SessionContext context = SessionContext.getContext();
+ context.put("profileContext", ctx);
+ context.put("sslClientCertProvider", new SSLClientCertProvider(request));
+ CMS.debug("RenewalSubmitter: set sslClientCertProvider");
+ if (origSubjectDN != null)
+ context.put("origSubjectDN", origSubjectDN);
+
+ // before creating the request, authenticate the request
+ IAuthToken authToken = authenticate(request, origReq, authenticator, context, true);
+
+ // authentication success, now authorize
+ authorize(profileId, renewProfile, authToken);
+
+ ///////////////////////////////////////////////
+ // create and populate requests
+ ///////////////////////////////////////////////
+ startTiming("request_population");
+ IRequest[] reqs = profile.createRequests(ctx, locale);
+ populateRequests(data, true, locale, origNotAfter, origSubjectDN, origReq, profileId,
+ profile, ctx, authenticator, authToken, reqs);
+ endTiming("request_population");
+
+ ///////////////////////////////////////////////
+ // submit request
+ ///////////////////////////////////////////////
+ String errorCode = submitRequests(locale, profile, authToken, reqs);
+ String errorReason = codeToReason(locale, errorCode);
+
+ HashMap<String, Object> ret = new HashMap<String, Object>();
+ ret.put(ARG_REQUESTS, reqs);
+ ret.put(ARG_ERROR_CODE, errorCode);
+ ret.put(ARG_ERROR_REASON, errorReason);
+ ret.put(ARG_PROFILE, profile);
+
+ CMS.debug("RenewalSubmitter: done serving");
+ endTiming("enrollment");
+
+ return ret;
+ } finally {
+ SessionContext.releaseContext();
+ endAllEvents();
+ }
+ }
+
+ private BigInteger getSerialNumberFromCert(HttpServletRequest request) throws EBaseException {
+ BigInteger certSerial;
+ SSLClientCertProvider sslCCP = new SSLClientCertProvider(request);
+ X509Certificate[] certs = sslCCP.getClientCertificateChain();
+ certSerial = null;
+ if (certs == null || certs.length == 0) {
+ CMS.debug("RenewalSubmitter: renewal: no ssl client cert chain");
+ return null;
+ } else { // has ssl client cert
+ CMS.debug("RenewalSubmitter: renewal: has ssl client cert chain");
+ // shouldn't expect leaf cert to be always at the
+ // same location
+ X509Certificate clientCert = null;
+ for (int i = 0; i < certs.length; i++) {
+ clientCert = certs[i];
+ byte[] extBytes = clientCert.getExtensionValue("2.5.29.19");
+ // try to see if this is a leaf cert
+ // look for BasicConstraint extension
+ if (extBytes == null) {
+ // found leaf cert
+ CMS.debug("RenewalSubmitter: renewal: found leaf cert");
+ break;
+ } else {
+ CMS.debug("RenewalSubmitter: renewal: found cert having BasicConstraints ext");
+ // it's got BasicConstraints extension
+ // so it's not likely to be a leaf cert,
+ // however, check the isCA field regardless
+ try {
+ BasicConstraintsExtension bce =
+ new BasicConstraintsExtension(true, extBytes);
+ if (bce != null) {
+ if (!(Boolean) bce.get("is_ca")) {
+ CMS.debug("RenewalSubmitter: renewal: found CA cert in chain");
+ break;
+ } // else found a ca cert, continue
+ }
+ } catch (Exception e) {
+ CMS.debug("RenewalSubmitter: renewal: exception:" + e.toString());
+ return null;
+ }
+ }
+ }
+ if (clientCert == null) {
+ CMS.debug("RenewalSubmitter: renewal: no client cert in chain");
+ return null;
+ }
+ // convert to java X509 cert interface
+ try {
+ byte[] certEncoded = clientCert.getEncoded();
+ clientCert = new X509CertImpl(certEncoded);
+ } catch (Exception e) {
+ e.printStackTrace();
+ CMS.debug("RenewalSubmitter: renewal: exception:" + e.toString());
+ return null;
+ }
+
+ certSerial = clientCert.getSerialNumber();
+ }
+ return certSerial;
+ }
+
+ /*
+ * fill input info from "request" to context.
+ * This is expected to be used by renewal where the request
+ * is retrieved from request record
+ */
+ private void setInputsIntoContext(IRequest request, IProfile profile, IProfileContext ctx, Locale locale) {
+ // passing inputs into context
+ Enumeration<String> inputIds = profile.getProfileInputIds();
+
+ if (inputIds != null) {
+ while (inputIds.hasMoreElements()) {
+ String inputId = inputIds.nextElement();
+ IProfileInput profileInput = profile.getProfileInput(inputId);
+ Enumeration<String> inputNames = profileInput.getValueNames();
+
+ while (inputNames.hasMoreElements()) {
+ String inputName = inputNames.nextElement();
+ String inputValue = "";
+ CMS.debug("RenewalSubmitter: setInputsIntoContext() getting input name= " + inputName);
+ try {
+ inputValue = profileInput.getValue(inputName, locale, request);
+ } catch (Exception e) {
+ CMS.debug("RenewalSubmitter: setInputsIntoContext() getvalue() failed: " + e.toString());
+ }
+
+ if (inputValue != null) {
+ CMS.debug("RenewalSubmitter: setInputsIntoContext() setting value in ctx:" + inputValue);
+ ctx.set(inputName, inputValue);
+ } else {
+ CMS.debug("RenewalSubmitter: setInputsIntoContext() value null");
+ }
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/RenewalServlet.java b/base/server/cms/src/com/netscape/cms/servlet/cert/RenewalServlet.java
new file mode 100644
index 000000000..a697e14e4
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/RenewalServlet.java
@@ -0,0 +1,523 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+import netscape.security.extensions.CertInfo;
+import netscape.security.x509.CertificateSerialNumber;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+
+/**
+ * Certificate Renewal
+ *
+ * @version $Revision$, $Date$
+ */
+public class RenewalServlet extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3094124661102395244L;
+
+ // renewal templates.
+ public static final String RENEWAL_SUCCESS_TEMPLATE = "RenewalSuccess.template";
+
+ // http params
+ public static final String CERT_TYPE = "certType";
+ public static final String SERIAL_NO = "serialNo";
+ // XXX can't do pkcs10 cause it's got no serial no.
+ // (unless put serial no in pki attributes)
+ // public static final String PKCS10 = "pkcs10";
+ public static final String IMPORT_CERT = "importCert";
+
+ private String mRenewalSuccessTemplate = RENEWAL_SUCCESS_TEMPLATE;
+ private ICMSTemplateFiller mRenewalSuccessFiller = new ImportCertsTemplateFiller();
+
+ public RenewalServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet makes use of the
+ * template file "RenewalSuccess.template" to render the
+ * response
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success template. has same info as enrollment.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ try {
+ mRenewalSuccessTemplate = sc.getInitParameter(
+ PROP_SUCCESS_TEMPLATE);
+ if (mRenewalSuccessTemplate == null)
+ mRenewalSuccessTemplate = RENEWAL_SUCCESS_TEMPLATE;
+ String fillername =
+ sc.getInitParameter(PROP_SUCCESS_TEMPLATE_FILLER);
+
+ if (fillername != null) {
+ ICMSTemplateFiller filler = newFillerObject(fillername);
+
+ if (filler != null)
+ mRenewalSuccessFiller = filler;
+ }
+ } catch (Exception e) {
+ // this should never happen.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_IMP_INIT_SERV_ERR", e.toString(),
+ mId));
+ }
+
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ long startTime = CMS.getCurrentDate().getTime();
+ IArgBlock httpParams = cmsReq.getHttpParams();
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+
+ // renewal requires either:
+ // - coming from ee:
+ // - old cert from ssl client auth
+ // - old certs from auth manager
+ // - coming from agent or trusted RA:
+ // - serial no of cert to be renewed.
+
+ BigInteger old_serial_no = null;
+ X509CertImpl old_cert = null;
+ X509CertImpl renewed_cert = null;
+ Date notBefore = null;
+ Date notAfter = null;
+ boolean doSaveAuthToken = false;
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "renew");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ String authMgr = AuditFormat.NOAUTH;
+
+ if (authToken != null && !mAuthMgr.equals("sslClientCertAuthMgr")) {
+ authMgr =
+ authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ }
+
+ // coming from agent
+ if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) {
+ X509Certificate[] cert = new X509Certificate[1];
+
+ old_serial_no = getCertFromAgent(httpParams, cert);
+ old_cert = (X509CertImpl) cert[0];
+
+ // optional validity params from input.
+ int beginYear = httpParams.getValueAsInt("beginYear", -1);
+ int beginMonth = httpParams.getValueAsInt("beginMonth", -1);
+ int beginDate = httpParams.getValueAsInt("beginDate", -1);
+ int endYear = httpParams.getValueAsInt("endYear", -1);
+ int endMonth = httpParams.getValueAsInt("endMonth", -1);
+ int endDate = httpParams.getValueAsInt("endDate", -1);
+
+ if (beginYear != -1 && beginMonth != -1 && beginDate != -1 &&
+ endYear != -1 && endMonth != -1 && endDate != -1) {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(beginYear, beginMonth, beginDate);
+ notBefore = calendar.getTime();
+ calendar.set(endYear, endMonth, endDate);
+ notAfter = calendar.getTime();
+ }
+ } // coming from client
+ else {
+ // from auth manager
+ X509CertImpl[] cert = new X509CertImpl[1];
+
+ old_serial_no = getCertFromAuthMgr(authToken, cert);
+ old_cert = cert[0];
+ }
+
+ IRequest req = null;
+
+ try {
+ // get ready to send request to request queue.
+ X509CertInfo new_certInfo = null;
+
+ req = mRequestQueue.newRequest(IRequest.RENEWAL_REQUEST);
+ req.setExtData(IRequest.OLD_SERIALS, new BigInteger[] { old_serial_no });
+ if (old_cert != null) {
+ req.setExtData(IRequest.OLD_CERTS,
+ new X509CertImpl[] { old_cert }
+ );
+ // create new certinfo from old_cert contents.
+ X509CertInfo old_certInfo = (X509CertInfo)
+ old_cert.get(X509CertImpl.NAME + "." + X509CertImpl.INFO);
+
+ new_certInfo = new X509CertInfo(old_certInfo.getEncodedInfo());
+ } else {
+ // if no old cert (came from RA agent) create new cert info
+ // (serializable) to pass through policies. And set the old
+ // serial number to pick up.
+ new_certInfo = new CertInfo();
+ new_certInfo.set(X509CertInfo.SERIAL_NUMBER,
+ new CertificateSerialNumber(old_serial_no));
+ }
+
+ if (notBefore == null || notAfter == null) {
+ notBefore = new Date(0);
+ notAfter = new Date(0);
+ }
+ new_certInfo.set(X509CertInfo.VALIDITY,
+ new CertificateValidity(notBefore, notAfter));
+ req.setExtData(IRequest.CERT_INFO, new X509CertInfo[] { new_certInfo }
+ );
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_SETTING_RENEWAL_VALIDITY_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SETTING_RENEWAL_VALIDITY_ERROR"));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_SETTING_RENEWAL_VALIDITY_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SETTING_RENEWAL_VALIDITY_ERROR"));
+ }
+
+ saveHttpHeaders(httpReq, req);
+ saveHttpParams(httpParams, req);
+ if (doSaveAuthToken)
+ saveAuthToken(authToken, req);
+ cmsReq.setIRequest(req);
+
+ // send request to request queue.
+ mRequestQueue.processRequest(req);
+
+ // for audit log
+ String initiative = null;
+ String agentID = null;
+
+ if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) {
+ agentID = authToken.getInString("userid");
+ initiative = AuditFormat.FROMAGENT + " agentID: " + agentID;
+ } else {
+ // request is from eegateway, so fromUser.
+ initiative = AuditFormat.FROMUSER;
+ }
+
+ // check resulting status
+ RequestStatus status = req.getRequestStatus();
+
+ if (status != RequestStatus.COMPLETE) {
+ cmsReq.setIRequestStatus();
+ // audit log the status
+ if (status == RequestStatus.REJECTED) {
+ Vector<String> messages = req.getExtDataInStringVector(IRequest.ERRORS);
+
+ if (messages != null) {
+ Enumeration<String> msgs = messages.elements();
+ StringBuffer wholeMsg = new StringBuffer();
+
+ while (msgs.hasMoreElements()) {
+ wholeMsg.append("\n");
+ wholeMsg.append(msgs.nextElement());
+ }
+
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.RENEWALFORMAT,
+ new Object[] {
+ req.getRequestId(),
+ initiative,
+ authMgr,
+ status.toString(),
+ old_cert.getSubjectDN(),
+ old_cert.getSerialNumber().toString(16),
+ "violation: " +
+ wholeMsg.toString() }
+ // wholeMsg},
+ // ILogger.L_MULTILINE
+ );
+ } else { // no policy violation, from agent
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.RENEWALFORMAT,
+ new Object[] {
+ req.getRequestId(),
+ initiative,
+ authMgr,
+ status.toString(),
+ old_cert.getSubjectDN(),
+ old_cert.getSerialNumber().toString(16),
+ "" }
+ );
+ }
+ } else { // other imcomplete status
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.RENEWALFORMAT,
+ new Object[] {
+ req.getRequestId(),
+ initiative,
+ authMgr,
+ status.toString(),
+ old_cert.getSubjectDN(),
+ old_cert.getSerialNumber().toString(16),
+ "" }
+ );
+ }
+ return;
+ }
+
+ // service error
+ Integer result = req.getExtDataInInteger(IRequest.RESULT);
+
+ CMS.debug(
+ "RenewalServlet: Result for request " + req.getRequestId() + " is " + result);
+ if (result.equals(IRequest.RES_ERROR)) {
+ CMS.debug(
+ "RenewalServlet: Result for request " + req.getRequestId() + " is error.");
+
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(req.getExtDataInString(IRequest.ERROR));
+ String[] svcErrors =
+ req.getExtDataInStringArray(IRequest.SVCERRORS);
+
+ if (svcErrors != null && svcErrors.length > 0) {
+ for (int i = 0; i < svcErrors.length; i++) {
+ String err = svcErrors[i];
+
+ if (err != null) {
+ //System.out.println(
+ //"revocation servlet: setting error description "+
+ //err.toString());
+ cmsReq.setErrorDescription(err);
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.RENEWALFORMAT,
+ new Object[] {
+ req.getRequestId(),
+ initiative,
+ authMgr,
+ "completed with error: " +
+ err,
+ old_cert.getSubjectDN(),
+ old_cert.getSerialNumber().toString(16),
+ "" }
+ );
+
+ }
+ }
+ }
+ return;
+ }
+
+ // success.
+ X509CertImpl[] certs = req.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ renewed_cert = certs[0];
+ respondSuccess(cmsReq, renewed_cert);
+ long endTime = CMS.getCurrentDate().getTime();
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.RENEWALFORMAT,
+ new Object[] {
+ req.getRequestId(),
+ initiative,
+ authMgr,
+ "completed",
+ old_cert.getSubjectDN(),
+ old_cert.getSerialNumber().toString(16),
+ "new serial number: 0x" +
+ renewed_cert.getSerialNumber().toString(16) + " time: " + (endTime - startTime) }
+ );
+
+ return;
+ }
+
+ private void respondSuccess(
+ CMSRequest cmsReq, X509CertImpl renewed_cert)
+ throws EBaseException {
+ cmsReq.setResult(new X509CertImpl[] { renewed_cert }
+ );
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+
+ // check if cert should be imported.
+ // browser must have input type set to nav or cartman since
+ // there's no other way to tell
+
+ IArgBlock httpParams = cmsReq.getHttpParams();
+
+ if (checkImportCertToNav(cmsReq.getHttpResp(),
+ httpParams, renewed_cert)) {
+ return;
+ } else {
+ try {
+ renderTemplate(cmsReq,
+ mRenewalSuccessTemplate, mRenewalSuccessFiller);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGE_ERROR_DISPLAY_TEMPLATE_1",
+ mRenewalSuccessTemplate, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+ return;
+ }
+
+ protected BigInteger getRenewedCert(ICertRecord certRec)
+ throws EBaseException {
+ BigInteger renewedCert = null;
+ String serial = null;
+ MetaInfo meta = certRec.getMetaInfo();
+
+ if (meta == null) {
+ log(ILogger.LL_INFO,
+ "no meta info in cert serial 0x" + certRec.getSerialNumber().toString(16));
+ return null;
+ }
+ serial = (String) meta.get(ICertRecord.META_RENEWED_CERT);
+ if (serial == null) {
+ log(ILogger.LL_INFO,
+ "no renewed cert in cert 0x" + certRec.getSerialNumber().toString(16));
+ return null;
+ }
+ renewedCert = new BigInteger(serial);
+ log(ILogger.LL_INFO,
+ "renewed cert serial 0x" + renewedCert.toString(16) + "found for 0x" +
+ certRec.getSerialNumber().toString(16));
+ return renewedCert;
+ }
+
+ /**
+ * get certs to renew from agent.
+ */
+ private BigInteger getCertFromAgent(
+ IArgBlock httpParams, X509Certificate[] certContainer)
+ throws EBaseException {
+ BigInteger serialno = null;
+ X509Certificate cert = null;
+
+ // get serial no
+ serialno = httpParams.getValueAsBigInteger(SERIAL_NO, null);
+ if (serialno == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_SERIALNO_FOR_RENEW"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_SERIALNO_FOR_RENEW"));
+ }
+ // get cert from db if we're cert authority.
+ if (mAuthority instanceof ICertificateAuthority) {
+ cert = getX509Certificate(serialno);
+ if (cert == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_SERIALNO_FOR_RENEW_1", serialno.toString(16)));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_CERT_FOR_RENEWAL"));
+ }
+ }
+ certContainer[0] = cert;
+ return serialno;
+ }
+
+ /**
+ * get cert to renew from auth manager
+ */
+ private BigInteger getCertFromAuthMgr(
+ IAuthToken authToken, X509Certificate[] certContainer)
+ throws EBaseException {
+ X509CertImpl cert =
+ authToken.getInCert(AuthToken.TOKEN_CERT);
+
+ if (cert == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_CERTS_RENEW_FROM_AUTHMGR"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_CERTS_RENEW_FROM_AUTHMGR"));
+ }
+ if (mAuthority instanceof ICertificateAuthority &&
+ !isCertFromCA(cert)) {
+ log(ILogger.LL_FAILURE, "certficate from auth manager for " +
+ " renewal is not from this ca.");
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_CERT_FOR_RENEWAL"));
+ }
+ certContainer[0] = cert;
+ BigInteger serialno = ((X509Certificate) cert).getSerialNumber();
+
+ return serialno;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java
new file mode 100644
index 000000000..2826f477e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java
@@ -0,0 +1,464 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+
+import javax.servlet.http.HttpServletRequest;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzException;
+import com.netscape.certsrv.base.BadRequestDataException;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.cert.CertReviewResponse;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EDeferException;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IPolicyConstraint;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileOutput;
+import com.netscape.certsrv.profile.IProfilePolicy;
+import com.netscape.certsrv.profile.PolicyDefault;
+import com.netscape.certsrv.profile.ProfileAttribute;
+import com.netscape.certsrv.profile.ProfileOutput;
+import com.netscape.certsrv.profile.ProfilePolicySet;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.profile.ProfileOutputFactory;
+
+public class RequestProcessor extends CertProcessor {
+
+ public RequestProcessor(String id, Locale locale) throws EPropertyNotFound, EBaseException {
+ super(id, locale);
+ }
+
+ public CertReviewResponse processRequest(CMSRequest cmsReq, IRequest request, String op) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ IRequest ireq = cmsReq.getIRequest();
+
+ String profileId = ireq.getExtDataInString("profileId");
+ IProfile profile = ps.getProfile(profileId);
+ CertReviewResponse data = CertReviewResponseFactory.create(
+ cmsReq, profile, authority.noncesEnabled(), locale);
+
+ processRequest(req, data, request, op);
+ return data;
+ }
+
+ public void processRequest(HttpServletRequest request, CertReviewResponse data, IRequest req, String op)
+ throws EBaseException {
+ try {
+ startTiming("approval");
+
+ IAuthToken authToken = null;
+
+ if (CMS.debugOn()) {
+ HashMap<String, String> params = data.toParams();
+ printParameterValues(params);
+ CMS.debug("processRequest op is " + op);
+ }
+
+ if (authMgr != null) {
+ authToken = authenticate(request);
+ }
+
+ AuthzToken authzToken = authorize(aclMethod, authToken, authzResourceName, "approve");
+ if (authzToken == null) {
+ throw new EAuthzException(CMS.getUserMessage(locale, "CMS_AUTHORIZATION_ERROR"));
+ }
+
+ if (authority.noncesEnabled()) {
+ Object id = data.getRequestId().toBigInteger();
+
+ String requestNonce = data.getNonce();
+ if (requestNonce == null) {
+ CMS.debug("RequestProcessor: Missing nonce");
+ throw new BadRequestException("Missing nonce.");
+ }
+
+ Long nonce = new Long(requestNonce.trim());
+ validateNonce(request, "cert-request", id, nonce);
+ }
+
+ CMS.debug("RequestProcessor: processRequest: start serving");
+
+ RequestId requestId = data.getRequestId();
+ if (requestId == null || requestId.equals("")) {
+ CMS.debug(CMS.getUserMessage(locale, "CMS_REQUEST_ID_NOT_FOUND"));
+ throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_REQUEST_ID_NOT_FOUND"));
+ }
+ CMS.debug("RequestProcessor: requestId=" + requestId);
+
+ // check if the request is in one of the terminal states
+ if (!req.getRequestStatus().equals(RequestStatus.PENDING)) {
+ CMS.debug(CMS.getUserMessage(locale, "CMS_REQUEST_NOT_PENDING", requestId.toString()));
+ throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_REQUEST_NOT_PENDING",
+ requestId.toString()));
+ }
+
+ // save auth token in request
+ saveAuthToken(authToken, req);
+
+ String profileId = req.getExtDataInString("profileId");
+ if (profileId == null || profileId.equals("")) {
+ CMS.debug("RequestProcessor: Profile Id not found in request");
+ throw new EBaseException(CMS.getUserMessage(locale, "CMS_PROFILE_ID_NOT_FOUND"));
+ }
+ CMS.debug("RequestProcessor: profileId=" + profileId);
+
+ IProfile profile = ps.getProfile(profileId);
+ if (profile == null) {
+ CMS.debug(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId));
+ throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId));
+ }
+ if (!ps.isProfileEnable(profileId)) {
+ CMS.debug("RequestProcessor: Profile " + profileId + " not enabled");
+ throw new BadRequestDataException("Profile " + profileId + " not enabled");
+ }
+
+ if (op.equals("assign")) {
+ String owner = req.getRequestOwner();
+
+ // assigned owner
+ if (owner != null && owner.length() > 0) {
+ if (!grantPermission(req, authToken)) {
+ CMS.debug("RequestProcessor: Permission not granted to assign request.");
+ throw new EAuthzException(CMS.getUserMessage(locale, "CMS_PROFILE_DENY_OPERATION"));
+ }
+ }
+ String id = auditSubjectID();
+ req.setRequestOwner(id);
+ } else {
+ if (grantPermission(req, authToken)) {
+ if (op.equals("approve")) {
+ checkProfileVersion(profile, req);
+ updateValues(data, req, profile, locale);
+ updateNotes(data, req);
+ approveRequest(req, data, profile, locale);
+ } else if (op.equals("reject")) {
+ updateNotes(data, req);
+ rejectRequest(req);
+ } else if (op.equals("cancel")) {
+ updateNotes(data, req);
+ cancelRequest(req);
+ } else if (op.equals("update")) {
+ checkProfileVersion(profile, req);
+ updateValues(data, req, profile, locale);
+ updateNotes(data, req);
+ } else if (op.equals("validate")) {
+ updateValues(data, req, profile, locale);
+ } else if (op.equals("unassign")) {
+ req.setRequestOwner("");
+ }
+ } else {
+ CMS.debug("RequestProcessor: Permission not granted to approve/reject/cancel/update/validate/unassign request.");
+ throw new EAuthzException(CMS.getUserMessage(locale, "CMS_PROFILE_DENY_OPERATION"));
+ }
+ }
+
+ // commit request to the storage
+ if (!op.equals("validate")) {
+ if (op.equals("approve")) {
+ queue.markAsServiced(req);
+ } else {
+ queue.updateRequest(req);
+ }
+ }
+ endTiming("approval");
+
+ } finally {
+ endAllEvents();
+ }
+ }
+
+ private boolean grantPermission(IRequest req, IAuthToken token) {
+ boolean enable = false;
+ try {
+ enable = CMS.getConfigStore().getBoolean("request.assignee.enable", false);
+ } catch (EBaseException e) {
+ }
+
+ if (!enable)
+ return true;
+ String owner = req.getRequestOwner();
+
+ // unassigned owner
+ if (owner == null || owner.length() == 0)
+ return true;
+ String uid = token.getInString(IAuthToken.USER_ID);
+ if (uid.equals(owner))
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Check if the request creation time is older than the profile
+ * lastModified attribute.
+ */
+ private void checkProfileVersion(IProfile profile, IRequest req) throws EProfileException {
+ IConfigStore profileConfig = profile.getConfigStore();
+ if (profileConfig != null) {
+ String lastModified = null;
+
+ try {
+ lastModified = profileConfig.getString("lastModified", "");
+ } catch (EBaseException e) {
+ }
+
+ if (!lastModified.equals("")) {
+ Date profileModifiedAt = new Date(Long.parseLong(lastModified));
+ CMS.debug("CertRequestExecutor: Profile Last Modified=" +
+ profileModifiedAt);
+ Date reqCreatedAt = req.getCreationTime();
+ CMS.debug("CertRequestExecutor: Request Created At=" +
+ reqCreatedAt);
+ if (profileModifiedAt.after(reqCreatedAt)) {
+ CMS.debug("Profile Newer Than Request");
+ throw new ERejectException("Profile Newer Than Request");
+ }
+ }
+ }
+ }
+
+ /**
+ * Cancel request
+ * <P>
+ *
+ * (Certificate Request Processed - a manual "agent" profile based cert cancellation)
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been
+ * through the approval process
+ * </ul>
+ *
+ *
+ * @param req the certificate request
+ * @exception EProfileException an error related to this profile has
+ * occurred
+ */
+ private void cancelRequest(IRequest req) throws EProfileException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRequesterID = auditRequesterID(req);
+ String auditInfoValue = auditInfoValue(req);
+
+ req.setRequestStatus(RequestStatus.CANCELED);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_CANCELLATION,
+ auditInfoValue);
+
+ audit(auditMessage);
+ }
+
+ /**
+ * Reject request
+ * <P>
+ *
+ * (Certificate Request Processed - a manual "agent" profile based cert rejection)
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been
+ * through the approval process
+ * </ul>
+ *
+ * @param req the certificate request
+ * @exception EProfileException an error related to this profile has
+ * occurred
+ */
+ private void rejectRequest(IRequest req) throws EProfileException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRequesterID = auditRequesterID(req);
+ String auditInfoValue = auditInfoValue(req);
+
+ req.setRequestStatus(RequestStatus.REJECTED);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_REJECTION,
+ auditInfoValue);
+
+ audit(auditMessage);
+ }
+
+ /**
+ * Approve request
+ * <P>
+ *
+ * (Certificate Request Processed - a manual "agent" profile based cert acceptance)
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been
+ * through the approval process
+ * </ul>
+ *
+ * @param request the servlet request
+ * @param req the certificate request
+ * @param profile this profile
+ * @param locale the system locale
+ * @exception EProfileException an error related to this profile has
+ * occurred
+ */
+ private void approveRequest(IRequest req, CertReviewResponse data, IProfile profile, Locale locale)
+ throws EProfileException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRequesterID = auditRequesterID(req);
+
+ try {
+ profile.execute(req);
+ req.setRequestStatus(RequestStatus.COMPLETE);
+
+ Enumeration<String> outputIds = profile.getProfileOutputIds();
+ while (outputIds.hasMoreElements()) {
+ IProfileOutput output = profile.getProfileOutput(outputIds.nextElement());
+ ProfileOutput addOutput = ProfileOutputFactory.create(output, req, locale);
+ data.addOutput(addOutput);
+ }
+
+ // retrieve the certificate
+ X509CertImpl theCert = req.getExtDataInCert(
+ IEnrollProfile.REQUEST_ISSUED_CERT);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_ACCEPTANCE,
+ auditInfoCertValue(theCert));
+
+ audit(auditMessage);
+
+ } catch (EProfileException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_ACCEPTANCE,
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+
+ audit(auditMessage);
+
+ CMS.debug("CertRequestExecutor: about to throw EProfileException because of bad profile execute.");
+ throw eAudit1;
+ }
+ }
+
+ private void updateValues(CertReviewResponse data, IRequest req,
+ IProfile profile, Locale locale)
+ throws ERejectException, EDeferException, EPropertyException {
+
+ // put request policy defaults in a local hash
+ HashMap<String, String> policyData = new HashMap<String,String>();
+ for (ProfilePolicySet policySet: data.getPolicySets()) {
+ for (com.netscape.certsrv.profile.ProfilePolicy policy: policySet.getPolicies()) {
+ PolicyDefault def = policy.getDef();
+ List<ProfileAttribute> attrs = def.getAttributes();
+ for (ProfileAttribute attr: attrs) {
+ policyData.put(attr.getName(), attr.getValue());
+ }
+ }
+ }
+
+ String profileSetId = req.getExtDataInString("profileSetId");
+
+ Enumeration<IProfilePolicy> policies = profile.getProfilePolicies(profileSetId);
+ int count = 0;
+
+ while (policies.hasMoreElements()) {
+ IProfilePolicy policy = policies.nextElement();
+
+ setValue(locale, count, policy, req, policyData);
+ count++;
+ }
+
+ policies = profile.getProfilePolicies(profileSetId);
+ count = 0;
+ while (policies.hasMoreElements()) {
+ IProfilePolicy policy = policies.nextElement();
+
+ validate(count, policy, req);
+ count++;
+ }
+
+ }
+
+ private void updateNotes(CertReviewResponse data, IRequest req) {
+ String notes = data.getRequestNotes();
+
+ if (notes != null) {
+ req.setExtData("requestNotes", notes);
+ }
+ }
+
+ private void validate(int count, IProfilePolicy policy, IRequest req)
+ throws ERejectException, EDeferException {
+ IPolicyConstraint con = policy.getConstraint();
+
+ con.validate(req);
+ }
+
+ private void setValue(Locale locale, int count, IProfilePolicy policy, IRequest req,
+ HashMap<String, String> data) throws EPropertyException {
+ // handle default policy
+ IPolicyDefault def = policy.getDefault();
+ Enumeration<String> defNames = def.getValueNames();
+
+ while (defNames.hasMoreElements()) {
+ String defName = defNames.nextElement();
+ String defValue = data.get(defName);
+
+ def.setValue(defName, locale, req, defValue);
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/RevocationProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/RevocationProcessor.java
new file mode 100644
index 000000000..93b7531c8
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/RevocationProcessor.java
@@ -0,0 +1,525 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.Principal;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Locale;
+
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.InvalidityDateExtension;
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.UnauthorizedException;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.CertId;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.certsrv.usrgrp.Certificates;
+import com.netscape.certsrv.usrgrp.IUser;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class RevocationProcessor extends CertProcessor {
+
+ public final static String REVOKE = "revoke";
+ public final static String ON_HOLD = "on-hold";
+ public final static String OFF_HOLD = "off-hold";
+
+ public final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST =
+ "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_5";
+ public final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED =
+ "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED_7";
+
+ long startTime;
+
+ ICertificateAuthority authority;
+ ICertificateRepository repo;
+ IRequestQueue requestQueue;
+ IPublisherProcessor publisherProcessor;
+
+ String initiative;
+ RequestId requestID;
+ CertId serialNumber;
+ RevocationReason revocationReason;
+ Date invalidityDate;
+ String comments;
+ String requestType;
+
+ CRLExtensions entryExtn;
+ Collection<X509CertImpl> certificates = new ArrayList<X509CertImpl>();
+ Collection<RevokedCertImpl> revCertImpls = new ArrayList<RevokedCertImpl>();
+ IRequest request;
+ RequestStatus requestStatus;
+
+ public RevocationProcessor(String id, Locale locale) throws EPropertyNotFound, EBaseException {
+ super(id, locale);
+ }
+
+ public ICertificateAuthority getAuthority() {
+ return authority;
+ }
+
+ public void setAuthority(ICertificateAuthority authority) {
+ this.authority = authority;
+ repo = authority.getCertificateRepository();
+ requestQueue = authority.getRequestQueue();
+ publisherProcessor = authority.getPublisherProcessor();
+ }
+
+ public long getStartTime() {
+ return startTime;
+ }
+
+ public void setStartTime(long startTime) {
+ this.startTime = startTime;
+ }
+
+ public String getInitiative() {
+ return initiative;
+ }
+
+ public void setInitiative(String initiative) {
+ this.initiative = initiative;
+ }
+
+ public RequestId getRequestID() {
+ return requestID;
+ }
+
+ public void setRequestID(RequestId requestID) {
+ this.requestID = requestID;
+ }
+
+ public CertId getSerialNumber() {
+ return serialNumber;
+ }
+
+ public void setSerialNumber(CertId serialNumber) {
+ this.serialNumber = serialNumber;
+ }
+
+ public RevocationReason getRevocationReason() {
+ return revocationReason;
+ }
+
+ public void setRevocationReason(RevocationReason revocationReason) {
+ this.revocationReason = revocationReason;
+ }
+
+ public Date getInvalidityDate() {
+ return invalidityDate;
+ }
+
+ public void setInvalidityDate(Date invalidityDate) {
+ this.invalidityDate = invalidityDate;
+ }
+
+ public String getComments() {
+ return comments;
+ }
+
+ public void setComments(String comments) {
+ this.comments = comments;
+ }
+
+ public String getRequestType() {
+ return requestType;
+ }
+
+ public void setRequestType(String requestType) {
+ this.requestType = requestType;
+ }
+
+ public RequestStatus getRequestStatus() {
+ return requestStatus;
+ }
+
+ public void setRequestStatus(RequestStatus requestStatus) {
+ this.requestStatus = requestStatus;
+ }
+
+ public void addCertificate(X509CertImpl cert) {
+ certificates.add(cert);
+ }
+
+ public Collection<X509CertImpl> getCertificates() {
+ return certificates;
+ }
+
+ public IRequest getRequest() {
+ return request;
+ }
+
+ public boolean isMemberOfSubsystemGroup(X509Certificate clientCert) {
+
+ if (clientCert == null) {
+ return false;
+ }
+
+ try {
+ X509Certificate certChain[] = new X509Certificate[1];
+ certChain[0] = clientCert;
+
+ IUser user = ul.locateUser(new Certificates(certChain));
+ return ug.isMemberOf(user, "Subsystem Group");
+
+ } catch (Exception e) {
+ CMS.debug("RevocationProcessor: Failed to map certificate '" +
+ clientCert.getSubjectDN().getName() + "' to user.");
+ return false;
+ }
+ }
+
+ public void validateCertificateToRevoke(String subjectDN, ICertRecord targetRecord, boolean revokingCACert) {
+
+ X509CertImpl targetCert = targetRecord.getCertificate();
+ BigInteger targetSerialNumber = targetCert.getSerialNumber();
+ Principal targetSubjectDN = targetCert.getSubjectDN();
+
+ // Verify the subject DN matches the target cert's subject DN.
+ // Agent has null subject DN so he can revoke any certificate.
+ // Other users can only revoke their own certificate.
+ if (subjectDN != null && !subjectDN.equals(targetSubjectDN.toString())) {
+ throw new UnauthorizedException(
+ "Certificate 0x" + targetSerialNumber.toString(16) + " belongs to different subject.");
+ }
+
+ boolean targetIsCACert = isSystemCertificate(targetCert);
+
+ // If not revoking CA cert verify target cert is not CA cert.
+ if (!revokingCACert && targetIsCACert) {
+ throw new UnauthorizedException(
+ "Certificate 0x" + targetSerialNumber.toString(16) + " is a CA signing certificate");
+ }
+
+ // If revoking CA Cert verify target cert is CA cert.
+ if (revokingCACert && !targetIsCACert) {
+ throw new UnauthorizedException(
+ "Certificate 0x" + targetSerialNumber.toString(16) + " is not a CA signing certificate");
+ }
+
+ // Verify target cert is not already revoked.
+ if (targetRecord.getStatus().equals(ICertRecord.STATUS_REVOKED)) {
+ throw new BadRequestException(
+ CMS.getLogMessage("CA_CERTIFICATE_ALREADY_REVOKED_1", targetSerialNumber.toString(16)));
+ }
+ }
+
+ public void addCertificateToRevoke(X509CertImpl cert) {
+ addCertificate(cert);
+ revCertImpls.add(new RevokedCertImpl(cert.getSerialNumber(), CMS.getCurrentDate(), entryExtn));
+ }
+
+ public void addSerialNumberToUnrevoke(BigInteger serialNumber) throws EBaseException {
+ ICertRecord record = getCertificateRecord(serialNumber);
+ X509CertImpl cert = record.getCertificate();
+ addCertificate(cert);
+ }
+
+ public ICertRecord[] getCertificateRecords(BigInteger[] serialNumbers) throws EBaseException {
+ ICertRecord[] records = new ICertRecord[serialNumbers.length];
+ for (int i=0; i<serialNumbers.length; i++) {
+ records[i] = getCertificateRecord(serialNumbers[i]);
+ }
+ return records;
+ }
+
+ public ICertRecord getCertificateRecord(CertId id) throws EBaseException {
+ return getCertificateRecord(id.toBigInteger());
+ }
+
+ public ICertRecord getCertificateRecord(BigInteger serialNumber) throws EBaseException {
+ return repo.readCertificateRecord(serialNumber);
+ }
+
+ public X509CertImpl[] getCertificates(ICertRecord[] records) throws EBaseException {
+ X509CertImpl[] certs = new X509CertImpl[records.length];
+ for (int i=0; i<records.length; i++) {
+ certs[i] = records[i].getCertificate();
+ }
+ return certs;
+ }
+
+ public void createCRLExtension() throws IOException {
+
+ // Construct a CRL extension for this request.
+ entryExtn = new CRLExtensions();
+
+ // Construct a CRL reason code extension.
+ CRLReasonExtension crlReasonExtn = new CRLReasonExtension(revocationReason);
+ entryExtn.set(crlReasonExtn.getName(), crlReasonExtn);
+
+ // Construct a CRL invalidity date extension.
+ if (invalidityDate != null) {
+ InvalidityDateExtension invalidityDateExtn = new InvalidityDateExtension(invalidityDate);
+ entryExtn.set(invalidityDateExtn.getName(), invalidityDateExtn);
+ }
+ }
+
+ public void createRevocationRequest() throws EBaseException {
+
+ request = requestQueue.newRequest(IRequest.REVOCATION_REQUEST);
+
+ request.setExtData(IRequest.REQ_TYPE, IRequest.REVOCATION_REQUEST);
+
+ request.setExtData(IRequest.OLD_CERTS, certificates.toArray(new X509CertImpl[certificates.size()]));
+ request.setExtData(IRequest.CERT_INFO, revCertImpls.toArray(new RevokedCertImpl[revCertImpls.size()]));
+
+ if (AuditFormat.FROMUSER.equals(initiative)) {
+ request.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_EE);
+ } else {
+ request.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_AGENT);
+ }
+
+ if (comments != null) {
+ request.setExtData(IRequest.REQUESTOR_COMMENTS, comments);
+ }
+
+ request.setExtData(IRequest.REVOKED_REASON, revocationReason.toInt());
+ }
+
+ public void processRevocationRequest() throws EBaseException {
+
+ requestQueue.processRequest(request);
+ requestStatus = request.getRequestStatus();
+
+ CMS.debug("revokeCert: status: " + requestStatus);
+
+ String type = request.getRequestType();
+
+ // The SVC_PENDING check has been added for the Cloned CA request
+ // that is meant for the Master CA. From Clone's point of view
+ // the request is complete
+
+ if (requestStatus == RequestStatus.COMPLETE
+ || requestStatus == RequestStatus.SVC_PENDING
+ && type.equals(IRequest.CLA_CERT4CRL_REQUEST)) {
+
+ // audit log the error
+ Integer result = request.getExtDataInInteger(IRequest.RESULT);
+
+ if (result.equals(IRequest.RES_ERROR)) {
+ String[] svcErrors = request.getExtDataInStringArray(IRequest.SVCERRORS);
+
+ if (svcErrors != null) {
+ for (String err : svcErrors) {
+ //cmsReq.setErrorDescription(err);
+ for (X509CertImpl cert : certificates) {
+ logRevoke(
+ request, cert,
+ "completed with error: " + err,
+ revocationReason.toString());
+ }
+ }
+ }
+
+ throw new EBaseException(CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED"));
+ }
+
+ long endTime = CMS.getCurrentDate().getTime();
+
+ // audit log the success.
+ for (X509CertImpl cert : certificates) {
+ logRevoke(request, cert,
+ "completed",
+ revocationReason + " time: " + (endTime - startTime));
+ }
+
+ } else {
+
+ // audit log the pending, revoked and rest
+ for (X509CertImpl cert : certificates) {
+ logRevoke(request, cert,
+ requestStatus.toString(),
+ revocationReason.toString());
+ }
+ }
+ }
+
+ public void createUnrevocationRequest() throws EBaseException {
+
+ request = requestQueue.newRequest(IRequest.UNREVOCATION_REQUEST);
+
+ request.setExtData(IRequest.REQ_TYPE, IRequest.UNREVOCATION_REQUEST);
+
+ Collection<BigInteger> serialNumbers = new ArrayList<BigInteger>();
+ for (X509CertImpl cert : certificates) {
+ serialNumbers.add(cert.getSerialNumber());
+ }
+ request.setExtData(IRequest.OLD_SERIALS, serialNumbers.toArray(new BigInteger[serialNumbers.size()]));
+ request.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_AGENT);
+ }
+
+ public void processUnrevocationRequest() throws EBaseException {
+
+ requestQueue.processRequest(request);
+ requestStatus = request.getRequestStatus();
+
+ String type = request.getRequestType();
+
+ if (requestStatus == RequestStatus.COMPLETE
+ || requestStatus == RequestStatus.SVC_PENDING && type.equals(IRequest.CLA_UNCERT4CRL_REQUEST)) {
+
+ Integer result = request.getExtDataInInteger(IRequest.RESULT);
+
+ if (result != null && result.equals(IRequest.RES_SUCCESS)) {
+ for (X509CertImpl cert : certificates) {
+ logUnrevoke(request, cert, "completed");
+ }
+
+ } else {
+ String error = request.getExtDataInString(IRequest.ERROR);
+ for (X509CertImpl cert : certificates) {
+ logUnrevoke(request, cert, "completed with error: " + error);
+ }
+ }
+
+ } else {
+ for (X509CertImpl cert : certificates) {
+ logUnrevoke(request, cert, requestStatus.toString());
+ }
+ }
+ }
+
+ /**
+ * A system certificate such as the CA signing certificate
+ * should not be allowed to delete.
+ * The main purpose is to avoid revoking the self signed
+ * CA certificate accidentally.
+ */
+ public boolean isSystemCertificate(X509Certificate cert) {
+
+ X509Certificate caCert = authority.getCACert();
+ if (caCert == null)
+ return false;
+
+ // check whether it's a CA certificate
+ if (!caCert.getSerialNumber().equals(cert.getSerialNumber()))
+ return false;
+
+ // check whether it's a self-signed we certificate
+ return caCert.getSubjectDN().equals(caCert.getIssuerDN());
+ }
+
+ public void logRevoke(IRequest revocationRequest, X509Certificate cert, String status, String message) {
+
+ if (logger == null)
+ return;
+
+ logger.log(
+ ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ revocationRequest.getRequestId(),
+ initiative,
+ status,
+ cert.getSubjectDN(),
+ cert.getSerialNumber().toString(16),
+ message
+ });
+ }
+
+ public void logUnrevoke(IRequest unrevocationRequest, X509Certificate cert, String status) {
+
+ if (logger == null)
+ return;
+
+ logger.log(
+ ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOUNREVOKEFORMAT,
+ new Object[] {
+ unrevocationRequest.getRequestId(),
+ initiative,
+ status,
+ cert.getSubjectDN(),
+ cert.getSerialNumber().toString(16),
+ });
+ }
+
+ public void auditChangeRequest(String status) {
+
+ if (auditor == null)
+ return;
+
+ String auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST,
+ auditor.getSubjectID(),
+ status,
+ requestID == null ? ILogger.UNIDENTIFIED : requestID.toString(),
+ serialNumber == null ? ILogger.SIGNED_AUDIT_EMPTY_VALUE : serialNumber.toHexString(),
+ requestType);
+
+ auditor.log(auditMessage);
+ }
+
+ public void auditChangeRequestProcessed(String status) {
+
+ if (auditor == null)
+ return;
+
+ // store a message in the signed audit log file
+ // if and only if "requestStatus" is
+ // "complete", "revoked", or "canceled"
+
+ if (!(requestStatus == RequestStatus.COMPLETE
+ || requestStatus == RequestStatus.REJECTED
+ || requestStatus == RequestStatus.CANCELED)) return;
+
+ String auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED,
+ auditor.getSubjectID(),
+ status,
+ requestID == null ? ILogger.UNIDENTIFIED : requestID.toString(),
+ serialNumber == null ? ILogger.SIGNED_AUDIT_EMPTY_VALUE : serialNumber.toHexString(),
+ requestType,
+ String.valueOf(revocationReason.toInt()),
+ requestStatus == null ? ILogger.SIGNED_AUDIT_EMPTY_VALUE : requestStatus.toString());
+
+ auditor.log(auditMessage);
+ }
+
+ public void log(int level, String message) {
+ log(ILogger.S_CA, level, message);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/RevocationServlet.java b/base/server/cms/src/com/netscape/cms/servlet/cert/RevocationServlet.java
new file mode 100644
index 000000000..ec77d1cec
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/RevocationServlet.java
@@ -0,0 +1,394 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Random;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Perform the first step in revoking a certificate
+ *
+ * @version $Revision$, $Date$
+ */
+public class RevocationServlet extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -9086730404084717413L;
+ private final static String PROP_REVOKEBYDN = "revokeByDN";
+ // revocation templates.
+ private final static String TPL_FILE = "reasonToRevoke.template";
+
+ // http params
+ public static final String SERIAL_NO = "serialNo";
+ // XXX can't do pkcs10 cause it's got no serial no.
+ // (unless put serial no in pki attributes)
+ // public static final String PKCS10 = "pkcs10";
+ public static final String REASON_CODE = "reasonCode";
+
+ private String mFormPath = null;
+ private boolean mRevokeByDN = true;
+
+ private Random mRandom = null;
+
+ public RevocationServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses
+ * the template file "reasonToRevoke.template" to render the
+ * result.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success template. has same info as enrollment.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+
+ mFormPath = "/" + TPL_FILE;
+ try {
+ mFormPath = sc.getInitParameter(
+ PROP_SUCCESS_TEMPLATE);
+ if (mFormPath == null)
+ mFormPath = "/" + TPL_FILE;
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ if (((ICertificateAuthority) mAuthority).noncesEnabled()) {
+ mRandom = new Random();
+ }
+ }
+
+ // set to false by revokeByDN=false in web.xml
+ mRevokeByDN = false;
+ String tmp = sc.getInitParameter(PROP_REVOKEBYDN);
+
+ if (tmp == null || tmp.trim().equalsIgnoreCase("false"))
+ mRevokeByDN = false;
+ else if (tmp.trim().equalsIgnoreCase("true"))
+ mRevokeByDN = true;
+ } catch (Exception e) {
+ }
+ }
+
+ /**
+ * Process the HTTP request. Note that this servlet does not
+ * actually perform the certificate revocation. This is the first
+ * step in the multi-step revocation process. (the next step is
+ * in the ReasonToRevoke servlet.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ IArgBlock httpParams = cmsReq.getHttpParams();
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ // revocation requires either:
+ // - coming from ee:
+ // - old cert from ssl client auth
+ // - old certs from auth manager
+ // - coming from agent or trusted RA:
+ // - serial no of cert to be revoked.
+
+ BigInteger old_serial_no = null;
+ X509CertImpl old_cert = null;
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, httpReq, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "submit");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ // coming from agent
+ if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) {
+ X509Certificate[] cert = new X509Certificate[1];
+
+ old_serial_no = getCertFromAgent(httpParams, cert);
+ old_cert = (X509CertImpl) cert[0];
+ } // coming from client
+ else {
+ // from auth manager
+ X509CertImpl[] cert = new X509CertImpl[1];
+
+ old_serial_no = getCertFromAuthMgr(authToken, cert);
+ old_cert = cert[0];
+ }
+
+ header.addStringValue("serialNumber", old_cert.getSerialNumber().toString(16));
+ header.addStringValue("serialNumberDecimal", old_cert.getSerialNumber().toString());
+ // header.addStringValue("subject", old_cert.getSubjectDN().toString());
+ // header.addLongValue("validNotBefore", old_cert.getNotBefore().getTime()/1000);
+ // header.addLongValue("validNotAfter", old_cert.getNotAfter().getTime()/1000);
+
+ boolean noInfo = false;
+ X509CertImpl[] certsToRevoke = null;
+
+ if (mAuthority instanceof ICertificateAuthority) {
+
+ if (certAuthority.noncesEnabled()) {
+ // generate nonce
+ long n = mRandom.nextLong();
+ // store nonce in session
+ Map<Object, Long> nonces = certAuthority.getNonces(cmsReq.getHttpReq(), "cert-revoke");
+ nonces.put(old_serial_no, n);
+ // return serial number and nonce to client
+ header.addStringValue("nonce", old_serial_no+":"+n);
+ }
+
+ certsToRevoke = ((ICertificateAuthority) mAuthority).getCertificateRepository().getX509Certificates(
+ old_cert.getSubjectDN().toString(),
+ ICertificateRepository.ALL_UNREVOKED_CERTS);
+
+ } else if (mAuthority instanceof IRegistrationAuthority) {
+ IRequest req = mRequestQueue.newRequest(IRequest.GETCERTS_REQUEST);
+ String filter = "(&(" + ICertRecord.ATTR_X509CERT + "." +
+ X509CertInfo.SUBJECT + "=" +
+ old_cert.getSubjectDN().toString() + ")(|(" +
+ ICertRecord.ATTR_CERT_STATUS + "=" +
+ ICertRecord.STATUS_VALID + ")(" +
+ ICertRecord.ATTR_CERT_STATUS + "=" +
+ ICertRecord.STATUS_EXPIRED + ")))";
+
+ req.setExtData(IRequest.CERT_FILTER, filter);
+ mRequestQueue.processRequest(req);
+ RequestStatus status = req.getRequestStatus();
+
+ if (status == RequestStatus.COMPLETE) {
+ header.addStringValue("request", req.getRequestId().toString());
+ Enumeration<String> enum1 = req.getExtDataKeys();
+
+ while (enum1.hasMoreElements()) {
+ String name = enum1.nextElement();
+
+ if (name.equals(IRequest.OLD_CERTS)) {
+ X509CertImpl[] certs = req.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ certsToRevoke = certs;
+ }
+ }
+ } else {
+ noInfo = true;
+ }
+ }
+
+ boolean authorized = false;
+
+ if (certsToRevoke != null && certsToRevoke.length > 0) {
+ for (int i = 0; i < certsToRevoke.length; i++) {
+ if (old_cert.getSerialNumber().equals(certsToRevoke[i].getSerialNumber())) {
+ authorized = true;
+ break;
+ }
+ }
+ }
+
+ if (!noInfo && (certsToRevoke == null || certsToRevoke.length == 0 ||
+ (!authorized))) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CA_CERT_ALREADY_REVOKED_1", old_serial_no.toString(16)));
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_CERT_ALREADY_REVOKED"));
+ }
+
+ if (!mRevokeByDN || noInfo) {
+ certsToRevoke = new X509CertImpl[1];
+ certsToRevoke[0] = old_cert;
+ try {
+ byte[] ba = old_cert.getEncoded();
+ // Do base 64 encoding
+
+ header.addStringValue("b64eCertificate", Utils.base64encode(ba));
+ } catch (CertificateEncodingException e) {
+ }
+ }
+
+ if (certsToRevoke != null && certsToRevoke.length > 0) {
+ header.addIntegerValue("totalRecordCount", certsToRevoke.length);
+ header.addIntegerValue("verifiedRecordCount", certsToRevoke.length);
+
+ for (int i = 0; i < certsToRevoke.length; i++) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addStringValue("serialNumber",
+ certsToRevoke[i].getSerialNumber().toString(16));
+ rarg.addStringValue("serialNumberDecimal",
+ certsToRevoke[i].getSerialNumber().toString());
+ rarg.addStringValue("subject",
+ certsToRevoke[i].getSubjectDN().toString());
+ rarg.addLongValue("validNotBefore",
+ certsToRevoke[i].getNotBefore().getTime() / 1000);
+ rarg.addLongValue("validNotAfter",
+ certsToRevoke[i].getNotAfter().getTime() / 1000);
+ argSet.addRepeatRecord(rarg);
+ }
+ } else {
+ header.addIntegerValue("totalRecordCount", 0);
+ header.addIntegerValue("verifiedRecordCount", 0);
+ }
+
+ // set revocation reason, default to unspecified if not set.
+ int reasonCode = httpParams.getValueAsInt(REASON_CODE, 0);
+
+ header.addIntegerValue("reason", reasonCode);
+
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ return;
+ }
+
+ /**
+ * get cert to revoke from agent.
+ */
+ private BigInteger getCertFromAgent(
+ IArgBlock httpParams, X509Certificate[] certContainer)
+ throws EBaseException {
+ BigInteger serialno = null;
+ X509Certificate cert = null;
+
+ // get serial no
+ serialno = httpParams.getValueAsBigInteger(SERIAL_NO, null);
+ if (serialno == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_SERIALNO_FOR_REVOKE"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_SERIALNO_FOR_REVOKE"));
+ }
+
+ // get cert from db if we're cert authority.
+ if (mAuthority instanceof ICertificateAuthority) {
+ cert = getX509Certificate(serialno);
+ if (cert == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_INVALID_CERT_FOR_REVOCATION"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_CERT_FOR_REVOCATION"));
+ }
+ }
+ certContainer[0] = cert;
+ return serialno;
+ }
+
+ /**
+ * get cert to revoke from auth manager
+ */
+ private BigInteger getCertFromAuthMgr(
+ IAuthToken authToken, X509Certificate[] certContainer)
+ throws EBaseException {
+ X509CertImpl cert =
+ authToken.getInCert(AuthToken.TOKEN_CERT);
+
+ if (cert == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_CERTS_REVOKE_FROM_AUTHMGR"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_CERTS_REVOKE_FROM_AUTHMGR"));
+ }
+ if (mAuthority instanceof ICertificateAuthority &&
+ !isCertFromCA(cert)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_CERT_FOR_REVOCATION"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_CERT_FOR_REVOCATION"));
+ }
+ certContainer[0] = cert;
+ BigInteger serialno = ((X509Certificate) cert).getSerialNumber();
+
+ return serialno;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/RevocationSuccessTemplateFiller.java b/base/server/cms/src/com/netscape/cms/servlet/cert/RevocationSuccessTemplateFiller.java
new file mode 100644
index 000000000..2fce3e6e1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/RevocationSuccessTemplateFiller.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.util.Locale;
+
+import javax.servlet.http.HttpServletRequest;
+
+import netscape.security.x509.RevokedCertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+
+/**
+ * Certificates Template filler.
+ * must have list of certificates in result.
+ * looks at inputs: certtype.
+ * outputs:
+ * - cert type from http input (if any)
+ * - CA chain
+ * - authority name (RM, CM, DRM)
+ * - scheme:host:port of server.
+ * array of one or more
+ * - cert serial number
+ * - cert pretty print
+ * - cert in base 64 encoding.
+ * - cmmf blob to import
+ *
+ * @version $Revision$, $Date$
+ */
+class RevocationSuccessTemplateFiller implements ICMSTemplateFiller {
+ public final static String SERIAL_NO = "serialNo";
+
+ public RevocationSuccessTemplateFiller() {
+ }
+
+ /**
+ * @param cmsReq CMS Request
+ * @param authority this authority
+ * @param locale locale of template.
+ * @param e unexpected exception e. ignored.
+ */
+ public CMSTemplateParams getTemplateParams(
+ CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e)
+ throws Exception {
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams params = new CMSTemplateParams(null, fixed);
+
+ // set host name and port.
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ String host = httpReq.getServerName();
+ int port = httpReq.getServerPort();
+ String scheme = httpReq.getScheme();
+
+ fixed.set(ICMSTemplateFiller.HOST, host);
+ fixed.set(ICMSTemplateFiller.PORT, Integer.valueOf(port));
+ fixed.set(ICMSTemplateFiller.SCHEME, scheme);
+
+ // this authority
+ fixed.set(ICMSTemplateFiller.AUTHORITY, authority.getOfficialName());
+
+ // XXX CA chain.
+
+ RevokedCertImpl[] revoked =
+ (RevokedCertImpl[]) cmsReq.getResult();
+
+ // revoked certs.
+ for (int i = 0; i < revoked.length; i++) {
+ IArgBlock repeat = CMS.createArgBlock();
+
+ repeat.set(SERIAL_NO, revoked[i].getSerialNumber());
+ params.addRepeatRecord(repeat);
+ }
+
+ return params;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/SrchCerts.java b/base/server/cms/src/com/netscape/cms/servlet/cert/SrchCerts.java
new file mode 100644
index 000000000..508a8df70
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/SrchCerts.java
@@ -0,0 +1,761 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.security.PublicKey;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.provider.RSAPublicKey;
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.Extension;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.dbs.certdb.IRevocationInfo;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+/**
+ * Search for certificates matching complex query filter
+ *
+ * @version $Revision$, $Date$
+ */
+public class SrchCerts extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5876805830088921643L;
+ private final static String TPL_FILE = "srchCert.template";
+ private final static String PROP_MAX_SEARCH_RETURNS = "maxSearchReturns";
+
+ private final static String CURRENT_TIME = "currentTime";
+ private final static int MAX_RESULTS = 1000;
+
+ private ICertificateRepository mCertDB = null;
+ private X500Name mAuthName = null;
+ private String mFormPath = null;
+ private int mMaxReturns = MAX_RESULTS;
+ private int mTimeLimits = 30; /* in seconds */
+ private boolean mUseClientFilter = false;
+
+ /**
+ * Constructs query key servlet.
+ */
+ public SrchCerts() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses srchCert.template
+ * to render the response
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success to render own template.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+
+ if (mAuthority instanceof ISubsystem) {
+ ISubsystem sub = mAuthority;
+ IConfigStore authConfig = sub.getConfigStore();
+
+ if (authConfig != null) {
+ try {
+ mMaxReturns = authConfig.getInteger(PROP_MAX_SEARCH_RETURNS, MAX_RESULTS);
+ } catch (EBaseException e) {
+ // do nothing
+ }
+ }
+ }
+ if (mAuthority instanceof ICertificateAuthority) {
+ ICertificateAuthority ca = (ICertificateAuthority) mAuthority;
+
+ mCertDB = ca.getCertificateRepository();
+ mAuthName = ca.getX500Name();
+ }
+
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ /* Server-Side time limit */
+ try {
+ int maxResults = Integer.parseInt(sc.getInitParameter("maxResults"));
+ if (maxResults < mMaxReturns)
+ mMaxReturns = maxResults;
+ } catch (Exception e) {
+ /* do nothing, just use the default if integer parsing failed */
+ }
+ try {
+ mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits"));
+ } catch (Exception e) {
+ /* do nothing, just use the default if integer parsing failed */
+ }
+
+ /* useClientFilter should be off by default. We keep
+ this parameter around so that we do not break
+ the client applications that submits raw LDAP
+ filter into this servlet. */
+ if (sc.getInitParameter("useClientFilter") != null &&
+ sc.getInitParameter("useClientFilter").equalsIgnoreCase("true")) {
+ mUseClientFilter = true;
+ }
+ }
+
+ private boolean isOn(HttpServletRequest req, String name) {
+ String inUse = req.getParameter(name);
+ if (inUse == null) {
+ return false;
+ }
+ if (inUse.equals("on")) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isOff(HttpServletRequest req, String name) {
+ String inUse = req.getParameter(name);
+ if (inUse == null) {
+ return false;
+ }
+ if (inUse.equals("off")) {
+ return true;
+ }
+ return false;
+ }
+
+ private void buildCertStatusFilter(HttpServletRequest req, StringBuffer filter) {
+ if (!isOn(req, "statusInUse")) {
+ return;
+ }
+ String status = req.getParameter("status");
+ filter.append("(certStatus=");
+ filter.append(status);
+ filter.append(")");
+ }
+
+ private void buildProfileFilter(HttpServletRequest req, StringBuffer filter) {
+ if (!isOn(req, "profileInUse")) {
+ return;
+ }
+ String profile = req.getParameter("profile");
+ filter.append("(certMetaInfo=profileId:");
+ filter.append(profile);
+ filter.append(")");
+ }
+
+ private void buildBasicConstraintsFilter(HttpServletRequest req, StringBuffer filter) {
+ if (!isOn(req, "basicConstraintsInUse")) {
+ return;
+ }
+ filter.append("(x509cert.BasicConstraints.isCA=on)");
+ }
+
+ private void buildSerialNumberRangeFilter(HttpServletRequest req, StringBuffer filter) {
+ if (!isOn(req, "serialNumberRangeInUse")) {
+ return;
+ }
+ boolean changed = false;
+ String serialFrom = req.getParameter("serialFrom");
+ if (serialFrom != null && !serialFrom.equals("")) {
+ filter.append("(certRecordId>=" + serialFrom + ")");
+ changed = true;
+ }
+ String serialTo = req.getParameter("serialTo");
+ if (serialTo != null && !serialTo.equals("")) {
+ filter.append("(certRecordId<=" + serialTo + ")");
+ changed = true;
+ }
+ if (!changed) {
+ filter.append("(certRecordId=*)");
+ }
+ }
+
+ private void buildAVAFilter(HttpServletRequest req, String paramName,
+ String avaName, StringBuffer lf, String match) {
+ String val = req.getParameter(paramName);
+ if (val != null && !val.equals("")) {
+ if (match != null && match.equals("exact")) {
+ lf.append("(|");
+ lf.append("(x509cert.subject=*");
+ lf.append(avaName);
+ lf.append("=");
+ lf.append(LDAPUtil.escapeFilter(LDAPUtil.escapeRDNValue(val)));
+ lf.append(",*)");
+ lf.append("(x509cert.subject=*");
+ lf.append(avaName);
+ lf.append("=");
+ lf.append(LDAPUtil.escapeFilter(LDAPUtil.escapeRDNValue(val)));
+ lf.append(")");
+ lf.append(")");
+ } else {
+ lf.append("(x509cert.subject=*");
+ lf.append(avaName);
+ lf.append("=");
+ lf.append("*");
+ lf.append(LDAPUtil.escapeFilter(LDAPUtil.escapeRDNValue(val)));
+ lf.append("*)");
+ }
+ }
+ }
+
+ private void buildSubjectFilter(HttpServletRequest req, StringBuffer filter) {
+ if (!isOn(req, "subjectInUse")) {
+ return;
+ }
+ StringBuffer lf = new StringBuffer();
+ String match = req.getParameter("match");
+
+ buildAVAFilter(req, "eMail", "E", lf, match);
+ buildAVAFilter(req, "commonName", "CN", lf, match);
+ buildAVAFilter(req, "userID", "UID", lf, match);
+ buildAVAFilter(req, "orgUnit", "OU", lf, match);
+ buildAVAFilter(req, "org", "O", lf, match);
+ buildAVAFilter(req, "locality", "L", lf, match);
+ buildAVAFilter(req, "state", "ST", lf, match);
+ buildAVAFilter(req, "country", "C", lf, match);
+
+ if (lf.length() == 0) {
+ filter.append("(x509cert.subject=*)");
+ return;
+ }
+ if (match.equals("exact")) {
+ filter.append("(&");
+ filter.append(lf);
+ filter.append(")");
+ } else {
+ filter.append("(|");
+ filter.append(lf);
+ filter.append(")");
+ }
+ }
+
+ private void buildRevokedByFilter(HttpServletRequest req,
+ StringBuffer filter) {
+ if (!isOn(req, "revokedByInUse")) {
+ return;
+ }
+ String revokedBy = req.getParameter("revokedBy");
+ if (revokedBy == null || revokedBy.equals("")) {
+ filter.append("(certRevokedBy=*)");
+ } else {
+ filter.append("(certRevokedBy=");
+ filter.append(revokedBy);
+ filter.append(")");
+ }
+ }
+
+ private void buildDateFilter(HttpServletRequest req, String prefix,
+ String outStr, long adjustment,
+ StringBuffer filter) {
+ long epoch = 0;
+ try {
+ epoch = Long.parseLong(req.getParameter(prefix));
+ } catch (NumberFormatException e) {
+ // exception safely ignored
+ }
+ Calendar from = Calendar.getInstance();
+ from.setTimeInMillis(epoch);
+ CMS.debug("buildDateFilter epoch=" + req.getParameter(prefix));
+ CMS.debug("buildDateFilter from=" + from);
+ filter.append("(");
+ filter.append(outStr);
+ filter.append(Long.toString(from.getTimeInMillis() + adjustment));
+ filter.append(")");
+ }
+
+ private void buildRevokedOnFilter(HttpServletRequest req,
+ StringBuffer filter) {
+ if (!isOn(req, "revokedOnInUse")) {
+ return;
+ }
+ buildDateFilter(req, "revokedOnFrom", "certRevokedOn>=", 0, filter);
+ buildDateFilter(req, "revokedOnTo", "certRevokedOn<=", 86399999,
+ filter);
+ }
+
+ private void buildRevocationReasonFilter(HttpServletRequest req,
+ StringBuffer filter) {
+ if (!isOn(req, "revocationReasonInUse")) {
+ return;
+ }
+ String reasons = req.getParameter("revocationReason");
+ if (reasons == null) {
+ return;
+ }
+ String queryCertFilter = null;
+ StringTokenizer st = new StringTokenizer(reasons, ",");
+ if (st.hasMoreTokens()) {
+ filter.append("(|");
+ while (st.hasMoreTokens()) {
+ String token = st.nextToken();
+ if (queryCertFilter == null) {
+ queryCertFilter = "";
+ }
+ filter.append("(x509cert.certRevoInfo=");
+ filter.append(token);
+ filter.append(")");
+ }
+ filter.append(")");
+ }
+ }
+
+ private void buildIssuedByFilter(HttpServletRequest req,
+ StringBuffer filter) {
+ if (!isOn(req, "issuedByInUse")) {
+ return;
+ }
+ String issuedBy = req.getParameter("issuedBy");
+ if (issuedBy == null || issuedBy.equals("")) {
+ filter.append("(certIssuedBy=*)");
+ } else {
+ filter.append("(certIssuedBy=");
+ filter.append(issuedBy);
+ filter.append(")");
+ }
+ }
+
+ private void buildIssuedOnFilter(HttpServletRequest req,
+ StringBuffer filter) {
+ if (!isOn(req, "issuedOnInUse")) {
+ return;
+ }
+ buildDateFilter(req, "issuedOnFrom", "certCreateTime>=", 0, filter);
+ buildDateFilter(req, "issuedOnTo", "certCreateTime<=", 86399999,
+ filter);
+ }
+
+ private void buildValidNotBeforeFilter(HttpServletRequest req,
+ StringBuffer filter) {
+ if (!isOn(req, "validNotBeforeInUse")) {
+ return;
+ }
+ buildDateFilter(req, "validNotBeforeFrom", "x509cert.notBefore>=",
+ 0, filter);
+ buildDateFilter(req, "validNotBeforeTo", "x509cert.notBefore<=",
+ 86399999, filter);
+ }
+
+ private void buildValidNotAfterFilter(HttpServletRequest req,
+ StringBuffer filter) {
+ if (!isOn(req, "validNotAfterInUse")) {
+ return;
+ }
+ buildDateFilter(req, "validNotAfterFrom", "x509cert.notAfter>=",
+ 0, filter);
+ buildDateFilter(req, "validNotAfterTo", "x509cert.notAfter<=",
+ 86399999, filter);
+ }
+
+ private void buildValidityLengthFilter(HttpServletRequest req,
+ StringBuffer filter) {
+ if (!isOn(req, "validityLengthInUse")) {
+ return;
+ }
+ String op = req.getParameter("validityOp");
+ long count = 0;
+ try {
+ count = Long.parseLong(req.getParameter("count"));
+ } catch (NumberFormatException e) {
+ // safely ignore
+ }
+ long unit = 0;
+ try {
+ unit = Long.parseLong(req.getParameter("unit"));
+ } catch (NumberFormatException e) {
+ // safely ignore
+ }
+ filter.append("(");
+ filter.append("x509cert.duration");
+ filter.append(op);
+ filter.append(count * unit);
+ filter.append(")");
+ }
+
+ private void buildCertTypeFilter(HttpServletRequest req,
+ StringBuffer filter) {
+ if (!isOn(req, "certTypeInUse")) {
+ return;
+ }
+ if (isOn(req, "SSLClient")) {
+ filter.append("(x509cert.nsExtension.SSLClient=on)");
+ } else if (isOff(req, "SSLClient")) {
+ filter.append("(x509cert.nsExtension.SSLClient=off)");
+ }
+ if (isOn(req, "SSLServer")) {
+ filter.append("(x509cert.nsExtension.SSLServer=on)");
+ } else if (isOff(req, "SSLServer")) {
+ filter.append("(x509cert.nsExtension.SSLServer=off)");
+ }
+ if (isOn(req, "SecureEmail")) {
+ filter.append("(x509cert.nsExtension.SecureEmail=on)");
+ } else if (isOff(req, "SecureEmail")) {
+ filter.append("(x509cert.nsExtension.SecureEmail=off)");
+ }
+ if (isOn(req, "SubordinateSSLCA")) {
+ filter.append("(x509cert.nsExtension.SubordinateSSLCA=on)");
+ } else if (isOff(req, "SubordinateSSLCA")) {
+ filter.append("(x509cert.nsExtension.SubordinateSSLCA=off)");
+ }
+ if (isOn(req, "SubordinateEmailCA")) {
+ filter.append("(x509cert.nsExtension.SubordinateEmailCA=on)");
+ } else if (isOff(req, "SubordinateEmailCA")) {
+ filter.append("(x509cert.nsExtension.SubordinateEmailCA=off)");
+ }
+ }
+
+ public String buildFilter(HttpServletRequest req) {
+ String queryCertFilter = req.getParameter("queryCertFilter");
+
+ StringBuffer filter = new StringBuffer();
+ buildSerialNumberRangeFilter(req, filter);
+ buildSubjectFilter(req, filter);
+ buildRevokedByFilter(req, filter);
+ buildRevokedOnFilter(req, filter);
+ buildRevocationReasonFilter(req, filter);
+ buildIssuedByFilter(req, filter);
+ buildIssuedOnFilter(req, filter);
+ buildValidNotBeforeFilter(req, filter);
+ buildValidNotAfterFilter(req, filter);
+ buildValidityLengthFilter(req, filter);
+ buildCertTypeFilter(req, filter);
+ buildCertStatusFilter(req, filter);
+ buildProfileFilter(req, filter);
+ buildBasicConstraintsFilter(req, filter);
+
+ if (mUseClientFilter) {
+ CMS.debug("useClientFilter=true");
+ } else {
+ CMS.debug("useClientFilter=false");
+ CMS.debug("client queryCertFilter = " + queryCertFilter);
+ queryCertFilter = "(&" + filter.toString() + ")";
+ }
+ CMS.debug("queryCertFilter = " + queryCertFilter);
+ return queryCertFilter;
+ }
+
+ /**
+ * Serves HTTP request. This format of this request is as follows:
+ * queryCert?
+ * [maxCount=<number>]
+ * [queryFilter=<filter>]
+ * [revokeAll=<filter>]
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "list");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ String revokeAll = null;
+ EBaseException error = null;
+ int maxResults = -1;
+ int timeLimit = -1;
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ try {
+ revokeAll = req.getParameter("revokeAll");
+
+ String maxResultsStr = req.getParameter("maxResults");
+
+ if (maxResultsStr != null && maxResultsStr.length() > 0)
+ maxResults = Integer.parseInt(maxResultsStr);
+ String timeLimitStr = req.getParameter("timeLimit");
+
+ if (timeLimitStr != null && timeLimitStr.length() > 0)
+ timeLimit = Integer.parseInt(timeLimitStr);
+
+ String queryCertFilter = buildFilter(req);
+ process(argSet, header, queryCertFilter,
+ revokeAll, maxResults, timeLimit, req, resp, locale[0]);
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT"));
+ error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT"));
+ } catch (EBaseException e) {
+ error = e;
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ }
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ /**
+ * Process the key search.
+ */
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ String filter, String revokeAll,
+ int maxResults, int timeLimit,
+ HttpServletRequest req, HttpServletResponse resp,
+ Locale locale)
+ throws EBaseException {
+ try {
+ long startTime = CMS.getCurrentDate().getTime();
+
+ if (filter.indexOf(CURRENT_TIME, 0) > -1) {
+ filter = insertCurrentTime(filter);
+ }
+
+ // xxx the filter includes serial number range???
+ if (maxResults == -1 || maxResults > mMaxReturns) {
+ CMS.debug("Resetting maximum of returned results from " + maxResults + " to " + mMaxReturns);
+ maxResults = mMaxReturns;
+ }
+ if (timeLimit == -1 || timeLimit > mTimeLimits) {
+ CMS.debug("Resetting timelimit from " + timeLimit + " to " + mTimeLimits);
+ timeLimit = mTimeLimits;
+ }
+ CMS.debug("Start searching ... "
+ + "filter=" + filter + " maxreturns=" + maxResults + " timelimit=" + timeLimit);
+ Enumeration<ICertRecord> e = mCertDB.searchCertificates(filter, maxResults, timeLimit);
+
+ int count = 0;
+
+ while (e != null && e.hasMoreElements()) {
+ ICertRecord rec = e.nextElement();
+
+ if (rec != null) {
+ count++;
+ IArgBlock rarg = CMS.createArgBlock();
+
+ fillRecordIntoArg(rec, rarg);
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+
+ long endTime = CMS.getCurrentDate().getTime();
+
+ header.addStringValue("op", req.getParameter("op"));
+ if (mAuthName != null)
+ header.addStringValue("issuerName", mAuthName.toString());
+ header.addStringValue("time", Long.toString(endTime - startTime));
+ header.addStringValue("serviceURL", req.getRequestURI());
+ header.addStringValue("queryFilter", filter);
+ if (revokeAll != null)
+ header.addStringValue("revokeAll", revokeAll);
+ header.addIntegerValue("totalRecordCount", count);
+ header.addIntegerValue("maxSize", maxResults);
+ } catch (EBaseException e) {
+ CMS.getLogMessage("CMSGW_ERROR_LISTCERTS", e.toString());
+ throw e;
+ }
+ return;
+ }
+
+ private String insertCurrentTime(String filter) {
+ Date now = null;
+ StringBuffer newFilter = new StringBuffer();
+ int k = 0;
+ int i = filter.indexOf(CURRENT_TIME, k);
+
+ while (i > -1) {
+ if (now == null)
+ now = new Date();
+ newFilter.append(filter.substring(k, i));
+ newFilter.append(now.getTime());
+ k = i + CURRENT_TIME.length();
+ i = filter.indexOf(CURRENT_TIME, k);
+ }
+ if (k > 0) {
+ newFilter.append(filter.substring(k, filter.length()));
+ }
+ return newFilter.toString();
+ }
+
+ /**
+ * Fills cert record into argument block.
+ */
+ private void fillRecordIntoArg(ICertRecord rec, IArgBlock rarg)
+ throws EBaseException {
+
+ X509CertImpl xcert = rec.getCertificate();
+
+ if (xcert != null) {
+ fillX509RecordIntoArg(rec, rarg);
+ }
+ }
+
+ private void fillX509RecordIntoArg(ICertRecord rec, IArgBlock rarg)
+ throws EBaseException {
+
+ X509CertImpl cert = rec.getCertificate();
+
+ rarg.addIntegerValue("version", cert.getVersion());
+ rarg.addStringValue("serialNumber", cert.getSerialNumber().toString(16));
+ rarg.addStringValue("serialNumberDecimal", cert.getSerialNumber().toString());
+
+ String subject = cert.getSubjectDN().toString();
+
+ if (subject.equals("")) {
+ rarg.addStringValue("subject", " ");
+ } else {
+ rarg.addStringValue("subject", subject);
+
+ }
+
+ rarg.addStringValue("type", "X.509");
+
+ try {
+ PublicKey pKey = cert.getPublicKey();
+ X509Key key = null;
+
+ if (pKey instanceof CertificateX509Key) {
+ CertificateX509Key certKey = (CertificateX509Key) pKey;
+
+ key = (X509Key) certKey.get(CertificateX509Key.KEY);
+ }
+ if (pKey instanceof X509Key) {
+ key = (X509Key) pKey;
+ }
+ rarg.addStringValue("subjectPublicKeyAlgorithm", key.getAlgorithmId().getOID().toString());
+ if (key.getAlgorithmId().toString().equalsIgnoreCase("RSA")) {
+ RSAPublicKey rsaKey = new RSAPublicKey(key.getEncoded());
+
+ rarg.addIntegerValue("subjectPublicKeyLength", rsaKey.getKeySize());
+ }
+ } catch (Exception e) {
+ rarg.addStringValue("subjectPublicKeyAlgorithm", null);
+ rarg.addIntegerValue("subjectPublicKeyLength", 0);
+ }
+
+ rarg.addLongValue("validNotBefore", cert.getNotBefore().getTime() / 1000);
+ rarg.addLongValue("validNotAfter", cert.getNotAfter().getTime() / 1000);
+ rarg.addStringValue("signatureAlgorithm", cert.getSigAlgOID());
+ String issuedBy = rec.getIssuedBy();
+
+ if (issuedBy == null)
+ issuedBy = "";
+ rarg.addStringValue("issuedBy", issuedBy); // cert.getIssuerDN().toString()
+ rarg.addLongValue("issuedOn", rec.getCreateTime().getTime() / 1000);
+
+ rarg.addStringValue("revokedBy",
+ ((rec.getRevokedBy() == null) ? "" : rec.getRevokedBy()));
+ if (rec.getRevokedOn() == null) {
+ rarg.addStringValue("revokedOn", null);
+ } else {
+ rarg.addLongValue("revokedOn", rec.getRevokedOn().getTime() / 1000);
+
+ IRevocationInfo revocationInfo = rec.getRevocationInfo();
+
+ if (revocationInfo != null) {
+ CRLExtensions crlExts = revocationInfo.getCRLEntryExtensions();
+
+ if (crlExts != null) {
+ Enumeration<Extension> enum1 = crlExts.getElements();
+ int reason = 0;
+
+ while (enum1.hasMoreElements()) {
+ Extension ext = enum1.nextElement();
+
+ if (ext instanceof CRLReasonExtension) {
+ reason = ((CRLReasonExtension) ext).getReason().toInt();
+ break;
+ }
+ }
+ rarg.addIntegerValue("revocationReason", reason);
+ }
+ }
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/UpdateCRL.java b/base/server/cms/src/com/netscape/cms/servlet/cert/UpdateCRL.java
new file mode 100644
index 000000000..e39b66555
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/UpdateCRL.java
@@ -0,0 +1,529 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.InvalidityDateExtension;
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.RevokedCertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ca.EErrorPublishCRL;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapRule;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.util.IStatsSubsystem;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Force the CRL to be updated now.
+ *
+ * @version $Revision$, $Date$
+ */
+public class UpdateCRL extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1182106454856991246L;
+ private final static String TPL_FILE = "updateCRL.template";
+
+ private static Vector<String> mTesting = new Vector<String>();
+
+ private String mFormPath = null;
+ private ICertificateAuthority mCA = null;
+
+ /**
+ * Constructs UpdateCRL servlet.
+ */
+ public UpdateCRL() {
+ super();
+ }
+
+ /**
+ * Initializes the servlet. This servlet uses updateCRL.template
+ * to render the result
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ if (mAuthority instanceof ICertificateAuthority)
+ mCA = (ICertificateAuthority) mAuthority;
+
+ // override success to do output orw own template.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param signatureAlgorithm the algorithm to use to sign the CRL
+ * <li>http.param waitForUpdate true/false - should the servlet wait until the CRL update is complete?
+ * <li>http.param clearCRLCache true/false - should the CRL cache cleared before the CRL is generated?
+ * <li>http.param crlIssuingPoint the CRL Issuing Point to Update
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ statsSub.startTiming("crl", true /* main action */);
+ }
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "update");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ if (statsSub != null) {
+ statsSub.endTiming("crl");
+ }
+ return;
+ }
+
+ EBaseException error = null;
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ if (statsSub != null) {
+ statsSub.endTiming("crl");
+ }
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ try {
+ String signatureAlgorithm =
+ req.getParameter("signatureAlgorithm");
+
+ process(argSet, header, req, resp,
+ signatureAlgorithm, locale[0]);
+ } catch (EBaseException e) {
+ error = e;
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE",
+ e.toString()));
+ if (statsSub != null) {
+ statsSub.endTiming("crl");
+ }
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ if (statsSub != null) {
+ statsSub.endTiming("crl");
+ }
+ }
+
+ private CRLExtensions crlEntryExtensions(String reason, String invalidity) {
+ CRLExtensions entryExts = new CRLExtensions();
+
+ CRLReasonExtension crlReasonExtn = null;
+ if (reason != null && reason.length() > 0) {
+ try {
+ RevocationReason revReason = RevocationReason.fromInt(Integer.parseInt(reason));
+ if (revReason == null)
+ revReason = RevocationReason.UNSPECIFIED;
+ crlReasonExtn = new CRLReasonExtension(revReason);
+ } catch (Exception e) {
+ CMS.debug("Invalid revocation reason: " + reason);
+ }
+ }
+
+ InvalidityDateExtension invalidityDateExtn = null;
+ if (invalidity != null && invalidity.length() > 0) {
+ long now = System.currentTimeMillis();
+ Date invalidityDate = null;
+ try {
+ long backInTime = Long.parseLong(invalidity);
+ invalidityDate = new Date(now - (backInTime * 60000));
+ } catch (Exception e) {
+ CMS.debug("Invalid invalidity time offset: " + invalidity);
+ }
+ if (invalidityDate != null) {
+ try {
+ invalidityDateExtn = new InvalidityDateExtension(invalidityDate);
+ } catch (Exception e) {
+ CMS.debug("Error creating invalidity extension: " + e);
+ }
+ }
+ }
+
+ if (crlReasonExtn != null) {
+ try {
+ entryExts.set(crlReasonExtn.getName(), crlReasonExtn);
+ } catch (Exception e) {
+ CMS.debug("Error adding revocation reason extension to entry extensions: " + e);
+ }
+ }
+
+ if (invalidityDateExtn != null) {
+ try {
+ entryExts.set(invalidityDateExtn.getName(), invalidityDateExtn);
+ } catch (Exception e) {
+ CMS.debug("Error adding invalidity date extension to entry extensions: " + e);
+ }
+ }
+
+ return entryExts;
+ }
+
+ private void addInfo(CMSTemplateParams argSet, ICRLIssuingPoint crlIssuingPoint, long cacheUpdate) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addLongValue("cacheUpdate", cacheUpdate);
+
+ String crlNumbers = crlIssuingPoint.getCRLNumber().toString();
+ BigInteger deltaNumber = crlIssuingPoint.getDeltaCRLNumber();
+ String crlSizes = "" + crlIssuingPoint.getCRLSize();
+ if (deltaNumber != null && deltaNumber.compareTo(BigInteger.ZERO) > 0) {
+ if (crlNumbers != null)
+ crlNumbers += ",";
+ if (crlNumbers != null)
+ crlNumbers += deltaNumber.toString();
+ if (crlSizes != null)
+ crlSizes += "," + crlIssuingPoint.getDeltaCRLSize();
+ }
+ rarg.addStringValue("crlNumbers", crlNumbers);
+ rarg.addStringValue("crlSizes", crlSizes);
+
+ StringBuffer crlSplits = new StringBuffer();
+ Vector<Long> splits = crlIssuingPoint.getSplitTimes();
+ for (int i = 0; i < splits.size(); i++) {
+ crlSplits.append(splits.elementAt(i));
+ if (i + 1 < splits.size())
+ crlSplits.append(",");
+ }
+ rarg.addStringValue("crlSplits", crlSplits.toString());
+
+ argSet.addRepeatRecord(rarg);
+ }
+
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ HttpServletRequest req,
+ HttpServletResponse resp,
+ String signatureAlgorithm,
+ Locale locale)
+ throws EBaseException {
+ long startTime = CMS.getCurrentDate().getTime();
+ String waitForUpdate =
+ req.getParameter("waitForUpdate");
+ String clearCache =
+ req.getParameter("clearCRLCache");
+ String crlIssuingPointId =
+ req.getParameter("crlIssuingPoint");
+ String test = req.getParameter("test");
+ String add = req.getParameter("add");
+ String from = req.getParameter("from");
+ String by = req.getParameter("by");
+ String reason = req.getParameter("reason");
+ String invalidity = req.getParameter("invalidity");
+ String results = req.getParameter("results");
+
+ if (crlIssuingPointId != null) {
+ Enumeration<ICRLIssuingPoint> ips = mCA.getCRLIssuingPoints();
+
+ while (ips.hasMoreElements()) {
+ ICRLIssuingPoint ip = ips.nextElement();
+
+ if (crlIssuingPointId.equals(ip.getId())) {
+ break;
+ }
+ if (!ips.hasMoreElements())
+ crlIssuingPointId = null;
+ }
+ }
+ if (crlIssuingPointId == null) {
+ crlIssuingPointId = ICertificateAuthority.PROP_MASTER_CRL;
+ }
+
+ ICRLIssuingPoint crlIssuingPoint =
+ mCA.getCRLIssuingPoint(crlIssuingPointId);
+ header.addStringValue("crlIssuingPoint", crlIssuingPointId);
+ IPublisherProcessor lpm = mCA.getPublisherProcessor();
+
+ if (crlIssuingPoint != null) {
+ if (clearCache != null && clearCache.equals("true") &&
+ crlIssuingPoint.isCRLGenerationEnabled() &&
+ crlIssuingPoint.isCRLUpdateInProgress() == ICRLIssuingPoint.CRL_UPDATE_DONE &&
+ crlIssuingPoint.isCRLIssuingPointInitialized()
+ == ICRLIssuingPoint.CRL_IP_INITIALIZED) {
+ crlIssuingPoint.clearCRLCache();
+ }
+ if (waitForUpdate != null && waitForUpdate.equals("true") &&
+ crlIssuingPoint.isCRLGenerationEnabled() &&
+ crlIssuingPoint.isCRLUpdateInProgress() == ICRLIssuingPoint.CRL_UPDATE_DONE &&
+ crlIssuingPoint.isCRLIssuingPointInitialized()
+ == ICRLIssuingPoint.CRL_IP_INITIALIZED) {
+ if (test != null && test.equals("true") &&
+ crlIssuingPoint.isCRLCacheTestingEnabled() &&
+ (!mTesting.contains(crlIssuingPointId))) {
+ CMS.debug("CRL test started.");
+ mTesting.add(crlIssuingPointId);
+ BigInteger addLen = null;
+ BigInteger startFrom = null;
+ if (add != null && add.length() > 0 &&
+ from != null && from.length() > 0) {
+ try {
+ addLen = new BigInteger(add);
+ startFrom = new BigInteger(from);
+ } catch (Exception e) {
+ }
+ }
+ if (addLen != null && startFrom != null) {
+ Date revocationDate = CMS.getCurrentDate();
+ String err = null;
+
+ CRLExtensions entryExts = crlEntryExtensions(reason, invalidity);
+
+ BigInteger serialNumber = startFrom;
+ BigInteger counter = addLen;
+ BigInteger stepBy = null;
+ if (by != null && by.length() > 0) {
+ try {
+ stepBy = new BigInteger(by);
+ } catch (Exception e) {
+ }
+ }
+
+ long t1 = System.currentTimeMillis();
+ long t2 = 0;
+
+ while (counter.compareTo(BigInteger.ZERO) > 0) {
+ RevokedCertImpl revokedCert =
+ new RevokedCertImpl(serialNumber, revocationDate, entryExts);
+ crlIssuingPoint.addRevokedCert(serialNumber, revokedCert);
+ serialNumber = serialNumber.add(BigInteger.ONE);
+ counter = counter.subtract(BigInteger.ONE);
+
+ if ((counter.compareTo(BigInteger.ZERO) == 0) ||
+ (stepBy != null && ((counter.mod(stepBy)).compareTo(BigInteger.ZERO) == 0))) {
+ t2 = System.currentTimeMillis();
+ long t0 = t2 - t1;
+ t1 = t2;
+ try {
+ if (signatureAlgorithm != null) {
+ crlIssuingPoint.updateCRLNow(signatureAlgorithm);
+ } else {
+ crlIssuingPoint.updateCRLNow();
+ }
+ } catch (Throwable e) {
+ counter = BigInteger.ZERO;
+ err = e.toString();
+ }
+ if (results != null && results.equals("1")) {
+ addInfo(argSet, crlIssuingPoint, t0);
+ }
+ }
+ }
+ if (err != null) {
+ header.addStringValue("crlUpdate", "Failure");
+ header.addStringValue("error", err);
+ } else {
+ header.addStringValue("crlUpdate", "Success");
+ }
+ } else {
+ CMS.debug("CRL test error: missing parameters.");
+ header.addStringValue("crlUpdate", "missingParameters");
+ }
+
+ mTesting.remove(crlIssuingPointId);
+ CMS.debug("CRL test finished.");
+ } else if (test != null && test.equals("true") &&
+ crlIssuingPoint.isCRLCacheTestingEnabled() &&
+ mTesting.contains(crlIssuingPointId)) {
+ header.addStringValue("crlUpdate", "testingInProgress");
+ } else if (test != null && test.equals("true") &&
+ (!crlIssuingPoint.isCRLCacheTestingEnabled())) {
+ header.addStringValue("crlUpdate", "testingNotEnabled");
+ } else {
+ try {
+ EBaseException publishError = null;
+
+ try {
+ long now1 = System.currentTimeMillis();
+
+ if (signatureAlgorithm != null) {
+ crlIssuingPoint.updateCRLNow(signatureAlgorithm);
+ } else {
+ crlIssuingPoint.updateCRLNow();
+ }
+
+ long now2 = System.currentTimeMillis();
+
+ header.addStringValue("time", "" + (now2 - now1));
+ } catch (EErrorPublishCRL e) {
+ publishError = e;
+ }
+
+ if (lpm != null && lpm.enabled()) {
+ Enumeration<ILdapRule> rules = lpm.getRules(IPublisherProcessor.PROP_LOCAL_CRL);
+ if (rules != null && rules.hasMoreElements()) {
+ if (publishError != null) {
+ header.addStringValue("crlPublished", "Failure");
+ header.addStringValue("error", publishError.toString(locale));
+ } else {
+ header.addStringValue("crlPublished", "Success");
+ }
+ }
+ }
+
+ // for audit log
+ SessionContext sContext = SessionContext.getContext();
+ String agentId = (String) sContext.get(SessionContext.USER_ID);
+ IAuthToken authToken = (IAuthToken) sContext.get(SessionContext.AUTH_TOKEN);
+ String authMgr = AuditFormat.NOAUTH;
+
+ if (authToken != null) {
+ authMgr = authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ }
+ long endTime = CMS.getCurrentDate().getTime();
+
+ if (crlIssuingPoint.getNextUpdate() != null) {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.CRLUPDATEFORMAT,
+ new Object[] {
+ AuditFormat.FROMAGENT + " agentID: " + agentId,
+ authMgr,
+ "completed",
+ crlIssuingPoint.getId(),
+ crlIssuingPoint.getCRLNumber(),
+ crlIssuingPoint.getLastUpdate(),
+ crlIssuingPoint.getNextUpdate(),
+ Long.toString(crlIssuingPoint.getCRLSize())
+ + " time: " + (endTime - startTime) }
+ );
+ } else {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.CRLUPDATEFORMAT,
+ new Object[] {
+ AuditFormat.FROMAGENT + " agentID: " + agentId,
+ authMgr,
+ "completed",
+ crlIssuingPoint.getId(),
+ crlIssuingPoint.getCRLNumber(),
+ crlIssuingPoint.getLastUpdate(),
+ "not set",
+ Long.toString(crlIssuingPoint.getCRLSize())
+ + " time: " + (endTime - startTime) }
+ );
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_UPDATE_CRL", e.toString()));
+ if ((lpm != null) && lpm.enabled() && (e instanceof ELdapException)) {
+ header.addStringValue("crlPublished", "Failure");
+ header.addStringValue("error", e.toString(locale));
+ } else {
+ throw e;
+ }
+ }
+ }
+ } else {
+ if (crlIssuingPoint.isCRLIssuingPointInitialized() != ICRLIssuingPoint.CRL_IP_INITIALIZED) {
+ header.addStringValue("crlUpdate", "notInitialized");
+ } else if (crlIssuingPoint.isCRLUpdateInProgress()
+ != ICRLIssuingPoint.CRL_UPDATE_DONE ||
+ crlIssuingPoint.isManualUpdateSet()) {
+ header.addStringValue("crlUpdate", "inProgress");
+ } else if (!crlIssuingPoint.isCRLGenerationEnabled()) {
+ header.addStringValue("crlUpdate", "Disabled");
+ } else {
+ crlIssuingPoint.setManualUpdate(signatureAlgorithm);
+ header.addStringValue("crlUpdate", "Scheduled");
+ }
+ }
+ }
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/UpdateDir.java b/base/server/cms/src/com/netscape/cms/servlet/cert/UpdateDir.java
new file mode 100644
index 000000000..a662f8e7b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/UpdateDir.java
@@ -0,0 +1,747 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X509CRLImpl;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+import com.netscape.certsrv.dbs.crldb.ICRLRepository;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Update the configured LDAP server with specified objects
+ *
+ * @version $Revision$, $Date$
+ */
+public class UpdateDir extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3063889978908136789L;
+ private final static String TPL_FILE = "updateDir.template";
+ private final static int UPDATE_ALL = 0;
+ private final static int UPDATE_CRL = 1;
+ private final static int UPDATE_CA = 2;
+ private final static int UPDATE_VALID = 3;
+ private final static int VALID_FROM = 4;
+ private final static int VALID_TO = 5;
+ private final static int UPDATE_EXPIRED = 6;
+ private final static int EXPIRED_FROM = 7;
+ private final static int EXPIRED_TO = 8;
+ private final static int UPDATE_REVOKED = 9;
+ private final static int REVOKED_FROM = 10;
+ private final static int REVOKED_TO = 11;
+ private final static int CHECK_FLAG = 12;
+ private final static String[] updateName =
+ { "updateAll", "updateCRL", "updateCA",
+ "updateValid", "validFrom", "validTo",
+ "updateExpired", "expiredFrom", "expiredTo",
+ "updateRevoked", "revokedFrom", "revokedTo",
+ "checkFlag" };
+
+ private String mFormPath = null;
+ private ICertificateAuthority mCA = null;
+ private IPublisherProcessor mPublisherProcessor = null;
+ private ICRLRepository mCRLRepository = null;
+ private boolean mClonedCA = false;
+
+ /**
+ * Constructs UpdateDir servlet.
+ */
+ public UpdateDir() {
+ super();
+ }
+
+ /**
+ * Initialize the servlet. This servlet uses the template
+ * 'updateDir.template' to render the response
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+
+ if (mAuthority != null) {
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ if (mAuthority instanceof ICertificateAuthority) {
+ mCA = (ICertificateAuthority) mAuthority;
+ mPublisherProcessor = mCA.getPublisherProcessor();
+ mCRLRepository = mCA.getCRLRepository();
+ }
+
+ // override success to do output orw own template.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mOutputTemplatePath != null) {
+ mFormPath = mOutputTemplatePath;
+ }
+ }
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "update");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ EBaseException error = null;
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ try {
+ String crlIssuingPointId = req.getParameter("crlIssuingPoint");
+
+ if (mPublisherProcessor == null ||
+ !mPublisherProcessor.enabled())
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_PUB_MODULE"));
+
+ String[] updateValue = new String[updateName.length];
+
+ for (int i = 0; i < updateName.length; i++) {
+ updateValue[i] = req.getParameter(updateName[i]);
+ }
+
+ String masterHost = CMS.getConfigStore().getString("master.ca.agent.host", "");
+ String masterPort = CMS.getConfigStore().getString("master.ca.agent.port", "");
+ if (masterHost != null && masterHost.length() > 0 &&
+ masterPort != null && masterPort.length() > 0) {
+ mClonedCA = true;
+ }
+
+ process(argSet, header, req, resp, crlIssuingPointId, updateValue, locale[0]);
+ } catch (EBaseException e) {
+ error = e;
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ private void updateCRLIssuingPoint(
+ IArgBlock header,
+ String crlIssuingPointId,
+ ICRLIssuingPoint crlIssuingPoint,
+ Locale locale) {
+ SessionContext sc = SessionContext.getContext();
+
+ sc.put(ICRLIssuingPoint.SC_ISSUING_POINT_ID, crlIssuingPointId);
+ sc.put(ICRLIssuingPoint.SC_IS_DELTA_CRL, "false");
+ ICRLIssuingPointRecord crlRecord = null;
+
+ try {
+ if (mCRLRepository != null) {
+ crlRecord = mCRLRepository.readCRLIssuingPointRecord(crlIssuingPointId);
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_GET_CRL_RECORD", e.toString()));
+ }
+
+ if (crlRecord == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CRL_NOT_YET_UPDATED_1", crlIssuingPointId));
+ header.addStringValue("crlPublished", "Failure");
+ header.addStringValue("crlError",
+ new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_CRL_NOT_YET_UPDATED")).toString());
+ } else {
+ String publishDN = (crlIssuingPoint != null) ? crlIssuingPoint.getPublishDN() : null;
+ byte[] crlbytes = crlRecord.getCRL();
+
+ if (crlbytes == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CRL_NOT_YET_UPDATED_1", ""));
+ header.addStringValue("crlPublished", "Failure");
+ header.addStringValue("crlError",
+ new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_CRL_NOT_YET_UPDATED")).toString());
+ } else {
+ X509CRLImpl crl = null;
+
+ try {
+ crl = new X509CRLImpl(crlbytes);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_DECODE_CRL", e.toString()));
+ }
+
+ if (crl == null) {
+ header.addStringValue("crlPublished", "Failure");
+ header.addStringValue("crlError",
+ new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_DECODE_CRL_FAILED")).toString());
+ } else {
+ try {
+ if (publishDN != null) {
+ mPublisherProcessor.publishCRL(publishDN, crl);
+ } else {
+ mPublisherProcessor.publishCRL(crl, crlIssuingPointId);
+ }
+ header.addStringValue("crlPublished", "Success");
+ } catch (ELdapException e) {
+ header.addStringValue("crlPublished", "Failure");
+ header.addStringValue("crlError", e.toString(locale));
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_ERROR_PUBLISH_CRL", e.toString()));
+ }
+ }
+ }
+
+ sc.put(ICRLIssuingPoint.SC_IS_DELTA_CRL, "true");
+ // handle delta CRL if any
+ byte[] deltaCrlBytes = crlRecord.getDeltaCRL();
+
+ if (deltaCrlBytes != null) {
+ X509CRLImpl deltaCrl = null;
+
+ try {
+ deltaCrl = new X509CRLImpl(deltaCrlBytes);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_DECODE_DELTA_CRL", e.toString()));
+ }
+
+ boolean goodDelta = false;
+ if (mClonedCA) {
+ BigInteger crlNumber = crlRecord.getCRLNumber();
+ BigInteger deltaNumber = crlRecord.getDeltaCRLNumber();
+ Long deltaCRLSize = crlRecord.getDeltaCRLSize();
+ if (deltaCRLSize != null && deltaCRLSize.longValue() > -1 &&
+ crlNumber != null && deltaNumber != null &&
+ deltaNumber.compareTo(crlNumber) >= 0) {
+ goodDelta = true;
+ }
+ }
+
+ if (deltaCrl != null && ((mClonedCA && goodDelta) ||
+ (crlIssuingPoint != null &&
+ crlIssuingPoint.isThisCurrentDeltaCRL(deltaCrl)))) {
+ try {
+ if (publishDN != null) {
+ mPublisherProcessor.publishCRL(publishDN, deltaCrl);
+ } else {
+ mPublisherProcessor.publishCRL(deltaCrl, crlIssuingPointId);
+ }
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_PUBLISH_DELTA_CRL", e.toString()));
+ }
+ }
+ }
+ } // if
+ }
+
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ HttpServletRequest req,
+ HttpServletResponse resp,
+ String crlIssuingPointId,
+ String[] updateValue,
+ Locale locale)
+ throws EBaseException {
+ // all or crl
+ if ((updateValue[UPDATE_ALL] != null &&
+ updateValue[UPDATE_ALL].equalsIgnoreCase("yes")) ||
+ (updateValue[UPDATE_CRL] != null &&
+ updateValue[UPDATE_CRL].equalsIgnoreCase("yes"))) {
+ // check if received issuing point ID is known to the server
+ if (crlIssuingPointId != null) {
+ Enumeration<ICRLIssuingPoint> ips = mCA.getCRLIssuingPoints();
+
+ while (ips.hasMoreElements()) {
+ ICRLIssuingPoint ip = ips.nextElement();
+
+ if (crlIssuingPointId.equals(ip.getId())) {
+ break;
+ }
+ if (!ips.hasMoreElements())
+ crlIssuingPointId = null;
+ }
+ }
+ if (crlIssuingPointId == null) {
+ // publish all issuing points
+ if (mClonedCA && mCRLRepository != null) {
+ Vector<String> ipNames = mCRLRepository.getIssuingPointsNames();
+ if (ipNames != null && ipNames.size() > 0) {
+ for (int i = 0; i < ipNames.size(); i++) {
+ String ipName = ipNames.elementAt(i);
+
+ updateCRLIssuingPoint(header, ipName, null, locale);
+ }
+ }
+ } else {
+ Enumeration<ICRLIssuingPoint> oips = mCA.getCRLIssuingPoints();
+
+ while (oips.hasMoreElements()) {
+ ICRLIssuingPoint oip = oips.nextElement();
+
+ updateCRLIssuingPoint(header, oip.getId(), oip, locale);
+ }
+ }
+ } else {
+ ICRLIssuingPoint crlIssuingPoint =
+ mCA.getCRLIssuingPoint(crlIssuingPointId);
+
+ updateCRLIssuingPoint(header, crlIssuingPointId,
+ crlIssuingPoint, locale);
+ }
+ }
+
+ ICertificateRepository certificateRepository = mCA.getCertificateRepository();
+
+ // all or ca
+ if ((updateValue[UPDATE_ALL] != null &&
+ updateValue[UPDATE_ALL].equalsIgnoreCase("yes")) ||
+ (updateValue[UPDATE_CA] != null &&
+ updateValue[UPDATE_CA].equalsIgnoreCase("yes"))) {
+ X509CertImpl caCert = mCA.getSigningUnit().getCertImpl();
+
+ try {
+ mPublisherProcessor.publishCACert(caCert);
+ header.addStringValue("caCertPublished", "Success");
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_ERROR_PUBLISH_CACERT_1",
+ caCert.getSerialNumber().toString(16), e.toString()));
+ header.addStringValue("caCertPublished", "Failure");
+ header.addStringValue("caCertError", e.toString(locale));
+ }
+ }
+
+ // all or valid
+ if ((updateValue[UPDATE_ALL] != null &&
+ updateValue[UPDATE_ALL].equalsIgnoreCase("yes")) ||
+ (updateValue[UPDATE_VALID] != null &&
+ updateValue[UPDATE_VALID].equalsIgnoreCase("yes"))) {
+ if (certificateRepository != null) {
+ if (updateValue[VALID_FROM].startsWith("0x")) {
+ updateValue[VALID_FROM] = hexToDecimal(updateValue[VALID_FROM]);
+ }
+ if (updateValue[VALID_TO].startsWith("0x")) {
+ updateValue[VALID_TO] = hexToDecimal(updateValue[VALID_TO]);
+ }
+ Enumeration<ICertRecord> validCerts = null;
+
+ if (updateValue[CHECK_FLAG] != null &&
+ updateValue[CHECK_FLAG].equalsIgnoreCase("yes")) {
+ validCerts =
+ certificateRepository.getValidNotPublishedCertificates(
+ updateValue[VALID_FROM],
+ updateValue[VALID_TO]);
+ } else {
+ validCerts =
+ certificateRepository.getValidCertificates(
+ updateValue[VALID_FROM],
+ updateValue[VALID_TO]);
+ }
+ int i = 0;
+ int l = 0;
+ String validCertsError = "";
+
+ if (validCerts != null) {
+ while (validCerts.hasMoreElements()) {
+ ICertRecord certRecord =
+ validCerts.nextElement();
+ //X509CertImpl cert = certRecord.getCertificate();
+ X509CertImpl cert = null;
+ Object o = certRecord.getCertificate();
+
+ if (o instanceof X509CertImpl)
+ cert = (X509CertImpl) o;
+
+ MetaInfo metaInfo = null;
+ String ridString = null;
+
+ metaInfo = (MetaInfo) certRecord.get(ICertRecord.ATTR_META_INFO);
+ if (metaInfo == null) {
+ // ca's self signed signing cert and
+ // server cert has no related request and
+ // have no metaInfo
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAIL_GET_ICERT_RECORD",
+ cert.getSerialNumber().toString(16)));
+ } else {
+ ridString = (String) metaInfo.get(ICertRecord.META_REQUEST_ID);
+ }
+
+ IRequest r = null;
+
+ if (ridString != null) {
+ RequestId rid = new RequestId(ridString);
+
+ r = mCA.getRequestQueue().findRequest(rid);
+ }
+
+ try {
+ l++;
+ SessionContext sc = SessionContext.getContext();
+
+ if (r == null) {
+ if (CMS.isEncryptionCert(cert))
+ sc.put("isEncryptionCert", "true");
+ else
+ sc.put("isEncryptionCert", "false");
+ mPublisherProcessor.publishCert(cert, null);
+ } else {
+ if (CMS.isEncryptionCert(cert))
+ r.setExtData("isEncryptionCert", "true");
+ else
+ r.setExtData("isEncryptionCert", "false");
+ mPublisherProcessor.publishCert(cert, r);
+ }
+ i++;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAIL_PUBLISH_CERT",
+ certRecord.getSerialNumber().toString(16),
+ e.toString()));
+ validCertsError +=
+ "Failed to publish certificate: 0x" +
+ certRecord.getSerialNumber().toString(16) +
+ ".\n <BR> &nbsp;&nbsp;&nbsp;&nbsp;";
+ }
+ }
+ }
+ if (i > 0 && i == l) {
+ header.addStringValue("validCertsPublished",
+ "Success");
+ if (i == 1)
+ header.addStringValue("validCertsError", i +
+ " valid certificate is published in the directory.");
+ else
+ header.addStringValue("validCertsError", i +
+ " valid certificates are published in the directory.");
+ } else {
+ if (l == 0) {
+ header.addStringValue("validCertsPublished", "No");
+ } else {
+ header.addStringValue("validCertsPublished", "Failure");
+ header.addStringValue("validCertsError",
+ validCertsError);
+ }
+ }
+ } else {
+ header.addStringValue("validCertsPublished", "Failure");
+ header.addStringValue("validCertsError", "Certificate repository is unavailable.");
+ }
+ }
+
+ // all or expired
+ if ((updateValue[UPDATE_ALL] != null &&
+ updateValue[UPDATE_ALL].equalsIgnoreCase("yes")) ||
+ (updateValue[UPDATE_EXPIRED] != null &&
+ updateValue[UPDATE_EXPIRED].equalsIgnoreCase("yes"))) {
+ if (certificateRepository != null) {
+ if (updateValue[EXPIRED_FROM].startsWith("0x")) {
+ updateValue[EXPIRED_FROM] = hexToDecimal(updateValue[EXPIRED_FROM]);
+ }
+ if (updateValue[EXPIRED_TO].startsWith("0x")) {
+ updateValue[EXPIRED_TO] = hexToDecimal(updateValue[EXPIRED_TO]);
+ }
+ Enumeration<ICertRecord> expiredCerts = null;
+
+ if (updateValue[CHECK_FLAG] != null &&
+ updateValue[CHECK_FLAG].equalsIgnoreCase("yes")) {
+ expiredCerts =
+ certificateRepository.getExpiredPublishedCertificates(
+ updateValue[EXPIRED_FROM],
+ updateValue[EXPIRED_TO]);
+ } else {
+ expiredCerts =
+ certificateRepository.getExpiredCertificates(
+ updateValue[EXPIRED_FROM],
+ updateValue[EXPIRED_TO]);
+ }
+ int i = 0;
+ int l = 0;
+ StringBuffer expiredCertsError = new StringBuffer();
+
+ if (expiredCerts != null) {
+ while (expiredCerts.hasMoreElements()) {
+ ICertRecord certRecord = expiredCerts.nextElement();
+ //X509CertImpl cert = certRecord.getCertificate();
+ X509CertImpl cert = null;
+ Object o = certRecord.getCertificate();
+
+ if (o instanceof X509CertImpl)
+ cert = (X509CertImpl) o;
+
+ MetaInfo metaInfo = null;
+ String ridString = null;
+
+ metaInfo = (MetaInfo) certRecord.get(ICertRecord.ATTR_META_INFO);
+ if (metaInfo == null) {
+ // ca's self signed signing cert and
+ // server cert has no related request and
+ // have no metaInfo
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAIL_GET_ICERT_RECORD",
+ cert.getSerialNumber().toString(16)));
+ } else {
+ ridString = (String) metaInfo.get(ICertRecord.META_REQUEST_ID);
+ }
+
+ IRequest r = null;
+
+ if (ridString != null) {
+ RequestId rid = new RequestId(ridString);
+
+ r = mCA.getRequestQueue().findRequest(rid);
+ }
+
+ try {
+ l++;
+ if (r == null) {
+ mPublisherProcessor.unpublishCert(cert, null);
+ } else {
+ mPublisherProcessor.unpublishCert(cert, r);
+ }
+ i++;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LDAP_ERROR_UNPUBLISH_CERT",
+ certRecord.getSerialNumber().toString(16),
+ e.toString()));
+ expiredCertsError.append(
+ "Failed to unpublish certificate: 0x");
+ expiredCertsError.append(
+ certRecord.getSerialNumber().toString(16));
+ expiredCertsError.append(
+ ".\n <BR> &nbsp;&nbsp;&nbsp;&nbsp;");
+ }
+ }
+ }
+ if (i > 0 && i == l) {
+ header.addStringValue("expiredCertsUnpublished", "Success");
+ if (i == 1)
+ header.addStringValue("expiredCertsError", i +
+ " expired certificate is unpublished in the directory.");
+ else
+ header.addStringValue("expiredCertsError", i +
+ " expired certificates are unpublished in the directory.");
+ } else {
+ if (l == 0) {
+ header.addStringValue("expiredCertsUnpublished", "No");
+ } else {
+ header.addStringValue("expiredCertsUnpublished", "Failure");
+ header.addStringValue("expiredCertsError",
+ expiredCertsError.toString());
+ }
+ }
+ } else {
+ header.addStringValue("expiredCertsUnpublished", "Failure");
+ header.addStringValue("expiredCertsError", "Certificate repository is unavailable.");
+ }
+ }
+
+ // all or revoked
+ if ((updateValue[UPDATE_ALL] != null &&
+ updateValue[UPDATE_ALL].equalsIgnoreCase("yes")) ||
+ (updateValue[UPDATE_REVOKED] != null &&
+ updateValue[UPDATE_REVOKED].equalsIgnoreCase("yes"))) {
+ if (certificateRepository != null) {
+ if (updateValue[REVOKED_FROM].startsWith("0x")) {
+ updateValue[REVOKED_FROM] = hexToDecimal(updateValue[REVOKED_FROM]);
+ }
+ if (updateValue[REVOKED_TO].startsWith("0x")) {
+ updateValue[REVOKED_TO] = hexToDecimal(updateValue[REVOKED_TO]);
+ }
+ Enumeration<ICertRecord> revokedCerts = null;
+
+ if (updateValue[CHECK_FLAG] != null &&
+ updateValue[CHECK_FLAG].equalsIgnoreCase("yes")) {
+ revokedCerts =
+ certificateRepository.getRevokedPublishedCertificates(
+ updateValue[REVOKED_FROM],
+ updateValue[REVOKED_TO]);
+ } else {
+ revokedCerts =
+ certificateRepository.getRevokedCertificates(
+ updateValue[REVOKED_FROM],
+ updateValue[REVOKED_TO]);
+ }
+ int i = 0;
+ int l = 0;
+ String revokedCertsError = "";
+
+ if (revokedCerts != null) {
+ while (revokedCerts.hasMoreElements()) {
+ ICertRecord certRecord = revokedCerts.nextElement();
+ //X509CertImpl cert = certRecord.getCertificate();
+ X509CertImpl cert = null;
+ Object o = certRecord.getCertificate();
+
+ if (o instanceof X509CertImpl)
+ cert = (X509CertImpl) o;
+
+ MetaInfo metaInfo = null;
+ String ridString = null;
+
+ metaInfo = (MetaInfo) certRecord.get(ICertRecord.ATTR_META_INFO);
+ if (metaInfo == null) {
+ // ca's self signed signing cert and
+ // server cert has no related request and
+ // have no metaInfo
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAIL_GET_ICERT_RECORD",
+ cert.getSerialNumber().toString(16)));
+ } else {
+ ridString = (String) metaInfo.get(ICertRecord.META_REQUEST_ID);
+ }
+
+ IRequest r = null;
+
+ if (ridString != null) {
+ RequestId rid = new RequestId(ridString);
+
+ r = mCA.getRequestQueue().findRequest(rid);
+ }
+
+ try {
+ l++;
+ if (r == null) {
+ mPublisherProcessor.unpublishCert(cert, null);
+ } else {
+ mPublisherProcessor.unpublishCert(cert, r);
+ }
+ i++;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("LDAP_ERROR_UNPUBLISH_CERT",
+ certRecord.getSerialNumber().toString(16),
+ e.toString()));
+ revokedCertsError +=
+ "Failed to unpublish certificate: 0x" +
+ certRecord.getSerialNumber().toString(16) +
+ ".\n <BR> &nbsp;&nbsp;&nbsp;&nbsp;";
+ }
+ }
+ }
+ if (i > 0 && i == l) {
+ header.addStringValue("revokedCertsUnpublished", "Success");
+ if (i == 1)
+ header.addStringValue("revokedCertsError", i +
+ " revoked certificate is unpublished in the directory.");
+ else
+ header.addStringValue("revokedCertsError", i +
+ " revoked certificates are unpublished in the directory.");
+ } else {
+ if (l == 0) {
+ header.addStringValue("revokedCertsUnpublished", "No");
+ } else {
+ header.addStringValue("revokedCertsUnpublished", "Failure");
+ header.addStringValue("revokedCertsError",
+ revokedCertsError);
+ }
+ }
+ } else {
+ header.addStringValue("revokedCertsUnpublished", "Failure");
+ header.addStringValue("revokedCertsError", "Certificate repository is unavailable.");
+ }
+ }
+
+ return;
+ }
+
+ private String hexToDecimal(String hex) {
+ String newHex = hex.substring(2);
+ BigInteger bi = new BigInteger(newHex, 16);
+
+ return bi.toString();
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/scep/CRSEnrollment.java b/base/server/cms/src/com/netscape/cms/servlet/cert/scep/CRSEnrollment.java
new file mode 100644
index 000000000..30c07d1c1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/scep/CRSEnrollment.java
@@ -0,0 +1,2133 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert.scep;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileOutputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Random;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.security.pkcs.PKCS10;
+import netscape.security.pkcs.PKCS10Attribute;
+import netscape.security.pkcs.PKCS10Attributes;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AVA;
+import netscape.security.x509.CertAttrSet;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.DNSName;
+import netscape.security.x509.Extension;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNameInterface;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.IPAddressName;
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.OIDMap;
+import netscape.security.x509.RDN;
+import netscape.security.x509.SubjectAlternativeNameExtension;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X500NameAttrMap;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.NoSuchTokenException;
+import org.mozilla.jss.asn1.ANY;
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.BIT_STRING;
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.crypto.Cipher;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.EncryptionAlgorithm;
+import org.mozilla.jss.crypto.IVParameterSpec;
+import org.mozilla.jss.crypto.KeyGenAlgorithm;
+import org.mozilla.jss.crypto.KeyGenerator;
+import org.mozilla.jss.crypto.KeyWrapAlgorithm;
+import org.mozilla.jss.crypto.KeyWrapper;
+import org.mozilla.jss.crypto.ObjectNotFoundException;
+import org.mozilla.jss.crypto.SymmetricKey;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.pkcs7.IssuerAndSerialNumber;
+import org.mozilla.jss.pkix.cert.Certificate;
+import org.mozilla.jss.util.IncorrectPasswordException;
+import org.mozilla.jss.util.PasswordCallback;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthCredentials;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.profile.SSLClientCertProvider;
+import com.netscape.cmsutil.scep.CRSPKIMessage;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * This servlet deals with PKCS#10-based certificate requests from
+ * CRS, now called SCEP, and defined at:
+ * http://search.ietf.org/internet-drafts/draft-nourse-scep-02.txt
+ *
+ * The router is hardcoded to look for the http://host:80/cgi-bin/pkiclient.exe
+ *
+ * The HTTP parameters are 'operation' and 'message'
+ * operation can be either 'GetCACert' or 'PKIOperation'
+ *
+ * @version $Revision$, $Date$
+ */
+public class CRSEnrollment extends HttpServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8483002540957382369L;
+ protected IProfileSubsystem mProfileSubsystem = null;
+ protected String mProfileId = null;
+ protected ICertAuthority mAuthority;
+ protected IConfigStore mConfig = null;
+ protected IAuthSubsystem mAuthSubsystem;
+ protected String mAppendDN = null;
+ protected String mEntryObjectclass = null;
+ protected boolean mCreateEntry = false;
+ protected boolean mFlattenDN = false;
+
+ private String mAuthManagerName;
+ private String mSubstoreName;
+ private boolean mEnabled = false;
+ private boolean mUseCA = true;
+ private String mNickname = null;
+ private String mTokenName = "";
+ private String mHashAlgorithm = "SHA1";
+ private String mHashAlgorithmList = null;
+ private String[] mAllowedHashAlgorithm;
+ private String mConfiguredEncryptionAlgorithm = "DES3";
+ private String mEncryptionAlgorithm = "DES3";
+ private String mEncryptionAlgorithmList = null;
+ private String[] mAllowedEncryptionAlgorithm;
+ private Random mRandom = null;
+ private int mNonceSizeLimit = 0;
+ protected ILogger mLogger = CMS.getLogger();
+ private ICertificateAuthority ca;
+ /* for hashing challenge password */
+ protected MessageDigest mSHADigest = null;
+
+ private static final String PROP_SUBSTORENAME = "substorename";
+ private static final String PROP_AUTHORITY = "authority";
+ private static final String PROP_CRSAUTHMGR = "authName";
+ private static final String PROP_APPENDDN = "appendDN";
+ private static final String PROP_CREATEENTRY = "createEntry";
+ private static final String PROP_FLATTENDN = "flattenDN";
+ private static final String PROP_ENTRYOC = "entryObjectclass";
+
+ // URL parameters
+ private static final String URL_OPERATION = "operation";
+ private static final String URL_MESSAGE = "message";
+
+ // possible values for 'operation'
+ private static final String OP_GETCACERT = "GetCACert";
+ private static final String OP_PKIOPERATION = "PKIOperation";
+
+ public static final String AUTH_PASSWORD = "pwd";
+
+ public static final String AUTH_CREDS = "AuthCreds";
+ public static final String AUTH_TOKEN = "AuthToken";
+ public static final String AUTH_FAILED = "AuthFailed";
+
+ public static final String SANE_DNSNAME = "DNSName";
+ public static final String SANE_IPADDRESS = "IPAddress";
+
+ public static final String CERTINFO = "CertInfo";
+ public static final String SUBJECTNAME = "SubjectName";
+
+ public static ObjectIdentifier OID_UNSTRUCTUREDNAME = null;
+ public static ObjectIdentifier OID_UNSTRUCTUREDADDRESS = null;
+ public static ObjectIdentifier OID_SERIALNUMBER = null;
+
+ public CRSEnrollment() {
+ }
+
+ public static Hashtable<String, String> toHashtable(HttpServletRequest req) {
+ Hashtable<String, String> httpReqHash = new Hashtable<String, String>();
+ Enumeration<String> names = req.getParameterNames();
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ httpReqHash.put(name, req.getParameter(name));
+ }
+ return httpReqHash;
+ }
+
+ public void init(ServletConfig sc) {
+ // Find the CertificateAuthority we should use for CRS.
+ String crsCA = sc.getInitParameter(PROP_AUTHORITY);
+ if (crsCA == null)
+ crsCA = "ca";
+ mAuthority = (ICertAuthority) CMS.getSubsystem(crsCA);
+ ca = (ICertificateAuthority) mAuthority;
+
+ if (mAuthority == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CANT_FIND_AUTHORITY", crsCA));
+ }
+
+ try {
+ if (mAuthority instanceof ISubsystem) {
+ IConfigStore authorityConfig = ((ISubsystem) mAuthority).getConfigStore();
+ IConfigStore scepConfig = authorityConfig.getSubStore("scep");
+ mEnabled = scepConfig.getBoolean("enable", false);
+ mHashAlgorithm = scepConfig.getString("hashAlgorithm", "SHA1");
+ mConfiguredEncryptionAlgorithm = scepConfig.getString("encryptionAlgorithm", "DES3");
+ mNonceSizeLimit = scepConfig.getInteger("nonceSizeLimit", 0);
+ mHashAlgorithmList = scepConfig.getString("allowedHashAlgorithms", "SHA1,SHA256,SHA512");
+ mAllowedHashAlgorithm = mHashAlgorithmList.split(",");
+ mEncryptionAlgorithmList = scepConfig.getString("allowedEncryptionAlgorithms", "DES3");
+ mAllowedEncryptionAlgorithm = mEncryptionAlgorithmList.split(",");
+ mNickname = scepConfig.getString("nickname", ca.getNickname());
+ if (mNickname.equals(ca.getNickname())) {
+ mTokenName = ca.getSigningUnit().getTokenName();
+ } else {
+ mTokenName = scepConfig.getString("tokenname", "");
+ mUseCA = false;
+ }
+ if (!(mTokenName.equalsIgnoreCase(Constants.PR_INTERNAL_TOKEN) ||
+ mTokenName.equalsIgnoreCase("Internal Key Storage Token") || mTokenName.length() == 0)) {
+ int i = mNickname.indexOf(':');
+ if (!((i > -1) && (mTokenName.length() == i) && (mNickname.startsWith(mTokenName)))) {
+ mNickname = mTokenName + ":" + mNickname;
+ }
+ }
+ }
+ } catch (EBaseException e) {
+ CMS.debug("CRSEnrollment: init: EBaseException: " + e);
+ }
+ mEncryptionAlgorithm = mConfiguredEncryptionAlgorithm;
+ CMS.debug("CRSEnrollment: init: SCEP support is " + ((mEnabled) ? "enabled" : "disabled") + ".");
+ CMS.debug("CRSEnrollment: init: SCEP nickname: " + mNickname);
+ CMS.debug("CRSEnrollment: init: CA nickname: " + ca.getNickname());
+ CMS.debug("CRSEnrollment: init: Token name: " + mTokenName);
+ CMS.debug("CRSEnrollment: init: Is SCEP using CA keys: " + mUseCA);
+ CMS.debug("CRSEnrollment: init: mNonceSizeLimit: " + mNonceSizeLimit);
+ CMS.debug("CRSEnrollment: init: mHashAlgorithm: " + mHashAlgorithm);
+ CMS.debug("CRSEnrollment: init: mHashAlgorithmList: " + mHashAlgorithmList);
+ for (int i = 0; i < mAllowedHashAlgorithm.length; i++) {
+ mAllowedHashAlgorithm[i] = mAllowedHashAlgorithm[i].trim();
+ CMS.debug("CRSEnrollment: init: mAllowedHashAlgorithm[" + i + "]=" + mAllowedHashAlgorithm[i]);
+ }
+ CMS.debug("CRSEnrollment: init: mEncryptionAlgorithm: " + mEncryptionAlgorithm);
+ CMS.debug("CRSEnrollment: init: mEncryptionAlgorithmList: " + mEncryptionAlgorithmList);
+ for (int i = 0; i < mAllowedEncryptionAlgorithm.length; i++) {
+ mAllowedEncryptionAlgorithm[i] = mAllowedEncryptionAlgorithm[i].trim();
+ CMS.debug("CRSEnrollment: init: mAllowedEncryptionAlgorithm[" + i + "]=" + mAllowedEncryptionAlgorithm[i]);
+ }
+
+ try {
+ mProfileSubsystem = (IProfileSubsystem) CMS.getSubsystem("profile");
+ mProfileId = sc.getInitParameter("profileId");
+ CMS.debug("CRSEnrollment: init: mProfileId=" + mProfileId);
+
+ mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ mAuthManagerName = sc.getInitParameter(PROP_CRSAUTHMGR);
+ mAppendDN = sc.getInitParameter(PROP_APPENDDN);
+ String tmp = sc.getInitParameter(PROP_CREATEENTRY);
+ if (tmp != null && tmp.trim().equalsIgnoreCase("true"))
+ mCreateEntry = true;
+ else
+ mCreateEntry = false;
+ tmp = sc.getInitParameter(PROP_FLATTENDN);
+ if (tmp != null && tmp.trim().equalsIgnoreCase("true"))
+ mFlattenDN = true;
+ else
+ mFlattenDN = false;
+ mEntryObjectclass = sc.getInitParameter(PROP_ENTRYOC);
+ if (mEntryObjectclass == null)
+ mEntryObjectclass = "cep";
+ mSubstoreName = sc.getInitParameter(PROP_SUBSTORENAME);
+ if (mSubstoreName == null)
+ mSubstoreName = "default";
+ } catch (Exception e) {
+ }
+
+ OID_UNSTRUCTUREDNAME = X500NameAttrMap.getDefault().getOid("UNSTRUCTUREDNAME");
+ OID_UNSTRUCTUREDADDRESS = X500NameAttrMap.getDefault().getOid("UNSTRUCTUREDADDRESS");
+ OID_SERIALNUMBER = X500NameAttrMap.getDefault().getOid("SERIALNUMBER");
+
+ try {
+ mSHADigest = MessageDigest.getInstance("SHA1");
+ } catch (NoSuchAlgorithmException e) {
+ }
+
+ mRandom = new Random();
+ }
+
+ /**
+ *
+ * Service a CRS Request. It all starts here. This is where the message from the
+ * router is processed
+ *
+ * @param httpReq The HttpServletRequest.
+ * @param httpResp The HttpServletResponse.
+ *
+ */
+ public void service(HttpServletRequest httpReq,
+ HttpServletResponse httpResp)
+ throws ServletException {
+ boolean running_state = CMS.isInRunningState();
+ if (!running_state)
+ throw new ServletException(
+ "CMS server is not ready to serve.");
+
+ String operation = null;
+ String message = null;
+ mEncryptionAlgorithm = mConfiguredEncryptionAlgorithm;
+
+ // Parse the URL from the HTTP Request. Split it up into
+ // a structure which enables us to read the form elements
+ IArgBlock input = CMS.createArgBlock(toHashtable(httpReq));
+
+ try {
+ // Read in two form parameters - the router sets these
+ operation = (String) input.get(URL_OPERATION);
+ CMS.debug("operation=" + operation);
+ message = (String) input.get(URL_MESSAGE);
+ CMS.debug("message=" + message);
+
+ if (!mEnabled) {
+ CMS.debug("CRSEnrollment: SCEP support is disabled.");
+ throw new ServletException("SCEP support is disabled.");
+ }
+ if (operation == null) {
+ // 'operation' is mandatory.
+ throw new ServletException("Bad request: operation missing from URL");
+ }
+
+ /**
+ * the router can make two kinds of requests
+ * 1) simple request for CA cert
+ * 2) encoded, signed, enveloped request for anything else (PKIOperation)
+ */
+
+ if (operation.equals(OP_GETCACERT)) {
+ handleGetCACert(httpReq, httpResp);
+ } else if (operation.equals(OP_PKIOPERATION)) {
+ String decodeMode = (String) input.get("decode");
+ if (decodeMode == null || decodeMode.equals("false")) {
+ handlePKIOperation(httpReq, httpResp, message);
+ } else {
+ decodePKIMessage(httpReq, httpResp, message);
+ }
+ } else {
+ CMS.debug("Invalid operation " + operation);
+ throw new ServletException("unknown operation requested: " + operation);
+ }
+
+ } catch (ServletException e) {
+ CMS.debug("ServletException " + e);
+ throw new ServletException(e.getMessage().toString());
+ } catch (Exception e) {
+ CMS.debug("Service exception " + e);
+ log(ILogger.LL_FAILURE, e.getMessage());
+ }
+
+ }
+
+ /**
+ * Log a message to the system log
+ */
+
+ private void log(int level, String msg) {
+
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ level, "CEP Enrollment: " + msg);
+ }
+
+ private boolean isAlgorithmAllowed(String[] allowedAlgorithm, String algorithm) {
+ boolean allowed = false;
+
+ if (algorithm != null && algorithm.length() > 0) {
+ for (int i = 0; i < allowedAlgorithm.length; i++) {
+ if (algorithm.equalsIgnoreCase(allowedAlgorithm[i])) {
+ allowed = true;
+ }
+ }
+ }
+
+ return allowed;
+ }
+
+ public IAuthToken authenticate(AuthCredentials credentials, IProfileAuthenticator authenticator,
+ HttpServletRequest request) throws EBaseException {
+
+ // build credential
+ Enumeration<String> authNames = authenticator.getValueNames();
+
+ if (authNames != null) {
+ while (authNames.hasMoreElements()) {
+ String authName = authNames.nextElement();
+
+ credentials.set(authName, request.getParameter(authName));
+ }
+ }
+
+ credentials.set("clientHost", request.getRemoteHost());
+ IAuthToken authToken = authenticator.authenticate(credentials);
+ if (authToken == null) {
+ return null;
+ }
+ SessionContext sc = SessionContext.getContext();
+ if (sc != null) {
+ sc.put(SessionContext.AUTH_MANAGER_ID, authenticator.getName());
+ String userid = authToken.getInString(IAuthToken.USER_ID);
+ if (userid != null) {
+ sc.put(SessionContext.USER_ID, userid);
+ }
+ }
+
+ return authToken;
+ }
+
+ /**
+ * Return the CA certificate back to the requestor.
+ * This needs to be changed so that if the CA has a certificate chain,
+ * the whole thing should get packaged as a PKIMessage (degnerate PKCS7 - no
+ * signerInfo)
+ */
+
+ public void handleGetCACert(HttpServletRequest httpReq,
+ HttpServletResponse httpResp)
+ throws ServletException {
+ java.security.cert.X509Certificate[] chain = null;
+
+ CertificateChain certChain = mAuthority.getCACertChain();
+
+ try {
+ if (certChain == null) {
+ throw new ServletException("Internal Error: cannot get CA Cert");
+ }
+
+ chain = certChain.getChain();
+
+ byte[] bytes = null;
+
+ int i = 0;
+ String message = httpReq.getParameter(URL_MESSAGE);
+ CMS.debug("handleGetCACert message=" + message);
+ if (message != null) {
+ try {
+ int j = Integer.parseInt(message);
+ if (j < chain.length) {
+ i = j;
+ }
+ } catch (NumberFormatException e1) {
+ }
+ }
+ CMS.debug("handleGetCACert selected chain=" + i);
+
+ if (mUseCA) {
+ bytes = chain[i].getEncoded();
+ } else {
+ CryptoContext cx = new CryptoContext();
+ bytes = cx.getSigningCert().getEncoded();
+ }
+
+ httpResp.setContentType("application/x-x509-ca-cert");
+
+ // The following code may be used one day to encode
+ // the RA/CA cert chain for RA mode, but it will need some
+ // work.
+
+ /******
+ * SET certs = new SET();
+ * for (int i=0; i<chain.length; i++) {
+ * ANY cert = new ANY(chain[i].getEncoded());
+ * certs.addElement(cert);
+ * }
+ *
+ * SignedData crsd = new SignedData(
+ * new SET(), // empty set of digestAlgorithmID's
+ * new ContentInfo(
+ * new OBJECT_IDENTIFIER(new long[] {1,2,840,113549,1,7,1}),
+ * null), //empty content
+ * certs,
+ * null, // no CRL's
+ * new SET() // empty SignerInfos
+ * );
+ *
+ * ContentInfo wrap = new ContentInfo(ContentInfo.SIGNED_DATA, crsd);
+ *
+ * ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ * wrap.encode(baos);
+ *
+ * bytes = baos.toByteArray();
+ *
+ * httpResp.setContentType("application/x-x509-ca-ra-cert");
+ *****/
+
+ httpResp.setContentLength(bytes.length);
+ httpResp.getOutputStream().write(bytes);
+ httpResp.getOutputStream().flush();
+
+ CMS.debug("Output certificate chain:");
+ CMS.debug(bytes);
+ } catch (Exception e) {
+ CMS.debug("handleGetCACert exception " + e);
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_SENDING_DER_ENCODE_CERT", e.getMessage()));
+ throw new ServletException("Failed sending DER encoded version of CA cert to client");
+ }
+
+ }
+
+ public String getPasswordFromP10(PKCS10 p10) {
+ PKCS10Attributes p10atts = p10.getAttributes();
+ Enumeration<PKCS10Attribute> e = p10atts.getElements();
+
+ try {
+ while (e.hasMoreElements()) {
+ PKCS10Attribute p10a = e.nextElement();
+ CertAttrSet attr = p10a.getAttributeValue();
+
+ if (attr.getName().equals(ChallengePassword.NAME)) {
+ if (attr.get(ChallengePassword.PASSWORD) != null) {
+ return (String) attr.get(ChallengePassword.PASSWORD);
+ }
+ }
+ }
+ } catch (Exception e1) {
+ // do nothing
+ }
+ return null;
+ }
+
+ /**
+ * If the 'operation' is 'PKIOperation', the 'message' part of the URL is a
+ * PKIMessage structure. We decode it to see what type message it is.
+ */
+
+ /**
+ * Decodes the PKI message and return information to RA.
+ */
+ public void decodePKIMessage(HttpServletRequest httpReq,
+ HttpServletResponse httpResp,
+ String msg)
+ throws ServletException {
+
+ CryptoContext cx = null;
+
+ CRSPKIMessage req = null;
+
+ byte[] decodedPKIMessage;
+ byte[] response = null;
+ String responseData = "";
+
+ decodedPKIMessage = Utils.base64decode(msg);
+
+ try {
+ ByteArrayInputStream is = new ByteArrayInputStream(decodedPKIMessage);
+
+ // We make two CRSPKIMessages. One of them, is the request, so we initialize
+ // it from the DER given to us from the router.
+ // The second is the response, and we'll fill this in as we go.
+
+ if (decodedPKIMessage.length < 50) {
+ throw new ServletException("CRS request is too small to be a real request (" +
+ decodedPKIMessage.length + " bytes)");
+ }
+ try {
+ req = new CRSPKIMessage(is);
+ String ea = req.getEncryptionAlgorithm();
+ if (!isAlgorithmAllowed(mAllowedEncryptionAlgorithm, ea)) {
+ CMS.debug("CRSEnrollment: decodePKIMessage: Encryption algorithm '" + ea +
+ "' is not allowed (" + mEncryptionAlgorithmList + ").");
+ throw new ServletException("Encryption algorithm '" + ea +
+ "' is not allowed (" + mEncryptionAlgorithmList + ").");
+ }
+ String da = req.getDigestAlgorithmName();
+ if (!isAlgorithmAllowed(mAllowedHashAlgorithm, da)) {
+ CMS.debug("CRSEnrollment: decodePKIMessage: Hashing algorithm '" + da +
+ "' is not allowed (" + mHashAlgorithmList + ").");
+ throw new ServletException("Hashing algorithm '" + da +
+ "' is not allowed (" + mHashAlgorithmList + ").");
+ }
+ if (ea != null) {
+ mEncryptionAlgorithm = ea;
+ }
+ } catch (Exception e) {
+ CMS.debug(e);
+ throw new ServletException("Could not decode the request.");
+ }
+
+ // Create a new crypto context for doing all the crypto operations
+ cx = new CryptoContext();
+
+ // Verify Signature on message (throws exception if sig bad)
+ verifyRequest(req, cx);
+ unwrapPKCS10(req, cx);
+
+ IProfile profile = mProfileSubsystem.getProfile(mProfileId);
+ if (profile == null) {
+ CMS.debug("Profile '" + mProfileId + "' not found.");
+ throw new ServletException("Profile '" + mProfileId + "' not found.");
+ } else {
+ CMS.debug("Found profile '" + mProfileId + "'.");
+ }
+
+ IProfileAuthenticator authenticator = null;
+ try {
+ CMS.debug("Retrieving authenticator");
+ authenticator = profile.getAuthenticator();
+ if (authenticator == null) {
+ CMS.debug("Authenticator not found.");
+ throw new ServletException("Authenticator not found.");
+ } else {
+ CMS.debug("Got authenticator=" + authenticator.getClass().getName());
+ }
+ } catch (EProfileException e) {
+ throw new ServletException("Authenticator not found.");
+ }
+ AuthCredentials credentials = new AuthCredentials();
+ IAuthToken authToken = null;
+ // for ssl authentication; pass in servlet for retrieving
+ // ssl client certificates
+ SessionContext context = SessionContext.getContext();
+
+ // insert profile context so that input parameter can be retrieved
+ context.put("sslClientCertProvider", new SSLClientCertProvider(httpReq));
+
+ try {
+ authToken = authenticate(credentials, authenticator, httpReq);
+ } catch (Exception e) {
+ CMS.debug("Authentication failure: " + e.getMessage());
+ throw new ServletException("Authentication failure: " + e.getMessage());
+ }
+ if (authToken == null) {
+ CMS.debug("Authentication failure.");
+ throw new ServletException("Authentication failure.");
+ }
+
+ // Deal with Transaction ID
+ String transactionID = req.getTransactionID();
+ responseData = responseData +
+ "<TransactionID>" + transactionID + "</TransactionID>";
+
+ // End-User or RA's IP address
+ responseData = responseData +
+ "<RemoteAddr>" + httpReq.getRemoteAddr() + "</RemoteAddr>";
+
+ responseData = responseData +
+ "<RemoteHost>" + httpReq.getRemoteHost() + "</RemoteHost>";
+
+ // Deal with message type
+ String mt = req.getMessageType();
+ responseData = responseData +
+ "<MessageType>" + mt + "</MessageType>";
+
+ PKCS10 p10 = req.getP10();
+ X500Name p10subject = p10.getSubjectName();
+ responseData = responseData +
+ "<SubjectName>" + p10subject.toString() + "</SubjectName>";
+
+ String pkcs10Attr = "";
+ PKCS10Attributes p10atts = p10.getAttributes();
+ Enumeration<PKCS10Attribute> e = p10atts.getElements();
+
+ while (e.hasMoreElements()) {
+ PKCS10Attribute p10a = e.nextElement();
+ CertAttrSet attr = p10a.getAttributeValue();
+
+ if (attr.getName().equals(ChallengePassword.NAME)) {
+ if (attr.get(ChallengePassword.PASSWORD) != null) {
+ pkcs10Attr =
+ pkcs10Attr
+ +
+ "<ChallengePassword><Password>"
+ + (String) attr.get(ChallengePassword.PASSWORD)
+ + "</Password></ChallengePassword>";
+ }
+
+ }
+ String extensionsStr = "";
+ if (attr.getName().equals(ExtensionsRequested.NAME)) {
+
+ Enumeration<Extension> exts = ((ExtensionsRequested) attr).getExtensions().elements();
+ while (exts.hasMoreElements()) {
+ Extension ext = exts.nextElement();
+
+ if (ext.getExtensionId().equals(
+ OIDMap.getOID(SubjectAlternativeNameExtension.IDENT))) {
+ SubjectAlternativeNameExtension sane = new SubjectAlternativeNameExtension(
+ Boolean.valueOf(false), // noncritical
+ ext.getExtensionValue());
+
+ @SuppressWarnings("unchecked")
+ Vector<GeneralNameInterface> v =
+ (Vector<GeneralNameInterface>) sane
+ .get(SubjectAlternativeNameExtension.SUBJECT_NAME);
+
+ Enumeration<GeneralNameInterface> gne = v.elements();
+
+ StringBuffer subjAltNameStr = new StringBuffer();
+ while (gne.hasMoreElements()) {
+ GeneralNameInterface gni = gne.nextElement();
+ if (gni instanceof GeneralName) {
+ GeneralName genName = (GeneralName) gni;
+
+ String gn = genName.toString();
+ int colon = gn.indexOf(':');
+ String gnType = gn.substring(0, colon).trim();
+ String gnValue = gn.substring(colon + 1).trim();
+
+ subjAltNameStr.append("<");
+ subjAltNameStr.append(gnType);
+ subjAltNameStr.append(">");
+ subjAltNameStr.append(gnValue);
+ subjAltNameStr.append("</");
+ subjAltNameStr.append(gnType);
+ subjAltNameStr.append(">");
+ }
+ } // while
+ extensionsStr = "<SubjAltName>" +
+ subjAltNameStr.toString() + "</SubjAltName>";
+ } // if
+ } // while
+ pkcs10Attr = pkcs10Attr +
+ "<Extensions>" + extensionsStr + "</Extensions>";
+ } // if extensions
+ } // while
+ responseData = responseData +
+ "<PKCS10>" + pkcs10Attr + "</PKCS10>";
+
+ } catch (ServletException e) {
+ throw new ServletException(e.getMessage().toString());
+ } catch (CRSInvalidSignatureException e) {
+ CMS.debug("handlePKIMessage exception " + e);
+ CMS.debug(e);
+ } catch (Exception e) {
+ CMS.debug("handlePKIMessage exception " + e);
+ CMS.debug(e);
+ throw new ServletException("Failed to process message in CEP servlet: " + e.getMessage());
+ }
+
+ // We have now processed the request, and need to make the response message
+
+ try {
+
+ responseData = "<XMLResponse>" + responseData + "</XMLResponse>";
+ // Get the response coding
+ response = responseData.getBytes();
+
+ // Encode the httpResp into B64
+ httpResp.setContentType("application/xml");
+ httpResp.setContentLength(response.length);
+ httpResp.getOutputStream().write(response);
+ httpResp.getOutputStream().flush();
+
+ int i1 = responseData.indexOf("<Password>");
+ if (i1 > -1) {
+ i1 += 10; // 10 is a length of "<Password>"
+ int i2 = responseData.indexOf("</Password>", i1);
+ if (i2 > -1) {
+ responseData = responseData.substring(0, i1) + "********" +
+ responseData.substring(i2, responseData.length());
+ }
+ }
+
+ CMS.debug("Output (decoding) PKIOperation response:");
+ CMS.debug(responseData);
+ } catch (Exception e) {
+ throw new ServletException("Failed to create response for CEP message" + e.getMessage());
+ }
+
+ }
+
+ /**
+ * finds a request with this transaction ID.
+ * If could not find any request - return null
+ * If could only find 'rejected' or 'cancelled' requests, return null
+ * If found 'pending' or 'completed' request - return that request
+ */
+
+ public void handlePKIOperation(HttpServletRequest httpReq,
+ HttpServletResponse httpResp,
+ String msg)
+ throws ServletException {
+
+ CryptoContext cx = null;
+
+ CRSPKIMessage req = null;
+ CRSPKIMessage crsResp = null;
+
+ byte[] decodedPKIMessage;
+ byte[] response = null;
+ X509CertImpl cert = null;
+
+ decodedPKIMessage = Utils.base64decode(msg);
+
+ try {
+ ByteArrayInputStream is = new ByteArrayInputStream(decodedPKIMessage);
+
+ // We make two CRSPKIMessages. One of them, is the request, so we initialize
+ // it from the DER given to us from the router.
+ // The second is the response, and we'll fill this in as we go.
+
+ if (decodedPKIMessage.length < 50) {
+ throw new ServletException("CRS request is too small to be a real request (" +
+ decodedPKIMessage.length + " bytes)");
+ }
+ try {
+ req = new CRSPKIMessage(is);
+ String ea = req.getEncryptionAlgorithm();
+ if (!isAlgorithmAllowed(mAllowedEncryptionAlgorithm, ea)) {
+ CMS.debug("CRSEnrollment: handlePKIOperation: Encryption algorithm '" + ea +
+ "' is not allowed (" + mEncryptionAlgorithmList + ").");
+ throw new ServletException("Encryption algorithm '" + ea +
+ "' is not allowed (" + mEncryptionAlgorithmList + ").");
+ }
+ String da = req.getDigestAlgorithmName();
+ if (!isAlgorithmAllowed(mAllowedHashAlgorithm, da)) {
+ CMS.debug("CRSEnrollment: handlePKIOperation: Hashing algorithm '" + da +
+ "' is not allowed (" + mHashAlgorithmList + ").");
+ throw new ServletException("Hashing algorithm '" + da +
+ "' is not allowed (" + mHashAlgorithmList + ").");
+ }
+ if (ea != null) {
+ mEncryptionAlgorithm = ea;
+ }
+ crsResp = new CRSPKIMessage();
+ } catch (ServletException e) {
+ throw new ServletException(e.getMessage().toString());
+ } catch (Exception e) {
+ CMS.debug(e);
+ throw new ServletException("Could not decode the request.");
+ }
+ crsResp.setMessageType(CRSPKIMessage.mType_CertRep);
+
+ // Create a new crypto context for doing all the crypto operations
+ cx = new CryptoContext();
+
+ // Verify Signature on message (throws exception if sig bad)
+ verifyRequest(req, cx);
+
+ // Deal with Transaction ID
+ String transactionID = req.getTransactionID();
+ if (transactionID == null) {
+ throw new ServletException("Error: malformed PKIMessage - missing transactionID");
+ } else {
+ crsResp.setTransactionID(transactionID);
+ }
+
+ // Deal with Nonces
+ byte[] sn = req.getSenderNonce();
+ if (sn == null) {
+ throw new ServletException("Error: malformed PKIMessage - missing sendernonce");
+ } else {
+ if (mNonceSizeLimit > 0 && sn.length > mNonceSizeLimit) {
+ byte[] snLimited = (mNonceSizeLimit > 0) ? new byte[mNonceSizeLimit] : null;
+ System.arraycopy(sn, 0, snLimited, 0, mNonceSizeLimit);
+ crsResp.setRecipientNonce(snLimited);
+ } else {
+ crsResp.setRecipientNonce(sn);
+ }
+ byte[] serverNonce = new byte[16];
+ mRandom.nextBytes(serverNonce);
+ crsResp.setSenderNonce(serverNonce);
+ // crsResp.setSenderNonce(new byte[] {0});
+ }
+
+ // Deal with message type
+ String mt = req.getMessageType();
+ if (mt == null) {
+ throw new ServletException("Error: malformed PKIMessage - missing messageType");
+ }
+
+ // now run appropriate code, depending on message type
+ if (mt.equals(CRSPKIMessage.mType_PKCSReq)) {
+ CMS.debug("Processing PKCSReq");
+ try {
+ // Check if there is an existing request. If this returns non-null,
+ // then the request is 'active' (either pending or completed) in
+ // which case, we compare the hash of the new request to the hash of the
+ // one in the queue - if they are the same, I return the state of the
+ // original request - as if it was 'getCertInitial' message.
+ // If the hashes are different, then the user attempted to enroll
+ // for a new request with the same txid, which is not allowed -
+ // so we return 'failure'.
+
+ IRequest cmsRequest = findRequestByTransactionID(req.getTransactionID(), true);
+
+ // If there was no request (with a cert) with this transaction ID,
+ // process it as a new request
+
+ cert = handlePKCSReq(httpReq, cmsRequest, req, crsResp, cx);
+
+ } catch (CRSFailureException e) {
+ throw new ServletException("Couldn't handle CEP request (PKCSReq) - " + e.getMessage());
+ }
+ } else if (mt.equals(CRSPKIMessage.mType_GetCertInitial)) {
+ CMS.debug("Processing GetCertInitial");
+ cert = handleGetCertInitial(req, crsResp);
+ } else {
+ CMS.debug("Invalid request type " + mt);
+ }
+ } catch (ServletException e) {
+ throw new ServletException(e.getMessage().toString());
+ } catch (CRSInvalidSignatureException e) {
+ CMS.debug("handlePKIMessage exception " + e);
+ CMS.debug(e);
+ crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badMessageCheck);
+ } catch (Exception e) {
+ CMS.debug("handlePKIMessage exception " + e);
+ CMS.debug(e);
+ throw new ServletException("Failed to process message in CEP servlet: " + e.getMessage());
+ }
+
+ // We have now processed the request, and need to make the response message
+
+ try {
+ // make the response
+ processCertRep(cx, cert, crsResp, req);
+
+ // Get the response coding
+ response = crsResp.getResponse();
+
+ // Encode the crsResp into B64
+ httpResp.setContentType("application/x-pki-message");
+ httpResp.setContentLength(response.length);
+ httpResp.getOutputStream().write(response);
+ httpResp.getOutputStream().flush();
+
+ CMS.debug("Output PKIOperation response:");
+ CMS.debug(CMS.BtoA(response));
+ } catch (Exception e) {
+ throw new ServletException("Failed to create response for CEP message" + e.getMessage());
+ }
+
+ }
+
+ /**
+ * finds a request with this transaction ID.
+ * If could not find any request - return null
+ * If could only find 'rejected' or 'cancelled' requests, return null
+ * If found 'pending' or 'completed' request - return that request
+ */
+
+ public IRequest findRequestByTransactionID(String txid, boolean ignoreRejected)
+ throws EBaseException {
+
+ /* Check if certificate request has been completed */
+
+ IRequestQueue rq = ca.getRequestQueue();
+ IRequest foundRequest = null;
+
+ Enumeration<RequestId> rids = rq.findRequestsBySourceId(txid);
+ if (rids == null) {
+ return null;
+ }
+
+ while (rids.hasMoreElements()) {
+ RequestId rid = rids.nextElement();
+ if (rid == null) {
+ continue;
+ }
+
+ IRequest request = rq.findRequest(rid);
+ if (request == null) {
+ continue;
+ }
+ if (!ignoreRejected ||
+ request.getRequestStatus().equals(RequestStatus.PENDING) ||
+ request.getRequestStatus().equals(RequestStatus.COMPLETE)) {
+ if (foundRequest != null) {
+ }
+ foundRequest = request;
+ }
+ }
+ return foundRequest;
+ }
+
+ /**
+ * Called if the router is requesting us to send it its certificate
+ * Examine request queue for a request matching the transaction ID.
+ * Ignore any rejected or cancelled requests.
+ *
+ * If a request is found in the pending state, the response should be
+ * 'pending'
+ *
+ * If a request is found in the completed state, the response should be
+ * to return the certificate
+ *
+ * If no request is found, the response should be to return null
+ *
+ */
+
+ public X509CertImpl handleGetCertInitial(CRSPKIMessage req, CRSPKIMessage resp) {
+ IRequest foundRequest = null;
+
+ // already done by handlePKIOperation
+ // resp.setRecipientNonce(req.getSenderNonce());
+ // resp.setSenderNonce(null);
+
+ try {
+ foundRequest = findRequestByTransactionID(req.getTransactionID(), false);
+ } catch (EBaseException e) {
+ }
+
+ if (foundRequest == null) {
+ resp.setFailInfo(CRSPKIMessage.mFailInfo_badCertId);
+ resp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE);
+ return null;
+ }
+
+ return makeResponseFromRequest(req, resp, foundRequest);
+ }
+
+ public void verifyRequest(CRSPKIMessage req, CryptoContext cx)
+ throws CRSInvalidSignatureException {
+
+ // Get Signed Data
+
+ @SuppressWarnings("unused")
+ byte[] reqAAbytes = req.getAA(); // check for errors
+
+ @SuppressWarnings("unused")
+ byte[] reqAAsig = req.getAADigest(); // check for errors
+
+ }
+
+ /**
+ * Create an entry for this user in the publishing directory
+ *
+ */
+
+ private boolean createEntry(String dn) {
+ boolean result = false;
+
+ IPublisherProcessor ldapPub = mAuthority.getPublisherProcessor();
+ if (ldapPub == null || !ldapPub.enabled()) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_CREATE_ENTRY_FROM_CEP"));
+
+ return result;
+ }
+
+ ILdapConnFactory connFactory = ldapPub.getLdapConnModule().getLdapConnFactory();
+ if (connFactory == null) {
+ return result;
+ }
+
+ LDAPConnection connection = null;
+ try {
+ connection = connFactory.getConn();
+ String[] objectclasses = { "top", mEntryObjectclass };
+ LDAPAttribute ocAttrs = new LDAPAttribute("objectclass", objectclasses);
+
+ LDAPAttributeSet attrSet = new LDAPAttributeSet();
+ attrSet.add(ocAttrs);
+
+ LDAPEntry newEntry = new LDAPEntry(dn, attrSet);
+ connection.add(newEntry);
+ result = true;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_FAIL_CREAT_ENTRY_EXISTS", dn));
+ } finally {
+ try {
+ connFactory.returnConn(connection);
+ } catch (Exception f) {
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Here we decrypt the PKCS10 message from the client
+ *
+ */
+
+ public void unwrapPKCS10(CRSPKIMessage req, CryptoContext cx)
+ throws ServletException,
+ CryptoManager.NotInitializedException,
+ CryptoContext.CryptoContextException,
+ CRSFailureException {
+
+ byte[] decryptedP10bytes = null;
+ SymmetricKey sk;
+ SymmetricKey skinternal;
+ SymmetricKey.Type skt;
+ KeyWrapper kw;
+ Cipher cip;
+ EncryptionAlgorithm ea;
+
+ // Unwrap the session key with the Cert server key
+ try {
+ kw = cx.getKeyWrapper();
+
+ kw.initUnwrap(cx.getPrivateKey(), null);
+
+ skt = SymmetricKey.Type.DES;
+ ea = EncryptionAlgorithm.DES_CBC;
+ if (mEncryptionAlgorithm != null && mEncryptionAlgorithm.equals("DES3")) {
+ skt = SymmetricKey.Type.DES3;
+ ea = EncryptionAlgorithm.DES3_CBC;
+ }
+
+ sk = kw.unwrapSymmetric(req.getWrappedKey(),
+ skt,
+ SymmetricKey.Usage.DECRYPT,
+ 0); // keylength is ignored
+
+ skinternal = cx.getDESKeyGenerator().clone(sk);
+
+ cip = skinternal.getOwningToken().getCipherContext(ea);
+
+ cip.initDecrypt(skinternal, (new IVParameterSpec(req.getIV())));
+
+ decryptedP10bytes = cip.doFinal(req.getEncryptedPkcs10());
+ CMS.debug("decryptedP10bytes:");
+ CMS.debug(decryptedP10bytes);
+
+ req.setP10(new PKCS10(decryptedP10bytes));
+ } catch (Exception e) {
+ CMS.debug("failed to unwrap PKCS10 " + e);
+ throw new CRSFailureException("Could not unwrap PKCS10 blob: " + e.getMessage());
+ }
+
+ }
+
+ private void getDetailFromRequest(CRSPKIMessage req, CRSPKIMessage crsResp)
+ throws CRSFailureException {
+
+ SubjectAlternativeNameExtension sane = null;
+
+ try {
+ PKCS10 p10 = req.getP10();
+
+ if (p10 == null) {
+ crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badMessageCheck);
+ crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE);
+ throw new CRSFailureException("Failed to decode pkcs10 from CEP request");
+ }
+
+ AuthCredentials authCreds = new AuthCredentials();
+
+ // Here, we make a new CertInfo - it's a new start for a certificate
+
+ X509CertInfo certInfo = CMS.getDefaultX509CertInfo();
+
+ // get some stuff out of the request
+ X509Key key = p10.getSubjectPublicKeyInfo();
+ X500Name p10subject = p10.getSubjectName();
+
+ X500Name subject = null;
+
+ // The following code will copy all the attributes
+ // into the AuthCredentials so they can be used for
+ // authentication
+ //
+ // Optionally, you can re-map the subject name from:
+ // one RDN, with many AVA's to
+ // many RDN's with one AVA in each.
+
+ Enumeration<RDN> rdne = p10subject.getRDNs();
+ Vector<RDN> rdnv = new Vector<RDN>();
+
+ Hashtable<String, String> sanehash = new Hashtable<String, String>();
+
+ X500NameAttrMap xnap = X500NameAttrMap.getDefault();
+ while (rdne.hasMoreElements()) {
+ RDN rdn = rdne.nextElement();
+ int i = 0;
+ AVA[] oldavas = rdn.getAssertion();
+ for (i = 0; i < rdn.getAssertionLength(); i++) {
+ AVA[] newavas = new AVA[1];
+ newavas[0] = oldavas[i];
+
+ authCreds.set(xnap.getName(oldavas[i].getOid()),
+ oldavas[i].getValue().getAsString());
+
+ if (oldavas[i].getOid().equals(OID_UNSTRUCTUREDNAME)) {
+
+ sanehash.put(SANE_DNSNAME, oldavas[i].getValue().getAsString());
+ }
+ if (oldavas[i].getOid().equals(OID_UNSTRUCTUREDADDRESS)) {
+ sanehash.put(SANE_IPADDRESS, oldavas[i].getValue().getAsString());
+ }
+
+ RDN newrdn = new RDN(newavas);
+ if (mFlattenDN) {
+ rdnv.addElement(newrdn);
+ }
+ }
+ }
+
+ if (mFlattenDN)
+ subject = new X500Name(rdnv);
+ else
+ subject = p10subject;
+
+ // create default key usage extension
+ KeyUsageExtension kue = new KeyUsageExtension();
+ kue.set(KeyUsageExtension.DIGITAL_SIGNATURE, Boolean.valueOf(true));
+ kue.set(KeyUsageExtension.KEY_ENCIPHERMENT, Boolean.valueOf(true));
+
+ PKCS10Attributes p10atts = p10.getAttributes();
+ Enumeration<PKCS10Attribute> e = p10atts.getElements();
+
+ while (e.hasMoreElements()) {
+ PKCS10Attribute p10a = e.nextElement();
+ CertAttrSet attr = p10a.getAttributeValue();
+
+ if (attr.getName().equals(ChallengePassword.NAME)) {
+ if (attr.get(ChallengePassword.PASSWORD) != null) {
+ req.put(AUTH_PASSWORD, attr.get(ChallengePassword.PASSWORD));
+ req.put(ChallengePassword.NAME,
+ hashPassword(
+ (String) attr.get(ChallengePassword.PASSWORD)));
+ }
+ }
+
+ if (attr.getName().equals(ExtensionsRequested.NAME)) {
+
+ Enumeration<Extension> exts = ((ExtensionsRequested) attr).getExtensions().elements();
+ while (exts.hasMoreElements()) {
+ Extension ext = exts.nextElement();
+
+ if (ext.getExtensionId().equals(
+ OIDMap.getOID(KeyUsageExtension.IDENT))) {
+
+ kue = new KeyUsageExtension(
+ new Boolean(false), // noncritical
+ ext.getExtensionValue());
+ }
+
+ if (ext.getExtensionId().equals(
+ OIDMap.getOID(SubjectAlternativeNameExtension.IDENT))) {
+ sane = new SubjectAlternativeNameExtension(
+ new Boolean(false), // noncritical
+ ext.getExtensionValue());
+
+ @SuppressWarnings("unchecked")
+ Vector<GeneralNameInterface> v =
+ (Vector<GeneralNameInterface>) sane
+ .get(SubjectAlternativeNameExtension.SUBJECT_NAME);
+
+ Enumeration<GeneralNameInterface> gne = v.elements();
+
+ while (gne.hasMoreElements()) {
+ GeneralNameInterface gni = gne.nextElement();
+ if (gni instanceof GeneralName) {
+ GeneralName genName = (GeneralName) gni;
+
+ String gn = genName.toString();
+ int colon = gn.indexOf(':');
+ String gnType = gn.substring(0, colon).trim();
+ String gnValue = gn.substring(colon + 1).trim();
+
+ authCreds.set(gnType, gnValue);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (authCreds != null)
+ req.put(AUTH_CREDS, authCreds);
+
+ try {
+ if (sane == null)
+ sane = makeDefaultSubjectAltName(sanehash);
+ } catch (Exception sane_e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ENROLL_FAIL_NO_SUBJ_ALT_NAME",
+ sane_e.getMessage()));
+ }
+
+ try {
+ if (mAppendDN != null && !mAppendDN.equals("")) {
+
+ new X500Name(subject.toString()); // check for errors
+
+ subject = new X500Name(subject.toString().concat("," + mAppendDN));
+ }
+
+ } catch (Exception sne) {
+ log(ILogger.LL_INFO,
+ "Unable to use appendDN parameter: "
+ + mAppendDN + ". Error is " + sne.getMessage() + " Using unmodified subjectname");
+ }
+
+ if (subject != null)
+ req.put(SUBJECTNAME, subject);
+
+ if (key == null || subject == null) {
+ // log
+ //throw new ERegistrationException(RegistrationResources.ERROR_MALFORMED_P10);
+ }
+
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+
+ certInfo.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(subject));
+
+ certInfo.set(X509CertInfo.KEY,
+ new CertificateX509Key(key));
+
+ CertificateExtensions ext = new CertificateExtensions();
+
+ if (kue != null) {
+ ext.set(KeyUsageExtension.NAME, kue);
+ }
+
+ // add subjectAltName extension, if present
+ if (sane != null) {
+ ext.set(SubjectAlternativeNameExtension.NAME, sane);
+ }
+
+ certInfo.set(X509CertInfo.EXTENSIONS, ext);
+
+ req.put(CERTINFO, certInfo);
+ } catch (Exception e) {
+ crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badMessageCheck);
+ crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE);
+ return;
+ } // NEED TO FIX
+ }
+
+ private SubjectAlternativeNameExtension makeDefaultSubjectAltName(Hashtable<String, String> ht) {
+
+ // if no subjectaltname extension was requested, we try to make it up
+ // from some of the elements of the subject name
+
+ int itemCount = ht.size();
+ GeneralNameInterface[] gn = new GeneralNameInterface[ht.size()];
+
+ itemCount = 0;
+ Enumeration<String> en = ht.keys();
+ while (en.hasMoreElements()) {
+ String key = en.nextElement();
+ if (key.equals(SANE_DNSNAME)) {
+ gn[itemCount++] = new DNSName(ht.get(key));
+ }
+ if (key.equals(SANE_IPADDRESS)) {
+ gn[itemCount++] = new IPAddressName(ht.get(key));
+ }
+ }
+
+ try {
+ return new SubjectAlternativeNameExtension(new GeneralNames(gn));
+ } catch (Exception e) {
+ log(ILogger.LL_INFO, CMS.getLogMessage("CMSGW_ENROLL_FAIL_NO_SUBJ_ALT_NAME",
+ e.getMessage()));
+ return null;
+ }
+ }
+
+ // Perform authentication
+
+ /*
+ * if the authentication is set up for CEP, and the user provides
+ * some credential, an attempt is made to authenticate the user
+ * If this fails, this method will return true
+ * If it is sucessful, this method will return true and
+ * an authtoken will be in the request
+ *
+ * If authentication is not configured, this method will
+ * return false. The request will be processed in the usual
+ * way, but no authtoken will be in the request.
+ *
+ * In other word, this method returns true if the request
+ * should be aborted, false otherwise.
+ */
+
+ private boolean authenticateUser(CRSPKIMessage req) {
+ boolean authenticationFailed = true;
+
+ if (mAuthManagerName == null) {
+ return false;
+ }
+
+ String password = (String) req.get(AUTH_PASSWORD);
+
+ AuthCredentials authCreds = (AuthCredentials) req.get(AUTH_CREDS);
+
+ if (authCreds == null) {
+ authCreds = new AuthCredentials();
+ }
+
+ // authtoken starts as null
+ AuthToken token = null;
+
+ if (password != null && !password.equals("")) {
+ try {
+ authCreds.set(AUTH_PASSWORD, password);
+ } catch (Exception e) {
+ }
+ }
+
+ try {
+ token = (AuthToken) mAuthSubsystem.authenticate(authCreds, mAuthManagerName);
+ authCreds.delete(AUTH_PASSWORD);
+ // if we got here, the authenticate call must not have thrown
+ // an exception
+ authenticationFailed = false;
+ } catch (EInvalidCredentials ex) {
+ // Invalid credentials - we must reject the request
+ authenticationFailed = true;
+ } catch (EMissingCredential mc) {
+ // Misssing credential - we'll log, and process manually
+ authenticationFailed = false;
+ } catch (EBaseException ex) {
+ // If there's some other error, we'll reject
+ // So, we just continue on, - AUTH_TOKEN will not be set.
+ }
+
+ if (token != null) {
+ req.put(AUTH_TOKEN, token);
+ }
+
+ return authenticationFailed;
+ }
+
+ private boolean areFingerprintsEqual(IRequest req, Hashtable<String, byte[]> fingerprints) {
+
+ Hashtable<String, String> old_fprints = req.getExtDataInHashtable(IRequest.FINGERPRINTS);
+ if (old_fprints == null) {
+ return false;
+ }
+
+ byte[] old_md5 = CMS.AtoB(old_fprints.get("MD5"));
+ byte[] new_md5 = fingerprints.get("MD5");
+
+ if (old_md5.length != new_md5.length)
+ return false;
+
+ for (int i = 0; i < old_md5.length; i++) {
+ if (old_md5[i] != new_md5[i])
+ return false;
+ }
+ return true;
+ }
+
+ public X509CertImpl handlePKCSReq(HttpServletRequest httpReq,
+ IRequest cmsRequest, CRSPKIMessage req,
+ CRSPKIMessage crsResp, CryptoContext cx)
+ throws ServletException,
+ CryptoManager.NotInitializedException,
+ CRSFailureException {
+
+ try {
+ unwrapPKCS10(req, cx);
+ Hashtable<String, byte[]> fingerprints = makeFingerPrints(req);
+
+ if (cmsRequest != null) {
+ if (areFingerprintsEqual(cmsRequest, fingerprints)) {
+ CMS.debug("created response from request");
+ return makeResponseFromRequest(req, crsResp, cmsRequest);
+ } else {
+ CMS.debug("duplicated transaction id");
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ENROLL_FAIL_DUP_TRANS_ID"));
+ crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badRequest);
+ crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE);
+ return null;
+ }
+ }
+
+ getDetailFromRequest(req, crsResp);
+ boolean authFailed = authenticateUser(req);
+
+ if (authFailed) {
+ CMS.debug("authentication failed");
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMSGW_ENROLL_FAIL_NO_AUTH"));
+ crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badIdentity);
+ crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE);
+
+ // perform audit log
+ String auditMessage = CMS.getLogMessage(
+ "LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST_5",
+ httpReq.getRemoteAddr(),
+ ILogger.FAILURE,
+ req.getTransactionID(),
+ "CRSEnrollment",
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+ ILogger signedAuditLogger = CMS.getSignedAuditLogger();
+ if (signedAuditLogger != null) {
+ signedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null, ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY, auditMessage);
+ }
+
+ return null;
+ } else {
+ IRequest ireq = postRequest(httpReq, req, crsResp);
+
+ CMS.debug("created response");
+ return makeResponseFromRequest(req, crsResp, ireq);
+ }
+ } catch (CryptoContext.CryptoContextException e) {
+ CMS.debug("failed to decrypt the request " + e);
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ENROLL_FAIL_NO_DECRYPT_PKCS10",
+ e.getMessage()));
+ crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badMessageCheck);
+ crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE);
+ } catch (EBaseException e) {
+ CMS.debug("operation failure - " + e);
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERNOLL_FAIL_NO_NEW_REQUEST_POSTED",
+ e.getMessage()));
+ crsResp.setFailInfo(CRSPKIMessage.mFailInfo_internalCAError);
+ crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE);
+ }
+ return null;
+ }
+
+ ////// post the request
+
+ /*
+ needed:
+
+ token (authtoken)
+ certInfo
+ fingerprints x
+ req.transactionID
+ crsResp
+ */
+
+ private IRequest postRequest(HttpServletRequest httpReq, CRSPKIMessage req, CRSPKIMessage crsResp)
+ throws EBaseException {
+ X500Name subject = (X500Name) req.get(SUBJECTNAME);
+
+ if (mCreateEntry) {
+ if (subject == null) {
+ CMS.debug("CRSEnrollment::postRequest() - subject is null!");
+ return null;
+ }
+ createEntry(subject.toString());
+ }
+
+ // use profile framework to handle SCEP
+ if (mProfileId != null) {
+ PKCS10 pkcs10data = req.getP10();
+ String pkcs10blob = CMS.BtoA(pkcs10data.toByteArray());
+
+ // XXX authentication handling
+ CMS.debug("Found profile=" + mProfileId);
+ IProfile profile = mProfileSubsystem.getProfile(mProfileId);
+ if (profile == null) {
+ CMS.debug("profile " + mProfileId + " not found");
+ return null;
+ }
+ IProfileContext ctx = profile.createContext();
+
+ IProfileAuthenticator authenticator = null;
+ try {
+ CMS.debug("Retrieving authenticator");
+ authenticator = profile.getAuthenticator();
+ if (authenticator == null) {
+ CMS.debug("No authenticator Found");
+ } else {
+ CMS.debug("Got authenticator=" + authenticator.getClass().getName());
+ }
+ } catch (EProfileException e) {
+ // authenticator not installed correctly
+ }
+
+ IAuthToken authToken = null;
+
+ // for ssl authentication; pass in servlet for retrieving
+ // ssl client certificates
+ SessionContext context = SessionContext.getContext();
+
+ // insert profile context so that input parameter can be retrieved
+ context.put("profileContext", ctx);
+ context.put("sslClientCertProvider",
+ new SSLClientCertProvider(httpReq));
+
+ String p10Password = getPasswordFromP10(pkcs10data);
+ AuthCredentials credentials = new AuthCredentials();
+ credentials.set("UID", httpReq.getRemoteAddr());
+ credentials.set("PWD", p10Password);
+
+ if (authenticator == null) {
+ // XXX - to help caRouterCert to work, we need to
+ // add authentication to caRouterCert
+ authToken = new AuthToken(null);
+ } else {
+ authToken = authenticate(credentials, authenticator, httpReq);
+ }
+
+ IRequest reqs[] = null;
+ CMS.debug("CRSEnrollment: Creating profile requests");
+ ctx.set(IEnrollProfile.CTX_CERT_REQUEST_TYPE, "pkcs10");
+ ctx.set(IEnrollProfile.CTX_CERT_REQUEST, pkcs10blob);
+ Locale locale = Locale.getDefault();
+ reqs = profile.createRequests(ctx, locale);
+ if (reqs == null) {
+ CMS.debug("CRSEnrollment: No request has been created");
+ return null;
+ } else {
+ CMS.debug("CRSEnrollment: Request (" + reqs.length + ") have been created");
+ }
+ // set transaction id
+ reqs[0].setSourceId(req.getTransactionID());
+ reqs[0].setExtData("profile", "true");
+ reqs[0].setExtData("profileId", mProfileId);
+ reqs[0].setExtData(IEnrollProfile.CTX_CERT_REQUEST_TYPE, IEnrollProfile.REQ_TYPE_PKCS10);
+ reqs[0].setExtData(IEnrollProfile.CTX_CERT_REQUEST, pkcs10blob);
+ reqs[0].setExtData("requestor_name", "");
+ reqs[0].setExtData("requestor_email", "");
+ reqs[0].setExtData("requestor_phone", "");
+ reqs[0].setExtData("profileRemoteHost", httpReq.getRemoteHost());
+ reqs[0].setExtData("profileRemoteAddr", httpReq.getRemoteAddr());
+ reqs[0].setExtData("profileApprovedBy", profile.getApprovedBy());
+
+ CMS.debug("CRSEnrollment: Populating inputs");
+ profile.populateInput(ctx, reqs[0]);
+ CMS.debug("CRSEnrollment: Populating requests");
+ profile.populate(reqs[0]);
+
+ CMS.debug("CRSEnrollment: Submitting request");
+ profile.submit(authToken, reqs[0]);
+ CMS.debug("CRSEnrollment: Done submitting request");
+ profile.getRequestQueue().markAsServiced(reqs[0]);
+ CMS.debug("CRSEnrollment: Request marked as serviced");
+
+ return reqs[0];
+
+ }
+
+ IRequestQueue rq = ca.getRequestQueue();
+ IRequest pkiReq = rq.newRequest(IRequest.ENROLLMENT_REQUEST);
+
+ AuthToken token = (AuthToken) req.get(AUTH_TOKEN);
+ if (token != null) {
+ pkiReq.setExtData(IRequest.AUTH_TOKEN, token);
+ }
+
+ pkiReq.setExtData(IRequest.HTTP_PARAMS, IRequest.CERT_TYPE, IRequest.CEP_CERT);
+ X509CertInfo certInfo = (X509CertInfo) req.get(CERTINFO);
+ pkiReq.setExtData(IRequest.CERT_INFO, new X509CertInfo[] { certInfo });
+ pkiReq.setExtData("cepsubstore", mSubstoreName);
+
+ try {
+ String chpwd = (String) req.get(ChallengePassword.NAME);
+ if (chpwd != null) {
+ pkiReq.setExtData("challengePhrase",
+ chpwd);
+ }
+ } catch (Exception pwex) {
+ }
+
+ Hashtable<?, ?> fingerprints = (Hashtable<?, ?>) req.get(IRequest.FINGERPRINTS);
+ if (fingerprints.size() > 0) {
+ Hashtable<String, String> encodedPrints = new Hashtable<String, String>(fingerprints.size());
+ Enumeration<?> e = fingerprints.keys();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ byte[] value = (byte[]) fingerprints.get(key);
+ encodedPrints.put(key, CMS.BtoA(value));
+ }
+ pkiReq.setExtData(IRequest.FINGERPRINTS, encodedPrints);
+ }
+
+ pkiReq.setSourceId(req.getTransactionID());
+
+ rq.processRequest(pkiReq);
+
+ crsResp.setPKIStatus(CRSPKIMessage.mStatus_SUCCESS);
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.ENROLLMENTFORMAT,
+ new Object[] {
+ pkiReq.getRequestId(),
+ AuditFormat.FROMROUTER,
+ mAuthManagerName == null ? AuditFormat.NOAUTH : mAuthManagerName,
+ "pending",
+ subject,
+ "" }
+ );
+
+ return pkiReq;
+ }
+
+ public Hashtable<String, byte[]> makeFingerPrints(CRSPKIMessage req) {
+ Hashtable<String, byte[]> fingerprints = new Hashtable<String, byte[]>();
+
+ MessageDigest md;
+ String[] hashes = new String[] { "MD2", "MD5", "SHA1", "SHA256", "SHA512" };
+ PKCS10 p10 = req.getP10();
+
+ for (int i = 0; i < hashes.length; i++) {
+ try {
+ md = MessageDigest.getInstance(hashes[i]);
+ md.update(p10.getCertRequestInfo());
+ fingerprints.put(hashes[i], md.digest());
+ } catch (NoSuchAlgorithmException nsa) {
+ }
+ }
+
+ if (fingerprints != null) {
+ req.put(IRequest.FINGERPRINTS, fingerprints);
+ }
+ return fingerprints;
+ }
+
+ // Take a look to see if the request was successful, and fill
+ // in the response message
+
+ private X509CertImpl makeResponseFromRequest(CRSPKIMessage crsReq, CRSPKIMessage crsResp,
+ IRequest pkiReq) {
+
+ X509CertImpl issuedCert = null;
+
+ RequestStatus status = pkiReq.getRequestStatus();
+
+ String profileId = pkiReq.getExtDataInString("profileId");
+ if (profileId != null) {
+ CMS.debug("CRSEnrollment: Found profile request");
+ X509CertImpl cert =
+ pkiReq.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
+ if (cert == null) {
+ CMS.debug("CRSEnrollment: No certificate has been found");
+ } else {
+ CMS.debug("CRSEnrollment: Found certificate");
+ }
+ crsResp.setPKIStatus(CRSPKIMessage.mStatus_SUCCESS);
+ return cert;
+ }
+
+ if (status.equals(RequestStatus.COMPLETE)) {
+ Integer success = pkiReq.getExtDataInInteger(IRequest.RESULT);
+
+ if (success.equals(IRequest.RES_SUCCESS)) {
+ // The cert was issued, lets send it back to the router
+ X509CertImpl[] issuedCertBuf =
+ pkiReq.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+ if (issuedCertBuf == null || issuedCertBuf.length == 0) {
+ // writeError("Internal Error: Bad operation",httpReq,httpResp);
+ CMS.debug("CRSEnrollment::makeResponseFromRequest() - " +
+ "Bad operation");
+ return null;
+ }
+ issuedCert = issuedCertBuf[0];
+ crsResp.setPKIStatus(CRSPKIMessage.mStatus_SUCCESS);
+
+ } else { // status is not 'success' - there must've been a problem
+
+ crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE);
+ crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badAlg);
+ }
+ } else if (status == RequestStatus.REJECTED ||
+ status == RequestStatus.CANCELED) {
+ crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE);
+ crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badRequest);
+ } else { // not complete
+ crsResp.setPKIStatus(CRSPKIMessage.mStatus_PENDING);
+ }
+
+ return issuedCert;
+ }
+
+ protected String hashPassword(String pwd) {
+ String salt = "lala123";
+ byte[] pwdDigest = mSHADigest.digest((salt + pwd).getBytes());
+ String b64E = Utils.base64encode(pwdDigest);
+ return "{SHA}" + b64E;
+ }
+
+ /**
+ * Make the CRSPKIMESSAGE response
+ */
+
+ private void processCertRep(CryptoContext cx,
+ X509CertImpl issuedCert,
+ CRSPKIMessage crsResp,
+ CRSPKIMessage crsReq)
+ throws CRSFailureException {
+ byte[] msgdigest = null;
+ byte[] encryptedDesKey = null;
+
+ try {
+ if (issuedCert != null) {
+
+ SymmetricKey sk;
+ SymmetricKey skinternal;
+
+ KeyGenAlgorithm kga = KeyGenAlgorithm.DES;
+ EncryptionAlgorithm ea = EncryptionAlgorithm.DES_CBC;
+ if (mEncryptionAlgorithm != null && mEncryptionAlgorithm.equals("DES3")) {
+ kga = KeyGenAlgorithm.DES3;
+ ea = EncryptionAlgorithm.DES3_CBC;
+ }
+
+ // 1. Make the Degenerated PKCS7 with the recipient's certificate in it
+
+ byte toBeEncrypted[] =
+ crsResp.makeSignedRep(1, // version
+ issuedCert.getEncoded()
+ );
+
+ // 2. Encrypt the above byte array with a new random DES key
+
+ sk = cx.getDESKeyGenerator().generate();
+
+ skinternal = cx.getInternalToken().getKeyGenerator(kga).clone(sk);
+
+ byte[] padded = Cipher.pad(toBeEncrypted, ea.getBlockSize());
+
+ // This should be changed to generate proper DES IV.
+
+ Cipher cipher = cx.getInternalToken().getCipherContext(ea);
+ IVParameterSpec desIV =
+ new IVParameterSpec(new byte[] {
+ (byte) 0xff, (byte) 0x00,
+ (byte) 0xff, (byte) 0x00,
+ (byte) 0xff, (byte) 0x00,
+ (byte) 0xff, (byte) 0x00 });
+
+ cipher.initEncrypt(sk, desIV);
+ byte[] encryptedData = cipher.doFinal(padded);
+
+ crsResp.makeEncryptedContentInfo(desIV.getIV(), encryptedData, mEncryptionAlgorithm);
+
+ // 3. Extract the recipient's public key
+
+ PublicKey rcpPK = crsReq.getSignerPublicKey();
+
+ // 4. Encrypt the DES key with the public key
+
+ // we have to move the key onto the interal token.
+ //skinternal = cx.getInternalKeyStorageToken().cloneKey(sk);
+ skinternal = cx.getInternalToken().cloneKey(sk);
+
+ KeyWrapper kw = cx.getInternalKeyWrapper();
+ kw.initWrap(rcpPK, null);
+ encryptedDesKey = kw.wrap(skinternal);
+
+ crsResp.setRcpIssuerAndSerialNumber(crsReq.getSgnIssuerAndSerialNumber());
+ crsResp.makeRecipientInfo(0, encryptedDesKey);
+
+ }
+
+ byte[] ed = crsResp.makeEnvelopedData(0);
+
+ // 7. Make Digest of SignedData Content
+ MessageDigest md = MessageDigest.getInstance(mHashAlgorithm);
+ msgdigest = md.digest(ed);
+
+ crsResp.setMsgDigest(msgdigest);
+
+ }
+
+ catch (Exception e) {
+ throw new CRSFailureException("Failed to create inner response to CEP message: " + e.getMessage());
+ }
+
+ // 5. Make a RecipientInfo
+
+ // The issuer name & serial number here, should be that of
+ // the EE's self-signed Certificate
+ // [I can get it from the req blob, but later, I should
+ // store the recipient's self-signed certificate with the request
+ // so I can get at it later. I need to do this to support
+ // 'PENDING']
+
+ try {
+
+ // 8. Make Authenticated Attributes
+ // we can just pull the transaction ID out of the request.
+ // Later, we will have to put it out of the Request queue,
+ // so we can support PENDING
+ crsResp.setTransactionID(crsReq.getTransactionID());
+ // recipientNonce and SenderNonce have already been set
+
+ crsResp.makeAuthenticatedAttributes();
+ // crsResp.makeAuthenticatedAttributes_old();
+
+ // now package up the rest of the SignerInfo
+ {
+ byte[] signingcertbytes = cx.getSigningCert().getEncoded();
+
+ Certificate.Template sgncert_t = new Certificate.Template();
+ Certificate sgncert =
+ (Certificate) sgncert_t.decode(new ByteArrayInputStream(signingcertbytes));
+
+ IssuerAndSerialNumber sgniasn =
+ new IssuerAndSerialNumber(sgncert.getInfo().getIssuer(),
+ sgncert.getInfo().getSerialNumber());
+
+ crsResp.setSgnIssuerAndSerialNumber(sgniasn);
+
+ // 10. Make SignerInfo
+ crsResp.makeSignerInfo(1, cx.getPrivateKey(), mHashAlgorithm);
+
+ // 11. Make SignedData
+ crsResp.makeSignedData(1, signingcertbytes, mHashAlgorithm);
+
+ crsResp.debug();
+ }
+ } catch (Exception e) {
+ throw new CRSFailureException("Failed to create outer response to CEP request: " + e.getMessage());
+ }
+
+ // if debugging, dump out the response into a file
+
+ }
+
+ class CryptoContext {
+ private CryptoManager cm;
+ private CryptoToken internalToken;
+ private CryptoToken keyStorageToken;
+ private CryptoToken internalKeyStorageToken;
+ private KeyGenerator DESkg;
+ private Enumeration<?> externalTokens = null;
+ private org.mozilla.jss.crypto.X509Certificate signingCert;
+ private org.mozilla.jss.crypto.PrivateKey signingCertPrivKey;
+
+ @SuppressWarnings("unused")
+ private int signingCertKeySize;
+
+ class CryptoContextException extends Exception {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1124116326126256475L;
+
+ public CryptoContextException() {
+ super();
+ }
+
+ public CryptoContextException(String s) {
+ super(s);
+ }
+ }
+
+ public CryptoContext()
+ throws CryptoContextException {
+ try {
+ KeyGenAlgorithm kga = KeyGenAlgorithm.DES;
+ if (mEncryptionAlgorithm != null && mEncryptionAlgorithm.equals("DES3")) {
+ kga = KeyGenAlgorithm.DES3;
+ }
+ cm = CryptoManager.getInstance();
+ internalToken = cm.getInternalCryptoToken();
+ DESkg = internalToken.getKeyGenerator(kga);
+ if (mTokenName.equalsIgnoreCase(Constants.PR_INTERNAL_TOKEN) ||
+ mTokenName.equalsIgnoreCase("Internal Key Storage Token") ||
+ mTokenName.length() == 0) {
+ keyStorageToken = cm.getInternalKeyStorageToken();
+ internalKeyStorageToken = keyStorageToken;
+ CMS.debug("CRSEnrollment: CryptoContext: internal token name: '" + mTokenName + "'");
+ } else {
+ keyStorageToken = cm.getTokenByName(mTokenName);
+ internalKeyStorageToken = null;
+ }
+ if (!mUseCA && internalKeyStorageToken == null) {
+ PasswordCallback cb = CMS.getPasswordCallback();
+ keyStorageToken.login(cb); // ONE_TIME by default.
+ }
+ signingCert = cm.findCertByNickname(mNickname);
+ signingCertPrivKey = cm.findPrivKeyByCert(signingCert);
+ byte[] encPubKeyInfo = signingCert.getPublicKey().getEncoded();
+ SEQUENCE.Template outer = SEQUENCE.getTemplate();
+ outer.addElement(ANY.getTemplate()); // algid
+ outer.addElement(BIT_STRING.getTemplate());
+ SEQUENCE outerSeq = (SEQUENCE) ASN1Util.decode(outer, encPubKeyInfo);
+ BIT_STRING bs = (BIT_STRING) outerSeq.elementAt(1);
+ byte[] encPubKey = bs.getBits();
+ if (bs.getPadCount() != 0) {
+ throw new CryptoContextException(
+ "Internal error: Invalid Public key. Not an integral number of bytes.");
+ }
+ SEQUENCE.Template inner = new SEQUENCE.Template();
+ inner.addElement(INTEGER.getTemplate());
+ inner.addElement(INTEGER.getTemplate());
+ SEQUENCE pubKeySeq = (SEQUENCE) ASN1Util.decode(inner, encPubKey);
+ INTEGER modulus = (INTEGER) pubKeySeq.elementAt(0);
+ signingCertKeySize = modulus.bitLength();
+
+ try {
+ FileOutputStream fos = new FileOutputStream("pubkey.der");
+ fos.write(signingCert.getPublicKey().getEncoded());
+ fos.close();
+ } catch (Exception e) {
+ }
+
+ } catch (InvalidBERException e) {
+ throw new CryptoContextException(
+ "Internal Error: Bad internal Certificate Representation. Not a valid RSA-signed certificate");
+ } catch (CryptoManager.NotInitializedException e) {
+ throw new CryptoContextException("Crypto Manager not initialized");
+ } catch (NoSuchAlgorithmException e) {
+ throw new CryptoContextException("Cannot create DES key generator");
+ } catch (ObjectNotFoundException e) {
+ throw new CryptoContextException("Certificate not found: " + ca.getNickname());
+ } catch (TokenException e) {
+ throw new CryptoContextException("Problem with Crypto Token: " + e.getMessage());
+ } catch (NoSuchTokenException e) {
+ throw new CryptoContextException("Crypto Token not found: " + e.getMessage());
+ } catch (IncorrectPasswordException e) {
+ throw new CryptoContextException("Incorrect Password.");
+ }
+ }
+
+ public KeyGenerator getDESKeyGenerator() {
+ return DESkg;
+ }
+
+ public CryptoToken getInternalToken() {
+ return internalToken;
+ }
+
+ public void setExternalTokens(Enumeration<?> tokens) {
+ externalTokens = tokens;
+ }
+
+ public Enumeration<?> getExternalTokens() {
+ return externalTokens;
+ }
+
+ public CryptoToken getInternalKeyStorageToken() {
+ return internalKeyStorageToken;
+ }
+
+ public CryptoToken getKeyStorageToken() {
+ return keyStorageToken;
+ }
+
+ public CryptoManager getCryptoManager() {
+ return cm;
+ }
+
+ public KeyWrapper getKeyWrapper()
+ throws CryptoContextException {
+ try {
+ return signingCertPrivKey.getOwningToken().getKeyWrapper(KeyWrapAlgorithm.RSA);
+ } catch (TokenException e) {
+ throw new CryptoContextException("Problem with Crypto Token: " + e.getMessage());
+ } catch (NoSuchAlgorithmException e) {
+ throw new CryptoContextException(e.getMessage());
+ }
+ }
+
+ public KeyWrapper getInternalKeyWrapper()
+ throws CryptoContextException {
+ try {
+ return getInternalToken().getKeyWrapper(KeyWrapAlgorithm.RSA);
+ } catch (TokenException e) {
+ throw new CryptoContextException("Problem with Crypto Token: " + e.getMessage());
+ } catch (NoSuchAlgorithmException e) {
+ throw new CryptoContextException(e.getMessage());
+ }
+ }
+
+ public org.mozilla.jss.crypto.PrivateKey getPrivateKey() {
+ return signingCertPrivKey;
+ }
+
+ public org.mozilla.jss.crypto.X509Certificate getSigningCert() {
+ return signingCert;
+ }
+
+ }
+
+ /* General failure. The request/response cannot be processed. */
+
+ class CRSFailureException extends Exception {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1962741611501549051L;
+
+ public CRSFailureException() {
+ super();
+ }
+
+ public CRSFailureException(String s) {
+ super(s);
+ }
+ }
+
+ class CRSInvalidSignatureException extends Exception {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 9096408193567657944L;
+
+ public CRSInvalidSignatureException() {
+ super();
+ }
+
+ public CRSInvalidSignatureException(String s) {
+ super(s);
+ }
+ }
+
+ class CRSPolicyException extends Exception {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5846593800658787396L;
+
+ public CRSPolicyException() {
+ super();
+ }
+
+ public CRSPolicyException(String s) {
+ super(s);
+ }
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/scep/ChallengePassword.java b/base/server/cms/src/com/netscape/cms/servlet/cert/scep/ChallengePassword.java
new file mode 100644
index 000000000..5c7ac856f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/scep/ChallengePassword.java
@@ -0,0 +1,141 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert.scep;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.cert.CertificateException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.security.util.DerValue;
+import netscape.security.x509.CertAttrSet;
+
+/**
+ * Class for handling the decoding of a SCEP Challenge Password
+ * object. Currently this class cannot be used for encoding
+ * thus some fo the methods are unimplemented
+ */
+public class ChallengePassword implements CertAttrSet {
+
+ public static final String NAME = "ChallengePassword";
+ public static final String PASSWORD = "password";
+
+ private String cpw;
+
+ /**
+ * Get the password marshalled in this object
+ *
+ * @return the challenge password
+ */
+ public String toString() {
+ return cpw;
+ }
+
+ /**
+ * Create a ChallengePassword object
+ *
+ * @param stuff (must be of type byte[]) a DER-encoded by array following
+ * The ASN.1 template for ChallenegePassword specified in the SCEP
+ * documentation
+ * @throws IOException if the DER encoded byt array was malformed, or if it
+ * did not match the template
+ */
+
+ public ChallengePassword(Object stuff)
+ throws IOException {
+
+ ByteArrayInputStream is = new ByteArrayInputStream((byte[]) stuff);
+ try {
+ decode(is);
+ } catch (Exception e) {
+ throw new IOException(e.getMessage());
+ }
+
+ }
+
+ /**
+ * Currently Unimplemented
+ */
+ public void encode(OutputStream out)
+ throws CertificateException, IOException {
+ }
+
+ public void decode(InputStream in)
+ throws CertificateException, IOException {
+ DerValue derVal = new DerValue(in);
+
+ construct(derVal);
+
+ }
+
+ private void construct(DerValue derVal) throws IOException {
+ try {
+ cpw = derVal.getPrintableString();
+ } catch (NullPointerException e) {
+ cpw = "";
+ }
+ }
+
+ /**
+ * Currently Unimplemented
+ */
+ public void set(String name, Object obj)
+ throws CertificateException, IOException {
+ }
+
+ /**
+ * Get an attribute of this object.
+ *
+ * @param name the name of the attribute of this object to get. The only
+ * supported attribute is "password"
+ */
+ public Object get(String name)
+ throws CertificateException, IOException {
+ if (name.equalsIgnoreCase(PASSWORD)) {
+ return cpw;
+ } else {
+ throw new IOException("Attribute name not recognized by " +
+ "CertAttrSet: ChallengePassword");
+ }
+ }
+
+ /**
+ * Currently Unimplemented
+ */
+ public void delete(String name)
+ throws CertificateException, IOException {
+ }
+
+ /**
+ * @return an empty set of elements
+ */
+ public Enumeration<String> getAttributeNames() {
+ return (new Vector<String>()).elements();
+ }
+
+ /**
+ * @return the String "ChallengePassword"
+ */
+ public String getName() {
+ return NAME;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/scep/ExtensionsRequested.java b/base/server/cms/src/com/netscape/cms/servlet/cert/scep/ExtensionsRequested.java
new file mode 100644
index 000000000..3cb88f3f8
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/scep/ExtensionsRequested.java
@@ -0,0 +1,176 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.cert.scep;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.cert.CertificateException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.security.util.DerInputStream;
+import netscape.security.util.DerValue;
+import netscape.security.x509.CertAttrSet;
+import netscape.security.x509.Extension;
+
+public class ExtensionsRequested implements CertAttrSet {
+
+ public static final String NAME = "EXTENSIONS_REQUESTED";
+
+ public static final String KUE_DIGITAL_SIGNATURE = "kue_digital_signature";
+ public static final String KUE_KEY_ENCIPHERMENT = "kue_key_encipherment";
+
+ private String kue_digital_signature = "false";
+ private String kue_key_encipherment = "false";
+
+ private Vector<Extension> exts = new Vector<Extension>();
+
+ public ExtensionsRequested(Object stuff) throws IOException {
+ ByteArrayInputStream is = new ByteArrayInputStream((byte[]) stuff);
+
+ try {
+ decode(is);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ public void encode(OutputStream out)
+ throws CertificateException, IOException {
+ }
+
+ public void decode(InputStream in)
+ throws CertificateException, IOException {
+ DerValue derVal = new DerValue(in);
+
+ construct(derVal);
+ }
+
+ public void set(String name, Object obj)
+ throws CertificateException, IOException {
+ }
+
+ public Object get(String name)
+ throws CertificateException, IOException {
+ if (name.equalsIgnoreCase(KUE_DIGITAL_SIGNATURE)) {
+ return kue_digital_signature;
+ }
+ if (name.equalsIgnoreCase(KUE_KEY_ENCIPHERMENT)) {
+ return kue_key_encipherment;
+ }
+
+ throw new IOException("Unsupported attribute queried");
+ }
+
+ public void delete(String name)
+ throws CertificateException, IOException {
+ }
+
+ public Enumeration<String> getAttributeNames() {
+ return (new Vector<String>()).elements();
+ }
+
+ public String getName() {
+ return NAME;
+ }
+
+ /**
+ * construct - expects this in the inputstream (from the router):
+ *
+ * 211 30 31: SEQUENCE {
+ * 213 06 10: OBJECT IDENTIFIER '2 16 840 1 113733 1 9 8'
+ * 225 31 17: SET {
+ * 227 04 15: OCTET STRING, encapsulates {
+ * 229 30 13: SEQUENCE {
+ * 231 30 11: SEQUENCE {
+ * 233 06 3: OBJECT IDENTIFIER keyUsage (2 5 29 15)
+ * 238 04 4: OCTET STRING
+ * : 03 02 05 A0
+ * : }
+ * : }
+ * : }
+ *
+ * or this (from IRE client):
+ *
+ * 262 30 51: SEQUENCE {
+ * 264 06 9: OBJECT IDENTIFIER extensionReq (1 2 840 113549 1 9 14)
+ * 275 31 38: SET {
+ * 277 30 36: SEQUENCE {
+ * 279 30 34: SEQUENCE {
+ * 281 06 3: OBJECT IDENTIFIER subjectAltName (2 5 29 17)
+ * 286 04 27: OCTET STRING
+ * : 30 19 87 04 D0 0C 3E 6F 81 03 61 61 61 82 0C 61
+ * : 61 61 2E 6D 63 6F 6D 2E 63 6F 6D
+ * : }
+ * : }
+ * : }
+ * : }
+ */
+ private void construct(DerValue dv) throws IOException {
+
+ DerInputStream stream = null;
+
+ try { // try decoding as sequence first
+
+ stream = dv.toDerInputStream();
+
+ stream.getDerValue(); // consume stream
+ stream.reset();
+
+ stream.getSequence(2); // consume stream
+ } catch (IOException ioe) {
+ // if it failed, the outer sequence may be
+ // encapsulated in an octet string, as in the first
+ // example above
+
+ byte[] octet_string = dv.getOctetString();
+
+ // Make a new input stream from the byte array,
+ // and re-parse it as a sequence.
+
+ dv = new DerValue(octet_string);
+
+ stream = dv.toDerInputStream();
+ stream.getSequence(2); // consume stream
+ }
+
+ // now, the stream will be in the correct format
+ stream.reset();
+
+ while (true) {
+ DerValue ext_dv = null;
+ try {
+ ext_dv = stream.getDerValue();
+ } catch (IOException ex) {
+ break;
+ }
+
+ Extension ext = new Extension(ext_dv);
+ exts.addElement(ext);
+ }
+
+ }
+
+ public Vector<Extension> getExtensions() {
+ return exts;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/AuthCredentials.java b/base/server/cms/src/com/netscape/cms/servlet/common/AuthCredentials.java
new file mode 100644
index 000000000..32ae0fcc8
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/AuthCredentials.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.base.IArgBlock;
+
+/**
+ * Authentication Credentials as input to the authMgr
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class AuthCredentials implements IAuthCredentials {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5995164231849154265L;
+ private Hashtable<String, Object> authCreds = null;
+ // Inserted by bskim
+ private IArgBlock argblk = null;
+
+ // Insert end
+
+ public AuthCredentials() {
+ authCreds = new Hashtable<String, Object>();
+ }
+
+ /**
+ * sets a credential with credential name and the credential
+ *
+ * @param name credential name
+ * @param cred credential
+ * @exception com.netscape.certsrv.base.EBaseException NullPointerException
+ */
+ public void set(String name, Object cred) throws EAuthException {
+ if (cred == null) {
+ throw new EAuthException("AuthCredentials.set()");
+ }
+
+ authCreds.put(name, cred);
+ }
+
+ /**
+ * returns the credential to which the specified name is mapped in this
+ * credential set
+ *
+ * @param name credential name
+ * @return the named authentication credential
+ */
+ public Object get(String name) {
+ return authCreds.get(name);
+ }
+
+ /**
+ * removes the name and its corresponding credential from this
+ * credential set. This method does nothing if the named
+ * credential is not in the credential set.
+ *
+ * @param name credential name
+ */
+ public void delete(String name) {
+ authCreds.remove(name);
+ }
+
+ /**
+ * returns an enumeration of the credential names in this credential
+ * set. Use the Enumeration methods on the returned object to
+ * fetch the elements sequentially.
+ *
+ * @return an enumeration of the names in this credential set
+ * @see java.util.Enumeration
+ */
+ public Enumeration<String> getElements() {
+ return authCreds.keys();
+ }
+
+ // Inserted by bskim
+ public void setArgBlock(IArgBlock blk) {
+ argblk = blk;
+ return;
+ }
+
+ // Insert end
+
+ public IArgBlock getArgBlock() {
+ return argblk;
+ }
+ // Insert end
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java
new file mode 100644
index 000000000..f1320f44a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java
@@ -0,0 +1,1106 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.util.Date;
+import java.util.Hashtable;
+
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.InvalidityDateExtension;
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509Key;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.asn1.ANY;
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.ENUMERATED;
+import org.mozilla.jss.asn1.GeneralizedTime;
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
+import org.mozilla.jss.asn1.OCTET_STRING;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.asn1.SET;
+import org.mozilla.jss.asn1.UTF8String;
+import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.crypto.SignatureAlgorithm;
+import org.mozilla.jss.pkcs11.PK11PubKey;
+import org.mozilla.jss.pkix.cert.Certificate;
+import org.mozilla.jss.pkix.cmc.CMCCertId;
+import org.mozilla.jss.pkix.cmc.CMCStatusInfo;
+import org.mozilla.jss.pkix.cmc.GetCert;
+import org.mozilla.jss.pkix.cmc.OtherInfo;
+import org.mozilla.jss.pkix.cmc.OtherMsg;
+import org.mozilla.jss.pkix.cmc.PendInfo;
+import org.mozilla.jss.pkix.cmc.ResponseBody;
+import org.mozilla.jss.pkix.cmc.TaggedAttribute;
+import org.mozilla.jss.pkix.cmmf.RevRequest;
+import org.mozilla.jss.pkix.cms.ContentInfo;
+import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo;
+import org.mozilla.jss.pkix.cms.IssuerAndSerialNumber;
+import org.mozilla.jss.pkix.cms.SignedData;
+import org.mozilla.jss.pkix.cms.SignerIdentifier;
+import org.mozilla.jss.pkix.cms.SignerInfo;
+import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier;
+import org.mozilla.jss.pkix.primitive.Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.ISharedToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+
+/**
+ * Utility CMCOutputTemplate
+ *
+ * @version $ $, $Date$
+ */
+public class CMCOutputTemplate {
+ public CMCOutputTemplate() {
+ }
+
+ public void createFullResponseWithFailedStatus(HttpServletResponse resp,
+ SEQUENCE bpids, int code, UTF8String s) {
+ SEQUENCE controlSeq = new SEQUENCE();
+ SEQUENCE cmsSeq = new SEQUENCE();
+ SEQUENCE otherMsgSeq = new SEQUENCE();
+
+ int bpid = 1;
+ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL,
+ new INTEGER(code), null);
+ CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(
+ new INTEGER(CMCStatusInfo.FAILED),
+ bpids, s, otherInfo);
+ TaggedAttribute tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+
+ try {
+ ResponseBody respBody = new ResponseBody(controlSeq,
+ cmsSeq, otherMsgSeq);
+
+ SET certs = new SET();
+ ContentInfo contentInfo = getContentInfo(respBody, certs);
+ if (contentInfo == null)
+ return;
+ ByteArrayOutputStream fos = new ByteArrayOutputStream();
+ contentInfo.encode(fos);
+ fos.close();
+ byte[] contentBytes = fos.toByteArray();
+
+ resp.setContentType("application/pkcs7-mime");
+ resp.setContentLength(contentBytes.length);
+ OutputStream os = resp.getOutputStream();
+ os.write(contentBytes);
+ os.flush();
+ } catch (Exception e) {
+ CMS.debug("CMCOutputTemplate createFullResponseWithFailedStatus Exception: " + e.toString());
+ return;
+ }
+ }
+
+ public void createFullResponse(HttpServletResponse resp, IRequest[] reqs,
+ String cert_request_type, int[] error_codes) {
+
+ SEQUENCE controlSeq = new SEQUENCE();
+ SEQUENCE cmsSeq = new SEQUENCE();
+ SEQUENCE otherMsgSeq = new SEQUENCE();
+ SessionContext context = SessionContext.getContext();
+
+ // set status info control for simple enrollment request
+ // in rfc 2797: body list value is 1
+ int bpid = 1;
+ SEQUENCE pending_bpids = null;
+ SEQUENCE success_bpids = null;
+ SEQUENCE failed_bpids = null;
+ if (cert_request_type.equals("crmf") ||
+ cert_request_type.equals("pkcs10")) {
+ String reqId = reqs[0].getRequestId().toString();
+ OtherInfo otherInfo = null;
+ if (error_codes[0] == 2) {
+ PendInfo pendInfo = new PendInfo(reqId, new Date());
+ otherInfo = new OtherInfo(OtherInfo.PEND, null,
+ pendInfo);
+ } else {
+ otherInfo = new OtherInfo(OtherInfo.FAIL,
+ new INTEGER(OtherInfo.BAD_REQUEST), null);
+ }
+
+ SEQUENCE bpids = new SEQUENCE();
+ bpids.addElement(new INTEGER(1));
+ CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.PENDING,
+ bpids, (String) null, otherInfo);
+ TaggedAttribute tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ } else if (cert_request_type.equals("cmc")) {
+ pending_bpids = new SEQUENCE();
+ success_bpids = new SEQUENCE();
+ failed_bpids = new SEQUENCE();
+ if (reqs != null) {
+ for (int i = 0; i < reqs.length; i++) {
+ if (error_codes[i] == 0) {
+ success_bpids.addElement(new INTEGER(
+ reqs[i].getExtDataInBigInteger("bodyPartId")));
+ } else if (error_codes[i] == 2) {
+ pending_bpids.addElement(new INTEGER(
+ reqs[i].getExtDataInBigInteger("bodyPartId")));
+ } else {
+ failed_bpids.addElement(new INTEGER(
+ reqs[i].getExtDataInBigInteger("bodyPartId")));
+ }
+ }
+ }
+
+ TaggedAttribute tagattr = null;
+ CMCStatusInfo cmcStatusInfo = null;
+ SEQUENCE identityBpids = (SEQUENCE) context.get("identityProof");
+ if (identityBpids != null && identityBpids.size() > 0) {
+ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL,
+ new INTEGER(OtherInfo.BAD_IDENTITY), null);
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED,
+ identityBpids, (String) null, otherInfo);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ }
+
+ SEQUENCE POPLinkWitnessBpids = (SEQUENCE) context.get("POPLinkWitness");
+ if (POPLinkWitnessBpids != null && POPLinkWitnessBpids.size() > 0) {
+ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL,
+ new INTEGER(OtherInfo.BAD_REQUEST), null);
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED,
+ POPLinkWitnessBpids, (String) null, otherInfo);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ }
+
+ if (pending_bpids.size() > 0) {
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.PENDING,
+ pending_bpids, (String) null, null);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ }
+
+ if (success_bpids.size() > 0) {
+ boolean confirmRequired = false;
+ try {
+ confirmRequired =
+ CMS.getConfigStore().getBoolean("cmc.cert.confirmRequired",
+ false);
+ } catch (Exception e) {
+ }
+ if (confirmRequired) {
+ CMS.debug("CMCOutputTemplate: confirmRequired in the request");
+ cmcStatusInfo =
+ new CMCStatusInfo(CMCStatusInfo.CONFIRM_REQUIRED,
+ success_bpids, (String) null, null);
+ } else {
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS,
+ success_bpids, (String) null, null);
+ }
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ }
+
+ if (failed_bpids.size() > 0) {
+ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL,
+ new INTEGER(OtherInfo.BAD_REQUEST), null);
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED,
+ failed_bpids, (String) null, otherInfo);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ }
+ }
+
+ SET certs = new SET();
+
+ try {
+ // deal with controls
+ Integer nums = (Integer) (context.get("numOfControls"));
+ if (nums != null && nums.intValue() > 0) {
+ TaggedAttribute attr =
+ (TaggedAttribute) (context.get(OBJECT_IDENTIFIER.id_cmc_getCert));
+ if (attr != null) {
+ try {
+ processGetCertControl(attr, certs);
+ } catch (EBaseException ee) {
+ CMS.debug("CMCOutputTemplate: " + ee.toString());
+ OtherInfo otherInfo1 = new OtherInfo(OtherInfo.FAIL,
+ new INTEGER(OtherInfo.BAD_CERT_ID), null);
+ SEQUENCE bpids1 = new SEQUENCE();
+ bpids1.addElement(attr.getBodyPartID());
+ CMCStatusInfo cmcStatusInfo1 = new CMCStatusInfo(
+ new INTEGER(CMCStatusInfo.FAILED),
+ bpids1, null, otherInfo1);
+ TaggedAttribute tagattr1 = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo1);
+ controlSeq.addElement(tagattr1);
+ }
+ }
+
+ attr =
+ (TaggedAttribute) (context.get(OBJECT_IDENTIFIER.id_cmc_dataReturn));
+ if (attr != null)
+ bpid = processDataReturnControl(attr, controlSeq, bpid);
+
+ attr =
+ (TaggedAttribute) context.get(OBJECT_IDENTIFIER.id_cmc_transactionId);
+ if (attr != null)
+ bpid = processTransactionControl(attr, controlSeq, bpid);
+
+ attr =
+ (TaggedAttribute) context.get(OBJECT_IDENTIFIER.id_cmc_senderNonce);
+ if (attr != null)
+ bpid = processSenderNonceControl(attr, controlSeq, bpid);
+
+ attr =
+ (TaggedAttribute) context.get(OBJECT_IDENTIFIER.id_cmc_QueryPending);
+ if (attr != null)
+ bpid = processQueryPendingControl(attr, controlSeq, bpid);
+
+ attr =
+ (TaggedAttribute) context.get(OBJECT_IDENTIFIER.id_cmc_idConfirmCertAcceptance);
+
+ if (attr != null)
+ bpid = processConfirmCertAcceptanceControl(attr, controlSeq,
+ bpid);
+
+ attr =
+ (TaggedAttribute) context.get(OBJECT_IDENTIFIER.id_cmc_revokeRequest);
+
+ if (attr != null)
+ bpid = processRevokeRequestControl(attr, controlSeq,
+ bpid);
+ }
+
+ if (success_bpids != null && success_bpids.size() > 0) {
+ for (int i = 0; i < reqs.length; i++) {
+ if (error_codes[i] == 0) {
+ X509CertImpl impl =
+ (reqs[i].getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT));
+ byte[] bin = impl.getEncoded();
+ Certificate.Template certTemplate = new Certificate.Template();
+ Certificate cert = (Certificate) certTemplate.decode(
+ new ByteArrayInputStream(bin));
+ certs.addElement(cert);
+ }
+ }
+ }
+
+ ResponseBody respBody = new ResponseBody(controlSeq,
+ cmsSeq, otherMsgSeq);
+
+ ContentInfo contentInfo = getContentInfo(respBody, certs);
+ ByteArrayOutputStream fos = new ByteArrayOutputStream();
+ contentInfo.encode(fos);
+ fos.close();
+ byte[] contentBytes = fos.toByteArray();
+
+ resp.setContentType("application/pkcs7-mime");
+ resp.setContentLength(contentBytes.length);
+ OutputStream os = resp.getOutputStream();
+ os.write(contentBytes);
+ os.flush();
+ } catch (java.security.cert.CertificateEncodingException e) {
+ CMS.debug("CMCOutputTemplate exception: " + e.toString());
+ } catch (InvalidBERException e) {
+ CMS.debug("CMCOutputTemplate exception: " + e.toString());
+ } catch (IOException e) {
+ CMS.debug("CMCOutputTemplate exception: " + e.toString());
+ } catch (Exception e) {
+ CMS.debug("Exception: " + e.toString());
+ }
+ }
+
+ private ContentInfo getContentInfo(ResponseBody respBody, SET certs) {
+ try {
+ ICertificateAuthority ca = null;
+ // add CA cert chain
+ ca = (ICertificateAuthority) CMS.getSubsystem("ca");
+ CertificateChain certchains = ca.getCACertChain();
+ java.security.cert.X509Certificate[] chains = certchains.getChain();
+
+ for (int i = 0; i < chains.length; i++) {
+ Certificate.Template certTemplate = new Certificate.Template();
+ Certificate cert = (Certificate) certTemplate.decode(
+ new ByteArrayInputStream(chains[i].getEncoded()));
+ certs.addElement(cert);
+ }
+
+ EncapsulatedContentInfo enContentInfo = new EncapsulatedContentInfo(
+ OBJECT_IDENTIFIER.id_cct_PKIResponse, respBody);
+ org.mozilla.jss.crypto.X509Certificate x509CAcert = null;
+ x509CAcert = ca.getCaX509Cert();
+ X509CertImpl caimpl = new X509CertImpl(x509CAcert.getEncoded());
+ X500Name issuerName = (X500Name) caimpl.getIssuerDN();
+ byte[] issuerByte = issuerName.getEncoded();
+ ByteArrayInputStream istream = new ByteArrayInputStream(issuerByte);
+ Name issuer = (Name) Name.getTemplate().decode(istream);
+ IssuerAndSerialNumber ias = new IssuerAndSerialNumber(
+ issuer, new INTEGER(x509CAcert.getSerialNumber().toString()));
+ SignerIdentifier si = new SignerIdentifier(
+ SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null);
+ // use CA instance's default signature and digest algorithm
+ SignatureAlgorithm signAlg = ca.getDefaultSignatureAlgorithm();
+ org.mozilla.jss.crypto.PrivateKey privKey =
+ CryptoManager.getInstance().findPrivKeyByCert(x509CAcert);
+ /*
+ org.mozilla.jss.crypto.PrivateKey.Type keyType = privKey.getType();
+ if( keyType.equals( org.mozilla.jss.crypto.PrivateKey.RSA ) ) {
+ signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest;
+ } else if( keyType.equals( org.mozilla.jss.crypto.PrivateKey.DSA ) ) {
+ signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest;
+ } else if( keyType.equals( org.mozilla.jss.crypto.PrivateKey.EC ) ) {
+ signAlg = SignatureAlgorithm.ECSignatureWithSHA1Digest;
+ } else {
+ CMS.debug( "CMCOutputTemplate::getContentInfo() - "
+ + "signAlg is unsupported!" );
+ return null;
+ }
+ */
+ DigestAlgorithm digestAlg = signAlg.getDigestAlg();
+ MessageDigest msgDigest = null;
+ byte[] digest = null;
+
+ msgDigest = MessageDigest.getInstance(digestAlg.toString());
+
+ ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+
+ respBody.encode(ostream);
+ digest = msgDigest.digest(ostream.toByteArray());
+
+ SignerInfo signInfo = new
+ SignerInfo(si, null, null,
+ OBJECT_IDENTIFIER.id_cct_PKIResponse,
+ digest, signAlg, privKey);
+ SET signInfos = new SET();
+
+ signInfos.addElement(signInfo);
+
+ SET digestAlgs = new SET();
+
+ if (digestAlg != null) {
+ AlgorithmIdentifier ai = new
+ AlgorithmIdentifier(digestAlg.toOID(), null);
+
+ digestAlgs.addElement(ai);
+ }
+ SignedData signedData = new SignedData(digestAlgs,
+ enContentInfo, certs, null, signInfos);
+
+ ContentInfo contentInfo = new ContentInfo(signedData);
+ CMS.debug("CMCOutputTemplate::getContentInfo() - done");
+ return contentInfo;
+ } catch (Exception e) {
+ CMS.debug("CMCOutputTemplate: Failed to create CMCContentInfo. Exception: " + e.toString());
+ }
+ return null;
+ }
+
+ public void createSimpleResponse(HttpServletResponse resp, IRequest[] reqs) {
+ SET certs = new SET();
+ SessionContext context = SessionContext.getContext();
+ try {
+ TaggedAttribute attr =
+ (TaggedAttribute) (context.get(OBJECT_IDENTIFIER.id_cmc_getCert));
+ processGetCertControl(attr, certs);
+ } catch (Exception e) {
+ CMS.debug("CMCOutputTemplate: No certificate is found.");
+ }
+
+ SET digestAlgorithms = new SET();
+ SET signedInfos = new SET();
+
+ // oid for id-data
+ OBJECT_IDENTIFIER oid = new OBJECT_IDENTIFIER("1.2.840.113549.1.7.1");
+ EncapsulatedContentInfo enContentInfo = new EncapsulatedContentInfo(oid, null);
+
+ try {
+ if (reqs != null) {
+ for (int i = 0; i < reqs.length; i++) {
+ X509CertImpl impl =
+ (reqs[i].getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT));
+ byte[] bin = impl.getEncoded();
+ Certificate.Template certTemplate = new Certificate.Template();
+ Certificate cert =
+ (Certificate) certTemplate.decode(new ByteArrayInputStream(bin));
+
+ certs.addElement(cert);
+ }
+
+ // Get CA certs
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca");
+ CertificateChain certchains = ca.getCACertChain();
+ java.security.cert.X509Certificate[] chains = certchains.getChain();
+
+ for (int i = 0; i < chains.length; i++) {
+ Certificate.Template certTemplate = new Certificate.Template();
+ Certificate cert = (Certificate) certTemplate.decode(
+ new ByteArrayInputStream(chains[i].getEncoded()));
+ certs.addElement(cert);
+ }
+ }
+
+ if (certs.size() == 0)
+ return;
+ SignedData signedData = new SignedData(digestAlgorithms,
+ enContentInfo, certs, null, signedInfos);
+
+ ContentInfo contentInfo = new ContentInfo(signedData);
+ ByteArrayOutputStream fos = new ByteArrayOutputStream();
+ contentInfo.encode(fos);
+ fos.close();
+ byte[] contentBytes = fos.toByteArray();
+
+ resp.setContentType("application/pkcs7-mime");
+ resp.setContentLength(contentBytes.length);
+ OutputStream os = resp.getOutputStream();
+ os.write(contentBytes);
+ os.flush();
+ } catch (java.security.cert.CertificateEncodingException e) {
+ CMS.debug("CMCOutputTemplate exception: " + e.toString());
+ } catch (InvalidBERException e) {
+ CMS.debug("CMCOutputTemplate exception: " + e.toString());
+ } catch (IOException e) {
+ CMS.debug("CMCOutputTemplate exception: " + e.toString());
+ }
+ }
+
+ private int processConfirmCertAcceptanceControl(
+ TaggedAttribute attr, SEQUENCE controlSeq, int bpid) {
+ if (attr != null) {
+ INTEGER bodyId = attr.getBodyPartID();
+ SEQUENCE seq = new SEQUENCE();
+ seq.addElement(bodyId);
+ SET values = attr.getValues();
+ if (values != null && values.size() > 0) {
+ try {
+ CMCCertId cmcCertId =
+ (CMCCertId) (ASN1Util.decode(CMCCertId.getTemplate(),
+ ASN1Util.encode(values.elementAt(0))));
+ BigInteger serialno = cmcCertId.getSerial();
+ SEQUENCE issuers = cmcCertId.getIssuer();
+ //ANY issuer = (ANY)issuers.elementAt(0);
+ ANY issuer =
+ (ANY) (ASN1Util.decode(ANY.getTemplate(),
+ ASN1Util.encode(issuers.elementAt(0))));
+ byte[] b = issuer.getEncoded();
+ X500Name n = new X500Name(b);
+ ICertificateAuthority ca = null;
+ ca = (ICertificateAuthority) CMS.getSubsystem("ca");
+ X500Name caName = ca.getX500Name();
+ boolean confirmAccepted = false;
+ if (n.toString().equalsIgnoreCase(caName.toString())) {
+ CMS.debug("CMCOutputTemplate: Issuer names are equal");
+ ICertificateRepository repository = ca.getCertificateRepository();
+ try {
+ repository.getX509Certificate(serialno);
+ } catch (EBaseException ee) {
+ CMS.debug("CMCOutputTemplate: Certificate in the confirm acceptance control was not found");
+ }
+ }
+ CMCStatusInfo cmcStatusInfo = null;
+ if (confirmAccepted) {
+ CMS.debug("CMCOutputTemplate: Confirm Acceptance received. The certificate exists in the certificate repository.");
+ cmcStatusInfo =
+ new CMCStatusInfo(CMCStatusInfo.SUCCESS, seq,
+ (String) null, null);
+ } else {
+ CMS.debug("CMCOutputTemplate: Confirm Acceptance received. The certificate does not exist in the certificate repository.");
+ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL,
+ new INTEGER(OtherInfo.BAD_CERT_ID), null);
+ cmcStatusInfo =
+ new CMCStatusInfo(CMCStatusInfo.FAILED, seq,
+ (String) null, otherInfo);
+ }
+ TaggedAttribute statustagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(statustagattr);
+ } catch (Exception e) {
+ CMS.debug("CMCOutputTemplate exception: " + e.toString());
+ }
+ }
+ }
+ return bpid;
+ }
+
+ private void processGetCertControl(TaggedAttribute attr, SET certs)
+ throws InvalidBERException, java.security.cert.CertificateEncodingException,
+ IOException, EBaseException {
+ if (attr != null) {
+ SET vals = attr.getValues();
+
+ if (vals.size() == 1) {
+ GetCert getCert =
+ (GetCert) (ASN1Util.decode(GetCert.getTemplate(),
+ ASN1Util.encode(vals.elementAt(0))));
+ BigInteger serialno = getCert.getSerialNumber();
+ ANY issuer = getCert.getIssuer();
+ byte b[] = issuer.getEncoded();
+ X500Name n = new X500Name(b);
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca");
+ X500Name caName = ca.getX500Name();
+ if (!n.toString().equalsIgnoreCase(caName.toString())) {
+ CMS.debug("CMCOutputTemplate: Issuer names are equal in the GetCert Control");
+ throw new EBaseException("Certificate is not found");
+ }
+ ICertificateRepository repository =
+ ca.getCertificateRepository();
+ X509CertImpl impl = repository.getX509Certificate(serialno);
+ byte[] bin = impl.getEncoded();
+ Certificate.Template certTemplate = new Certificate.Template();
+ Certificate cert =
+ (Certificate) certTemplate.decode(new ByteArrayInputStream(bin));
+ certs.addElement(cert);
+ }
+ }
+ }
+
+ private int processQueryPendingControl(TaggedAttribute attr,
+ SEQUENCE controlSeq, int bpid) {
+ if (attr != null) {
+ SET values = attr.getValues();
+ if (values != null && values.size() > 0) {
+ SEQUENCE pending_bpids = new SEQUENCE();
+ SEQUENCE success_bpids = new SEQUENCE();
+ SEQUENCE failed_bpids = new SEQUENCE();
+ for (int i = 0; i < values.size(); i++) {
+ try {
+ INTEGER reqId = (INTEGER)
+ ASN1Util.decode(INTEGER.getTemplate(),
+ ASN1Util.encode(values.elementAt(i)));
+ String requestId = new String(reqId.toByteArray());
+
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca");
+ IRequestQueue queue = ca.getRequestQueue();
+ IRequest r = queue.findRequest(new RequestId(requestId));
+ if (r != null) {
+ RequestStatus status = r.getRequestStatus();
+ if (status.equals(RequestStatus.PENDING)) {
+ pending_bpids.addElement(reqId);
+ } else if (status.equals(RequestStatus.APPROVED)) {
+ success_bpids.addElement(reqId);
+ } else if (status.equals(RequestStatus.REJECTED)) {
+ failed_bpids.addElement(reqId);
+ }
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ if (pending_bpids.size() > 0) {
+ CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.PENDING,
+ pending_bpids, (String) null, null);
+ TaggedAttribute tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ }
+ if (success_bpids.size() > 0) {
+ CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS,
+ pending_bpids, (String) null, null);
+ TaggedAttribute tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ }
+
+ if (failed_bpids.size() > 0) {
+ CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED,
+ pending_bpids, (String) null, null);
+ TaggedAttribute tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ }
+
+ }
+ }
+ return bpid;
+ }
+
+ private int processTransactionControl(TaggedAttribute attr,
+ SEQUENCE controlSeq, int bpid) {
+ if (attr != null) {
+ SET transIds = attr.getValues();
+ if (transIds != null) {
+ TaggedAttribute tagattr = new TaggedAttribute(
+ new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_transactionId,
+ transIds);
+ controlSeq.addElement(tagattr);
+ }
+ }
+
+ return bpid;
+ }
+
+ private int processSenderNonceControl(TaggedAttribute attr,
+ SEQUENCE controlSeq, int bpid) {
+ if (attr != null) {
+ SET sNonce = attr.getValues();
+ if (sNonce != null) {
+ TaggedAttribute tagattr = new TaggedAttribute(
+ new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_recipientNonce,
+ sNonce);
+ controlSeq.addElement(tagattr);
+ Date date = new Date();
+ String salt = "lala123" + date.toString();
+ byte[] dig;
+ try {
+ MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+ dig = SHA1Digest.digest(salt.getBytes());
+ } catch (NoSuchAlgorithmException ex) {
+ dig = salt.getBytes();
+ }
+
+ String b64E = CMS.BtoA(dig);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_senderNonce,
+ new OCTET_STRING(b64E.getBytes()));
+ controlSeq.addElement(tagattr);
+ }
+ }
+
+ return bpid;
+ }
+
+ private int processDataReturnControl(TaggedAttribute attr,
+ SEQUENCE controlSeq, int bpid) throws InvalidBERException {
+
+ if (attr != null) {
+ SET vals = attr.getValues();
+
+ if (vals.size() > 0) {
+ OCTET_STRING str =
+ (OCTET_STRING) (ASN1Util.decode(OCTET_STRING.getTemplate(),
+ ASN1Util.encode(vals.elementAt(0))));
+ TaggedAttribute tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_dataReturn, str);
+ controlSeq.addElement(tagattr);
+ }
+ }
+
+ return bpid;
+ }
+
+ private int processRevokeRequestControl(TaggedAttribute attr,
+ SEQUENCE controlSeq, int bpid) throws InvalidBERException, EBaseException,
+ IOException {
+ boolean revoke = false;
+ SessionContext context = SessionContext.getContext();
+ if (attr != null) {
+ INTEGER attrbpid = attr.getBodyPartID();
+ CMCStatusInfo cmcStatusInfo = null;
+ SET vals = attr.getValues();
+ if (vals.size() > 0) {
+ RevRequest revRequest =
+ (RevRequest) (ASN1Util.decode(new RevRequest.Template(),
+ ASN1Util.encode(vals.elementAt(0))));
+ OCTET_STRING str = revRequest.getSharedSecret();
+ INTEGER pid = attr.getBodyPartID();
+ TaggedAttribute tagattr = null;
+ INTEGER revokeCertSerial = revRequest.getSerialNumber();
+ BigInteger revokeSerial = new BigInteger(revokeCertSerial.toByteArray());
+ if (str == null) {
+ boolean needVerify = true;
+ try {
+ needVerify = CMS.getConfigStore().getBoolean("cmc.revokeCert.verify", true);
+ } catch (Exception e) {
+ }
+
+ if (needVerify) {
+ Integer num1 = (Integer) context.get("numOfOtherMsgs");
+ int num = num1.intValue();
+ for (int i = 0; i < num; i++) {
+ OtherMsg data = (OtherMsg) context.get("otherMsg" + i);
+ INTEGER dpid = data.getBodyPartID();
+ if (pid.longValue() == dpid.longValue()) {
+ ANY msgValue = data.getOtherMsgValue();
+ SignedData msgData =
+ (SignedData) msgValue.decodeWith(SignedData.getTemplate());
+ if (!verifyRevRequestSignature(msgData)) {
+ OtherInfo otherInfo =
+ new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_MESSAGE_CHECK),
+ null);
+ SEQUENCE failed_bpids = new SEQUENCE();
+ failed_bpids.addElement(attrbpid);
+ cmcStatusInfo =
+ new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null,
+ otherInfo);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ return bpid;
+ }
+ }
+ }
+ }
+
+ revoke = true;
+ // check shared secret
+ } else {
+ ISharedToken tokenClass = null;
+ boolean sharedSecretFound = true;
+ String name = null;
+ try {
+ name = CMS.getConfigStore().getString("cmc.revokeCert.sharedSecret.class");
+ } catch (EPropertyNotFound e) {
+ CMS.debug("EnrollProfile: Failed to find the token class in the configuration file.");
+ sharedSecretFound = false;
+ } catch (EBaseException e) {
+ CMS.debug("EnrollProfile: Failed to find the token class in the configuration file.");
+ sharedSecretFound = false;
+ }
+
+ try {
+ tokenClass = (ISharedToken) Class.forName(name).newInstance();
+ } catch (ClassNotFoundException e) {
+ CMS.debug("EnrollProfile: Failed to find class name: " + name);
+ sharedSecretFound = false;
+ } catch (InstantiationException e) {
+ CMS.debug("EnrollProfile: Failed to instantiate class: " + name);
+ sharedSecretFound = false;
+ } catch (IllegalAccessException e) {
+ CMS.debug("EnrollProfile: Illegal access: " + name);
+ sharedSecretFound = false;
+ }
+
+ if (!sharedSecretFound) {
+ CMS.debug("CMCOutputTemplate: class for shared secret was not found.");
+ OtherInfo otherInfo =
+ new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.INTERNAL_CA_ERROR), null);
+ SEQUENCE failed_bpids = new SEQUENCE();
+ failed_bpids.addElement(attrbpid);
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ return bpid;
+ }
+
+ String sharedSecret = null;
+ if (tokenClass != null) {
+ sharedSecret = tokenClass.getSharedToken(revokeSerial);
+ }
+
+ if (sharedSecret == null) {
+ CMS.debug("CMCOutputTemplate: class for shared secret was not found.");
+ OtherInfo otherInfo =
+ new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.INTERNAL_CA_ERROR), null);
+ SEQUENCE failed_bpids = new SEQUENCE();
+ failed_bpids.addElement(attrbpid);
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ return bpid;
+ }
+
+ byte[] strb = str.toByteArray();
+ String clientSC = new String(strb);
+ if (clientSC.equals(sharedSecret)) {
+ CMS.debug("CMCOutputTemplate: Both client and server shared secret are the same, can go ahead to revoke certificate.");
+ revoke = true;
+ } else {
+ CMS.debug("CMCOutputTemplate: Both client and server shared secret are not the same, cant revoke certificate.");
+ OtherInfo otherInfo =
+ new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_MESSAGE_CHECK), null);
+ SEQUENCE failed_bpids = new SEQUENCE();
+ failed_bpids.addElement(attrbpid);
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ return bpid;
+ }
+ }
+
+ if (revoke) {
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca");
+ ICertificateRepository repository = ca.getCertificateRepository();
+ ICertRecord record = null;
+ try {
+ record = repository.readCertificateRecord(revokeSerial);
+ } catch (EBaseException ee) {
+ CMS.debug("CMCOutputTemplate: Exception: " + ee.toString());
+ }
+
+ if (record == null) {
+ CMS.debug("CMCOutputTemplate: The certificate is not found");
+ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_CERT_ID), null);
+ SEQUENCE failed_bpids = new SEQUENCE();
+ failed_bpids.addElement(attrbpid);
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ return bpid;
+ }
+
+ if (record.getStatus().equals(ICertRecord.STATUS_REVOKED)) {
+ CMS.debug("CMCOutputTemplate: The certificate is already revoked.");
+ SEQUENCE success_bpids = new SEQUENCE();
+ success_bpids.addElement(attrbpid);
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS,
+ success_bpids, (String) null, null);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ return bpid;
+ }
+ X509CertImpl impl = record.getCertificate();
+ X509CertImpl[] impls = new X509CertImpl[1];
+ impls[0] = impl;
+ ENUMERATED n = revRequest.getReason();
+ RevocationReason reason = toRevocationReason(n);
+ CRLReasonExtension crlReasonExtn = new CRLReasonExtension(reason);
+ CRLExtensions entryExtn = new CRLExtensions();
+ GeneralizedTime t = revRequest.getInvalidityDate();
+ InvalidityDateExtension invalidityDateExtn = null;
+ if (t != null) {
+ invalidityDateExtn = new InvalidityDateExtension(t.toDate());
+ entryExtn.set(invalidityDateExtn.getName(), invalidityDateExtn);
+ }
+ if (crlReasonExtn != null) {
+ entryExtn.set(crlReasonExtn.getName(), crlReasonExtn);
+ }
+
+ RevokedCertImpl revCertImpl =
+ new RevokedCertImpl(impl.getSerialNumber(), CMS.getCurrentDate(), entryExtn);
+ RevokedCertImpl[] revCertImpls = new RevokedCertImpl[1];
+ revCertImpls[0] = revCertImpl;
+ IRequestQueue queue = ca.getRequestQueue();
+ IRequest revReq = queue.newRequest(IRequest.REVOCATION_REQUEST);
+ revReq.setExtData(IRequest.CERT_INFO, revCertImpls);
+ revReq.setExtData(IRequest.REVOKED_REASON,
+ Integer.valueOf(reason.toInt()));
+ UTF8String utfstr = revRequest.getComment();
+ if (utfstr != null)
+ revReq.setExtData(IRequest.REQUESTOR_COMMENTS, utfstr.toString());
+ revReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_AGENT);
+ queue.processRequest(revReq);
+ RequestStatus stat = revReq.getRequestStatus();
+ if (stat == RequestStatus.COMPLETE) {
+ Integer result = revReq.getExtDataInInteger(IRequest.RESULT);
+ CMS.debug("CMCOutputTemplate: revReq result = " + result);
+ if (result.equals(IRequest.RES_ERROR)) {
+ CMS.debug("CMCOutputTemplate: revReq exception: " +
+ revReq.getExtDataInString(IRequest.ERROR));
+ OtherInfo otherInfo =
+ new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_REQUEST), null);
+ SEQUENCE failed_bpids = new SEQUENCE();
+ failed_bpids.addElement(attrbpid);
+ cmcStatusInfo =
+ new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ return bpid;
+ }
+ }
+
+ ILogger logger = CMS.getLogger();
+ String initiative = AuditFormat.FROMUSER;
+ logger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT, new Object[] {
+ revReq.getRequestId(), initiative, "completed",
+ impl.getSubjectDN(),
+ impl.getSerialNumber().toString(16),
+ reason.toString() });
+ CMS.debug("CMCOutputTemplate: Certificate get revoked.");
+ SEQUENCE success_bpids = new SEQUENCE();
+ success_bpids.addElement(attrbpid);
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS,
+ success_bpids, (String) null, null);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ return bpid;
+ } else {
+ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_MESSAGE_CHECK), null);
+ SEQUENCE failed_bpids = new SEQUENCE();
+ failed_bpids.addElement(attrbpid);
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ return bpid;
+ }
+ }
+ }
+
+ return bpid;
+ }
+
+ private RevocationReason toRevocationReason(ENUMERATED n) {
+ long code = n.getValue();
+ if (code == RevRequest.aACompromise.getValue())
+ return RevocationReason.UNSPECIFIED;
+ else if (code == RevRequest.affiliationChanged.getValue())
+ return RevocationReason.AFFILIATION_CHANGED;
+ else if (code == RevRequest.cACompromise.getValue())
+ return RevocationReason.CA_COMPROMISE;
+ else if (code == RevRequest.certificateHold.getValue())
+ return RevocationReason.CERTIFICATE_HOLD;
+ else if (code == RevRequest.cessationOfOperation.getValue())
+ return RevocationReason.CESSATION_OF_OPERATION;
+ else if (code == RevRequest.keyCompromise.getValue())
+ return RevocationReason.KEY_COMPROMISE;
+ else if (code == RevRequest.privilegeWithdrawn.getValue())
+ return RevocationReason.UNSPECIFIED;
+ else if (code == RevRequest.removeFromCRL.getValue())
+ return RevocationReason.REMOVE_FROM_CRL;
+ else if (code == RevRequest.superseded.getValue())
+ return RevocationReason.SUPERSEDED;
+ else if (code == RevRequest.unspecified.getValue())
+ return RevocationReason.UNSPECIFIED;
+ return RevocationReason.UNSPECIFIED;
+ }
+
+ private boolean verifyRevRequestSignature(SignedData msgData) {
+ try {
+ EncapsulatedContentInfo ci = msgData.getContentInfo();
+ OCTET_STRING content = ci.getContent();
+ ByteArrayInputStream s = new ByteArrayInputStream(content.toByteArray());
+ TaggedAttribute tattr = (TaggedAttribute) (new TaggedAttribute.Template()).decode(s);
+ SET values = tattr.getValues();
+ RevRequest revRequest = null;
+ if (values != null && values.size() > 0)
+ revRequest =
+ (RevRequest) (ASN1Util.decode(new RevRequest.Template(),
+ ASN1Util.encode(values.elementAt(0))));
+
+ SET dias = msgData.getDigestAlgorithmIdentifiers();
+ int numDig = dias.size();
+ Hashtable<String, byte[]> digs = new Hashtable<String, byte[]>();
+ for (int i = 0; i < numDig; i++) {
+ AlgorithmIdentifier dai =
+ (AlgorithmIdentifier) dias.elementAt(i);
+ String name =
+ DigestAlgorithm.fromOID(dai.getOID()).toString();
+ MessageDigest md =
+ MessageDigest.getInstance(name);
+ byte[] digest = md.digest(content.toByteArray());
+ digs.put(name, digest);
+ }
+
+ SET sis = msgData.getSignerInfos();
+ int numSis = sis.size();
+ for (int i = 0; i < numSis; i++) {
+ org.mozilla.jss.pkix.cms.SignerInfo si =
+ (org.mozilla.jss.pkix.cms.SignerInfo) sis.elementAt(i);
+ String name = si.getDigestAlgorithm().toString();
+ byte[] digest = digs.get(name);
+ if (digest == null) {
+ MessageDigest md = MessageDigest.getInstance(name);
+ ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+ revRequest.encode(ostream);
+ digest = md.digest(ostream.toByteArray());
+ }
+ SignerIdentifier sid = si.getSignerIdentifier();
+ if (sid.getType().equals(SignerIdentifier.ISSUER_AND_SERIALNUMBER)) {
+ org.mozilla.jss.pkix.cms.IssuerAndSerialNumber issuerAndSerialNumber =
+ sid.getIssuerAndSerialNumber();
+ java.security.cert.X509Certificate cert = null;
+ if (msgData.hasCertificates()) {
+ SET certs = msgData.getCertificates();
+ int numCerts = certs.size();
+ for (int j = 0; j < numCerts; j++) {
+ org.mozilla.jss.pkix.cert.Certificate certJss =
+ (Certificate) certs.elementAt(j);
+ org.mozilla.jss.pkix.cert.CertificateInfo certI =
+ certJss.getInfo();
+ Name issuer = certI.getIssuer();
+ byte[] issuerB = ASN1Util.encode(issuer);
+ INTEGER sn = certI.getSerialNumber();
+ if (new String(issuerB).equalsIgnoreCase(new String(ASN1Util.encode(issuerAndSerialNumber
+ .getIssuer()))) &&
+ sn.toString().equals(issuerAndSerialNumber.getSerialNumber().toString())) {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ certJss.encode(os);
+ cert = new X509CertImpl(os.toByteArray());
+ break;
+ }
+ }
+ }
+
+ if (cert != null) {
+ PublicKey pbKey = cert.getPublicKey();
+ PK11PubKey pubK = PK11PubKey.fromSPKI(((X509Key) pbKey).getKey());
+ si.verify(digest, ci.getContentType(), pubK);
+ return true;
+ }
+ }
+ }
+
+ return false;
+ } catch (Exception e) {
+ CMS.debug("CMCOutputTemplate: verifyRevRequestSignature. Exception: " + e.toString());
+ return false;
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMSFile.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMSFile.java
new file mode 100644
index 000000000..7f73ce8d3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMSFile.java
@@ -0,0 +1,102 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * CMSFile represents a file from the filesystem cached in memory
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSFile {
+ protected String mAbsPath;
+ protected long mLastModified;
+ protected byte[] mContent;
+ protected long mLastAccess = 0;
+
+ protected ILogger mLogger = CMS.getLogger();
+
+ protected CMSFile() {
+ }
+
+ public CMSFile(File file) throws IOException, EBaseException {
+ mAbsPath = file.getAbsolutePath();
+ mLastModified = file.lastModified();
+ fillContent(file);
+ }
+
+ private void fillContent(File file) throws IOException {
+ int fileSize = (int) file.length();
+
+ mContent = new byte[fileSize];
+ FileInputStream fileIn = new FileInputStream(file);
+ int actualSize = fileIn.read(mContent);
+ fileIn.close();
+
+ if (actualSize != fileSize) {
+ byte[] actualContent = new byte[actualSize];
+
+ System.arraycopy(mContent, 0, actualContent, 0, actualSize);
+ mContent = actualContent;
+ }
+ }
+
+ public String getAbsPath() {
+ return mAbsPath;
+ }
+
+ public byte[] getContent() {
+ return mContent;
+ }
+
+ public long getLastModified() {
+ return mLastModified;
+ }
+
+ public synchronized long getLastAccess() {
+ return mLastAccess;
+ }
+
+ public synchronized void setLastAccess(long lastAccess) {
+ mLastAccess = lastAccess;
+ }
+
+ protected void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, level, ILogger.S_OTHER, "CMSgateway:" + msg);
+ }
+
+ public String toString() {
+ try {
+ return new String(mContent, "UTF8");
+ } catch (UnsupportedEncodingException e) {
+ return new String(mContent);
+ }
+ }
+
+ public String toString(String enc) throws UnsupportedEncodingException {
+ return new String(mContent, enc);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMSFileLoader.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMSFileLoader.java
new file mode 100644
index 000000000..a27a3dd43
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMSFileLoader.java
@@ -0,0 +1,161 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+
+/**
+ * CMSFileLoader - file cache.
+ *
+ * @version $Revision$, $Date$
+ */
+
+public class CMSFileLoader {
+ // default max size
+ public final int MAX_SIZE = 200;
+ // default number of files to clear when max is reached.
+ public final int CLEAR_SIZE = 50;
+ // max size property
+ public final String PROP_MAX_SIZE = "maxSize";
+ // clear size property
+ public final String PROP_CLEAR_SIZE = "clearSize";
+ // property to cache templates only
+ public final String PROP_CACHE_TEMPLATES_ONLY = "cacheTemplatesOnly";
+
+ // hash of files to their content.
+ private Hashtable<String, CMSFile> mLoadedFiles = new Hashtable<String, CMSFile>();
+
+ // max number of files
+ private int mMaxSize = MAX_SIZE;
+
+ // number of files to clear when max is reached.
+ private int mClearSize = CLEAR_SIZE;
+
+ // whether to cache templates and forms only.
+ @SuppressWarnings("unused")
+ private boolean mCacheTemplatesOnly = true;
+
+ public CMSFileLoader() {
+ }
+
+ public void init(IConfigStore config) throws EBaseException {
+ mMaxSize = config.getInteger(PROP_MAX_SIZE, MAX_SIZE);
+ mClearSize = config.getInteger(PROP_CLEAR_SIZE, CLEAR_SIZE);
+ mCacheTemplatesOnly =
+ config.getBoolean(PROP_CACHE_TEMPLATES_ONLY, true);
+ }
+
+ // Changed by bskim
+ //public byte[] get(String absPath) throws EBaseException, IOException {
+ // File file = new File(absPath);
+ // return get(file);
+ //}
+ public byte[] get(String absPath, String enc) throws EBaseException, IOException {
+ File file = new File(absPath);
+
+ return get(file, enc);
+ }
+
+ // Change end
+
+ // Changed by bskim
+ //public byte[] get(File file) throws EBaseException, IOException {
+ // CMSFile cmsFile = getCMSFile(file);
+ public byte[] get(File file, String enc) throws EBaseException, IOException {
+ CMSFile cmsFile = getCMSFile(file, enc);
+
+ // Change end
+ return cmsFile.getContent();
+ }
+
+ // Changed by bskim
+ //public CMSFile getCMSFile(File file) throws EBaseException, IOException {
+ public CMSFile getCMSFile(File file, String enc) throws EBaseException, IOException {
+ // Change end
+ String absPath = file.getAbsolutePath();
+ long modified = file.lastModified();
+ CMSFile cmsFile = mLoadedFiles.get(absPath);
+ long lastModified = (cmsFile == null ? 0 : cmsFile.getLastModified());
+
+ // new file.
+ if (cmsFile == null || modified != lastModified) {
+ // Changed by bskim
+ //cmsFile = updateFile(absPath, file);
+ cmsFile = updateFile(absPath, file, enc);
+ // Change end
+ }
+ cmsFile.setLastAccess(System.currentTimeMillis());
+ return cmsFile;
+ }
+
+ // Changed by bskim
+ //private CMSFile updateFile(String absPath, File file)
+ private CMSFile updateFile(String absPath, File file, String enc)
+ // Change end
+ throws EBaseException, IOException {
+ // clear if cache size exceeded.
+ if (mLoadedFiles.size() >= mMaxSize) {
+ clearSomeFiles();
+ }
+
+ CMSFile cmsFile = null;
+
+ // check if file is a js template or plain template by its first String
+ if (absPath.endsWith(CMSTemplate.SUFFIX)) {
+ // Changed by bskim
+ //cmsFile = new CMSTemplate(file);
+ cmsFile = new CMSTemplate(file, enc);
+ // End of Change
+ } else {
+ cmsFile = new CMSFile(file);
+ }
+ mLoadedFiles.put(absPath, cmsFile); // replace old one if any.
+ return cmsFile;
+ }
+
+ private synchronized void clearSomeFiles() {
+
+ // recheck this in case some other thread has cleared it.
+ if (mLoadedFiles.size() < mMaxSize)
+ return;
+
+ // remove the LRU files.
+ // XXX could be optimized more.
+ Enumeration<CMSFile> elements = mLoadedFiles.elements();
+
+ for (int i = mClearSize; i > 0; i--) {
+ long lru = java.lang.Long.MAX_VALUE;
+ CMSFile lruFile = null;
+
+ while (elements.hasMoreElements()) {
+ CMSFile cmsFile = elements.nextElement();
+
+ if (cmsFile.getLastAccess() < lru) {
+ lruFile = cmsFile;
+ }
+ mLoadedFiles.remove(lruFile.getAbsPath());
+ }
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMSGWResources.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMSGWResources.java
new file mode 100644
index 000000000..32264c01e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMSGWResources.java
@@ -0,0 +1,44 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.util.ListResourceBundle;
+
+/**
+ * A class represents a resource bundle for cms gateway.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ * @see java.util.ListResourceBundle
+ */
+public class CMSGWResources extends ListResourceBundle {
+
+ /**
+ * Returns the content of this resource.
+ */
+ public Object[][] getContents() {
+ return contents;
+ }
+
+ /*
+ * Constants. The suffix represents the number of
+ * possible parameters.
+ */
+
+ static final Object[][] contents = {};
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMSGateway.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMSGateway.java
new file mode 100644
index 000000000..3c8f88e89
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMSGateway.java
@@ -0,0 +1,370 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * This class is to hold some general method for servlets.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSGateway {
+ public final static String PROP_CMSGATEWAY = "cmsgateway";
+ private final static String PROP_ENABLE_ADMIN_ENROLL = "enableAdminEnroll";
+
+ public static final String CERT_ATTR =
+ "javax.servlet.request.X509Certificate";
+
+ protected static CMSFileLoader mFileLoader = new CMSFileLoader();
+
+ protected static boolean mEnableFileServing;
+ private static boolean mEnableAdminEnroll = true;
+ private static IConfigStore mConfig = null;
+
+ // system logger.
+ protected static ILogger mLogger = CMS.getLogger();
+
+ static {
+ mEnableFileServing = true;
+ mConfig = CMS.getConfigStore().getSubStore(PROP_CMSGATEWAY);
+ try {
+ mEnableAdminEnroll =
+ mConfig.getBoolean(PROP_ENABLE_ADMIN_ENROLL, false);
+ } catch (EBaseException e) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_BAD_CONFIG_PARAM"));
+ }
+ }
+
+ public CMSGateway() {
+ }
+
+ public static Hashtable<String, String> toHashtable(HttpServletRequest req) {
+ Hashtable<String, String> httpReqHash = new Hashtable<String, String>();
+ Enumeration<String> names = req.getParameterNames();
+
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+
+ httpReqHash.put(name, req.getParameter(name));
+ }
+
+ String ip = req.getRemoteAddr();
+ if (ip != null)
+ httpReqHash.put("clientHost", ip);
+ return httpReqHash;
+ }
+
+ public static boolean getEnableAdminEnroll() {
+ return mEnableAdminEnroll;
+ }
+
+ public static void setEnableAdminEnroll(boolean enableAdminEnroll)
+ throws EBaseException {
+ IConfigStore mainConfig = CMS.getConfigStore();
+
+ //!!! Is it thread safe? xxxx
+ mEnableAdminEnroll = enableAdminEnroll;
+ mConfig.putBoolean(PROP_ENABLE_ADMIN_ENROLL, enableAdminEnroll);
+ mainConfig.commit(true);
+ }
+
+ public static void disableAdminEnroll() throws EBaseException {
+ setEnableAdminEnroll(false);
+
+ /* need to do this in web.xml and restart ws
+ removeServlet("/ca/adminEnroll", "AdminEnroll");
+ initGateway();
+ */
+ }
+
+ /**
+ * construct a authentication credentials to pass into authentication
+ * manager.
+ */
+ public static AuthCredentials getAuthCreds(
+ IAuthManager authMgr, IArgBlock argBlock, X509Certificate clientCert)
+ throws EBaseException {
+ // get credentials from http parameters.
+ if (authMgr == null)
+ return null;
+ String[] reqCreds = authMgr.getRequiredCreds();
+ AuthCredentials creds = new AuthCredentials();
+
+ if (clientCert instanceof java.security.cert.X509Certificate) {
+ try {
+ clientCert = new netscape.security.x509.X509CertImpl(clientCert.getEncoded());
+ } catch (Exception e) {
+ CMS.debug("CMSGateway: getAuthCreds " + e.toString());
+ }
+ }
+
+ for (int i = 0; i < reqCreds.length; i++) {
+ String reqCred = reqCreds[i];
+
+ if (reqCred.equals(IAuthManager.CRED_SSL_CLIENT_CERT)) {
+ // cert could be null;
+ creds.set(reqCred, new X509Certificate[] { clientCert }
+ );
+ } else {
+ String value = argBlock.getValueAsString(reqCred);
+
+ creds.set(reqCred, value); // value could be null;
+ }
+ }
+
+ creds.set("clientHost", argBlock.getValueAsString("clientHost"));
+ // Inserted by bskim
+ creds.setArgBlock(argBlock);
+ // Insert end
+ return creds;
+ }
+
+ protected final static String AUTHMGR_PARAM = "authenticator";
+
+ public static AuthToken checkAuthManager(
+ HttpServletRequest httpReq, IArgBlock httpParams,
+ X509Certificate cert, String authMgrName)
+ throws EBaseException {
+ IArgBlock httpArgs = httpParams;
+
+ if (httpArgs == null)
+ httpArgs = CMS.createArgBlock(toHashtable(httpReq));
+
+ IAuthSubsystem authSub = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+
+ String authMgr_http = httpArgs.getValueAsString(
+ AUTHMGR_PARAM, null);
+
+ if (authMgr_http != null) {
+ authMgrName = authMgr_http;
+ }
+
+ if (authMgrName == null || authMgrName.length() == 0) {
+ throw new EBaseException(CMS.getLogMessage("BASE_INTERNAL_ERROR_1",
+ CMS.getLogMessage("CMSGW_AUTH_MAN_EXPECTED")));
+ }
+
+ IAuthManager authMgr =
+ authSub.getAuthManager(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID);
+
+ authMgr = authSub.getAuthManager(authMgrName);
+ if (authMgr == null)
+ return null;
+ IAuthCredentials creds =
+ getAuthCreds(authMgr, CMS.createArgBlock(toHashtable(httpReq)), cert);
+ AuthToken authToken = null;
+
+ try {
+ authToken = (AuthToken) authMgr.authenticate(creds);
+ } catch (EBaseException e) {
+ throw e;
+ } catch (Exception e) {
+ CMS.debug("CMSGateway: " + e);
+ // catch all errors from authentication manager.
+ throw new ECMSGWException(CMS.getLogMessage("CMSGW_AUTH_ERROR_2",
+ e.toString(), e.getMessage()));
+ }
+ return authToken;
+ }
+
+ public static void renderTemplate(
+ String templateName,
+ HttpServletRequest req,
+ HttpServletResponse resp,
+ ServletConfig servletConfig,
+ CMSFileLoader fileLoader)
+ throws EBaseException, IOException {
+ CMSTemplate template =
+ getTemplate(templateName, req,
+ servletConfig, fileLoader, new Locale[1]);
+ ServletOutputStream out = resp.getOutputStream();
+
+ template.renderOutput(out, new CMSTemplateParams(null, null));
+ }
+
+ // XXX TBD move this to a utility function too.
+
+ public static Locale getLocale(String lang) {
+ int dash = lang.indexOf('-');
+
+ if (dash == -1)
+ return new Locale(lang, "");
+ else
+ return new Locale(lang.substring(0, dash), lang.substring(dash + 1));
+ }
+
+ /**
+ * @param req http servlet request
+ * @param realpathFile the file to get.
+ * @param locale array of at least one to be filled with locale found.
+ */
+ public static File getLangFile(
+ HttpServletRequest req, File realpathFile, Locale[] locale)
+ throws IOException {
+ File file = null;
+ String acceptLang = req.getHeader("accept-language");
+
+ if (acceptLang != null && !acceptLang.equals("")) {
+ StringTokenizer tokenizer = new StringTokenizer(acceptLang, ",");
+ int numLangs = tokenizer.countTokens();
+
+ if (numLangs > 0) {
+ // languages are searched in order.
+ String parent = realpathFile.getParent();
+
+ if (parent == null) {
+ parent = "." + File.separatorChar;
+ }
+ String name = realpathFile.getName();
+
+ if (name == null) { // filename should never be null.
+ throw new IOException("file has no name");
+ }
+ int i;
+
+ for (i = 0; i < numLangs; i++) {
+ String lang = null;
+ String token = tokenizer.nextToken();
+
+ int semicolon = token.indexOf(';');
+
+ if (semicolon == -1) {
+ lang = token.trim();
+ } else {
+ if (semicolon < 2)
+ continue; // protocol error.
+ lang = token.substring(0, semicolon).trim();
+ }
+ // if browser locale is the same as default locale,
+ // use the default form. (is this the right thing to do ?)
+ Locale l = getLocale(lang);
+
+ if (Locale.getDefault().equals(l)) {
+ locale[0] = l;
+ file = realpathFile;
+ break;
+ }
+
+ String langfilepath =
+ parent + File.separatorChar +
+ lang + File.separatorChar + name;
+
+ file = new File(langfilepath);
+ if (file.exists()) {
+ locale[0] = getLocale(lang);
+ break;
+ }
+ }
+ // if no file for lang was found use default
+ if (i == numLangs) {
+ file = realpathFile;
+ locale[0] = Locale.getDefault();
+ }
+ }
+ } else {
+ // use default if accept-language is not availabe
+ file = realpathFile;
+ locale[0] = Locale.getDefault();
+ }
+ return file;
+ }
+
+ /**
+ * get a template
+ */
+ protected static CMSTemplate getTemplate(
+ String templateName,
+ HttpServletRequest httpReq,
+ ServletConfig servletConfig,
+ CMSFileLoader fileLoader,
+ Locale[] locale)
+ throws EBaseException, IOException {
+ // this converts to system dependent file seperator char.
+ if (servletConfig == null) {
+ CMS.debug("CMSGateway:getTemplate() - servletConfig is null!");
+ return null;
+ }
+ if (servletConfig.getServletContext() == null) {
+ }
+ if (templateName == null) {
+ }
+ String realpath =
+ servletConfig.getServletContext().getRealPath("/" + templateName);
+ File realpathFile = new File(realpath);
+ File templateFile =
+ getLangFile(httpReq, realpathFile, locale);
+ CMSTemplate template =
+ //(CMSTemplate)fileLoader.getCMSFile(templateFile);
+ (CMSTemplate) fileLoader.getCMSFile(templateFile, httpReq.getCharacterEncoding());
+
+ return template;
+ }
+
+ /**
+ * Get the If-Modified-Since header and compare it to the millisecond
+ * epoch value passed in. If there is no header, or there is a problem
+ * parsing the value, or if the file has been modified this will return
+ * true, indicating the file has changed.
+ *
+ * @param lastModified The time value in milliseconds past the epoch to
+ * compare the If-Modified-Since header to.
+ */
+ public static boolean modifiedSince(HttpServletRequest req, long lastModified) {
+ long ifModSinceStr;
+
+ try {
+ ifModSinceStr = req.getDateHeader("If-Modified-Since");
+ } catch (IllegalArgumentException e) {
+ return true;
+ }
+
+ if (ifModSinceStr < 0) {
+ return true;
+ }
+
+ if (ifModSinceStr < lastModified) {
+ return true; // Data must be resent
+ }
+
+ return false; // Data has not been modified
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMSLoadTemplate.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMSLoadTemplate.java
new file mode 100644
index 000000000..4e3d3c0bc
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMSLoadTemplate.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+/**
+ * handy class containing cms templates to load & fill.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSLoadTemplate {
+ public String mPropName;
+ public String mFillerPropName;
+ public String mTemplateName;
+ public ICMSTemplateFiller mFiller;
+
+ public CMSLoadTemplate() {
+ }
+
+ public CMSLoadTemplate(
+ String propName, String fillerPropName,
+ String templateName, ICMSTemplateFiller filler) {
+
+ mPropName = propName;
+ mFillerPropName = fillerPropName;
+ mTemplateName = templateName;
+ mFiller = filler;
+ }
+
+ public String getPropName() {
+ return mPropName;
+ }
+
+ public String getFillerPropName() {
+ return mFillerPropName;
+ }
+
+ public String getTemplateName() {
+ return mTemplateName;
+ }
+
+ public ICMSTemplateFiller getTemplateFiller() {
+ return mFiller;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMSRequest.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMSRequest.java
new file mode 100644
index 000000000..5ac640952
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMSRequest.java
@@ -0,0 +1,293 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+
+/**
+ * This represents a user request.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSRequest implements ICMSRequest {
+
+ private static final String RESULT = "cmsRequestResult";
+
+ // Reason message for request failure
+ private String reason = null;
+
+ // http parameters - handier than getting directly from http request.
+ private IArgBlock mHttpParams = null;
+
+ // http headers & other info.
+ private HttpServletRequest mHttpReq = null;
+
+ // http response.
+ private HttpServletResponse mHttpResp = null;
+
+ // http servlet config.
+ private ServletConfig mServletConfig = null;
+
+ // http servlet context.
+ private ServletContext mServletContext = null;
+
+ // permanent request in request queue.
+ private IRequest mRequest = null;
+
+ // whether request processed successfully
+ private Integer mStatus = SUCCESS;
+
+ // exception message containing error that occured.
+ // note exception could also be thrown seperately.
+ private String mError = null;
+
+ // any error description.
+ private Vector<String> mErrorDescr = null;
+
+ // any request resulting data;
+ Object mResult = null;
+ Hashtable<String, Object> mResults = new Hashtable<String, Object>();
+
+ /**
+ * Constructor
+ */
+ public CMSRequest() {
+ }
+
+ // set methods use by servlets.
+
+ /**
+ * set the HTTP parameters
+ */
+ public void setHttpParams(IArgBlock httpParams) {
+ mHttpParams = httpParams;
+ }
+
+ /**
+ * set the Request aobject associated with this session
+ */
+ public void setIRequest(IRequest request) {
+ mRequest = request;
+ }
+
+ /**
+ * set the HTTP Request object associated with this session
+ */
+ public void setHttpReq(HttpServletRequest httpReq) {
+ mHttpReq = httpReq;
+ }
+
+ /**
+ * set the HTTP Response object which is used to create the
+ * HTTP response which is sent back to the user
+ */
+ public void setHttpResp(HttpServletResponse httpResp) {
+ mHttpResp = httpResp;
+ }
+
+ /**
+ * set the servlet configuration. The servlet configuration is
+ * read from the WEB-APPS/web.xml file under the &lt;servlet&gt;
+ * XML definition. The parameters are delimited by init-param
+ * param-name/param-value options as described in the servlet
+ * documentation.
+ */
+ public void setServletConfig(ServletConfig servletConfig) {
+ mServletConfig = servletConfig;
+ }
+
+ /*
+ * set the servlet context. the servletcontext has detail
+ * about the currently running request
+ */
+ public void setServletContext(ServletContext servletContext) {
+ mServletContext = servletContext;
+ }
+
+ /**
+ * Set request status.
+ *
+ * @param status request status. Allowed values are
+ * UNAUTHORIZED, SUCCESS, REJECTED, PENDING, ERROR, SVC_PENDING
+ * @throws IllegalArgumentException if status is not one of the above values
+ */
+ public void setStatus(Integer status) {
+ if (!status.equals(UNAUTHORIZED) &&
+ !status.equals(SUCCESS) &&
+ !status.equals(REJECTED) &&
+ !status.equals(PENDING) &&
+ !status.equals(ERROR) &&
+ !status.equals(SVC_PENDING) &&
+ !status.equals(EXCEPTION)) {
+ throw new IllegalArgumentException(CMS.getLogMessage("CMSGW_BAD_REQ_STATUS"));
+ }
+ mStatus = status;
+ }
+
+ public void setError(EBaseException error) {
+ mError = error.toString();
+ }
+
+ public void setError(String error) {
+ mError = error;
+ }
+
+ public void setErrorDescription(String descr) {
+ if (mErrorDescr == null)
+ mErrorDescr = new Vector<String>();
+ mErrorDescr.addElement(descr);
+ }
+
+ public void setResult(Object result) {
+ mResult = result;
+ mResults.put(RESULT, result);
+ }
+
+ public void setResult(String name, Object result) {
+ mResults.put(name, result);
+ }
+
+ public IArgBlock getHttpParams() {
+ return mHttpParams;
+ }
+
+ public HttpServletRequest getHttpReq() {
+ return mHttpReq;
+ }
+
+ public HttpServletResponse getHttpResp() {
+ return mHttpResp;
+ }
+
+ public ServletConfig getServletConfig() {
+ return mServletConfig;
+ }
+
+ public ServletContext getServletContext() {
+ return mServletContext;
+ }
+
+ public IRequest getIRequest() {
+ return mRequest;
+ }
+
+ public Integer getStatus() {
+ return mStatus;
+ }
+
+ public String getError() {
+ return mError;
+ }
+
+ public Vector<String> getErrorDescr() {
+ return mErrorDescr;
+ }
+
+ public Object getResult() {
+ return mResult;
+ }
+
+ public Object getResult(String name) {
+ return mResults.get(name);
+ }
+
+ public void setReason(String reason) {
+ this.reason = reason;
+ }
+
+ public String getReason() {
+ return reason;
+ }
+
+ // handy routines for IRequest.
+
+ public void setExtData(String type, String value) {
+ if (mRequest != null) {
+ mRequest.setExtData(type, value);
+ }
+ }
+
+ public String getExtData(String type) {
+ if (mRequest != null) {
+ return mRequest.getExtDataInString(type);
+ } else {
+ return null;
+ }
+ }
+
+ // policy errors; set on rejection or possibly deferral.
+ public Vector<String> getPolicyMessages() {
+ if (mRequest != null) {
+ return mRequest.getExtDataInStringVector(IRequest.ERRORS);
+ }
+ return null;
+ }
+
+ /**
+ * set default CMS status according to IRequest status.
+ */
+ public void setIRequestStatus() throws EBaseException {
+ if (mRequest == null) {
+ EBaseException e =
+ new ECMSGWException(CMS.getLogMessage("CMSGW_MISSING_REQUEST"));
+
+ throw e;
+ }
+
+ RequestStatus status = mRequest.getRequestStatus();
+
+ // completed equivalent to success by default.
+ if (status == RequestStatus.COMPLETE) {
+ mStatus = ICMSRequest.SUCCESS;
+ return;
+ }
+ // unexpected resulting request status.
+ if (status == RequestStatus.REJECTED) {
+ mStatus = ICMSRequest.REJECTED;
+ return;
+ } // pending or service pending.
+ else if (status == RequestStatus.PENDING) {
+ mStatus = ICMSRequest.PENDING;
+ return;
+ } else if (status == RequestStatus.SVC_PENDING) {
+ mStatus = ICMSRequest.SVC_PENDING;
+ return;
+ } else {
+ RequestId reqId = mRequest.getRequestId();
+
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_UNEXPECTED_REQUEST_STATUS_2",
+ status.toString(), reqId.toString()));
+ }
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMSTemplate.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMSTemplate.java
new file mode 100644
index 000000000..336032dd3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMSTemplate.java
@@ -0,0 +1,593 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import javax.servlet.ServletOutputStream;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * File templates. This implementation will take
+ * an HTML file with a special customer tag
+ * &lt;CMS_TEMPLATE&gt; and replace the tag with
+ * a series of javascript variable definitions
+ * (depending on the servlet)
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSTemplate extends CMSFile {
+
+ public static final String SUFFIX = ".template";
+
+ /*==========================================================
+ * variables
+ *==========================================================*/
+
+ /* public vaiables */
+ public String mPreOutput;
+ public String mPostOutput;
+ public static final String TEMPLATE_TAG = "<CMS_TEMPLATE>";
+
+ /* Character set for i18n */
+
+ /* Will be set by CMSServlet.getTemplate() */
+ private String mCharset = null;
+
+ /*==========================================================
+ * constructors
+ *==========================================================*/
+
+ /**
+ * Constructor
+ *
+ * @param file template file to load
+ * @param charset character set
+ * @throws IOException if the there was an error opening the file
+ */
+ public CMSTemplate(File file, String charset) throws IOException, EBaseException {
+ mCharset = charset;
+ mAbsPath = file.getAbsolutePath();
+ mLastModified = file.lastModified();
+ try {
+ init(file);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_CANT_LOAD_TEMPLATE", mAbsPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_LOADING_TEMPLATE"));
+ }
+ String content = mPreOutput + mPostOutput;
+
+ mContent = content.getBytes(mCharset);
+ }
+
+ /*==========================================================
+ * public methods
+ *==========================================================*/
+
+ /* *
+ * Load the form from the file and setup the
+ * pre/post output buffer if it is a template
+ * file. Otherwise, only post output buffer is
+ * filled.
+ * @param template the template file to load
+ * @return true if successful
+ */
+ public boolean init(File template) throws EBaseException, IOException {
+ /* load template */
+ String content = loadFile(template);
+
+ if (content == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_TEMPLATE_EMPTY", mAbsPath));
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_TEMPLATE_NO_CONTENT_1", mAbsPath));
+ }
+
+ /* if template file, find template tag substring and set
+ * pre/post output string
+ */
+ int location = content.indexOf(TEMPLATE_TAG);
+
+ if (location == -1) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage(
+ "CMSGW_TEMPLATE_MISSING", mAbsPath, TEMPLATE_TAG));
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_MISSING_TEMPLATE_TAG_2",
+ TEMPLATE_TAG, mAbsPath));
+ }
+ mPreOutput = content.substring(0, location);
+ mPostOutput = content.substring(TEMPLATE_TAG.length() + location);
+
+ return true;
+ }
+
+ /**
+ * Write a javascript representation of 'input'
+ * surrounded by SCRIPT tags to the outputstream
+ *
+ * @param rout the outputstream to write to
+ * @param input the parameters to write
+ */
+ public void renderOutput(OutputStream rout, CMSTemplateParams input)
+ throws IOException {
+ Enumeration<String> e = null;
+ Enumeration<IArgBlock> q = null;
+ IArgBlock r = null;
+ CMSTemplateParams data = input;
+
+ try (HTTPOutputStreamWriter http_out = (mCharset == null ?
+ new HTTPOutputStreamWriter(rout): new HTTPOutputStreamWriter(rout, mCharset))) {
+ templateLine out = new templateLine();
+
+ // Output the prolog
+ out.print(mPreOutput);
+
+ // Output the header data
+ out.println("<SCRIPT LANGUAGE=\"JavaScript\">");
+ out.println("var header = new Object();");
+ out.println("var fixed = new Object();");
+ out.println("var recordSet = new Array;");
+ out.println("var result = new Object();");
+
+ // hack
+ out.println("var httpParamsCount = 0;");
+ out.println("var httpHeadersCount = 0;");
+ out.println("var authTokenCount = 0;");
+ out.println("var serverAttrsCount = 0;");
+ out.println("header.HTTP_PARAMS = new Array;");
+ out.println("header.HTTP_HEADERS = new Array;");
+ out.println("header.AUTH_TOKEN = new Array;");
+ out.println("header.SERVER_ATTRS = new Array;");
+
+ r = data.getHeader();
+ if (r != null) {
+ e = r.elements();
+ while (e.hasMoreElements()) {
+ String n = e.nextElement();
+ Object v = r.getValue(n);
+
+ out.println("header." + n + " = " + renderValue(v) + ";");
+ }
+ }
+
+ // Output the fixed data
+ r = data.getFixed();
+ if (r != null) {
+ e = r.elements();
+ while (e.hasMoreElements()) {
+ String n = e.nextElement();
+ Object v = r.getValue(n);
+
+ out.println("fixed." + n + " = " + renderValue(v) + ";");
+ }
+ }
+
+ // Output the query data
+ q = data.queryRecords();
+ if (q != null && q.hasMoreElements()) {
+ out.println("var recordCount = 0;");
+ out.println("var record;");
+ while (q.hasMoreElements()) {
+ out.println("record = new Object;");
+ out.println("record.HTTP_PARAMS = new Array;");
+ out.println("record.HTTP_HEADERS = new Array;");
+ out.println("record.AUTH_TOKEN = new Array;");
+ out.println("record.SERVER_ATTRS = new Array;");
+
+ // Get a query record
+ r = q.nextElement();
+ e = r.elements();
+ while (e.hasMoreElements()) {
+ String n = e.nextElement();
+ Object v = r.getValue(n);
+
+ out.println("record." + n + "=" + renderValue(v) + ";");
+ }
+ out.println("recordSet[recordCount++] = record;");
+ }
+ out.println("record.recordSet = recordSet;");
+ }
+
+ //if (headerBlock)
+ out.println("result.header = header;");
+ //if (fixedBlock)
+ out.println("result.fixed = fixed;");
+ //if (queryBlock)
+ out.println("result.recordSet = recordSet;");
+ out.println("</SCRIPT>");
+ out.println(mPostOutput);
+ http_out.print(out.toString());
+
+ } catch (EBaseException ex) {
+ throw new IOException(ex.getMessage());
+ }
+ }
+
+ /**
+ * Ouput the pre-amble HTML Header including
+ * the pre-output buffer.
+ *
+ * @param out output stream specified
+ * @return success or error
+ */
+ public boolean outputProlog(PrintWriter out) {
+
+ //Debug.trace("FormCache:outputProlog");
+
+ /* output pre-output buffer */
+ out.print(mPreOutput);
+
+ /* output JavaScript variables and objects */
+ out.println("<SCRIPT LANGUAGE=\"JavaScript\">");
+ out.println("var header = new Object();");
+ out.println("var result = new Object();");
+
+ return true;
+ }
+
+ /**
+ * Output the post HTML tags and post-output
+ * buffer.
+ *
+ * @param out output stream specified
+ * @return success or error
+ */
+ public boolean outputEpilog(PrintWriter out) {
+
+ out.println("</SCRIPT>");
+ out.println(mPostOutput);
+
+ return true;
+ }
+
+ /**
+ * @return full path of template
+ */
+ public String getTemplateName() {
+ return mAbsPath;
+ }
+
+ // inherit getabspath, getContent, get last access and set last access
+
+ /*==========================================================
+ * private methods
+ *==========================================================*/
+
+ /* load file into string */
+ private String loadFile(File template) throws IOException {
+
+ // Debug.trace("FormCache:loadFile");
+
+ /* create input stream, can throw IOException */
+ FileInputStream inStream = new FileInputStream(template);
+ InputStreamReader inReader = new InputStreamReader(inStream, mCharset);
+ ;
+ BufferedReader in = new BufferedReader(inReader);
+ StringBuffer buf = new StringBuffer();
+ String line;
+
+ while ((line = in.readLine()) != null) {
+ buf.append(line);
+ buf.append('\n');
+ }
+ try {
+ in.close();
+ inStream.close();
+ } catch (IOException e) {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_ERR_CLOSE_TEMPL_FILE", mAbsPath, e.getMessage()));
+ }
+ return buf.toString();
+ }
+
+ private String renderValue(Object v) {
+ String s = null;
+
+ // Figure out the type of object
+ if (v instanceof IRawJS) {
+ s = v.toString();
+ } else if (v instanceof String) {
+ if (v.equals(""))
+ s = "null";
+ else
+ s = "\"" + escapeJavaScriptString((String) v) + "\"";
+ } else if (v instanceof Integer) {
+ s = ((Integer) v).toString();
+ } else if (v instanceof Boolean) {
+
+ if (((Boolean) v).booleanValue() == true) {
+ s = "true";
+ } else {
+ s = "false";
+ }
+ } else if (v instanceof BigInteger) {
+ s = ((BigInteger) v).toString(10);
+ } else if (v instanceof Character &&
+ ((Character) v).equals(Character.valueOf((char) 0))) {
+ s = "null";
+ } else {
+ s = "\"" + v.toString() + "\"";
+ }
+
+ return s;
+ }
+
+ /**
+ * Escape the contents of src string in preparation to be enclosed in
+ * double quotes as a JavaScript String Literal within an <script>
+ * portion of an HTML document.
+ * stevep - performance improvements - about 4 times faster than before.
+ */
+ public static String escapeJavaScriptString(String v) {
+ int l = v.length();
+ char in[] = new char[l];
+ char out[] = new char[l * 4];
+ int j = 0;
+
+ v.getChars(0, l, in, 0);
+
+ for (int i = 0; i < l; i++) {
+ char c = in[i];
+
+ if ((c > 0x23) && (c != 0x5c) && (c != 0x3c) && (c != 0x3e)) {
+ out[j++] = c;
+ continue;
+ }
+
+ if ((c == 0x5c) && ((i + 1) < l) && (in[i + 1] == 'n' ||
+ in[i + 1] == 'r' || in[i + 1] == 'f' || in[i + 1] == 't' ||
+ in[i + 1] == '<' || in[i + 1] == '>' ||
+ in[i + 1] == '\"' || in[i + 1] == '\'' || in[i + 1] == '\\')) {
+ if (in[i + 1] == 'x' && ((i + 3) < l) && in[i + 2] == '3' &&
+ (in[i + 3] == 'c' || in[i + 3] == 'e')) {
+ out[j++] = '\\';
+ out[j++] = in[i + 1];
+ out[j++] = in[i + 2];
+ out[j++] = in[i + 3];
+ i += 3;
+ } else {
+ out[j++] = '\\';
+ out[j++] = in[i + 1];
+ i++;
+ }
+ continue;
+ }
+
+ switch (c) {
+ case '\n':
+ out[j++] = '\\';
+ out[j++] = 'n';
+ break;
+
+ case '\\':
+ out[j++] = '\\';
+ out[j++] = '\\';
+ break;
+
+ case '\"':
+ out[j++] = '\\';
+ out[j++] = '\"';
+ break;
+
+ case '\r':
+ out[j++] = '\\';
+ out[j++] = 'r';
+ break;
+
+ case '\f':
+ out[j++] = '\\';
+ out[j++] = 'f';
+ break;
+
+ case '\t':
+ out[j++] = '\\';
+ out[j++] = 't';
+ break;
+
+ case '<':
+ out[j++] = '\\';
+ out[j++] = 'x';
+ out[j++] = '3';
+ out[j++] = 'c';
+ break;
+
+ case '>':
+ out[j++] = '\\';
+ out[j++] = 'x';
+ out[j++] = '3';
+ out[j++] = 'e';
+ break;
+
+ default:
+ out[j++] = c;
+ }
+ }
+ return new String(out, 0, j);
+ }
+
+ /**
+ * Like escapeJavaScriptString(String s) but also escape '[' for
+ * HTML processing.
+ */
+ public static String escapeJavaScriptStringHTML(String v) {
+ int l = v.length();
+ char in[] = new char[l];
+ char out[] = new char[l * 4];
+ int j = 0;
+
+ v.getChars(0, l, in, 0);
+
+ for (int i = 0; i < l; i++) {
+ char c = in[i];
+
+ if (c > 0x5C) {
+ out[j++] = c;
+ continue;
+ }
+
+ if ((c == 0x5c) && ((i + 1) < l) && (in[i + 1] == 'n' ||
+ in[i + 1] == 'r' || in[i + 1] == 'f' || in[i + 1] == 't' ||
+ in[i + 1] == '<' || in[i + 1] == '>' ||
+ in[i + 1] == '\"' || in[i + 1] == '\'' || in[i + 1] == '\\')) {
+ if (in[i + 1] == 'x' && ((i + 3) < l) && in[i + 2] == '3' &&
+ (in[i + 3] == 'c' || in[i + 3] == 'e')) {
+ out[j++] = '\\';
+ out[j++] = in[i + 1];
+ out[j++] = in[i + 2];
+ out[j++] = in[i + 3];
+ i += 3;
+ } else {
+ out[j++] = '\\';
+ out[j++] = in[i + 1];
+ i++;
+ }
+ continue;
+ }
+
+ switch (c) {
+ case '\n':
+ out[j++] = '\\';
+ out[j++] = 'n';
+ break;
+
+ case '\\':
+ out[j++] = '\\';
+ out[j++] = '\\';
+ break;
+
+ case '\"':
+ out[j++] = '\\';
+ out[j++] = '\"';
+ break;
+
+ case '\r':
+ out[j++] = '\\';
+ out[j++] = 'r';
+ break;
+
+ case '\f':
+ out[j++] = '\\';
+ out[j++] = 'f';
+ break;
+
+ case '\t':
+ out[j++] = '\\';
+ out[j++] = 't';
+ break;
+
+ case '<':
+ out[j++] = '\\';
+ out[j++] = 'x';
+ out[j++] = '3';
+ out[j++] = 'c';
+ break;
+ case '>':
+ out[j++] = '\\';
+ out[j++] = 'x';
+ out[j++] = '3';
+ out[j++] = 'e';
+ break;
+
+ default:
+ out[j++] = c;
+ }
+ }
+ return new String(out, 0, j);
+ }
+
+ /**
+ * for debugging, return contents that would've been outputed.
+ */
+ public String getOutput(CMSTemplateParams input)
+ throws IOException {
+ debugOutputStream out = new debugOutputStream();
+
+ renderOutput(out, input);
+ return out.toString();
+ }
+
+ private class HTTPOutputStreamWriter extends OutputStreamWriter {
+ public HTTPOutputStreamWriter(OutputStream out)
+ throws UnsupportedEncodingException {
+ super(out);
+ }
+
+ public HTTPOutputStreamWriter(OutputStream out, String enc)
+ throws UnsupportedEncodingException {
+ super(out, enc);
+ }
+
+ public void print(String s) throws IOException {
+ write(s, 0, s.length());
+ flush();
+ return;
+ }
+ }
+
+ private class templateLine {
+ private StringBuffer s = new StringBuffer();
+
+ void println(String p) {
+ s.append('\n');
+ s.append(p);
+ }
+
+ void print(String p) {
+ s.append(p);
+ }
+
+ public String toString() {
+ return s.toString();
+ }
+
+ }
+
+ private static class debugOutputStream extends ServletOutputStream {
+ private StringWriter mStringWriter = new StringWriter();
+
+ public debugOutputStream() {
+ super();
+ }
+
+ public void write(int b) throws IOException {
+ mStringWriter.write(b);
+ }
+
+ public String toString() {
+ return mStringWriter.toString();
+ }
+
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMSTemplateParams.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMSTemplateParams.java
new file mode 100644
index 000000000..50c5e824f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMSTemplateParams.java
@@ -0,0 +1,70 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.netscape.certsrv.base.IArgBlock;
+
+/**
+ * Holds template parameters
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMSTemplateParams {
+ private IArgBlock mHeader = null;
+ private IArgBlock mFixed = null;
+ private Vector<IArgBlock> mRepeat = new Vector<IArgBlock>();
+
+ public CMSTemplateParams() {
+ }
+
+ public CMSTemplateParams(IArgBlock header, IArgBlock fixed) {
+ mHeader = header;
+ mFixed = fixed;
+ }
+
+ public void setHeader(IArgBlock h) {
+ mHeader = h;
+ }
+
+ public IArgBlock getHeader() {
+ return mHeader;
+ }
+
+ public void setFixed(IArgBlock f) {
+ mFixed = f;
+ }
+
+ public IArgBlock getFixed() {
+ return mFixed;
+ }
+
+ public void addRepeatRecord(IArgBlock r) {
+ mRepeat.addElement(r);
+ }
+
+ public void clearRepeatRecords() {
+ mRepeat = new Vector<IArgBlock>();
+ }
+
+ public Enumeration<IArgBlock> queryRecords() {
+ return mRepeat.elements();
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/ECMSGWException.java b/base/server/cms/src/com/netscape/cms/servlet/common/ECMSGWException.java
new file mode 100644
index 000000000..2c24c112a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/ECMSGWException.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import com.netscape.certsrv.base.EBaseException;
+
+/**
+ * A class represents a CMS gateway exception.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class ECMSGWException extends EBaseException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7546430025179838019L;
+ /**
+ * CA resource class name.
+ */
+ private static final String CMSGW_RESOURCES = CMSGWResources.class.getName();
+
+ /**
+ * Constructs a CMS Gateway exception.
+ * <P>
+ */
+ public ECMSGWException(String msgFormat) {
+ super(msgFormat);
+ }
+
+ /**
+ * Constructs a CMSGW exception.
+ * <P>
+ */
+ public ECMSGWException(String msgFormat, String param) {
+ super(msgFormat, param);
+ }
+
+ /**
+ * Constructs a CMSGW exception.
+ * <P>
+ */
+ public ECMSGWException(String msgFormat, Exception e) {
+ super(msgFormat, e);
+ }
+
+ /**
+ * Constructs a CMSGW exception.
+ * <P>
+ */
+ public ECMSGWException(String msgFormat, Object params[]) {
+ super(msgFormat, params);
+ }
+
+ protected String getBundleName() {
+ return CMSGW_RESOURCES;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/GenErrorTemplateFiller.java b/base/server/cms/src/com/netscape/cms/servlet/common/GenErrorTemplateFiller.java
new file mode 100644
index 000000000..29e106ae9
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/GenErrorTemplateFiller.java
@@ -0,0 +1,102 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+
+/**
+ * Default error template filler
+ *
+ * @version $Revision$, $Date$
+ */
+public class GenErrorTemplateFiller implements ICMSTemplateFiller {
+ public GenErrorTemplateFiller() {
+ }
+
+ /**
+ * fill error details and description if any.
+ *
+ * @param cmsReq the CMS Request.
+ * @param authority the authority
+ * @param locale the locale of template.
+ * @param e unexpected error. ignored.
+ */
+ public CMSTemplateParams getTemplateParams(
+ CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) {
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams params = new CMSTemplateParams(null, fixed);
+
+ // request status if any.
+ if (cmsReq != null) {
+ Integer sts = cmsReq.getStatus();
+
+ if (sts != null)
+ fixed.set(ICMSTemplateFiller.REQUEST_STATUS, sts.toString());
+ } else {
+ CMS.debug("GenErrorTemplateFiller::getTemplateParams() - " +
+ "cmsReq is null!");
+ return null;
+ }
+
+ // error
+ String ex = cmsReq.getError();
+
+ // Changed by beomsuk
+ /*if (ex == null)
+ ex = new EBaseException(CMS.getLogMessage("BASE_UNKNOWN_ERROR"));
+ fixed.set(ICMSTemplateFiller.ERROR, ex.toString(locale));
+ */
+ if ((ex == null) && (cmsReq.getReason() == null))
+ ex = new EBaseException(CMS.getLogMessage("BASE_UNKNOWN_ERROR")).toString();
+ else if (ex != null)
+ fixed.set(ICMSTemplateFiller.ERROR, ex);
+ else if (cmsReq.getReason() != null)
+ fixed.set(ICMSTemplateFiller.ERROR, cmsReq.getReason());
+ // Change end
+
+ // error description if any.
+ Vector<String> descr = cmsReq.getErrorDescr();
+
+ if (descr != null) {
+ Enumeration<String> num = descr.elements();
+
+ while (num.hasMoreElements()) {
+ String elem = num.nextElement();
+ //System.out.println("Setting description "+elem.toString());
+ IArgBlock argBlock = CMS.createArgBlock();
+
+ argBlock.set(ICMSTemplateFiller.ERROR_DESCR,
+ elem);
+ params.addRepeatRecord(argBlock);
+ }
+ }
+
+ // this authority
+ if (authority != null)
+ fixed.set(ICMSTemplateFiller.AUTHORITY,
+ authority.getOfficialName());
+ return params;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java b/base/server/cms/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java
new file mode 100644
index 000000000..83a2d8cf0
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java
@@ -0,0 +1,286 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Date;
+import java.util.Locale;
+
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
+import org.mozilla.jss.asn1.OCTET_STRING;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.asn1.SET;
+import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.crypto.SignatureAlgorithm;
+import org.mozilla.jss.pkix.cmc.CMCStatusInfo;
+import org.mozilla.jss.pkix.cmc.OtherInfo;
+import org.mozilla.jss.pkix.cmc.PendInfo;
+import org.mozilla.jss.pkix.cmc.ResponseBody;
+import org.mozilla.jss.pkix.cmc.TaggedAttribute;
+import org.mozilla.jss.pkix.cms.ContentInfo;
+import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo;
+import org.mozilla.jss.pkix.cms.IssuerAndSerialNumber;
+import org.mozilla.jss.pkix.cms.SignedData;
+import org.mozilla.jss.pkix.cms.SignerIdentifier;
+import org.mozilla.jss.pkix.cms.SignerInfo;
+import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier;
+import org.mozilla.jss.pkix.primitive.Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestId;
+
+/**
+ * default Pending template filler
+ *
+ * @version $Revision$, $Date$
+ */
+public class GenPendingTemplateFiller implements ICMSTemplateFiller {
+ public static String FULL_RESPONSE = "cmcFullEnrollmentResponse";
+
+ public GenPendingTemplateFiller() {
+ }
+
+ /**
+ * fill error details and description if any.
+ *
+ * @param cmsReq CMS Request
+ * @param authority this authority
+ * @param locale locale of template.
+ * @param e unexpected exception e. ignored.
+ */
+ public CMSTemplateParams getTemplateParams(
+ CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) {
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams params = new CMSTemplateParams(null, fixed);
+
+ if (cmsReq == null) {
+ return null;
+ }
+
+ // request status if any.
+ Integer sts = cmsReq.getStatus();
+
+ if (sts != null)
+ fixed.set(ICMSTemplateFiller.REQUEST_STATUS, sts.toString());
+
+ // request id
+ IRequest req = cmsReq.getIRequest();
+
+ if (req != null) {
+ RequestId reqId = req.getRequestId();
+
+ fixed.set(ICMSTemplateFiller.REQUEST_ID, reqId);
+ // set pendInfo, CMCStatusInfo
+ IArgBlock httpParams = cmsReq.getHttpParams();
+
+ if (doFullResponse(httpParams)) {
+ SEQUENCE controlSeq = new SEQUENCE();
+ int bpid = 1;
+ PendInfo pendInfo = new PendInfo(reqId.toString(), new
+ Date());
+ OtherInfo otherInfo = new
+ OtherInfo(OtherInfo.PEND, null, pendInfo);
+ SEQUENCE bpids = new SEQUENCE();
+ String[] reqIdArray =
+ req.getExtDataInStringArray(IRequest.CMC_REQIDS);
+
+ for (int i = 0; i < reqIdArray.length; i++) {
+ bpids.addElement(new INTEGER(reqIdArray[i]));
+ }
+ CMCStatusInfo cmcStatusInfo = new
+ CMCStatusInfo(CMCStatusInfo.PENDING, bpids,
+ (String) null, otherInfo);
+ TaggedAttribute ta = new TaggedAttribute(new
+ INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo,
+ cmcStatusInfo);
+
+ controlSeq.addElement(ta);
+ // copy transactionID, senderNonce,
+ // create recipientNonce
+ // create responseInfo if regInfo exist
+ String[] transIds =
+ req.getExtDataInStringArray(IRequest.CMC_TRANSID);
+ SET ids = new SET();
+
+ for (int i = 0; i < transIds.length; i++) {
+ ids.addElement(new INTEGER(transIds[i]));
+ }
+ ta = new TaggedAttribute(new
+ INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_transactionId,
+ ids);
+ controlSeq.addElement(ta);
+
+ String[] senderNonce = req.getExtDataInStringArray(IRequest.CMC_SENDERNONCE);
+ SET nonces = new SET();
+
+ for (int i = 0; i < senderNonce.length; i++) {
+ nonces.addElement(new OCTET_STRING(senderNonce[i].getBytes()));
+ }
+ ta = new TaggedAttribute(new
+ INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_recipientNonce,
+ nonces);
+ controlSeq.addElement(ta);
+ req.setExtData(IRequest.CMC_RECIPIENTNONCE, senderNonce);
+
+ Date date = CMS.getCurrentDate();
+ String salt = "lala123" + date.toString();
+ byte[] dig;
+
+ try {
+ MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+
+ dig = SHA1Digest.digest(salt.getBytes());
+ } catch (NoSuchAlgorithmException ex) {
+ dig = salt.getBytes();
+ }
+ String b64E = CMS.BtoA(dig);
+ String[] newNonce = { b64E };
+
+ ta = new TaggedAttribute(new
+ INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_senderNonce,
+ new OCTET_STRING(newNonce[0].getBytes()));
+ controlSeq.addElement(ta);
+ req.setExtData(IRequest.CMC_SENDERNONCE, newNonce);
+
+ ResponseBody rb = new ResponseBody(controlSeq, new
+ SEQUENCE(), new
+ SEQUENCE());
+ EncapsulatedContentInfo ci = new
+ EncapsulatedContentInfo(OBJECT_IDENTIFIER.id_cct_PKIResponse,
+ rb);
+ org.mozilla.jss.crypto.X509Certificate x509cert = null;
+
+ if (authority instanceof ICertificateAuthority) {
+ x509cert = ((ICertificateAuthority) authority).getCaX509Cert();
+ } else if (authority instanceof IRegistrationAuthority) {
+ x509cert = ((IRegistrationAuthority) authority).getRACert();
+ }
+ if (x509cert == null)
+ return params;
+ try {
+ X509CertImpl cert = new X509CertImpl(x509cert.getEncoded());
+ ByteArrayInputStream issuer1 = new
+ ByteArrayInputStream(((X500Name) cert.getIssuerDN()).getEncoded());
+ Name issuer = (Name) Name.getTemplate().decode(issuer1);
+ IssuerAndSerialNumber ias = new
+ IssuerAndSerialNumber(issuer, new INTEGER(cert.getSerialNumber().toString()));
+ SignerIdentifier si = new
+ SignerIdentifier(SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null);
+
+ // SHA1 is the default digest Alg for now.
+ DigestAlgorithm digestAlg = null;
+ SignatureAlgorithm signAlg = null;
+ org.mozilla.jss.crypto.PrivateKey privKey = CryptoManager.getInstance().findPrivKeyByCert(x509cert);
+ org.mozilla.jss.crypto.PrivateKey.Type keyType = privKey.getType();
+
+ if (keyType.equals(org.mozilla.jss.crypto.PrivateKey.RSA)) {
+ signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest;
+ } else if (keyType.equals(org.mozilla.jss.crypto.PrivateKey.DSA)) {
+ signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest;
+ } else {
+ CMS.debug("GenPendingTemplateFiller::getTemplateParams() - "
+ + "keyType " + keyType.toString()
+ + " is unsupported!");
+ return null;
+ }
+
+ MessageDigest SHADigest = null;
+ byte[] digest = null;
+
+ try {
+ SHADigest = MessageDigest.getInstance("SHA1");
+ digestAlg = DigestAlgorithm.SHA1;
+
+ ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+
+ rb.encode(ostream);
+ digest = SHADigest.digest(ostream.toByteArray());
+ } catch (NoSuchAlgorithmException ex) {
+ //log("digest fail");
+ }
+
+ SignerInfo signInfo = new
+ SignerInfo(si, null, null,
+ OBJECT_IDENTIFIER.id_cct_PKIResponse,
+ digest, signAlg,
+ privKey);
+ SET signInfos = new SET();
+
+ signInfos.addElement(signInfo);
+
+ SET digestAlgs = new SET();
+
+ if (digestAlg != null) {
+ AlgorithmIdentifier ai = new
+ AlgorithmIdentifier(digestAlg.toOID(),
+ null);
+
+ digestAlgs.addElement(ai);
+ }
+
+ SignedData fResponse = new
+ SignedData(digestAlgs, ci,
+ null, null, signInfos);
+ ContentInfo fullResponse = new
+ ContentInfo(ContentInfo.SIGNED_DATA, fResponse);
+ ByteArrayOutputStream ostream = new
+ ByteArrayOutputStream();
+
+ fullResponse.encode(ostream);
+ byte[] fr = ostream.toByteArray();
+
+ fixed.set(FULL_RESPONSE, CMS.BtoA(fr));
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+ // this authority
+ if (authority != null)
+ fixed.set(ICMSTemplateFiller.AUTHORITY,
+ authority.getOfficialName());
+ return params;
+ }
+
+ /**
+ * handy routine to check if client want full enrollment response
+ */
+ public static boolean doFullResponse(IArgBlock httpParams) {
+ if (httpParams.getValueAsBoolean("fullResponse", false))
+ return true;
+ else
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/GenRejectedTemplateFiller.java b/base/server/cms/src/com/netscape/cms/servlet/common/GenRejectedTemplateFiller.java
new file mode 100644
index 000000000..95631ba5e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/GenRejectedTemplateFiller.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * default Service Pending template filler
+ *
+ * @version $Revision$, $Date$
+ */
+public class GenRejectedTemplateFiller implements ICMSTemplateFiller {
+ public final static String POLICY_MESSAGE = "policyMessage";
+
+ public GenRejectedTemplateFiller() {
+ }
+
+ /**
+ * @param cmsReq CMS Request
+ * @param authority this authority
+ * @param locale locale of template.
+ * @param e unexpected exception e. ignored.
+ */
+ public CMSTemplateParams getTemplateParams(
+ CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) {
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams params = new CMSTemplateParams(null, fixed);
+
+ // request status if any.
+ if (cmsReq != null) {
+ Integer sts = cmsReq.getStatus();
+
+ if (sts != null)
+ fixed.set(ICMSTemplateFiller.REQUEST_STATUS, sts.toString());
+ } else {
+ CMS.debug("GenRejectedTemplateFiller::getTemplateParams() - " +
+ "cmsReq is null!");
+ return null;
+ }
+
+ // request id
+ IRequest req = cmsReq.getIRequest();
+
+ if (req != null) {
+ fixed.set(ICMSTemplateFiller.REQUEST_ID, req.getRequestId());
+
+ // policy errors (rejection reasons)
+ Vector<String> messages = req.getExtDataInStringVector(IRequest.ERRORS);
+
+ if (messages != null) {
+ Enumeration<String> msgs = messages.elements();
+
+ while (msgs.hasMoreElements()) {
+ String ex = msgs.nextElement();
+ IArgBlock messageArgBlock = CMS.createArgBlock();
+
+ messageArgBlock.set(POLICY_MESSAGE, ex);
+ params.addRepeatRecord(messageArgBlock);
+ }
+ }
+ }
+
+ // this authority
+
+ if (authority != null)
+ fixed.set(ICMSTemplateFiller.AUTHORITY,
+ authority.getOfficialName());
+ return params;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/GenSuccessTemplateFiller.java b/base/server/cms/src/com/netscape/cms/servlet/common/GenSuccessTemplateFiller.java
new file mode 100644
index 000000000..bf164977d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/GenSuccessTemplateFiller.java
@@ -0,0 +1,63 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.IArgBlock;
+
+/**
+ * default Success template filler
+ *
+ * @version $Revision$, $Date$
+ */
+public class GenSuccessTemplateFiller implements ICMSTemplateFiller {
+
+ public GenSuccessTemplateFiller() {
+ }
+
+ /**
+ * fill error details and description if any.
+ *
+ * @param cmsReq CMS Request
+ * @param authority this authority
+ * @param locale locale of template.
+ * @param e unexpected exception e. ignored.
+ */
+ public CMSTemplateParams getTemplateParams(
+ CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) {
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams params = new CMSTemplateParams(null, fixed);
+
+ // request status if any.
+ if (cmsReq != null) {
+ Integer sts = cmsReq.getStatus();
+
+ if (sts != null)
+ fixed.set(ICMSTemplateFiller.REQUEST_STATUS, sts.toString());
+ }
+
+ // this authority
+ if (authority != null)
+ fixed.set(ICMSTemplateFiller.AUTHORITY,
+ authority.getOfficialName());
+ return params;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/GenSvcPendingTemplateFiller.java b/base/server/cms/src/com/netscape/cms/servlet/common/GenSvcPendingTemplateFiller.java
new file mode 100644
index 000000000..275980cf1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/GenSvcPendingTemplateFiller.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * default Service Pending template filler
+ *
+ * @version $Revision$, $Date$
+ */
+public class GenSvcPendingTemplateFiller implements ICMSTemplateFiller {
+ public static final String REMOTE_AUTHORITY = "remoteAuthority";
+
+ public GenSvcPendingTemplateFiller() {
+ }
+
+ /**
+ * fill error details and description if any.
+ *
+ * @param cmsReq CMS Request
+ * @param authority this authority
+ * @param locale locale of template.
+ * @param e unexpected exception e. ignored.
+ */
+ public CMSTemplateParams getTemplateParams(
+ CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) {
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams params = new CMSTemplateParams(null, fixed);
+
+ // request status if any.
+ if (cmsReq != null) {
+ Integer sts = cmsReq.getStatus();
+
+ if (sts != null)
+ fixed.set(ICMSTemplateFiller.REQUEST_STATUS, sts.toString());
+
+ // request id
+ IRequest req = cmsReq.getIRequest();
+
+ if (req != null) {
+ fixed.set(ICMSTemplateFiller.REQUEST_ID, req.getRequestId());
+
+ // remote authority we're waiting for
+ String remoteAuthority =
+ req.getExtDataInString(IRequest.REMOTE_SERVICE_AUTHORITY);
+
+ if (remoteAuthority != null)
+ fixed.set(REMOTE_AUTHORITY, remoteAuthority);
+ }
+ }
+
+ // this authority
+ if (authority != null)
+ fixed.set(ICMSTemplateFiller.AUTHORITY,
+ authority.getOfficialName());
+ return params;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/GenUnauthorizedTemplateFiller.java b/base/server/cms/src/com/netscape/cms/servlet/common/GenUnauthorizedTemplateFiller.java
new file mode 100644
index 000000000..48a4a54ea
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/GenUnauthorizedTemplateFiller.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.IArgBlock;
+
+/**
+ * default Unauthorized template filler
+ *
+ * @version $Revision$, $Date$
+ */
+public class GenUnauthorizedTemplateFiller implements ICMSTemplateFiller {
+
+ public GenUnauthorizedTemplateFiller() {
+ }
+
+ /**
+ * fill error details and description if any.
+ *
+ * @param cmsReq CMS Request
+ * @param authority this authority
+ * @param locale locale of template.
+ * @param e unexpected exception e. ignored.
+ */
+ public CMSTemplateParams getTemplateParams(
+ CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) {
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams params = new CMSTemplateParams(null, fixed);
+
+ // request status if any.
+ if (cmsReq != null) {
+ Integer sts = cmsReq.getStatus();
+
+ if (sts != null)
+ fixed.set(ICMSTemplateFiller.REQUEST_STATUS, sts.toString());
+ }
+
+ // set unauthorized error
+ fixed.set(ICMSTemplateFiller.ERROR,
+ new ECMSGWException(CMS.getLogMessage("CMSGW_UNAUTHORIZED")));
+
+ // this authority
+ if (authority != null)
+ fixed.set(ICMSTemplateFiller.AUTHORITY,
+ authority.getOfficialName());
+ return params;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/GenUnexpectedErrorTemplateFiller.java b/base/server/cms/src/com/netscape/cms/servlet/common/GenUnexpectedErrorTemplateFiller.java
new file mode 100644
index 000000000..cf0b0a063
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/GenUnexpectedErrorTemplateFiller.java
@@ -0,0 +1,77 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+
+/**
+ * default unexpected error template filler
+ *
+ * @version $Revision$, $Date$
+ */
+public class GenUnexpectedErrorTemplateFiller implements ICMSTemplateFiller {
+
+ public GenUnexpectedErrorTemplateFiller() {
+ }
+
+ /**
+ * fill error details and description if any.
+ *
+ * @param cmsReq CMS Request
+ * @param authority this authority
+ * @param locale locale of template.
+ * @param e unexpected exception e. ignored.
+ */
+ public CMSTemplateParams getTemplateParams(
+ CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) {
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams params = new CMSTemplateParams(null, fixed);
+
+ // When an exception occurs the exit is non-local which probably
+ // will leave the requestStatus value set to something other
+ // than CMSRequest.EXCEPTION, so force the requestStatus to
+ // EXCEPTION since it must be that if we're here.
+ Integer sts = ICMSRequest.EXCEPTION;
+ if (cmsReq != null)
+ cmsReq.setStatus(sts);
+ fixed.set(ICMSTemplateFiller.REQUEST_STATUS, sts.toString());
+
+ // the unexpected error (exception)
+ if (e == null)
+ e = new EBaseException(CMS.getLogMessage("BASE_UNKNOWN_ERROR"));
+ String errMsg = null;
+
+ if (e instanceof EBaseException)
+ errMsg = ((EBaseException) e).toString(locale);
+ else
+ errMsg = e.toString();
+ fixed.set(ICMSTemplateFiller.EXCEPTION, errMsg);
+
+ // this authority
+ if (authority != null)
+ fixed.set(ICMSTemplateFiller.AUTHORITY,
+ authority.getOfficialName());
+ return params;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/ICMSTemplateFiller.java b/base/server/cms/src/com/netscape/cms/servlet/common/ICMSTemplateFiller.java
new file mode 100644
index 000000000..27bcf308d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/ICMSTemplateFiller.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.util.Locale;
+
+import com.netscape.certsrv.authority.IAuthority;
+
+/**
+ * This interface represents a template filler.
+ *
+ * @version $Revision$, $Date$
+ */
+public interface ICMSTemplateFiller {
+ // common template variables.
+ public final static String ERROR = "errorDetails";
+ public final static String ERROR_DESCR = "errorDescription";
+ public final static String EXCEPTION = "unexpectedError";
+
+ public static final String HOST = "host";
+ public static final String PORT = "port";
+ public static final String SCHEME = "scheme";
+
+ public static final String AUTHORITY = "authorityName";
+
+ public static final String REQUEST_STATUS = "requestStatus";
+
+ public static final String KEYREC_ID = "keyrecId";
+ public static final String REQUEST_ID = "requestId";
+
+ public CMSTemplateParams getTemplateParams(
+ CMSRequest cmsReq, IAuthority mAuthority, Locale locale, Exception e)
+ throws Exception;
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/IRawJS.java b/base/server/cms/src/com/netscape/cms/servlet/common/IRawJS.java
new file mode 100644
index 000000000..e5714f727
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/IRawJS.java
@@ -0,0 +1,26 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+/**
+ * This represents raw JS parameters.
+ *
+ * @version $Revision$, $Date$
+ */
+public interface IRawJS {
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/IndexTemplateFiller.java b/base/server/cms/src/com/netscape/cms/servlet/common/IndexTemplateFiller.java
new file mode 100644
index 000000000..53ddc4c88
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/IndexTemplateFiller.java
@@ -0,0 +1,111 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.ISubsystem;
+
+/**
+ * A class represents a certificate server kernel. This
+ * kernel contains a list of resident subsystems such
+ * as logging, security, remote administration. Additional
+ * subsystems can be loaded into this kernel by specifying
+ * parameters in the configuration store.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class IndexTemplateFiller implements ICMSTemplateFiller {
+
+ // input parameters
+
+ // output parameters
+ private final static String OUT_TYPE = "type";
+ private final static String OUT_ID = "id";
+ private final static String OUT_TOTAL_COUNT = "totalCount";
+
+ public IndexTemplateFiller() {
+ }
+
+ public CMSTemplateParams getTemplateParams(
+ CMSRequest cmsReq, IAuthority mAuthority, Locale locale, Exception e) {
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams params = new CMSTemplateParams(header, ctx);
+
+ ISubsystem ca = CMS.getSubsystem("ca");
+ ISubsystem ra = CMS.getSubsystem("ra");
+ ISubsystem kra = CMS.getSubsystem("kra");
+ ISubsystem ocsp = CMS.getSubsystem("ocsp");
+ ISubsystem tks = CMS.getSubsystem("tks");
+
+ IArgBlock rarg = null;
+ int count = 0;
+
+ if (ca != null) {
+ rarg = CMS.createArgBlock();
+ rarg.addStringValue(OUT_TYPE, "CertificateAuthority");
+ rarg.addStringValue(OUT_ID, "ca");
+ params.addRepeatRecord(rarg);
+ count++;
+ }
+ if (ra != null) {
+ rarg = CMS.createArgBlock();
+ rarg.addStringValue(OUT_TYPE, "RegistrationAuthority");
+ rarg.addStringValue(OUT_ID, "ra");
+ params.addRepeatRecord(rarg);
+ count++;
+ }
+ if (ocsp != null) {
+ rarg = CMS.createArgBlock();
+ rarg.addStringValue(OUT_TYPE, "OCSPAuthority");
+ rarg.addStringValue(OUT_ID, "ocsp");
+ params.addRepeatRecord(rarg);
+ count++;
+ }
+ if (kra != null) {
+ rarg = CMS.createArgBlock();
+ rarg.addStringValue(OUT_TYPE, "KeyRecoveryAuthority");
+ rarg.addStringValue(OUT_ID, "kra");
+ params.addRepeatRecord(rarg);
+ count++;
+ }
+ if (tks != null) {
+ rarg = CMS.createArgBlock();
+ rarg.addStringValue(OUT_TYPE, "TKSAuthority");
+ rarg.addStringValue(OUT_ID, "tks");
+ params.addRepeatRecord(rarg);
+ count++;
+ }
+ // information about what is selected is provided
+ // from the caller. This parameter (selected) is used
+ // by header servlet
+ try {
+ header.addStringValue("selected",
+ cmsReq.getHttpParams().getValueAsString("selected"));
+ } catch (EBaseException ex) {
+ }
+ header.addIntegerValue(OUT_TOTAL_COUNT, count);
+ return params;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/RawJS.java b/base/server/cms/src/com/netscape/cms/servlet/common/RawJS.java
new file mode 100644
index 000000000..03a4e7e2b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/RawJS.java
@@ -0,0 +1,35 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+/**
+ * This represents raw JS parameters.
+ *
+ * @version $Revision$, $Date$
+ */
+public class RawJS implements IRawJS {
+ private String mRawJSstr = null;
+
+ public RawJS(String s) {
+ mRawJSstr = s;
+ }
+
+ public String toString() {
+ return mRawJSstr;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/ServletUtils.java b/base/server/cms/src/com/netscape/cms/servlet/common/ServletUtils.java
new file mode 100644
index 000000000..a709b6b02
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/ServletUtils.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.common;
+
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authorization.IAuthzSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+
+/**
+ * Utility class
+ *
+ * @version $Revision$, $Date$
+ */
+public class ServletUtils {
+
+ public final static String AUTHZ_SRC_LDAP = "ldap";
+ public final static String AUTHZ_SRC_TYPE = "sourceType";
+ public final static String AUTHZ_CONFIG_STORE = "authz";
+ public final static String AUTHZ_SRC_XML = "web.xml";
+ public final static String PROP_AUTHZ_MGR = "AuthzMgr";
+ public final static String PROP_ACL = "ACLinfo";
+ public final static String AUTHZ_MGR_BASIC = "BasicAclAuthz";
+ public final static String AUTHZ_MGR_LDAP = "DirAclAuthz";
+
+ public static String initializeAuthz(ServletConfig sc,
+ IAuthzSubsystem authz, String id) throws ServletException {
+ String srcType = AUTHZ_SRC_LDAP;
+
+ try {
+ IConfigStore authzConfig =
+ CMS.getConfigStore().getSubStore(AUTHZ_CONFIG_STORE);
+
+ srcType = authzConfig.getString(AUTHZ_SRC_TYPE, AUTHZ_SRC_LDAP);
+ } catch (EBaseException e) {
+ CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_FAIL_SRC_TYPE"));
+ }
+
+ String aclMethod = null;
+
+ if (srcType.equalsIgnoreCase(AUTHZ_SRC_XML)) {
+ CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_INITED", ""));
+ aclMethod = sc.getInitParameter(PROP_AUTHZ_MGR);
+ if (aclMethod != null &&
+ aclMethod.equalsIgnoreCase(AUTHZ_MGR_BASIC)) {
+ String aclInfo = sc.getInitParameter(PROP_ACL);
+
+ if (aclInfo != null) {
+ try {
+ addACLInfo(authz, aclMethod, aclInfo);
+ } catch (EBaseException ee) {
+ throw new ServletException(
+ "failed to init authz info from xml config file");
+ }
+
+ CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_MGR_INIT_DONE",
+ id));
+ } else {
+ CMS.debug(CMS.getLogMessage(
+ "ADMIN_SRVLT_PROP_ACL_NOT_SPEC", PROP_ACL, id,
+ AUTHZ_MGR_LDAP));
+ }
+ } else {
+ CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_PROP_ACL_NOT_SPEC",
+ PROP_AUTHZ_MGR, id, AUTHZ_MGR_LDAP));
+ }
+ } else {
+ aclMethod = AUTHZ_MGR_LDAP;
+ CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_AUTH_LDAP_NOT_XML", id));
+ }
+
+ return aclMethod;
+ }
+
+ public static void addACLInfo(IAuthzSubsystem authz, String aclMethod,
+ String aclInfo) throws EBaseException {
+
+ StringTokenizer tokenizer = new StringTokenizer(aclInfo, "#");
+
+ while (tokenizer.hasMoreTokens()) {
+ String acl = tokenizer.nextToken();
+
+ authz.authzMgrAccessInit(aclMethod, acl);
+ }
+ }
+
+ public static String getACLMethod(String aclInfo, String authzMgr, String id) throws EBaseException {
+ String srcType = AUTHZ_SRC_LDAP;
+ IAuthzSubsystem authz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ);
+
+ try {
+ IConfigStore authzConfig = CMS.getConfigStore().getSubStore(AUTHZ_CONFIG_STORE);
+ srcType = authzConfig.getString(AUTHZ_SRC_TYPE, AUTHZ_SRC_LDAP);
+ } catch (EBaseException e) {
+ CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_FAIL_SRC_TYPE"));
+ }
+
+ String aclMethod = null;
+
+ if (srcType.equalsIgnoreCase(AUTHZ_SRC_XML)) {
+ CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_INITED", ""));
+ try {
+ aclMethod = authzMgr;
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ if (aclMethod != null && aclMethod.equalsIgnoreCase(AUTHZ_MGR_BASIC)) {
+ if (aclInfo != null) {
+ addACLInfo(authz, aclMethod, aclInfo);
+ CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_MGR_INIT_DONE", id));
+ } else {
+ CMS.debug(CMS.getLogMessage(
+ "ADMIN_SRVLT_PROP_ACL_NOT_SPEC", PROP_ACL, id,
+ AUTHZ_MGR_LDAP));
+ }
+ } else {
+ CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_PROP_ACL_NOT_SPEC",
+ PROP_AUTHZ_MGR, id, AUTHZ_MGR_LDAP));
+ }
+ } else {
+ aclMethod = AUTHZ_MGR_LDAP;
+ CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_AUTH_LDAP_NOT_XML", id));
+ }
+
+ return aclMethod;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/CloneServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/CloneServlet.java
new file mode 100644
index 000000000..5634cfd55
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/connector/CloneServlet.java
@@ -0,0 +1,580 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.connector;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthCredentials;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.connector.IPKIMessage;
+import com.netscape.certsrv.connector.IRequestEncoder;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+
+/**
+ * Clone servlet - part of the Clone Authority (CLA)
+ * processes Revoked certs from its dependant clone CAs
+ * service request and return status.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CloneServlet extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3474557834182380981L;
+ public static final String INFO = "Clone Servlet";
+ public final static String PROP_AUTHORITY = "authority";
+ protected ServletConfig mConfig = null;
+ protected IAuthority mAuthority = null;
+ protected IRequestEncoder mReqEncoder = null;
+ protected IAuthSubsystem mAuthSubsystem = null;
+ protected ILogger mLogger = CMS.getLogger();
+
+ public CloneServlet() {
+ }
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mConfig = sc;
+ String authority = sc.getInitParameter(PROP_AUTHORITY);
+
+ if (authority != null)
+ mAuthority = (IAuthority)
+ CMS.getSubsystem(authority);
+ mReqEncoder = CMS.getHttpRequestEncoder();
+ mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ }
+
+ public void service(HttpServletRequest req,
+ HttpServletResponse resp) throws ServletException, IOException {
+ boolean running_state = CMS.isInRunningState();
+
+ if (!running_state)
+ throw new IOException(
+ "CMS server is not ready to serve.");
+
+ CMSRequest cmsRequest = newCMSRequest();
+
+ // set argblock
+ cmsRequest.setHttpParams(CMS.createArgBlock(toHashtable(req)));
+
+ // set http request
+ cmsRequest.setHttpReq(req);
+
+ // set http response
+ cmsRequest.setHttpResp(resp);
+
+ // set servlet config.
+ cmsRequest.setServletConfig(mConfig);
+
+ // set servlet context.
+ cmsRequest.setServletContext(mConfig.getServletContext());
+
+ char[] content = null;
+ String encodedreq = null;
+ String method = null;
+ int len = -1;
+ IPKIMessage msg = null;
+ IPKIMessage replymsg = null;
+
+ // NOTE must read all bufer before redoing handshake for
+ // ssl client auth for client auth to work.
+
+ // get request method
+ method = req.getMethod();
+
+ // get content length
+ len = req.getContentLength();
+
+ // get content, a base 64 encoded serialized request.
+ if (len > 0) {
+ InputStream in = req.getInputStream();
+ InputStreamReader inreader = new InputStreamReader(in, "UTF8");
+ BufferedReader reader = new BufferedReader(inreader, len);
+
+ content = new char[len];
+ int done = reader.read(content, 0, len);
+ int total = done;
+
+ while (done >= 0 && total < len) {
+ done = reader.read(content, total, len - total);
+ total += done;
+ }
+ reader.close();
+ encodedreq = new String(content);
+ }
+
+ // force client auth handshake, validate clone CA (CCA)
+ // and get CCA's Id.
+ // NOTE must do this after all contents are read for ssl
+ // redohandshake to work
+
+ X509Certificate peerCert;
+
+ try {
+ peerCert = getPeerCert(req);
+ } catch (EBaseException e) {
+ mAuthority.log(ILogger.LL_SECURITY,
+ CMS.getLogMessage("CMSGW_HAS_NO_CLIENT_CERT"));
+ resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ return;
+ }
+
+ if (peerCert == null) {
+ // XXX log something here.
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+
+ // authenticate clone CA (CCA)
+
+ String CCA_Id = null;
+ String CCAUserId = null;
+ IAuthToken token = null;
+
+ try {
+ // cfu +++ authenticate checks both SUBJECT and Signer SUBJECT
+ CMS.debug("CloneServlet: about to authenticate");
+ token = authenticate(peerCert);
+ // cfu maybe don't need CCA_Id, because the above check
+ // was good enough
+ CCAUserId = token.getInString("userid");
+ CCA_Id = peerCert.getSubjectDN().toString();
+ } catch (EInvalidCredentials e) {
+ // already logged.
+ resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ return;
+ } catch (EBaseException e) {
+ // already logged.
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+
+ mAuthority.log(ILogger.LL_INFO,
+ "Clone Certificate Authority authenticated: " + peerCert.getSubjectDN());
+
+ // authorize, any authenticated user are authorized
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, token,
+ mAuthzResourceName, "submit");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsRequest.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ // after cert validated, check http request.
+ if (!method.equalsIgnoreCase("POST")) {
+ resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+ return;
+ }
+ if (len <= 0) {
+ resp.sendError(HttpServletResponse.SC_LENGTH_REQUIRED);
+ return;
+ }
+
+ // now process CCA request - should just be posting revoked
+ // certs for now
+
+ try {
+ // decode request.
+ CMS.debug("Cloneservlet: before decoding request, encodedreq= " + encodedreq);
+ msg = (IPKIMessage) mReqEncoder.decode(encodedreq);
+ // process request
+ CMS.debug("Cloneservlet: decoded request");
+ replymsg = processRequest(CCA_Id, CCAUserId, msg, token);
+ } catch (IOException e) {
+ e.printStackTrace();
+ mAuthority.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString()));
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ } catch (EBaseException e) {
+ mAuthority.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString()));
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
+ // encode reply
+ String encodedrep = mReqEncoder.encode(replymsg);
+
+ resp.setStatus(HttpServletResponse.SC_OK);
+ resp.setContentType("text/html");
+ resp.setContentLength(encodedrep.length());
+
+ // send reply
+ OutputStream out = resp.getOutputStream();
+ OutputStreamWriter writer = new OutputStreamWriter(out, "UTF8");
+
+ writer.write(encodedrep);
+ writer.flush();
+ writer.close();
+ out.flush();
+ }
+
+ //cfu ++change this to just check the subject and signer
+ protected IAuthToken authenticate(
+ X509Certificate peerCert)
+ throws EBaseException {
+ try {
+ // XXX using agent authentication now since we're only
+ // verifying that the cert belongs to a user in the db.
+ // XXX change this to ACL in the future.
+
+ // build JAVA X509Certificate from peerCert.
+ X509CertImpl cert = new X509CertImpl(peerCert.getEncoded());
+
+ AuthCredentials creds = new AuthCredentials();
+
+ creds.set(IAuthManager.CRED_SSL_CLIENT_CERT,
+ new X509Certificate[] { cert }
+ );
+
+ IAuthToken token = mAuthSubsystem.authenticate(creds,
+ IAuthSubsystem.CERTUSERDB_AUTHMGR_ID);
+
+ return token;
+ } catch (CertificateException e) {
+ mAuthority.log(ILogger.LL_SECURITY,
+ CMS.getLogMessage("CMSGW_REMOTE_AUTHORITY_AUTH_FAILURE", peerCert.getSubjectDN().toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ } catch (EInvalidCredentials e) {
+ mAuthority.log(ILogger.LL_SECURITY,
+ CMS.getLogMessage("CMSGW_REMOTE_AUTHORITY_AUTH_FAILURE", peerCert.getSubjectDN().toString()));
+ throw e;
+ } catch (EBaseException e) {
+ mAuthority.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_REMOTE_AUTHORITY_AUTH_FAILURE", peerCert.getSubjectDN().toString()));
+ throw e;
+ }
+ }
+
+ protected IPKIMessage processRequest(
+ String source, String sourceUserId, IPKIMessage msg, IAuthToken token)
+ throws EBaseException {
+ IPKIMessage replymsg = null;
+ IRequestQueue queue = mAuthority.getRequestQueue();
+ String srcid = source + ":" + msg.getReqId();
+
+ mAuthority.log(ILogger.LL_INFO, "CFU: in CloneServlet processRequest");
+
+ // find request in request queue and return result.
+ RequestId thisreqid = queue.findRequestBySourceId(srcid);
+ IRequest thisreq = null;
+
+ if (thisreqid != null) {
+ thisreq = queue.findRequest(thisreqid);
+ if (thisreq == null) {
+ // strange case.
+ String errormsg = "Cannot find request in request queue " + thisreqid;
+
+ mAuthority.log(ILogger.LL_FAILURE, errormsg);
+ throw new EBaseException(errormsg);
+ } else {
+ mAuthority.log(ILogger.LL_INFO,
+ "Found request " + thisreqid + " for " + srcid);
+ replymsg = CMS.getHttpPKIMessage();
+ replymsg.fromRequest(thisreq);
+ return replymsg;
+ }
+ }
+
+ // if not found process request.
+ thisreq = queue.newRequest(msg.getReqType());
+ thisreq.setSourceId(srcid);
+ msg.toRequest(thisreq);
+ thisreq.setExtData(IRequest.AUTH_TOKEN, token);
+
+ // setting requestor type must come after copy contents. because
+ // requestor is a regular attribute.
+ thisreq.setExtData(IRequest.REQUESTOR_TYPE,
+ IRequest.REQUESTOR_RA);
+ mAuthority.log(ILogger.LL_INFO, "Processing remote request " + srcid);
+
+ // Set this so that request's updateBy is recorded
+ SessionContext s = SessionContext.getContext();
+
+ if (s.get(SessionContext.USER_ID) == null) {
+ s.put(SessionContext.USER_ID, sourceUserId);
+ }
+
+ queue.processRequest(thisreq);
+ replymsg = CMS.getHttpPKIMessage();
+ replymsg.fromRequest(thisreq);
+
+ //for audit log
+ String agentID = sourceUserId;
+ String initiative = AuditFormat.FROMRA + " trustedManagerID: " +
+ agentID + " remote reqID " + msg.getReqId();
+ String authMgr = AuditFormat.NOAUTH;
+
+ if (token != null) {
+ authMgr =
+ token.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ }
+
+ // Get the certificate info from the request
+ X509CertInfo certInfo[] = thisreq.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ try {
+ if (!thisreq.getRequestStatus().equals(RequestStatus.COMPLETE)) {
+ if (certInfo != null) {
+ for (int i = 0; i < certInfo.length; i++) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ thisreq.getRequestStatus(),
+ certInfo[i].get(X509CertInfo.SUBJECT),
+ "" }
+ );
+ }
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ thisreq.getRequestStatus() }
+ );
+ }
+ } else {
+ if (thisreq.getRequestType().equals(IRequest.CLA_CERT4CRL_REQUEST)) {
+ Integer result = thisreq.getExtDataInInteger(IRequest.RESULT);
+
+ if (result.equals(IRequest.RES_ERROR)) {
+ CMS.debug("CloneServlet: error in CLA_CERT4CRL_REQUEST");
+ } else {
+ // the success.
+ CMS.debug("CloneServlet: success in CLA_CERT4CRL_REQUEST");
+ }
+ }
+
+ /* cfu ---
+ if (thisreq.getRequestType().equals(IRequest.ENROLLMENT_REQUEST)) {
+ // XXX make the repeat record.
+ // Get the certificate(s) from the request
+ X509CertImpl issuedCerts[] =
+ (X509CertImpl[])thisreq.get(IRequest.ISSUED_CERTS);
+ // return potentially more than one certificates.
+ if (issuedCerts != null) {
+ for (int i = 0; i < issuedCerts.length; i++) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId() ,
+ initiative ,
+ authMgr ,
+ "completed",
+ issuedCerts[i].getSubjectDN() ,
+ "cert issued serial number: 0x" +
+ issuedCerts[i].getSerialNumber().toString(16)}
+ );
+ }
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId() ,
+ initiative ,
+ authMgr ,
+ "completed"}
+ );
+ }
+ } else if (thisreq.getRequestType().equals(IRequest.RENEWAL_REQUEST)) {
+ X509CertImpl[] certs = (X509CertImpl[])thisreq.get(IRequest.OLD_CERTS);
+ X509CertImpl old_cert = certs[0];
+ certs = (X509CertImpl[])thisreq.get(IRequest.ISSUED_CERTS);
+ X509CertImpl renewed_cert = certs[0];
+ if (old_cert != null && renewed_cert != null) {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.RENEWALFORMAT,
+ new Object[] {
+ thisreq.getRequestId(),
+ initiative ,
+ authMgr ,
+ "completed",
+ old_cert.getSubjectDN() ,
+ old_cert.getSerialNumber().toString(16) ,
+ "new serial number: 0x" +
+ renewed_cert.getSerialNumber().toString(16)}
+ );
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId() ,
+ initiative ,
+ authMgr ,
+ "completed with error"}
+ );
+ }
+ } else if (thisreq.getRequestType().equals(IRequest.REVOCATION_REQUEST)) {
+ X509CertImpl[] oldCerts = (X509CertImpl[])thisreq.get(IRequest.OLD_CERTS);
+ RevokedCertImpl crlentries[] =
+ (RevokedCertImpl[])thisreq.get(IRequest.REVOKED_CERTS);
+ CRLExtensions crlExts = crlentries[0].getExtensions();
+ int reason = 0;
+ if (crlExts != null) {
+ Enumeration enum = crlExts.getElements();
+ while(enum.hasMoreElements()){
+ Extension ext = (Extension) enum.nextElement();
+ if (ext instanceof CRLReasonExtension) {
+ reason = ((CRLReasonExtension)ext).getReason().toInt
+ ();
+ break;
+ }
+ }
+ }
+
+ int count = oldCerts.length;
+ Integer result = (Integer)thisreq.get(IRequest.RESULT);
+ if (result.equals(IRequest.RES_ERROR)) {
+ EBaseException ex = (EBaseException)thisreq.get(IRequest.ERROR);
+ EBaseException[] svcErrors =
+ (EBaseException[])thisreq.get(IRequest.SVCERRORS);
+ if (svcErrors != null && svcErrors.length > 0) {
+ for (int i = 0; i < svcErrors.length; i++) {
+ EBaseException err = svcErrors[i];
+ if (err != null) {
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ thisreq.getRequestId(),
+ initiative ,
+ "completed with error: " +
+ err.toString() ,
+ oldCerts[j].getSubjectDN() ,
+ oldCerts[j].getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString()}
+ );
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // the success.
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ thisreq.getRequestId(),
+ initiative ,
+ "completed" ,
+ oldCerts[j].getSubjectDN() ,
+ oldCerts[j].getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString()}
+ );
+ }
+ }
+ }
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId() ,
+ initiative ,
+ authMgr ,
+ "completed"}
+ );
+ }
+ cfu */
+ }
+ } catch (IOException e) {
+ } catch (CertificateException e) {
+ }
+
+ return replymsg;
+ }
+
+ protected X509Certificate
+ getPeerCert(HttpServletRequest req) throws EBaseException {
+ return getSSLClientCertificate(req);
+ }
+
+ public String getServletInfo() {
+ return INFO;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
new file mode 100644
index 000000000..5f1fc4805
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
@@ -0,0 +1,1115 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.connector;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.Extension;
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.connector.IPKIMessage;
+import com.netscape.certsrv.connector.IRequestEncoder;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Connector servlet
+ * process requests from remote authority -
+ * service request or return status.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ConnectorServlet extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1221916495803185863L;
+ public static final String INFO = "Connector Servlet";
+ public final static String PROP_AUTHORITY = "authority";
+ protected ServletConfig mConfig = null;
+ protected IAuthority mAuthority = null;
+ protected IRequestEncoder mReqEncoder = null;
+ protected IAuthSubsystem mAuthSubsystem = null;
+ protected ILogger mLogger = CMS.getLogger();
+
+ protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+ private final static String SIGNED_AUDIT_PROTECTION_METHOD_SSL = "ssl";
+ private final static String LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS_5";
+ private final static String LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST =
+ "LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST_5";
+ private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED =
+ "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5";
+
+ private final static byte EOL[] = { Character.LINE_SEPARATOR };
+
+ public ConnectorServlet() {
+ }
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mConfig = sc;
+ String authority = sc.getInitParameter(PROP_AUTHORITY);
+
+ if (authority != null)
+ mAuthority = (IAuthority)
+ CMS.getSubsystem(authority);
+ mReqEncoder = CMS.getHttpRequestEncoder();
+
+ mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ }
+
+ public void service(HttpServletRequest request,
+ HttpServletResponse response)
+ throws ServletException, IOException {
+
+ boolean running_state = CMS.isInRunningState();
+
+ if (!running_state)
+ throw new IOException(
+ "CMS server is not ready to serve.");
+
+ HttpServletRequest req = request;
+ HttpServletResponse resp = response;
+
+ CMSRequest cmsRequest = newCMSRequest();
+
+ // set argblock
+ cmsRequest.setHttpParams(CMS.createArgBlock(toHashtable(request)));
+
+ // set http request
+ cmsRequest.setHttpReq(request);
+
+ // set http response
+ cmsRequest.setHttpResp(response);
+
+ // set servlet config.
+ cmsRequest.setServletConfig(mConfig);
+
+ // set servlet context.
+ cmsRequest.setServletContext(mConfig.getServletContext());
+
+ char[] content = null;
+ String encodedreq = null;
+ String method = null;
+ int len = -1;
+ IPKIMessage msg = null;
+ IPKIMessage replymsg = null;
+
+ // NOTE must read all bufer before redoing handshake for
+ // ssl client auth for client auth to work.
+
+ // get request method
+ method = req.getMethod();
+
+ // get content length
+ len = request.getContentLength();
+
+ // get content, a base 64 encoded serialized request.
+ if (len > 0) {
+ InputStream in = request.getInputStream();
+ InputStreamReader inreader = new InputStreamReader(in, "UTF8");
+ BufferedReader reader = new BufferedReader(inreader, len);
+
+ content = new char[len];
+ int done = reader.read(content, 0, len);
+ int total = done;
+
+ while (done >= 0 && total < len) {
+ done = reader.read(content, total, len - total);
+ total += done;
+ }
+ reader.close();
+ encodedreq = new String(content);
+ }
+
+ // force client auth handshake, validate RA and get RA's Id.
+ // NOTE must do this after all contents are read for ssl
+ // redohandshake to work
+
+ X509Certificate peerCert;
+
+ try {
+ peerCert = getPeerCert(req);
+ } catch (EBaseException e) {
+ mAuthority.log(ILogger.LL_SECURITY,
+ CMS.getLogMessage("CMSGW_HAS_NO_CLIENT_CERT"));
+ resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ return;
+ }
+
+ if (peerCert == null) {
+ // XXX log something here.
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+
+ // authenticate RA
+
+ String RA_Id = null;
+ String raUserId = null;
+ IAuthToken token = null;
+
+ try {
+ token = authenticate(request);
+ raUserId = token.getInString("userid");
+ RA_Id = peerCert.getSubjectDN().toString();
+ } catch (EInvalidCredentials e) {
+ // already logged.
+ resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ return;
+ } catch (EBaseException e) {
+ // already logged.
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+
+ mAuthority.log(ILogger.LL_INFO,
+ "Remote Authority authenticated: " + peerCert.getSubjectDN());
+
+ // authorize
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, token,
+ mAuthzResourceName, "submit");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsRequest.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ // after cert validated, check http request.
+ if (!method.equalsIgnoreCase("POST")) {
+ resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+ return;
+ }
+ if (len <= 0) {
+ resp.sendError(HttpServletResponse.SC_LENGTH_REQUIRED);
+ return;
+ }
+
+ // now process request.
+
+ CMS.debug("ConnectorServlet: process request RA_Id=" + RA_Id);
+ try {
+ // decode request.
+ msg = (IPKIMessage) mReqEncoder.decode(encodedreq);
+ // process request
+ replymsg = processRequest(RA_Id, raUserId, msg, token);
+ } catch (IOException e) {
+ CMS.debug("ConnectorServlet: service " + e.toString());
+ CMS.debug(e);
+ mAuthority.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString()));
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ } catch (EBaseException e) {
+ CMS.debug("ConnectorServlet: service " + e.toString());
+ CMS.debug(e);
+ mAuthority.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString()));
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return;
+ } catch (Exception e) {
+ CMS.debug("ConnectorServlet: service " + e.toString());
+ CMS.debug(e);
+ }
+
+ CMS.debug("ConnectorServlet: done processRequest");
+
+ // encode reply
+ try {
+ String encodedrep = mReqEncoder.encode(replymsg);
+
+ resp.setStatus(HttpServletResponse.SC_OK);
+ resp.setContentType("text/html");
+ resp.setContentLength(encodedrep.length());
+
+ // send reply
+ OutputStream out = response.getOutputStream();
+ OutputStreamWriter writer = new OutputStreamWriter(out, "UTF8");
+
+ writer.write(encodedrep);
+ writer.flush();
+ writer.close();
+ out.flush();
+ } catch (Exception e) {
+ CMS.debug("ConnectorServlet: error writing e=" + e.toString());
+ }
+ CMS.debug("ConnectorServlet: send response RA_Id=" + RA_Id);
+ }
+
+ public static boolean isProfileRequest(IRequest request) {
+ String profileId = request.getExtDataInString("profileId");
+
+ if (profileId == null || profileId.equals(""))
+ return false;
+ else
+ return true;
+ }
+
+ public void normalizeProfileRequest(IRequest request) {
+ // if it is profile request, we need to normalize the
+ // x509certinfo from ra into request
+ X509CertInfo info = null;
+ ByteArrayOutputStream byteStream;
+
+ try {
+ info = request.getExtDataInCertInfo(IEnrollProfile.REQUEST_CERTINFO);
+
+ // request.set(IEnrollProfile.REQUEST_SEQ_NUM, new Integer("0"));
+ CertificateX509Key certKey = (CertificateX509Key) info.get(X509CertInfo.KEY);
+ if (certKey != null) {
+ byteStream = new ByteArrayOutputStream();
+ certKey.encode(byteStream);
+ request.setExtData(IEnrollProfile.REQUEST_KEY,
+ byteStream.toByteArray());
+ }
+
+ CertificateSubjectName certSubject = (CertificateSubjectName)
+ info.get(X509CertInfo.SUBJECT);
+ if (certSubject != null) {
+ request.setExtData(IEnrollProfile.REQUEST_SUBJECT_NAME,
+ certSubject);
+ }
+
+ CertificateValidity certValidity = (CertificateValidity)
+ info.get(X509CertInfo.VALIDITY);
+ if (certValidity != null) {
+ byteStream = new ByteArrayOutputStream();
+ certValidity.encode(byteStream);
+ request.setExtData(IEnrollProfile.REQUEST_VALIDITY,
+ byteStream.toByteArray());
+ }
+
+ CertificateExtensions extensions = (CertificateExtensions)
+ info.get(X509CertInfo.EXTENSIONS);
+ if (extensions != null) {
+ request.setExtData(IEnrollProfile.REQUEST_EXTENSIONS,
+ extensions);
+ }
+
+ CertificateAlgorithmId certAlg = (CertificateAlgorithmId)
+ info.get(X509CertInfo.ALGORITHM_ID);
+ if (certAlg != null) {
+ ByteArrayOutputStream certAlgOut = new ByteArrayOutputStream();
+ certAlg.encode(certAlgOut);
+ request.setExtData(IEnrollProfile.REQUEST_SIGNING_ALGORITHM,
+ certAlgOut.toByteArray());
+ }
+ } catch (Exception e) {
+ CMS.debug("ConnectorServlet: profile normalization " +
+ e.toString());
+ }
+
+ String profileId = request.getExtDataInString("profileId");
+ IProfileSubsystem ps = (IProfileSubsystem)
+ CMS.getSubsystem("profile");
+ IEnrollProfile profile = null;
+
+ // profile subsystem may not be available. In case of KRA for
+ // example
+ if (ps == null) {
+ CMS.debug("ConnectorServlet: Profile Subsystem not found ");
+ return;
+ }
+ try {
+ profile = (IEnrollProfile) (ps.getProfile(profileId));
+ profile.setDefaultCertInfo(request);
+ } catch (EProfileException e) {
+ CMS.debug("ConnectorServlet: normalizeProfileRequest Exception: " + e.toString());
+ }
+ if (profile == null) {
+ CMS.debug("ConnectorServlet: Profile not found " + profileId);
+ return;
+ }
+ }
+
+ /**
+ * Process request
+ * <P>
+ *
+ * (Certificate Request - all "agent" profile cert requests made through a connector)
+ * <P>
+ *
+ * (Certificate Request Processed - all automated "agent" profile based cert acceptance made through a connector)
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST used when a profile cert request is made (before
+ * approval process)
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been
+ * through the approval process
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS used when inter-CIMC_Boundary data transfer is
+ * successful (this is used when data does not need to be captured)
+ * </ul>
+ *
+ * @param source string containing source
+ * @param sourceUserId string containing source user ID
+ * @param msg PKI message
+ * @param token the authentication token
+ * @exception EBaseException an error has occurred
+ * @return PKI message
+ */
+ protected IPKIMessage processRequest(
+ String source, String sourceUserId, IPKIMessage msg, IAuthToken token)
+ throws EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = sourceUserId;
+ String auditProtectionMethod = SIGNED_AUDIT_PROTECTION_METHOD_SSL;
+ String auditRequestType = msg.getReqType();
+ String auditRequesterID = msg.getReqId();
+
+ // additional parms for LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST
+ String auditCertificateSubjectName = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ String subject = null;
+
+ // additional parms for LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED
+ String auditInfoCertValue = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+
+ // "normalize" the "auditSubjectID"
+ if (auditSubjectID != null) {
+ auditSubjectID = auditSubjectID.trim();
+ } else {
+ auditSubjectID = ILogger.UNIDENTIFIED;
+ }
+
+ // "normalize" the "auditRequestType"
+ if (auditRequestType != null) {
+ auditRequestType = auditRequestType.trim();
+ } else {
+ auditRequestType = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ // "normalize" the "auditRequesterID"
+ if (auditRequesterID != null) {
+ auditRequesterID = auditRequesterID.trim();
+ } else {
+ auditRequesterID = ILogger.UNIDENTIFIED;
+ }
+
+ IPKIMessage replymsg = null;
+
+ try {
+ IRequestQueue queue = mAuthority.getRequestQueue();
+ String srcid = source + ":" + msg.getReqId();
+
+ // find request in request queue and return result.
+ RequestId thisreqid = queue.findRequestBySourceId(srcid);
+ IRequest thisreq = null;
+
+ if (thisreqid != null) {
+ thisreq = queue.findRequest(thisreqid);
+ if (thisreq == null) {
+ // strange case.
+ String errormsg = "Cannot find request in request queue " +
+ thisreqid;
+
+ mAuthority.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage(
+ "CMSGW_REQUEST_ID_NOT_FOUND_1",
+ thisreqid.toString()));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+
+ // NOTE: The signed audit event
+ // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST
+ // does not yet matter at this point!
+
+ throw new EBaseException(errormsg);
+ } else {
+ mAuthority.log(ILogger.LL_INFO,
+ "Found request " + thisreqid + " for " + srcid);
+ replymsg = CMS.getHttpPKIMessage();
+ replymsg.fromRequest(thisreq);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+
+ // NOTE: The signed audit event
+ // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST
+ // does not yet matter at this point!
+
+ return replymsg;
+ }
+ }
+
+ // if not found process request.
+ thisreq = queue.newRequest(msg.getReqType());
+ CMS.debug("ConnectorServlet: created requestId=" +
+ thisreq.getRequestId().toString());
+ thisreq.setSourceId(srcid);
+
+ // NOTE: For the following signed audit message, since we only
+ // care about the "msg.toRequest( thisreq );" command, and
+ // since this command does not throw an EBaseException
+ // (which is the only exception designated by this method),
+ // then this code does NOT need to be contained within its
+ // own special try/catch block.
+ msg.toRequest(thisreq);
+
+ if (isProfileRequest(thisreq)) {
+ X509CertInfo info =
+ thisreq.getExtDataInCertInfo(
+ IEnrollProfile.REQUEST_CERTINFO);
+
+ try {
+ CertificateSubjectName sn = (CertificateSubjectName)
+ info.get(X509CertInfo.SUBJECT);
+
+ // if the cert subject name is NOT MISSING, retrieve the
+ // actual "auditCertificateSubjectName" and "normalize"
+ // it
+ if (sn != null) {
+ subject = sn.toString();
+ if (subject != null) {
+ // NOTE: This is ok even if the cert subject
+ // name is "" (empty)!
+ auditCertificateSubjectName = subject.trim();
+ }
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditProfileID(),
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+ } catch (CertificateException e) {
+ CMS.debug("ConnectorServlet: processRequest "
+ + e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditProfileID(),
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+ } catch (IOException e) {
+ CMS.debug("ConnectorServlet: processRequest "
+ + e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditProfileID(),
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+ }
+ }
+
+ thisreq.setExtData(IRequest.AUTH_TOKEN, token);
+
+ // setting requestor type must come after copy contents. because
+ // requestor is a regular attribute.
+ thisreq.setExtData(IRequest.REQUESTOR_TYPE,
+ IRequest.REQUESTOR_RA);
+ mAuthority.log(ILogger.LL_INFO, "Processing remote request " +
+ srcid);
+
+ // Set this so that request's updateBy is recorded
+ SessionContext s = SessionContext.getContext();
+
+ if (s.get(SessionContext.USER_ID) == null) {
+ s.put(SessionContext.USER_ID, sourceUserId);
+ }
+
+ if (s.get(SessionContext.REQUESTER_ID) == null) {
+ s.put(SessionContext.REQUESTER_ID, msg.getReqId());
+ }
+
+ CMS.debug("ConnectorServlet: calling processRequest instance=" +
+ thisreq);
+ if (isProfileRequest(thisreq)) {
+ normalizeProfileRequest(thisreq);
+ }
+
+ try {
+ queue.processRequest(thisreq);
+
+ if (isProfileRequest(thisreq)) {
+ // reset the "auditInfoCertValue"
+ auditInfoCertValue = auditInfoCertValue(thisreq);
+
+ if (auditInfoCertValue != null) {
+ if (!(auditInfoCertValue.equals(
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE))) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_ACCEPTANCE,
+ auditInfoCertValue);
+
+ audit(auditMessage);
+ }
+ }
+ }
+ } catch (EBaseException eAudit1) {
+ if (isProfileRequest(thisreq)) {
+ // reset the "auditInfoCertValue"
+ auditInfoCertValue = auditInfoCertValue(thisreq);
+
+ if (auditInfoCertValue != null) {
+ if (!(auditInfoCertValue.equals(
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE))) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_ACCEPTANCE,
+ auditInfoCertValue);
+
+ audit(auditMessage);
+ }
+ }
+ }
+
+ // rethrow EBaseException to primary catch clause
+ // within this method
+ throw eAudit1;
+ }
+
+ replymsg = CMS.getHttpPKIMessage();
+ replymsg.fromRequest(thisreq);
+
+ CMS.debug("ConnectorServlet: replymsg.reqStatus=" +
+ replymsg.getReqStatus());
+
+ //for audit log
+ String agentID = sourceUserId;
+ String initiative = AuditFormat.FROMRA + " trustedManagerID: " +
+ agentID + " remote reqID " + msg.getReqId();
+ String authMgr = AuditFormat.NOAUTH;
+
+ if (token != null) {
+ authMgr =
+ token.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ }
+
+ if (isProfileRequest(thisreq)) {
+ // XXX audit log
+ CMS.debug("ConnectorServlet: done requestId=" +
+ thisreq.getRequestId().toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+
+ // NOTE: The signed audit event
+ // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST
+ // has already been logged at this point!
+
+ return replymsg;
+ }
+
+ // Get the certificate info from the request
+ X509CertInfo x509Info[] = thisreq.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ try {
+ if (!thisreq.getRequestStatus().equals(RequestStatus.COMPLETE)) {
+ if (x509Info != null) {
+ for (int i = 0; i < x509Info.length; i++) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ thisreq.getRequestStatus(),
+ x509Info[i].get(X509CertInfo.SUBJECT),
+ "" }
+ );
+ }
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ thisreq.getRequestStatus() }
+ );
+ }
+ } else {
+ if (thisreq.getRequestType().equals(IRequest.ENROLLMENT_REQUEST)) {
+ // XXX make the repeat record.
+ // Get the certificate(s) from the request
+ X509CertImpl x509Certs[] = null;
+
+ if (x509Info != null)
+ x509Certs =
+ thisreq.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ // return potentially more than one certificates.
+ if (x509Certs != null) {
+ for (int i = 0; i < x509Certs.length; i++) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ "completed",
+ x509Certs[i].getSubjectDN(),
+ "cert issued serial number: 0x" +
+ x509Certs[i].getSerialNumber().toString(16) }
+ );
+ }
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ "completed" }
+ );
+ }
+ } else if (thisreq.getRequestType().equals(IRequest.RENEWAL_REQUEST)) {
+ X509CertImpl[] certs =
+ thisreq.getExtDataInCertArray(IRequest.OLD_CERTS);
+ X509CertImpl old_cert = certs[0];
+
+ certs = thisreq.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+ X509CertImpl renewed_cert = certs[0];
+
+ if (old_cert != null && renewed_cert != null) {
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.RENEWALFORMAT,
+ new Object[] {
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ "completed",
+ old_cert.getSubjectDN(),
+ old_cert.getSerialNumber().toString(16),
+ "new serial number: 0x" +
+ renewed_cert.getSerialNumber().toString(16) }
+ );
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ "completed with error" }
+ );
+ }
+ } else if (thisreq.getRequestType().equals(IRequest.REVOCATION_REQUEST)) {
+ Certificate[] oldCerts =
+ thisreq.getExtDataInCertArray(IRequest.OLD_CERTS);
+ RevokedCertImpl crlentries[] =
+ thisreq.getExtDataInRevokedCertArray(IRequest.REVOKED_CERTS);
+ CRLExtensions crlExts = crlentries[0].getExtensions();
+ int reason = 0;
+
+ if (crlExts != null) {
+ Enumeration<Extension> enum1 = crlExts.getElements();
+
+ while (enum1.hasMoreElements()) {
+ Extension ext = enum1.nextElement();
+
+ if (ext instanceof CRLReasonExtension) {
+ reason = ((CRLReasonExtension) ext).getReason().toInt();
+ break;
+ }
+ }
+ }
+
+ int count = oldCerts.length;
+ Integer result = thisreq.getExtDataInInteger(IRequest.RESULT);
+
+ if (result.equals(IRequest.RES_ERROR)) {
+ String[] svcErrors =
+ thisreq.getExtDataInStringArray(IRequest.SVCERRORS);
+
+ if (svcErrors != null && svcErrors.length > 0) {
+ for (int i = 0; i < svcErrors.length; i++) {
+ String err = svcErrors[i];
+
+ if (err != null) {
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ if (oldCerts[j] instanceof X509CertImpl) {
+ X509CertImpl cert = (X509CertImpl) oldCerts[j];
+
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ thisreq.getRequestId(),
+ initiative,
+ "completed with error: " +
+ err,
+ cert.getSubjectDN(),
+ cert.getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString() }
+ );
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // the success.
+ for (int j = 0; j < count; j++) {
+ if (oldCerts[j] != null) {
+ if (oldCerts[j] instanceof X509CertImpl) {
+ X509CertImpl cert = (X509CertImpl) oldCerts[j];
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.DOREVOKEFORMAT,
+ new Object[] {
+ thisreq.getRequestId(),
+ initiative,
+ "completed",
+ cert.getSubjectDN(),
+ cert.getSerialNumber().toString(16),
+ RevocationReason.fromInt(reason).toString() }
+ );
+ }
+ }
+ }
+ }
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ thisreq.getRequestType(),
+ thisreq.getRequestId(),
+ initiative,
+ authMgr,
+ "completed" }
+ );
+ }
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+ } catch (IOException e) {
+ CMS.debug("ConnectorServlet: process " + e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+ } catch (CertificateException e) {
+ CMS.debug("ConnectorServlet: process " + e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+ } catch (Exception e) {
+ CMS.debug("ConnectorServlet: process " + e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+ } finally {
+ SessionContext.releaseContext();
+ }
+
+ // NOTE: The signed audit event
+ // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST
+ // has already been logged at this point!
+
+ return replymsg;
+ } catch (EBaseException e) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProtectionMethod,
+ auditRequestType,
+ auditRequesterID);
+
+ audit(auditMessage);
+
+ // NOTE: The signed audit event
+ // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST
+ // has either already been logged, or
+ // does not yet matter at this point!
+
+ return replymsg;
+ }
+ }
+
+ protected X509Certificate
+ getPeerCert(HttpServletRequest req) throws EBaseException {
+ return getSSLClientCertificate(req);
+ }
+
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Signed Audit Log
+ *
+ * This method is inherited by all extended "CMSServlet"s,
+ * and is called to store messages to the signed audit log.
+ * <P>
+ *
+ * @param msg signed audit log message
+ */
+ protected void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+
+ if (mSignedAuditLogger == null) {
+ return;
+ }
+
+ mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+
+ /**
+ * Signed Audit Log Profile ID
+ *
+ * This method is inherited by all extended "EnrollProfile"s,
+ * and is called to obtain the "ProfileID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @return id string containing the signed audit log message ProfileID
+ */
+ protected String auditProfileID() {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String profileID = getId();
+
+ if (profileID != null) {
+ profileID = profileID.trim();
+ } else {
+ profileID = ILogger.UNIDENTIFIED;
+ }
+
+ return profileID;
+ }
+
+ /**
+ * Signed Audit Log Info Certificate Value
+ *
+ * This method is called to obtain the certificate from the passed in
+ * "X509CertImpl" for a signed audit log message.
+ * <P>
+ *
+ * @param request a Request containing an X509CertImpl
+ * @return cert string containing the certificate
+ */
+ private String auditInfoCertValue(IRequest request) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ X509CertImpl x509cert = request.getExtDataInCert(
+ IEnrollProfile.REQUEST_ISSUED_CERT);
+
+ if (x509cert == null) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ byte rawData[] = null;
+
+ try {
+ rawData = x509cert.getEncoded();
+ } catch (CertificateEncodingException e) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ String cert = null;
+
+ // convert "rawData" into "base64Data"
+ if (rawData != null) {
+ String base64Data = null;
+
+ base64Data = Utils.base64encode(rawData).trim();
+
+ StringBuffer sb = new StringBuffer();
+ // extract all line separators from the "base64Data"
+ for (int i = 0; i < base64Data.length(); i++) {
+ if (base64Data.substring(i, i).getBytes() != EOL) {
+ sb.append(base64Data.substring(i, i));
+ }
+ }
+ cert = sb.toString();
+ }
+
+ if (cert != null) {
+ cert = cert.trim();
+
+ if (cert.equals("")) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ } else {
+ return cert;
+ }
+ } else {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java
new file mode 100644
index 000000000..3d0ad4c62
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java
@@ -0,0 +1,336 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.connector;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Hashtable;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IPrettyPrintFormat;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+
+/**
+ * GenerateKeyPairServlet
+ * handles "server-side key pair generation" requests from the
+ * netkey RA.
+ *
+ * @author Christina Fu (cfu)
+ * @version $Revision$, $Date$
+ */
+//XXX add auditing later
+public class GenerateKeyPairServlet extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 4308385291961910458L;
+ private final static String INFO = "GenerateKeyPairServlet";
+ public final static String PROP_AUTHORITY = "authority";
+ protected ServletConfig mConfig = null;
+ protected IAuthority mAuthority = null;
+ public static int ERROR = 1;
+ IPrettyPrintFormat pp = CMS.getPrettyPrintFormat(":");
+ protected IAuthSubsystem mAuthSubsystem = null;
+ protected ILogger mLogger = CMS.getLogger();
+ private Hashtable<String, String> supportedECCurves_ht = null;
+
+ /**
+ * Constructs GenerateKeyPair servlet.
+ *
+ */
+ public GenerateKeyPairServlet() {
+ super();
+ }
+
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ mConfig = config;
+ IConfigStore sconfig = CMS.getConfigStore();
+ String authority = config.getInitParameter(PROP_AUTHORITY);
+
+ if (authority != null)
+ mAuthority = (IAuthority)
+ CMS.getSubsystem(authority);
+
+ mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ // supported EC cuves by the smart cards
+ String curveList = null;
+ try {
+ curveList = sconfig.getString("kra.keygen.curvelist",
+ "nistp256,nistp384,nistp521");
+ } catch (EBaseException e) {
+ curveList = "nistp256,nistp384,nistp521";
+ }
+
+ supportedECCurves_ht = new Hashtable<String, String>();
+ String[] supportedECCurves = curveList.split(",");
+ for ( int i = 0; i < supportedECCurves.length; i++) {
+ supportedECCurves_ht.put(supportedECCurves[i], supportedECCurves[i]);
+ }
+
+ }
+
+ /**
+ * Returns serlvet information.
+ *
+ * @return name of this servlet
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /*
+ * processServerSideKeyGen -
+ * handles netkey DRM serverside keygen.
+ * netkey operations:
+ * 1. generate keypair (archive user priv key)
+ * 2. unwrap des key with transport key, then url decode it
+ * 3. wrap user priv key with des key
+ * 4. send the following to RA:
+ * * des key wrapped(user priv key)
+ * * user public key
+ * (note: RA should have kek-wrapped des key from TKS)
+ * * recovery blob (used for recovery)
+ */
+ private void processServerSideKeyGen(HttpServletRequest req,
+ HttpServletResponse resp) throws EBaseException {
+ IRequestQueue queue = mAuthority.getRequestQueue();
+ IRequest thisreq = null;
+
+ boolean missingParam = false;
+ String status = "0";
+
+ CMS.debug("processServerSideKeyGen begins:");
+
+ String rCUID = req.getParameter("CUID");
+ String rUserid = req.getParameter("userid");
+ String rdesKeyString = req.getParameter("drm_trans_desKey");
+ String rArchive = req.getParameter("archive");
+ String rKeysize = req.getParameter("keysize");
+ String rKeytype = req.getParameter("keytype");
+ String rKeycurve = req.getParameter("eckeycurve");
+
+ if ((rCUID == null) || (rCUID.equals(""))) {
+ CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: CUID");
+ missingParam = true;
+ }
+
+ if ((rUserid == null) || (rUserid.equals(""))) {
+ CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: userid");
+ missingParam = true;
+ }
+
+ // if not specified, default to RSA
+ if ((rKeytype == null) || (rKeytype.equals(""))) {
+ rKeytype = "RSA";
+ }
+
+ // keysize is for non-EC (EC uses keycurve)
+ if (!rKeytype.equals("EC") && ((rKeysize == null) || (rKeysize.equals("")))) {
+ rKeysize = "1024"; // default to 1024
+ }
+
+ if (rKeytype.equals("EC")) {
+ if ((rKeycurve == null) || (rKeycurve.equals(""))) {
+ rKeycurve = "nistp256";
+ }
+ // is the specified curve supported?
+ boolean isSupportedCurve = supportedECCurves_ht.containsKey(rKeycurve);
+ if (isSupportedCurve == false) {
+ CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): unsupported curve:"+ rKeycurve);
+ missingParam = true;
+ } else {
+ CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): curve to be generated:"+ rKeycurve);
+ }
+ }
+
+ if ((rdesKeyString == null) ||
+ (rdesKeyString.equals(""))) {
+ CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: DRM-transportKey-wrapped DES key");
+ missingParam = true;
+ }
+
+ if ((rArchive == null) || (rArchive.equals(""))) {
+ CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing key archival flag 'archive' ,default to true");
+ rArchive = "true";
+ }
+
+ if (!missingParam) {
+ thisreq = queue.newRequest(IRequest.NETKEY_KEYGEN_REQUEST);
+
+ thisreq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_NETKEY_RA);
+ thisreq.setExtData(IRequest.NETKEY_ATTR_CUID, rCUID);
+ thisreq.setExtData(IRequest.NETKEY_ATTR_USERID, rUserid);
+ thisreq.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY, rdesKeyString);
+ thisreq.setExtData(IRequest.NETKEY_ATTR_ARCHIVE_FLAG, rArchive);
+ thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_SIZE, rKeysize);
+ thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_TYPE, rKeytype);
+ thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_EC_CURVE, rKeycurve);
+
+ queue.processRequest(thisreq);
+ Integer result = thisreq.getExtDataInInteger(IRequest.RESULT);
+ if (result != null) {
+ // sighs! tps thinks 0 is good, and DRM thinks 1 is good
+ if (result.intValue() == 1)
+ status = "0";
+ else
+ status = result.toString();
+ } else
+ status = "7";
+
+ CMS.debug("processServerSideKeygen finished");
+ } // ! missingParam
+
+ String value = "";
+
+ resp.setContentType("text/html");
+
+ String wrappedPrivKeyString = "";
+ String publicKeyString = "";
+
+ if (thisreq == null) {
+ CMS.debug("GenerateKeyPairServlet::processServerSideKeyGen() - "
+ + "thisreq is null!");
+ throw new EBaseException("thisreq is null");
+ }
+
+ publicKeyString = thisreq.getExtDataInString("public_key");
+ wrappedPrivKeyString = thisreq.getExtDataInString("wrappedUserPrivate");
+
+ String ivString = thisreq.getExtDataInString("iv_s");
+
+ /*
+ if (selectedToken == null)
+ status = "4";
+ */
+ if (!status.equals("0"))
+ value = "status=" + status;
+ else {
+ StringBuffer sb = new StringBuffer();
+ sb.append("status=0&");
+ sb.append("wrapped_priv_key=");
+ sb.append(wrappedPrivKeyString);
+ sb.append("&iv_param=");
+ sb.append(ivString);
+ sb.append("&public_key=");
+ sb.append(publicKeyString);
+ value = sb.toString();
+
+ }
+ CMS.debug("processServerSideKeyGen:outputString.encode " + value);
+
+ try {
+ resp.setContentLength(value.length());
+ CMS.debug("GenerateKeyPairServlet:outputString.length " + value.length());
+ OutputStream ooss = resp.getOutputStream();
+ ooss.write(value.getBytes());
+ ooss.flush();
+ mRenderResult = false;
+ } catch (IOException e) {
+ CMS.debug("GenerateKeyPairServlet: " + e.toString());
+ }
+ }
+
+ /*
+
+ * For GenerateKeyPair:
+ *
+ * input:
+ * CUID=value0
+ * trans-wrapped-desKey=value1
+ *
+ * output:
+ * status=value0
+ * publicKey=value1
+ * desKey-wrapped-userPrivateKey=value2
+ * proofOfArchival=value3
+ */
+
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "execute");
+ } catch (Exception e) {
+ }
+
+ if (authzToken == null) {
+
+ try {
+ resp.setContentType("text/html");
+ String value = "unauthorized=";
+ CMS.debug("GenerateKeyPairServlet: Unauthorized");
+
+ resp.setContentLength(value.length());
+ OutputStream ooss = resp.getOutputStream();
+ ooss.write(value.getBytes());
+ ooss.flush();
+ mRenderResult = false;
+ } catch (Exception e) {
+ CMS.debug("GenerateKeyPairServlet: " + e.toString());
+ }
+
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ // begin Netkey serverSideKeyGen and archival
+ CMS.debug("GenerateKeyPairServlet: processServerSideKeyGen would be called");
+ processServerSideKeyGen(req, resp);
+ return;
+ // end Netkey functions
+
+ }
+
+ /**
+ * XXX remember tocheck peer SSL cert and get RA id later
+ *
+ * Serves HTTP admin request.
+ *
+ * @param req HTTP request
+ * @param resp HTTP response
+ */
+ public void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java
new file mode 100644
index 000000000..ebcd42c14
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java
@@ -0,0 +1,327 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.connector;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IPrettyPrintFormat;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+
+/**
+ * TokenKeyRecoveryServlet
+ * handles "key recovery service" requests from the
+ * netkey TPS
+ *
+ * @author Christina Fu (cfu)
+ * @version $Revision$, $Date$
+ */
+//XXX add auditing later
+public class TokenKeyRecoveryServlet extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2322410659376501336L;
+ private final static String INFO = "TokenKeyRecoveryServlet";
+ public final static String PROP_AUTHORITY = "authority";
+ protected ServletConfig mConfig = null;
+ protected IAuthority mAuthority = null;
+ public static int ERROR = 1;
+ IPrettyPrintFormat pp = CMS.getPrettyPrintFormat(":");
+ protected IAuthSubsystem mAuthSubsystem = null;
+
+ /**
+ * Constructs TokenKeyRecovery servlet.
+ *
+ */
+ public TokenKeyRecoveryServlet() {
+ super();
+ }
+
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ mConfig = config;
+ String authority = config.getInitParameter(PROP_AUTHORITY);
+
+ if (authority != null)
+ mAuthority = (IAuthority)
+ CMS.getSubsystem(authority);
+
+ mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ }
+
+ /**
+ * Returns serlvet information.
+ *
+ * @return name of this servlet
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param s The URL to decode
+ */
+ protected String URLdecode(String s) {
+ if (s == null)
+ return null;
+ ByteArrayOutputStream out = new ByteArrayOutputStream(s.length());
+
+ for (int i = 0; i < s.length(); i++) {
+ int c = s.charAt(i);
+
+ if (c == '+') {
+ out.write(' ');
+ } else if (c == '%') {
+ int c1 = Character.digit(s.charAt(++i), 16);
+ int c2 = Character.digit(s.charAt(++i), 16);
+
+ out.write((char) (c1 * 16 + c2));
+ } else {
+ out.write(c);
+ }
+ } // end for
+ return out.toString();
+ }
+
+ /*
+ * processTokenKeyRecovery
+ * handles netkey key recovery requests
+ * input params are:
+ * CUID - the CUID of the old token where the keys/certs were initially for
+ * userid - the userid that belongs to both the old token and the new token
+ * drm_trans_desKey - the des key generated for the NEW token
+ * wrapped with DRM transport key
+ * cert - the user cert corresponding to the key to be recovered
+ *
+ * operations:
+ * 1. unwrap des key with transport key, then url decode it
+ * 2. retrieve user private key
+ * 3. wrap user priv key with des key
+ * 4. send the following to RA:
+ * * des key wrapped(user priv key)
+ * (note: RA should have kek-wrapped des key from TKS)
+ * * recovery blob (used for recovery)
+ *
+ * output params are:
+ * status=value0
+ * publicKey=value1
+ * desKey-wrapped-userPrivateKey=value2
+ */
+ private void processTokenKeyRecovery(HttpServletRequest req,
+ HttpServletResponse resp) throws EBaseException {
+ IRequestQueue queue = mAuthority.getRequestQueue();
+ IRequest thisreq = null;
+
+ // IConfigStore sconfig = CMS.getConfigStore();
+ boolean missingParam = false;
+ String status = "0";
+
+ CMS.debug("processTokenKeyRecovery begins:");
+
+ String rCUID = req.getParameter("CUID");
+ String rUserid = req.getParameter("userid");
+ String rdesKeyString = req.getParameter("drm_trans_desKey");
+ String rCert = req.getParameter("cert");
+
+ if ((rCUID == null) || (rCUID.equals(""))) {
+ CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: CUID");
+ missingParam = true;
+ }
+
+ if ((rUserid == null) || (rUserid.equals(""))) {
+ CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: userid");
+ missingParam = true;
+ }
+
+ if ((rdesKeyString == null) ||
+ (rdesKeyString.equals(""))) {
+ CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: DRM-transportKey-wrapped des key");
+ missingParam = true;
+ }
+
+ if ((rCert == null) || (rCert.equals(""))) {
+ CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: cert");
+ missingParam = true;
+ }
+
+ if (!missingParam) {
+ thisreq = queue.newRequest(IRequest.NETKEY_KEYRECOVERY_REQUEST);
+
+ thisreq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_NETKEY_RA);
+ thisreq.setExtData(IRequest.NETKEY_ATTR_CUID, rCUID);
+ thisreq.setExtData(IRequest.NETKEY_ATTR_USERID, rUserid);
+ thisreq.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY, rdesKeyString);
+ thisreq.setExtData(IRequest.NETKEY_ATTR_USER_CERT, rCert);
+
+ //XXX auto process for netkey
+ queue.processRequest(thisreq);
+ // IService svc = (IService) new TokenKeyRecoveryService(kra);
+ // svc.serviceRequest(thisreq);
+
+ Integer result = thisreq.getExtDataInInteger(IRequest.RESULT);
+ if (result != null) {
+ // sighs! tps thinks 0 is good, and drm thinks 1 is good
+ if (result.intValue() == 1)
+ status = "0";
+ else
+ status = result.toString();
+ } else
+ status = "7";
+
+ CMS.debug("processTokenKeyRecovery finished");
+ } // ! missingParam
+
+ String value = "";
+
+ resp.setContentType("text/html");
+
+ String wrappedPrivKeyString = "";
+ String publicKeyString = "";
+ String ivString = "";
+ /* if is RECOVERY_PROTOTYPE
+ String recoveryBlobString = "";
+
+ IKeyRecord kr = (IKeyRecord) thisreq.get("keyRecord");
+ byte publicKey_b[] = kr.getPublicKeyData();
+
+ BigInteger serialNo = kr.getSerialNumber();
+
+ String serialNumberString =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(serialNo.toByteArray());
+
+ recoveryBlobString = (String)
+ thisreq.get("recoveryBlob");
+ */
+
+ if (thisreq == null) {
+ CMS.debug("TokenKeyRecoveryServlet::processTokenKeyRecovery() - "
+ + "thisreq is null!");
+ throw new EBaseException("thisreq is null");
+ }
+
+ publicKeyString = thisreq.getExtDataInString("public_key");
+ wrappedPrivKeyString = thisreq.getExtDataInString("wrappedUserPrivate");
+
+ ivString = thisreq.getExtDataInString("iv_s");
+ /*
+ if (selectedToken == null)
+ status = "4";
+ */
+ if (!status.equals("0"))
+ value = "status=" + status;
+ else {
+ StringBuffer sb = new StringBuffer();
+ sb.append("status=0&");
+ sb.append("wrapped_priv_key=");
+ sb.append(wrappedPrivKeyString);
+ sb.append("&public_key=");
+ sb.append(publicKeyString);
+ sb.append("&iv_param=");
+ sb.append(ivString);
+ value = sb.toString();
+
+ }
+ CMS.debug("ProcessTokenKeyRecovery:outputString.encode " + value);
+
+ try {
+ resp.setContentLength(value.length());
+ CMS.debug("TokenKeyRecoveryServlet:outputString.length " + value.length());
+ OutputStream ooss = resp.getOutputStream();
+ ooss.write(value.getBytes());
+ ooss.flush();
+ mRenderResult = false;
+ } catch (IOException e) {
+ CMS.debug("TokenKeyRecoveryServlet: " + e.toString());
+ }
+ }
+
+ /*
+ * For TokenKeyRecovery
+ *
+ * input:
+ * CUID=value0
+ * trans-wrapped-desKey=value1
+ *
+ * output:
+ * status=value0
+ * publicKey=value1
+ * desKey-wrapped-userPrivateKey=value2
+ * proofOfArchival=value3
+ */
+
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "submit");
+ } catch (Exception e) {
+ }
+
+ if (authzToken == null) {
+
+ try {
+ resp.setContentType("text/html");
+ String value = "unauthorized=";
+ CMS.debug("TokenKeyRecoveryServlet: Unauthorized");
+
+ resp.setContentLength(value.length());
+ OutputStream ooss = resp.getOutputStream();
+ ooss.write(value.getBytes());
+ ooss.flush();
+ mRenderResult = false;
+ } catch (Exception e) {
+ CMS.debug("TokenKeyRecoveryServlet: " + e.toString());
+ }
+
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ // begin Netkey serverSideKeyGen and archival
+ CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery would be called");
+ processTokenKeyRecovery(req, resp);
+ return;
+ // end Netkey functions
+
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/AdminPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/AdminPanel.java
new file mode 100644
index 000000000..579c54df0
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/AdminPanel.java
@@ -0,0 +1,332 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.property.PropertySet;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.util.HttpInput;
+import com.netscape.cms.servlet.wizard.WizardServlet;
+
+public class AdminPanel extends WizardPanelBase {
+
+ private static final String ADMIN_UID = "admin";
+
+ public AdminPanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Administrator");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) {
+ setPanelNo(panelno);
+ setName("Administrator");
+ setId(id);
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ cs.putString("preop.admin.email", "");
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String s = cs.getString("preop.admin.email", "");
+ if (s == null || s.equals("")) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (Exception e) {
+ }
+
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ Descriptor emailDesc = new Descriptor(IDescriptor.STRING, null, /* no constraint */
+ null, /* no default parameter */
+ "Email address for an administrator");
+
+ set.add("admin_email", emailDesc);
+
+ Descriptor pwdDesc = new Descriptor(IDescriptor.STRING, null, /* no constraint */
+ null, /* no default parameter */
+ "Administrator's password");
+
+ set.add("pwd", pwdDesc);
+
+ Descriptor pwdAgainDesc = new Descriptor(IDescriptor.STRING, null, /* no constraint */
+ null, /* no default parameter */
+ "Administrator's password again");
+
+ set.add("admin_password_again", pwdAgainDesc);
+ return set;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ CMS.debug("AdminPanel: display");
+
+ IConfigStore cs = CMS.getConfigStore();
+ String session_id = request.getParameter("session_id");
+ if (session_id != null) {
+ CMS.debug("NamePanel setting session id.");
+ CMS.setConfigSDSessionId(session_id);
+ }
+
+ String type = "";
+ String info = "";
+ context.put("import", "true");
+
+ try {
+ type = cs.getString("preop.ca.type", "");
+ } catch (Exception e) {
+ }
+
+ if (isPanelDone()) {
+ try {
+ context.put("admin_email", cs.getString("preop.admin.email"));
+ context.put("admin_name", cs.getString("preop.admin.name"));
+ context.put("admin_pwd", "");
+ context.put("admin_pwd_again", "");
+ context.put("admin_uid", cs.getString("preop.admin.uid"));
+ } catch (Exception e) {
+ }
+ } else {
+ String def_admin_name = "";
+ try {
+ def_admin_name = cs.getString("cs.type") + " Administrator of Instance " + cs.getString("instanceId");
+ } catch (EBaseException e) {
+ }
+ context.put("admin_name", def_admin_name);
+ context.put("admin_email", "");
+ context.put("admin_pwd", "");
+ context.put("admin_pwd_again", "");
+ context.put("admin_uid", ADMIN_UID);
+ }
+ ISubsystem ca = CMS.getSubsystem("ca");
+
+ if (ca == null) {
+ context.put("ca", "false");
+ } else {
+ context.put("ca", "true");
+ }
+ context.put("caType", type);
+
+ String domainname = "";
+ try {
+ domainname = cs.getString("securitydomain.name", "");
+ } catch (EBaseException e1) {
+ }
+ context.put("securityDomain", domainname);
+ context.put("title", "Administrator");
+ context.put("panel", "admin/console/config/adminpanel.vm");
+ context.put("errorString", "");
+ context.put("info", info);
+
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ String pwd = HttpInput.getPassword(request, "__pwd");
+ String pwd_again = HttpInput.getPassword(request, "__admin_password_again");
+ String email = HttpInput.getEmail(request, "email");
+ String name = HttpInput.getName(request, "name");
+ String uid = HttpInput.getUID(request, "uid");
+ context.put("admin_email", email);
+ context.put("admin_name", name);
+ context.put("admin_pwd", pwd);
+ context.put("admin_pwd_again", pwd_again);
+ context.put("import", "true");
+
+ if (name == null || name.equals("")) {
+ context.put("updateStatus", "validate-failure");
+ throw new IOException("Name is empty");
+ }
+
+ if (email == null || email.equals("")) {
+ context.put("updateStatus", "validate-failure");
+ throw new IOException("Email is empty");
+ }
+
+ if (uid == null || uid.equals("")) {
+ context.put("updateStatus", "validate-failure");
+ throw new IOException("Uid is empty");
+ }
+
+ if (!pwd.equals(pwd_again)) {
+ context.put("updateStatus", "validate-failure");
+ throw new IOException("Password and password again are not the same.");
+ }
+
+ if (email == null || email.length() == 0) {
+ context.put("updateStatus", "validate-failure");
+ throw new IOException("Email address is empty string.");
+ }
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request, HttpServletResponse response, Context context) throws IOException {
+ IConfigStore config = CMS.getConfigStore();
+ context.put("info", "");
+ context.put("import", "true");
+
+ String uid = HttpInput.getUID(request, "uid");
+ String email = HttpInput.getEmail(request, "email");
+ String name = HttpInput.getName(request, "name");
+ String pwd = HttpInput.getPassword(request, "__pwd");
+ String cert_request_type = HttpInput.getID(request, "cert_request_type");
+ String subject = request.getParameter("subject");
+ String cert_request = HttpInput.getCertRequest(request, "cert_request");
+ String profileId = HttpInput.getID(request, "profileId");
+
+ try {
+ String type = config.getString(PRE_CA_TYPE, "");
+ String subsystemtype = config.getString("cs.type", "");
+ String selected_hierarchy = config.getString("preop.hierarchy.select", "");
+
+ ISubsystem ca = CMS.getSubsystem("ca");
+
+ if (ca == null) {
+ context.put("ca", "false");
+ } else {
+ context.put("ca", "true");
+ }
+ context.put("caType", type);
+
+ config.putString("preop.admin.uid", uid);
+ config.putString("preop.admin.email", email);
+ config.putString("preop.admin.name", name);
+ ConfigurationUtils.createAdmin(uid, email, name, pwd);
+
+ if (ca != null) {
+ if (selected_hierarchy.equals("root")) {
+ CMS.debug("AdminPanel update: " + "Root CA subsystem");
+ } else {
+ CMS.debug("AdminPanel update: " + "Subordinate CA subsystem");
+ }
+
+ ConfigurationUtils.createAdminCertificate(cert_request,
+ cert_request_type, subject);
+ } else {
+ String ca_hostname = null;
+ int ca_port = -1;
+
+ CMS.debug("AdminPanel update: " + subsystemtype + " subsystem");
+
+ if (type.equals("sdca")) {
+ ca_hostname = config.getString("preop.ca.hostname");
+ ca_port = config.getInteger("preop.ca.httpsport");
+ } else {
+ ca_hostname = config.getString("securitydomain.host", "");
+ ca_port = config.getInteger("securitydomain.httpseeport");
+ }
+
+ ConfigurationUtils.submitAdminCertRequest(ca_hostname, ca_port,
+ profileId, cert_request_type, cert_request, subject);
+ }
+
+ CMS.reinit(IUGSubsystem.ID);
+ config.commit(false);
+ } catch (Exception e) {
+ CMS.debug("AdminPanel update(): Exception thrown " + e);
+ e.printStackTrace();
+ context.put("updateStatus", "failure");
+ throw new IOException("Error when adding admin user" + e);
+ }
+
+ context.put("updateStatus", "success");
+ }
+
+ /**
+ * If validate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+
+ context.put("title", "Administrator");
+ context.put("panel", "admin/console/config/adminpanel.vm");
+ ISubsystem ca = CMS.getSubsystem("ca");
+ IConfigStore cs = CMS.getConfigStore();
+ String type = "";
+ String info = "";
+
+ try {
+ type = cs.getString("preop.ca.type", "");
+ } catch (Exception e) {
+ }
+ if (ca == null && type.equals("otherca")) {
+ info =
+ "Since you do not join the Redhat CA network, the administrator's certificate will not be generated automatically.";
+ }
+ context.put("info", info);
+ context.put("admin_email", request.getParameter("email"));
+ context.put("admin_name", request.getParameter("name"));
+ context.put("admin_pwd", "");
+ context.put("admin_pwd_again", "");
+ context.put("admin_uid", request.getParameter("uid"));
+ }
+
+ public boolean shouldSkip() {
+ try {
+ IConfigStore c = CMS.getConfigStore();
+ String s = c.getString("preop.subsystem.select", null);
+ if (s != null && s.equals("clone")) {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/AuthDBPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/AuthDBPanel.java
new file mode 100644
index 000000000..f7ee25dfe
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/AuthDBPanel.java
@@ -0,0 +1,125 @@
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+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.wizard.WizardServlet;
+
+public class AuthDBPanel extends WizardPanelBase {
+
+ public AuthDBPanel() {
+ }
+
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Authentication Directory");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Authentication Directory");
+ setId(id);
+ }
+
+ public boolean shouldSkip() {
+ return false;
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ cs.putString("preop.authdb.select", "");
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String s = cs.getString("preop.authdb.select", "");
+ if (s != null && !s.isEmpty()) {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+ return set;
+ }
+
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("title", "Authentication Directory");
+ context.put("panel", "admin/console/config/authdbpanel.vm");
+ IConfigStore config = CMS.getConfigStore();
+
+ String basedn="";
+ String host="";
+ String port="";
+ String secureConn="";
+ try {
+ String machineName = config.getString("service.machineName");
+ basedn = config.getString("auths.instance.ldap1.ldap.basedn");
+
+ if (basedn.contains("[")) {
+ // basedn not yet set
+ basedn = machineName.replaceAll("\\.", ",dc=");
+ basedn = "dc=" + basedn;
+ }
+
+ host = config.getString("auths.instance.ldap1.ldap.ldapconn.host", "localhost");
+ port = config.getString("auths.instance.ldap1.ldap.ldapconn.port","389");
+ secureConn = config.getString("auths.instance.ldap1.ldap.ldapconn.secureConn", "false");
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ CMS.debug("Unable to get host, port, secureConn:" + e);
+ }
+
+ context.put("hostname", host);
+ context.put("portStr", port);
+ context.put("basedn", basedn);
+ context.put("secureconn", secureConn);
+ context.put("errorString", "");
+ }
+
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+
+ String host = HttpInput.getHostname(request, "host");
+ String port = HttpInput.getPortNumber(request, "port");
+ String basedn = HttpInput.getString(request,"basedn");
+ String secureConn = HttpInput.getString(request, "secureConn");
+
+ if (secureConn == null || (!secureConn.equalsIgnoreCase("true"))) {
+ secureConn = "false";
+ }
+ ConfigurationUtils.updateAuthdbInfo(basedn, host, port, secureConn);
+ context.put("updateStatus", "success");
+ }
+
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/AuthenticatePanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/AuthenticatePanel.java
new file mode 100644
index 000000000..6700b9312
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/AuthenticatePanel.java
@@ -0,0 +1,192 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+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.wizard.WizardServlet;
+
+public class AuthenticatePanel extends WizardPanelBase {
+
+ public AuthenticatePanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Authentication");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Authentication");
+ setId(id);
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ cs.putString("preop.ca.agent.uid", "");
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String s = cs.getString("preop.ca.agent.uid", "");
+ if (s == null || s.equals("")) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ /* XXX */
+
+ return set;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("title", "Authentication");
+ IConfigStore config = CMS.getConfigStore();
+
+ if (isPanelDone()) {
+
+ try {
+ String s = config.getString("preop.ca.agent.uid", "");
+ String type = config.getString("preop.hierarchy.select", "");
+ if (type.equals("root"))
+ context.put("uid", "");
+ else
+ context.put("uid", s);
+ } catch (Exception e) {
+ CMS.debug(e.toString());
+ }
+ } else {
+ context.put("uid", "");
+ }
+
+ context.put("password", "");
+ context.put("panel", "admin/console/config/authenticatepanel.vm");
+ context.put("errorString", "");
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ IConfigStore config = CMS.getConfigStore();
+ String type = "";
+ String catype = "";
+ try {
+ type = config.getString("preop.hierarchy.select", "");
+ catype = config.getString("preop.ca.type", "");
+ } catch (Exception e) {
+ }
+
+ if (type.equals("root")) {
+ CMS.debug("AuthenticatePanel: This is root, no need for authentication");
+ } else if (catype.equals("sdca")) {
+ CMS.debug("AuthenticatePanel: This is not external CA");
+ String uid = HttpInput.getUID(request, "uid");
+ if (uid == null) {
+ context.put("errorString", "Uid is empty");
+ throw new IOException("Uid is empty");
+ }
+ context.put("uid", uid);
+ String pwd = HttpInput.getPassword(request, "__password");
+ config.putString("preop.ca.agent.uid", uid);
+ config.putString("preop.ca.agent.pwd", pwd);
+ String host = "";
+ int httpsport = -1;
+ try {
+ host = config.getString("preop.ca.hostname");
+ } catch (Exception e) {
+ CMS.debug("AuthenticatePanel update: " + e.toString());
+ context.put("errorString", "Missing hostname");
+ throw new IOException("Missing hostname");
+ }
+
+ try {
+ httpsport = config.getInteger("preop.ca.httpsport");
+ } catch (Exception e) {
+ CMS.debug("AuthenticatePanel update: " + e.toString());
+ context.put("errorString", "Missing port");
+ throw new IOException("Missing port");
+ }
+
+ boolean authenticated = authenticate(host, httpsport, true,
+ "/ca/ee/ca/configSubsystem", "uid=" + uid + "&pwd=" + pwd);
+
+ if (!authenticated) {
+ context.put("errorString", "Wrong user id or password");
+ throw new IOException("Wrong user id or password");
+ }
+
+ try {
+ config.commit(false);
+ } catch (EBaseException e) {
+ }
+ }
+ }
+
+ /**
+ * If validiate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("password", "");
+ context.put("panel", "admin/console/config/authenticatepanel.vm");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/BackupKeyCertPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/BackupKeyCertPanel.java
new file mode 100644
index 000000000..f29b22ae7
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/BackupKeyCertPanel.java
@@ -0,0 +1,215 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+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.wizard.WizardServlet;
+
+public class BackupKeyCertPanel extends WizardPanelBase {
+
+ public BackupKeyCertPanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Export Keys and Certificates");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Export Keys and Certificates");
+ setId(id);
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ /* clean up if necessary */
+ try {
+ @SuppressWarnings("unused")
+ boolean done = cs.getBoolean("preop.backupkeycert.done"); // check for errors
+ cs.putBoolean("preop.backupkeycert.done", false);
+ cs.commit(false);
+ } catch (Exception e) {
+ }
+ }
+
+ public boolean shouldSkip() {
+ IConfigStore cs = CMS.getConfigStore();
+
+ try {
+ String s = cs.getString("preop.module.token", "");
+ if (s.equals("Internal Key Storage Token"))
+ return false;
+ } catch (Exception e) {
+ }
+
+ return true;
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String s = cs.getString("preop.backupkeycert.done", "");
+ if (s == null || s.equals("")) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ /* XXX */
+
+ return set;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("title", "Export Keys and Certificates");
+ IConfigStore config = CMS.getConfigStore();
+
+ if (isPanelDone()) {
+ try {
+ boolean enable = config.getBoolean("preop.backupkeys.enable");
+ if (enable) {
+ context.put("dobackup", "checked");
+ context.put("nobackup", "");
+ } else {
+ context.put("dobackup", "");
+ context.put("nobackup", "checked");
+ }
+ } catch (Exception e) {
+ }
+ } else {
+ context.put("dobackup", "");
+ context.put("nobackup", "checked");
+ }
+
+ context.put("panel", "admin/console/config/backupkeycertpanel.vm");
+ context.put("pwd", "");
+ context.put("pwdagain", "");
+ context.put("errorString", "");
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response, Context context) throws IOException {
+ String select = HttpInput.getID(request, "choice");
+ if (select.equals("backupkey")) {
+ String pwd = request.getParameter("__pwd");
+ String pwdAgain = request.getParameter("__pwdagain");
+ if (pwd == null || pwdAgain == null || pwd.equals("") || pwdAgain.equals("")) {
+ CMS.debug("BackupKeyCertPanel validate: Password is null");
+ context.put("updateStatus", "validate-failure");
+ throw new IOException("PK12 password is empty.");
+ }
+
+ if (!pwd.equals(pwdAgain)) {
+ CMS.debug("BackupKeyCertPanel validate: Password and password again are not the same.");
+ context.put("updateStatus", "validate-failure");
+ throw new IOException("PK12 password is different from the PK12 password again.");
+ }
+ }
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ IConfigStore config = CMS.getConfigStore();
+
+ try {
+ String select = HttpInput.getID(request, "choice");
+ String pwd = request.getParameter("__pwd");
+ if (select.equals("backupkey")) {
+ CMS.debug("BackupKeyCertPanel update: backup");
+ config.putBoolean("preop.backupkeys.enable", true);
+ ConfigurationUtils.backupKeys(pwd, null);
+ } else {
+ CMS.debug("BackupKeyCertPanel update: no backup");
+ config.putBoolean("preop.backupkeys.enable", false);
+ }
+
+ config.putBoolean("preop.backupkeycert.done", true);
+ config.commit(false);
+ } catch (Exception e) {
+ CMS.debug("BackupKeyertPanel: update(): Exception thrown " + e);
+ e.printStackTrace();
+ context.put("updateStatus", "failure");
+ throw new IOException(e);
+ }
+ context.put("updateStatus", "success");
+ }
+
+ /**
+ * If validiate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ String select = "";
+ try {
+ select = HttpInput.getID(request, "choice");
+ } catch (Exception e) {
+ }
+
+ if (select.equals("backupkey")) {
+ context.put("dobackup", "checked");
+ context.put("nobackup", "");
+ } else {
+ context.put("dobackup", "");
+ context.put("nobackup", "checked");
+ }
+
+ context.put("pwd", "");
+ context.put("pwdagain", "");
+ context.put("title", "Export Keys and Certificates");
+ context.put("panel", "admin/console/config/backupkeycertpanel.vm");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/BaseServlet.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/BaseServlet.java
new file mode 100644
index 000000000..3b3ae4033
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/BaseServlet.java
@@ -0,0 +1,121 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.Template;
+import org.apache.velocity.context.Context;
+import org.apache.velocity.servlet.VelocityServlet;
+
+import com.netscape.certsrv.apps.CMS;
+
+@SuppressWarnings("deprecation")
+public class BaseServlet extends VelocityServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3169697149104780149L;
+
+ /**
+ * Returns usage of this servlet.
+ */
+ public String getUsage() {
+ return null;
+ }
+
+ public boolean authenticate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ String pin = (String) request.getSession().getAttribute("pin");
+
+ if (pin == null) {
+ try {
+ response.sendRedirect("login");
+ } catch (IOException e) {
+ }
+ return false;
+ }
+ return true;
+ }
+
+ public void outputHttpParameters(HttpServletRequest httpReq) {
+ CMS.debug("BaseServlet:service() uri = " + httpReq.getRequestURI());
+ Enumeration<String> paramNames = httpReq.getParameterNames();
+
+ while (paramNames.hasMoreElements()) {
+ String pn = paramNames.nextElement();
+ // added this facility so that password can be hidden,
+ // all sensitive parameters should be prefixed with
+ // __ (double underscores); however, in the event that
+ // a security parameter slips through, we perform multiple
+ // additional checks to insure that it is NOT displayed
+ if (pn.startsWith("__") ||
+ pn.endsWith("password") ||
+ pn.endsWith("passwd") ||
+ pn.endsWith("pwd") ||
+ pn.equalsIgnoreCase("admin_password_again") ||
+ pn.equalsIgnoreCase("directoryManagerPwd") ||
+ pn.equalsIgnoreCase("bindpassword") ||
+ pn.equalsIgnoreCase("bindpwd") ||
+ pn.equalsIgnoreCase("passwd") ||
+ pn.equalsIgnoreCase("password") ||
+ pn.equalsIgnoreCase("pin") ||
+ pn.equalsIgnoreCase("pwd") ||
+ pn.equalsIgnoreCase("pwdagain") ||
+ pn.equalsIgnoreCase("uPasswd")) {
+ CMS.debug("BaseServlet::service() param name='" + pn +
+ "' value='(sensitive)'");
+ } else {
+ CMS.debug("BaseServlet::service() param name='" + pn +
+ "' value='" + httpReq.getParameter(pn) + "'");
+ }
+ }
+ }
+
+ /**
+ * Processes request.
+ */
+ public Template process(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ return null;
+ }
+
+ public Template handleRequest(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ if (CMS.debugOn()) {
+ outputHttpParameters(request);
+ }
+
+ /* XXX - authentication */
+ if (!authenticate(request, response, context)) {
+ return null;
+ }
+
+ /* XXX - authorization */
+
+ return process(request, response, context);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/CAInfoPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CAInfoPanel.java
new file mode 100644
index 000000000..72bffc767
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CAInfoPanel.java
@@ -0,0 +1,166 @@
+package com.netscape.cms.servlet.csadmin;
+
+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.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);
+ }
+ ConfigurationUtils.updateCAConnInfo(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/server/cms/src/com/netscape/cms/servlet/csadmin/Cert.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/Cert.java
new file mode 100644
index 000000000..066f9dea1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/Cert.java
@@ -0,0 +1,188 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+public class Cert {
+ private String mNickname = "";
+ private String mTokenname = "";
+ private String mRequest = "";
+ private String mCert = "";
+ private String mType = ""; // "selfsign," "local," or "remote"
+ private String mDN = "";
+ private String mCertTag = "";
+ private String mCertpp = "";
+ private String mUserFriendlyName = "";
+ private String mKeyOption = "";
+ private String mCustomKeysize = "";
+ private String mCustomCurvename = "";
+ private boolean mEnable = true;
+ private boolean mSigningRequired = false;
+ private String mSubsystem = "";
+ private String certChain = "";
+
+ public Cert(String tokenName, String nickName, String certTag) {
+ mTokenname = tokenName;
+ mNickname = nickName;
+ mCertTag = certTag;
+ }
+
+ public void setEnable(boolean enable) {
+ mEnable = enable;
+ }
+
+ public boolean isEnable() {
+ return mEnable;
+ }
+
+ public void setSigningRequired(boolean required) {
+ mSigningRequired = required;
+ }
+
+ public boolean isSigningRequired() {
+ return mSigningRequired;
+ }
+
+ public void setNickname(String s) {
+ mNickname = s;
+ }
+
+ public String getNickname() {
+ return mNickname;
+ }
+
+ public void setSubsystem(String s) {
+ mSubsystem = s;
+ }
+
+ public String getSubsystem() {
+ return mSubsystem;
+ }
+
+ public String getUserFriendlyName() {
+ return mUserFriendlyName;
+ }
+
+ public void setUserFriendlyName(String name) {
+ mUserFriendlyName = name;
+ }
+
+ public String getTokenname() {
+ return mTokenname;
+ }
+
+ public String getRequest() {
+ return mRequest;
+ }
+
+ public void setRequest(String req) {
+ mRequest = req;
+ }
+
+ public String getEscapedCert() {
+ return escapeForHTML(mCert);
+ }
+
+ public String getCert() {
+ return mCert;
+ }
+
+ public void setCert(String cert) {
+ mCert = cert;
+ }
+
+ public String getType() {
+ return mType;
+ }
+
+ public void setType(String type) {
+ mType = type;
+ }
+
+ public String escapeForHTML(String s) {
+ s = s.replaceAll("\"", "&quot;");
+ return s;
+ }
+
+ public String getEscapedDN() {
+ // Need to escape "
+ return escapeForHTML(mDN);
+ }
+
+ public String getDN() {
+ return mDN;
+ }
+
+ public void setDN(String dn) {
+ mDN = dn;
+ }
+
+ public String getCertTag() {
+ return mCertTag;
+ }
+
+ public String getEscapedCertpp() {
+ return escapeForHTML(mCertpp);
+ }
+
+ public String getCertpp() {
+ return mCertpp;
+ }
+
+ public void setCertpp(String pp) {
+ mCertpp = pp;
+ }
+
+ public String getKeyOption() {
+ return mKeyOption;
+ }
+
+ /*
+ * "default" or "custom"
+ */
+ public void setKeyOption(String option) {
+ mKeyOption = option;
+ }
+
+ public boolean useDefaultKey() {
+ return (mKeyOption.equals("default"));
+ }
+
+ public String getCustomKeysize() {
+ return mCustomKeysize;
+ }
+
+ public void setCustomKeysize(String size) {
+ mCustomKeysize = size;
+ }
+
+ public String getCustomCurvename() {
+ return mCustomCurvename;
+ }
+
+ public void setCustomCurvename(String curve) {
+ mCustomCurvename = curve;
+ }
+
+ public String getCertChain() {
+ return certChain;
+ }
+
+ public void setCertChain(String certChain) {
+ this.certChain = certChain;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertRequestPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertRequestPanel.java
new file mode 100644
index 000000000..81c6e5ca3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertRequestPanel.java
@@ -0,0 +1,375 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.util.CertPrettyPrint;
+
+import org.apache.velocity.context.Context;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.property.PropertySet;
+import com.netscape.certsrv.util.HttpInput;
+import com.netscape.cms.servlet.wizard.WizardServlet;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+
+public class CertRequestPanel extends WizardPanelBase {
+ private Vector<Cert> mCerts = null;
+
+ @SuppressWarnings("unused")
+ private WizardServlet mServlet;
+
+ public CertRequestPanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Requests & Certificates");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Requests and Certificates");
+ mServlet = servlet;
+ setId(id);
+ }
+
+ // XXX how do you do this? There could be multiple certs.
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ Descriptor certDesc = new Descriptor(IDescriptor.STRING, null, /* no constraint */
+ null, /* no default parameters */
+ null);
+
+ set.add("cert", certDesc);
+
+ return set;
+ }
+
+ /**
+ * Show "Apply" button on frame?
+ */
+ public boolean showApplyButton() {
+ if (isPanelDone())
+ return false;
+ else
+ return true;
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ String list = "";
+ String tokenname = "";
+ try {
+ list = cs.getString("preop.cert.list", "");
+ tokenname = cs.getString("preop.module.token", "");
+ } catch (Exception e) {
+ }
+
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(
+ ICertificateAuthority.ID);
+
+ if (ca != null) {
+ CMS.debug("CertRequestPanel cleanup: get certificate repository");
+ BigInteger beginS = null;
+ BigInteger endS = null;
+ String beginNum = "";
+ String endNum = "";
+ try {
+ beginNum = cs.getString("dbs.beginSerialNumber", "");
+ endNum = cs.getString("dbs.endSerialNumber", "");
+ if (!beginNum.equals(""))
+ beginS = new BigInteger(beginNum, 16);
+ if (!endNum.equals(""))
+ endS = new BigInteger(endNum, 16);
+ } catch (Exception e) {
+ }
+
+ ICertificateRepository cr = ca.getCertificateRepository();
+ if (cr != null) {
+ try {
+ cr.removeCertRecords(beginS, endS);
+ } catch (Exception e) {
+ CMS.debug("CertRequestPanel cleanUp exception in removing all objects: " + e.toString());
+ }
+
+ try {
+ cr.resetSerialNumber(new BigInteger(beginNum, 16));
+ } catch (Exception e) {
+ CMS.debug("CertRequestPanel cleanUp exception in resetting serial number: " + e.toString());
+ }
+ }
+ }
+
+ StringTokenizer st = new StringTokenizer(list, ",");
+ String nickname = "";
+ boolean enable = false;
+ while (st.hasMoreTokens()) {
+ String t = st.nextToken();
+
+ try {
+ enable = cs.getBoolean(PCERT_PREFIX + t + ".enable", true);
+ nickname = cs.getString(PCERT_PREFIX + t + ".nickname", "");
+ } catch (Exception e) {
+ }
+
+ if (!enable)
+ continue;
+
+ if (t.equals("sslserver"))
+ continue;
+
+ try {
+ if (ConfigurationUtils.findCertificate(tokenname, nickname)) {
+ CMS.debug("CertRequestPanel cleanup: deleting certificate (" + nickname + ").");
+ ConfigurationUtils.deleteCert(tokenname, nickname);
+ }
+ } catch (Exception e) {
+ CMS.debug("CertRequestPanel cleanup: failed to delete certificate ("
+ + nickname + "). Exception: " + e.toString());
+ }
+ }
+
+ try {
+ @SuppressWarnings("unused")
+ boolean done = cs.getBoolean("preop.CertRequestPanel.done"); // check for errors
+ cs.putBoolean("preop.CertRequestPanel.done", false);
+ cs.commit(false);
+ } catch (Exception e) {
+ }
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ boolean s = cs.getBoolean("preop.CertRequestPanel.done",
+ false);
+
+ if (s != true) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+
+ return false;
+ }
+
+ public void getCert(IConfigStore config,
+ Context context, String certTag, Cert cert) {
+ try {
+
+ String subsystem = config.getString(PCERT_PREFIX + certTag + ".subsystem");
+ String certs = config.getString(subsystem + "." + certTag + ".cert", "");
+
+ if (cert != null) {
+ String certf = certs;
+
+ CMS.debug("CertRequestPanel getCert: certTag=" + certTag + " cert=" + certs);
+
+ //get and set formated cert
+ if (!certs.startsWith("...")) {
+ certf = CryptoUtil.certFormat(certs);
+ }
+ cert.setCert(certf);
+
+ //get and set cert pretty print
+ byte[] certb = CryptoUtil.base64Decode(certs);
+ CertPrettyPrint pp = new CertPrettyPrint(certb);
+ cert.setCertpp(pp.toString(Locale.getDefault()));
+ } else {
+ CMS.debug("CertRequestPanel::getCert() - cert is null!");
+ return;
+ }
+ String userfriendlyname = config.getString(
+ PCERT_PREFIX + certTag + ".userfriendlyname");
+
+ cert.setUserFriendlyName(userfriendlyname);
+ String type = config.getString(PCERT_PREFIX + certTag + ".type");
+
+ cert.setType(type);
+ String dn = config.getString(PCERT_PREFIX + certTag + ".dn");
+
+ cert.setDN(dn);
+ } catch (Exception e) {
+ CMS.debug("CertRequestPanel:getCert" + e.toString());
+ } // try
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+
+ CMS.debug("CertRequestPanel: display()");
+ context.put("title", "Requests and Certificates");
+
+ try {
+ mCerts = new Vector<Cert>();
+
+ IConfigStore config = CMS.getConfigStore();
+
+ String certTags = config.getString("preop.cert.list");
+ String csType = config.getString("cs.type");
+ StringTokenizer st = new StringTokenizer(certTags, ",");
+
+ while (st.hasMoreTokens()) {
+ String certTag = st.nextToken();
+
+ try {
+ String subsystem = config.getString(PCERT_PREFIX + certTag + ".subsystem");
+ String nickname = config.getString(subsystem + "." + certTag + ".nickname");
+ String tokenname = config.getString(subsystem + "." + certTag + ".tokenname");
+
+ Cert c = new Cert(tokenname, nickname, certTag);
+ ConfigurationUtils.handleCertRequest(config, certTag, c);
+
+ String type = config.getString(PCERT_PREFIX + certTag + ".type");
+ c.setType(type);
+
+ boolean enable = config.getBoolean(PCERT_PREFIX + certTag + ".enable", true);
+ c.setEnable(enable);
+ getCert(config, context, certTag, c);
+
+ c.setSubsystem(subsystem);
+ mCerts.addElement(c);
+
+ if (csType.equals("TPS") && certTag.equals("subsystem")) {
+ // update nicknames in case they have changed
+ if (!tokenname.isEmpty() && !tokenname.equals("internal")
+ && !tokenname.equals("Internal Key Storage Token"))
+ nickname = tokenname + ":" + nickname;
+
+ config.putString("conn.ca1.clientNickname", nickname);
+ config.putString("conn.drm1.clientNickname", nickname);
+ config.putString("conn.tks1.clientNickname", nickname);
+ }
+ } catch (Exception e) {
+ CMS.debug("CertRequestPanel:display() Exception caught: " + e.toString() +
+ " for certTag " + certTag);
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("CertRequestPanel:display() Exception caught: " + e.toString());
+ System.err.println("Exception caught: " + e.toString());
+
+ } // try
+
+ context.put("reqscerts", mCerts);
+ context.put("status", "display");
+ // context.put("status_token", "None");
+ context.put("panel", "admin/console/config/certrequestpanel.vm");
+
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ CMS.debug("CertRequestPanel: in update()");
+ boolean hasErr = false;
+ IConfigStore config = CMS.getConfigStore();
+
+ if (isPanelDone()) {
+ context.put("updateStatus", "success");
+ return;
+ }
+
+ Enumeration<Cert> c = mCerts.elements();
+ while (c.hasMoreElements()) {
+ Cert cert = c.nextElement();
+ if (hasErr) continue;
+
+ int ret=0;
+ try {
+ cert.setCert(HttpInput.getCert(request, cert.getCertTag()));
+ cert.setCertChain(HttpInput.getCertChain(request, cert.getCertTag() + "_cc"));
+
+ ret = ConfigurationUtils.handleCerts(cert);
+ ConfigurationUtils.setCertPermissions(cert.getCertTag());
+ } catch (Exception e) {
+ CMS.debug("Exception in configuring system certificate " + cert.getCertTag() + ": " + e);
+ e.printStackTrace();
+ hasErr = true;
+ }
+ if (ret != 0) {
+ CMS.debug("System certificates not configured " + cert.getCertTag());
+ }
+ }
+ // end new
+
+ if (!hasErr) {
+ try {
+ config.putBoolean("preop.CertRequestPanel.done", true);
+ config.commit(false);
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ CMS.debug("Unable to commit changes to CS,cfg: " +e);
+ }
+ context.put("updateStatus", "success");
+ } else {
+ context.put("updateStatus", "failure");
+ }
+ }
+
+ /**
+ * If validate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("title", "Certificate Request");
+ context.put("panel", "admin/console/config/certrequestpanel.vm");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java
new file mode 100644
index 000000000..789c0aab5
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java
@@ -0,0 +1,670 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.math.BigInteger;
+import java.util.Date;
+
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.ldap.LDAPException;
+import netscape.security.pkcs.PKCS10;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import org.apache.velocity.context.Context;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.PrivateKey;
+import org.mozilla.jss.crypto.X509Certificate;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.profile.CertInfoProfile;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+import com.netscape.cmsutil.http.HttpClient;
+import com.netscape.cmsutil.http.HttpRequest;
+import com.netscape.cmsutil.http.HttpResponse;
+import com.netscape.cmsutil.http.JssSSLSocketFactory;
+import com.netscape.cmsutil.xml.XMLObject;
+
+public class CertUtil {
+ static final int LINE_COUNT = 76;
+
+ public static X509CertImpl createRemoteCert(String hostname,
+ int port, String content, HttpServletResponse response, WizardPanelBase panel)
+ throws IOException {
+ HttpClient httpclient = new HttpClient();
+ String c = null;
+ CMS.debug("CertUtil createRemoteCert: content " + content);
+ try {
+ JssSSLSocketFactory factory = new JssSSLSocketFactory();
+
+ httpclient = new HttpClient(factory);
+ httpclient.connect(hostname, port);
+ HttpRequest httprequest = new HttpRequest();
+
+ httprequest.setMethod(HttpRequest.POST);
+ httprequest.setURI("/ca/ee/ca/profileSubmit");
+ httprequest.setHeader("user-agent", "HTTPTool/1.0");
+ httprequest.setHeader("content-length", "" + content.length());
+ httprequest.setHeader("content-type",
+ "application/x-www-form-urlencoded");
+ httprequest.setContent(content);
+ HttpResponse httpresponse = httpclient.send(httprequest);
+
+ c = httpresponse.getContent();
+ } catch (Exception e) {
+ CMS.debug("CertUtil createRemoteCert: " + e.toString());
+ throw new IOException(e.toString());
+ }
+
+ if (c != null) {
+ try {
+ ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes());
+ XMLObject parser = null;
+
+ try {
+ parser = new XMLObject(bis);
+ } catch (Exception e) {
+ CMS.debug("CertUtil::createRemoteCert() - "
+ + "Exception=" + e.toString());
+ throw new IOException(e.toString());
+ }
+ String status = parser.getValue("Status");
+
+ CMS.debug("CertUtil createRemoteCert: status=" + status);
+ if (status.equals("2")) {
+ //relogin to the security domain
+ panel.reloginSecurityDomain(response);
+ return null;
+ } else if (!status.equals("0")) {
+ String error = parser.getValue("Error");
+ throw new IOException(error);
+ }
+
+ String b64 = parser.getValue("b64");
+
+ CMS.debug("CertUtil createRemoteCert: " + b64);
+ b64 = CryptoUtil.normalizeCertAndReq(b64);
+ byte[] b = CryptoUtil.base64Decode(b64);
+
+ return new X509CertImpl(b);
+ } catch (Exception e) {
+ CMS.debug("CertUtil createRemoteCert: " + e.toString());
+ throw new IOException(e.toString());
+ }
+ }
+
+ return null;
+ }
+
+ public static String getPKCS10(IConfigStore config, String prefix,
+ Cert certObj, Context context) throws IOException {
+ String certTag = certObj.getCertTag();
+
+ X509Key pubk = null;
+ try {
+ String pubKeyType = config.getString(
+ prefix + certTag + ".keytype");
+ String algorithm = config.getString(
+ prefix + certTag + ".keyalgorithm");
+ if (pubKeyType.equals("rsa")) {
+ String pubKeyModulus = config.getString(
+ prefix + certTag + ".pubkey.modulus");
+ String pubKeyPublicExponent = config.getString(
+ prefix + certTag + ".pubkey.exponent");
+ pubk = CryptoUtil.getPublicX509Key(
+ CryptoUtil.string2byte(pubKeyModulus),
+ CryptoUtil.string2byte(pubKeyPublicExponent));
+ } else if (pubKeyType.equals("ecc")) {
+ String pubKeyEncoded = config.getString(
+ prefix + certTag + ".pubkey.encoded");
+ pubk = CryptoUtil.getPublicX509ECCKey(
+ CryptoUtil.string2byte(pubKeyEncoded));
+ } else {
+ CMS.debug("CertRequestPanel::getPKCS10() - "
+ + "public key type is unsupported!");
+ throw new IOException("public key type is unsupported");
+ }
+
+ if (pubk != null) {
+ CMS.debug("CertRequestPanel: got public key");
+ } else {
+ CMS.debug("CertRequestPanel: error getting public key null");
+ throw new IOException("public key is null");
+ }
+ // get private key
+ String privKeyID = config.getString(prefix + certTag + ".privkey.id");
+ byte[] keyIDb = CryptoUtil.string2byte(privKeyID);
+
+ PrivateKey privk = CryptoUtil.findPrivateKeyFromID(keyIDb);
+
+ if (privk != null) {
+ CMS.debug("CertRequestPanel: got private key");
+ } else {
+ CMS.debug("CertRequestPanel: error getting private key null");
+ }
+
+ // construct cert request
+ String dn = config.getString(prefix + certTag + ".dn");
+
+ PKCS10 certReq = null;
+ certReq = CryptoUtil.createCertificationRequest(dn, pubk,
+ privk, algorithm);
+ byte[] certReqb = certReq.toByteArray();
+ String certReqs = CryptoUtil.base64Encode(certReqb);
+
+ return certReqs;
+ } catch (Throwable e) {
+ CMS.debug(e);
+ if (context != null) {
+ context.put("errorString", e.toString());
+ }
+ CMS.debug("CertUtil getPKCS10: " + e.toString());
+ throw new IOException(e.toString());
+ }
+ }
+
+ /*
+ * create requests so renewal can work on these initial certs
+ */
+ public static IRequest createLocalRequest(IRequestQueue queue, String serialNum, X509CertInfo info)
+ throws EBaseException {
+ // RequestId rid = new RequestId(serialNum);
+ // just need a request, no need to get into a queue
+ // IRequest r = new EnrollmentRequest(rid);
+ CMS.debug("CertUtil: createLocalRequest for serial: " + serialNum);
+ IRequest req = queue.newRequest("enrollment");
+ CMS.debug("certUtil: newRequest called");
+ req.setExtData("profile", "true");
+ req.setExtData("requestversion", "1.0.0");
+ req.setExtData("req_seq_num", "0");
+ req.setExtData(IEnrollProfile.REQUEST_CERTINFO, info);
+ req.setExtData(IEnrollProfile.REQUEST_EXTENSIONS,
+ new CertificateExtensions());
+ req.setExtData("requesttype", "enrollment");
+ req.setExtData("requestor_name", "");
+ req.setExtData("requestor_email", "");
+ req.setExtData("requestor_phone", "");
+ req.setExtData("profileRemoteHost", "");
+ req.setExtData("profileRemoteAddr", "");
+ req.setExtData("requestnotes", "");
+ req.setExtData("isencryptioncert", "false");
+ req.setExtData("profileapprovedby", "system");
+
+ // mark request as complete
+ CMS.debug("certUtil: calling setRequestStatus");
+ req.setRequestStatus(RequestStatus.COMPLETE);
+
+ return req;
+ }
+
+ /**
+ * update local cert request with the actual request
+ * called from CertRequestPanel.java
+ */
+ public static void updateLocalRequest(IConfigStore config, String certTag, String certReq, String reqType,
+ String subjectName) {
+ try {
+ CMS.debug("Updating local request... certTag=" + certTag);
+ RequestId rid = new RequestId(config.getString("preop.cert." + certTag + ".reqId"));
+
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(
+ ICertificateAuthority.ID);
+
+ IRequestQueue queue = ca.getRequestQueue();
+ if (queue != null) {
+ IRequest req = queue.findRequest(rid);
+ if (req != null) {
+ if (!certReq.equals(""))
+ req.setExtData("cert_request", certReq);
+ req.setExtData("cert_request_type", reqType);
+ if (subjectName != null) {
+ req.setExtData("subject", subjectName);
+ new X500Name(subjectName); // check for errors
+ }
+ }
+ queue.updateRequest(req);
+ } else {
+ CMS.debug("CertUtil:updateLocalRequest - request queue = null");
+ }
+ } catch (Exception e) {
+ CMS.debug("CertUtil:updateLocalRequest - Exception:" + e.toString());
+ }
+ }
+
+ /**
+ * reads from the admin cert profile caAdminCert.profile and takes the first
+ * entry in the list of allowed algorithms. Users that wish a different algorithm
+ * can specify it in the profile using default.params.signingAlg
+ */
+
+ public static String getAdminProfileAlgorithm(IConfigStore config) {
+ String algorithm = "SHA256withRSA";
+ try {
+ String caSigningKeyType = config.getString("preop.cert.signing.keytype", "rsa");
+ String pfile = config.getString("profile.caAdminCert.config");
+ FileInputStream fis = new FileInputStream(pfile);
+ DataInputStream in = new DataInputStream(fis);
+ BufferedReader br = new BufferedReader(new InputStreamReader(in));
+
+ String strLine;
+ while ((strLine = br.readLine()) != null) {
+ String marker2 = "default.params.signingAlg=";
+ int indx = strLine.indexOf(marker2);
+ if (indx != -1) {
+ String alg = strLine.substring(indx + marker2.length());
+ if ((alg.length() > 0) && (!alg.equals("-"))) {
+ algorithm = alg;
+ break;
+ }
+ ;
+ }
+ ;
+
+ String marker = "signingAlgsAllowed=";
+ indx = strLine.indexOf(marker);
+ if (indx != -1) {
+ String[] algs = strLine.substring(indx + marker.length()).split(",");
+ for (int i = 0; i < algs.length; i++) {
+ if ((caSigningKeyType.equals("rsa") && (algs[i].indexOf("RSA") != -1)) ||
+ (caSigningKeyType.equals("ecc") && (algs[i].indexOf("EC") != -1))) {
+ algorithm = algs[i];
+ break;
+ }
+ }
+ }
+ }
+ in.close();
+ } catch (Exception e) {
+ CMS.debug("getAdminProfleAlgorithm: exception: " + e);
+ }
+ return algorithm;
+ }
+
+ public static X509CertImpl createLocalCert(IConfigStore config, X509Key x509key,
+ String prefix, String certTag, String type, Context context) throws IOException {
+
+ CMS.debug("Creating local certificate... certTag=" + certTag);
+ String profile = null;
+
+ try {
+ profile = config.getString(prefix + certTag + ".profile");
+ } catch (Exception e) {
+ }
+
+ X509CertImpl cert = null;
+ ICertificateAuthority ca = null;
+ ICertificateRepository cr = null;
+ RequestId reqId = null;
+ String profileId = null;
+ IRequestQueue queue = null;
+ IRequest req = null;
+
+ try {
+ String dn = config.getString(prefix + certTag + ".dn");
+ String keyAlgorithm = null;
+ Date date = new Date();
+
+ X509CertInfo info = null;
+
+ if (certTag.equals("admin")) {
+ keyAlgorithm = getAdminProfileAlgorithm(config);
+ } else {
+ keyAlgorithm = config.getString(prefix + certTag + ".keyalgorithm");
+ }
+ ca = (ICertificateAuthority) CMS.getSubsystem(
+ ICertificateAuthority.ID);
+ cr = ca.getCertificateRepository();
+ BigInteger serialNo = cr.getNextSerialNumber();
+ if (type.equals("selfsign")) {
+ CMS.debug("Creating local certificate... issuerdn=" + dn);
+ CMS.debug("Creating local certificate... dn=" + dn);
+ info = CryptoUtil.createX509CertInfo(x509key, serialNo, dn, dn, date, date, keyAlgorithm);
+ } else {
+ String issuerdn = config.getString("preop.cert.signing.dn", "");
+ CMS.debug("Creating local certificate... issuerdn=" + issuerdn);
+ CMS.debug("Creating local certificate... dn=" + dn);
+
+ info = CryptoUtil.createX509CertInfo(x509key, serialNo, issuerdn, dn, date, date, keyAlgorithm);
+ }
+ CMS.debug("Cert Template: " + info.toString());
+
+ String instanceRoot = config.getString("instanceRoot");
+
+ String configurationRoot = config.getString("configurationRoot");
+
+ CertInfoProfile processor = new CertInfoProfile(
+ instanceRoot + configurationRoot + profile);
+
+ // cfu - create request to enable renewal
+ try {
+ queue = ca.getRequestQueue();
+ if (queue != null) {
+ req = createLocalRequest(queue, serialNo.toString(), info);
+ CMS.debug("CertUtil profile name= " + profile);
+ req.setExtData("req_key", x509key.toString());
+
+ // store original profile id in cert request
+ int idx = profile.lastIndexOf('.');
+ if (idx == -1) {
+ CMS.debug("CertUtil profileName contains no .");
+ req.setExtData("origprofileid", profile);
+ } else {
+ String name = profile.substring(0, idx);
+ req.setExtData("origprofileid", name);
+ }
+
+ // store mapped profile ID for use in renewal
+ profileId = processor.getProfileIDMapping();
+ req.setExtData("profileid", profileId);
+ req.setExtData("profilesetid", processor.getProfileSetIDMapping());
+
+ reqId = req.getRequestId();
+ config.putString("preop.cert." + certTag + ".reqId", reqId.toString());
+ } else {
+ CMS.debug("certUtil: requestQueue null");
+ }
+ } catch (Exception e) {
+ CMS.debug("Creating local request exception:" + e.toString());
+ }
+
+ processor.populate(req, info);
+
+ String caPriKeyID = config.getString(
+ prefix + "signing" + ".privkey.id");
+ byte[] keyIDb = CryptoUtil.string2byte(caPriKeyID);
+ PrivateKey caPrik = CryptoUtil.findPrivateKeyFromID(
+ keyIDb);
+
+ if (caPrik == null) {
+ CMS.debug("CertUtil::createSelfSignedCert() - "
+ + "CA private key is null!");
+ throw new IOException("CA private key is null");
+ } else {
+ CMS.debug("CertUtil createSelfSignedCert: got CA private key");
+ }
+
+ String keyAlgo = x509key.getAlgorithm();
+ CMS.debug("key algorithm is " + keyAlgo);
+ String caSigningKeyType =
+ config.getString("preop.cert.signing.keytype", "rsa");
+ String caSigningKeyAlgo = "";
+ if (type.equals("selfsign")) {
+ caSigningKeyAlgo = config.getString("preop.cert.signing.keyalgorithm", "SHA256withRSA");
+ } else {
+ caSigningKeyAlgo = config.getString("preop.cert.signing.signingalgorithm", "SHA256withRSA");
+ }
+
+ CMS.debug("CA Signing Key type " + caSigningKeyType);
+ CMS.debug("CA Signing Key algorithm " + caSigningKeyAlgo);
+
+ if (caSigningKeyType.equals("ecc")) {
+ CMS.debug("CA signing cert is ECC");
+ cert = CryptoUtil.signECCCert(caPrik, info,
+ caSigningKeyAlgo);
+ } else {
+ CMS.debug("CA signing cert is not ecc");
+ cert = CryptoUtil.signCert(caPrik, info,
+ caSigningKeyAlgo);
+ }
+
+ if (cert != null) {
+ CMS.debug("CertUtil createSelfSignedCert: got cert signed");
+ }
+ } catch (Exception e) {
+ CMS.debug(e);
+ CMS.debug("NamePanel configCert() exception caught:" + e.toString());
+ }
+
+ if (cr == null) {
+ if (context != null) {
+ context.put("errorString", "Ceritifcate Authority is not ready to serve.");
+ }
+ throw new IOException("Ceritifcate Authority is not ready to serve.");
+ }
+
+ ICertRecord record = null;
+ try {
+ MetaInfo meta = new MetaInfo();
+ if (reqId != null) {
+ meta.set(ICertRecord.META_REQUEST_ID, reqId.toString());
+ }
+
+ meta.set(ICertRecord.META_PROFILE_ID, profileId);
+ record = cr.createCertRecord(
+ cert.getSerialNumber(), cert, meta);
+ } catch (Exception e) {
+ CMS.debug(
+ "NamePanel configCert: failed to add metainfo. Exception: " + e.toString());
+ }
+
+ try {
+ cr.addCertificateRecord(record);
+ CMS.debug(
+ "NamePanel configCert: finished adding certificate record.");
+ } catch (Exception e) {
+ CMS.debug(
+ "NamePanel configCert: failed to add certificate record. Exception: "
+ + e.toString());
+ try {
+ cr.deleteCertificateRecord(record.getSerialNumber());
+ cr.addCertificateRecord(record);
+ } catch (Exception ee) {
+ CMS.debug("NamePanel update: Exception: " + ee.toString());
+ }
+ }
+
+ if (req != null) {
+ // update request with cert
+ req.setExtData(IEnrollProfile.REQUEST_ISSUED_CERT, cert);
+
+ // store request in db
+ try {
+ CMS.debug("certUtil: before updateRequest");
+ if (queue != null) {
+ queue.updateRequest(req);
+ }
+ } catch (Exception e) {
+ CMS.debug("Exception in updateRequest" + e);
+ }
+ }
+
+ return cert;
+ }
+
+ public static void addUserCertificate(X509CertImpl cert) {
+ IConfigStore cs = CMS.getConfigStore();
+ int num = 0;
+ try {
+ num = cs.getInteger("preop.subsystem.count", 0);
+ } catch (Exception e) {
+ }
+ IUGSubsystem system = (IUGSubsystem) (CMS.getSubsystem(IUGSubsystem.ID));
+ String id = "user" + num;
+
+ try {
+ String sysType = cs.getString("cs.type", "");
+ String machineName = cs.getString("machineName", "");
+ String securePort = cs.getString("service.securePort", "");
+ id = sysType + "-" + machineName + "-" + securePort;
+ } catch (Exception e1) {
+ // ignore
+ }
+
+ num++;
+ cs.putInteger("preop.subsystem.count", num);
+ cs.putInteger("subsystem.count", num);
+
+ try {
+ cs.commit(false);
+ } catch (Exception e) {
+ }
+
+ IUser user = null;
+ X509CertImpl[] certs = new X509CertImpl[1];
+ CMS.debug("CertUtil addUserCertificate starts");
+ try {
+ user = system.createUser(id);
+ user.setFullName(id);
+ user.setEmail("");
+ user.setPassword("");
+ user.setUserType("agentType");
+ user.setState("1");
+ user.setPhone("");
+ certs[0] = cert;
+ user.setX509Certificates(certs);
+ system.addUser(user);
+ CMS.debug("CertUtil addUserCertificate: successfully add the user");
+ } catch (LDAPException e) {
+ CMS.debug("CertUtil addUserCertificate" + e.toString());
+ if (e.getLDAPResultCode() != LDAPException.ENTRY_ALREADY_EXISTS) {
+ try {
+ user = system.getUser(id);
+ user.setX509Certificates(certs);
+ } catch (Exception ee) {
+ CMS.debug("CertUtil addUserCertificate: successfully find the user");
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("CertUtil addUserCertificate addUser " + e.toString());
+ }
+
+ try {
+ system.addUserCert(user);
+ CMS.debug("CertUtil addUserCertificate: successfully add the user certificate");
+ } catch (Exception e) {
+ CMS.debug("CertUtil addUserCertificate exception=" + e.toString());
+ }
+
+ IGroup group = null;
+ String groupName = "Subsystem Group";
+
+ try {
+ group = system.getGroupFromName(groupName);
+ if (!group.isMember(id)) {
+ group.addMemberName(id);
+ system.modifyGroup(group);
+ CMS.debug("CertUtil addUserCertificate: update: successfully added the user to the group.");
+ }
+ } catch (Exception e) {
+ CMS.debug("CertUtil addUserCertificate update: modifyGroup " + e.toString());
+ }
+ }
+
+ /*
+ * formats a cert fingerprints
+ */
+ public static String fingerPrintFormat(String content) {
+ if (content == null || content.length() == 0) {
+ return "";
+ }
+
+ StringBuffer result = new StringBuffer();
+ result.append("Fingerprints:\n");
+
+ while (content.length() >= LINE_COUNT) {
+ result.append(content.substring(0, LINE_COUNT));
+ result.append("\n");
+ content = content.substring(LINE_COUNT);
+ }
+ if (content.length() > 0)
+ result.append(content);
+ result.append("\n");
+
+ return result.toString();
+ }
+
+ public static boolean privateKeyExistsOnToken(String certTag,
+ String tokenname, String nickname) {
+ IConfigStore cs = CMS.getConfigStore();
+ String givenid = "";
+ try {
+ givenid = cs.getString("preop.cert." + certTag + ".privkey.id");
+ } catch (Exception e) {
+ CMS.debug("CertUtil privateKeyExistsOnToken: we did not generate private key yet.");
+ return false;
+ }
+
+ String fullnickname = nickname;
+
+ if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token")) {
+ fullnickname = tokenname + ":" + nickname;
+ }
+
+ X509Certificate cert = null;
+ CryptoManager cm = null;
+ try {
+ cm = CryptoManager.getInstance();
+ cert = cm.findCertByNickname(fullnickname);
+ } catch (Exception e) {
+ CMS.debug("CertUtil privateKeyExistsOnToken: nickname=" + fullnickname + " Exception:" + e.toString());
+ return false;
+ }
+
+ PrivateKey privKey = null;
+ try {
+ privKey = cm.findPrivKeyByCert(cert);
+ } catch (Exception e) {
+ CMS.debug("CertUtil privateKeyExistsOnToken: cant find private key ("
+ + fullnickname + ") exception: " + e.toString());
+ return false;
+ }
+
+ if (privKey == null) {
+ CMS.debug("CertUtil privateKeyExistsOnToken: cant find private key (" + fullnickname + ")");
+ return false;
+ } else {
+ String str = "";
+ try {
+ str = CryptoUtil.byte2string(privKey.getUniqueID());
+ } catch (Exception e) {
+ CMS.debug("CertUtil privateKeyExistsOnToken: encode string Exception: " + e.toString());
+ }
+
+ if (str.equals(givenid)) {
+ CMS.debug("CertUtil privateKeyExistsOnToken: find the private key on the token.");
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/CheckIdentity.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CheckIdentity.java
new file mode 100644
index 000000000..046fb111d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CheckIdentity.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cmsutil.xml.XMLObject;
+
+public class CheckIdentity extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1647682040815275807L;
+ private final static String SUCCESS = "0";
+
+ public CheckIdentity() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+
+ CMS.debug("CheckIdentity init");
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ try {
+ authenticate(cmsReq);
+ } catch (Exception e) {
+ CMS.debug("CheckIdentity authentication failed");
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "",
+ e.toString()));
+ outputError(httpResp, "Error: Not authenticated");
+ return;
+ }
+
+ try {
+ XMLObject xmlObj = null;
+
+ xmlObj = new XMLObject();
+
+ Node root = xmlObj.createRoot("XMLResponse");
+
+ xmlObj.addItemToContainer(root, "Status", SUCCESS);
+ byte[] cb = xmlObj.toByteArray();
+
+ outputResult(httpResp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("Failed to send the XML output");
+ }
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {
+ // do nothing, ie, it will not return the default javascript.
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java
new file mode 100644
index 000000000..956c285b5
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java
@@ -0,0 +1,33 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.ssl.SSLCertificateApprovalCallback;
+
+public class ConfigCertApprovalCallback
+ implements SSLCertificateApprovalCallback {
+
+ public ConfigCertApprovalCallback() {
+ }
+
+ public boolean approve(X509Certificate cert,
+ SSLCertificateApprovalCallback.ValidityStatus status) {
+ return true;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigHSMLoginPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigHSMLoginPanel.java
new file mode 100644
index 000000000..03233042c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigHSMLoginPanel.java
@@ -0,0 +1,296 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.util.IncorrectPasswordException;
+import org.mozilla.jss.util.Password;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.property.PropertySet;
+import com.netscape.certsrv.util.HttpInput;
+import com.netscape.cms.servlet.wizard.WizardServlet;
+import com.netscape.cmsutil.password.PlainPasswordReader;
+import com.netscape.cmsutil.password.PlainPasswordWriter;
+
+public class ConfigHSMLoginPanel extends WizardPanelBase {
+ private CryptoManager mCryptoManager = null;
+ private String mPwdFilePath = "";
+
+ public ConfigHSMLoginPanel() {
+ }
+
+ public void init(ServletConfig config, int panelno) throws ServletException {
+ try {
+ mCryptoManager = CryptoManager.getInstance();
+ mPwdFilePath = CMS.getConfigStore().getString(
+ "passwordFile");
+ } catch (Exception e) {
+ CMS.debug("ConfigHSMLoginPanel: " + e.toString());
+ }
+ setPanelNo(panelno);
+ setName("ConfigHSMLogin");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) throws ServletException {
+ try {
+ mCryptoManager = CryptoManager.getInstance();
+ mPwdFilePath = CMS.getConfigStore().getString(
+ "passwordFile");
+ } catch (Exception e) {
+ CMS.debug("ConfigHSMLoginPanel: " + e.toString());
+ }
+ setPanelNo(panelno);
+ setName("ConfigHSMLogin");
+ setId(id);
+ }
+
+ public void cleanUp() throws IOException {
+ }
+
+ public boolean isPanelDone() {
+ return true;
+ }
+
+ public boolean isSubPanel() {
+ return true;
+ }
+
+ public boolean isLoopbackPanel() {
+ return true;
+ }
+
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+
+ CMS.debug("ConfigHSMLoginPanel: in display()");
+ context.put("title", "Security Module Login");
+
+ // get token selected to be logged in
+ String tokName = null;
+ tokName = HttpInput.getTokenName(request, "SecToken");
+
+ if (tokName != null) {
+ CMS.debug("ConfigHSMLoginPanel: selected token name= " + tokName);
+ } else {
+ CMS.debug("ConfigHSMLoginPanel: missing SecToken name");
+ context.put("error", "noTokenName");
+ context.put("panel", "admin/console/config/config_hsmloginpanel.vm");
+ return;
+ }
+ CryptoToken token = null;
+
+ try {
+ token = mCryptoManager.getTokenByName(tokName);
+ } catch (Exception e) {
+ CMS.debug(
+ "ConfigHSMLoginPanel: getTokenByName() failed: "
+ + e.toString());
+ context.put("error", "tokenNotFound:" + tokName);
+ context.put("panel", "admin/console/config/config_hsmloginpanel.vm");
+ return;
+ }
+ // first see if password in password file, try to login
+ PlainPasswordReader pr = new PlainPasswordReader();
+
+ try {
+ pr.init(mPwdFilePath);
+ } catch (Exception e) {
+ // is ok to not have it
+ CMS.debug("ConfigHSMLoginPanel: passwrd file path: " + e.toString());
+ }
+ CMS.debug("ConfigHSMLoginPanel: checking if passwd in cache");
+ String tokPwd = pr.getPassword("hardware-" + tokName);
+
+ boolean loggedIn = false;
+
+ if (tokPwd == null) {
+ CMS.debug("ConfigHSMLoginPanel: passwd not in cache");
+ } else {
+ loggedIn = loginToken(token, tokPwd, context);
+ }
+
+ if (!loggedIn) {
+ context.put("status", "display");
+ }
+ context.put("panel", "admin/console/config/config_hsmloginpanel.vm");
+ context.put("SecToken", tokName);
+ }
+
+ // if logged in successfully, returns true
+ private boolean loginToken(CryptoToken token, String tokPwd, Context context) {
+ boolean rv = true;
+ Password password = null;
+
+ password = new Password(tokPwd.toCharArray());
+
+ try {
+ if (token.passwordIsInitialized()) {
+ CMS.debug(
+ "ConfigHSMLoginPanel: loginToken():token password is initialized");
+ if (!token.isLoggedIn()) {
+ CMS.debug(
+ "ConfigHSMLoginPanel: loginToken():Token is not logged in, try it");
+ token.login(password);
+ context.put("status", "justLoggedIn");
+ } else {
+ CMS.debug(
+ "ConfigHSMLoginPanel:Token has already logged on");
+ context.put("status", "alreadyLoggedIn");
+ }
+ } else {
+ CMS.debug(
+ "ConfigHSMLoginPanel: loginToken():Token password not initialized");
+ context.put("status", "tokenPasswordNotInitialized");
+ rv = false;
+ }
+
+ } catch (IncorrectPasswordException e) {
+ context.put("status", "incorrectPassword");
+ context.put("errorString", e.toString());
+ CMS.debug("ConfigHSMLoginPanel: loginToken():" + e.toString());
+ rv = false;
+ } catch (Exception e) {
+ CMS.debug("ConfigHSMLoginPanel: loginToken():" + e.toString());
+ context.put("errorString", e.toString());
+ rv = false;
+ }
+ return rv;
+ }
+
+ // XXX how do you do this?
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ Descriptor choiceDesc = new Descriptor(IDescriptor.CHOICE, "", "", null); /* no default parameters */
+
+ set.add(
+ "choice", choiceDesc);
+
+ return set;
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+
+ CMS.debug("ConfigHSMLoginPanel: in update()");
+
+ String uTokName = null;
+ String uPasswd = null;
+ try {
+ uTokName = HttpInput.getTokenName(request, "uTokName");
+ uPasswd = HttpInput.getPassword(request, "__uPasswd");
+ } catch (Exception e) {
+ }
+
+ if (uPasswd == null) {
+ CMS.debug("ConfigHSMLoginPanel: password not found");
+ context.put("error", "no password");
+ context.put("panel", "admin/console/config/config_hsmloginpanel.vm");
+ context.put("updateStatus", "no password");
+ return;
+ } else {
+ CMS.debug("ConfigHSMLoginPanel: got password");
+
+ CryptoToken token = null;
+
+ try {
+ token = mCryptoManager.getTokenByName(uTokName);
+ } catch (Exception e) {
+ CMS.debug(
+ "ConfigHSMLoginPanel: getTokenByName() failed: "
+ + e.toString());
+ context.put("error", "tokenNotFound:" + uTokName);
+ }
+
+ try {
+ if (loginToken(token, uPasswd, context) == false) {
+ CMS.debug(
+ "ConfigHSMLoginPanel:loginToken failed for "
+ + uTokName);
+ context.put("error", "tokenLoginFailed");
+ context.put("updateStatus", "login failed");
+ context.put("panel",
+ "admin/console/config/config_hsmloginpanel.vm");
+ return;
+ }
+ CMS.debug(
+ "ConfigHSMLoginPanel: update(): just logged in successfully");
+ PlainPasswordWriter pw = new PlainPasswordWriter();
+
+ pw.init(mPwdFilePath);
+ pw.putPassword("hardware-" + uTokName, uPasswd);
+ pw.commit();
+
+ } catch (FileNotFoundException e) {
+ CMS.debug(
+ "ConfigHSMLoginPanel: update(): Exception caught: "
+ + e.toString() + " writing to " + mPwdFilePath);
+ CMS.debug(
+ "ConfigHSMLoginPanel: update(): password not written to cache");
+ System.err.println("Exception caught: " + e.toString());
+ context.put("error", "Exception:" + e.toString());
+ } catch (Exception e) {
+ CMS.debug(
+ "ConfigHSMLoginPanel: update(): Exception caught: "
+ + e.toString());
+ System.err.println("Exception caught: " + e.toString());
+ context.put("error", "Exception:" + e.toString());
+ }
+
+ } // found password
+
+ context.put("panel", "admin/console/config/config_hsmloginpanel.vm");
+ context.put("status", "update");
+ context.put("error", "");
+ context.put("updateStatus", "success");
+
+ }
+
+ /**
+ * If validiate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("title", "Security Module Login");
+ context.put("panel", "admin/console/config/config_hsmloginpanel.vm");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
new file mode 100644
index 000000000..bbfb17374
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
@@ -0,0 +1,4085 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+ package com.netscape.cms.servlet.csadmin;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.CharConversionException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.math.BigInteger;
+import java.net.ConnectException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.security.DigestException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.SignatureException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.interfaces.RSAPublicKey;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.Response;
+import javax.xml.parsers.ParserConfigurationException;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPDN;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPSearchConstraints;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv3;
+import netscape.security.pkcs.ContentInfo;
+import netscape.security.pkcs.PKCS10;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.pkcs.SignerInfo;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509Key;
+
+import org.apache.velocity.context.Context;
+import org.jboss.resteasy.client.ClientResponse;
+import org.jboss.resteasy.client.ClientResponseFailure;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.NicknameConflictException;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.CryptoManager.UserCertConflictException;
+import org.mozilla.jss.NoSuchTokenException;
+import org.mozilla.jss.asn1.ANY;
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.ASN1Value;
+import org.mozilla.jss.asn1.BMPString;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
+import org.mozilla.jss.asn1.OCTET_STRING;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.asn1.SET;
+import org.mozilla.jss.crypto.BadPaddingException;
+import org.mozilla.jss.crypto.Cipher;
+import org.mozilla.jss.crypto.CryptoStore;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.EncryptionAlgorithm;
+import org.mozilla.jss.crypto.IVParameterSpec;
+import org.mozilla.jss.crypto.IllegalBlockSizeException;
+import org.mozilla.jss.crypto.InternalCertificate;
+import org.mozilla.jss.crypto.InvalidKeyFormatException;
+import org.mozilla.jss.crypto.KeyGenAlgorithm;
+import org.mozilla.jss.crypto.KeyGenerator;
+import org.mozilla.jss.crypto.KeyWrapAlgorithm;
+import org.mozilla.jss.crypto.KeyWrapper;
+import org.mozilla.jss.crypto.NoSuchItemOnTokenException;
+import org.mozilla.jss.crypto.ObjectNotFoundException;
+import org.mozilla.jss.crypto.PBEAlgorithm;
+import org.mozilla.jss.crypto.PrivateKey;
+import org.mozilla.jss.crypto.SymmetricKey;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.pkcs11.PK11Store;
+import org.mozilla.jss.pkcs12.AuthenticatedSafes;
+import org.mozilla.jss.pkcs12.CertBag;
+import org.mozilla.jss.pkcs12.PFX;
+import org.mozilla.jss.pkcs12.PasswordConverter;
+import org.mozilla.jss.pkcs12.SafeBag;
+import org.mozilla.jss.pkix.primitive.Attribute;
+import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo;
+import org.mozilla.jss.pkix.primitive.PrivateKeyInfo;
+import org.mozilla.jss.ssl.SSLCertificateApprovalCallback;
+import org.mozilla.jss.util.IncorrectPasswordException;
+import org.mozilla.jss.util.Password;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import com.netscape.certsrv.account.AccountClient;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authorization.IAuthzSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.ResourceNotFoundException;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.PKIClient;
+import com.netscape.certsrv.client.PKIConnection;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+import com.netscape.certsrv.key.KeyData;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.ocsp.IDefStore;
+import com.netscape.certsrv.ocsp.IOCSPAuthority;
+import com.netscape.certsrv.system.InstallToken;
+import com.netscape.certsrv.system.SecurityDomainClient;
+import com.netscape.certsrv.system.TPSConnectorClient;
+import com.netscape.certsrv.system.TPSConnectorData;
+import com.netscape.certsrv.usrgrp.EUsrGrpException;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cms.servlet.admin.UserService;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+import com.netscape.cmsutil.http.HttpClient;
+import com.netscape.cmsutil.http.HttpRequest;
+import com.netscape.cmsutil.http.HttpResponse;
+import com.netscape.cmsutil.http.JssSSLSocketFactory;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+import com.netscape.cmsutil.xml.XMLObject;
+
+/**
+ * Utility class for functions to be used both by the RESTful installer
+ * and the UI Panels.
+ *
+ * @author alee
+ *
+ */
+public class ConfigurationUtils {
+
+ private static final String PCERT_PREFIX = "preop.cert.";
+ public static String SUCCESS = "0";
+ public static String FAILURE = "1";
+ public static String AUTH_FAILURE = "2";
+ public static final BigInteger BIG_ZERO = new BigInteger("0");
+ public static final Long MINUS_ONE = Long.valueOf(-1);
+ public static final String DBUSER = "pkidbuser";
+
+ public static boolean loginToken(CryptoToken token, String tokPwd) throws TokenException,
+ IncorrectPasswordException {
+ boolean rv = true;
+ Password password = null;
+ password = new Password(tokPwd.toCharArray());
+
+ if (token.passwordIsInitialized()) {
+ CMS.debug("loginToken():token password is initialized");
+ if (!token.isLoggedIn()) {
+ CMS.debug("loginToken():Token is not logged in, try it");
+ token.login(password);
+ } else {
+ CMS.debug("loginToken():Token has already logged on");
+ }
+ } else {
+ CMS.debug("loginToken():Token password not initialized");
+ rv = false;
+ }
+ return rv;
+ }
+
+ public static String getHttpResponse(String hostname, int port, boolean secure,
+ String uri, String content, String clientnickname) throws IOException {
+ return getHttpResponse(hostname, port, secure, uri, content, clientnickname, null);
+ }
+
+ public static ClientResponse<String> getClientResponse(String hostname, int port, boolean secure,
+ String path, String content, String clientnickname,
+ SSLCertificateApprovalCallback certApprovalCallback)
+ throws Exception {
+
+ String protocol = secure ? "https" : "http";
+ ClientConfig config = new ClientConfig();
+ config.setServerURI(protocol + "://" + hostname + ":" + port + path);
+ config.setCertNickname(clientnickname);
+
+ PKIClient client = new PKIClient(config);
+ PKIConnection connection = client.getConnection();
+ ClientResponse<String> response = connection.post(content);
+
+ return response;
+ }
+
+ //TODO - replace with Jack's connector code
+ // or as we replace calls with restful calls, remove altogether
+ public static String getHttpResponse(String hostname, int port, boolean secure,
+ String uri, String content, String clientnickname,
+ SSLCertificateApprovalCallback certApprovalCallback)
+ throws IOException {
+ HttpClient httpclient = null;
+ String c = null;
+
+ try {
+ if (secure) {
+ JssSSLSocketFactory factory = null;
+ if (clientnickname != null && clientnickname.length() > 0)
+ factory = new JssSSLSocketFactory(clientnickname);
+ else
+ factory = new JssSSLSocketFactory();
+
+ httpclient = new HttpClient(factory, certApprovalCallback);
+ } else {
+ httpclient = new HttpClient();
+ }
+ httpclient.connect(hostname, port);
+ HttpRequest httprequest = new HttpRequest();
+
+ httprequest.setMethod(HttpRequest.POST);
+ httprequest.setURI(uri);
+ httprequest.setHeader("user-agent", "HTTPTool/1.0");
+ httprequest.setHeader("content-type",
+ "application/x-www-form-urlencoded");
+ if (content != null && content.length() > 0) {
+ String content_c = content;
+ httprequest.setHeader("content-length", "" + content_c.length());
+ httprequest.setContent(content_c);
+ }
+ HttpResponse httpresponse = httpclient.send(httprequest);
+
+ c = httpresponse.getContent();
+ } catch (ConnectException e) {
+ CMS.debug("getHttpResponse: " + e.toString());
+ throw new IOException("The server you tried to contact is not running.");
+ } catch (Exception e) {
+ CMS.debug("getHttpResponse: " + e.toString());
+ throw new IOException(e.toString());
+ } finally {
+ if (httpclient.connected()) {
+ httpclient.disconnect();
+ }
+ }
+
+ return c;
+ }
+
+ public static void importCertChain(String host, int port, String serverPath, String tag)
+ throws IOException, SAXException, ParserConfigurationException, CertificateEncodingException,
+ CertificateException, NotInitializedException, TokenException, EBaseException {
+ IConfigStore cs = CMS.getConfigStore();
+ ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback();
+ XMLObject parser = null;
+ String c = ConfigurationUtils.getHttpResponse(host, port, true, serverPath, null, null,
+ certApprovalCallback);
+ if (c != null) {
+ ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes());
+ parser = new XMLObject(bis);
+ String certchain = parser.getValue("ChainBase64");
+ if ((certchain != null) && (certchain.length() > 0)) {
+ certchain = CryptoUtil.normalizeCertStr(certchain);
+ cs.putString("preop." + tag + ".pkcs7", certchain);
+
+ // separate individual certs in chain for display
+ byte[] decoded = CryptoUtil.base64Decode(certchain);
+ java.security.cert.X509Certificate[] b_certchain = CryptoUtil.getX509CertificateFromPKCS7(decoded);
+ int size = 0;
+
+ if (b_certchain != null) {
+ size = b_certchain.length;
+ }
+ cs.putInteger("preop." + tag + ".certchain.size", size);
+ for (int i = 0; i < size; i++) {
+ byte[] bb = b_certchain[i].getEncoded();
+ cs.putString("preop." + tag + ".certchain." + i,
+ CryptoUtil.normalizeCertStr(CryptoUtil.base64Encode(bb)));
+ }
+
+ cs.commit(false);
+ CryptoUtil.importCertificateChain(certchain);
+ } else {
+ throw new IOException("importCertChain: Security Domain response does not contain certificate chain");
+ }
+ } else {
+ throw new IOException("importCertChain: Failed to get response from security domain");
+ }
+ }
+
+ public static String getInstallToken(String sdhost, int sdport, String user, String passwd) throws Exception {
+ IConfigStore cs = CMS.getConfigStore();
+ boolean oldtoken = cs.getBoolean("cs.useOldTokenInterface", false);
+
+ if (oldtoken) {
+ return ConfigurationUtils.getOldToken(sdhost, sdport, user, passwd);
+ }
+
+ String csType = cs.getString("cs.type");
+
+ ClientConfig config = new ClientConfig();
+ config.setServerURI("https://" + sdhost + ":" + sdport);
+ config.setUsername(user);
+ config.setPassword(passwd);
+
+ PKIClient client = new PKIClient(config);
+ PKIConnection connection = client.getConnection();
+
+ // Ignore the "UNTRUSTED_ISSUER" validity status
+ // during PKI instance creation since we are
+ // utilizing an untrusted temporary CA cert.
+ connection.addIgnoredCertStatus(SSLCertificateApprovalCallback.ValidityStatus.UNTRUSTED_ISSUER);
+
+ // Ignore the "CA_CERT_INVALID" validity status
+ // during PKI instance creation since we are
+ // utilizing an untrusted temporary CA cert.
+ connection.addIgnoredCertStatus(SSLCertificateApprovalCallback.ValidityStatus.CA_CERT_INVALID);
+
+ AccountClient accountClient = new AccountClient(client, "ca");
+ SecurityDomainClient sdClient = new SecurityDomainClient(client, "ca");
+
+ try {
+ accountClient.login();
+ InstallToken token = sdClient.getInstallToken(sdhost, csType);
+ accountClient.logout();
+ return token.getToken();
+
+ } catch (ClientResponseFailure e) {
+ if (e.getResponse().getResponseStatus() == Response.Status.NOT_FOUND) {
+ // try the old servlet
+ String tokenString = getOldCookie(sdhost, sdport, user, passwd);
+ return tokenString;
+ }
+
+ throw e;
+ }
+ }
+
+ public static String getOldCookie(String sdhost, int sdport, String user, String passwd) throws Exception {
+ IConfigStore cs = CMS.getConfigStore();
+
+ String subca_url = "https://" + CMS.getEEHost() + ":"
+ + CMS.getAdminPort() + "/ca/admin/console/config/wizard" +
+ "?p=5&subsystem=" + cs.getString("cs.type");
+
+ String content = "uid=" + URLEncoder.encode(user, "UTF-8") + "&pwd=" + URLEncoder.encode(passwd, "UTF-8") +
+ "&url=" + URLEncoder.encode(subca_url, "UTF-8");
+
+ ClientResponse<String> response = getClientResponse(sdhost, sdport, true, "/ca/admin/ca/getCookie",
+ content, null, null);
+ String body = response.getEntity();
+ return getContentValue(body, "header.session_id");
+ }
+
+ public static String getOldToken(String sdhost, int sdport, String user, String passwd) throws IOException,
+ EPropertyNotFound, EBaseException, URISyntaxException {
+ IConfigStore cs = CMS.getConfigStore();
+
+ String subca_url = "https://" + CMS.getEEHost() + ":"
+ + CMS.getAdminPort() + "/ca/admin/console/config/wizard" +
+ "?p=5&subsystem=" + cs.getString("cs.type");
+
+ String content = "uid=" + URLEncoder.encode(user, "UTF-8") + "&pwd=" + URLEncoder.encode(passwd, "UTF-8") +
+ "&url=" + URLEncoder.encode(subca_url, "UTF-8");
+
+ String response = ConfigurationUtils.getHttpResponse(sdhost, sdport, true,
+ "/ca/admin/ca/getCookie", content, null);
+
+ return getContentValue(response, "header.session_id");
+ }
+
+ public static String getContentValue(String body, String header) {
+ StringTokenizer st = new StringTokenizer(body, "\n");
+
+ while (st.hasMoreTokens()) {
+ String line = st.nextToken();
+ // format for line assumed to be name="value";
+
+ int eqPos = line.indexOf('=');
+ if (eqPos != -1) {
+ String name = line.substring(0, eqPos).trim();
+ String tempval = line.substring(eqPos + 1).trim();
+ String value = tempval.replaceAll("(^\")|(\";$)","");
+
+ if (name.equals(header)) {
+ return value;
+ }
+ }
+ }
+ return null;
+ }
+
+ public static String getGroupName(String uid, String subsystemname) {
+ IUGSubsystem subsystem = (IUGSubsystem) (CMS.getSubsystem(IUGSubsystem.ID));
+ if (subsystem.isMemberOf(uid, "Enterprise CA Administrators") && subsystemname.equals("CA")) {
+ return "Enterprise CA Administrators";
+ } else if (subsystem.isMemberOf(uid, "Enterprise KRA Administrators") && subsystemname.equals("KRA")) {
+ return "Enterprise KRA Administrators";
+ } else if (subsystem.isMemberOf(uid, "Enterprise OCSP Administrators") && subsystemname.equals("OCSP")) {
+ return "Enterprise OCSP Administrators";
+ } else if (subsystem.isMemberOf(uid, "Enterprise TKS Administrators") && subsystemname.equals("TKS")) {
+ return "Enterprise TKS Administrators";
+ } else if (subsystem.isMemberOf(uid, "Enterprise RA Administrators") && subsystemname.equals("RA")) {
+ return "Enterprise RA Administrators";
+ } else if (subsystem.isMemberOf(uid, "Enterprise TPS Administrators") && subsystemname.equals("TPS")) {
+ return "Enterprise TPS Administrators";
+ }
+ return null;
+ }
+
+ public static String getDomainXML(String hostname, int https_admin_port, boolean https)
+ throws IOException, SAXException, ParserConfigurationException {
+ CMS.debug("getDomainXML start");
+ String c = getHttpResponse(hostname, https_admin_port, https, "/ca/admin/ca/getDomainXML", null, null, null);
+ if (c != null) {
+ ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes());
+ XMLObject parser = null;
+
+ parser = new XMLObject(bis);
+ String status = parser.getValue("Status");
+ CMS.debug("getDomainXML: status=" + status);
+
+ if (status.equals(SUCCESS)) {
+ String domainInfo = parser.getValue("DomainInfo");
+ CMS.debug("getDomainXML: domainInfo=" + domainInfo);
+ return domainInfo;
+ } else {
+ String error = parser.getValue("Error");
+ throw new IOException(error);
+ }
+
+ }
+ return null;
+ }
+
+ public static void getSecurityDomainPorts(String domainXML, String host, int port) throws SAXException,
+ IOException, ParserConfigurationException {
+ ByteArrayInputStream bis = new ByteArrayInputStream(domainXML.getBytes());
+ IConfigStore cs = CMS.getConfigStore();
+
+ XMLObject parser = new XMLObject(bis);
+ Document doc = parser.getDocument();
+ NodeList nodeList = doc.getElementsByTagName("CA");
+
+ int len = nodeList.getLength();
+ CMS.debug("len is " + len);
+ for (int i = 0; i < len; i++) {
+ String hostname = parser.getValuesFromContainer(nodeList.item(i), "Host").elementAt(0);
+ String admin_port = parser.getValuesFromContainer(nodeList.item(i), "SecureAdminPort").elementAt(0);
+ CMS.debug("hostname: <" + hostname + ">");
+ CMS.debug("admin_port: <" + admin_port + ">");
+
+ if (hostname.equals(host) && admin_port.equals(port + "")) {
+ cs.putString("securitydomain.httpport",
+ parser.getValuesFromContainer(nodeList.item(i), "UnSecurePort").elementAt(0));
+ cs.putString("securitydomain.httpsagentport",
+ parser.getValuesFromContainer(nodeList.item(i), "SecureAgentPort").elementAt(0));
+ cs.putString("securitydomain.httpseeport",
+ parser.getValuesFromContainer(nodeList.item(i), "SecurePort").elementAt(0));
+
+ break;
+ }
+ }
+ }
+
+ public static Vector<String> getUrlListFromSecurityDomain(IConfigStore config,
+ String type, String portType)
+ throws EPropertyNotFound, EBaseException, IOException, SAXException, ParserConfigurationException {
+ Vector<String> v = new Vector<String>();
+
+ String hostname = config.getString("securitydomain.host");
+ int httpsadminport = config.getInteger("securitydomain.httpsadminport");
+
+ CMS.debug("getUrlListFromSecurityDomain(): Getting domain.xml from CA...");
+ String c = getDomainXML(hostname, httpsadminport, true);
+
+ CMS.debug("getUrlListFromSecurityDomain: Getting " + portType + " from Security Domain ...");
+ if (!portType.equals("UnSecurePort") &&
+ !portType.equals("SecureAgentPort") &&
+ !portType.equals("SecurePort") &&
+ !portType.equals("SecureAdminPort")) {
+ CMS.debug("getUrlListFromSecurityDomain: " +
+ "unknown port type " + portType);
+ return v;
+ }
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes());
+ XMLObject parser = new XMLObject(bis);
+ Document doc = parser.getDocument();
+ NodeList nodeList = doc.getElementsByTagName(type);
+
+ // save domain name in cfg
+ config.putString("securitydomain.name", parser.getValue("Name"));
+
+ int len = nodeList.getLength();
+
+ CMS.debug("Len " + len);
+ for (int i = 0; i < len; i++) {
+ Vector<String> v_name = parser.getValuesFromContainer(nodeList.item(i), "SubsystemName");
+ Vector<String> v_host = parser.getValuesFromContainer(nodeList.item(i), "Host");
+ Vector<String> v_port = parser.getValuesFromContainer(nodeList.item(i), portType);
+ Vector<String> v_admin_port = parser.getValuesFromContainer(nodeList.item(i), "SecureAdminPort");
+
+ if (v_host.elementAt(0).equals(hostname)
+ && v_admin_port.elementAt(0).equals(new Integer(httpsadminport).toString())) {
+ // add security domain CA to the beginning of list
+ v.add(0, v_name.elementAt(0) + " - https://" + v_host.elementAt(0) + ":" + v_port.elementAt(0));
+ } else {
+ v.addElement(v_name.elementAt(0) + " - https://" + v_host.elementAt(0) + ":" + v_port.elementAt(0));
+ }
+ }
+
+ return v;
+ }
+
+ public static boolean isValidCloneURI(String domainXML, String cloneHost, int clonePort) throws EPropertyNotFound,
+ EBaseException, SAXException, IOException, ParserConfigurationException {
+ IConfigStore cs = CMS.getConfigStore();
+ String csType = cs.getString("cs.type");
+ ByteArrayInputStream bis = new ByteArrayInputStream(domainXML.getBytes());
+
+ XMLObject parser = new XMLObject(bis);
+ Document doc = parser.getDocument();
+ NodeList nodeList = doc.getElementsByTagName(csType.toUpperCase());
+
+ int len = nodeList.getLength();
+ for (int i = 0; i < len; i++) {
+ String hostname = parser.getValuesFromContainer(nodeList.item(i), "Host").elementAt(0);
+ String secure_port = parser.getValuesFromContainer(nodeList.item(i), "SecurePort").elementAt(0);
+
+ if (hostname.equals(cloneHost) && secure_port.equals(clonePort + "")) {
+ cs.putString("preop.master.hostname", cloneHost);
+ cs.putInteger("preop.master.httpsport", clonePort);
+ cs.putString("preop.master.httpsadminport",
+ parser.getValuesFromContainer(nodeList.item(i), "SecureAdminPort").elementAt(0));
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static void getConfigEntriesFromMaster()
+ throws IOException, EBaseException, SAXException, ParserConfigurationException {
+
+ IConfigStore config = CMS.getConfigStore();
+ String cstype = "";
+
+ cstype = config.getString("cs.type", "");
+
+ cstype = cstype.toLowerCase();
+
+ String session_id = CMS.getConfigSDSessionId();
+ String master_hostname = config.getString("preop.master.hostname", "");
+ int master_port = config.getInteger("preop.master.httpsadminport", -1);
+ int master_ee_port = config.getInteger("preop.master.httpsport", -1);
+
+ String content = "";
+ if (cstype.equals("ca") || cstype.equals("kra")) {
+ content = "type=request&xmlOutput=true&sessionID=" + session_id;
+ CMS.debug("http content=" + content);
+ updateNumberRange(master_hostname, master_ee_port, master_port, true, content, "request");
+
+ content = "type=serialNo&xmlOutput=true&sessionID=" + session_id;
+ updateNumberRange(master_hostname, master_ee_port, master_port, true, content, "serialNo");
+
+ content = "type=replicaId&xmlOutput=true&sessionID=" + session_id;
+ updateNumberRange(master_hostname, master_ee_port, master_port, true, content, "replicaId");
+ }
+
+ String list = "";
+
+ list = config.getString("preop.cert.list", "");
+
+ StringBuffer c1 = new StringBuffer();
+ StringBuffer s1 = new StringBuffer();
+ StringTokenizer tok = new StringTokenizer(list, ",");
+ while (tok.hasMoreTokens()) {
+ String t1 = tok.nextToken();
+ if (t1.equals("sslserver"))
+ continue;
+ c1.append(",cloning." + t1 + ".nickname");
+ c1.append(",cloning." + t1 + ".dn");
+ c1.append(",cloning." + t1 + ".keytype");
+ c1.append(",cloning." + t1 + ".keyalgorithm");
+ c1.append(",cloning." + t1 + ".privkey.id");
+ c1.append(",cloning." + t1 + ".pubkey.exponent");
+ c1.append(",cloning." + t1 + ".pubkey.modulus");
+ c1.append(",cloning." + t1 + ".pubkey.encoded");
+
+ if (s1.length() != 0)
+ s1.append(",");
+ s1.append(cstype + "." + t1);
+ }
+
+ if (!cstype.equals("ca")) {
+ c1.append(",cloning.ca.hostname,cloning.ca.httpport,cloning.ca.httpsport,cloning.ca.list,cloning.ca.pkcs7,cloning.ca.type");
+ }
+
+ if (cstype.equals("ca")) {
+ /* get ca connector details */
+ if (s1.length() != 0)
+ s1.append(",");
+ s1.append("ca.connector.KRA");
+ }
+
+ s1.append(",internaldb,internaldb.ldapauth,internaldb.ldapconn");
+
+ content =
+ "op=get&names=cloning.module.token,cloning.token,instanceId,internaldb.basedn,internaldb.ldapauth.password,"
+ + "internaldb.replication.password" + c1.toString()
+ + "&substores=" + s1.toString()
+ + "&xmlOutput=true&sessionID="
+ + session_id;
+ boolean success = updateConfigEntries(master_hostname, master_port, true,
+ "/" + cstype + "/admin/" + cstype + "/getConfigEntries", content, config);
+ if (!success) {
+ throw new IOException("Failed to get configuration entries from the master");
+ }
+ config.putString("preop.clone.configuration", "true");
+
+ config.commit(false);
+
+ }
+
+ public static void updateNumberRange(String hostname, int eePort, int adminPort, boolean https, String content,
+ String type) throws IOException, EBaseException, SAXException, ParserConfigurationException {
+ CMS.debug("updateNumberRange start host=" + hostname + " adminPort=" + adminPort + " eePort=" + eePort);
+ IConfigStore cs = CMS.getConfigStore();
+
+ String cstype = cs.getString("cs.type", "");
+ cstype = cstype.toLowerCase();
+
+ String serverPath = "/" + cstype + "/admin/" + cstype + "/updateNumberRange";
+ String c = null;
+ XMLObject parser = null;
+ try {
+ c = getHttpResponse(hostname, adminPort, https, serverPath, content, null, null);
+ if (c == null || c.equals("")) {
+ CMS.debug("updateNumberRange: content is null.");
+ throw new IOException("The server you want to contact is not available");
+ }
+
+ CMS.debug("content from admin interface ="+ c);
+ // when the admin servlet is unavailable, we return a badly formatted error page
+ // in that case, this will throw an exception and be passed into the catch block.
+ parser = new XMLObject(new ByteArrayInputStream(c.getBytes()));
+ } catch (Exception e) {
+ // for backward compatibility, try the old ee interface too
+ CMS.debug("updateNumberRange: Failed to contact master using admin port" + e);
+ CMS.debug("updateNumberRange: Attempting to contact master using EE port");
+ serverPath = "/" + cstype + "/ee/" + cstype + "/updateNumberRange";
+ c = getHttpResponse(hostname, eePort, https, serverPath, content, null, null);
+ if (c == null || c.equals("")) {
+ CMS.debug("updateNumberRange: content is null.");
+ throw new IOException("The server you want to contact is not available");
+ }
+ CMS.debug("content from ee interface =" + c);
+ parser = new XMLObject(new ByteArrayInputStream(c.getBytes()));
+ }
+
+ String status = parser.getValue("Status");
+
+ CMS.debug("updateNumberRange(): status=" + status);
+ if (status.equals(SUCCESS)) {
+ String beginNum = parser.getValue("beginNumber");
+ String endNum = parser.getValue("endNumber");
+ if (type.equals("request")) {
+ cs.putString("dbs.beginRequestNumber", beginNum);
+ cs.putString("dbs.endRequestNumber", endNum);
+ } else if (type.equals("serialNo")) {
+ cs.putString("dbs.beginSerialNumber", beginNum);
+ cs.putString("dbs.endSerialNumber", endNum);
+ } else if (type.equals("replicaId")) {
+ cs.putString("dbs.beginReplicaNumber", beginNum);
+ cs.putString("dbs.endReplicaNumber", endNum);
+ }
+ // enable serial number management in clone
+ cs.putString("dbs.enableSerialManagement", "true");
+ cs.commit(false);
+ return;
+ } else if (status.equals(AUTH_FAILURE)) {
+ throw new EAuthException(AUTH_FAILURE);
+ } else {
+ String error = parser.getValue("Error");
+ throw new IOException(error);
+ }
+ }
+
+ public static boolean updateConfigEntries(String hostname, int port, boolean https,
+ String servlet, String uri, IConfigStore config)
+ throws IOException, EBaseException, SAXException, ParserConfigurationException {
+ CMS.debug("updateConfigEntries start");
+ String c = getHttpResponse(hostname, port, https, servlet, uri, null, null);
+
+ if (c != null) {
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes());
+ XMLObject parser = null;
+
+ parser = new XMLObject(bis);
+
+ String status = parser.getValue("Status");
+ CMS.debug("updateConfigEntries: status=" + status);
+
+ if (status.equals(SUCCESS)) {
+ String cstype = "";
+
+ cstype = config.getString("cs.type", "");
+
+ Document doc = parser.getDocument();
+ NodeList list = doc.getElementsByTagName("name");
+ int len = list.getLength();
+ for (int i = 0; i < len; i++) {
+ Node n = list.item(i);
+ NodeList nn = n.getChildNodes();
+ String name = nn.item(0).getNodeValue();
+ Node parent = n.getParentNode();
+ nn = parent.getChildNodes();
+ int len1 = nn.getLength();
+ String v = "";
+ for (int j = 0; j < len1; j++) {
+ Node nv = nn.item(j);
+ String val = nv.getNodeName();
+ if (val.equals("value")) {
+ NodeList n2 = nv.getChildNodes();
+ if (n2.getLength() > 0)
+ v = n2.item(0).getNodeValue();
+ break;
+ }
+ }
+
+ if (name.equals("internaldb.basedn")) {
+ config.putString(name, v);
+ config.putString("preop.internaldb.master.basedn", v);
+ } else if (name.startsWith("internaldb")) {
+ config.putString(name.replaceFirst("internaldb", "preop.internaldb.master"), v);
+ } else if (name.equals("instanceId")) {
+ config.putString("preop.master.instanceId", v);
+ } else if (name.equals("cloning.signing.nickname")) {
+ config.putString("preop.master.signing.nickname", v);
+ config.putString("preop.cert.signing.nickname", v);
+ } else if (name.equals("cloning.ocsp_signing.nickname")) {
+ config.putString("preop.master.ocsp_signing.nickname", v);
+ config.putString("preop.cert.ocsp_signing.nickname", v);
+ } else if (name.equals("cloning.subsystem.nickname")) {
+ config.putString("preop.master.subsystem.nickname", v);
+ config.putString("preop.cert.subsystem.nickname", v);
+ } else if (name.equals("cloning.transport.nickname")) {
+ config.putString("preop.master.transport.nickname", v);
+ config.putString("kra.transportUnit.nickName", v);
+ config.putString("preop.cert.transport.nickname", v);
+ } else if (name.equals("cloning.storage.nickname")) {
+ config.putString("preop.master.storage.nickname", v);
+ config.putString("kra.storageUnit.nickName", v);
+ config.putString("preop.cert.storage.nickname", v);
+ } else if (name.equals("cloning.audit_signing.nickname")) {
+ config.putString("preop.master.audit_signing.nickname", v);
+ config.putString("preop.cert.audit_signing.nickname", v);
+ config.putString(name, v);
+ } else if (name.startsWith("cloning.ca")) {
+ config.putString(name.replaceFirst("cloning", "preop"), v);
+ } else if (name.equals("cloning.signing.keyalgorithm")) {
+ config.putString(name.replaceFirst("cloning", "preop.cert"), v);
+ if (cstype.equals("CA")) {
+ config.putString("ca.crl.MasterCRL.signingAlgorithm", v);
+ config.putString("ca.signing.defaultSigningAlgorithm", v);
+ } else if (cstype.equals("OCSP")) {
+ config.putString("ocsp.signing.defaultSigningAlgorithm", v);
+ }
+ } else if (name.equals("cloning.transport.keyalgorithm")) {
+ config.putString(name.replaceFirst("cloning", "preop.cert"), v);
+ config.putString("kra.transportUnit.signingAlgorithm", v);
+ } else if (name.equals("cloning.ocsp_signing.keyalgorithm")) {
+ config.putString(name.replaceFirst("cloning", "preop.cert"), v);
+ if (cstype.equals("CA")) {
+ config.putString("ca.ocsp_signing.defaultSigningAlgorithm", v);
+ }
+ } else if (name.startsWith("cloning")) {
+ config.putString(name.replaceFirst("cloning", "preop.cert"), v);
+ } else {
+ config.putString(name, v);
+ }
+ }
+
+ // set master ldap password (if it exists) temporarily in password store
+ // in case it is needed for replication. Not stored in password.conf.
+
+ String master_pwd = config.getString("preop.internaldb.master.ldapauth.password", "");
+ if (!master_pwd.equals("")) {
+ config.putString("preop.internaldb.master.ldapauth.bindPWPrompt", "master_internaldb");
+ String passwordFile = config.getString("passwordFile");
+ IConfigStore psStore = CMS.createFileConfigStore(passwordFile);
+ psStore.putString("master_internaldb", master_pwd);
+ psStore.commit(false);
+ }
+
+ return true;
+ } else if (status.equals(AUTH_FAILURE)) {
+ throw new EAuthException(AUTH_FAILURE);
+ } else {
+ String error = parser.getValue("Error");
+ throw new IOException(error);
+ }
+ }
+
+ return false;
+ }
+
+ public static void restoreCertsFromP12(String p12File, String p12Pass) throws EPropertyNotFound, EBaseException,
+ InvalidKeyException, CertificateException, NoSuchAlgorithmException,
+ InvalidAlgorithmParameterException, IllegalStateException, TokenException, IllegalBlockSizeException,
+ BadPaddingException, NotInitializedException, NicknameConflictException, UserCertConflictException,
+ NoSuchItemOnTokenException, InvalidBERException, IOException {
+ byte b[] = new byte[1000000];
+
+ FileInputStream fis = new FileInputStream(p12File);
+ while (fis.available() > 0)
+ fis.read(b);
+ fis.close();
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(b);
+ StringBuffer reason = new StringBuffer();
+ Password password = new Password(p12Pass.toCharArray());
+ PFX pfx = null;
+ boolean verifypfx = false;
+
+ pfx = (PFX) (new PFX.Template()).decode(bis);
+ verifypfx = pfx.verifyAuthSafes(password, reason);
+
+ if (verifypfx) {
+ AuthenticatedSafes safes = pfx.getAuthSafes();
+ Vector<Vector<Object>> pkeyinfo_collection = new Vector<Vector<Object>>();
+ Vector<Vector<Object>> cert_collection = new Vector<Vector<Object>>();
+ for (int i = 0; i < safes.getSize(); i++) {
+ SEQUENCE scontent = safes.getSafeContentsAt(null, i);
+ for (int j = 0; j < scontent.size(); j++) {
+ SafeBag bag = (SafeBag) scontent.elementAt(j);
+ OBJECT_IDENTIFIER oid = bag.getBagType();
+ if (oid.equals(SafeBag.PKCS8_SHROUDED_KEY_BAG)) {
+ EncryptedPrivateKeyInfo privkeyinfo =
+ (EncryptedPrivateKeyInfo) bag.getInterpretedBagContent();
+ PrivateKeyInfo pkeyinfo = privkeyinfo.decrypt(password, new PasswordConverter());
+ Vector<Object> pkeyinfo_v = new Vector<Object>();
+ pkeyinfo_v.addElement(pkeyinfo);
+ SET bagAttrs = bag.getBagAttributes();
+ for (int k = 0; k < bagAttrs.size(); k++) {
+ Attribute attrs = (Attribute) bagAttrs.elementAt(k);
+ OBJECT_IDENTIFIER aoid = attrs.getType();
+ if (aoid.equals(SafeBag.FRIENDLY_NAME)) {
+ SET val = attrs.getValues();
+ ANY ss = (ANY) val.elementAt(0);
+ ByteArrayInputStream bbis = new ByteArrayInputStream(ss.getEncoded());
+ BMPString sss = (BMPString) new BMPString.Template().decode(bbis);
+ String s = sss.toString();
+ pkeyinfo_v.addElement(s);
+ }
+ }
+ pkeyinfo_collection.addElement(pkeyinfo_v);
+ } else if (oid.equals(SafeBag.CERT_BAG)) {
+ CertBag cbag = (CertBag) bag.getInterpretedBagContent();
+ OCTET_STRING str = (OCTET_STRING) cbag.getInterpretedCert();
+ byte[] x509cert = str.toByteArray();
+ Vector<Object> cert_v = new Vector<Object>();
+ cert_v.addElement(x509cert);
+ SET bagAttrs = bag.getBagAttributes();
+
+ if (bagAttrs != null) {
+ for (int k = 0; k < bagAttrs.size(); k++) {
+ Attribute attrs = (Attribute) bagAttrs.elementAt(k);
+ OBJECT_IDENTIFIER aoid = attrs.getType();
+ if (aoid.equals(SafeBag.FRIENDLY_NAME)) {
+ SET val = attrs.getValues();
+ ANY ss = (ANY) val.elementAt(0);
+ ByteArrayInputStream bbis = new ByteArrayInputStream(ss.getEncoded());
+ BMPString sss = (BMPString) (new BMPString.Template()).decode(bbis);
+ String s = sss.toString();
+ cert_v.addElement(s);
+ }
+ }
+ }
+
+ cert_collection.addElement(cert_v);
+ }
+ }
+ }
+
+ importkeycert(pkeyinfo_collection, cert_collection);
+ } else {
+ throw new IOException("P12 File is incorrect");
+ }
+
+ }
+
+ public static boolean isCertdbCloned() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ CryptoManager cm = CryptoManager.getInstance();
+ String certList = cs.getString("preop.cert.list");
+ String cstype = cs.getString("cs.type").toLowerCase();
+ StringTokenizer st = new StringTokenizer(certList, ",");
+ while (st.hasMoreTokens()) {
+ String tag = st.nextToken();
+ if (tag.equals("sslserver"))
+ continue;
+ String tokenname = cs.getString("preop.module.token", "");
+ cm.getTokenByName(tokenname); // throw exception if token doesn't exist
+ String name1 = "preop.master." + tag + ".nickname";
+ String nickname = cs.getString(name1, "");
+ if (!tokenname.equals("Internal Key Storage Token") &&
+ !tokenname.equals("internal"))
+ nickname = tokenname + ":" + nickname;
+
+ CMS.debug("isCertdbCloned: " + nickname);
+
+ // TODO : remove this when we eliminate the extraneous nicknames
+ // needed for self tests
+ cs.putString(cstype + ".cert." + tag + ".nickname", nickname);
+
+ X509Certificate cert = cm.findCertByNickname(nickname);
+ if (cert == null)
+ return false;
+ }
+ } catch (Exception e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public static void importkeycert(Vector<Vector<Object>> pkeyinfo_collection,
+ Vector<Vector<Object>> cert_collection) throws IOException, CertificateException, TokenException,
+ NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalStateException,
+ IllegalBlockSizeException, BadPaddingException, NotInitializedException, NicknameConflictException,
+ UserCertConflictException, NoSuchItemOnTokenException, EPropertyNotFound, EBaseException {
+ CryptoManager cm = CryptoManager.getInstance();
+
+ // delete all existing certificates first
+ deleteExistingCerts();
+
+ ArrayList<String> masterList = getMasterCertKeyList();
+
+ for (int i = 0; i < pkeyinfo_collection.size(); i++) {
+ Vector<Object> pkeyinfo_v = pkeyinfo_collection.elementAt(i);
+ PrivateKeyInfo pkeyinfo = (PrivateKeyInfo) pkeyinfo_v.elementAt(0);
+ String nickname = (String) pkeyinfo_v.elementAt(1);
+
+ if (! importRequired(masterList,nickname)) {
+ CMS.debug("Ignoring key " + nickname);
+ continue;
+ }
+
+ byte[] x509cert = getX509Cert(nickname, cert_collection);
+ X509Certificate cert = cm.importCACertPackage(x509cert);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ pkeyinfo.encode(bos);
+ byte[] pkey = bos.toByteArray();
+
+ PublicKey publickey = cert.getPublicKey();
+ CryptoToken token = cm.getInternalKeyStorageToken();
+ CryptoStore store = token.getCryptoStore();
+
+ try {
+ store.deleteCert(cert);
+ } catch (NoSuchItemOnTokenException e) {
+ // this is OK
+ }
+
+ KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3);
+ SymmetricKey sk = kg.generate();
+ byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
+ IVParameterSpec param = new IVParameterSpec(iv);
+ Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD);
+ c.initEncrypt(sk, param);
+ byte[] encpkey = c.doFinal(pkey);
+
+ KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
+ wrapper.initUnwrap(sk, param);
+ wrapper.unwrapPrivate(encpkey, getPrivateKeyType(publickey), publickey);
+
+ }
+
+ for (int i = 0; i < cert_collection.size(); i++) {
+
+ Vector<Object> cert_v = cert_collection.elementAt(i);
+ byte[] cert = (byte[]) cert_v.elementAt(0);
+ if (cert_v.size() > 1) {
+ String name = (String) cert_v.elementAt(1);
+ if (! masterList.contains(name)) {
+ CMS.debug("Not importing " + name);
+ // only import the master's system certs
+ continue;
+ }
+ // we need to delete the trusted CA certificate if it is
+ // the same as the ca signing certificate
+ if (isCASigningCert(name)) {
+ X509Certificate certchain = getX509CertFromToken(cert);
+ if (certchain != null) {
+ CryptoToken token = cm.getInternalKeyStorageToken();
+ CryptoStore store = token.getCryptoStore();
+ if (store instanceof PK11Store) {
+ try {
+ PK11Store pk11store = (PK11Store) store;
+ pk11store.deleteCertOnly(certchain);
+ } catch (Exception ee) {
+ CMS.debug("importKeyCert: Exception=" + ee.toString());
+ }
+ }
+ }
+ }
+
+ X509Certificate xcert = cm.importUserCACertPackage(cert, name);
+ if (isCASigningCert(name)) {
+ // we need to change the trust attribute to CT
+ InternalCertificate icert = (InternalCertificate) xcert;
+ icert.setSSLTrust(InternalCertificate.TRUSTED_CA
+ | InternalCertificate.TRUSTED_CLIENT_CA
+ | InternalCertificate.VALID_CA);
+ } else if (isAuditSigningCert(name)) {
+ InternalCertificate icert = (InternalCertificate) xcert;
+ icert.setObjectSigningTrust(InternalCertificate.USER
+ | InternalCertificate.VALID_PEER | InternalCertificate.TRUSTED_PEER);
+ }
+ } else {
+ cm.importCACertPackage(cert);
+ }
+ }
+ }
+
+ private static boolean importRequired(ArrayList<String> masterList, String nickname) {
+ if (masterList.contains(nickname))
+ return true;
+ try {
+ X500Name xname = new X500Name(nickname);
+ for (String key: masterList) {
+ try {
+ X500Name xkey = new X500Name(key);
+ if (xkey.equals(xname)) return true;
+ } catch (IOException e) {
+ // xkey not an X500Name
+ }
+ }
+
+ } catch (IOException e) {
+ // nickname is not a x500Name
+ return false;
+ }
+ return false;
+ }
+
+ public static X509Certificate getX509CertFromToken(byte[] cert)
+ throws IOException, CertificateException, NotInitializedException {
+
+ X509CertImpl impl = new X509CertImpl(cert);
+ String issuer_impl = impl.getIssuerDN().toString();
+ BigInteger serial_impl = impl.getSerialNumber();
+ CryptoManager cm = CryptoManager.getInstance();
+ X509Certificate[] permcerts = cm.getPermCerts();
+ for (int i = 0; i < permcerts.length; i++) {
+ String issuer_p = permcerts[i].getSubjectDN().toString();
+ BigInteger serial_p = permcerts[i].getSerialNumber();
+ if (issuer_p.equals(issuer_impl) && serial_p.compareTo(serial_impl) == 0) {
+ return permcerts[i];
+ }
+ }
+ return null;
+ }
+
+ public static org.mozilla.jss.crypto.PrivateKey.Type getPrivateKeyType(PublicKey pubkey) {
+ CMS.debug("Key Algorithm '" + pubkey.getAlgorithm() + "'");
+ if (pubkey.getAlgorithm().equals("EC")) {
+ return org.mozilla.jss.crypto.PrivateKey.Type.EC;
+ }
+ return org.mozilla.jss.crypto.PrivateKey.Type.RSA;
+ }
+
+ public static boolean isCASigningCert(String name) {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String nickname = cs.getString("preop.master.signing.nickname");
+ if (nickname.equals(name)) return true;
+ } catch(Exception e) {
+ // nickname may not exist if this is not cloning a CA
+ };
+
+ return false;
+ }
+
+ public static boolean isAuditSigningCert(String name) throws EPropertyNotFound, EBaseException {
+ IConfigStore cs = CMS.getConfigStore();
+ String nickname = cs.getString("preop.master.audit_signing.nickname");
+ if (nickname.equals(name)) return true;
+ return false;
+ }
+
+ public static void deleteExistingCerts() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String list = cs.getString("preop.cert.list", "");
+ StringTokenizer st = new StringTokenizer(list, ",");
+ while (st.hasMoreTokens()) {
+ String s = st.nextToken();
+ if (s.equals("sslserver"))
+ continue;
+ String name = "preop.master." + s + ".nickname";
+ String nickname = cs.getString(name, "");
+ CryptoManager cm = CryptoManager.getInstance();
+ X509Certificate xcert = null;
+ try {
+ xcert = cm.findCertByNickname(nickname);
+ } catch (Exception ee) {
+ CMS.debug("deleteExistingCerts: Exception=" + ee.toString());
+ }
+ CryptoToken ct = cm.getInternalKeyStorageToken();
+ CryptoStore store = ct.getCryptoStore();
+ try {
+ store.deleteCert(xcert);
+ } catch (Exception ee) {
+ CMS.debug("deleteExistingCerts: Exception=" + ee.toString());
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("deleteExistingCerts: Exception=" + e.toString());
+ }
+ }
+
+ public static ArrayList<String> getMasterCertKeyList() throws EBaseException {
+ ArrayList<String> list = new ArrayList<String>();
+ IConfigStore cs = CMS.getConfigStore();
+ String certList = cs.getString("preop.cert.list", "");
+ StringTokenizer st = new StringTokenizer(certList, ",");
+ while (st.hasMoreTokens()) {
+ String s = st.nextToken();
+ if (s.equals("sslserver"))
+ continue;
+ String name = "preop.master." + s + ".nickname";
+ String nickname = cs.getString(name);
+ list.add(nickname);
+
+ name = "preop.cert." + s + ".dn";
+ String dn = cs.getString(name);
+ list.add(dn);
+ }
+ return list;
+ }
+
+ public static byte[] getX509Cert(String nickname, Vector<Vector<Object>> cert_collection)
+ throws CertificateException {
+ for (int i = 0; i < cert_collection.size(); i++) {
+ Vector<Object> v = cert_collection.elementAt(i);
+ byte[] b = (byte[]) v.elementAt(0);
+ X509CertImpl impl = null;
+ impl = new X509CertImpl(b);
+ Principal subjectdn = impl.getSubjectDN();
+ if (LDAPDN.equals(subjectdn.toString(), nickname)) return b;
+ }
+ return null;
+ }
+
+ public static void releaseConnection(LDAPConnection conn) {
+ try {
+ if (conn != null) conn.disconnect();
+ } catch (LDAPException e) {
+ e.printStackTrace();
+ CMS.debug("releaseConnection: " + e);
+ }
+ }
+
+ public static void populateDB() throws IOException, EBaseException {
+ IConfigStore cs = CMS.getConfigStore();
+
+ String baseDN = cs.getString("internaldb.basedn");
+ String database = cs.getString("internaldb.database", "");
+ String remove = cs.getString("preop.database.removeData", "false");
+
+ IConfigStore dbCfg = cs.getSubStore("internaldb");
+ ILdapConnFactory dbFactory = CMS.getLdapBoundConnFactory();
+ dbFactory.init(dbCfg);
+ LDAPConnection conn = dbFactory.getConn();
+
+ // check that the database and baseDN do not exist
+ boolean foundBaseDN = false;
+ try {
+ LDAPEntry entry = conn.read(baseDN);
+ if (entry != null) foundBaseDN = true;
+ } catch (LDAPException e) {
+ switch (e.getLDAPResultCode()) {
+ case LDAPException.NO_SUCH_OBJECT:
+ break;
+ default:
+ e.printStackTrace();
+ CMS.debug("populateDB: LDAPException " + e.toString());
+ releaseConnection(conn);
+ throw new IOException("Failed to determine if basedDN exists.");
+ }
+ }
+
+ boolean foundDatabase = false;
+ try {
+ String dn = "cn=" + LDAPUtil.escapeRDNValue(database) + ",cn=ldbm database, cn=plugins, cn=config";
+ LDAPEntry entry = conn.read(dn);
+ if (entry != null) foundDatabase = true;
+ } catch (LDAPException e) {
+ switch (e.getLDAPResultCode()) {
+ case LDAPException.NO_SUCH_OBJECT:
+ break;
+ default:
+ e.printStackTrace();
+ CMS.debug("populatedb: LDAPException " + e.toString());
+ releaseConnection(conn);
+ throw new IOException("Failed to determine if database exists.");
+ }
+ }
+ try {
+ String dn = "cn=\"" + baseDN + "\",cn=mapping tree, cn=config";
+ LDAPEntry entry = conn.read(dn);
+ if (entry != null) foundDatabase = true;
+ } catch (LDAPException e) {
+ switch (e.getLDAPResultCode()) {
+ case LDAPException.NO_SUCH_OBJECT:
+ break;
+ default:
+ e.printStackTrace();
+ CMS.debug("populateDB: LDAPException " + e.toString());
+ releaseConnection(conn);
+ throw new IOException("Failed to determine if mapping tree exists.");
+ }
+ }
+
+ if (foundDatabase) {
+ CMS.debug("populatedb: This database has already been used.");
+ if (remove.equals("false")) {
+ releaseConnection(conn);
+ throw new IOException("This database has already been used. " +
+ "Select the checkbox below to remove all data and reuse this database");
+ } else {
+ CMS.debug("populateDB: Deleting existing DB and reusing base DN");
+ cleanupDB(conn, baseDN, database);
+ foundBaseDN = false;
+ foundDatabase = false;
+ }
+ }
+
+ if (foundBaseDN) {
+ CMS.debug("DatabasePanel update: This base DN has already been used.");
+ if (remove.equals("false")) {
+ releaseConnection(conn);
+ throw new IOException( "This base DN (" + baseDN
+ + ") has already been used. Select the checkbox below to remove all data and reuse this base DN");
+ } else {
+ CMS.debug("populateDB: Deleting existing DB and reusing base DN");
+ cleanupDB(conn, baseDN, database);
+ foundBaseDN = false;
+ foundDatabase = false;
+ }
+ }
+
+ // create database
+ try {
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+ String oc[] = { "top", "extensibleObject", "nsBackendInstance" };
+ attrs.add(new LDAPAttribute("objectClass", oc));
+ attrs.add(new LDAPAttribute("cn", database));
+ attrs.add(new LDAPAttribute("nsslapd-suffix", baseDN));
+ String dn = "cn=" + LDAPUtil.escapeRDNValue(database) + ",cn=ldbm database, cn=plugins, cn=config";
+ LDAPEntry entry = new LDAPEntry(dn, attrs);
+ conn.add(entry);
+ } catch (Exception e) {
+ CMS.debug("populateDB: Warning: database creation error - " + e.toString());
+ releaseConnection(conn);
+ throw new IOException("Failed to create the database.");
+ }
+
+ try {
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+ String oc2[] = { "top", "extensibleObject", "nsMappingTree" };
+ attrs.add(new LDAPAttribute("objectClass", oc2));
+ attrs.add(new LDAPAttribute("cn", baseDN));
+ attrs.add(new LDAPAttribute("nsslapd-backend", database));
+ attrs.add(new LDAPAttribute("nsslapd-state", "Backend"));
+ String dn = "cn=\"" + baseDN + "\",cn=mapping tree, cn=config";
+ LDAPEntry entry = new LDAPEntry(dn, attrs);
+ conn.add(entry);
+ } catch (Exception e) {
+ CMS.debug("populateDB: Warning: database mapping tree creation error - " + e.toString());
+ releaseConnection(conn);
+ throw new IOException("Failed to create the database.");
+ }
+
+ try {
+ // create base dn
+ CMS.debug("Creating base DN: " + baseDN);
+ String dns3[] = LDAPDN.explodeDN(baseDN, false);
+ StringTokenizer st = new StringTokenizer(dns3[0], "=");
+ String n = st.nextToken();
+ String v = st.nextToken();
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+ String oc3[] = { "top", "domain" };
+ if (n.equals("o")) {
+ oc3[1] = "organization";
+ } else if (n.equals("ou")) {
+ oc3[1] = "organizationalUnit";
+ }
+ attrs.add(new LDAPAttribute("objectClass", oc3));
+ attrs.add(new LDAPAttribute(n, v));
+
+ LDAPEntry entry = new LDAPEntry(baseDN, attrs);
+ conn.add(entry);
+ } catch (Exception e) {
+ CMS.debug("populateDB: Warning: suffix creation error - " + e.toString());
+ releaseConnection(conn);
+ throw new IOException("Failed to create the base DN: " + baseDN);
+ }
+
+ try {
+ String select = cs.getString("preop.subsystem.select", "");
+ if (select.equals("clone")) {
+ // in most cases, we want to replicate the schema and therefore
+ // NOT add it here. We provide this option though in case the
+ // clone already has schema and we want to replicate back to the
+ // master.
+ boolean replicateSchema = cs.getBoolean("preop.internaldb.replicateSchema", true);
+ if (! replicateSchema) {
+ importLDIFS("preop.internaldb.schema.ldif", conn);
+ }
+ importLDIFS("preop.internaldb.ldif", conn);
+
+ // add the index before replication, add VLV indexes afterwards
+ importLDIFS("preop.internaldb.index_ldif", conn);
+ } else {
+ // data will be replicated from the master to the clone
+ // so clone does not need the data
+ importLDIFS("preop.internaldb.schema.ldif", conn);
+ importLDIFS("preop.internaldb.ldif", conn);
+ importLDIFS("preop.internaldb.data_ldif", conn);
+ importLDIFS("preop.internaldb.index_ldif", conn);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ CMS.debug("Failed to import ldif files: " + e);
+ releaseConnection(conn);
+ throw new IOException("Failed to import ldif files");
+ }
+
+ releaseConnection(conn);
+ }
+
+ public static void importLDIFS(String param, LDAPConnection conn) throws IOException, EPropertyNotFound,
+ EBaseException {
+ IConfigStore cs = CMS.getConfigStore();
+
+ CMS.debug("importLDIFS: param=" + param);
+ String v = cs.getString(param);
+
+ String baseDN = cs.getString("internaldb.basedn");
+ String database = cs.getString("internaldb.database");
+ String instancePath = cs.getString("instanceRoot");
+ String instanceId = cs.getString("instanceId");
+ String cstype = cs.getString("cs.type");
+
+ String dbuser = "uid=" + DBUSER + ",ou= people," + baseDN;
+
+ String configDir = instancePath + File.separator + cstype.toLowerCase() + File.separator + "conf";
+
+ StringTokenizer tokenizer = new StringTokenizer(v, ",");
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken().trim();
+ int index = token.lastIndexOf("/");
+ String name = token;
+
+ if (index != -1) {
+ name = token.substring(index + 1);
+ }
+
+ CMS.debug("importLDIFS(): ldif file = " + token);
+ String filename = configDir + File.separator + name;
+
+ CMS.debug("importLDIFS(): ldif file copy to " + filename);
+ PrintStream ps = null;
+ BufferedReader in = null;
+
+ in = new BufferedReader(new FileReader(token));
+ ps = new PrintStream(new FileOutputStream(filename, false));
+ while (in.ready()) {
+ String s = in.readLine();
+ int n = s.indexOf("{");
+
+ if (n == -1) {
+ ps.println(s);
+ } else {
+ boolean endOfline = false;
+
+ while (n != -1) {
+ ps.print(s.substring(0, n));
+ int n1 = s.indexOf("}");
+ String tok = s.substring(n + 1, n1);
+
+ if (tok.equals("instanceId")) {
+ ps.print(instanceId);
+ } else if (tok.equals("rootSuffix")) {
+ ps.print(baseDN);
+ } else if (tok.equals("database")) {
+ ps.print(database);
+ } else if (tok.equals("dbuser")) {
+ ps.print(dbuser);
+ }
+ if ((s.length() + 1) == n1) {
+ endOfline = true;
+ break;
+ }
+ s = s.substring(n1 + 1);
+ n = s.indexOf("{");
+ }
+
+ if (!endOfline) {
+ ps.println(s);
+ }
+ }
+ }
+ in.close();
+ ps.close();
+
+ ArrayList<String> errors = new ArrayList<String>();
+ LDAPUtil.importLDIF(conn, filename, errors);
+ if (!errors.isEmpty()) {
+ CMS.debug("importLDIFS(): LDAP Errors in importing " + filename);
+ for (String error : errors) {
+ CMS.debug(error);
+ }
+ }
+ }
+ }
+
+ public static void cleanupDB(LDAPConnection conn, String baseDN, String database) {
+ String[] entries = {};
+ String filter = "objectclass=*";
+ LDAPSearchConstraints cons = null;
+ String[] attrs = null;
+ String dn = "";
+ try {
+ CMS.debug("cleanupDB: Deleting baseDN: " + baseDN);
+ LDAPSearchResults res = conn.search(baseDN, LDAPConnection.SCOPE_BASE, filter,
+ attrs, true, cons);
+ if (res != null)
+ deleteEntries(res, conn, baseDN, entries);
+ } catch (LDAPException e) {
+ CMS.debug("cleanupDB: ldapexception thrown" + e);
+ }
+
+ try {
+ dn = "cn=mapping tree, cn=config";
+ filter = "nsslapd-backend=" + LDAPUtil.escapeFilter(database);
+ LDAPSearchResults res = conn.search(dn, LDAPConnection.SCOPE_ONE, filter,
+ attrs, true, cons);
+ if (res != null) {
+ while (res.hasMoreElements()) {
+ dn = res.next().getDN();
+ filter = "objectclass=*";
+ LDAPSearchResults res2 = conn.search(dn, LDAPConnection.SCOPE_BASE, filter,
+ attrs, true, cons);
+ if (res2 != null)
+ deleteEntries(res2, conn, dn, entries);
+ }
+ }
+ } catch (LDAPException e) {
+ CMS.debug("cleanupDB: ldapexception thrown" + e);
+ }
+
+ try {
+ dn = "cn=" + LDAPUtil.escapeRDNValue(database) + ",cn=ldbm database, cn=plugins, cn=config";
+ LDAPSearchResults res = conn.search(dn, LDAPConnection.SCOPE_BASE, filter,
+ attrs, true, cons);
+ if (res != null) {
+ deleteEntries(res, conn, dn, entries);
+ String dbdir = getInstanceDir(conn) + "/db/" + database;
+ if (dbdir != null) {
+ CMS.debug("cleanupDB: Deleting dbdir " + dbdir);
+ boolean success = deleteDir(new File(dbdir));
+ if (!success) {
+ CMS.debug("cleanupDB: Unable to delete database directory " + dbdir);
+ }
+ }
+ }
+ } catch (LDAPException e) {
+ CMS.debug("cleanupDB: ldapexception thrown" + e);
+ }
+ }
+
+ public static void deleteEntries(LDAPSearchResults res, LDAPConnection conn,
+ String dn, String[] entries) {
+ String[] attrs = null;
+ LDAPSearchConstraints cons = null;
+ String filter = "objectclass=*";
+
+ try {
+ if (res.getCount() == 0)
+ return;
+ else {
+ while (res.hasMoreElements()) {
+ LDAPEntry entry = res.next();
+ String dn1 = entry.getDN();
+ LDAPSearchResults res1 = conn.search(dn1, 1, filter, attrs, true, cons);
+ deleteEntries(res1, conn, dn1, entries);
+ deleteEntry(conn, dn1, entries);
+ }
+ }
+ } catch (Exception ee) {
+ CMS.debug("deleteEntries: Exception=" + ee.toString());
+ }
+ }
+
+ public static void deleteEntry(LDAPConnection conn, String dn, String[] entries) {
+ try {
+ for (int i = 0; i < entries.length; i++) {
+ if (LDAPDN.equals(dn, entries[i])) {
+ CMS.debug("deleteEntry: entry with this dn " + dn + " is not deleted.");
+ return;
+ }
+ }
+
+ CMS.debug("deleteEntry: deleting dn=" + dn);
+ conn.delete(dn);
+ } catch (Exception e) {
+ CMS.debug("deleteEntry: Exception=" + e.toString());
+ }
+ }
+
+ public static String getInstanceDir(LDAPConnection conn) throws LDAPException {
+ String instancedir = "";
+
+ String filter = "(objectclass=*)";
+ String[] attrs = { "nsslapd-directory" };
+ LDAPSearchResults results = conn.search("cn=config,cn=ldbm database,cn=plugins,cn=config",
+ LDAPv3.SCOPE_SUB, filter, attrs, false);
+
+ while (results.hasMoreElements()) {
+ LDAPEntry entry = results.next();
+ String dn = entry.getDN();
+ CMS.debug("getInstanceDir: DN for storing nsslapd-directory: " + dn);
+ LDAPAttributeSet entryAttrs = entry.getAttributeSet();
+
+ @SuppressWarnings("unchecked")
+ Enumeration<LDAPAttribute> attrsInSet = entryAttrs.getAttributes();
+ while (attrsInSet.hasMoreElements()) {
+ LDAPAttribute nextAttr = attrsInSet.nextElement();
+ String attrName = nextAttr.getName();
+ CMS.debug("getInstanceDir: attribute name: " + attrName);
+ @SuppressWarnings("unchecked")
+ Enumeration<String> valsInAttr = nextAttr.getStringValues();
+ while (valsInAttr.hasMoreElements()) {
+ String nextValue = valsInAttr.nextElement();
+ if (attrName.equalsIgnoreCase("nsslapd-directory")) {
+ CMS.debug("getInstanceDir: instanceDir=" + nextValue);
+ return nextValue.substring(0, nextValue.lastIndexOf("/db"));
+ }
+ }
+ }
+ }
+
+ return instancedir;
+ }
+
+ public static boolean deleteDir(File dir) {
+ if (dir.isDirectory()) {
+ String[] children = dir.list();
+ for (int i = 0; i < children.length; i++) {
+ boolean success = deleteDir(new File(dir, children[i]));
+ if (!success) {
+ return false;
+ }
+ }
+ }
+ return dir.delete();
+ }
+
+ public static void populateDBManager() throws Exception {
+ CMS.debug("populateDBManager(): start");
+ IConfigStore cs = CMS.getConfigStore();
+
+ IConfigStore dbCfg = cs.getSubStore("internaldb");
+ ILdapConnFactory dbFactory = CMS.getLdapBoundConnFactory();
+ dbFactory.init(dbCfg);
+ LDAPConnection conn = dbFactory.getConn();
+
+ try {
+ importLDIFS("preop.internaldb.manager_ldif", conn);
+ } catch (Exception e) {
+ CMS.debug("populateDBManager(): Exception thrown: " + e);
+ throw e;
+ } finally {
+ releaseConnection(conn);
+ }
+ }
+
+ public static void populateVLVIndexes() throws Exception {
+ CMS.debug("populateVLVIndexes(): start");
+ IConfigStore cs = CMS.getConfigStore();
+
+ IConfigStore dbCfg = cs.getSubStore("internaldb");
+ ILdapConnFactory dbFactory = CMS.getLdapBoundConnFactory();
+ dbFactory.init(dbCfg);
+ LDAPConnection conn = dbFactory.getConn();
+
+ try {
+ importLDIFS("preop.internaldb.post_ldif", conn);
+
+ /* For vlvtask, we need to check if the task has
+ been completed or not. Presence of nsTaskExitCode means task is complete
+ */
+ String wait_dn = cs.getString("preop.internaldb.wait_dn", "");
+ if (!wait_dn.equals("")) {
+ LDAPEntry task = null;
+ boolean taskComplete = false;
+ CMS.debug("Checking wait_dn " + wait_dn);
+ do {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ // restore the interrupted status
+ Thread.currentThread().interrupt();
+ }
+
+ try {
+ task = conn.read(wait_dn, (String[]) null);
+ if (task != null) {
+ LDAPAttribute attr = task.getAttribute("nsTaskExitCode");
+ if (attr != null) {
+ taskComplete = true;
+ String val = (String) attr.getStringValues().nextElement();
+ if (val.compareTo("0") != 0) {
+ CMS.debug("Error in populating local VLV indexes: nsTaskExitCode=" + val);
+ }
+ }
+ }
+ } catch (Exception le) {
+ CMS.debug("Still checking wait_dn '" + wait_dn + "' (" + le.toString() + ")");
+ }
+ } while (!taskComplete);
+ }
+ } catch (Exception e) {
+ CMS.debug("populateVLVIndexes(): Exception thrown: " + e);
+ throw e;
+ } finally {
+ releaseConnection(conn);
+ }
+ }
+
+ public static void setupReplication() throws EBaseException, IOException {
+ IConfigStore cs = CMS.getConfigStore();
+
+ String machinename = cs.getString("machineName", "");
+ String instanceId = cs.getString("instanceId", "");
+ String secure = cs.getString("internaldb.ldapconn.secureConn");
+ String replicationSecurity = cs.getString("internaldb.ldapconn.replicationSecurity");
+ int masterReplicationPort = cs.getInteger("internaldb.ldapconn.masterReplicationPort");
+ int cloneReplicationPort = cs.getInteger("internaldb.ldapconn.cloneReplicationPort");
+
+ //setup replication agreement
+ String masterAgreementName = "masterAgreement1-" + machinename + "-" + instanceId;
+ cs.putString("internaldb.replication.master", masterAgreementName);
+ String cloneAgreementName = "cloneAgreement1-" + machinename + "-" + instanceId;
+ cs.putString("internaldb.replication.consumer", cloneAgreementName);
+
+ cs.commit(false);
+
+ // get connection to master
+ LDAPConnection masterConn = null;
+ ILdapConnFactory masterFactory = null;
+ try {
+ IConfigStore masterCfg = cs.getSubStore("preop.internaldb.master");
+ masterFactory = CMS.getLdapBoundConnFactory();
+ masterFactory.init(masterCfg);
+ masterConn = masterFactory.getConn();
+ } catch (Exception e) {
+ CMS.debug("setupEeplication: Failed to set up connection to master:" + e.toString());
+ e.printStackTrace();
+ releaseConnection(masterConn);
+ throw new IOException("Failed to set up replication: No connection to master");
+ }
+
+ // get connection to replica
+ LDAPConnection replicaConn = null;
+ ILdapConnFactory replicaFactory = null;
+ try {
+ IConfigStore replicaCfg = cs.getSubStore("internaldb");
+ replicaFactory = CMS.getLdapBoundConnFactory();
+ replicaFactory.init(replicaCfg);
+ replicaConn = replicaFactory.getConn();
+ } catch (Exception e) {
+ CMS.debug("SetupReplication: Failed to set up connection to replica:" + e.toString());
+ e.printStackTrace();
+ releaseConnection(masterConn);
+ releaseConnection(replicaConn);
+ throw new IOException("Failed to set up replication: No connection to replica");
+ }
+
+ try {
+ String master_hostname = cs.getString("preop.internaldb.master.ldapconn.host", "");
+ String master_replicationpwd = cs.getString("preop.internaldb.master.replication.password", "");
+ String replica_hostname = cs.getString("internaldb.ldapconn.host", "");
+ String replica_replicationpwd = cs.getString("preop.internaldb.replicationpwd", "");
+ String basedn = cs.getString("internaldb.basedn");
+ String suffix = cs.getString("internaldb.basedn", "");
+
+ String replicadn = "cn=replica,cn=\"" + suffix + "\",cn=mapping tree,cn=config";
+ CMS.debug("DatabasePanel setupReplication: replicadn=" + replicadn);
+
+ String masterBindUser = "Replication Manager " + masterAgreementName;
+ String cloneBindUser = "Replication Manager " + cloneAgreementName;
+
+ createReplicationManager(masterConn, masterBindUser, master_replicationpwd);
+ createReplicationManager(replicaConn, cloneBindUser, replica_replicationpwd);
+
+ String dir1 = getInstanceDir(masterConn);
+ createChangeLog(masterConn, dir1 + "/changelogs");
+
+ String dir2 = getInstanceDir(replicaConn);
+ createChangeLog(replicaConn, dir2 + "/changelogs");
+
+ int replicaId = cs.getInteger("dbs.beginReplicaNumber", 1);
+
+ replicaId = enableReplication(replicadn, masterConn, masterBindUser, basedn, replicaId);
+ replicaId = enableReplication(replicadn, replicaConn, cloneBindUser, basedn, replicaId);
+ cs.putString("dbs.beginReplicaNumber", Integer.toString(replicaId));
+
+ CMS.debug("setupReplication: Finished enabling replication");
+
+ createReplicationAgreement(replicadn, masterConn, masterAgreementName,
+ replica_hostname, cloneReplicationPort, replica_replicationpwd, basedn,
+ cloneBindUser, secure, replicationSecurity);
+
+ createReplicationAgreement(replicadn, replicaConn, cloneAgreementName,
+ master_hostname, masterReplicationPort, master_replicationpwd, basedn,
+ masterBindUser, secure, replicationSecurity);
+
+ // initialize consumer
+ initializeConsumer(replicadn, masterConn, masterAgreementName);
+
+ while (!replicationDone(replicadn, masterConn, masterAgreementName)) {
+ CMS.debug("setupReplication: Waiting for replication to complete");
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ String status = replicationStatus(replicadn, masterConn, masterAgreementName);
+ if (!status.startsWith("0 ")) {
+ CMS.debug("setupReplication: consumer initialization failed. " +status);
+ throw new IOException("consumer initialization failed. " + status);
+ }
+
+ // remove master ldap password from password.conf (if present)
+ String passwordFile = cs.getString("passwordFile");
+ IConfigStore psStore = CMS.createFileConfigStore(passwordFile);
+ psStore.remove("master_internaldb");
+ psStore.commit(false);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ CMS.debug("setupReplication: " + e.toString());
+ throw new IOException("Failed to setup the replication for cloning.");
+ } finally {
+ releaseConnection(masterConn);
+ releaseConnection(replicaConn);
+ }
+}
+
+ public static void createReplicationManager(LDAPConnection conn, String bindUser, String pwd)
+ throws LDAPException {
+ LDAPAttributeSet attrs = null;
+ LDAPEntry entry = null;
+
+ // for older subsystems, the container ou=csusers, cn=config may not yet exist
+ String dn = "ou=csusers, cn=config";
+ try {
+ attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass", "top"));
+ attrs.add(new LDAPAttribute("objectclass", "organizationalUnit"));
+ attrs.add(new LDAPAttribute("ou", "csusers"));
+ entry = new LDAPEntry(dn, attrs);
+ conn.add(entry);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) {
+ CMS.debug("createReplicationManager: containing ou already exists");
+ } else {
+ CMS.debug("createReplicationManager: Failed to create containing ou. Exception: "
+ + e.toString());
+ throw e;
+ }
+ }
+
+ dn = "cn=" + LDAPUtil.escapeRDNValue(bindUser) + ",ou=csusers,cn=config";
+ try {
+ attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass", "top"));
+ attrs.add(new LDAPAttribute("objectclass", "person"));
+ attrs.add(new LDAPAttribute("userpassword", pwd));
+ attrs.add(new LDAPAttribute("cn", bindUser));
+ attrs.add(new LDAPAttribute("sn", "manager"));
+ entry = new LDAPEntry(dn, attrs);
+ conn.add(entry);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) {
+ CMS.debug("createReplicationManager: Replication Manager has already used");
+ try {
+ conn.delete(dn);
+ conn.add(entry);
+ } catch (LDAPException ee) {
+ CMS.debug("createReplicationManager: " + ee.toString());
+ }
+ return;
+ } else {
+ CMS.debug("createReplicationManager: Failed to create replication manager. Exception: "
+ + e.toString());
+ throw e;
+ }
+ }
+
+ CMS.debug("createReplicationManager: Successfully created Replication Manager");
+ }
+
+ public static void createChangeLog(LDAPConnection conn, String dir)
+ throws LDAPException {
+ LDAPAttributeSet attrs = null;
+ LDAPEntry entry = null;
+ String dn = "cn=changelog5,cn=config";
+ try {
+ attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass", "top"));
+ attrs.add(new LDAPAttribute("objectclass", "extensibleObject"));
+ attrs.add(new LDAPAttribute("cn", "changelog5"));
+ attrs.add(new LDAPAttribute("nsslapd-changelogdir", dir));
+ entry = new LDAPEntry(dn, attrs);
+ conn.add(entry);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) {
+ CMS.debug("createChangeLog: Changelog entry has already used");
+ /* leave it, dont delete it because it will have operation error */
+ return;
+ } else {
+ CMS.debug("createChangeLog: Failed to create changelog entry. Exception: " + e.toString());
+ throw e;
+ }
+ }
+
+ CMS.debug("createChangeLog: Successfully create change log entry");
+ }
+
+ public static int enableReplication(String replicadn, LDAPConnection conn, String bindUser, String basedn, int id)
+ throws LDAPException {
+ CMS.debug("enableReplication: replicadn: " + replicadn);
+ LDAPAttributeSet attrs = null;
+ LDAPEntry entry = null;
+ try {
+ attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass", "top"));
+ attrs.add(new LDAPAttribute("objectclass", "nsDS5Replica"));
+ attrs.add(new LDAPAttribute("objectclass", "extensibleobject"));
+ attrs.add(new LDAPAttribute("nsDS5ReplicaRoot", basedn));
+ attrs.add(new LDAPAttribute("nsDS5ReplicaType", "3"));
+ attrs.add(new LDAPAttribute("nsDS5ReplicaBindDN",
+ "cn=" + LDAPUtil.escapeRDNValue(bindUser) + ",ou=csusers,cn=config"));
+ attrs.add(new LDAPAttribute("cn", "replica"));
+ attrs.add(new LDAPAttribute("nsDS5ReplicaId", Integer.toString(id)));
+ attrs.add(new LDAPAttribute("nsds5flags", "1"));
+ entry = new LDAPEntry(replicadn, attrs);
+ conn.add(entry);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) {
+ /* BZ 470918 -we cant just add the new dn. We need to do a replace instead
+ * until the DS code is fixed */
+ CMS.debug("enableReplication: " + replicadn + " has already been used");
+
+ try {
+ entry = conn.read(replicadn);
+ LDAPAttribute attr = entry.getAttribute("nsDS5ReplicaBindDN");
+ attr.addValue("cn=" + LDAPUtil.escapeRDNValue(bindUser) + ",ou=csusers,cn=config");
+ LDAPModification mod = new LDAPModification(LDAPModification.REPLACE, attr);
+ conn.modify(replicadn, mod);
+ } catch (LDAPException ee) {
+ CMS.debug("enableReplication: Failed to modify "
+ + replicadn + " entry. Exception: " + e.toString());
+ }
+ return id;
+ } else {
+ CMS.debug("enableReplication: Failed to create "
+ + replicadn + " entry. Exception: " + e.toString());
+ return id;
+ }
+ }
+
+ CMS.debug("enableReplication: Successfully create " + replicadn + " entry.");
+ return id + 1;
+ }
+
+ public static void createReplicationAgreement(String replicadn, LDAPConnection conn, String name,
+ String replicahost, int replicaport, String replicapwd, String basedn, String bindUser,
+ String secure, String replicationSecurity) throws LDAPException {
+ String dn = "cn=" + LDAPUtil.escapeRDNValue(name) + "," + replicadn;
+ CMS.debug("createReplicationAgreement: dn: " + dn);
+ LDAPEntry entry = null;
+ LDAPAttributeSet attrs = null;
+ try {
+ attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass", "top"));
+ attrs.add(new LDAPAttribute("objectclass",
+ "nsds5replicationagreement"));
+ attrs.add(new LDAPAttribute("cn", name));
+ attrs.add(new LDAPAttribute("nsDS5ReplicaRoot", basedn));
+ attrs.add(new LDAPAttribute("nsDS5ReplicaHost", replicahost));
+
+ attrs.add(new LDAPAttribute("nsDS5ReplicaPort", "" + replicaport));
+ attrs.add(new LDAPAttribute("nsDS5ReplicaBindDN",
+ "cn=" + LDAPUtil.escapeRDNValue(bindUser) + ",ou=csusers,cn=config"));
+ attrs.add(new LDAPAttribute("nsDS5ReplicaBindMethod", "Simple"));
+ attrs.add(new LDAPAttribute("nsds5replicacredentials", replicapwd));
+
+ if (replicationSecurity.equals("SSL")) {
+ attrs.add(new LDAPAttribute("nsDS5ReplicaTransportInfo", "SSL"));
+ } else if (replicationSecurity.equals("TLS")) {
+ attrs.add(new LDAPAttribute("nsDS5ReplicaTransportInfo", "TLS"));
+ }
+
+ CMS.debug("About to set description attr to " + name);
+ attrs.add(new LDAPAttribute("description", name));
+
+ entry = new LDAPEntry(dn, attrs);
+ conn.add(entry);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) {
+ CMS.debug("createReplicationAgreement: " + dn + " has already used");
+ try {
+ conn.delete(dn);
+ } catch (LDAPException ee) {
+ CMS.debug("createReplicationAgreement: " + ee.toString());
+ throw ee;
+ }
+
+ try {
+ conn.add(entry);
+ } catch (LDAPException ee) {
+ CMS.debug("createReplicationAgreement: " + ee.toString());
+ throw ee;
+ }
+ } else {
+ CMS.debug("createReplicationAgreement: Failed to create "
+ + dn + " entry. Exception: " + e.toString());
+ throw e;
+ }
+ }
+
+ CMS.debug("createReplicationAgreement: Successfully create replication agreement " + name);
+ }
+
+ public static void initializeConsumer(String replicadn, LDAPConnection conn, String name) throws LDAPException {
+ String dn = "cn=" + LDAPUtil.escapeRDNValue(name) + "," + replicadn;
+ CMS.debug("initializeConsumer: initializeConsumer dn: " + dn);
+ CMS.debug("initializeConsumer: initializeConsumer host: " + conn.getHost() + " port: " + conn.getPort());
+
+ LDAPAttribute attr = new LDAPAttribute("nsds5beginreplicarefresh", "start");
+ LDAPModification mod = new LDAPModification(LDAPModification.REPLACE, attr);
+ conn.modify(dn, mod);
+
+ CMS.debug("initializeConsumer: Successfully initialized consumer");
+ }
+
+ public static boolean replicationDone(String replicadn, LDAPConnection conn, String name)
+ throws LDAPException, IOException {
+ String dn = "cn=" + LDAPUtil.escapeRDNValue(name) + "," + replicadn;
+ String filter = "(objectclass=*)";
+ String[] attrs = { "nsds5beginreplicarefresh" };
+
+ CMS.debug("replicationDone: dn: " + dn);
+
+ LDAPSearchResults results = conn.search(dn, LDAPConnection.SCOPE_BASE, filter, attrs, true);
+ int count = results.getCount();
+ if (count < 1) {
+ throw new IOException("Replication entry not found");
+ }
+
+ LDAPEntry entry = results.next();
+ LDAPAttribute refresh = entry.getAttribute("nsds5beginreplicarefresh");
+ if (refresh == null) {
+ return true;
+ }
+ return false;
+ }
+
+ public static String replicationStatus(String replicadn, LDAPConnection conn, String name)
+ throws IOException, LDAPException {
+ String dn = "cn=" + LDAPUtil.escapeRDNValue(name) + "," + replicadn;
+ String filter = "(objectclass=*)";
+ String[] attrs = { "nsds5replicalastinitstatus" };
+
+ CMS.debug("replicationStatus: dn: " + dn);
+
+ LDAPSearchResults results = conn.search(dn, LDAPConnection.SCOPE_BASE, filter, attrs, false);
+
+ int count = results.getCount();
+ if (count < 1) {
+ throw new IOException("Replication entry not found");
+ }
+
+ LDAPEntry entry = results.next();
+ LDAPAttribute attr = entry.getAttribute("nsds5replicalastinitstatus");
+ if (attr != null) {
+ @SuppressWarnings("unchecked")
+ Enumeration<String> valsInAttr = attr.getStringValues();
+ if (valsInAttr.hasMoreElements()) {
+ return valsInAttr.nextElement();
+ } else {
+ throw new IOException("No value returned for nsds5replicalastinitstatus");
+ }
+ } else {
+ throw new IOException("nsDS5ReplicaLastInitStatus is null.");
+ }
+ }
+
+ public static void reInitSubsystem(String csType) throws EBaseException {
+ CMS.reinit(IDBSubsystem.SUB_ID);
+ if (csType.equals("CA"))
+ CMS.reinit(ICertificateAuthority.ID);
+ CMS.reinit(IAuthSubsystem.ID);
+ CMS.reinit(IAuthzSubsystem.ID);
+ CMS.reinit(IUGSubsystem.ID);
+ }
+
+ public static void setExternalCACert(String certStr, String subsystem, IConfigStore config, Cert certObj) throws Exception {
+ certStr = CryptoUtil.stripCertBrackets(certStr.trim());
+ certStr = CryptoUtil.normalizeCertStr(certStr);
+ config.putString(subsystem + ".external_ca.cert", certStr);
+ certObj.setSubsystem(subsystem);
+ certObj.setType(config.getString("preop.ca.type", "otherca"));
+ certObj.setCert(certStr);
+ }
+
+ public static void setExternalCACertChain(String certChainStr, String subsystem, IConfigStore config, Cert certObj) {
+ certChainStr = CryptoUtil.normalizeCertAndReq(certChainStr);
+ config.putString(subsystem + ".external_ca_chain.cert", certChainStr);
+ certObj.setCertChain(certChainStr);
+ }
+
+ public static void createECCKeyPair(String token, String curveName, IConfigStore config, String ct)
+ throws NoSuchAlgorithmException, NoSuchTokenException, TokenException,
+ CryptoManager.NotInitializedException, EPropertyNotFound, EBaseException {
+ CMS.debug("createECCKeyPair: Generating ECC key pair with curvename=" + curveName + ", token=" + token);
+ KeyPair pair = null;
+ /*
+ * default ssl server cert to ECDHE unless stated otherwise
+ * note: IE only supports "ECDHE", but "ECDH" is more efficient
+ *
+ * for "ECDHE", server.xml should have the following for ciphers:
+ * +TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ * -TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ *
+ * for "ECDH", server.xml should have the following for ciphers:
+ * -TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ * +TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ */
+ String sslType = "ECDHE";
+ try {
+ sslType = config.getString(PCERT_PREFIX + ct + "ec.type", "ECDHE");
+ } catch (Exception e) {}
+
+ // ECDHE needs "SIGN" but no "DERIVE"
+ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage usages_mask[] = {
+ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.DERIVE
+ };
+
+ // ECDH needs "DERIVE" but no any kind of "SIGN"
+ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage ECDH_usages_mask[] = {
+ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN,
+ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN_RECOVER,
+ };
+
+ do {
+ if (ct.equals("sslserver") && sslType.equalsIgnoreCase("ECDH")) {
+ CMS.debug("SizePanel: createECCKeypair: sslserver cert for ECDH. Make sure server.xml is set " +
+ "properly with -TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,+TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA");
+ pair = CryptoUtil.generateECCKeyPair(token, curveName, null, ECDH_usages_mask);
+ } else {
+ if (ct.equals("sslserver")) {
+ CMS.debug("SizePanel: createECCKeypair: sslserver cert for ECDHE. Make sure server.xml is set " +
+ "properly with +TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA");
+ }
+ pair = CryptoUtil.generateECCKeyPair(token, curveName, null, usages_mask);
+ }
+
+ // XXX - store curve , w
+ byte id[] = ((org.mozilla.jss.crypto.PrivateKey) pair.getPrivate()).getUniqueID();
+ String kid = CryptoUtil.byte2string(id);
+ config.putString(PCERT_PREFIX + ct + ".privkey.id", kid);
+
+ // try to locate the private key
+ org.mozilla.jss.crypto.PrivateKey privk = CryptoUtil.findPrivateKeyFromID(CryptoUtil.string2byte(kid));
+ if (privk == null) {
+ CMS.debug("Found bad ECC key id " + kid);
+ pair = null;
+ }
+ } while (pair == null);
+
+ CMS.debug("Public key class " + pair.getPublic().getClass().getName());
+ byte encoded[] = pair.getPublic().getEncoded();
+ config.putString(PCERT_PREFIX + ct + ".pubkey.encoded", CryptoUtil.byte2string(encoded));
+
+ String keyAlgo = config.getString(PCERT_PREFIX + ct + ".signingalgorithm");
+ setSigningAlgorithm(ct, keyAlgo, config);
+ }
+
+ public static void createRSAKeyPair(String token, int keysize, IConfigStore config, String ct)
+ throws NoSuchAlgorithmException, NoSuchTokenException, TokenException,
+ CryptoManager.NotInitializedException, EPropertyNotFound, EBaseException {
+ /* generate key pair */
+ KeyPair pair = null;
+ do {
+ pair = CryptoUtil.generateRSAKeyPair(token, keysize);
+ byte id[] = ((org.mozilla.jss.crypto.PrivateKey) pair.getPrivate()).getUniqueID();
+ String kid = CryptoUtil.byte2string(id);
+ config.putString(PCERT_PREFIX + ct + ".privkey.id", kid);
+ // try to locate the private key
+ org.mozilla.jss.crypto.PrivateKey privk =
+ CryptoUtil.findPrivateKeyFromID(CryptoUtil.string2byte(kid));
+ if (privk == null) {
+ CMS.debug("Found bad RSA key id " + kid);
+ pair = null;
+ }
+ } while (pair == null);
+
+ byte modulus[] = ((RSAPublicKey) pair.getPublic()).getModulus().toByteArray();
+ byte exponent[] = ((RSAPublicKey) pair.getPublic()).getPublicExponent().toByteArray();
+
+ config.putString(PCERT_PREFIX + ct + ".pubkey.modulus",
+ CryptoUtil.byte2string(modulus));
+ config.putString(PCERT_PREFIX + ct + ".pubkey.exponent",
+ CryptoUtil.byte2string(exponent));
+
+ String keyAlgo = config.getString(PCERT_PREFIX + ct + ".signingalgorithm");
+ setSigningAlgorithm(ct, keyAlgo, config);
+ }
+
+ public static void setSigningAlgorithm(String ct, String keyAlgo, IConfigStore config) throws EPropertyNotFound, EBaseException {
+ String systemType = config.getString("cs.type");
+ if (systemType.equalsIgnoreCase("CA")) {
+ if (ct.equals("signing")) {
+ config.putString("ca.signing.defaultSigningAlgorithm", keyAlgo);
+ config.putString("ca.crl.MasterCRL.signingAlgorithm", keyAlgo);
+ } else if (ct.equals("ocsp_signing")) {
+ config.putString("ca.ocsp_signing.defaultSigningAlgorithm", keyAlgo);
+ }
+ } else if (systemType.equalsIgnoreCase("OCSP")) {
+ if (ct.equals("signing")) {
+ config.putString("ocsp.signing.defaultSigningAlgorithm", keyAlgo);
+ }
+ } else if (systemType.equalsIgnoreCase("KRA") || systemType.equalsIgnoreCase("DRM")) {
+ if (ct.equals("transport")) {
+ config.putString("kra.transportUnit.signingAlgorithm", keyAlgo);
+ }
+ }
+ }
+
+ public static int getSubsystemCount(String hostname, int https_admin_port,
+ boolean https, String type) throws IOException, SAXException, ParserConfigurationException {
+ CMS.debug("getSubsystemCount start");
+ String c = getDomainXML(hostname, https_admin_port, true);
+ if (c != null) {
+ ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes());
+ XMLObject obj = new XMLObject(bis);
+ String containerName = type + "List";
+ Node n = obj.getContainer(containerName);
+ NodeList nlist = n.getChildNodes();
+ String countS = "";
+ for (int i = 0; i < nlist.getLength(); i++) {
+ Element nn = (Element) nlist.item(i);
+ String tagname = nn.getTagName();
+ if (tagname.equals("SubsystemCount")) {
+ NodeList nlist1 = nn.getChildNodes();
+ Node nn1 = nlist1.item(0);
+ countS = nn1.getNodeValue();
+ break;
+ }
+ }
+ CMS.debug("getSubsystemCount: SubsystemCount=" + countS);
+ int num = 0;
+
+ if (countS != null && !countS.equals("")) {
+ try {
+ num = Integer.parseInt(countS);
+ } catch (Exception ee) {
+ }
+ }
+
+ return num;
+ }
+ return -1;
+ }
+
+ public static void configCert(HttpServletRequest request, HttpServletResponse response,
+ Context context, Cert certObj, WizardPanelBase panel) throws IOException {
+
+ IConfigStore config = CMS.getConfigStore();
+ String caType = certObj.getType();
+ CMS.debug("configCert: caType is " + caType);
+ X509CertImpl cert = null;
+ String certTag = certObj.getCertTag();
+
+ try {
+ updateConfig(config, certTag);
+ if (caType.equals("remote")) {
+ String v = config.getString("preop.ca.type", "");
+
+ CMS.debug("configCert: remote CA");
+ String pkcs10 = CertUtil.getPKCS10(config, PCERT_PREFIX, certObj, context);
+ certObj.setRequest(pkcs10);
+ String subsystem = config.getString(PCERT_PREFIX + certTag + ".subsystem");
+ config.putString(subsystem + "." + certTag + ".certreq", pkcs10);
+ String profileId = config.getString(PCERT_PREFIX + certTag + ".profile");
+ String session_id = CMS.getConfigSDSessionId();
+ String sd_hostname = "";
+ int sd_ee_port = -1;
+ try {
+ sd_hostname = config.getString("securitydomain.host", "");
+ sd_ee_port = config.getInteger("securitydomain.httpseeport", -1);
+ } catch (Exception ee) {
+ CMS.debug("configCert(): exception caught:" + ee.toString());
+ }
+ String sysType = config.getString("cs.type", "");
+ String machineName = config.getString("machineName", "");
+ String securePort = config.getString("service.securePort", "");
+ if (certTag.equals("subsystem")) {
+ boolean standalone = config.getBoolean(sysType.toLowerCase() + ".standalone", false);
+ if (standalone) {
+ // Treat standalone subsystem the same as "otherca"
+ config.putString(subsystem + "." + certTag + ".cert",
+ "...paste certificate here...");
+ } else {
+ String content =
+ "requestor_name="
+ + sysType + "-" + machineName + "-" + securePort + "&profileId=" + profileId
+ + "&cert_request_type=pkcs10&cert_request=" + URLEncoder.encode(pkcs10, "UTF-8")
+ + "&xmlOutput=true&sessionID=" + session_id;
+ cert = CertUtil.createRemoteCert(sd_hostname, sd_ee_port,
+ content, response, panel);
+ if (cert == null) {
+ throw new IOException("Error: remote certificate is null");
+ }
+ }
+ } else if (v.equals("sdca")) {
+ String ca_hostname = "";
+ int ca_port = -1;
+ try {
+ ca_hostname = config.getString("preop.ca.hostname", "");
+ ca_port = config.getInteger("preop.ca.httpsport", -1);
+ } catch (Exception ee) {
+ }
+
+ String content =
+ "requestor_name="
+ + sysType + "-" + machineName + "-" + securePort + "&profileId=" + profileId
+ + "&cert_request_type=pkcs10&cert_request=" + URLEncoder.encode(pkcs10, "UTF-8")
+ + "&xmlOutput=true&sessionID=" + session_id;
+ cert = CertUtil.createRemoteCert(ca_hostname, ca_port,
+ content, response, panel);
+ if (cert == null) {
+ throw new IOException("Error: remote certificate is null");
+ }
+ } else if (v.equals("otherca")) {
+ config.putString(subsystem + "." + certTag + ".cert",
+ "...paste certificate here...");
+ } else {
+ CMS.debug("NamePanel: no preop.ca.type is provided");
+ }
+ } else { // not remote CA, ie, self-signed or local
+ ISubsystem ca = CMS.getSubsystem(ICertificateAuthority.ID);
+
+ if (ca == null) {
+ String s = PCERT_PREFIX + certTag + ".type";
+
+ CMS.debug(
+ "The value for " + s
+ + " should be remote, nothing else.");
+ throw new IOException(
+ "The value for " + s + " should be remote");
+ }
+
+ String pubKeyType = config.getString(
+ PCERT_PREFIX + certTag + ".keytype");
+ if (pubKeyType.equals("rsa")) {
+
+ String pubKeyModulus = config.getString(
+ PCERT_PREFIX + certTag + ".pubkey.modulus");
+ String pubKeyPublicExponent = config.getString(
+ PCERT_PREFIX + certTag + ".pubkey.exponent");
+ String subsystem = config.getString(
+ PCERT_PREFIX + certTag + ".subsystem");
+
+ if (certTag.equals("signing")) {
+ X509Key x509key = CryptoUtil.getPublicX509Key(
+ CryptoUtil.string2byte(pubKeyModulus),
+ CryptoUtil.string2byte(pubKeyPublicExponent));
+
+ cert = CertUtil.createLocalCert(config, x509key,
+ PCERT_PREFIX, certTag, caType, context);
+ } else {
+ String cacert = config.getString("ca.signing.cert", "");
+
+ if (cacert.equals("") || cacert.startsWith("...")) {
+ certObj.setCert(
+ "...certificate be generated internally...");
+ config.putString(subsystem + "." + certTag + ".cert",
+ "...certificate be generated internally...");
+ } else {
+ X509Key x509key = CryptoUtil.getPublicX509Key(
+ CryptoUtil.string2byte(pubKeyModulus),
+ CryptoUtil.string2byte(pubKeyPublicExponent));
+
+ cert = CertUtil.createLocalCert(config, x509key,
+ PCERT_PREFIX, certTag, caType, context);
+ }
+ }
+ } else if (pubKeyType.equals("ecc")) {
+ String pubKeyEncoded = config.getString(
+ PCERT_PREFIX + certTag + ".pubkey.encoded");
+ String subsystem = config.getString(
+ PCERT_PREFIX + certTag + ".subsystem");
+
+ if (certTag.equals("signing")) {
+
+ X509Key x509key = CryptoUtil.getPublicX509ECCKey(CryptoUtil.string2byte(pubKeyEncoded));
+ cert = CertUtil.createLocalCert(config, x509key,
+ PCERT_PREFIX, certTag, caType, context);
+ } else {
+ String cacert = config.getString("ca.signing.cert", "");
+
+ if (cacert.equals("") || cacert.startsWith("...")) {
+ certObj.setCert(
+ "...certificate be generated internally...");
+ config.putString(subsystem + "." + certTag + ".cert",
+ "...certificate be generated internally...");
+ } else {
+ X509Key x509key = CryptoUtil.getPublicX509ECCKey(
+ CryptoUtil.string2byte(pubKeyEncoded));
+
+ cert = CertUtil.createLocalCert(config, x509key,
+ PCERT_PREFIX, certTag, caType, context);
+ }
+ }
+ } else {
+ // invalid key type
+ CMS.debug("Invalid key type " + pubKeyType);
+ }
+ if (cert != null) {
+ if (certTag.equals("subsystem"))
+ CertUtil.addUserCertificate(cert);
+ }
+ } // done self-signed or local
+
+ if (cert != null) {
+ byte[] certb = cert.getEncoded();
+ String certs = CryptoUtil.base64Encode(certb);
+
+ certObj.setCert(certs);
+ String subsystem = config.getString(
+ PCERT_PREFIX + certTag + ".subsystem");
+ config.putString(subsystem + "." + certTag + ".cert", certs);
+ }
+ config.commit(false);
+ } catch (IOException e) {
+ throw e;
+ } catch (Exception e) {
+ CMS.debug("configCert() exception caught:" + e.toString());
+ }
+ }
+
+ public static void updateConfig(IConfigStore config, String certTag)
+ throws EBaseException, IOException {
+ String token = config.getString("preop.module.token");
+ String subsystem = config.getString(PCERT_PREFIX + certTag + ".subsystem");
+ String nickname = getNickname(config, certTag);
+
+ CMS.debug("NamePanel: updateConfig() for certTag " + certTag);
+ if (certTag.equals("signing") || certTag.equals("ocsp_signing")) {
+ CMS.debug("NamePanel: setting signing nickname=" + nickname);
+ config.putString(subsystem + "." + certTag + ".cacertnickname", nickname);
+ config.putString(subsystem + "." + certTag + ".certnickname", nickname);
+ }
+
+ // if KRA, hardware token needs param "kra.storageUnit.hardware" in CS.cfg
+ String cstype = config.getString("cs.type", null);
+ cstype = cstype.toLowerCase();
+ if (cstype.equals("kra")) {
+ if (!token.equals("Internal Key Storage Token")) {
+ if (certTag.equals("storage")) {
+ config.putString(subsystem + ".storageUnit.hardware", token);
+ config.putString(subsystem + ".storageUnit.nickName", token + ":" + nickname);
+ } else if (certTag.equals("transport")) {
+ config.putString(subsystem + ".transportUnit.nickName", token + ":" + nickname);
+ }
+ } else { // software token
+ if (certTag.equals("storage")) {
+ config.putString(subsystem + ".storageUnit.nickName", nickname);
+ } else if (certTag.equals("transport")) {
+ config.putString(subsystem + ".transportUnit.nickName", nickname);
+ }
+ }
+ }
+
+ String serverCertNickname = nickname;
+ String path = CMS.getConfigStore().getString("instanceRoot", "");
+ if (certTag.equals("sslserver")) {
+ if (!token.equals("Internal Key Storage Token")) {
+ serverCertNickname = token + ":" + nickname;
+ }
+ PrintStream ps = new PrintStream(new FileOutputStream(path + "/conf/serverCertNick.conf"));
+ ps.println(serverCertNickname);
+ ps.close();
+ }
+
+ config.putString(subsystem + "." + certTag + ".nickname", nickname);
+ config.putString(subsystem + "." + certTag + ".tokenname", token);
+ if (certTag.equals("audit_signing")) {
+ if (!token.equals("Internal Key Storage Token") && !token.equals("")) {
+ config.putString("log.instance.SignedAudit.signedAuditCertNickname",
+ token + ":" + nickname);
+ } else {
+ config.putString("log.instance.SignedAudit.signedAuditCertNickname",
+ nickname);
+ }
+ }
+
+ // for system certs verification
+ if (!token.equals("Internal Key Storage Token") && !token.equals("")) {
+ config.putString(subsystem + ".cert." + certTag + ".nickname",
+ token + ":" + nickname);
+ } else {
+ config.putString(subsystem + ".cert." + certTag + ".nickname", nickname);
+ }
+
+ config.commit(false);
+ CMS.debug("updateConfig() done");
+ }
+
+ public static String getNickname(IConfigStore config, String certTag) throws EBaseException {
+ String instanceID = config.getString("instanceId", "");
+
+ String nickname = certTag + "Cert cert-" + instanceID;
+ String preferredNickname = null;
+ try {
+ preferredNickname = config.getString(PCERT_PREFIX + certTag + ".nickname", null);
+ } catch (EBaseException e) {
+ }
+
+ if (preferredNickname != null) {
+ return preferredNickname;
+ }
+ return nickname;
+ }
+
+ public static int getPortFromSecurityDomain(String domainXML, String host, int port, String csType,
+ String givenTag, String wantedTag) throws SAXException, IOException, ParserConfigurationException {
+ IConfigStore cs = CMS.getConfigStore();
+ ByteArrayInputStream bis = new ByteArrayInputStream(domainXML.getBytes());
+ XMLObject parser = new XMLObject(bis);
+ Document doc = parser.getDocument();
+ NodeList nodeList = doc.getElementsByTagName(csType);
+
+ // save domain name in cfg
+ cs.putString("securitydomain.name", parser.getValue("Name"));
+
+ int len = nodeList.getLength();
+ CMS.debug("len: "+ len);
+ for (int i = 0; i < len; i++) {
+ Node node = nodeList.item(i);
+ String v_host = parser.getValuesFromContainer(node, "Host").elementAt(0);
+ CMS.debug("v_host " + v_host);
+ String v_given_port = parser.getValuesFromContainer(node, givenTag).elementAt(0);
+ CMS.debug("v_port " + v_given_port);
+ if (!(v_host.equals(host) && v_given_port.equals(port + "")))
+ continue;
+ String wanted_port = parser.getValuesFromContainer(node, wantedTag).elementAt(0);
+ return Integer.parseInt(wanted_port);
+ }
+
+ return 0;
+ }
+
+ public static void updateCloneConfig()
+ throws EBaseException, IOException {
+ IConfigStore config = CMS.getConfigStore();
+ String cstype = config.getString("cs.type", null);
+ cstype = cstype.toLowerCase();
+ if (cstype.equals("kra")) {
+ String token = config.getString("preop.module.token");
+ if (!token.equals("Internal Key Storage Token")) {
+ CMS.debug("NamePanel: updating configuration for KRA clone with hardware token");
+ String subsystem = config.getString(PCERT_PREFIX + "storage.subsystem");
+ String storageNickname = getNickname(config, "storage");
+ String transportNickname = getNickname(config, "transport");
+
+ config.putString(subsystem + ".storageUnit.hardware", token);
+ config.putString(subsystem + ".storageUnit.nickName", token + ":" + storageNickname);
+ config.putString(subsystem + ".transportUnit.nickName", token + ":" + transportNickname);
+ config.commit(false);
+ } else { // software token
+ // parameters already set
+ }
+ }
+
+ // audit signing cert
+ String audit_nn = config.getString(cstype + ".audit_signing" + ".nickname", "");
+ String audit_tk = config.getString(cstype + ".audit_signing" + ".tokenname", "");
+ if (!audit_tk.equals("Internal Key Storage Token") && !audit_tk.equals("")) {
+ config.putString("log.instance.SignedAudit.signedAuditCertNickname",
+ audit_tk + ":" + audit_nn);
+ } else {
+ config.putString("log.instance.SignedAudit.signedAuditCertNickname",
+ audit_nn);
+ }
+ }
+
+ public static void handleCertRequest(IConfigStore config, String certTag, Cert cert) throws EPropertyNotFound,
+ EBaseException, InvalidKeyException, NotInitializedException, TokenException, NoSuchAlgorithmException,
+ NoSuchProviderException, CertificateException, SignatureException, IOException {
+
+ // get public key
+ String pubKeyType = config.getString(PCERT_PREFIX + certTag + ".keytype");
+ String algorithm = config.getString(PCERT_PREFIX + certTag + ".keyalgorithm");
+ X509Key pubk = null;
+ if (pubKeyType.equals("rsa")) {
+ pubk = getRSAX509Key(config, certTag);
+ } else if (pubKeyType.equals("ecc")) {
+ pubk = getECCX509Key(config, certTag);
+ } else {
+ CMS.debug("handleCertRequest() - " + "pubKeyType " + pubKeyType + " is unsupported!");
+ return;
+ }
+
+ CMS.debug("handleCertRequest: tag=" + certTag);
+ if (pubk == null) {
+ CMS.debug("handleCertRequest: error getting public key null");
+ return;
+ }
+
+ // get private key
+ String privKeyID = config.getString(PCERT_PREFIX + certTag + ".privkey.id");
+ CMS.debug("privKeyID=" + privKeyID);
+ byte[] keyIDb = CryptoUtil.string2byte(privKeyID);
+
+ PrivateKey privk = CryptoUtil.findPrivateKeyFromID(keyIDb);
+ if (privk == null) {
+ CMS.debug("handleCertRequest: error getting private key");
+ }
+
+ // construct cert request
+ String caDN = config.getString(PCERT_PREFIX + certTag + ".dn");
+
+ cert.setDN(caDN);
+ PKCS10 certReq = CryptoUtil.createCertificationRequest(caDN, pubk, privk, algorithm);
+
+ CMS.debug("handleCertRequest: created cert request");
+ byte[] certReqb = certReq.toByteArray();
+ String certReqs = CryptoUtil.base64Encode(certReqb);
+ String certReqf = CryptoUtil.reqFormat(certReqs);
+
+ String subsystem = config.getString(PCERT_PREFIX + certTag + ".subsystem");
+ config.putString(subsystem + "." + certTag + ".certreq", certReqs);
+ config.commit(false);
+ cert.setRequest(certReqf);
+
+ }
+
+ public static X509Key getECCX509Key(IConfigStore config, String certTag) throws EPropertyNotFound, EBaseException,
+ InvalidKeyException {
+ X509Key pubk = null;
+ String pubKeyEncoded = config.getString(PCERT_PREFIX + certTag + ".pubkey.encoded");
+ pubk = CryptoUtil.getPublicX509ECCKey(CryptoUtil.string2byte(pubKeyEncoded));
+ return pubk;
+ }
+
+ public static X509Key getRSAX509Key(IConfigStore config, String certTag) throws EPropertyNotFound, EBaseException,
+ InvalidKeyException {
+ X509Key pubk = null;
+
+ String pubKeyModulus = config.getString(PCERT_PREFIX + certTag + ".pubkey.modulus");
+ String pubKeyPublicExponent = config.getString(PCERT_PREFIX + certTag + ".pubkey.exponent");
+ pubk = CryptoUtil.getPublicX509Key(
+ CryptoUtil.string2byte(pubKeyModulus),
+ CryptoUtil.string2byte(pubKeyPublicExponent));
+ return pubk;
+ }
+
+ public static int handleCerts(Cert cert) throws IOException, EBaseException, CertificateException,
+ NotInitializedException, TokenException, InvalidKeyException {
+ String certTag = cert.getCertTag();
+ String subsystem = cert.getSubsystem();
+ String nickname = cert.getNickname();
+ IConfigStore config = CMS.getConfigStore();
+
+ boolean enable = config.getBoolean(PCERT_PREFIX + certTag + ".enable", true);
+ if (!enable) return 0;
+
+ CMS.debug("handleCerts(): for cert tag '" + cert.getCertTag() + "' using cert type '" + cert.getType() + "'");
+ String b64 = cert.getCert();
+ String tokenname = config.getString("preop.module.token", "");
+
+ if (cert.getType().equals("local") && b64.equals("...certificate be generated internally...")) {
+ String pubKeyType = config.getString(PCERT_PREFIX + certTag + ".keytype");
+ X509Key x509key = null;
+ if (pubKeyType.equals("rsa")) {
+ x509key = getRSAX509Key(config, certTag);
+ } else if (pubKeyType.equals("ecc")) {
+ x509key = getECCX509Key(config, certTag);
+ }
+
+ if (findCertificate(tokenname, nickname)) {
+ if (!certTag.equals("sslserver")) return 0;
+ }
+ X509CertImpl impl = CertUtil.createLocalCert(config, x509key,
+ PCERT_PREFIX, certTag, cert.getType(), null);
+
+ if (impl != null) {
+ byte[] certb = impl.getEncoded();
+ String certs = CryptoUtil.base64Encode(certb);
+
+ cert.setCert(certs);
+ config.putString(subsystem + "." + certTag + ".cert", certs);
+ CMS.debug("handleCerts(): nickname=" + nickname);
+
+ try {
+ if (certTag.equals("sslserver") && findBootstrapServerCert())
+ deleteBootstrapServerCert();
+ if (findCertificate(tokenname, nickname))
+ deleteCert(tokenname, nickname);
+ if (certTag.equals("signing") && subsystem.equals("ca"))
+ CryptoUtil.importUserCertificate(impl, nickname);
+ else
+ CryptoUtil.importUserCertificate(impl, nickname, false);
+ CMS.debug("handleCerts(): cert imported for certTag '" + certTag + "'");
+ } catch (Exception ee) {
+ ee.printStackTrace();
+ CMS.debug("handleCerts(): import certificate for certTag=" + certTag + " Exception: " + ee.toString());
+ }
+ }
+ } else if (cert.getType().equals("remote")) {
+ if (b64 != null && b64.length() > 0 && !b64.startsWith("...")) {
+ CMS.debug("handleCerts(): process remote...import cert");
+ String b64chain = cert.getCertChain();
+
+ try {
+ if (certTag.equals("sslserver") && findBootstrapServerCert())
+ deleteBootstrapServerCert();
+ if (findCertificate(tokenname, nickname)) {
+ deleteCert(tokenname, nickname);
+ }
+ } catch (Exception e) {
+ CMS.debug("CertRequestPanel update (remote): deleteCert Exception=" + e.toString());
+ }
+
+ b64 = CryptoUtil.stripCertBrackets(b64.trim());
+ String certs = CryptoUtil.normalizeCertStr(b64);
+ byte[] certb = CryptoUtil.base64Decode(certs);
+
+ config.putString(subsystem + "." + certTag + ".cert", certs);
+ try {
+ CryptoManager cm = CryptoManager.getInstance();
+ X509Certificate x509cert = cm.importCertPackage(certb, nickname);
+ CryptoUtil.trustCertByNickname(nickname);
+
+ X509Certificate[] certchains = cm.buildCertificateChain(x509cert);
+ X509Certificate leaf = null;
+
+ if (certchains != null) {
+ CMS.debug("handleCerts(): certchains length=" + certchains.length);
+ leaf = certchains[certchains.length - 1];
+ }
+
+ if (leaf == null) {
+ CMS.debug("handleCerts(): leaf is null!");
+ throw new IOException("leaf is null");
+ }
+
+ if (b64chain != null && b64chain.length() != 0) {
+ CMS.debug("handlecerts: cert might not have contained chain...calling importCertificateChain: "
+ + b64chain);
+ try {
+ CryptoUtil.importCertificateChain(CryptoUtil.normalizeCertAndReq(b64chain));
+ } catch (Exception e) {
+ CMS.debug("handleCerts(): importCertChain: Exception: " + e.toString());
+ }
+ }
+
+ InternalCertificate icert = (InternalCertificate) leaf;
+
+ icert.setSSLTrust(
+ InternalCertificate.TRUSTED_CA
+ | InternalCertificate.TRUSTED_CLIENT_CA
+ | InternalCertificate.VALID_CA);
+ CMS.debug("handleCerts(): import certificate successfully, certTag=" + certTag);
+ } catch (Exception ee) {
+ ee.printStackTrace();
+ CMS.debug("handleCerts: import certificate for certTag=" + certTag + " Exception: "+ ee.toString());
+ }
+
+ } else {
+ CMS.debug("handleCerts(): b64 not set");
+ return 1;
+ }
+ } else {
+ b64 = CryptoUtil.stripCertBrackets(b64.trim());
+ String certs = CryptoUtil.normalizeCertStr(b64);
+ byte[] certb = CryptoUtil.base64Decode(certs);
+ X509CertImpl impl = new X509CertImpl(certb);
+ try {
+ if (certTag.equals("sslserver") && findBootstrapServerCert())
+ deleteBootstrapServerCert();
+ if (findCertificate(tokenname, nickname)) {
+ deleteCert(tokenname, nickname);
+ }
+ } catch (Exception ee) {
+ CMS.debug("handleCerts(): deleteCert Exception=" + ee.toString());
+ }
+
+ try {
+ if (certTag.equals("signing") && subsystem.equals("ca"))
+ CryptoUtil.importUserCertificate(impl, nickname);
+ else
+ CryptoUtil.importUserCertificate(impl, nickname, false);
+ } catch (Exception ee) {
+ CMS.debug("handleCerts(): Failed to import user certificate." + ee.toString());
+ return 1;
+ }
+ }
+
+ //update requests in request queue for local certs to allow renewal
+ if ((cert.getType().equals("local")) || (cert.getType().equals("selfsign"))) {
+ CertUtil.updateLocalRequest(config, certTag, cert.getRequest(), "pkcs10", null);
+ }
+
+ if (certTag.equals("signing") && subsystem.equals("ca")) {
+ String NickName = nickname;
+ if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token"))
+ NickName = tokenname + ":" + nickname;
+
+ CMS.debug("handleCerts(): set trust on CA signing cert " + NickName);
+ CryptoUtil.trustCertByNickname(NickName);
+ CMS.reinit(ICertificateAuthority.ID);
+ }
+ return 0;
+ }
+
+ public static void setCertPermissions(String tag) throws EBaseException, NotInitializedException,
+ ObjectNotFoundException, TokenException {
+ if (tag.equals("signing") || tag.equals("external_signing")) return;
+
+ IConfigStore cs = CMS.getConfigStore();
+ String nickname = cs.getString("preop.cert." + tag + ".nickname", "");
+ String tokenname = cs.getString("preop.module.token", "");
+ if (!tokenname.equals("Internal Key Storage Token"))
+ nickname = tokenname + ":" + nickname;
+
+ CryptoManager cm = CryptoManager.getInstance();
+ X509Certificate c = cm.findCertByNickname(nickname);
+
+ if (c instanceof InternalCertificate) {
+ InternalCertificate ic = (InternalCertificate) c;
+ ic.setSSLTrust(InternalCertificate.USER);
+ ic.setEmailTrust(InternalCertificate.USER);
+ if (tag.equals("audit_signing")) {
+ ic.setObjectSigningTrust(InternalCertificate.USER
+ | InternalCertificate.VALID_PEER | InternalCertificate.TRUSTED_PEER);
+ } else {
+ ic.setObjectSigningTrust(InternalCertificate.USER);
+ }
+ }
+ }
+
+ public static boolean findCertificate(String tokenname, String nickname) throws NotInitializedException,
+ TokenException, IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ CryptoManager cm = CryptoManager.getInstance();
+
+ String fullnickname = nickname;
+ boolean hardware = false;
+ if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token")) {
+ hardware = true;
+ fullnickname = tokenname + ":" + nickname;
+ }
+
+ X509Certificate cert = null;
+ try {
+ cert = cm.findCertByNickname(fullnickname);
+ } catch (ObjectNotFoundException e) {
+ return false;
+ }
+
+ if (cert == null)
+ return false;
+ try {
+ @SuppressWarnings("unused")
+ boolean done = cs.getBoolean("preop.CertRequestPanel.done"); // check for errors
+ } catch (Exception ee) {
+ if (hardware) {
+ CMS.debug("CertRequestPanel findCertificate: The certificate with the same nickname: "
+ + fullnickname + " has been found on HSM. Please remove it before proceeding.");
+ throw new IOException("The certificate with the same nickname: "
+ + fullnickname + " has been found on HSM. Please remove it before proceeding.");
+ }
+ }
+ return true;
+ }
+
+
+ public static boolean findBootstrapServerCert() throws EBaseException, NotInitializedException, TokenException {
+ IConfigStore cs = CMS.getConfigStore();
+
+ String nickname = cs.getString("preop.cert.sslserver.nickname");
+
+ CryptoManager cm = CryptoManager.getInstance();
+ X509Certificate cert;
+ try {
+ cert = cm.findCertByNickname(nickname);
+ } catch (ObjectNotFoundException e) {
+ return false;
+ }
+ Principal issuerDN = cert.getIssuerDN();
+ Principal subjectDN = cert.getSubjectDN();
+ if (issuerDN.equals(subjectDN)) return true;
+
+ return false;
+ }
+
+ public static void deleteBootstrapServerCert() throws EBaseException, NotInitializedException,
+ NoSuchTokenException, TokenException {
+ IConfigStore cs = CMS.getConfigStore();
+ String nickname = cs.getString("preop.cert.sslserver.nickname");
+ deleteCert("Internal Key Storage Token", nickname);
+ }
+
+ public static void deleteCert(String tokenname, String nickname) throws NotInitializedException,
+ NoSuchTokenException, TokenException {
+
+ CryptoManager cm = CryptoManager.getInstance();
+ CryptoToken tok = cm.getTokenByName(tokenname);
+ CryptoStore store = tok.getCryptoStore();
+ String fullnickname = nickname;
+ if (!tokenname.equals("") &&
+ !tokenname.equals("Internal Key Storage Token") &&
+ !tokenname.equals("internal"))
+ fullnickname = tokenname + ":" + nickname;
+
+ CMS.debug("deleteCert: nickname=" + fullnickname);
+ X509Certificate cert;
+ try {
+ cert = cm.findCertByNickname(fullnickname);
+ } catch (ObjectNotFoundException e) {
+ CMS.debug("deleteCert: cert not found");
+ return;
+ }
+
+ if (store instanceof PK11Store) {
+ PK11Store pk11store = (PK11Store) store;
+ try {
+ pk11store.deleteCertOnly(cert);
+ } catch (NoSuchItemOnTokenException e) {
+ }
+ CMS.debug("deleteCert: cert deleted successfully");
+ }
+ }
+
+ public static void backupKeys(String pwd, String fname) throws EPropertyNotFound, EBaseException,
+ NotInitializedException, ObjectNotFoundException, TokenException, DigestException,
+ InvalidKeyException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidBERException,
+ CertificateEncodingException, IllegalStateException, IllegalBlockSizeException, BadPaddingException,
+ IOException {
+ CMS.debug("backupKeys(): start");
+ IConfigStore cs = CMS.getConfigStore();
+ String certlist = cs.getString("preop.cert.list");
+
+ StringTokenizer st = new StringTokenizer(certlist, ",");
+ CryptoManager cm = CryptoManager.getInstance();
+
+ Password pass = new org.mozilla.jss.util.Password(pwd.toCharArray());
+ SEQUENCE encSafeContents = new SEQUENCE();
+ SEQUENCE safeContents = new SEQUENCE();
+ while (st.hasMoreTokens()) {
+ String t = st.nextToken();
+ if (t.equals("sslserver"))
+ continue;
+ String nickname = cs.getString("preop.cert." + t + ".nickname");
+ String modname = cs.getString("preop.module.token");
+
+ if (!modname.equals("Internal Key Storage Token"))
+ nickname = modname + ":" + nickname;
+
+ X509Certificate x509cert = cm.findCertByNickname(nickname);
+ byte localKeyId[] = addCertBag(x509cert, nickname, safeContents);
+ PrivateKey pkey = cm.findPrivKeyByCert(x509cert);
+ addKeyBag(pkey, x509cert, pass, localKeyId, encSafeContents);
+ }
+
+ X509Certificate[] cacerts = cm.getCACerts();
+
+ for (int i = 0; i < cacerts.length; i++) {
+ String nickname = null;
+ addCertBag(cacerts[i], nickname, safeContents);
+ }
+
+ AuthenticatedSafes authSafes = new AuthenticatedSafes();
+ authSafes.addSafeContents(safeContents);
+ authSafes.addSafeContents(encSafeContents);
+ PFX pfx = new PFX(authSafes);
+ pfx.computeMacData(pass, null, 5);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ pfx.encode(bos);
+ byte[] output = bos.toByteArray();
+ cs.putString("preop.pkcs12", CryptoUtil.byte2string(output));
+ pass.clear();
+ cs.commit(false);
+
+ if (fname != null) {
+ FileOutputStream fout = null;
+ try {
+ fout = new FileOutputStream(fname);
+ fout.write(output);
+ } catch (Exception e) {
+ throw new IOException("Failed to store keys in backup file" + e);
+ } finally {
+ if (fout != null) {
+ fout.close();
+ }
+ }
+ }
+ }
+
+ public static void addKeyBag(PrivateKey pkey, X509Certificate x509cert,
+ Password pass, byte[] localKeyId, SEQUENCE safeContents)
+ throws NoSuchAlgorithmException, InvalidBERException, InvalidKeyException,
+ InvalidAlgorithmParameterException, NotInitializedException, TokenException, IllegalStateException,
+ IllegalBlockSizeException, BadPaddingException, CharConversionException {
+
+ PasswordConverter passConverter = new PasswordConverter();
+
+ SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
+ byte salt[] = random.generateSeed(4); // 4 bytes salt
+ byte[] priData = getEncodedKey(pkey);
+
+ PrivateKeyInfo pki = (PrivateKeyInfo)
+ ASN1Util.decode(PrivateKeyInfo.getTemplate(), priData);
+ ASN1Value key = EncryptedPrivateKeyInfo.createPBE(
+ PBEAlgorithm.PBE_SHA1_DES3_CBC,
+ pass, salt, 1, passConverter, pki);
+ SET keyAttrs = createBagAttrs(
+ x509cert.getSubjectDN().toString(), localKeyId);
+ SafeBag keyBag = new SafeBag(SafeBag.PKCS8_SHROUDED_KEY_BAG,
+ key, keyAttrs);
+ safeContents.addElement(keyBag);
+
+ }
+
+ public static byte[] addCertBag(X509Certificate x509cert, String nickname,
+ SEQUENCE safeContents) throws CertificateEncodingException, NoSuchAlgorithmException, CharConversionException {
+ byte[] localKeyId = null;
+
+ ASN1Value cert = new OCTET_STRING(x509cert.getEncoded());
+ localKeyId = createLocalKeyId(x509cert);
+ SET certAttrs = null;
+ if (nickname != null)
+ certAttrs = createBagAttrs(nickname, localKeyId);
+ SafeBag certBag = new SafeBag(SafeBag.CERT_BAG,
+ new CertBag(CertBag.X509_CERT_TYPE, cert), certAttrs);
+ safeContents.addElement(certBag);
+
+ return localKeyId;
+ }
+
+ public static byte[] getEncodedKey(PrivateKey pkey) throws NotInitializedException, NoSuchAlgorithmException,
+ TokenException, IllegalStateException, CharConversionException, InvalidKeyException,
+ InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
+ CryptoManager cm = CryptoManager.getInstance();
+ CryptoToken token = cm.getInternalKeyStorageToken();
+ KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3);
+ SymmetricKey sk = kg.generate();
+ KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
+ byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
+ IVParameterSpec param = new IVParameterSpec(iv);
+ wrapper.initWrap(sk, param);
+ byte[] enckey = wrapper.wrap(pkey);
+ Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD);
+ c.initDecrypt(sk, param);
+ byte[] recovered = c.doFinal(enckey);
+ return recovered;
+ }
+
+ public static byte[] createLocalKeyId(X509Certificate cert)
+ throws NoSuchAlgorithmException, CertificateEncodingException {
+
+ // SHA1 hash of the X509Cert der encoding
+ byte certDer[] = cert.getEncoded();
+
+ MessageDigest md = MessageDigest.getInstance("SHA");
+
+ md.update(certDer);
+ return md.digest();
+
+ }
+
+ public static SET createBagAttrs(String nickName, byte localKeyId[]) throws CharConversionException {
+
+ SET attrs = new SET();
+ SEQUENCE nickNameAttr = new SEQUENCE();
+
+ nickNameAttr.addElement(SafeBag.FRIENDLY_NAME);
+ SET nickNameSet = new SET();
+
+ nickNameSet.addElement(new BMPString(nickName));
+ nickNameAttr.addElement(nickNameSet);
+ attrs.addElement(nickNameAttr);
+ SEQUENCE localKeyAttr = new SEQUENCE();
+
+ localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID);
+ SET localKeySet = new SET();
+
+ localKeySet.addElement(new OCTET_STRING(localKeyId));
+ localKeyAttr.addElement(localKeySet);
+ attrs.addElement(localKeyAttr);
+ return attrs;
+
+ }
+
+ public static void createAdminCertificate(String certRequest, String certRequestType, String subject)
+ throws InvalidBERException, IOException, InvalidKeyException, InvalidKeyFormatException,
+ NoSuchAlgorithmException, SignatureException, NoSuchProviderException, EBaseException {
+ IConfigStore cs = CMS.getConfigStore();
+ X509Key x509key = null;
+ if (certRequestType.equals("crmf")) {
+ byte[] b = CMS.AtoB(certRequest);
+ SEQUENCE crmfMsgs = CryptoUtil.parseCRMFMsgs(b);
+ subject = CryptoUtil.getSubjectName(crmfMsgs);
+ x509key = CryptoUtil.getX509KeyFromCRMFMsgs(crmfMsgs);
+ } else if (certRequestType.equals("pkcs10")) {
+ byte[] b = CMS.AtoB(certRequest);
+ PKCS10 pkcs10 = new PKCS10(b);
+ x509key = pkcs10.getSubjectPublicKeyInfo();
+ }
+
+ if (x509key == null) {
+ CMS.debug("createAdminCertificate() - x509key is null!");
+ throw new IOException("x509key is null");
+ }
+
+ cs.putString(PCERT_PREFIX + "admin.dn", subject);
+ String caType = cs.getString(PCERT_PREFIX + "admin.type", "local");
+ X509CertImpl impl = CertUtil.createLocalCert(cs, x509key, PCERT_PREFIX, "admin", caType, null);
+
+ // update the locally created request for renewal
+ CertUtil.updateLocalRequest(cs, "admin", certRequest, certRequestType, subject);
+
+ ISubsystem ca = CMS.getSubsystem("ca");
+ if (ca != null) {
+ createPKCS7(impl);
+ }
+ cs.putString("preop.admincert.serialno.0", impl.getSerialNumber().toString(16));
+ }
+
+ public static void createPKCS7(X509CertImpl cert) throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca");
+ CertificateChain cachain = ca.getCACertChain();
+ java.security.cert.X509Certificate[] cacerts = cachain.getChain();
+ X509CertImpl[] userChain = new X509CertImpl[cacerts.length + 1];
+ int m = 1, n = 0;
+
+ for (; n < cacerts.length; m++, n++) {
+ userChain[m] = (X509CertImpl) cacerts[n];
+ }
+
+ userChain[0] = cert;
+ PKCS7 p7 = new PKCS7(new AlgorithmId[0],
+ new ContentInfo(new byte[0]), userChain, new SignerInfo[0]);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ p7.encodeSignedData(bos);
+ byte[] p7Bytes = bos.toByteArray();
+ String p7Str = CMS.BtoA(p7Bytes);
+ cs.putString("preop.admincert.pkcs7", CryptoUtil.normalizeCertStr(p7Str));
+ }
+
+ public static void createAdmin(String uid, String email, String name, String pwd) throws IOException,
+ EBaseException {
+ IUGSubsystem system = (IUGSubsystem) (CMS.getSubsystem(IUGSubsystem.ID));
+ IConfigStore config = CMS.getConfigStore();
+ String groupNames = config.getString("preop.admin.group", "Certificate Manager Agents,Administrators");
+
+ IUser user = null;
+
+ try {
+ user = system.createUser(uid);
+ user.setEmail(email);
+ user.setPassword(pwd);
+ user.setFullName(name);
+ user.setUserType("adminType");
+ user.setState("1");
+ user.setPhone("");
+ system.addUser(user);
+ } catch (LDAPException e) {
+ CMS.debug("AdminPanel createAdmin: addUser " + e.toString());
+ if (e.getLDAPResultCode() != LDAPException.ENTRY_ALREADY_EXISTS) {
+ throw new IOException(e.toString());
+ }
+ } catch (Exception e) {
+ CMS.debug("AdminPanel createAdmin: addUser " + e.toString());
+ throw new IOException(e.toString());
+ }
+
+ IGroup group = null;
+ for (String groupName : groupNames.split(",")) {
+ groupName = groupName.trim();
+ group = system.getGroupFromName(groupName);
+ if (!group.isMember(uid)) {
+ group.addMemberName(uid);
+ system.modifyGroup(group);
+ }
+ }
+
+ String select = config.getString("securitydomain.select", "");
+ if (select.equals("new")) {
+ group = system.getGroupFromName("Security Domain Administrators");
+ if (group != null && !group.isMember(uid)) {
+ CMS.debug("AdminPanel createAdmin: add user '" + uid + "' to group 'Security Domain Administrators'");
+ group.addMemberName(uid);
+ system.modifyGroup(group);
+ }
+
+ group = system.getGroupFromName("Enterprise CA Administrators");
+ if (group != null && !group.isMember(uid)) {
+ CMS.debug("AdminPanel createAdmin: add user '" + uid + "' to group 'Enterprise CA Administrators'");
+ group.addMemberName(uid);
+ system.modifyGroup(group);
+ }
+
+ group = system.getGroupFromName("Enterprise KRA Administrators");
+ if (group != null && !group.isMember(uid)) {
+ CMS.debug("AdminPanel createAdmin: add user '" + uid + "' to group 'Enterprise KRA Administrators'");
+ group.addMemberName(uid);
+ system.modifyGroup(group);
+ }
+
+ group = system.getGroupFromName("Enterprise RA Administrators");
+ if (group != null && !group.isMember(uid)) {
+ CMS.debug("AdminPanel createAdmin: add user '" + uid + "' to group 'Enterprise RA Administrators'");
+ group.addMemberName(uid);
+ system.modifyGroup(group);
+ }
+
+ group = system.getGroupFromName("Enterprise TKS Administrators");
+ if (group != null && !group.isMember(uid)) {
+ CMS.debug("AdminPanel createAdmin: add user '" + uid + "' to group 'Enterprise TKS Administrators'");
+ group.addMemberName(uid);
+ system.modifyGroup(group);
+ }
+
+ group = system.getGroupFromName("Enterprise OCSP Administrators");
+ if (group != null && !group.isMember(uid)) {
+ CMS.debug("AdminPanel createAdmin: add user '" + uid + "' to group 'Enterprise OCSP Administrators'");
+ group.addMemberName(uid);
+ system.modifyGroup(group);
+ }
+
+ group = system.getGroupFromName("Enterprise TPS Administrators");
+ if (group != null && !group.isMember(uid)) {
+ CMS.debug("AdminPanel createAdmin: add user '" + uid + "' to group 'Enterprise TPS Administrators'");
+ group.addMemberName(uid);
+ system.modifyGroup(group);
+ }
+ }
+ }
+
+ public static String submitAdminCertRequest(String ca_hostname, int ca_port, String profileId,
+ String certRequestType, String certRequest, String subjectDN) throws IOException, EBaseException,
+ SAXException, ParserConfigurationException {
+ IConfigStore config = CMS.getConfigStore();
+
+ if (profileId == null) {
+ profileId = config.getString("preop.admincert.profile", "caAdminCert");
+ }
+ certRequest = URLEncoder.encode(certRequest, "UTF-8");
+ String session_id = CMS.getConfigSDSessionId();
+ String content = "profileId=" + profileId + "&cert_request_type=" + certRequestType +
+ "&cert_request=" + certRequest + "&xmlOutput=true&sessionID=" + session_id + "&subject=" + subjectDN;
+
+ String c = getHttpResponse(ca_hostname, ca_port, true, "/ca/ee/ca/profileSubmit", content, null, null);
+
+ // retrieve the request Id and admin certificate
+ if (c != null) {
+ ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes());
+ XMLObject parser = new XMLObject(bis);
+
+ String status = parser.getValue("Status");
+ CMS.debug("submitAdminXertRequest: status=" + status);
+ if (status.equals(AUTH_FAILURE)) {
+ throw new EAuthException(AUTH_FAILURE);
+ } else if (!status.equals(SUCCESS)) {
+ String error = parser.getValue("Error");
+ throw new IOException(error);
+ }
+
+ IConfigStore cs = CMS.getConfigStore();
+ String id = parser.getValue("Id");
+
+ cs.putString("preop.admincert.requestId.0", id);
+ String serial = parser.getValue("serialno");
+
+ cs.putString("preop.admincert.serialno.0", serial);
+ String b64 = parser.getValue("b64");
+
+ // save in a file for access by ImportAdminCertPanel
+ String instanceRoot = cs.getString("instanceRoot", "");
+ String dir = instanceRoot + File.separator + "conf" + File.separator + "admin.b64";
+ cs.putString("preop.admincert.b64", dir);
+
+ PrintStream ps = new PrintStream(new FileOutputStream(dir));
+ ps.println(b64);
+ ps.flush();
+ ps.close();
+
+ return b64;
+ } else {
+ throw new IOException("submitAdminCertRequest: Failed to get response from ca");
+ }
+ }
+
+ public static void createSecurityDomain() throws EBaseException, LDAPException, NumberFormatException, IOException,
+ SAXException, ParserConfigurationException {
+ IConfigStore cs = CMS.getConfigStore();
+ IConfigStore dbCfg = cs.getSubStore("internaldb");
+ ILdapConnFactory dbFactory = CMS.getLdapBoundConnFactory();
+ dbFactory.init(dbCfg);
+ LDAPConnection conn = dbFactory.getConn();
+ LDAPEntry entry = null;
+ LDAPAttributeSet attrs = null;
+
+ // Create security domain ldap entry
+ String basedn = cs.getString("internaldb.basedn");
+ String secdomain = cs.getString("securitydomain.name");
+
+ String dn = "ou=Security Domain," + basedn;
+ attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass", "top"));
+ attrs.add(new LDAPAttribute("objectclass", "pkiSecurityDomain"));
+ attrs.add(new LDAPAttribute("name", secdomain));
+ attrs.add(new LDAPAttribute("ou", "Security Domain"));
+ entry = new LDAPEntry(dn, attrs);
+ conn.add(entry);
+
+ // create list containers
+ String clist[] = { "CAList", "OCSPList", "KRAList", "RAList", "TKSList", "TPSList" };
+ for (int i = 0; i < clist.length; i++) {
+ dn = "cn=" + LDAPUtil.escapeRDNValue(clist[i]) + ",ou=Security Domain," + basedn;
+ attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass", "top"));
+ attrs.add(new LDAPAttribute("objectclass", "pkiSecurityGroup"));
+ attrs.add(new LDAPAttribute("cn", clist[i]));
+ entry = new LDAPEntry(dn, attrs);
+ conn.add(entry);
+ }
+
+ // Add this host
+ String cn = CMS.getEESSLHost() + ":" + CMS.getAdminPort();
+ dn = "cn=" + LDAPUtil.escapeRDNValue(cn) + ",cn=CAList,ou=Security Domain," + basedn;
+ String subsystemName = cs.getString("preop.subsystem.name");
+ attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass", "top"));
+ attrs.add(new LDAPAttribute("objectclass", "pkiSubsystem"));
+ attrs.add(new LDAPAttribute("Host", CMS.getEESSLHost()));
+ attrs.add(new LDAPAttribute("SecurePort", CMS.getEESSLPort()));
+ attrs.add(new LDAPAttribute("SecureAgentPort", CMS.getAgentPort()));
+ attrs.add(new LDAPAttribute("SecureAdminPort", CMS.getAdminPort()));
+ if (CMS.getEEClientAuthSSLPort() != null) {
+ attrs.add(new LDAPAttribute("SecureEEClientAuthPort", CMS.getEEClientAuthSSLPort()));
+ }
+ attrs.add(new LDAPAttribute("UnSecurePort", CMS.getEENonSSLPort()));
+ attrs.add(new LDAPAttribute("Clone", "FALSE"));
+ attrs.add(new LDAPAttribute("SubsystemName", subsystemName));
+ attrs.add(new LDAPAttribute("cn", cn));
+ attrs.add(new LDAPAttribute("DomainManager", "TRUE"));
+ entry = new LDAPEntry(dn, attrs);
+ conn.add(entry);
+
+ CMS.debug("createSecurityDomain(): finish updating domain info");
+ conn.disconnect();
+
+ // Fetch the "new" security domain and display it
+ // CMS.debug("createSecurityDomain(): Dump contents of new Security Domain . . .");
+ // @SuppressWarnings("unused")
+ // String c = getDomainXML(CMS.getEESSLHost(), Integer.parseInt(CMS.getAdminPort()), true);
+ }
+
+ public static void updateSecurityDomain() throws IOException, SAXException, ParserConfigurationException,
+ EPropertyNotFound, EBaseException {
+ IConfigStore cs = CMS.getConfigStore();
+
+ int sd_agent_port = cs.getInteger("securitydomain.httpsagentport");
+ int sd_admin_port = cs.getInteger("securitydomain.httpsadminport");
+ String select = cs.getString("preop.subsystem.select");
+ String type = cs.getString("cs.type");
+ String sd_host = cs.getString("securitydomain.host");
+ String subsystemName = cs.getString("preop.subsystem.name");
+
+ boolean cloneMaster = false;
+
+ if (select.equals("clone") && type.equalsIgnoreCase("CA") && isSDHostDomainMaster(cs)) {
+ cloneMaster = true;
+ CMS.debug("Cloning a domain master");
+ }
+
+ String cloneStr = select.equals("clone") ? "&clone=true" : "&clone=false";
+ String domainMasterStr = cloneMaster ? "&dm=true" : "&dm=false";
+ String eecaStr = (CMS.getEEClientAuthSSLPort() != null) ? "&eeclientauthsport=" + CMS.getEEClientAuthSSLPort()
+ : "";
+
+ String url = "/ca/admin/ca/updateDomainXML";
+ String content = "list=" + type + "List"
+ + "&type=" + type
+ + "&host=" + CMS.getEESSLHost()
+ + "&name=" + subsystemName
+ + "&sport=" + CMS.getEESSLPort()
+ + domainMasterStr
+ + cloneStr
+ + "&agentsport=" + CMS.getAgentPort()
+ + "&adminsport=" + CMS.getAdminPort()
+ + eecaStr
+ + "&httpport=" + CMS.getEENonSSLPort();
+
+ try {
+ String session_id = CMS.getConfigSDSessionId();
+ content += "&sessionID="+ session_id;
+ updateDomainXML(sd_host, sd_admin_port, true, url, content, false);
+ } catch (Exception e) {
+ CMS.debug("updateSecurityDomain: failed to update security domain using admin port "
+ + sd_admin_port + ": " + e);
+ CMS.debug("updateSecurityDomain: now trying agent port with client auth");
+ url = "/ca/agent/ca/updateDomainXML";
+ updateDomainXML(sd_host, sd_agent_port, true, url, content, true);
+ }
+
+ // Fetch the "updated" security domain and display it
+ CMS.debug("updateSecurityDomain(): Dump contents of updated Security Domain . . .");
+ @SuppressWarnings("unused")
+ String c = getDomainXML(sd_host, sd_admin_port, true);
+ }
+
+ public static boolean isSDHostDomainMaster(IConfigStore config) throws EPropertyNotFound, EBaseException,
+ IOException, SAXException, ParserConfigurationException {
+ String dm = "false";
+
+ String hostname = config.getString("securitydomain.host");
+ int httpsadminport = config.getInteger("securitydomain.httpsadminport");
+
+ CMS.debug("isSDHostDomainMaster(): Getting domain.xml from CA...");
+ String c = getDomainXML(hostname, httpsadminport, true);
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes());
+ XMLObject parser = new XMLObject(bis);
+ Document doc = parser.getDocument();
+ NodeList nodeList = doc.getElementsByTagName("CA");
+
+ int len = nodeList.getLength();
+ for (int i = 0; i < len; i++) {
+ Vector<String> v_hostname = parser.getValuesFromContainer(nodeList.item(i), "Host");
+ Vector<String> v_https_admin_port = parser.getValuesFromContainer(nodeList.item(i), "SecureAdminPort");
+ Vector<String> v_domain_mgr = parser.getValuesFromContainer(nodeList.item(i), "DomainManager");
+
+ if (v_hostname.elementAt(0).equals(hostname) &&
+ v_https_admin_port.elementAt(0).equals(Integer.toString(httpsadminport))) {
+ dm = v_domain_mgr.elementAt(0).toString();
+ break;
+ }
+ }
+ return dm.equalsIgnoreCase("true");
+ }
+
+ public static void updateDomainXML(String hostname, int port, boolean https,
+ String servlet, String uri, boolean useClientAuth) throws IOException, EBaseException, SAXException,
+ ParserConfigurationException {
+ CMS.debug("WizardPanelBase updateDomainXML start hostname=" + hostname + " port=" + port);
+ String c = null;
+ if (useClientAuth) {
+ IConfigStore cs = CMS.getConfigStore();
+ String nickname = cs.getString("preop.cert.subsystem.nickname", "");
+ String tokenname = cs.getString("preop.module.token", "");
+
+ if (!tokenname.equals("") &&
+ !tokenname.equals("Internal Key Storage Token") &&
+ !tokenname.equals("internal")) {
+ nickname = tokenname + ":" + nickname;
+ }
+ CMS.debug("updateDomainXML() nickname=" + nickname);
+
+ c = getHttpResponse(hostname, port, https, servlet, uri, nickname, null);
+ } else {
+ c = getHttpResponse(hostname, port, https, servlet, uri, null, null);
+ }
+ if (c != null && !c.equals("")) {
+ ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes());
+ XMLObject obj = new XMLObject(bis);
+ String status = obj.getValue("Status");
+ CMS.debug("WizardPanelBase updateDomainXML: status=" + status);
+
+ if (status.equals(SUCCESS)) {
+ return;
+ } else {
+ String error = obj.getValue("Error");
+ throw new IOException(error);
+ }
+ } else {
+ throw new IOException("Failed to get response when updating security domain");
+ }
+ }
+
+ public static void updateConnectorInfo(String ownagenthost, String ownagentsport)
+ throws IOException, EBaseException, SAXException, ParserConfigurationException {
+ IConfigStore cs = CMS.getConfigStore();
+ int port = -1;
+ String url = "";
+ String host = null;
+ String transportCert = "";
+
+ url = cs.getString("preop.ca.url", "");
+ if (!url.equals("")) {
+ host = cs.getString("preop.ca.hostname", "");
+ port = cs.getInteger("preop.ca.httpsadminport", -1);
+ transportCert = cs.getString("kra.transport.cert", "");
+ }
+
+ if (host == null) {
+ CMS.debug("updateConnectorInfo(): preop.ca.url is not defined. External CA selected. No transport certificate setup is required");
+ } else {
+ CMS.debug("updateConnectorInfo(): Transport certificate is being setup in " + url);
+ String session_id = CMS.getConfigSDSessionId();
+ String content = "ca.connector.KRA.enable=true&ca.connector.KRA.local=false&ca.connector.KRA.timeout=30"
+ + "&ca.connector.KRA.uri=/kra/agent/kra/connector&ca.connector.KRA.host=" + ownagenthost
+ + "&ca.connector.KRA.port=" + ownagentsport
+ + "&ca.connector.KRA.transportCert=" + URLEncoder.encode(transportCert, "UTF-8")
+ + "&sessionID=" + session_id;
+
+ updateConnectorInfo(host, port, true, content);
+ }
+ }
+
+ public static void updateConnectorInfo(String host, int port, boolean https,
+ String content) throws IOException, SAXException, ParserConfigurationException {
+ CMS.debug("updateConnectorInfo start");
+ String c = getHttpResponse(host, port, https, "/ca/admin/ca/updateConnector", content, null, null);
+ if (c != null) {
+ ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes());
+ XMLObject parser = null;
+ parser = new XMLObject(bis);
+ String status = parser.getValue("Status");
+ CMS.debug("updateConnectorInfo: status=" + status);
+ if (!status.equals(SUCCESS)) {
+ String error = parser.getValue("Error");
+ throw new IOException(error);
+ }
+ }
+ }
+
+ public static void setupClientAuthUser() throws EBaseException, CertificateException, IOException, SAXException,
+ ParserConfigurationException, LDAPException {
+ IConfigStore cs = CMS.getConfigStore();
+ String host = cs.getString("preop.ca.hostname", "");
+ int port = cs.getInteger("preop.ca.httpsadminport", -1);
+
+ // retrieve CA subsystem certificate from the CA
+ IUGSubsystem system =
+ (IUGSubsystem) (CMS.getSubsystem(IUGSubsystem.ID));
+ String id = "";
+
+ String b64 = getSubsystemCert(host, port, true);
+ if (b64 != null) {
+ int num = cs.getInteger("preop.subsystem.count", 0);
+ id = "CA-" + host + "-" + port;
+ num++;
+ cs.putInteger("preop.subsystem.count", num);
+ cs.putInteger("subsystem.count", num);
+ IUser user = system.createUser(id);
+ user.setFullName(id);
+ user.setEmail("");
+ user.setPassword("");
+ user.setUserType("agentType");
+ user.setState("1");
+ user.setPhone("");
+ X509CertImpl[] certs = new X509CertImpl[1];
+ certs[0] = new X509CertImpl(CMS.AtoB(b64));
+ user.setX509Certificates(certs);
+ try {
+ system.addUser(user);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() != LDAPException.ENTRY_ALREADY_EXISTS) {
+ throw e;
+ }
+ }
+ CMS.debug("DonePanel display: successfully add the user");
+ system.addUserCert(user);
+ CMS.debug("DonePanel display: successfully add the user certificate");
+ cs.commit(false);
+ }
+
+ String groupName = "Trusted Managers";
+ IGroup group = system.getGroupFromName(groupName);
+ if (!group.isMember(id)) {
+ group.addMemberName(id);
+ system.modifyGroup(group);
+ CMS.debug("DonePanel display: successfully added the user to the group.");
+ }
+
+ }
+
+ public static String getSubsystemCert(String host, int port, boolean https)
+ throws IOException, SAXException, ParserConfigurationException {
+ CMS.debug("getSubsystemCert() start");
+ String c = getHttpResponse(host, port, https, "/ca/admin/ca/getSubsystemCert", null, null, null);
+ if (c != null) {
+ ByteArrayInputStream bis =
+ new ByteArrayInputStream(c.getBytes());
+ XMLObject parser = new XMLObject(bis);
+ String status = parser.getValue("Status");
+ if (status.equals(SUCCESS)) {
+ String s = parser.getValue("Cert");
+ return s;
+ } else {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public static String getTransportCert(URI secdomainURI, URI kraUri)
+ throws IOException, SAXException, ParserConfigurationException {
+ CMS.debug("getTransportCert() start");
+ String sessionId = CMS.getConfigSDSessionId();
+
+ String content = "&xmlOutput=true" +
+ "&sessionID=" + sessionId +
+ "&auth_hostname=" + secdomainURI.getHost() +
+ "&auth_port=" + secdomainURI.getPort();
+
+ String c = getHttpResponse(
+ kraUri.getHost(),
+ kraUri.getPort(),
+ true,
+ "/kra/admin/kra/getTransportCert",
+ content, null, null);
+
+ if (c != null) {
+ ByteArrayInputStream bis =
+ new ByteArrayInputStream(c.getBytes());
+ XMLObject parser = new XMLObject(bis);
+ String status = parser.getValue("Status");
+ if (status.equals(SUCCESS)) {
+ String s = parser.getValue("TransportCert");
+ return s;
+ } else {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public static void getSharedSecret(String tksHost, int tksPort, boolean importKey) throws EPropertyNotFound,
+ EBaseException, URISyntaxException {
+ IConfigStore cs = CMS.getConfigStore();
+ String host = cs.getString("service.machineName");
+ String port = cs.getString("service.securePort");
+ String dbDir = cs.getString("instanceRoot") + "/alias";
+ String dbNick = cs.getString("tps.cert.subsystem.nickname");
+
+ String passwordFile = cs.getString("passwordFile");
+ IConfigStore psStore = CMS.createFileConfigStore(passwordFile);
+ String dbPass = psStore.getString("internal");
+
+ ClientConfig config = new ClientConfig();
+ config.setServerURI("https://" + tksHost + ":" + tksPort);
+ config.setCertDatabase(dbDir);
+ config.setCertNickname(dbNick);
+ config.setCertPassword(dbPass);
+
+ PKIClient client = new PKIClient(config);
+ PKIConnection connection = client.getConnection();
+
+ // Ignore the "UNTRUSTED_ISSUER" and "CA_CERT_INVALID" validity status
+ // during PKI instance creation since we are using an untrusted temporary CA cert.
+ connection.addIgnoredCertStatus(SSLCertificateApprovalCallback.ValidityStatus.UNTRUSTED_ISSUER);
+ connection.addIgnoredCertStatus(SSLCertificateApprovalCallback.ValidityStatus.CA_CERT_INVALID);
+
+ AccountClient accountClient = new AccountClient(client, "tks");
+ TPSConnectorClient tpsConnectorClient = new TPSConnectorClient(client, "tks");
+
+ accountClient.login();
+ TPSConnectorData data = null;
+ try {
+ data = tpsConnectorClient.getConnector(host, port);
+ } catch (ResourceNotFoundException e) {
+ // no connector exists
+ data = null;
+ }
+ KeyData keyData = null;
+ if (data == null) {
+ data = tpsConnectorClient.createConnector(host, port);
+ keyData = tpsConnectorClient.createSharedSecret(data.getID());
+ } else {
+ String connId = data.getID();
+ keyData = tpsConnectorClient.getSharedSecret(connId);
+ if (keyData != null) {
+ keyData = tpsConnectorClient.replaceSharedSecret(connId);
+ } else {
+ keyData = tpsConnectorClient.createSharedSecret(connId);
+ }
+ }
+ accountClient.logout();
+
+ if (importKey) {
+ // TODO - we need code here to import the key into the tps certdb
+ // this is not needed if we are using a shared database with
+ // the tks.
+ }
+
+ // store the new nick in CS.cfg
+ String nick = "TPS-" + host + "-" + port + " sharedSecret";
+ cs.putString("conn.tks1.tksSharedSymKeyName", nick);
+ cs.commit(false);
+ }
+
+ public static void importCACertToOCSP() throws IOException, EBaseException, CertificateEncodingException {
+ IConfigStore config = CMS.getConfigStore();
+
+ // get certificate chain from CA
+ String b64 = config.getString("preop.ca.pkcs7", "");
+ if (b64.equals("")) {
+ throw new IOException("Failed to get certificate chain.");
+ }
+
+ // this could be a chain
+ java.security.cert.X509Certificate[] certs = com.netscape.cmsutil.util.Cert.mapCertFromPKCS7(b64);
+ java.security.cert.X509Certificate leafCert = null;
+ if (certs != null && certs.length > 0) {
+ if (certs[0].getSubjectDN().getName().equals(certs[0].getIssuerDN().getName())) {
+ leafCert = certs[certs.length - 1];
+ } else {
+ leafCert = certs[0];
+ }
+
+ IOCSPAuthority ocsp = (IOCSPAuthority) CMS.getSubsystem(IOCSPAuthority.ID);
+ IDefStore defStore = ocsp.getDefaultStore();
+
+ // (1) need to normalize (sort) the chain
+ // (2) store certificate (and certificate chain) into
+ // database
+ ICRLIssuingPointRecord rec = defStore.createCRLIssuingPointRecord(
+ leafCert.getSubjectDN().getName(),
+ BIG_ZERO,
+ MINUS_ONE, null, null);
+
+ rec.set(ICRLIssuingPointRecord.ATTR_CA_CERT, leafCert.getEncoded());
+ defStore.addCRLIssuingPoint(leafCert.getSubjectDN().getName(), rec);
+
+ CMS.debug("importCACertToOCSP(): Added CA certificate.");
+ }
+ }
+
+ public static void updateOCSPConfig()
+ throws IOException, EBaseException, SAXException, ParserConfigurationException {
+ IConfigStore config = CMS.getConfigStore();
+ String cahost = config.getString("preop.ca.hostname", "");
+ int caport = config.getInteger("preop.ca.httpsport", -1);
+ String ocsphost = CMS.getAgentHost();
+ int ocspport = Integer.parseInt(CMS.getAgentPort());
+ String session_id = CMS.getConfigSDSessionId();
+ String content = "xmlOutput=true&sessionID=" + session_id + "&ocsp_host=" + ocsphost + "&ocsp_port=" + ocspport;
+
+ String c = getHttpResponse(cahost, caport, true, "/ca/ee/ca/updateOCSPConfig", content, null, null);
+ if (c == null || c.equals("")) {
+ CMS.debug("WizardPanelBase updateOCSPConfig: content is null.");
+ throw new IOException("The server you want to contact is not available");
+ } else {
+ ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes());
+ XMLObject parser = new XMLObject(bis);
+
+ String status = parser.getValue("Status");
+ CMS.debug("WizardPanelBase updateOCSPConfig: status=" + status);
+
+ if (status.equals(SUCCESS)) {
+ CMS.debug("WizardPanelBase updateOCSPConfig: Successfully update the OCSP configuration in the CA.");
+ } else if (status.equals(AUTH_FAILURE)) {
+ throw new EAuthException(AUTH_FAILURE);
+ } else {
+ String error = parser.getValue("Error");
+ throw new IOException(error);
+ }
+ }
+ }
+
+ public static void setupDBUser() throws CertificateException, LDAPException, EBaseException,
+ NotInitializedException, ObjectNotFoundException, TokenException, IOException {
+ IUGSubsystem system =
+ (IUGSubsystem) (CMS.getSubsystem(IUGSubsystem.ID));
+
+ try {
+ @SuppressWarnings("unused")
+ Enumeration<IUser> dbusers = system.findUsers(DBUSER);
+ CMS.debug("DB User already exists: " + DBUSER);
+ return;
+ } catch (EUsrGrpException e) {
+ CMS.debug("Creating DB User: " + DBUSER);
+ }
+
+ String b64 = getSubsystemCert();
+ if (b64 == null) {
+ CMS.debug("setupDBUser(): failed to fetch subsystem cert");
+ throw new EBaseException("setupDBUser(): failed to fetch subsystem cert");
+ }
+
+ IUser user = system.createUser(DBUSER);
+ user.setFullName(DBUSER);
+ user.setEmail("");
+ user.setPassword("");
+ user.setUserType("agentType");
+ user.setState("1");
+ user.setPhone("");
+ X509CertImpl[] certs = new X509CertImpl[1];
+ certs[0] = new X509CertImpl(CMS.AtoB(b64));
+ user.setX509Certificates(certs);
+ system.addUser(user);
+ CMS.debug("setupDBUser(): successfully added the user");
+ system.addUserCert(user);
+ CMS.debug("setupDBUser(): successfully add the user certificate");
+
+ // set subject dn
+ system.addCertSubjectDN(user);
+
+ // remove old db users
+ CMS.debug("Removing seeAlso from old dbusers");
+ removeOldDBUsers(certs[0].getSubjectDN().toString());
+ }
+
+ public static void addProfilesToTPSUser(String adminID) throws EUsrGrpException {
+ CMS.debug("Adding all profiles to TPS admin user");
+ IUGSubsystem system = (IUGSubsystem) CMS.getSubsystem(IUGSubsystem.ID);
+ IUser user = system.getUser(adminID);
+
+ List<String> profiles = new ArrayList<String>();
+ profiles.add(UserService.ALL_PROFILES);
+
+ user.setTpsProfiles(profiles);
+ system.modifyUser(user);
+ }
+
+ public static void registerUser(URI secdomainURI, URI targetURI, String targetType) throws Exception {
+ IConfigStore cs = CMS.getConfigStore();
+ String csType = cs.getString("cs.type");
+ String uid = csType.toUpperCase() + "-" + cs.getString("machineName", "")
+ + "-" + cs.getString("service.securePort", "");
+ String sessionId = CMS.getConfigSDSessionId();
+ String subsystemName = cs.getString("preop.subsystem.name");
+
+ String content = "uid=" + uid +
+ "&xmlOutput=true" +
+ "&sessionID=" + sessionId +
+ "&auth_hostname=" + secdomainURI.getHost() +
+ "&auth_port=" + secdomainURI.getPort() +
+ "&certificate=" + URLEncoder.encode(getSubsystemCert(), "UTF-8") +
+ "&name=" + subsystemName;
+
+ String targetURL = "/" + targetType + "/admin/" + targetType + "/registerUser";
+
+ String response = getHttpResponse(
+ targetURI.getHost(),
+ targetURI.getPort(),
+ true,
+ targetURL,
+ content, null, null);
+
+ if (response == null || response.equals("")) {
+ CMS.debug("registerUser: response is empty or null.");
+ throw new IOException("The server " + targetURI + "is not available");
+ } else {
+ ByteArrayInputStream bis = new ByteArrayInputStream(response.getBytes());
+ XMLObject parser = new XMLObject(bis);
+
+ String status = parser.getValue("Status");
+ CMS.debug("registerUser: status=" + status);
+
+ if (status.equals(SUCCESS)) {
+ CMS.debug("registerUser: Successfully added user " + uid + " to " + targetURI +
+ " using " + targetURL);
+ } else if (status.equals(AUTH_FAILURE)) {
+ throw new EAuthException(AUTH_FAILURE);
+ } else {
+ String error = parser.getValue("Error");
+ throw new IOException(error);
+ }
+ }
+ }
+
+ public static void exportTransportCert(URI secdomainURI, URI targetURI, String transportCert) throws Exception {
+ IConfigStore cs = CMS.getConfigStore();
+ String name = "transportCert-" + cs.getString("machineName", "")
+ + "-" + cs.getString("service.securePort", "");
+ String sessionId = CMS.getConfigSDSessionId();
+
+ String content = "name=" + name +
+ "&xmlOutput=true" +
+ "&sessionID=" + sessionId +
+ "&auth_hostname=" + secdomainURI.getHost() +
+ "&auth_port=" + secdomainURI.getPort() +
+ "&certificate=" + URLEncoder.encode(transportCert, "UTF-8");
+
+ String targetURL = "/tks/admin/tks/importTransportCert";
+
+ String response = getHttpResponse(
+ targetURI.getHost(),
+ targetURI.getPort(),
+ true,
+ targetURL,
+ content, null, null);
+
+ if (response == null || response.equals("")) {
+ CMS.debug("exportTransportCert: response is empty or null.");
+ throw new IOException("The server " + targetURI + "is not available");
+ } else {
+ ByteArrayInputStream bis = new ByteArrayInputStream(response.getBytes());
+ XMLObject parser = new XMLObject(bis);
+
+ String status = parser.getValue("Status");
+ CMS.debug("exportTransportCert: status=" + status);
+
+ if (status.equals(SUCCESS)) {
+ CMS.debug("exportTransportCert: Successfully added transport cert to " + targetURI);
+ } else if (status.equals(AUTH_FAILURE)) {
+ throw new EAuthException(AUTH_FAILURE);
+ } else {
+ String error = parser.getValue("Error");
+ throw new IOException(error);
+ }
+ }
+ }
+
+ public static void removeOldDBUsers(String subjectDN) throws EBaseException, LDAPException {
+ IUGSubsystem system = (IUGSubsystem) (CMS.getSubsystem(IUGSubsystem.ID));
+ IConfigStore cs = CMS.getConfigStore();
+ String userbasedn = "ou=people, " + cs.getString("internaldb.basedn");
+ IConfigStore dbCfg = cs.getSubStore("internaldb");
+ ILdapConnFactory dbFactory = CMS.getLdapBoundConnFactory();
+ dbFactory.init(dbCfg);
+ LDAPConnection conn = dbFactory.getConn();
+
+ String filter = "(&(seeAlso=" + LDAPUtil.escapeFilter(subjectDN) + ")(!(uid=" + DBUSER + ")))";
+ String[] attrs = null;
+ LDAPSearchResults res = conn.search(userbasedn, LDAPConnection.SCOPE_SUB, filter,
+ attrs, false);
+ if (res != null) {
+ while (res.hasMoreElements()) {
+ String uid = (String) res.next().getAttribute("uid").getStringValues().nextElement();
+ IUser user = system.getUser(uid);
+ CMS.debug("removeOldDUsers: Removing seeAlso from " + uid);
+ system.removeCertSubjectDN(user);
+ }
+ }
+ }
+
+ public static String getSubsystemCert() throws EBaseException, NotInitializedException, ObjectNotFoundException,
+ TokenException, CertificateEncodingException, IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ String nickname = cs.getString("preop.cert.subsystem.nickname", "");
+ String tokenname = cs.getString("preop.module.token", "");
+
+ if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token")
+ && !tokenname.equals("")) {
+ nickname = tokenname + ":" + nickname;
+ }
+
+ CMS.debug("DonePanel getSubsystemCert: nickname=" + nickname);
+
+ CryptoManager cm = CryptoManager.getInstance();
+ org.mozilla.jss.crypto.X509Certificate cert = cm.findCertByNickname(nickname);
+ if (cert == null) {
+ CMS.debug("DonePanel getSubsystemCert: subsystem cert is null");
+ return null;
+ }
+ byte[] bytes = cert.getEncoded();
+ String s = CryptoUtil.normalizeCertStr(CryptoUtil.base64Encode(bytes));
+ return s;
+ }
+
+ public static void updateCAConnInfo(URI caUri, String subsystemNick) {
+ IConfigStore cs = CMS.getConfigStore();
+
+ cs.putString("preop.cainfo.select", caUri.toString());
+ cs.putString("conn.ca1.clientNickname", subsystemNick);
+ cs.putString("conn.ca1.hostport", caUri.getHost() + ":" + caUri.getPort());
+ cs.putString("conn.ca1.hostagentport", caUri.getHost() + ":" + caUri.getPort());
+ cs.putString("conn.ca1.hostadminport", caUri.getHost() + ":" + caUri.getPort());
+ }
+
+ public static void updateKRAConnInfo(boolean enableServerSideKeyGen, URI kraUri, String subsystemNick) {
+ IConfigStore cs = CMS.getConfigStore();
+ if (enableServerSideKeyGen) {
+ cs.putString("preop.krainfo.select", kraUri.toString());
+ cs.putString("conn.drm1.clientNickname", subsystemNick);
+ cs.putString("conn.drm1.hostport", kraUri.getHost() + ":" + kraUri.getPort());
+ cs.putString("conn.tks1.serverKeygen", "true");
+ 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");
+ } else {
+ // no keygen
+ cs.putString("conn.tks1.serverKeygen", "false");
+ 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("conn.drm1.clientNickname", "");
+ cs.putString("conn.drm1.hostport", "");
+ 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");
+ }
+ }
+
+ public static void updateTKSConnInfo(URI tksUri, String subsystemNick) {
+ IConfigStore cs = CMS.getConfigStore();
+
+ cs.putString("preop.tksinfo.select", tksUri.toString());
+ cs.putString("conn.tks1.clientNickname", subsystemNick);
+ cs.putString("conn.tks1.hostport", tksUri.getHost() + ":" + tksUri.getPort());
+ }
+
+ public static void updateAuthdbInfo(String basedn, String host, String port, String secureConn) {
+ IConfigStore cs = CMS.getConfigStore();
+
+ cs.putString("auths.instance.ldap1.ldap.basedn", basedn);
+ cs.putString("auths.instance.ldap1.ldap.ldapconn.host", host);
+ cs.putString("auths.instance.ldap1.ldap.ldapconn.port", port);
+ cs.putString("auths.instance.ldap1.ldap.ldapconn.secureConn", secureConn);
+ }
+
+
+ public static void updateNextRanges() throws EBaseException, LDAPException {
+ IConfigStore cs = CMS.getConfigStore();
+
+ String endRequestNumStr = cs.getString("dbs.endRequestNumber", "");
+ String endSerialNumStr = cs.getString("dbs.endSerialNumber", "");
+ String type = cs.getString("cs.type");
+ String basedn = cs.getString("internaldb.basedn");
+
+ BigInteger endRequestNum = new BigInteger(endRequestNumStr);
+ BigInteger endSerialNum = new BigInteger(endSerialNumStr);
+ BigInteger oneNum = new BigInteger("1");
+
+ // update global next range entries
+ IConfigStore dbCfg = cs.getSubStore("internaldb");
+ ILdapConnFactory dbFactory = CMS.getLdapBoundConnFactory();
+ dbFactory.init(dbCfg);
+ LDAPConnection conn = dbFactory.getConn();
+
+ String serialdn = "";
+ if (type.equals("CA")) {
+ serialdn = "ou=certificateRepository,ou=" + LDAPUtil.escapeRDNValue(type.toLowerCase()) + "," + basedn;
+ } else {
+ serialdn = "ou=keyRepository,ou=" + LDAPUtil.escapeRDNValue(type.toLowerCase()) + "," + basedn;
+ }
+ LDAPAttribute attrSerialNextRange =
+ new LDAPAttribute("nextRange", endSerialNum.add(oneNum).toString());
+ LDAPModification serialmod = new LDAPModification(LDAPModification.REPLACE, attrSerialNextRange);
+ conn.modify(serialdn, serialmod);
+
+ String requestdn = "ou=" + LDAPUtil.escapeRDNValue(type.toLowerCase()) + ",ou=requests," + basedn;
+ LDAPAttribute attrRequestNextRange =
+ new LDAPAttribute("nextRange", endRequestNum.add(oneNum).toString());
+ LDAPModification requestmod = new LDAPModification(LDAPModification.REPLACE, attrRequestNextRange);
+ conn.modify(requestdn, requestmod);
+
+ conn.disconnect();
+ }
+
+ /**
+ * save variables needed for cloning and remove preops
+ * @throws EBaseException
+ */
+ public static void removePreopConfigEntries() throws EBaseException {
+ IConfigStore cs = CMS.getConfigStore();
+ String type = cs.getString("cs.type");
+ String list = cs.getString("preop.cert.list", "");
+ StringTokenizer st = new StringTokenizer(list, ",");
+
+ while (st.hasMoreTokens()) {
+ String ss = st.nextToken();
+ if (ss.equals("sslserver"))
+ continue;
+ cs.putString("cloning." + ss + ".nickname", cs.getString("preop.cert." + ss + ".nickname", ""));
+ cs.putString("cloning." + ss + ".dn", cs.getString("preop.cert." + ss + ".dn", ""));
+ cs.putString("cloning." + ss + ".keytype", cs.getString("preop.cert." + ss + ".keytype", ""));
+ cs.putString("cloning." + ss + ".keyalgorithm", cs.getString("preop.cert." + ss + ".keyalgorithm", ""));
+ cs.putString("cloning." + ss + ".privkey.id", cs.getString("preop.cert." + ss + ".privkey.id", ""));
+ cs.putString("cloning." + ss + ".pubkey.exponent",
+ cs.getString("preop.cert." + ss + ".pubkey.exponent", ""));
+ cs.putString("cloning." + ss + ".pubkey.modulus",
+ cs.getString("preop.cert." + ss + ".pubkey.modulus", ""));
+ cs.putString("cloning." + ss + ".pubkey.encoded",
+ cs.getString("preop.cert." + ss + ".pubkey.encoded", ""));
+ }
+ cs.putString("cloning.module.token", cs.getString("preop.module.token", ""));
+ cs.putString("cloning.list", list);
+
+ // more cloning variables needed for non-ca clones
+
+ if (!type.equals("CA")) {
+ String val = cs.getString("preop.ca.hostname", "");
+ if (val.length() > 0)
+ cs.putString("cloning.ca.hostname", val);
+
+ val = cs.getString("preop.ca.httpport", "");
+ if (val.length() != 0)
+ cs.putString("cloning.ca.httpport", val);
+
+ val = cs.getString("preop.ca.httpsport", "");
+ if (val.length() != 0)
+ cs.putString("cloning.ca.httpsport", val);
+
+ val = cs.getString("preop.ca.list", "");
+ if (val.length() != 0)
+ cs.putString("cloning.ca.list", val);
+
+ val = cs.getString("preop.ca.pkcs7", "");
+ if (val.length() != 0)
+ cs.putString("cloning.ca.pkcs7", val);
+
+ val = cs.getString("preop.ca.type", "");
+ if (val.length() != 0)
+ cs.putString("cloning.ca.type", val);
+ }
+
+ // save EC type for sslserver cert (if present)
+ cs.putString("jss.ssl.sslserver.ectype", cs.getString("preop.cert.sslserver.ec.type", "ECDHE"));
+
+ cs.removeSubStore("preop");
+ cs.commit(false);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/CreateSubsystemPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CreateSubsystemPanel.java
new file mode 100644
index 000000000..462e05455
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CreateSubsystemPanel.java
@@ -0,0 +1,279 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+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.wizard.WizardServlet;
+
+public class CreateSubsystemPanel extends WizardPanelBase {
+
+ public CreateSubsystemPanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Subsystem Selection");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Subsystem Type");
+ setId(id);
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ cs.putString("preop.subsystem.select", "");
+ cs.putString("subsystem.select", "");
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String s = cs.getString("preop.subsystem.select", "");
+ if (s == null || s.equals("")) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ /* XXX */
+
+ return set;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("title", "Subsystem Type");
+ IConfigStore config = CMS.getConfigStore();
+
+ try {
+ String session_id = request.getParameter("session_id");
+ if (session_id != null) {
+ CMS.debug("CreateSubsystemPanel setting session id.");
+ CMS.setConfigSDSessionId(session_id);
+ }
+
+ if (isPanelDone()) {
+ String s = config.getString("preop.subsystem.select");
+ if (s.equals("new")) {
+ context.put("check_newsubsystem", "checked");
+ context.put("check_clonesubsystem", "");
+ } else if (s.equals("clone")) {
+ context.put("check_newsubsystem", "");
+ context.put("check_clonesubsystem", "checked");
+ }
+ context.put("subsystemName", config.getString("preop.subsystem.name"));
+ } else {
+ context.put("check_newsubsystem", "checked");
+ context.put("check_clonesubsystem", "");
+ context.put("subsystemName", config.getString("preop.system.fullname"));
+ }
+
+ String cstype = config.getString("cs.type", "");
+ context.put("cstype", cstype);
+ context.put("wizardname", config.getString("preop.wizard.name"));
+ context.put("systemname", config.getString("preop.system.name"));
+ context.put("fullsystemname", config.getString("preop.system.fullname"));
+ context.put("machineName", config.getString("machineName"));
+ context.put("http_port", CMS.getEENonSSLPort());
+ context.put("https_agent_port", CMS.getAgentPort());
+ context.put("https_ee_port", CMS.getEESSLPort());
+ context.put("https_admin_port", CMS.getAdminPort());
+
+ String domainType = config.getString("preop.securitydomain.select");
+ Vector<String> v = null;
+ if (!domainType.equals("new")) {
+ try {
+ v = ConfigurationUtils.getUrlListFromSecurityDomain(config, cstype, "SecurePort");
+ } catch (Exception e) {
+ // note: this is OK for a new master ca in a new domain
+ CMS.debug("Exception thrown when obtaining URL List from security domain:" + e);
+ e.printStackTrace();
+ }
+ }
+
+ if (v == null) {
+ v = new Vector<String>();
+ }
+
+ StringBuffer list = new StringBuffer();
+ int size = v.size();
+ for (int i = 0; i < size; i++) {
+ if (i == size - 1) {
+ list.append(v.elementAt(i));
+ } else {
+ list.append(v.elementAt(i));
+ list.append(",");
+ }
+ }
+
+ config.putString("preop.master.list", list.toString());
+ config.commit(false);
+
+ if (list.length() == 0)
+ context.put("disableClone", "true");
+
+ context.put("panel", "admin/console/config/createsubsystempanel.vm");
+ context.put("urls", v);
+ context.put("errorString", "");
+ } catch (Exception e) {
+ e.printStackTrace();
+ context.put("errorString", e.toString());
+ CMS.debug("CreateSubsystemPanel: Exception thrown: " + e);
+ }
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ IConfigStore config = CMS.getConfigStore();
+ String select = HttpInput.getID(request, "choice");
+
+ if (select == null) {
+ CMS.debug("CreateSubsystemPanel: choice not found");
+ context.put("updateStatus", "failure");
+ throw new IOException("choice not found");
+ }
+
+ try {
+ String cstype = config.getString("cs.type", "");
+ config.putString("preop.subsystem.name", HttpInput.getName(request, "subsystemName"));
+
+ if (select.equals("newsubsystem")) {
+ config.putString("preop.subsystem.select", "new");
+ config.putString("subsystem.select", "New");
+ } else if (select.equals("clonesubsystem")) {
+ config.putString("preop.subsystem.select", "clone");
+ config.putString("subsystem.select", "Clone");
+
+ String lists = config.getString("preop.cert.list", "");
+ StringTokenizer t = new StringTokenizer(lists, ",");
+ while (t.hasMoreTokens()) {
+ String tag = t.nextToken();
+ if (tag.equals("sslserver"))
+ config.putBoolean(PCERT_PREFIX + tag + ".enable", true);
+ else
+ config.putBoolean(PCERT_PREFIX + tag + ".enable", false);
+ }
+
+ // get the masterURL
+ String index = request.getParameter("urls");
+ String url = "";
+
+ int x = Integer.parseInt(index);
+ String list = config.getString("preop.master.list", "");
+ StringTokenizer tokenizer = new StringTokenizer(list, ",");
+ int counter = 0;
+
+ while (tokenizer.hasMoreTokens()) {
+ url = tokenizer.nextToken();
+ if (counter == x) break;
+ counter++;
+ }
+
+ url = url.substring(url.indexOf("http"));
+
+ URL u = new URL(url);
+ String host = u.getHost();
+ int https_ee_port = u.getPort();
+
+ String domainXML = config.getString("preop.domainXML");
+
+ // check URI and update preop.master port entries
+ boolean validUri = ConfigurationUtils.isValidCloneURI(domainXML, host, https_ee_port);
+ if (!validUri) {
+ throw new IOException("Invalid clone URI provided. Does not match the available subsystems in " +
+ "the security domain");
+ }
+ if (cstype.equals("CA")) {
+ int https_admin_port = ConfigurationUtils.getPortFromSecurityDomain(domainXML,
+ host, https_ee_port, "CA", "SecurePort", "SecureAdminPort");
+
+ ConfigurationUtils.importCertChain(host, https_admin_port, "/ca/admin/ca/getCertChain", "clone");
+ }
+ } else {
+ CMS.debug("CreateSubsystemPanel: invalid choice " + select);
+ context.put("updateStatus", "failure");
+ throw new IOException("invalid choice " + select);
+ }
+
+ config.commit(false);
+ } catch (Exception e) {
+ CMS.debug("CreateSubsystemPanel: Exception thrown : " + e);
+ context.put("errorString", e.toString());
+ context.put("updateStatus", "failure");
+ throw new IOException(e);
+ }
+
+ context.put("updateStatus", "success");
+ }
+
+ /**
+ * If validate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("title", "Subsystem Type");
+ context.put("panel", "admin/console/config/createsubsystempanel.vm");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/DRMInfoPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/DRMInfoPanel.java
new file mode 100644
index 000000000..1344104f1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/DRMInfoPanel.java
@@ -0,0 +1,150 @@
+package com.netscape.cms.servlet.csadmin;
+
+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.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");
+
+ ConfigurationUtils.updateKRAConnInfo(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/server/cms/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java
new file mode 100644
index 000000000..56234f7cd
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java
@@ -0,0 +1,532 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Random;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.property.PropertySet;
+import com.netscape.certsrv.util.HttpInput;
+import com.netscape.cms.servlet.wizard.WizardServlet;
+
+public class DatabasePanel extends WizardPanelBase {
+
+ private static final String HOST = "localhost";
+ private static final String CLONE_HOST = "Enter FQDN here";
+ private static final String PORT = "389";
+ private static final String BINDDN = "cn=Directory Manager";
+
+ private WizardServlet mServlet = null;
+
+ public DatabasePanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Internal Database");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Internal Database");
+ setId(id);
+ mServlet = servlet;
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ cs.putBoolean("preop.Database.done", false);
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ boolean s = cs.getBoolean("preop.Database.done",
+ false);
+
+ if (s != true) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+ Descriptor hostDesc = new Descriptor(IDescriptor.STRING, null, null, "Host name");
+ set.add("hostname", hostDesc);
+
+ Descriptor portDesc = new Descriptor(IDescriptor.INTEGER, null, null, "Port");
+ set.add("portStr", portDesc);
+
+ Descriptor basednDesc = new Descriptor(IDescriptor.STRING, null, null, "Base DN");
+ set.add("basedn", basednDesc);
+
+ Descriptor binddnDesc = new Descriptor(IDescriptor.STRING, null, null, "Bind DN");
+ set.add("binddn", binddnDesc);
+
+ Descriptor bindpwdDesc = new Descriptor(IDescriptor.PASSWORD, null, null, "Bind Password");
+ set.add("bindpwd", bindpwdDesc);
+
+ Descriptor databaseDesc = new Descriptor(IDescriptor.STRING, null, null, "Database");
+ set.add("database", databaseDesc);
+
+ return set;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ CMS.debug("DatabasePanel: display()");
+ context.put("title", "Internal Database");
+ context.put("firsttime", "false");
+ IConfigStore cs = CMS.getConfigStore();
+ String hostname = null;
+ String portStr = null;
+ String basedn = null;
+ String binddn = null;
+ String bindpwd = "";
+ String database = null;
+ String errorString = "";
+ String secure = "false";
+ String masterReplicationPort = "";
+ String cloneReplicationPort = "";
+ String replicationSecurity = "";
+
+ try {
+ @SuppressWarnings("unused")
+ String s = cs.getString("preop.database.removeData"); // check whether it's first time
+ } catch (Exception e) {
+ context.put("firsttime", "true");
+ }
+
+ String select = "";
+ try {
+ select = cs.getString("preop.subsystem.select", "");
+ } catch (Exception e) {
+ }
+
+ if (isPanelDone()) {
+ try {
+ hostname = cs.getString("internaldb.ldapconn.host", "");
+ portStr = cs.getString("internaldb.ldapconn.port", "");
+ basedn = cs.getString("internaldb.basedn", "");
+ binddn = cs.getString("internaldb.ldapauth.bindDN", "");
+ database = cs.getString("internaldb.database", "");
+ secure = cs.getString("internaldb.ldapconn.secureConn", "");
+ replicationSecurity = cs.getString("internaldb.ldapconn.replicationSecurity", "None");
+ masterReplicationPort = cs.getString("internaldb.ldapconn.masterReplicationPort", "");
+ cloneReplicationPort = cs.getString("internaldb.ldapconn.cloneReplicationPort", "");
+ errorString = cs.getString("preop.database.errorString", "");
+ } catch (Exception e) {
+ CMS.debug("DatabasePanel display: " + e.toString());
+ }
+ } else if (select.equals("clone")) {
+ hostname = CLONE_HOST;
+ portStr = PORT;
+ try {
+ basedn = cs.getString("internaldb.basedn", "");
+ } catch (Exception e) {
+ CMS.debug("DatabasePanel::display() - "
+ + "Exception=" + e.toString());
+ return;
+ }
+ binddn = BINDDN;
+ database = basedn.substring(basedn.lastIndexOf('=') + 1);
+ CMS.debug("Clone: database=" + database);
+ } else {
+ hostname = HOST;
+ portStr = PORT;
+ String instanceId = "";
+ String machineName = "";
+
+ try {
+ instanceId = cs.getString("instanceId", "");
+ machineName = cs.getString("machineName", "");
+ } catch (Exception e) {
+ CMS.debug("DatabasePanel display: " + e.toString());
+ }
+ String suffix = "dc=" + machineName + "-" + instanceId;
+
+ boolean multipleEnable = false;
+ try {
+ multipleEnable = cs.getBoolean(
+ "internaldb.multipleSuffix.enable", false);
+ } catch (Exception e) {
+ }
+
+ if (multipleEnable)
+ basedn = "ou=" + instanceId + "," + suffix;
+ else
+ basedn = suffix;
+ binddn = BINDDN;
+ database = machineName + "-" + instanceId;
+ }
+
+ context.put("clone", select);
+ context.put("hostname", hostname);
+ context.put("portStr", portStr);
+ context.put("basedn", basedn);
+ context.put("binddn", binddn);
+ context.put("bindpwd", bindpwd);
+ context.put("database", database);
+ context.put("secureConn", (secure.equals("true") ? "on" : "off"));
+ context.put("masterReplicationPort", masterReplicationPort);
+ context.put("cloneReplicationPort", cloneReplicationPort);
+ context.put("replicationSecurity", replicationSecurity);
+ context.put("panel", "admin/console/config/databasepanel.vm");
+ context.put("errorString", errorString);
+ }
+
+ public void initParams(HttpServletRequest request, Context context)
+ throws IOException {
+ IConfigStore config = CMS.getConfigStore();
+ String select = "";
+ try {
+ select = config.getString("preop.subsystem.select", "");
+ } catch (Exception e) {
+ }
+ context.put("clone", select);
+ context.put("hostname", (request.getParameter("host") != null) ? request.getParameter("host") : "");
+ context.put("portStr", (request.getParameter("port") != null) ? request.getParameter("port") : "");
+ context.put("basedn", (request.getParameter("basedn") != null) ? request.getParameter("basedn") : "");
+ context.put("binddn", (request.getParameter("binddn") != null) ? request.getParameter("binddn") : "");
+ context.put("bindpwd", (request.getParameter("__bindpwd") != null) ?
+ request.getParameter("__bindpwd"): "");
+ context.put("database", (request.getParameter("database") != null) ?
+ request.getParameter("database") : "");
+ context.put("masterReplicationPort", (request.getParameter("masterReplicationPort") != null) ?
+ request.getParameter("masterReplicationPort"): "");
+ context.put("cloneReplicationPort", (request.getParameter("cloneReplicationPort") != null) ?
+ request.getParameter("cloneReplicationPort"): "");
+ context.put("replicationSecurity", (request.getParameter("replicationSecurity") != null) ?
+ request.getParameter("replicationSecurity"): "None");
+ }
+
+ /**
+ * Parses and validates the parameters in the request.
+ */
+ public void parseParameters(HttpServletRequest request,
+ HttpServletResponse response, Context context) throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+
+ String select = "";
+ try {
+ select = cs.getString("preop.subsystem.select", "");
+ } catch (Exception e) {
+ }
+
+ String hostname = HttpInput.getHostname(request, "host");
+ if (hostname == null || hostname.length() == 0) {
+ throw new IOException("hostname is empty string");
+ }
+ context.put("hostname", hostname);
+
+ // this validates that port is an integer
+ String portStr = HttpInput.getPortNumber(request, "port");
+ context.put("portStr", portStr);
+
+ String basedn = HttpInput.getDN(request, "basedn");
+ if (basedn == null || basedn.length() == 0) {
+ throw new IOException("basedn is empty string");
+ }
+ context.put("basedn", basedn);
+
+ String binddn = HttpInput.getDN(request, "binddn");
+ if (binddn == null || binddn.length() == 0) {
+ throw new IOException("binddn is empty string");
+ }
+ context.put("binddn", binddn);
+
+ String database = HttpInput.getLdapDatabase(request, "database");
+ if (database == null || database.length() == 0) {
+ throw new IOException("Database is empty string");
+ }
+ context.put("database", database);
+
+ String bindpwd = HttpInput.getPassword(request, "__bindpwd");
+ if (bindpwd == null || bindpwd.length() == 0) {
+ throw new IOException("Bind password is empty string");
+ }
+ context.put("bindpwd", bindpwd);
+
+ String secure = HttpInput.getCheckbox(request, "secureConn");
+ context.put("secureConn", secure);
+
+ String masterReplicationPort = HttpInput.getString(request, "masterReplicationPort");
+ if (masterReplicationPort != null && masterReplicationPort.length() > 0) {
+ try {
+ Integer.parseInt(masterReplicationPort); // check for errors
+ } catch (NumberFormatException e) {
+ throw new IOException("Master replication port is invalid");
+ }
+ }
+ context.put("masterReplicationPort", masterReplicationPort);
+
+ String cloneReplicationPort = HttpInput.getString(request, "cloneReplicationPort");
+ if (cloneReplicationPort != null && cloneReplicationPort.length() > 0) {
+ try {
+ Integer.parseInt(cloneReplicationPort); // check for errors
+ } catch (Exception e) {
+ throw new IOException("Clone replication port is invalid");
+ }
+ }
+ context.put("cloneReplicationPort", cloneReplicationPort);
+
+ String replicationSecurity = HttpInput.getString(request, "replicationSecurity");
+ context.put("replicationSecurity", replicationSecurity);
+
+ if (select.equals("clone")) {
+ String masterhost = "";
+ String masterport = "";
+ String masterbasedn = "";
+ String realhostname = "";
+ try {
+ masterhost = cs.getString("preop.internaldb.master.ldapconn.host", "");
+ masterport = cs.getString("preop.internaldb.master.ldapconn.port", "");
+ masterbasedn = cs.getString("preop.internaldb.master.basedn", "");
+ realhostname = cs.getString("machineName", "");
+ } catch (Exception e) {
+ }
+
+ if (masterhost.equals(realhostname) && masterport.equals(portStr)) {
+ throw new IOException("Master and clone must not share the same internal database");
+ }
+
+ if (!masterbasedn.equals(basedn)) {
+ throw new IOException("Master and clone should have the same base DN");
+ }
+ }
+
+ context.put("errorString", "");
+ cs.putString("preop.database.errorString", "");
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+
+ IConfigStore cs = CMS.getConfigStore();
+ context.put("firsttime", "false");
+ try {
+ @SuppressWarnings("unused")
+ String s = cs.getString("preop.database.removeData"); // check whether it's first time
+ } catch (Exception e) {
+ context.put("firsttime", "true");
+ }
+
+ try {
+ parseParameters(request, response, context);
+ } catch (IOException e) {
+ context.put("errorString", e.getMessage());
+ cs.putString("preop.database.errorString", e.getMessage());
+ context.put("updateStatus", "validate-failure");
+ throw e;
+ }
+
+ context.put("errorString", "");
+ cs.putString("preop.database.errorString", "");
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+
+ context.put("firsttime", "false");
+ try {
+ @SuppressWarnings("unused")
+ String s = cs.getString("preop.database.removeData"); // check whether it's first time
+ } catch (Exception e) {
+ context.put("firsttime", "true");
+ }
+
+ String hostname1 = "";
+ String portStr1 = "";
+ String database1 = "";
+ String masterPortStr = "";
+ String csType = "";
+ String select = "";
+
+ try {
+ hostname1 = cs.getString("internaldb.ldapconn.host", "");
+ portStr1 = cs.getString("internaldb.ldapconn.port", "");
+ database1 = cs.getString("internaldb.database", "");
+ masterPortStr = cs.getString("preop.internaldb.master.ldapconn.port", "0");
+ csType = cs.getString("cs.type");
+ select = cs.getString("preop.subsystem.select", "");
+ } catch (Exception e) {
+ }
+
+ try {
+ parseParameters(request, response, context);
+ } catch (IOException e) {
+ context.put("errorString", e.getMessage());
+ cs.putString("preop.database.errorString", e.getMessage());
+ context.put("updateStatus", "validate-failure");
+ throw e;
+ }
+
+ String hostname2 = (String) context.get("hostname");
+ String portStr2 = (String) context.get("portStr");
+ String database2 = (String) context.get("database");
+ String basedn2 = (String) context.get("basedn");
+ String binddn = (String) context.get("binddn");
+ String secure = (String) context.get("secureConn");
+ String masterReplicationPortStr = (String) context.get("masterReplicationPort");
+ String cloneReplicationPortStr = (String) context.get("cloneReplicationPort");
+
+ cs.putString("internaldb.ldapconn.host", hostname2);
+ cs.putString("internaldb.ldapconn.port", portStr2);
+ cs.putString("internaldb.database", database2);
+ cs.putString("internaldb.basedn", basedn2);
+ cs.putString("internaldb.ldapauth.bindDN", binddn);
+ cs.putString("internaldb.ldapconn.secureConn", (secure.equals("on") ? "true" : "false"));
+
+ if (csType.equals("TPS")) {
+ cs.putString("tokendb.activityBaseDN", "ou=Activities," + basedn2);
+ cs.putString("tokendb.baseDN", "ou=Tokens," + basedn2);
+ cs.putString("tokendb.certBaseDN", "ou=Certificates," + basedn2);
+ cs.putString("tokendb.userBaseDN", basedn2);
+ cs.putString("tokendb.hostport", hostname2 + ":" + portStr2);
+ }
+
+ if ((masterReplicationPortStr == null) || (masterReplicationPortStr.length() == 0)) {
+ masterReplicationPortStr = masterPortStr;
+ }
+ cs.putString("internaldb.ldapconn.masterReplicationPort", masterReplicationPortStr);
+
+ int cloneReplicationPort = 0;
+ int port = Integer.parseInt(portStr2);
+ if ((cloneReplicationPortStr == null) || (cloneReplicationPortStr.length() == 0)) {
+ cloneReplicationPortStr = portStr2;
+ }
+ cloneReplicationPort = Integer.parseInt(cloneReplicationPortStr);
+ cs.putString("internaldb.ldapconn.cloneReplicationPort", cloneReplicationPortStr);
+
+ String replicationSecurity = HttpInput.getString(request, "replicationSecurity");
+ if ((cloneReplicationPort == port) && (secure.equals("true"))) {
+ replicationSecurity = "SSL";
+ } else if (replicationSecurity == null) {
+ replicationSecurity = "None";
+ }
+ cs.putString("internaldb.ldapconn.replicationSecurity", replicationSecurity);
+
+ String remove = HttpInput.getID(request, "removeData");
+ cs.putString("preop.database.removeData", ((remove != null) && (!remove.equals(""))) ?
+ "true" : "false");
+
+ if (isPanelDone() && (remove == null || remove.equals(""))) {
+ /* if user submits the same data, they just want to skip
+ to the next panel, no database population is required. */
+ if (hostname1.equals(hostname2) &&
+ portStr1.equals(portStr2) &&
+ database1.equals(database2)) {
+ context.put("updateStatus", "success");
+ return;
+ }
+ }
+
+ mServlet.cleanUpFromPanel(mServlet.getPanelNo(request));
+
+ try {
+ /* BZ 430745 create password for replication manager */
+ String replicationpwd = Integer.toString(new Random().nextInt());
+
+ IConfigStore psStore = null;
+ String passwordFile = null;
+ passwordFile = cs.getString("passwordFile");
+ psStore = CMS.createFileConfigStore(passwordFile);
+ psStore.putString("internaldb", HttpInput.getPassword(request, "__bindpwd"));
+ psStore.putString("replicationdb", replicationpwd);
+ psStore.commit(false);
+
+ ConfigurationUtils.populateDB();
+
+ cs.putString("preop.internaldb.replicationpwd", replicationpwd);
+ cs.putString("preop.database.removeData", "false");
+
+ if (select.equals("clone")) {
+ CMS.debug("Start setting up replication.");
+ ConfigurationUtils.setupReplication();
+ }
+
+ ConfigurationUtils.reInitSubsystem(csType);
+ ConfigurationUtils.populateDBManager();
+ ConfigurationUtils.populateVLVIndexes();
+
+ cs.putBoolean("preop.Database.done", true);
+ cs.commit(false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ CMS.debug("DatabasePanel update: error in populating database " + e.toString());
+ context.put("errorString", e.toString());
+ cs.putString("preop.database.errorString", e.toString());
+ context.put("updateStatus", "failure");
+ throw new IOException(e.toString());
+ }
+
+ context.put("updateStatus", "success");
+ }
+
+ /**
+ * If validate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+
+ try {
+ initParams(request, context);
+ } catch (IOException e) {
+ }
+ context.put("title", "Database");
+ context.put("panel", "admin/console/config/databasepanel.vm");
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/DisplayCertChainPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/DisplayCertChainPanel.java
new file mode 100644
index 000000000..702c5aa92
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/DisplayCertChainPanel.java
@@ -0,0 +1,226 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.util.CertPrettyPrint;
+import netscape.security.x509.X509CertImpl;
+
+import org.apache.velocity.context.Context;
+
+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.cms.servlet.wizard.WizardServlet;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+
+public class DisplayCertChainPanel extends WizardPanelBase {
+
+ public DisplayCertChainPanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Display Certificate Chain");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Display Certificate Chain");
+ setId(id);
+ }
+
+ public boolean isSubPanel() {
+ return true;
+ }
+
+ public boolean isPanelDone() {
+ return true;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ return set;
+ }
+
+ public void cleanUp() throws IOException {
+ }
+
+ /**
+ * Should we skip this panel for the configuration.
+ */
+ public boolean shouldSkip() {
+ CMS.debug("DisplayCertChainPanel: should skip");
+
+ IConfigStore cs = CMS.getConfigStore();
+ // if we are root, no need to get the certificate chain.
+
+ try {
+ String select = cs.getString("securitydomain.select", "");
+ String type = cs.getString("preop.subsystem.select", "");
+ String hierarchy = cs.getString("preop.hierarchy.select", "");
+
+ if (getId().equals("hierarchy") && hierarchy.equals("root"))
+ return true;
+
+ if (select.equals("new")) {
+ return true;
+ }
+
+ if (type.equals("new") && getId().equals("clone"))
+ return true;
+
+ if (type.equals("clone") && getId().equals("ca"))
+ return true;
+ } catch (EBaseException e) {
+ }
+
+ return false;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ try {
+ CMS.debug("DisplayCertChainPanel: display");
+
+ // update session id
+ String session_id = request.getParameter("session_id");
+ if (session_id != null) {
+ CMS.debug("DisplayCertChainPanel setting session id.");
+ CMS.setConfigSDSessionId(session_id);
+ }
+
+ String type = getId();
+ IConfigStore cs = CMS.getConfigStore();
+ String certChainConfigName = "preop." + type + ".certchain.size";
+ String certchain_size = cs.getString(certChainConfigName, "");
+ int size = 0;
+ Vector<String> v = new Vector<String>();
+
+ if (!certchain_size.equals("")) {
+ size = Integer.parseInt(certchain_size);
+ for (int i = 0; i < size; i++) {
+ certChainConfigName = "preop." + type + ".certchain." + i;
+ String c = cs.getString(certChainConfigName, "");
+ byte[] b_c = CryptoUtil.base64Decode(c);
+ CertPrettyPrint pp = new CertPrettyPrint(new X509CertImpl(b_c));
+
+ v.addElement(pp.toString(Locale.getDefault()));
+ }
+ }
+
+ if (getId().equals("securitydomain")) {
+ context.put("panelid", "securitydomain");
+ context.put("panelname", "Security Domain Trust Verification");
+ } else {
+ context.put("panelid", "other");
+ context.put("panelname", "Subsystem Trust Verification");
+ }
+ context.put("title", "Display Certificate Chain");
+ context.put("panel", "admin/console/config/displaycertchainpanel.vm");
+ context.put("errorString", "");
+ context.put("certchain", v);
+ } catch (Exception e) {
+ CMS.debug("DisplayCertPanel: Exception thrown: " + e.toString());
+ e.printStackTrace();
+ context.put("errorString", e.toString());
+ }
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+
+ if (getId().equals("securitydomain")) {
+ int panel = getPanelNo() + 1;
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String sd_hostname = cs.getString("securitydomain.host", "");
+ int sd_port = cs.getInteger("securitydomain.httpsadminport", -1);
+ String cs_hostname = cs.getString("machineName", "");
+ int cs_port = cs.getInteger("pkicreate.admin_secure_port", -1);
+ String subsystem = cs.getString("cs.type", "");
+ String urlVal = "https://" + cs_hostname + ":" + cs_port + "/" + subsystem.toLowerCase()
+ + "/admin/console/config/wizard?p=" + panel + "&subsystem=" + subsystem;
+ String encodedValue = URLEncoder.encode(urlVal, "UTF-8");
+ String sdurl = "https://" + sd_hostname + ":" + sd_port + "/ca/admin/ca/securityDomainLogin?url="
+ + encodedValue;
+ response.sendRedirect(sdurl);
+
+ // The user previously specified the CA Security Domain's
+ // SSL Admin port in the "Security Domain Panel";
+ // now retrieve this specified CA Security Domain's
+ // non-SSL EE, SSL Agent, and SSL EE ports:
+ String domainXML = ConfigurationUtils.getDomainXML(sd_hostname, sd_port, true);
+ ConfigurationUtils.getSecurityDomainPorts(domainXML, sd_hostname, sd_port);
+ cs.putString("preop.domainXML", domainXML);
+ cs.commit(false);
+ } catch (Exception e) {
+ CMS.debug("DisplayCertChainPanel Exception=" + e.toString());
+ e.printStackTrace();
+ context.put("errorString", e.toString());
+ context.put("updateStatus", "failure");
+ throw new IOException(e);
+ }
+ }
+ context.put("updateStatus", "success");
+ }
+
+ /**
+ * If validate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+
+ /* This should never be called */
+ context.put("title", "Display Certificate Chain");
+ context.put("panel", "admin/console/config/displaycertchainpanel.vm");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/DonePanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/DonePanel.java
new file mode 100644
index 000000000..57583fdcf
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/DonePanel.java
@@ -0,0 +1,311 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ocsp.IOCSPAuthority;
+import com.netscape.certsrv.property.PropertySet;
+import com.netscape.cms.servlet.wizard.WizardServlet;
+import com.netscape.cmsutil.util.Utils;
+
+public class DonePanel extends WizardPanelBase {
+
+ public static final BigInteger BIG_ZERO = new BigInteger("0");
+ public static final Long MINUS_ONE = Long.valueOf(-1);
+ public static final String RESTART_SERVER_AFTER_CONFIGURATION =
+ "restart_server_after_configuration";
+ public static final String PKI_SECURITY_DOMAIN = "pki_security_domain";
+
+ public DonePanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Done");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Done");
+ setId(id);
+ }
+
+ public boolean hasSubPanel() {
+ return false;
+ }
+
+ public void cleanUp() throws IOException {
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ /* XXX */
+
+ return set;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request, HttpServletResponse response, Context context) {
+ CMS.debug("DonePanel: display()");
+
+ // update session id
+ String session_id = request.getParameter("session_id");
+ if (session_id != null) {
+ CMS.debug("NamePanel setting session id.");
+ CMS.setConfigSDSessionId(session_id);
+ }
+
+ IConfigStore cs = CMS.getConfigStore();
+
+ String select = "";
+ String type = "";
+ String instanceId = "";
+ String instanceRoot = "";
+ String systemdService = "";
+ String ca_host = "";
+ String sdtype = "";
+ int state = 0;
+ try {
+ type = cs.getString("cs.type", "");
+ instanceId = cs.getString("instanceId");
+ instanceRoot = cs.getString("instanceRoot");
+ select = cs.getString("preop.subsystem.select", "");
+ systemdService = cs.getString("pkicreate.systemd.servicename", "");
+ ca_host = cs.getString("preop.ca.hostname", "");
+ sdtype = cs.getString("securitydomain.select", "");
+ state = cs.getInteger("cs.state");
+ } catch (Exception e) {
+ }
+
+ String initDaemon = "";
+ if (type.equals("CA")) {
+ initDaemon = "pki-cad";
+ } else if (type.equals("KRA")) {
+ initDaemon = "pki-krad";
+ } else if (type.equals("OCSP")) {
+ initDaemon = "pki-ocspd";
+ } else if (type.equals("TKS")) {
+ initDaemon = "pki-tksd";
+ }
+ String os = System.getProperty("os.name");
+ if (os.equalsIgnoreCase("Linux")) {
+ if (!systemdService.equals("")) {
+ context.put("initCommand", "/bin/systemctl");
+ context.put("instanceId", systemdService);
+ } else {
+ context.put("initCommand", "/sbin/service " + initDaemon);
+ context.put("instanceId", instanceId);
+ }
+ } else {
+ /* default case: e. g. - ( os.equalsIgnoreCase( "SunOS" ) */
+ context.put("initCommand", "/etc/init.d/" + initDaemon);
+ context.put("instanceId", instanceId);
+ }
+ context.put("title", "Done");
+ context.put("panel", "admin/console/config/donepanel.vm");
+ context.put("host", CMS.getAdminHost());
+ context.put("port", CMS.getAdminPort());
+ context.put("systemType", type.toLowerCase());
+
+ if (state == 1) {
+ context.put("csstate", "1");
+ return;
+ } else
+ context.put("csstate", "0");
+
+ if (ca_host.equals(""))
+ context.put("externalCA", "true");
+ else
+ context.put("externalCA", "false");
+
+ // Create or update security domain
+
+ try {
+ if (sdtype.equals("new")) {
+ ConfigurationUtils.createSecurityDomain();
+ } else { //existing domain
+ ConfigurationUtils.updateSecurityDomain();
+ }
+
+ cs.putString("service.securityDomainPort", CMS.getAgentPort());
+ cs.putString("securitydomain.store", "ldap");
+ cs.commit(false);
+ } catch (Exception e) {
+ CMS.debug("DonePanel - update(): Error while updating security domain: " + e);
+ e.printStackTrace();
+ }
+
+ // push connector information to the CA
+ try {
+ if (type.equals("KRA") && !ca_host.equals("")) {
+ ConfigurationUtils.updateConnectorInfo(CMS.getAgentHost(), CMS.getAgentPort());
+ ConfigurationUtils.setupClientAuthUser();
+ }
+ } catch (Exception e) {
+ context.put("info", "Failed to update connector information. "+e.getMessage());
+ CMS.debug("DonePanel - update(): Error while pushing KRA connectot information to the CA: " + e);
+ e.printStackTrace();
+ }
+
+ // import the CA certificate into the OCSP
+ // configure the CRL Publishing to OCSP in CA
+ try {
+ if (type.equals("OCSP") && !ca_host.equals("")) {
+ CMS.reinit(IOCSPAuthority.ID);
+ ConfigurationUtils.importCACertToOCSP();
+ ConfigurationUtils.updateOCSPConfig();
+ ConfigurationUtils.setupClientAuthUser();
+ }
+ } catch (Exception e) {
+ CMS.debug("DonePanel - update(): Error while configuring OCSP publishing on the CA: " + e);
+ e.printStackTrace();
+ }
+
+ try {
+ if (!select.equals("clone")) {
+ if (type.equals("CA") || type.equals("KRA")) {
+ ConfigurationUtils.updateNextRanges();
+
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("DonePanel - update(): Error while updating serial number next ranges: " + e);
+ e.printStackTrace();
+ }
+
+ try {
+ if (select.equals("clone") && type.equalsIgnoreCase("CA") && ConfigurationUtils.isSDHostDomainMaster(cs)) {
+ // cloning a domain master CA, the clone is also master of its domain
+ CMS.debug("Cloning a domain master");
+ cs.putString("securitydomain.host", CMS.getEESSLHost());
+ cs.putString("securitydomain.httpport", CMS.getEENonSSLPort());
+ cs.putString("securitydomain.httpsadminport", CMS.getAdminPort());
+ cs.putString("securitydomain.httpsagentport", CMS.getAgentPort());
+ cs.putString("securitydomain.httpseeport", CMS.getEESSLPort());
+ cs.putString("securitydomain.select", "new");
+ }
+ } catch (Exception e) {
+ CMS.debug("DonePanel - update(): Error in determining if security domain host is a master CA: " + e);
+ e.printStackTrace();
+ }
+
+ try {
+ ConfigurationUtils.setupDBUser();
+ } catch (Exception e) {
+ e.printStackTrace();
+ CMS.debug("DonePanel - update(): Unable to create or update dbuser" + e);
+ }
+
+ if (type.equals("TPS")) {
+ try {
+ String adminUID = cs.getString("preop.admin.uid", "tpsadmin");
+ ConfigurationUtils.addProfilesToTPSUser(adminUID);
+
+ String sd_admin_port = cs.getString("securitydomain.httpsadminport");
+ String sd_host = cs.getString("securitydomain.host");
+ URI secdomainURI = new URI("https://" + sd_host + ":" + sd_admin_port);
+
+ // register TPS with CA
+ URI caURI = new URI(cs.getString("preop.cainfo.select"));
+ ConfigurationUtils.registerUser(secdomainURI, caURI, "ca");
+
+ // register TPS with TKS
+ URI tksURI = new URI(cs.getString("preop.tksinfo.select"));
+ ConfigurationUtils.registerUser(secdomainURI, tksURI, "tks");
+
+ String keyGen = cs.getString("conn.tks1.serverKeygen", "false");
+ if (keyGen.equalsIgnoreCase("true")) {
+ URI kraURI = new URI(cs.getString("preop.krainfo.select"));
+ ConfigurationUtils.registerUser(secdomainURI, kraURI, "kra");
+ String transportCert = ConfigurationUtils.getTransportCert(secdomainURI, kraURI);
+ ConfigurationUtils.exportTransportCert(secdomainURI, tksURI, transportCert);
+ }
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ CMS.debug("Invalid URI for CA, TKS or KRA: " + e);
+ } catch (Exception e) {
+ e.printStackTrace();
+ CMS.debug("Errors in registering TPS to CA, TKS or KRA: " + e);
+ }
+ }
+
+ cs.putInteger("cs.state", 1);
+ try {
+ ConfigurationUtils.removePreopConfigEntries();
+ } catch (Exception e) {
+ CMS.debug("DonePanel - update(): Caught exception saving preop variables: " + e);
+ }
+
+ // Create an empty file that designates the fact that although
+ // this server instance has been configured, it has NOT yet
+ // been restarted!
+ String restart_server = instanceRoot + "/conf/"
+ + RESTART_SERVER_AFTER_CONFIGURATION;
+ if (!Utils.isNT()) {
+ Utils.exec("touch " + restart_server);
+ Utils.exec("chmod 00660 " + restart_server);
+ }
+
+ context.put("csstate", "1");
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ /**
+ * If validiate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {/* This should never be called */
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/DownloadPKCS12.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/DownloadPKCS12.java
new file mode 100644
index 000000000..7f7929930
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/DownloadPKCS12.java
@@ -0,0 +1,136 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+
+public class DownloadPKCS12 extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7770226137155537526L;
+ private final static String AUTH_FAILURE = "2";
+
+ public DownloadPKCS12() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ CMS.debug("DownloadPKCS12: initializing...");
+ super.init(sc);
+ CMS.debug("DownloadPKCS12: done initializing...");
+ }
+
+ /**
+ * Process the HTTP request.
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ CMS.debug("DownloadPKCS12: processing...");
+
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+ IConfigStore cs = CMS.getConfigStore();
+ mRenderResult = false;
+
+ // check the pin from the session
+ String pin = (String) httpReq.getSession().getAttribute("pin");
+ if (pin == null) {
+ CMS.debug("DownloadPKCS12 process: Failed to get the pin from the cookie.");
+ outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated",
+ null);
+ return;
+ }
+
+ String cspin = "";
+ try {
+ cspin = cs.getString("preop.pin");
+ } catch (Exception e) {
+ }
+
+ if (!pin.equals(cspin)) {
+ CMS.debug("DownloadPKCS12 process: Wrong pin");
+ outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated",
+ null);
+ return;
+ }
+
+ byte[] pkcs12 = null;
+ try {
+ String str = cs.getString("preop.pkcs12");
+ pkcs12 = CryptoUtil.string2byte(str);
+ } catch (Exception e) {
+ }
+
+ try {
+ httpResp.setContentType("application/x-pkcs12");
+ httpResp.getOutputStream().write(pkcs12);
+ return;
+ } catch (Exception e) {
+ CMS.debug("DownloadPKCS12 process: Exception=" + e.toString());
+ }
+ }
+
+ protected void setDefaultTemplates(ServletConfig sc) {
+ }
+
+ protected void renderTemplate(
+ CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler)
+ throws IOException {// do nothing
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetCertChain.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetCertChain.java
new file mode 100644
index 000000000..8cc0f85d6
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetCertChain.java
@@ -0,0 +1,157 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.CertificateChain;
+
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cmsutil.xml.XMLObject;
+
+public class GetCertChain extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -356806997334418285L;
+ private final static String SUCCESS = "0";
+
+ public GetCertChain() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param op 'downloadBIN' - return the binary certificate chain
+ * <li>http.param op 'displayIND' - display pretty-print of certificate chain components
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ CertificateChain certChain = ((ICertAuthority) mAuthority).getCACertChain();
+
+ if (certChain == null) {
+ CMS.debug(
+ "GetCertChain displayChain: cannot get the certificate chain.");
+ outputError(httpResp, "Error: Failed to get certificate chain.");
+ return;
+ }
+
+ byte[] bytes = null;
+
+ try {
+ ByteArrayOutputStream encoded = new ByteArrayOutputStream();
+
+ certChain.encode(encoded);
+ bytes = encoded.toByteArray();
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_ENCODING_CA_CHAIN_1",
+ e.toString()));
+ outputError(httpResp,
+ "Error: Failed to encode the certificate chain");
+ }
+
+ String chainBase64 = CMS.BtoA(bytes);
+
+ chainBase64 = normalizeCertStr(chainBase64);
+
+ try {
+ XMLObject xmlObj = null;
+
+ xmlObj = new XMLObject();
+
+ Node root = xmlObj.createRoot("XMLResponse");
+
+ xmlObj.addItemToContainer(root, "Status", SUCCESS);
+ xmlObj.addItemToContainer(root, "ChainBase64", chainBase64);
+ byte[] cb = xmlObj.toByteArray();
+
+ outputResult(httpResp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("Failed to send the XML output");
+ }
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+
+ private String normalizeCertStr(String s) {
+ StringBuffer val = new StringBuffer();
+
+ for (int i = 0; i < s.length(); i++) {
+ if (s.charAt(i) == '\n') {
+ continue;
+ } else if (s.charAt(i) == '\r') {
+ continue;
+ } else if (s.charAt(i) == '"') {
+ continue;
+ } else if (s.charAt(i) == ' ') {
+ continue;
+ }
+ val.append(s.charAt(i));
+ }
+ return val.toString();
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java
new file mode 100644
index 000000000..ee013ef48
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cmsutil.password.IPasswordStore;
+import com.netscape.cmsutil.xml.XMLObject;
+
+public class GetConfigEntries extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7418561215631752315L;
+ private final static String SUCCESS = "0";
+ private final static String AUTH_FAILURE = "2";
+
+ public GetConfigEntries() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ CMS.debug("GetConfigEntries init");
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param op 'downloadBIN' - return the binary certificate chain
+ * <li>http.param op 'displayIND' - display pretty-print of certificate chain components
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = null;
+
+ try {
+ authToken = authenticate(cmsReq);
+ } catch (Exception e) {
+ CMS.debug("GetConfigEntries authentication failed");
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "",
+ e.toString()));
+ outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated",
+ null);
+ return;
+ }
+
+ // Construct an ArgBlock
+ IArgBlock args = cmsReq.getHttpParams();
+
+ // Get the operation code
+ String op = null;
+
+ op = args.getValueAsString("op", null);
+ CMS.debug("GetConfigEntries process: op=" + op);
+
+ XMLObject xmlObj = null;
+ try {
+ xmlObj = new XMLObject();
+ } catch (Exception e) {
+ CMS.debug("GetConfigEntries process: Exception: " + e.toString());
+ throw new EBaseException(e.toString());
+ }
+
+ Node root = xmlObj.createRoot("XMLResponse");
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken, mAuthzResourceName,
+ "read");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp,
+ "Error: Encountered problem during authorization.");
+ return;
+ }
+
+ if (authzToken == null) {
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ }
+
+ if (op != null) {
+ IConfigStore config = CMS.getConfigStore();
+ String substores = args.getValueAsString("substores", "");
+ StringTokenizer t = new StringTokenizer(substores, ",");
+ while (t.hasMoreTokens()) {
+ String name1 = t.nextToken();
+ IConfigStore cs = config.getSubStore(name1);
+ Enumeration<String> enum1 = cs.getPropertyNames();
+
+ while (enum1.hasMoreElements()) {
+ String name = name1 + "." + enum1.nextElement();
+ try {
+ String value = config.getString(name);
+ if (value.equals("localhost")) {
+ value = config.getString("machineName", InetAddress.getLocalHost().getHostName());
+ }
+ Node container = xmlObj.createContainer(root, "Config");
+ xmlObj.addItemToContainer(container, "name", name);
+ xmlObj.addItemToContainer(container, "value", value);
+ } catch (Exception ee) {
+ continue;
+ }
+ }
+ }
+
+ String names = args.getValueAsString("names", "");
+ StringTokenizer t1 = new StringTokenizer(names, ",");
+ while (t1.hasMoreTokens()) {
+ String name = t1.nextToken();
+ String value = "";
+
+ try {
+ CMS.debug("Retrieving config name=" + name);
+ value = config.getString(name);
+ CMS.debug("Retrieving config value=" + value);
+ if (value.equals("localhost"))
+ value = config.getString("machineName", InetAddress.getLocalHost().getHostName());
+ } catch (Exception ee) {
+ if (name.equals("internaldb.ldapauth.password")) {
+ value = getLDAPPassword();
+ } else if (name.equals("internaldb.replication.password")) {
+ value = getReplicationPassword();
+ } else
+ continue;
+ }
+
+ Node container = xmlObj.createContainer(root, "Config");
+ xmlObj.addItemToContainer(container, "name", name);
+ xmlObj.addItemToContainer(container, "value", value);
+ }
+ }
+
+ try {
+ xmlObj.addItemToContainer(root, "Status", SUCCESS);
+ byte[] cb = xmlObj.toByteArray();
+
+ outputResult(httpResp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("Failed to send the XML output");
+ }
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+
+ private String getLDAPPassword() {
+ IPasswordStore pwdStore = CMS.getPasswordStore();
+ return pwdStore.getPassword("internaldb");
+ }
+
+ private String getReplicationPassword() {
+ IPasswordStore pwdStore = CMS.getPasswordStore();
+ return pwdStore.getPassword("replicationdb");
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetCookie.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetCookie.java
new file mode 100644
index 000000000..1e8c65182
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetCookie.java
@@ -0,0 +1,239 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.system.InstallToken;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+public class GetCookie extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2466968231929541707L;
+ private String mErrorFormPath = null;
+ private String mFormPath = null;
+
+ private final static String LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE =
+ "LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE_1";
+ private final static String LOGGING_SIGNED_AUDIT_ROLE_ASSUME =
+ "LOGGING_SIGNED_AUDIT_ROLE_ASSUME_3";
+
+ public GetCookie() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+
+ CMS.debug("GetCookie init");
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ mErrorFormPath = sc.getInitParameter("errorTemplatePath");
+ if (mOutputTemplatePath != null) {
+ mFormPath = mOutputTemplatePath;
+ }
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ CMS.debug("GetCookie start");
+ IAuthToken authToken = null;
+ IConfigStore cs = CMS.getConfigStore();
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ String url = httpReq.getParameter("url");
+ CMS.debug("GetCookie before auth, url =" + url);
+ String url_e = "";
+ URL u = null;
+ try {
+ url_e = URLDecoder.decode(url, "UTF-8");
+ u = new URL(url_e);
+ } catch (Exception eee) {
+ throw new ECMSGWException(
+ "GetCookie missing parameter: url");
+ }
+
+ int index2 = url_e.indexOf("subsystem=");
+ String subsystem = "";
+ if (index2 > 0) {
+ subsystem = url.substring(index2 + 10);
+ int index1 = subsystem.indexOf("&");
+ if (index1 > 0)
+ subsystem = subsystem.substring(0, index1);
+ }
+
+ try {
+ authToken = authenticate(cmsReq);
+ } catch (Exception e) {
+ CMS.debug("GetCookie authentication failed");
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "",
+ e.toString()));
+ header.addStringValue("sd_uid", "");
+ header.addStringValue("sd_pwd", "");
+ header.addStringValue("host", u.getHost());
+ header.addStringValue("sdhost", CMS.getEESSLHost());
+ header.addStringValue("subsystem", subsystem);
+ header.addStringValue("url", url_e);
+ header.addStringValue("errorString", "Failed Authentication");
+ String sdname = cs.getString("securitydomain.name", "");
+ header.addStringValue("sdname", sdname);
+
+ CMS.debug("mErrorFormPath=" + mErrorFormPath);
+ try {
+ form = getTemplate(mErrorFormPath, httpReq, locale);
+ } catch (IOException eee) {
+ CMS.debug("GetCookie process: cant locate the form");
+ /*
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ */
+ }
+
+ if (form == null) {
+ CMS.debug("GetCookie::process() - form is null!");
+ throw new EBaseException("form is null");
+ }
+
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ } catch (IOException ee) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", ee.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ return;
+ }
+
+ if (authToken != null) {
+ String uid = authToken.getInString("uid");
+
+ String addr = "";
+ try {
+ addr = u.getHost();
+ } catch (Exception e) {
+ }
+
+ try {
+ SecurityDomainProcessor processor = new SecurityDomainProcessor(getLocale(httpReq));
+
+ InstallToken installToken = processor.getInstallToken(uid, addr, subsystem);
+ String cookie = installToken.getToken();
+
+ if (!url.startsWith("$")) {
+ try {
+ form = getTemplate(mFormPath, httpReq, locale);
+ } catch (IOException e) {
+ CMS.debug("GetCookie process: cant locate the form");
+ /*
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ */
+ }
+
+ header.addStringValue("url", url);
+ header.addStringValue("session_id", cookie);
+
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetDomainXML.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetDomainXML.java
new file mode 100644
index 000000000..2c7d225fa
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetDomainXML.java
@@ -0,0 +1,130 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+import com.netscape.cmsutil.xml.XMLObject;
+
+public class GetDomainXML extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3079546345000720649L;
+ private final static String SUCCESS = "0";
+ private final static String FAILED = "1";
+
+ public GetDomainXML() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ CMS.debug("GetDomainXML: initializing...");
+ super.init(sc);
+ CMS.debug("GetDomainXML: done initializing...");
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param op 'downloadBIN' - return the binary certificate chain
+ * <li>http.param op 'displayIND' - display pretty-print of certificate chain components
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ CMS.debug("GetDomainXML: processing...");
+
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ String status = SUCCESS;
+
+ try {
+ XMLObject response = new XMLObject();
+ Node root = response.createRoot("XMLResponse");
+
+ try {
+ SecurityDomainProcessor processor = new SecurityDomainProcessor(getLocale(cmsReq.getHttpReq()));
+ XMLObject xmlObj = processor.getDomainXML();
+
+ // Add new xml object as string to response.
+ response.addItemToContainer(root, "DomainInfo", xmlObj.toXMLString());
+
+ } catch (Exception e) {
+ CMS.debug("Failed to read domain.xml: " + e.toString());
+ status = FAILED;
+ }
+
+ response.addItemToContainer(root, "Status", status);
+ byte[] cb = response.toByteArray();
+ outputResult(httpResp, "application/xml", cb);
+
+ } catch (Exception e) {
+ CMS.debug("GetDomainXML: Failed to send the XML output" + e.toString());
+ }
+ }
+
+ protected void setDefaultTemplates(ServletConfig sc) {
+ }
+
+ protected void renderTemplate(
+ CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler)
+ throws IOException {// do nothing
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetStatus.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetStatus.java
new file mode 100644
index 000000000..1d2d0e61f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetStatus.java
@@ -0,0 +1,111 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cmsutil.xml.XMLObject;
+
+public class GetStatus extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2852842030221659847L;
+
+ public GetStatus() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+ IConfigStore config = CMS.getConfigStore();
+
+ String state = config.getString("cs.state", "");
+ String type = config.getString("cs.type", "");
+ String status = CMS.getServerStatus();
+ String version = GetStatus.class.getPackage().getImplementationVersion();
+
+ try {
+ XMLObject xmlObj = null;
+
+ xmlObj = new XMLObject();
+
+ Node root = xmlObj.createRoot("XMLResponse");
+
+ xmlObj.addItemToContainer(root, "State", state);
+ xmlObj.addItemToContainer(root, "Type", type);
+ xmlObj.addItemToContainer(root, "Status", status);
+ xmlObj.addItemToContainer(root, "Version", version);
+ byte[] cb = xmlObj.toByteArray();
+
+ outputResult(httpResp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("Failed to send the XML output");
+ }
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetSubsystemCert.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetSubsystemCert.java
new file mode 100644
index 000000000..b894971b1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetSubsystemCert.java
@@ -0,0 +1,128 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+import com.netscape.cmsutil.xml.XMLObject;
+
+public class GetSubsystemCert extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5720342238234153488L;
+ private final static String SUCCESS = "0";
+
+ public GetSubsystemCert() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ }
+
+ /**
+ * Process the HTTP request.
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IConfigStore cs = CMS.getConfigStore();
+ String nickname = "";
+ try {
+ nickname = cs.getString("ca.subsystem.nickname", "");
+ String tokenname = cs.getString("ca.subsystem.tokenname", "");
+ if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token"))
+ nickname = tokenname + ":" + nickname;
+ } catch (Exception e) {
+ }
+
+ CMS.debug("GetSubsystemCert process: nickname=" + nickname);
+ String s = "";
+ try {
+ CryptoManager cm = CryptoManager.getInstance();
+ X509Certificate cert = cm.findCertByNickname(nickname);
+
+ if (cert == null) {
+ CMS.debug("GetSubsystemCert process: subsystem cert is null");
+ outputError(httpResp, "Error: Failed to get subsystem certificate.");
+ return;
+ }
+
+ byte[] bytes = cert.getEncoded();
+ s = CryptoUtil.normalizeCertStr(CryptoUtil.base64Encode(bytes));
+ } catch (Exception e) {
+ CMS.debug("GetSubsystemCert process: exception: " + e.toString());
+ }
+
+ try {
+ XMLObject xmlObj = null;
+ xmlObj = new XMLObject();
+ Node root = xmlObj.createRoot("XMLResponse");
+ xmlObj.addItemToContainer(root, "Status", SUCCESS);
+ xmlObj.addItemToContainer(root, "Cert", s);
+ byte[] cb = xmlObj.toByteArray();
+ outputResult(httpResp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("Failed to send the XML output");
+ }
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetTokenInfo.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetTokenInfo.java
new file mode 100644
index 000000000..2f44ca1b0
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetTokenInfo.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cmsutil.xml.XMLObject;
+
+public class GetTokenInfo extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -8416582986909026263L;
+ private final static String SUCCESS = "0";
+
+ public GetTokenInfo() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ CMS.debug("GetTokenInfo init");
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param op 'downloadBIN' - return the binary certificate chain
+ * <li>http.param op 'displayIND' - display pretty-print of certificate chain components
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ XMLObject xmlObj = null;
+ try {
+ xmlObj = new XMLObject();
+ } catch (Exception e) {
+ CMS.debug("GetTokenInfo process: Exception: " + e.toString());
+ throw new EBaseException(e.toString());
+ }
+
+ Node root = xmlObj.createRoot("XMLResponse");
+
+ IConfigStore config = CMS.getConfigStore();
+
+ String certlist = "";
+ try {
+ certlist = config.getString("cloning.list");
+ } catch (Exception e) {
+ }
+
+ StringTokenizer t1 = new StringTokenizer(certlist, ",");
+ while (t1.hasMoreTokens()) {
+ String name = t1.nextToken();
+ if (name.equals("sslserver"))
+ continue;
+ name = "cloning." + name + ".nickname";
+ String value = "";
+
+ try {
+ value = config.getString(name);
+ } catch (Exception ee) {
+ continue;
+ }
+
+ Node container = xmlObj.createContainer(root, "Config");
+ xmlObj.addItemToContainer(container, "name", name);
+ xmlObj.addItemToContainer(container, "value", value);
+ }
+
+ String value = "";
+ String name = "cloning.module.token";
+ try {
+ value = config.getString(name);
+ } catch (Exception e) {
+ }
+
+ Node container = xmlObj.createContainer(root, "Config");
+ xmlObj.addItemToContainer(container, "name", name);
+ xmlObj.addItemToContainer(container, "value", value);
+
+ try {
+ xmlObj.addItemToContainer(root, "Status", SUCCESS);
+ byte[] cb = xmlObj.toByteArray();
+
+ outputResult(httpResp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("Failed to send the XML output");
+ }
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetTransportCert.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetTransportCert.java
new file mode 100644
index 000000000..649b1214a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetTransportCert.java
@@ -0,0 +1,181 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.security.cert.CertificateEncodingException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.security.ITransportKeyUnit;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+import com.netscape.cmsutil.xml.XMLObject;
+
+/**
+ * This servlet retrieves the transport certificate from DRM.
+ */
+public class GetTransportCert extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2495152202191979339L;
+ private final static String SUCCESS = "0";
+ private final static String AUTH_FAILURE = "2";
+
+ public GetTransportCert() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ CMS.debug("GetTransportCert: initializing...");
+ super.init(sc);
+ CMS.debug("GetTransportCert: done initializing...");
+ }
+
+ /**
+ * Process the HTTP request.
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ CMS.debug("UpdateUpdater: processing...");
+
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = null;
+ try {
+ authToken = authenticate(cmsReq);
+ CMS.debug("GetTransportCert authentication successful.");
+ } catch (Exception e) {
+ CMS.debug("GetTransportCert: authentication failed.");
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "",
+ e.toString()));
+ outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated",
+ null);
+ return;
+ }
+
+ if (authToken == null) {
+ CMS.debug("GetTransportCert: authentication failed.");
+ outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated",
+ null);
+ return;
+ }
+
+ AuthzToken authzToken = null;
+ try {
+ authzToken = authorize(mAclMethod, authToken, mAuthzResourceName,
+ "read");
+ CMS.debug("GetTransportCert authorization successful.");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp,
+ "Error: Encountered problem during authorization.");
+ return;
+ }
+
+ if (authzToken == null) {
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ }
+
+ IKeyRecoveryAuthority kra =
+ (IKeyRecoveryAuthority) mAuthority;
+ ITransportKeyUnit tu = kra.getTransportKeyUnit();
+ org.mozilla.jss.crypto.X509Certificate transportCert =
+ tu.getCertificate();
+
+ String mime64 = "";
+ try {
+ mime64 = CMS.BtoA(transportCert.getEncoded());
+ mime64 = com.netscape.cmsutil.util.Cert.normalizeCertStrAndReq(mime64);
+ } catch (CertificateEncodingException eee) {
+ CMS.debug("GetTransportCert: Failed to encode certificate");
+ }
+
+ // send success status back to the requestor
+ try {
+ CMS.debug("GetTransportCert: Sending response " + mime64);
+ XMLObject xmlObj = new XMLObject();
+ Node root = xmlObj.createRoot("XMLResponse");
+
+ xmlObj.addItemToContainer(root, "Status", SUCCESS);
+ xmlObj.addItemToContainer(root, "TransportCert", mime64);
+ byte[] cb = xmlObj.toByteArray();
+
+ outputResult(httpResp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("GetTransportCert: Failed to send the XML output " + e);
+ }
+ }
+
+ protected void setDefaultTemplates(ServletConfig sc) {
+ }
+
+ protected void renderTemplate(
+ CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler)
+ throws IOException {// do nothing
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/HierarchyPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/HierarchyPanel.java
new file mode 100644
index 000000000..b42bdb7de
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/HierarchyPanel.java
@@ -0,0 +1,194 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+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.wizard.WizardServlet;
+
+public class HierarchyPanel extends WizardPanelBase {
+
+ public HierarchyPanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("PKI Hierarchy");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("PKI Hierarchy");
+ setId(id);
+ }
+
+ public boolean shouldSkip() {
+
+ // we dont need to ask the hierachy if we are
+ // setting up a clone
+ try {
+ IConfigStore c = CMS.getConfigStore();
+ String s = c.getString("preop.subsystem.select",
+ null);
+ if (s != null && s.equals("clone")) {
+ // mark this panel as done
+ c.putString("preop.hierarchy.select", "root");
+ c.putString("hierarchy.select", "Clone");
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+
+ return false;
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ cs.putString("preop.hierarchy.select", "");
+ cs.putString("hierarchy.select", "");
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String s = cs.getString("preop.hierarchy.select", "");
+ if (s == null || s.equals("")) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ /* XXX */
+
+ return set;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("title", "PKI Hierarchy");
+ IConfigStore config = CMS.getConfigStore();
+
+ if (isPanelDone()) {
+ try {
+ String s = config.getString("preop.hierarchy.select");
+
+ if (s.equals("root")) {
+ context.put("check_root", "checked");
+ } else if (s.equals("join")) {
+ context.put("check_join", "checked");
+ }
+ } catch (Exception e) {
+ CMS.debug(e.toString());
+ }
+ } else {
+ context.put("check_root", "checked");
+ context.put("check_join", "");
+ }
+
+ context.put("panel", "admin/console/config/hierarchypanel.vm");
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ IConfigStore config = CMS.getConfigStore();
+ try {
+ String cstype = config.getString("preop.subsystem.select", "");
+ if (cstype.equals("clone")) {
+ context.put("updateStatus", "success");
+ return;
+ }
+ } catch (Exception e) {
+ }
+
+ String select = HttpInput.getID(request, "choice");
+
+ if (select == null) {
+ CMS.debug("HierarchyPanel: choice not found");
+ context.put("updateStatus", "failure");
+ throw new IOException("choice not found");
+ }
+
+ if (select.equals("root")) {
+ config.putString("preop.hierarchy.select", "root");
+ config.putString("hierarchy.select", "Root");
+ config.putString("preop.ca.type", "sdca");
+ try {
+ config.commit(false);
+ } catch (EBaseException e) {
+ }
+ } else if (select.equals("join")) {
+ config.putString(PCERT_PREFIX + "signing.type", "remote");
+ config.putString("preop.hierarchy.select", "join");
+ config.putString("hierarchy.select", "Subordinate");
+ } else {
+ config.putString(PCERT_PREFIX + "signing.type", "remote");
+ CMS.debug("HierarchyPanel: invalid choice " + select);
+ context.put("updateStatus", "failure");
+ throw new IOException("invalid choice " + select);
+ }
+ context.put("updateStatus", "success");
+ }
+
+ /**
+ * If validiate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ImportAdminCertPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ImportAdminCertPanel.java
new file mode 100644
index 000000000..7019d1492
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ImportAdminCertPanel.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.math.BigInteger;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.ldap.LDAPException;
+import netscape.security.x509.X509CertImpl;
+
+import org.apache.velocity.context.Context;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.property.PropertySet;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cms.servlet.wizard.WizardServlet;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+
+public class ImportAdminCertPanel extends WizardPanelBase {
+
+ public ImportAdminCertPanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Import Administrator's Certificate");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Import Administrator's Certificate");
+ setId(id);
+ }
+
+ public boolean isSubPanel() {
+ return true;
+ }
+
+ public void cleanUp() throws IOException {
+ }
+
+ public boolean isPanelDone() {
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ return set;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ CMS.debug("ImportAdminCertPanel: display");
+ context.put("errorString", "");
+ context.put("title", "Import Administrator's Certificate");
+ context.put("panel", "admin/console/config/importadmincertpanel.vm");
+ context.put("import", "true");
+
+ IConfigStore cs = CMS.getConfigStore();
+
+ String type = "";
+
+ try {
+ type = cs.getString("preop.ca.type", "");
+ } catch (Exception e) {
+ }
+
+ try {
+ String serialno = cs.getString("preop.admincert.serialno.0");
+
+ context.put("serialNumber", serialno);
+ } catch (Exception e) {
+ context.put("errorString", "Failed to get serial number.");
+ }
+
+ context.put("caType", type);
+
+ ISubsystem ca = CMS.getSubsystem("ca");
+
+ if (ca == null) {
+ context.put("ca", "false");
+ } else {
+ context.put("ca", "true");
+ }
+
+ String caHost = "";
+ String caPort = "";
+ String info = "";
+
+ if (ca == null) {
+ if (type.equals("otherca")) {
+ try {
+ // this is a non-CA system that has elected to have its certificates
+ // signed by a CA outside of the security domain.
+ // in this case, we submitted the cert request for the admin cert to
+ // to security domain host.
+ caHost = cs.getString("securitydomain.host", "");
+ caPort = cs.getString("securitydomain.httpsadminport", "");
+ } catch (Exception e) {
+ }
+ } else if (type.equals("sdca")) {
+ try {
+ // this is a non-CA system that submitted its certs to a CA
+ // within the security domain. In this case, we submitted the cert
+ // request for the admin cert to this CA
+ caHost = cs.getString("preop.ca.hostname", "");
+ caPort = cs.getString("preop.ca.httpsadminport", "");
+ } catch (Exception e) {
+ }
+ }
+ } else {
+ // for CAs, we always generate our own admin certs
+ // send our own connection details
+ try {
+ caHost = cs.getString("service.machineName", "");
+ caPort = cs.getString("pkicreate.admin_secure_port", "");
+ } catch (Exception e) {
+ }
+ }
+
+ String pkcs7 = "";
+ try {
+ pkcs7 = cs.getString("preop.admincert.pkcs7", "");
+ } catch (Exception e) {
+ }
+
+ context.put("pkcs7", pkcs7);
+ context.put("caHost", caHost);
+ context.put("caPort", caPort);
+ context.put("info", info);
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+
+ String type = "";
+ String subsystemtype = "";
+ String selected_hierarchy = "";
+
+ try {
+ type = cs.getString("preop.ca.type", "");
+ subsystemtype = cs.getString("cs.type", "");
+ selected_hierarchy = cs.getString("preop.hierarchy.select", "");
+ } catch (Exception e) {
+ }
+
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(
+ ICertificateAuthority.ID);
+
+ if (ca == null) {
+ context.put("ca", "false");
+ } else {
+ context.put("ca", "true");
+ }
+ context.put("caType", type);
+
+ X509CertImpl certs[] = new X509CertImpl[1];
+
+ // REMINDER: This panel is NOT used by "clones"
+ if (ca != null) {
+ String serialno = null;
+
+ if (selected_hierarchy.equals("root")) {
+ CMS.debug("ImportAdminCertPanel update: "
+ + "Root CA subsystem - "
+ + "(new Security Domain)");
+ } else {
+ CMS.debug("ImportAdminCertPanel update: "
+ + "Subordinate CA subsystem - "
+ + "(new Security Domain)");
+ }
+
+ try {
+ serialno = cs.getString("preop.admincert.serialno.0");
+ } catch (Exception e) {
+ CMS.debug(
+ "ImportAdminCertPanel update: Failed to get request id.");
+ context.put("updateStatus", "failure");
+ throw new IOException("Failed to get request id.");
+ }
+
+ ICertificateRepository repost = ca.getCertificateRepository();
+
+ try {
+ certs[0] = repost.getX509Certificate(
+ new BigInteger(serialno, 16));
+ } catch (Exception ee) {
+ }
+ } else {
+ String dir = null;
+
+ // REMINDER: This panel is NOT used by "clones"
+ if (subsystemtype.equals("CA")) {
+ if (selected_hierarchy.equals("root")) {
+ CMS.debug("ImportAdminCertPanel update: "
+ + "Root CA subsystem - "
+ + "(existing Security Domain)");
+ } else {
+ CMS.debug("ImportAdminCertPanel update: "
+ + "Subordinate CA subsystem - "
+ + "(existing Security Domain)");
+ }
+ } else {
+ CMS.debug("ImportAdminCertPanel update: "
+ + subsystemtype
+ + " subsystem");
+ }
+
+ try {
+ dir = cs.getString("preop.admincert.b64", "");
+ CMS.debug("ImportAdminCertPanel update: dir=" + dir);
+ } catch (Exception ee) {
+ }
+
+ try {
+ BufferedReader reader = new BufferedReader(
+ new FileReader(dir));
+ String b64 = "";
+
+ StringBuffer sb = new StringBuffer();
+ while (reader.ready()) {
+ sb.append(reader.readLine());
+ }
+ b64 = sb.toString();
+ reader.close();
+
+ b64 = b64.trim();
+ b64 = CryptoUtil.stripCertBrackets(b64);
+ CMS.debug("ImportAdminCertPanel update: b64=" + b64);
+ byte[] b = CryptoUtil.base64Decode(b64);
+ certs[0] = new X509CertImpl(b);
+ } catch (Exception e) {
+ CMS.debug("ImportAdminCertPanel update: " + e.toString());
+ }
+ }
+
+ try {
+ IUGSubsystem ug = (IUGSubsystem) CMS.getSubsystem(IUGSubsystem.ID);
+ String uid = cs.getString("preop.admin.uid");
+ IUser user = ug.getUser(uid);
+ user.setX509Certificates(certs);
+ ug.addUserCert(user);
+ } catch (LDAPException e) {
+ CMS.debug("ImportAdminCertPanel update: failed to add certificate to the internal database. Exception: "
+ + e.toString());
+ if (e.getLDAPResultCode() != LDAPException.ATTRIBUTE_OR_VALUE_EXISTS) {
+ context.put("updateStatus", "failure");
+ throw new IOException(e.toString());
+ }
+ } catch (Exception e) {
+ CMS.debug(
+ "ImportAdminCertPanel update: failed to add certificate. Exception: "
+ + e.toString());
+ context.put("updateStatus", "failure");
+ throw new IOException(e.toString());
+ }
+
+ context.put("errorString", "");
+ context.put("info", "");
+ context.put("title", "Import Administrator Certificate");
+ context.put("panel", "admin/console/config/importadmincertpanel.vm");
+ context.put("updateStatus", "success");
+ }
+
+ public boolean shouldSkip() {
+ try {
+ IConfigStore c = CMS.getConfigStore();
+ String s = c.getString("preop.subsystem.select", null);
+ if (s != null && s.equals("clone")) {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+
+ return false;
+ }
+
+ /**
+ * If validiate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+
+ /* This should never be called */
+ context.put("title", "Import Administrator Certificate");
+ context.put("panel", "admin/console/config/importadmincertpanel.vm");
+ context.put("info", "");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ImportCAChainPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ImportCAChainPanel.java
new file mode 100755
index 000000000..bc4af9828
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ImportCAChainPanel.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.property.PropertySet;
+import com.netscape.cms.servlet.wizard.WizardServlet;
+
+public class ImportCAChainPanel extends WizardPanelBase {
+
+ public ImportCAChainPanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Import CA's Certificate Chain");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Import CA's Certificate Chain");
+ setId(id);
+ }
+
+ public boolean isSubPanel() {
+ return false;
+ }
+
+ public void cleanUp() throws IOException {
+ }
+
+ public boolean isPanelDone() {
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ return set;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ CMS.debug("ImportCACertChain: display");
+ context.put("errorString", "");
+ context.put("title", "Import CA's Certificate Chain");
+ context.put("panel", "admin/console/config/importcachainpanel.vm");
+ context.put("import", "true");
+
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ context.put("machineName", cs.getString("machineName"));
+ context.put("https_port", cs.getString("pkicreate.ee_secure_port"));
+ context.put("http_port", cs.getString("pkicreate.unsecure_port"));
+ } catch (EBaseException e) {
+ CMS.debug("ImportCACertChain:display: Exception: " + e.toString());
+ context.put("errorString", "Error loading values for Import CA Certificate Panel");
+ }
+
+ ISubsystem ca = CMS.getSubsystem("ca");
+
+ if (ca == null) {
+ context.put("ca", "false");
+ } else {
+ context.put("ca", "true");
+ }
+
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+
+ context.put("errorString", "");
+ context.put("title", "Import CA's Certificate Chain");
+ context.put("panel", "admin/console/config/importcachainpanel.vm");
+ context.put("updateStatus", "success");
+ }
+
+ /**
+ * If validiate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+
+ /* This should never be called */
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ context.put("machineName", cs.getString("machineName"));
+ context.put("https_port", cs.getString("pkicreate.ee_secure_port"));
+ context.put("http_port", cs.getString("pkicreate.unsecure_port"));
+ context.put("title", "Import CA's Certificate Chain");
+ context.put("panel", "admin/console/config/importcachainpanel.vm");
+ } catch (EBaseException e) {
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ImportTransportCert.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ImportTransportCert.java
new file mode 100644
index 000000000..b0dc966f3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ImportTransportCert.java
@@ -0,0 +1,180 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.mozilla.jss.CryptoManager;
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+import com.netscape.cmsutil.xml.XMLObject;
+
+/**
+ * This servlet imports DRM's transport certificate into TKS.
+ */
+public class ImportTransportCert extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7490067757951541235L;
+ private final static String SUCCESS = "0";
+ private final static String AUTH_FAILURE = "2";
+
+ public ImportTransportCert() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ CMS.debug("ImportTransportCert: initializing...");
+ super.init(sc);
+ CMS.debug("ImportTransportCert: done initializing...");
+ }
+
+ /**
+ * Process the HTTP request.
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ CMS.debug("UpdateUpdater: processing...");
+
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = null;
+ try {
+ authToken = authenticate(cmsReq);
+ CMS.debug("ImportTransportCert authentication successful.");
+ } catch (Exception e) {
+ CMS.debug("ImportTransportCert: authentication failed.");
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "",
+ e.toString()));
+ outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated",
+ null);
+ return;
+ }
+
+ if (authToken == null) {
+ CMS.debug("ImportTransportCert: authentication failed.");
+ outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated",
+ null);
+ return;
+ }
+
+ AuthzToken authzToken = null;
+ try {
+ authzToken = authorize(mAclMethod, authToken, mAuthzResourceName,
+ "modify");
+ CMS.debug("ImportTransportCert authorization successful.");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp,
+ "Error: Encountered problem during authorization.");
+ return;
+ }
+
+ if (authzToken == null) {
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ }
+
+ IConfigStore cs = CMS.getConfigStore();
+
+ String certsString = httpReq.getParameter("certificate");
+
+ try {
+ CryptoManager cm = CryptoManager.getInstance();
+ CMS.debug("ImportTransportCert: Importing certificate");
+ org.mozilla.jss.crypto.X509Certificate cert =
+ cm.importCACertPackage(CMS.AtoB(certsString));
+ String nickName = cert.getNickname();
+ CMS.debug("ImportTransportCert: nickname " + nickName);
+ cs.putString("tks.drm_transport_cert_nickname", nickName);
+ CMS.debug("ImportTransportCert: Commiting configuration");
+ cs.commit(false);
+
+ // send success status back to the requestor
+ CMS.debug("ImportTransportCert: Sending response");
+ XMLObject xmlObj = new XMLObject();
+ Node root = xmlObj.createRoot("XMLResponse");
+
+ xmlObj.addItemToContainer(root, "Status", SUCCESS);
+ byte[] cb = xmlObj.toByteArray();
+
+ outputResult(httpResp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("ImportTransportCert: Failed to send the XML output " + e);
+ }
+ }
+
+ protected void setDefaultTemplates(ServletConfig sc) {
+ }
+
+ protected void renderTemplate(
+ CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler)
+ throws IOException {// do nothing
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/LoginServlet.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/LoginServlet.java
new file mode 100644
index 000000000..713cb170a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/LoginServlet.java
@@ -0,0 +1,72 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.Template;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.context.Context;
+
+import com.netscape.certsrv.apps.CMS;
+
+public class LoginServlet extends BaseServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4766622132710080340L;
+
+ public boolean authenticate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ return true;
+ }
+
+ public Template process(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ Template template = null;
+
+ try {
+ String pin = request.getParameter("pin");
+
+ if (pin == null) {
+ context.put("error", "");
+ } else {
+ String cspin = CMS.getConfigStore().getString("preop.pin");
+
+ if (cspin != null && cspin.equals(pin)) {
+ // create session
+ request.getSession(true).setAttribute("pin", cspin);
+ // pin match, redirect to the welcome page
+ response.sendRedirect("wizard");
+ return null;
+ } else {
+ context.put("error", "Login Failed");
+ }
+ }
+ template = Velocity.getTemplate("admin/console/config/login.vm");
+ } catch (Exception e) {
+ System.err.println("Exception caught: " + e.getMessage());
+ }
+
+ return template;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/MainPageServlet.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/MainPageServlet.java
new file mode 100644
index 000000000..69b2a9d2a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/MainPageServlet.java
@@ -0,0 +1,157 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+public class MainPageServlet extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2425301522251239666L;
+ private String mFormPath = null;
+
+ public MainPageServlet() {
+ }
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ mTemplates.remove(ICMSRequest.ERROR);
+ }
+
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest request = cmsReq.getHttpReq();
+ HttpServletResponse response = cmsReq.getHttpResp();
+
+ CMS.debug("MainPageServlet process");
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+
+ try {
+ form = getTemplate(mFormPath, request, locale);
+ } catch (IOException e) {
+ CMS.debug("MainPageServlet process: cant locate the form");
+ /*
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ */
+ }
+
+ process(argSet, header, ctx, request, response);
+
+ try {
+ ServletOutputStream out = response.getOutputStream();
+
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ response.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ IArgBlock ctx, HttpServletRequest req, HttpServletResponse resp)
+ throws EBaseException {
+
+ int num = 0;
+ IArgBlock rarg = null;
+ IConfigStore cs = CMS.getConfigStore();
+ int state = 0;
+ String host = "";
+ String adminInterface = "";
+ String eeInterface = "";
+ String agentInterface = "";
+ try {
+ state = cs.getInteger("cs.state", 0);
+ host = cs.getString("machineName", "");
+ adminInterface = cs.getString("admin.interface.uri", "");
+ eeInterface = cs.getString("ee.interface.uri", "");
+ agentInterface = cs.getString("agent.interface.uri", "");
+ } catch (Exception e) {
+ }
+
+ if (state == 0) {
+ rarg = CMS.createArgBlock();
+ rarg.addStringValue("type", "admin");
+ rarg.addStringValue("prefix", "http");
+ rarg.addIntegerValue("port",
+ Integer.valueOf(CMS.getEENonSSLPort()).intValue());
+ rarg.addStringValue("host", host);
+ rarg.addStringValue("uri", adminInterface);
+ argSet.addRepeatRecord(rarg);
+ num++;
+ } else if (state == 1) {
+ if (!eeInterface.equals("")) {
+ rarg = CMS.createArgBlock();
+ rarg.addStringValue("type", "ee");
+ rarg.addStringValue("prefix", "https");
+ rarg.addIntegerValue("port",
+ Integer.valueOf(CMS.getEESSLPort()).intValue());
+ rarg.addStringValue("host", host);
+ rarg.addStringValue("uri", eeInterface);
+ argSet.addRepeatRecord(rarg);
+ num++;
+ }
+ if (!agentInterface.equals("")) {
+ rarg = CMS.createArgBlock();
+ rarg.addStringValue("type", "agent");
+ rarg.addStringValue("prefix", "https");
+ rarg.addIntegerValue("port",
+ Integer.valueOf(CMS.getAgentPort()).intValue());
+ rarg.addStringValue("host", host);
+ rarg.addStringValue("uri", agentInterface);
+ argSet.addRepeatRecord(rarg);
+ num++;
+ }
+ }
+ header.addIntegerValue("totalRecordCount", num);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ModulePanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ModulePanel.java
new file mode 100644
index 000000000..00474615f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ModulePanel.java
@@ -0,0 +1,338 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.pkcs11.PK11Module;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.property.PropertySet;
+import com.netscape.certsrv.util.HttpInput;
+import com.netscape.cms.servlet.wizard.WizardServlet;
+import com.netscape.cmsutil.crypto.Module;
+
+public class ModulePanel extends WizardPanelBase {
+ private CryptoManager mCryptoManager = null;
+ private Vector<Module> mSupportedModules = null;
+ private Vector<Module> mOtherModules = null;
+ private Hashtable<String, PK11Module> mCurrModTable = new Hashtable<String, PK11Module>();
+ private WizardServlet mServlet = null;
+
+ public ModulePanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Key Store");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Key Store");
+ setId(id);
+ mServlet = servlet;
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ cs.putBoolean("preop.ModulePanel.done", false);
+ }
+
+ public void loadCurrModTable() {
+ try {
+ // getting existing modules
+ mCryptoManager = CryptoManager.getInstance();
+ @SuppressWarnings("unchecked")
+ Enumeration<PK11Module> modules = mCryptoManager.getModules();
+
+ while (modules.hasMoreElements()) {
+ PK11Module mod = modules.nextElement();
+
+ CMS.debug("ModulePanel: got module " + mod.getName());
+ mCurrModTable.put(mod.getName(), mod);
+ } // while
+ } catch (Exception e) {
+ CMS.debug(
+ "ModulePanel: Exception caught in loadCurrModTable: "
+ + e.toString());
+ System.err.println("Exception caught: " + e.toString());
+ }
+ }
+
+ /*
+ * Modules not listed as supported modules
+ */
+ public void loadOtherModules() {
+ Enumeration<PK11Module> m = mCurrModTable.elements();
+
+ mOtherModules = new Vector<Module>();
+ while (m.hasMoreElements()) {
+ PK11Module mod = m.nextElement();
+ Enumeration<Module> s = mSupportedModules.elements();
+ boolean found = false;
+
+ while (s.hasMoreElements()) {
+ Module sm = s.nextElement();
+
+ if (mod.getName().equals(sm.getCommonName())) {
+ found = true;
+ break;
+ } else {
+ found = false;
+ }
+ }// while
+ if (!found) {
+ // unsupported, use common name as user friendly name
+ Module module = new Module(mod.getName(), mod.getName());
+
+ loadModTokens(module, mod);
+ module.setFound(true);
+ mOtherModules.addElement(module);
+ break;
+ }
+ }// while
+ }
+
+ /*
+ * find all tokens belonging to a module and load the Module
+ */
+ public void loadModTokens(Module module, PK11Module mod) {
+ @SuppressWarnings("unchecked")
+ Enumeration<CryptoToken> tokens = mod.getTokens();
+
+ while (tokens.hasMoreElements()) {
+ try {
+ CryptoToken token = tokens.nextElement();
+
+ CMS.debug("ModulePanel: token nick name=" + token.getName());
+ CMS.debug("ModulePanel: token logged in?" + token.isLoggedIn());
+ CMS.debug("ModulePanel: token is present?" + token.isPresent());
+ if (!token.getName().equals("Internal Crypto Services Token") &&
+ !token.getName().equals("NSS Generic Crypto Services")) {
+ module.addToken(token);
+ } else {
+ CMS.debug(
+ "ModulePanel: token " + token.getName()
+ + " not to be added");
+ }
+
+ } catch (TokenException ex) {
+ CMS.debug("ModulePanel:" + ex.toString());
+ }
+ }
+ }
+
+ /*
+ * Modules unsupported by the system will not be included
+ */
+ public void loadSupportedModules() {
+
+ // getting supported security modules
+ // a Vectgor of Modules
+ mSupportedModules = new Vector<Module>();
+ // read from conf store all supported modules
+ try {
+ int count = CMS.getConfigStore().getInteger(
+ "preop.configModules.count");
+
+ CMS.debug("ModulePanel: supported modules count= " + count);
+ for (int i = 0; i < count; i++) {
+ String cn = CMS.getConfigStore().getString(
+ "preop.configModules.module" + i + ".commonName");
+ String pn = CMS.getConfigStore().getString(
+ "preop.configModules.module" + i + ".userFriendlyName");
+ String img = CMS.getConfigStore().getString(
+ "preop.configModules.module" + i + ".imagePath");
+
+ if ((cn == null) || (cn.equals(""))) {
+ break;
+ }
+
+ CMS.debug("ModulePanel: got from config module: " + cn);
+ // create a Module object
+ Module module = new Module(cn, pn, img);
+
+ if (mCurrModTable.containsKey(cn)) {
+ CMS.debug("ModulePanel: module found: " + cn);
+ module.setFound(true);
+ // add token info to module vector
+ PK11Module m = mCurrModTable.get(cn);
+
+ loadModTokens(module, m);
+ }
+
+ CMS.debug("ModulePanel: adding module " + cn);
+ // add module to set
+ if (!mSupportedModules.contains(module)) {
+ mSupportedModules.addElement(module);
+ }
+ }// for
+
+ } catch (Exception e) {
+ CMS.debug(
+ "ModulePanel: Exception caught in loadSupportedModules(): "
+ + e.toString());
+ System.err.println("Exception caught: " + e.toString());
+ }
+ }
+
+ public PropertySet getUsage() {
+ // it a token choice. Available tokens are discovered dynamically so
+ // can't be a real CHOICE
+ PropertySet set = new PropertySet();
+
+ Descriptor tokenDesc = new Descriptor(IDescriptor.STRING, null, /* no constraint */
+ null, /* default parameter */
+ "module token selection");
+
+ set.add("choice", tokenDesc);
+
+ return set;
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ boolean s = cs.getBoolean("preop.ModulePanel.done",
+ false);
+
+ if (s != true) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+
+ return false;
+ }
+
+ public boolean hasSubPanel() {
+ return true;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ CMS.debug("ModulePanel: display()");
+ context.put("title", "Key Store");
+
+ loadCurrModTable();
+ loadSupportedModules();
+ loadOtherModules();
+
+ IConfigStore config = CMS.getConfigStore();
+
+ try {
+ String s = config.getString("preop.module.token",
+ "Internal Key Storage Token");
+
+ context.put("defTok", s);
+ } catch (Exception e) {
+ CMS.debug("ModulePanel:" + e.toString());
+ }
+
+ context.put("status", "display");
+ context.put("oms", mOtherModules);
+ context.put("sms", mSupportedModules);
+ // context.put("status_token", "None");
+ String subpanelno = String.valueOf(getPanelNo() + 1);
+ CMS.debug("ModulePanel subpanelno =" + subpanelno);
+ context.put("subpanelno", subpanelno);
+ context.put("panel", "admin/console/config/modulepanel.vm");
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ boolean hasErr = false;
+
+ try {
+ // get the value of the choice
+ String select = HttpInput.getID(request, "choice");
+
+ if (select == null) {
+ CMS.debug("ModulePanel: no choice selected");
+ hasErr = true;
+ throw new IOException("choice not found");
+ }
+
+ IConfigStore config = CMS.getConfigStore();
+ String oldtokenname = config.getString("preop.module.token", "");
+ if (!oldtokenname.equals(select))
+ mServlet.cleanUpFromPanel(mServlet.getPanelNo(request));
+
+ if (hasErr == false) {
+ config.putString("preop.module.token", select);
+ config.putBoolean("preop.ModulePanel.done", true);
+ }
+ config.commit(false);
+ context.put("updateStatus", "success");
+ } catch (Exception e) {
+ CMS.debug("ModulePanel: Exception caught: " + e.toString());
+ System.err.println("Exception caught: " + e.toString());
+ context.put("updateStatus", "failure");
+ }
+ }
+
+ /**
+ * If validiate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("title", "Security Module");
+ context.put("panel", "admin/console/config/modulepanel.vm");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/NamePanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/NamePanel.java
new file mode 100644
index 000000000..070e17e7c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/NamePanel.java
@@ -0,0 +1,622 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+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.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.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.property.PropertySet;
+import com.netscape.certsrv.util.HttpInput;
+import com.netscape.cms.servlet.wizard.WizardServlet;
+
+public class NamePanel extends WizardPanelBase {
+ private Vector<Cert> mCerts = null;
+ private WizardServlet mServlet = null;
+
+ public NamePanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Subject Names");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Subject Names");
+ setId(id);
+ mServlet = servlet;
+ }
+
+ /**
+ * Returns the usage.XXX usage needs to be made dynamic
+ */
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ Descriptor caDN = new Descriptor(IDescriptor.STRING, null, /* no constraint */
+ null, /* no default parameter */
+ "CA Signing Certificate's DN");
+
+ set.add("caDN", caDN);
+
+ Descriptor sslDN = new Descriptor(IDescriptor.STRING, null, /* no constraint */
+ null, /* no default parameter */
+ "SSL Server Certificate's DN");
+
+ set.add("sslDN", sslDN);
+
+ Descriptor subsystemDN = new Descriptor(IDescriptor.STRING, null, /* no constraint */
+ null, /* no default parameter */
+ "CA Subsystem Certificate's DN");
+
+ set.add("subsystemDN", subsystemDN);
+
+ Descriptor ocspDN = new Descriptor(IDescriptor.STRING, null, /* no constraint */
+ null, /* no default parameter */
+ "OCSP Signing Certificate's DN");
+
+ set.add("ocspDN", ocspDN);
+
+ return set;
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ @SuppressWarnings("unused")
+ boolean done = cs.getBoolean("preop.NamePanel.done"); // check for errors
+ cs.putBoolean("preop.NamePanel.done", false);
+ cs.commit(false);
+ } catch (Exception e) {
+ }
+
+ String list = "";
+ try {
+ list = cs.getString("preop.cert.list", "");
+ } catch (Exception e) {
+ }
+
+ StringTokenizer st = new StringTokenizer(list, ",");
+ while (st.hasMoreTokens()) {
+ String t = st.nextToken();
+ cs.remove("preop.cert." + t + ".done");
+ }
+
+ try {
+ cs.commit(false);
+ } catch (Exception e) {
+ }
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ boolean s = cs.getBoolean("preop.NamePanel.done", false);
+ if (s != true) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+
+ return false;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ CMS.debug("NamePanel: display()");
+ context.put("title", "Subject Names");
+
+ // update session id
+ String session_id = request.getParameter("session_id");
+ if (session_id != null) {
+ CMS.debug("NamePanel setting session id.");
+ CMS.setConfigSDSessionId(session_id);
+ }
+
+ mCerts = new Vector<Cert>();
+
+ String domainname = "";
+ IConfigStore config = CMS.getConfigStore();
+ String select = "";
+ String hselect = "";
+ String cstype = "";
+ String domainType = "";
+ try {
+ //if CA, at the hierarchy panel, was it root or subord?
+ hselect = config.getString("preop.hierarchy.select", "");
+ select = config.getString("preop.subsystem.select", "");
+ cstype = config.getString("cs.type", "");
+ domainType = config.getString("preop.securitydomain.select", "");
+ context.put("select", select);
+ if (cstype.equals("CA") && hselect.equals("root")) {
+ CMS.debug("NamePanel ca is root");
+ context.put("isRoot", "true");
+ } else {
+ CMS.debug("NamePanel not ca or not root");
+ context.put("isRoot", "false");
+ }
+ } catch (Exception e) {
+ }
+
+ try {
+ domainname = config.getString("securitydomain.name", "");
+
+ String certTags = config.getString("preop.cert.list");
+ // same token for now
+ String token = config.getString(PRE_CONF_CA_TOKEN);
+ StringTokenizer st = new StringTokenizer(certTags, ",");
+ String domaintype = config.getString("securitydomain.select");
+ int count = 0;
+ String host = "";
+ int sd_admin_port = -1;
+ if (domaintype.equals("existing")) {
+ host = config.getString("securitydomain.host", "");
+ sd_admin_port = config.getInteger("securitydomain.httpsadminport", -1);
+ count = ConfigurationUtils.getSubsystemCount(host, sd_admin_port, true, cstype);
+ }
+
+ while (st.hasMoreTokens()) {
+ String certTag = st.nextToken();
+
+ CMS.debug("NamePanel: display() about to process certTag :" + certTag);
+ String nn = config.getString(
+ PCERT_PREFIX + certTag + ".nickname");
+ Cert c = new Cert(token, nn, certTag);
+ String userfriendlyname = config.getString(
+ PCERT_PREFIX + certTag + ".userfriendlyname");
+ String subsystem = config.getString(
+ PCERT_PREFIX + certTag + ".subsystem");
+
+ c.setUserFriendlyName(userfriendlyname);
+
+ String type = config.getString(PCERT_PREFIX + certTag + ".type");
+ c.setType(type);
+ boolean enable = config.getBoolean(PCERT_PREFIX + certTag + ".enable", true);
+ c.setEnable(enable);
+
+ String cert = config.getString(subsystem + "." + certTag + ".cert", "");
+ String certreq =
+ config.getString(subsystem + "." + certTag + ".certreq", "");
+
+ String dn = config.getString(PCERT_PREFIX + certTag + ".dn");
+ boolean override = config.getBoolean(PCERT_PREFIX + certTag +
+ ".cncomponent.override", true);
+ //o_sd is to add o=secritydomainname
+ boolean o_sd = config.getBoolean(PCERT_PREFIX + certTag +
+ "o_securitydomain", true);
+ domainname = config.getString("securitydomain.name", "");
+ CMS.debug("NamePanel: display() override is " + override);
+ CMS.debug("NamePanel: display() o_securitydomain is " + o_sd);
+ CMS.debug("NamePanel: display() domainname is " + domainname);
+
+ boolean dnUpdated = false;
+ try {
+ dnUpdated = config.getBoolean(PCERT_PREFIX + certTag + ".updatedDN");
+ } catch (Exception e) {
+ }
+
+ try {
+ @SuppressWarnings("unused")
+ boolean done = config.getBoolean("preop.NamePanel.done"); // check for errors
+ c.setDN(dn);
+ } catch (Exception e) {
+ String instanceId = config.getString("service.instanceID", "");
+ if (select.equals("clone") || dnUpdated) {
+ c.setDN(dn);
+ } else if (count != 0 && override && (cert.equals("") || certreq.equals(""))) {
+ CMS.debug("NamePanel subsystemCount = " + count);
+ c.setDN(dn + " " + count +
+ ((!instanceId.equals("")) ? (",OU=" + instanceId) : "") +
+ ((o_sd) ? (",O=" + domainname) : ""));
+ config.putBoolean(PCERT_PREFIX + certTag + ".updatedDN", true);
+ } else {
+ c.setDN(dn +
+ ((!instanceId.equals("")) ? (",OU=" + instanceId) : "") +
+ ((o_sd) ? (",O=" + domainname) : ""));
+ config.putBoolean(PCERT_PREFIX + certTag + ".updatedDN", true);
+ }
+ }
+
+ mCerts.addElement(c);
+ CMS.debug(
+ "NamePanel: display() added cert to mCerts: certTag "
+ + certTag);
+ config.putString(PCERT_PREFIX + c.getCertTag() + ".dn", c.getDN());
+ }// while
+ } catch (EBaseException e) {
+ CMS.debug("NamePanel: display() exception caught:" + e.toString());
+ } catch (Exception e) {
+ CMS.debug("NamePanel: " + e.toString());
+ }
+
+ CMS.debug("NamePanel: Ready to get SSL EE HTTPS urls");
+ Vector<String> v = null;
+ if (!domainType.equals("new")) {
+ try {
+ v = ConfigurationUtils.getUrlListFromSecurityDomain(config, "CA", "SecurePort");
+ } catch (Exception e) {
+ CMS.debug("NamePanel: display(): Exception thrown in getUrlListFromSecurityDomain " + e);
+ e.printStackTrace();
+ }
+ }
+ if (v == null) {
+ v = new Vector<String>();
+ }
+ v.addElement("External CA");
+
+ StringBuffer list = new StringBuffer();
+ int size = v.size();
+
+ for (int i = 0; i < size; i++) {
+ if (i == size - 1) {
+ list.append(v.elementAt(i));
+ } else {
+ list.append(v.elementAt(i));
+ list.append(",");
+ }
+ }
+
+ try {
+ config.putString("preop.ca.list", list.toString());
+ config.commit(false);
+ } catch (Exception e) {
+ }
+
+ context.put("urls", v);
+
+ context.put("certs", mCerts);
+ context.put("panel", "admin/console/config/namepanel.vm");
+ context.put("errorString", "");
+
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ Enumeration<Cert> c = mCerts.elements();
+
+ while (c.hasMoreElements()) {
+ Cert cert = c.nextElement();
+ // get the dn's and put in config
+ if (cert.isEnable()) {
+ String dn = HttpInput.getDN(request, cert.getCertTag());
+
+ if (dn == null || dn.length() == 0) {
+ context.put("updateStatus", "validate-failure");
+ throw new IOException("Empty DN for " + cert.getUserFriendlyName());
+ }
+ }
+ } // while
+ }
+
+ public void configCertWithTag(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context, String tag) throws IOException {
+ CMS.debug("NamePanel: configCertWithTag start");
+ Enumeration<Cert> c = mCerts.elements();
+ IConfigStore config = CMS.getConfigStore();
+
+ while (c.hasMoreElements()) {
+ Cert cert = c.nextElement();
+ String ct = cert.getCertTag();
+ CMS.debug("NamePanel: configCertWithTag ct=" + ct + " tag=" + tag);
+ if (ct.equals(tag)) {
+ try {
+ String nickname = HttpInput.getNickname(request, ct + "_nick");
+ if (nickname != null) {
+ CMS.debug("configCertWithTag: Setting nickname for " + ct + " to " + nickname);
+ config.putString(PCERT_PREFIX + ct + ".nickname", nickname);
+ cert.setNickname(nickname);
+ config.commit(false);
+ }
+ String dn = HttpInput.getDN(request, ct);
+ if (dn != null) {
+ config.putString(PCERT_PREFIX + ct + ".dn", dn);
+ config.commit(false);
+ }
+ } catch (Exception e) {
+ CMS.debug("NamePanel: configCertWithTag: Exception in setting nickname for "
+ + ct + ": " + e.toString());
+ }
+
+ ConfigurationUtils.configCert(request, response, context, cert, this);
+ CMS.debug("NamePanel: configCertWithTag done with tag=" + tag);
+ return;
+ }
+ }
+ CMS.debug("NamePanel: configCertWithTag done");
+ }
+
+ private boolean inputChanged(HttpServletRequest request)
+ throws IOException {
+ IConfigStore config = CMS.getConfigStore();
+
+ boolean hasChanged = false;
+ try {
+ Enumeration<Cert> c = mCerts.elements();
+
+ while (c.hasMoreElements()) {
+ Cert cert = c.nextElement();
+ String ct = cert.getCertTag();
+ boolean enable = config.getBoolean(PCERT_PREFIX + ct + ".enable", true);
+ if (!enable)
+ continue;
+
+ String olddn = config.getString(PCERT_PREFIX + cert.getCertTag() + ".dn", "");
+ // get the dn's and put in config
+ String dn = HttpInput.getDN(request, cert.getCertTag());
+
+ if (!olddn.equals(dn))
+ hasChanged = true;
+
+ String oldnick = config.getString(PCERT_PREFIX + ct + ".nickname");
+ String nick = HttpInput.getNickname(request, ct + "_nick");
+ if (!oldnick.equals(nick))
+ hasChanged = true;
+
+ }
+ } catch (Exception e) {
+ }
+
+ return hasChanged;
+ }
+
+ public String getURL(HttpServletRequest request, IConfigStore config) {
+ String index = request.getParameter("urls");
+ if (index == null) {
+ return null;
+ }
+ String url = "";
+ if (index.startsWith("http")) {
+ // user may submit url directlry
+ url = index;
+ } else {
+ try {
+ int x = Integer.parseInt(index);
+ String list = config.getString("preop.ca.list", "");
+ StringTokenizer tokenizer = new StringTokenizer(list, ",");
+ int counter = 0;
+
+ while (tokenizer.hasMoreTokens()) {
+ url = tokenizer.nextToken();
+ if (counter == x) {
+ break;
+ }
+ counter++;
+ }
+ } catch (Exception e) {
+ }
+ }
+ return url;
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ CMS.debug("NamePanel: in update()");
+
+ if (inputChanged(request)) {
+ mServlet.cleanUpFromPanel(mServlet.getPanelNo(request));
+ } else if (isPanelDone()) {
+ context.put("updateStatus", "success");
+ return;
+ }
+
+ IConfigStore config = CMS.getConfigStore();
+ ISubsystem subsystem = CMS.getSubsystem(ICertificateAuthority.ID);
+
+ try {
+ //if CA, at the hierarchy panel, was it root or subord?
+ String hselect = config.getString("preop.hierarchy.select", "");
+ String cstype = config.getString("preop.subsystem.select", "");
+ if (cstype.equals("clone")) {
+ CMS.debug("NamePanel: clone configuration detected");
+ // still need to handle SSL certificate
+ configCertWithTag(request, response, context, "sslserver");
+ String url = getURL(request, config);
+ if (url != null && !url.equals("External CA")) {
+ // preop.ca.url and admin port are required for setting KRA connector
+ url = url.substring(url.indexOf("https"));
+ config.putString("preop.ca.url", url);
+
+ URL urlx = new URL(url);
+ updateCloneSDCAInfo(request, context, urlx.getHost(), urlx.getPort());
+
+ }
+ ConfigurationUtils.updateCloneConfig();
+ CMS.debug("NamePanel: clone configuration done");
+ context.put("updateStatus", "success");
+ return;
+ }
+
+ //if no hselect, then not CA
+ if (hselect.equals("") || hselect.equals("join")) {
+ String url = getURL(request, config);
+
+ URL urlx = null;
+
+ if (url.equals("External CA")) {
+ CMS.debug("NamePanel: external CA selected");
+ config.putString("preop.ca.type", "otherca");
+ if (subsystem != null) {
+ config.putString(PCERT_PREFIX + "signing.type", "remote");
+ }
+
+ config.putString("preop.ca.pkcs7", "");
+ config.putInteger("preop.ca.certchain.size", 0);
+ context.put("check_otherca", "checked");
+ CMS.debug("NamePanel: update: this is the external CA.");
+ } else {
+ CMS.debug("NamePanel: local CA selected");
+ url = url.substring(url.indexOf("https"));
+ config.putString("preop.ca.url", url);
+
+ urlx = new URL(url);
+ String host = urlx.getHost();
+ int port = urlx.getPort();
+ String domainXML = config.getString("preop.domainXML");
+ int admin_port = ConfigurationUtils.getPortFromSecurityDomain(domainXML,
+ host, port, "CA", "SecurePort", "SecureAdminPort");
+
+ config.putString("preop.ca.type", "sdca");
+ config.putString("preop.ca.hostname", host);
+ config.putInteger("preop.ca.httpsport", port);
+ config.putInteger("preop.ca.httpsadminport", admin_port);
+
+ context.put("check_sdca", "checked");
+ context.put("sdcaHostname", host);
+ context.put("sdHttpPort", port);
+
+ ConfigurationUtils.importCertChain(host, admin_port, "/ca/admin/ca/getCertChain", "ca");
+
+ if (subsystem != null) {
+ config.putString(PCERT_PREFIX + "signing.type", "remote");
+ config.putString(PCERT_PREFIX + "signing.profile", "caInstallCACert");
+ }
+ }
+ config.commit(false);
+
+ }
+
+ Enumeration<Cert> c = mCerts.elements();
+
+ while (c.hasMoreElements()) {
+ Cert cert = c.nextElement();
+ String ct = cert.getCertTag();
+ boolean enable = config.getBoolean(PCERT_PREFIX + ct + ".enable", true);
+ if (!enable)
+ continue;
+
+ boolean certDone = config.getBoolean(PCERT_PREFIX + ct + ".done", false);
+ if (certDone)
+ continue;
+
+ // get the nicknames and put in config
+ String nickname = HttpInput.getNickname(request, ct + "_nick");
+ if (nickname != null) {
+ CMS.debug("NamePanel: update: Setting nickname for " + ct + " to " + nickname);
+ config.putString(PCERT_PREFIX + ct + ".nickname", nickname);
+ cert.setNickname(nickname);
+ } else {
+ nickname = cert.getNickname();
+ }
+
+ // get the dn's and put in config
+ String dn = HttpInput.getDN(request, ct);
+
+ config.putString(PCERT_PREFIX + ct + ".dn", dn);
+ // commit here in case it changes
+ config.commit(false);
+
+ ConfigurationUtils.configCert(request, response, context, cert, this);
+ config.putBoolean("preop.cert." + cert.getCertTag() + ".done", true);
+ config.commit(false);
+
+ } // while
+
+ config.putBoolean("preop.NamePanel.done", true);
+ config.commit(false);
+ } catch (Exception e) {
+ CMS.debug("NamPanel - update(): Exception thrown : " + e);
+ e.printStackTrace();
+ context.put("updateStatus", "failure");
+ throw new IOException(e);
+ }
+ context.put("updateStatus", "success");
+
+ CMS.debug("NamePanel: update() done");
+ }
+
+ private void updateCloneSDCAInfo(HttpServletRequest request, Context context, String hostname, int httpsPort)
+ throws IOException, EPropertyNotFound, EBaseException, SAXException, ParserConfigurationException {
+ CMS.debug("NamePanel updateCloneSDCAInfo: selected CA hostname=" + hostname + " port=" + httpsPort);
+ IConfigStore config = CMS.getConfigStore();
+
+ if (hostname == null || hostname.length() == 0) {
+ context.put("errorString", "Hostname is null");
+ throw new IOException("Hostname is null");
+ }
+
+ // Retrieve the associated HTTPS Admin port so that it
+ // may be stored for use with ImportAdminCertPanel
+ String domainXML = config.getString("preop.domainXML");
+ int https_admin_port = ConfigurationUtils.getPortFromSecurityDomain(domainXML,
+ hostname, httpsPort, "CA", "SecurePort", "SecureAdminPort");
+
+ config.putString("preop.ca.hostname", hostname);
+ config.putInteger("preop.ca.httpsport", httpsPort);
+ config.putInteger("preop.ca.httpsadminport", https_admin_port);
+ }
+
+ public void initParams(HttpServletRequest request, Context context)
+ throws IOException {
+ context.put("certs", mCerts);
+ }
+
+ /**
+ * If validiate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ try {
+ initParams(request, context);
+ } catch (IOException e) {
+ }
+ context.put("title", "Subject Names");
+ context.put("panel", "admin/console/config/namepanel.vm");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/RegisterUser.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/RegisterUser.java
new file mode 100644
index 000000000..74197a4a8
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/RegisterUser.java
@@ -0,0 +1,332 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X509CertImpl;
+
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.usrgrp.ICertUserLocator;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+import com.netscape.cmsutil.util.Utils;
+import com.netscape.cmsutil.xml.XMLObject;
+
+/**
+ * This servlet creates a TPS user in the CA,
+ * and it associates TPS's server certificate to
+ * the user. Finally, it addes the user to the
+ * administrator group. This procedure will
+ * allows TPS to connect to the CA for certificate
+ * issuance.
+ */
+public class RegisterUser extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -699307373400031138L;
+ private final static String SUCCESS = "0";
+ private final static String AUTH_FAILURE = "2";
+ private String mGroupName = null;
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_ROLE =
+ "LOGGING_SIGNED_AUDIT_CONFIG_ROLE_3";
+
+ public RegisterUser() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ CMS.debug("RegisterUser: initializing...");
+ super.init(sc);
+ CMS.debug("RegisterUser: done initializing...");
+ mGroupName = sc.getInitParameter("GroupName");
+ CMS.debug("RegisterUser: group name " + mGroupName);
+ }
+
+ /**
+ * Process the HTTP request.
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ CMS.debug("UpdateUpdater: processing...");
+
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = null;
+ try {
+ authToken = authenticate(cmsReq);
+ CMS.debug("RegisterUser authentication successful.");
+ } catch (Exception e) {
+ CMS.debug("RegisterUser: authentication failed.");
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "",
+ e.toString()));
+ outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated",
+ null);
+ return;
+ }
+
+ if (authToken == null) {
+ CMS.debug("RegisterUser: authentication failed.");
+ outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated",
+ null);
+ return;
+ }
+
+ AuthzToken authzToken = null;
+ try {
+ authzToken = authorize(mAclMethod, authToken, mAuthzResourceName,
+ "modify");
+ CMS.debug("RegisterUser authorization successful.");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp,
+ "Error: Encountered problem during authorization.");
+ return;
+ }
+
+ if (authzToken == null) {
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ }
+
+ // create user and add certificate
+ String uid = httpReq.getParameter("uid");
+ String name = httpReq.getParameter("name");
+ String certsString = httpReq.getParameter("certificate");
+ CMS.debug("RegisterUser got uid=" + uid);
+ CMS.debug("RegisterUser got name=" + name);
+ CMS.debug("RegisterUser got certsString=" + certsString);
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditParams = "Scope;;users+Operation;;OP_ADD+source;;RegisterUser" +
+ "+Resource;;" + uid +
+ "+fullname;;" + name +
+ "+state;;1" +
+ "+userType;;<null>+email;;<null>+password;;<null>+phone;;<null>";
+
+ IUGSubsystem ugsys = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+
+ IUser user = null;
+ boolean foundByCert = false;
+ X509Certificate certs[] = new X509Certificate[1];
+ try {
+
+ byte bCert[] = null;
+ X509CertImpl cert = null;
+ bCert = Utils.base64decode(certsString);
+ cert = new X509CertImpl(bCert);
+ certs[0] = cert;
+
+ // test to see if the cert already belongs to a user
+ ICertUserLocator cul = ugsys.getCertUserLocator();
+ com.netscape.certsrv.usrgrp.Certificates c =
+ new com.netscape.certsrv.usrgrp.Certificates(certs);
+ user = cul.locateUser(c);
+ } catch (Exception ec) {
+ CMS.debug("RegisterUser: exception thrown: " + ec.toString());
+ }
+ if (user == null) {
+ CMS.debug("RegisterUser NOT found user by cert");
+ try {
+ user = ugsys.getUser(uid);
+ CMS.debug("RegisterUser found user by uid " + uid);
+ } catch (Exception eee) {
+ }
+ } else {
+ foundByCert = true;
+ CMS.debug("RegisterUser found user by cert");
+ }
+
+ try {
+
+ if (user == null) {
+ // create user only if such user does not exist
+ user = ugsys.createUser(uid);
+ user.setFullName(name);
+ user.setState("1");
+ user.setUserType("");
+ user.setEmail("");
+ user.setPhone("");
+ user.setPassword("");
+
+ ugsys.addUser(user);
+ CMS.debug("RegisterUser created user " + uid);
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams);
+ audit(auditMessage);
+ }
+
+ // extract all line separators
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < certsString.length(); i++) {
+ if (!Character.isWhitespace(certsString.charAt(i))) {
+ sb.append(certsString.charAt(i));
+ }
+ }
+ certsString = sb.toString();
+
+ auditParams = "Scope;;certs+Operation;;OP_ADD+source;;RegisterUser" +
+ "+Resource;;" + uid +
+ "+cert;;" + certsString;
+
+ user.setX509Certificates(certs);
+ if (!foundByCert) {
+ ugsys.addUserCert(user);
+ CMS.debug("RegisterUser added user certificate");
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams);
+ audit(auditMessage);
+ } else
+ CMS.debug("RegisterUser no need to add user certificate");
+ } catch (Exception eee) {
+ CMS.debug("RegisterUser error " + eee.toString());
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams);
+
+ audit(auditMessage);
+ outputError(httpResp, "Error: Certificate malformed");
+ return;
+ }
+
+ // add user to the group
+ auditParams = "Scope;;groups+Operation;;OP_MODIFY+source;;RegisterUser" +
+ "+Resource;;" + mGroupName;
+ try {
+ Enumeration<IGroup> groups = ugsys.findGroups(mGroupName);
+ IGroup group = groups.nextElement();
+
+ auditParams += "+user;;";
+ Enumeration<String> members = group.getMemberNames();
+ while (members.hasMoreElements()) {
+ auditParams += members.nextElement();
+ if (members.hasMoreElements()) {
+ auditParams += ",";
+ }
+ }
+
+ if (!group.isMember(user.getUserID())) {
+ auditParams += "," + user.getUserID();
+ group.addMemberName(user.getUserID());
+ ugsys.modifyGroup(group);
+ CMS.debug("RegisterUser modified group");
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams);
+
+ audit(auditMessage);
+ }
+ } catch (Exception e) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams);
+
+ audit(auditMessage);
+ }
+
+ // send success status back to the requestor
+ try {
+ CMS.debug("RegisterUser: Sending response");
+ XMLObject xmlObj = new XMLObject();
+ Node root = xmlObj.createRoot("XMLResponse");
+
+ xmlObj.addItemToContainer(root, "Status", SUCCESS);
+ byte[] cb = xmlObj.toByteArray();
+
+ outputResult(httpResp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("RegisterUser: Failed to send the XML output");
+ }
+ }
+
+ protected void setDefaultTemplates(ServletConfig sc) {
+ }
+
+ protected void renderTemplate(
+ CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler)
+ throws IOException {// do nothing
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java
new file mode 100644
index 000000000..243e7e839
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java
@@ -0,0 +1,235 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+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.wizard.WizardServlet;
+
+public class RestoreKeyCertPanel extends WizardPanelBase {
+
+ public RestoreKeyCertPanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Import Keys and Certificates");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Import Keys and Certificates");
+ setId(id);
+ }
+
+ /**
+ * Should we skip this panel for the configuration.
+ */
+ public boolean shouldSkip() {
+ CMS.debug("RestoreKeyCertPanel: should skip");
+
+ IConfigStore cs = CMS.getConfigStore();
+ // if we are root, no need to get the certificate chain.
+
+ try {
+ String select = cs.getString("preop.subsystem.select", "");
+ if (select.equals("clone")) {
+ return false;
+ }
+ } catch (EBaseException e) {
+ }
+
+ return true;
+ }
+
+ public boolean isSubPanel() {
+ return true;
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ /* clean up if necessary */
+ try {
+ @SuppressWarnings("unused")
+ boolean done = cs.getBoolean("preop.restorekeycert.done"); // check for errors
+ cs.putBoolean("preop.restorekeycert.done", false);
+ cs.commit(false);
+ } catch (Exception e) {
+ }
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String s = cs.getString("preop.restorekeycert.done", "");
+ if (s == null || s.equals("")) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ /* XXX */
+
+ return set;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("title", "Import Keys and Certificates");
+ IConfigStore config = CMS.getConfigStore();
+
+ if (isPanelDone()) {
+
+ try {
+ String s = config.getString("preop.pk12.path", "");
+ context.put("path", s);
+ } catch (Exception e) {
+ CMS.debug(e.toString());
+ }
+ } else {
+ context.put("path", "");
+ }
+
+ context.put("password", "");
+ context.put("panel", "admin/console/config/restorekeycertpanel.vm");
+ context.put("errorString", "");
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ IConfigStore config = CMS.getConfigStore();
+ String tokenname = "";
+ try {
+ tokenname = config.getString("preop.module.token", "");
+ } catch (Exception e) {
+ }
+
+ if (!tokenname.equals("Internal Key Storage Token"))
+ return;
+
+ // Path can be empty. If this case, we just want to
+ // get to the next panel. Customer has HSM.
+ String s = HttpInput.getString(request, "path");
+
+ if (s != null && !s.equals("")) {
+ s = HttpInput.getPassword(request, "__password");
+ if (s == null || s.equals("")) {
+ CMS.debug("RestoreKeyCertPanel validate: password is empty");
+ context.put("updateStatus", "validate-failure");
+ throw new IOException("Empty password");
+ }
+ }
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ IConfigStore config = CMS.getConfigStore();
+ try {
+ ConfigurationUtils.getConfigEntriesFromMaster();
+
+ String path = HttpInput.getString(request, "path");
+ if (path == null || path.equals("")) {
+ // skip to next panel
+ config.putBoolean("preop.restorekeycert.done", true);
+ config.commit(false);
+ context.put("updateStatus", "success");
+ return;
+ }
+
+ String pwd = HttpInput.getPassword(request, "__password");
+
+ String tokenn = config.getString("preop.module.token");
+ if (tokenn.equals("Internal Key Storage Token")) {
+ String instanceRoot = config.getString("instanceRoot");
+ String p12File = instanceRoot + File.separator + "alias" +
+ File.separator + path;
+ ConfigurationUtils.restoreCertsFromP12(p12File, pwd);
+ }
+
+ String subsystemtype = config.getString("preop.subsystem.select", "");
+ if (subsystemtype.equals("clone")) {
+ CMS.debug("RestoreKeyCertPanel: this is the clone subsystem");
+ boolean cloneReady = ConfigurationUtils.isCertdbCloned();
+ if (!cloneReady) {
+ CMS.debug("RestoreKeyCertPanel update: clone does not have all the certificates.");
+ throw new IOException("Clone is not ready");
+ }
+ }
+
+ config.putBoolean("preop.restorekeycert.done", true);
+ config.commit(false);
+ } catch (Exception e) {
+ CMS.debug("RestoreKeyCertPanel update: exception thrown:" + e);
+ e.printStackTrace();
+ context.put("errorString", e.toString());
+ context.put("updateStatus", "failure");
+ throw new IOException(e);
+ }
+
+ context.put("updateStatus", "success");
+ }
+
+ /**
+ * If validate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("title", "Import Keys and Certificates");
+ context.put("password", "");
+ context.put("path", "");
+ context.put("panel", "admin/console/config/restorekeycertpanel.vm");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/SavePKCS12Panel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SavePKCS12Panel.java
new file mode 100644
index 000000000..cdcefbfe7
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SavePKCS12Panel.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+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.cms.servlet.wizard.WizardServlet;
+
+public class SavePKCS12Panel extends WizardPanelBase {
+
+ public SavePKCS12Panel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Save Keys and Certificates");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Save Keys and Certificates");
+ setId(id);
+ }
+
+ public void cleanUp() throws IOException {
+ }
+
+ public boolean shouldSkip() {
+ IConfigStore cs = CMS.getConfigStore();
+
+ try {
+ boolean enable = cs.getBoolean("preop.backupkeys.enable", false);
+ if (!enable)
+ return true;
+ } catch (Exception e) {
+ }
+
+ return false;
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String s = cs.getString("preop.backupkeycert.done", "");
+ if (s == null || s.equals("")) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ return set;
+ }
+
+ public boolean isSubPanel() {
+ return true;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("title", "Save Keys and Certificates");
+ IConfigStore config = CMS.getConfigStore();
+ String subsystemtype = "";
+ try {
+ subsystemtype = config.getString("cs.type", "");
+ } catch (Exception e) {
+ }
+
+ subsystemtype = subsystemtype.toLowerCase();
+
+ context.put("panel", "admin/console/config/savepkcs12panel.vm");
+ context.put("subsystemtype", subsystemtype);
+ context.put("errorString", "");
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response, Context context) throws IOException {
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ context.put("title", "Save Keys and Certificates");
+ context.put("panel", "admin/console/config/savepkcs12panel.vm");
+ context.put("updateStatus", "success");
+ }
+
+ /**
+ * If validiate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("title", "Save Keys and Certificates");
+ context.put("panel", "admin/console/config/savepkcs12panel.vm");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainLogin.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainLogin.java
new file mode 100644
index 000000000..ed242f691
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainLogin.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.net.URL;
+import java.net.URLDecoder;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.Template;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.context.Context;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+
+public class SecurityDomainLogin extends BaseServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1616344299101179396L;
+
+ public boolean authenticate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ return true;
+ }
+
+ public Template process(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ Template template = null;
+
+ try {
+ String url = request.getParameter("url");
+ url = URLDecoder.decode(url, "UTF-8");
+ URL u = null;
+ if (url != null) {
+ u = new URL(url);
+ }
+ int index = url.indexOf("subsystem=");
+ String subsystem = "";
+ if (index > 0) {
+ subsystem = url.substring(index + 10);
+ int index1 = subsystem.indexOf("&");
+ if (index1 > 0)
+ subsystem = subsystem.substring(0, index1);
+ }
+ context.put("sd_uid", "");
+ context.put("sd_pwd", "");
+ context.put("url", url);
+ context.put("host", u.getHost());
+ context.put("errorString", "");
+ context.put("sdhost", CMS.getEESSLHost());
+ if (subsystem.equals("KRA")) {
+ subsystem = "DRM";
+ }
+ context.put("subsystem", subsystem);
+ // The "securitydomain.name" property ONLY resides in the "CS.cfg"
+ // associated with the CS subsystem hosting the security domain.
+ IConfigStore cs = CMS.getConfigStore();
+ String sdname = cs.getString("securitydomain.name", "");
+ context.put("name", sdname);
+ template = Velocity.getTemplate("admin/console/config/securitydomainloginpanel.vm");
+ } catch (Exception e) {
+ System.err.println("Exception caught: " + e.getMessage());
+ }
+
+ return template;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainPanel.java
new file mode 100644
index 000000000..1ae4c3397
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainPanel.java
@@ -0,0 +1,469 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+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.wizard.WizardServlet;
+
+public class SecurityDomainPanel extends WizardPanelBase {
+
+ public SecurityDomainPanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Security Domain");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Security Domain");
+ setId(id);
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ cs.putString("preop.securitydomain.select", "");
+ cs.putString("securitydomain.select", "");
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String s = cs.getString("preop.securitydomain.select", "");
+ if (s == null || s.equals("")) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ /* XXX */
+
+ return set;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ context.put("title", "Security Domain");
+ IConfigStore config = CMS.getConfigStore();
+ String errorString = "";
+ String default_admin_url = "";
+ String name = "";
+ String systemdService = "";
+
+ try {
+ default_admin_url = config.getString("preop.securitydomain.admin_url", "");
+ name = config.getString("preop.securitydomain.name", "");
+ systemdService = config.getString("pkicreate.systemd.servicename", "");
+ } catch (Exception e) {
+ CMS.debug(e.toString());
+ }
+ if (isPanelDone()) {
+ try {
+ String s = config.getString("preop.securitydomain.select");
+
+ if (s.equals("new")) {
+ context.put("check_newdomain", "checked");
+ context.put("check_existingdomain", "");
+ } else if (s.equals("existing")) {
+ context.put("check_newdomain", "");
+ context.put("check_existingdomain", "checked");
+ }
+ } catch (Exception e) {
+ CMS.debug(e.toString());
+ }
+ } else {
+ context.put("check_newdomain", "checked");
+ context.put("check_existingdomain", "");
+ }
+
+ try {
+ context.put("cstype", config.getString("cs.type"));
+ context.put("wizardname", config.getString("preop.wizard.name"));
+ context.put("panelname", "Security Domain Configuration");
+ context.put("systemname", config.getString("preop.system.name"));
+ context.put("machineName", config.getString("machineName"));
+ context.put("http_ee_port", CMS.getEENonSSLPort());
+ context.put("https_agent_port", CMS.getAgentPort());
+ context.put("https_ee_port", CMS.getEESSLPort());
+ context.put("https_admin_port", CMS.getAdminPort());
+ context.put("sdomainAdminURL", default_admin_url);
+ } catch (EBaseException e) {
+ }
+
+ context.put("panel", "admin/console/config/securitydomainpanel.vm");
+ context.put("errorString", errorString);
+
+ // from default_admin_url, find hostname, if fully qualified, get
+ // network domain name and generate default security domain name
+ if (name.equals("") && (default_admin_url != null)) {
+ try {
+ URL u = new URL(default_admin_url);
+
+ String hostname = u.getHost();
+ StringTokenizer st = new StringTokenizer(hostname, ".");
+ boolean first = true;
+ int numTokens = st.countTokens();
+ int count = 0;
+ String defaultDomain = "";
+ StringBuffer sb = new StringBuffer();
+ while (st.hasMoreTokens()) {
+ count++;
+ String n = st.nextToken();
+ if (first) { //skip the hostname
+ first = false;
+ continue;
+ }
+ if (count == numTokens) // skip the last element (e.g. com)
+ continue;
+ sb.append((defaultDomain.length() == 0) ? "" : " ");
+ sb.append(capitalize(n));
+ }
+ defaultDomain = sb.toString() + " " + "Domain";
+ name = defaultDomain;
+ CMS.debug("SecurityDomainPanel: defaultDomain generated:" + name);
+ } catch (MalformedURLException e) {
+ errorString = "Malformed URL";
+ // not being able to come up with default domain name is ok
+ }
+ }
+ context.put("sdomainName", name);
+
+ if (default_admin_url != null) {
+ String r = null;
+
+ try {
+ // check to see if "default" security domain exists
+ // on local machine
+ URL u = new URL(default_admin_url);
+
+ String hostname = u.getHost();
+ int port = u.getPort();
+ ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback();
+ r = pingCS(hostname, port, true, certApprovalCallback);
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainPanel: exception caught: "
+ + e.toString());
+ }
+
+ if (r != null) {
+ // "default" security domain exists on local machine;
+ // fill "sdomainURL" in with "default" security domain
+ // as an initial "guess"
+ CMS.debug("SecurityDomainPanel: pingCS returns: " + r);
+ context.put("sdomainURL", default_admin_url);
+ } else {
+ // "default" security domain does NOT exist on local machine;
+ // leave "sdomainURL" blank
+ CMS.debug("SecurityDomainPanel: pingCS no successful response");
+ context.put("sdomainURL", "");
+ }
+ }
+
+ // Information for "existing" Security Domain CAs
+ String initDaemon = "pki-cad";
+ String instanceId = "&lt;security_domain_instance_name&gt;";
+ String os = System.getProperty("os.name");
+ if (os.equalsIgnoreCase("Linux")) {
+ if (!systemdService.equals("")) {
+ context.put("initCommand", "/usr/bin/pkicontrol");
+ context.put("instanceId", "ca " + systemdService);
+ } else {
+ context.put("initCommand", "/sbin/service " + initDaemon);
+ context.put("instanceId", instanceId);
+ }
+ } else {
+ /* default case: e. g. - ( os.equalsIgnoreCase( "SunOS" ) */
+ context.put("initCommand", "/etc/init.d/" + initDaemon);
+ context.put("instanceId", instanceId);
+ }
+ }
+
+ public static String capitalize(String s) {
+ if (s.length() == 0) {
+ return s;
+ } else {
+ return s.substring(0, 1).toUpperCase() + s.substring(1);
+ }
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+
+ String select = HttpInput.getID(request, "choice");
+ if (select.equals("newdomain")) {
+ String name = HttpInput.getSecurityDomainName(request, "sdomainName");
+ if (name == null || name.equals("")) {
+ initParams(request, context);
+ context.put("updateStatus", "validate-failure");
+ throw new IOException("Missing name value for the security domain");
+ }
+ } else if (select.equals("existingdomain")) {
+ CMS.debug("SecurityDomainPanel: validating "
+ + "SSL Admin HTTPS . . .");
+ String admin_url = HttpInput.getURL(request, "sdomainURL");
+ if (admin_url == null || admin_url.equals("")) {
+ initParams(request, context);
+ context.put("updateStatus", "validate-failure");
+ throw new IOException("Missing SSL Admin HTTPS url value "
+ + "for the security domain");
+ } else {
+ String r = null;
+
+ try {
+ URL u = new URL(admin_url);
+
+ String hostname = u.getHost();
+ int admin_port = u.getPort();
+ ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback();
+ r = pingCS(hostname, admin_port, true,
+ certApprovalCallback);
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainPanel: exception caught: "
+ + e.toString());
+ context.put("updateStatus", "validate-failure");
+ throw new IOException("Illegal SSL Admin HTTPS url value "
+ + "for the security domain");
+ }
+
+ if (r != null) {
+ CMS.debug("SecurityDomainPanel: pingAdminCS returns: "
+ + r);
+ context.put("sdomainURL", admin_url);
+ } else {
+ CMS.debug("SecurityDomainPanel: pingAdminCS "
+ + "no successful response for SSL Admin HTTPS");
+ context.put("sdomainURL", "");
+ }
+ }
+ }
+ }
+
+ public void initParams(HttpServletRequest request, Context context)
+ throws IOException {
+ IConfigStore config = CMS.getConfigStore();
+ try {
+ context.put("cstype", config.getString("cs.type"));
+ } catch (Exception e) {
+ }
+
+ String select = request.getParameter("choice");
+ if (select.equals("newdomain")) {
+ context.put("check_newdomain", "checked");
+ context.put("check_existingdomain", "");
+ } else if (select.equals("existingdomain")) {
+ context.put("check_newdomain", "");
+ context.put("check_existingdomain", "checked");
+ }
+
+ String name = request.getParameter("sdomainName");
+ if (name == null)
+ name = "";
+ context.put("sdomainName", name);
+
+ String admin_url = request.getParameter("sdomainURL");
+ if (admin_url == null)
+ admin_url = "";
+ context.put("sdomainURL", admin_url);
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ String select = HttpInput.getID(request, "choice");
+
+ if (select == null) {
+ CMS.debug("SecurityDomainPanel: choice not found");
+ context.put("updateStatus", "failure");
+ throw new IOException("choice not found");
+ }
+ IConfigStore config = CMS.getConfigStore();
+
+ try {
+ if (select.equals("newdomain")) {
+ config.putString("preop.securitydomain.select", "new");
+ config.putString("securitydomain.select", "new");
+ config.putString("preop.securitydomain.name", HttpInput.getDomainName(request, "sdomainName"));
+ config.putString("securitydomain.name", HttpInput.getDomainName(request, "sdomainName"));
+ config.putString("securitydomain.host", CMS.getEENonSSLHost());
+ config.putString("securitydomain.httpport", CMS.getEENonSSLPort());
+ config.putString("securitydomain.httpsagentport", CMS.getAgentPort());
+ config.putString("securitydomain.httpseeport", CMS.getEESSLPort());
+ config.putString("securitydomain.httpsadminport", CMS.getAdminPort());
+
+ // make sure the subsystem certificate is issued locallly
+ config.putString("preop.cert.subsystem.type", "local");
+ config.putString("preop.cert.subsystem.profile", "subsystemCert.profile");
+
+ config.commit(false);
+ } else if (select.equals("existingdomain")) {
+ config.putString("preop.securitydomain.select", "existing");
+ config.putString("securitydomain.select", "existing");
+
+ // make sure the subsystem certificate is issued by the security domain
+ config.putString("preop.cert.subsystem.type", "remote");
+ config.putString("preop.cert.subsystem.profile", "caInternalAuthSubsystemCert");
+
+ String admin_url = HttpInput.getURL(request, "sdomainURL");
+ String hostname = "";
+ int admin_port = -1;
+
+ if (admin_url != null) {
+ URL admin_u = new URL(admin_url);
+ hostname = admin_u.getHost();
+ admin_port = admin_u.getPort();
+ context.put("sdomainURL", admin_url);
+ config.putString("securitydomain.host", hostname);
+ config.putInteger("securitydomain.httpsadminport", admin_port);
+ }
+ config.commit(false);
+
+ ConfigurationUtils.importCertChain(hostname, admin_port, "/ca/admin/ca/getCertChain", "securitydomain");
+ } else {
+ CMS.debug("SecurityDomainPanel: invalid choice " + select);
+ throw new IOException("invalid choice " + select);
+ }
+
+ config.commit(false);
+
+ context.put("cstype", config.getString("cs.type"));
+ context.put("wizardname", config.getString("preop.wizard.name"));
+ context.put("panelname", "Security Domain Configuration");
+ context.put("systemname", config.getString("preop.system.name"));
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainPanel update(): Exception thrown:" + e);
+ e.printStackTrace();
+ context.put("errorString", e.toString());
+ context.put("updateStatus", "failure");
+ throw new IOException(e);
+ }
+
+ context.put("updateStatus", "success");
+ }
+
+ /**
+ * If validate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ IConfigStore config = CMS.getConfigStore();
+ String default_admin_url = "";
+ try {
+ initParams(request, context);
+ } catch (IOException e) {
+ }
+
+ try {
+ default_admin_url = config.getString("preop.securitydomain.admin_url", "");
+ } catch (Exception e) {
+ }
+
+ if (default_admin_url != null) {
+ String r = null;
+
+ try {
+ // check to see if "default" security domain exists on local machine
+ URL u = new URL(default_admin_url);
+
+ String hostname = u.getHost();
+ int port = u.getPort();
+ ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback();
+ r = pingCS(hostname, port, true, certApprovalCallback);
+ } catch (Exception e) {
+ }
+
+ if (r != null) {
+ // "default" security domain exists on local machine;
+ // refill "sdomainURL" in with "default" security domain
+ // as an initial "guess"
+ context.put("sdomainURL", default_admin_url);
+ } else {
+ // "default" security domain does NOT exist on local machine;
+ // leave "sdomainURL" blank
+ context.put("sdomainURL", "");
+ }
+ }
+
+ try {
+ context.put("machineName", config.getString("machineName"));
+ context.put("http_ee_port", CMS.getEENonSSLPort());
+ context.put("https_agent_port", CMS.getAgentPort());
+ context.put("https_ee_port", CMS.getEESSLPort());
+ context.put("https_admin_port", CMS.getAdminPort());
+ context.put("sdomainAdminURL",
+ config.getString("preop.securitydomain.admin_url"));
+ } catch (EBaseException e) {
+ }
+
+ // Information for "existing" Security Domain CAs
+ String initDaemon = "pki-cad";
+ String instanceId = "&lt;security_domain_instance_name&gt;";
+ String os = System.getProperty("os.name");
+ if (os.equalsIgnoreCase("Linux")) {
+ context.put("initCommand", "/sbin/service " + initDaemon);
+ context.put("instanceId", instanceId);
+ } else {
+ /* default case: e. g. - ( os.equalsIgnoreCase( "SunOS" ) */
+ context.put("initCommand", "/etc/init.d/" + initDaemon);
+ context.put("instanceId", instanceId);
+ }
+
+ context.put("title", "Security Domain");
+ context.put("panel", "admin/console/config/securitydomainpanel.vm");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainProcessor.java
new file mode 100644
index 000000000..ddfa8fae1
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainProcessor.java
@@ -0,0 +1,398 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.StringWriter;
+import java.net.InetAddress;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Random;
+import java.util.Vector;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPSearchConstraints;
+import netscape.ldap.LDAPSearchResults;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+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.certsrv.base.ISecurityDomainSessionTable;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.base.UnauthorizedException;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.system.DomainInfo;
+import com.netscape.certsrv.system.InstallToken;
+import com.netscape.certsrv.system.SecurityDomainHost;
+import com.netscape.certsrv.system.SecurityDomainSubsystem;
+import com.netscape.cms.servlet.processors.Processor;
+import com.netscape.cmsutil.xml.XMLObject;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class SecurityDomainProcessor extends Processor {
+
+ public final static String LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE =
+ "LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE_1";
+
+ public final static String[] TYPES = { "CA", "KRA", "OCSP", "TKS", "RA", "TPS" };
+
+ Random random = new Random();
+
+ public SecurityDomainProcessor(Locale locale) throws EPropertyNotFound, EBaseException {
+ super("securitydomain", locale);
+ }
+
+ public InstallToken getInstallToken(
+ String user,
+ String hostname,
+ String subsystem) throws EBaseException {
+
+ String groupname = ConfigurationUtils.getGroupName(user, subsystem);
+
+ if (groupname == null) {
+ String message = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ user,
+ ILogger.FAILURE,
+ "Enterprise " + subsystem + " Administrators");
+ audit(message);
+
+ throw new UnauthorizedException("Access denied.");
+ }
+
+ String message = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ user,
+ ILogger.SUCCESS,
+ groupname);
+ audit(message);
+
+ String ip = "";
+ try {
+ ip = InetAddress.getByName(hostname).getHostAddress();
+ } catch (Exception e) {
+ CMS.debug("Unable to determine IP address for "+hostname);
+ }
+
+ // assign cookie
+ Long num = random.nextLong();
+ String cookie = num.toString();
+
+ String auditParams = "operation;;issue_token+token;;" + cookie + "+ip;;" + ip +
+ "+uid;;" + user + "+groupname;;" + groupname;
+
+ ISecurityDomainSessionTable ctable = CMS.getSecurityDomainSessionTable();
+ int status = ctable.addEntry(cookie, ip, user, groupname);
+
+ if (status == ISecurityDomainSessionTable.SUCCESS) {
+ message = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE,
+ user,
+ ILogger.SUCCESS,
+ auditParams);
+ audit(message);
+
+ } else {
+ message = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE,
+ user,
+ ILogger.FAILURE,
+ auditParams);
+ audit(message);
+
+ throw new PKIException("Failed to update security domain.");
+ }
+
+
+ return new InstallToken(cookie);
+ }
+
+ public DomainInfo getDomainInfo() throws EBaseException {
+
+ ILdapConnFactory connFactory = null;
+ LDAPConnection conn = null;
+
+ try {
+ LDAPSearchConstraints cons = null;
+ String[] attrs = null;
+
+ IConfigStore cs = CMS.getConfigStore();
+ String basedn = cs.getString("internaldb.basedn");
+ String dn = "ou=Security Domain," + basedn;
+ String filter = "objectclass=pkiSecurityGroup";
+
+ IConfigStore ldapConfig = cs.getSubStore("internaldb");
+ connFactory = CMS.getLdapBoundConnFactory();
+ connFactory.init(ldapConfig);
+ conn = connFactory.getConn();
+
+ // get the security domain name
+ String name = (String) conn.read(dn).getAttribute("name").getStringValues().nextElement();
+ CMS.debug("SecurityDomainProcessor: name: "+name);
+
+ DomainInfo domain = new DomainInfo();
+ domain.setName(name);
+
+ // this should return CAList, KRAList etc.
+ LDAPSearchResults res = conn.search(dn, LDAPConnection.SCOPE_ONE, filter,
+ attrs, true, cons);
+
+ while (res.hasMoreElements()) {
+ dn = res.next().getDN();
+ String listName = dn.substring(3, dn.indexOf(","));
+ String subType = listName.substring(0, listName.indexOf("List"));
+ CMS.debug("SecurityDomainProcessor: subtype: "+subType);
+
+ filter = "objectclass=pkiSubsystem";
+ LDAPSearchResults res2 = conn.search(dn, LDAPConnection.SCOPE_ONE, filter,
+ attrs, false, cons);
+
+ while (res2.hasMoreElements()) {
+ LDAPEntry entry = res2.next();
+ CMS.debug("SecurityDomainProcessor: - "+entry.getDN());
+
+ SecurityDomainHost host = new SecurityDomainHost();
+
+ LDAPAttributeSet entryAttrs = entry.getAttributeSet();
+
+ @SuppressWarnings("unchecked")
+ Enumeration<LDAPAttribute> attrsInSet = entryAttrs.getAttributes();
+ while (attrsInSet.hasMoreElements()) {
+ LDAPAttribute nextAttr = attrsInSet.nextElement();
+ String attrName = nextAttr.getName();
+ String attrValue = (String) nextAttr.getStringValues().nextElement();
+ CMS.debug("SecurityDomainProcessor: - "+attrName+": "+attrValue);
+
+ if ("Host".equalsIgnoreCase(attrName)) {
+ host.setHostname(attrValue);
+
+ } else if ("UnSecurePort".equalsIgnoreCase(attrName)) {
+ host.setPort(attrValue);
+
+ } else if ("SecurePort".equalsIgnoreCase(attrName)) {
+ host.setSecurePort(attrValue);
+
+ } else if ("SecureEEClientAuthPort".equalsIgnoreCase(attrName)) {
+ host.setSecureEEClientAuthPort(attrValue);
+
+ } else if ("SecureAgentPort".equalsIgnoreCase(attrName)) {
+ host.setSecureAgentPort(attrValue);
+
+ } else if ("SecureAdminPort".equalsIgnoreCase(attrName)) {
+ host.setSecureAdminPort(attrValue);
+
+ } else if ("Clone".equalsIgnoreCase(attrName)) {
+ host.setClone(attrValue);
+
+ } else if ("SubsystemName".equalsIgnoreCase(attrName)) {
+ host.setSubsystemName(attrValue);
+
+ } else if ("DomainManager".equalsIgnoreCase(attrName)) {
+ host.setDomainManager(attrValue);
+ }
+ }
+
+ String port = host.getSecurePort();
+ if (port == null) port = host.getSecureEEClientAuthPort();
+ host.setId(subType+" "+host.getHostname()+" "+port);
+
+ domain.addHost(subType, host);
+ }
+ }
+
+ return domain;
+
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainProcessor: Failed to read domain info from ldap " + e);
+ throw new EBaseException(e.getMessage(), e);
+
+ } finally {
+ if (conn != null && connFactory != null) {
+ CMS.debug("Releasing ldap connection");
+ connFactory.returnConn(conn);
+ }
+ }
+ }
+
+ public XMLObject getDomainXML() throws EBaseException, ParserConfigurationException {
+ return convertDomainInfoToXMLObject(getDomainInfo());
+ }
+
+ public static XMLObject convertDomainInfoToXMLObject(DomainInfo domain) throws ParserConfigurationException {
+
+ XMLObject xmlObject = new XMLObject();
+
+ Node domainInfo = xmlObject.createRoot("DomainInfo");
+ xmlObject.addItemToContainer(domainInfo, "Name", domain.getName());
+
+ for (String subType : TYPES) {
+ SecurityDomainSubsystem subsystem = domain.getSubsystem(subType);
+ Node listNode = xmlObject.createContainer(domainInfo, subType+"List");
+
+ int counter;
+ if (subsystem == null) {
+ counter = 0;
+
+ } else {
+ counter = subsystem.getHosts().length;
+
+ for (SecurityDomainHost host : subsystem.getHosts()) {
+ Node node = xmlObject.createContainer(listNode, subType);
+
+ String value = host.getHostname();
+ if (value != null) xmlObject.addItemToContainer(node, "Host", value);
+
+ value = host.getPort();
+ if (value != null) xmlObject.addItemToContainer(node, "UnSecurePort", value);
+
+ value = host.getSecurePort();
+ if (value != null) xmlObject.addItemToContainer(node, "SecurePort", value);
+
+ value = host.getSecureEEClientAuthPort();
+ if (value != null) xmlObject.addItemToContainer(node, "SecureEEClientAuthPort", value);
+
+ value = host.getSecureAgentPort();
+ if (value != null) xmlObject.addItemToContainer(node, "SecureAgentPort", value);
+
+ value = host.getSecureAdminPort();
+ if (value != null) xmlObject.addItemToContainer(node, "SecureAdminPort", value);
+
+ value = host.getClone();
+ if (value != null) xmlObject.addItemToContainer(node, "Clone", value);
+
+ value = host.getSubsystemName();
+ if (value != null) xmlObject.addItemToContainer(node, "SubsystemName", value);
+
+ value = host.getDomainManager();
+ if (value != null) xmlObject.addItemToContainer(node, "DomainManager", value);
+ }
+ }
+
+ xmlObject.addItemToContainer(
+ listNode, "SubsystemCount", Integer.toString(counter));
+ }
+
+ return xmlObject;
+ }
+
+ public static DomainInfo convertXMLObjectToDomainInfo(XMLObject xmlObject) {
+
+ DomainInfo domain = new DomainInfo();
+ Document doc = xmlObject.getDocument();
+ Node rootNode = doc.getFirstChild();
+
+ Vector<String> values = xmlObject.getValuesFromContainer(rootNode, "Name");
+ if (!values.isEmpty()) domain.setName(values.firstElement());
+
+ for (String type : TYPES) {
+ NodeList hosts = doc.getElementsByTagName(type);
+ for (int j=0; j<hosts.getLength(); j++) {
+ Node hostNode = hosts.item(j);
+ SecurityDomainHost host = new SecurityDomainHost();
+
+ values = xmlObject.getValuesFromContainer(hostNode, "Host");
+ if (!values.isEmpty()) host.setHostname(values.firstElement());
+
+ values = xmlObject.getValuesFromContainer(hostNode, "UnSecurePort");
+ if (!values.isEmpty()) host.setPort(values.firstElement());
+
+ values = xmlObject.getValuesFromContainer(hostNode, "SecurePort");
+ if (!values.isEmpty()) host.setSecurePort(values.firstElement());
+
+ values = xmlObject.getValuesFromContainer(hostNode, "SecureEEClientAuthPort");
+ if (!values.isEmpty()) host.setSecureEEClientAuthPort(values.firstElement());
+
+ values = xmlObject.getValuesFromContainer(hostNode, "SecureAgentPort");
+ if (!values.isEmpty()) host.setSecureAgentPort(values.firstElement());
+
+ values = xmlObject.getValuesFromContainer(hostNode, "SecureAdminPort");
+ if (!values.isEmpty()) host.setSecureAdminPort(values.firstElement());
+
+ values = xmlObject.getValuesFromContainer(hostNode, "Clone");
+ if (!values.isEmpty()) host.setClone(values.firstElement());
+
+ values = xmlObject.getValuesFromContainer(hostNode, "SubsystemName");
+ if (!values.isEmpty()) host.setSubsystemName(values.firstElement());
+
+ values = xmlObject.getValuesFromContainer(hostNode, "DomainManager");
+ if (!values.isEmpty()) host.setDomainManager(values.firstElement());
+
+ String port = host.getSecurePort();
+ if (port == null) port = host.getSecureEEClientAuthPort();
+ host.setId(type+" "+host.getHostname()+" "+port);
+
+ domain.addHost(type, host);
+ }
+ }
+
+ return domain;
+ }
+
+ public static void main(String args[]) throws Exception {
+
+ DomainInfo before = new DomainInfo();
+ before.setName("EXAMPLE");
+
+ SecurityDomainHost host = new SecurityDomainHost();
+ host.setId("CA localhost 8443");
+ host.setHostname("localhost");
+ host.setPort("8080");
+ host.setSecurePort("8443");
+ host.setDomainManager("TRUE");
+
+ before.addHost("CA", host);
+
+ System.out.println("Before:");
+ System.out.println(before);
+
+ XMLObject xmlObject = convertDomainInfoToXMLObject(before);
+ Document document = xmlObject.getDocument();
+
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+
+ StringWriter sw = new StringWriter();
+ transformer.transform(new DOMSource(document), new StreamResult(sw));
+
+ System.out.println("Domain XML:");
+ System.out.println(sw);
+
+ DomainInfo after = convertXMLObjectToDomainInfo(xmlObject);
+
+ System.out.println("After:");
+ System.out.println(after);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainService.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainService.java
new file mode 100644
index 000000000..399c28a35
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainService.java
@@ -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.
+//
+// (C) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+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.UriInfo;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.system.DomainInfo;
+import com.netscape.certsrv.system.InstallToken;
+import com.netscape.certsrv.system.SecurityDomainResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author alee
+ */
+public class SecurityDomainService extends PKIService implements SecurityDomainResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ @Override
+ public InstallToken getInstallToken(String hostname, String subsystem) {
+ try {
+ // Get uid from realm authentication.
+ String user = servletRequest.getUserPrincipal().getName();
+
+ SecurityDomainProcessor processor = new SecurityDomainProcessor(getLocale(headers));
+ return processor.getInstallToken(user, hostname, subsystem);
+
+ } catch (EBaseException e) {
+ throw new PKIException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public DomainInfo getDomainInfo() throws PKIException {
+ try {
+ SecurityDomainProcessor processor = new SecurityDomainProcessor(getLocale(headers));
+ return processor.getDomainInfo();
+
+ } catch (EBaseException e) {
+ throw new PKIException(e.getMessage(), e);
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/SizePanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SizePanel.java
new file mode 100644
index 000000000..45a4fe106
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SizePanel.java
@@ -0,0 +1,491 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.property.PropertySet;
+import com.netscape.certsrv.util.HttpInput;
+import com.netscape.cms.servlet.wizard.WizardServlet;
+
+public class SizePanel extends WizardPanelBase {
+ private Vector<Cert> mCerts = null;
+ private WizardServlet mServlet = null;
+
+ private String default_ecc_curve_name;
+ private String default_rsa_key_size;
+ private boolean mShowSigning = false;
+
+ public SizePanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Key Pairs");
+ setId(id);
+ mServlet = servlet;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ Descriptor choiceDesc =
+ new Descriptor(
+ IDescriptor.CHOICE,
+ "default,custom",
+ null, /* no default parameter */
+ "If 'default', the key size will be configured automatically. If 'custom', the key size will be set to the value of the parameter 'custom_size'.");
+
+ set.add("choice", choiceDesc);
+
+ Descriptor customSizeDesc = new Descriptor(IDescriptor.STRING, null, /* no constraint */
+ null, /* no default parameter */
+ "Custom Key Size");
+
+ set.add("custom_size", customSizeDesc);
+
+ return set;
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ /* clean up if necessary*/
+ try {
+ @SuppressWarnings("unused")
+ boolean done = cs.getBoolean("preop.SizePanel.done"); // check for errors
+ cs.putBoolean("preop.SizePanel.done", false);
+ cs.commit(false);
+ } catch (Exception e) {
+ }
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ boolean s = cs.getBoolean("preop.SizePanel.done", false);
+ if (s != true) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+
+ return false;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ CMS.debug("SizePanel: display()");
+ try {
+ initParams(request, context);
+ } catch (IOException e) {
+ }
+
+ context.put("firsttime", "false");
+ String errorString = "";
+ mCerts = new Vector<Cert>();
+
+ IConfigStore config = CMS.getConfigStore();
+ try {
+ @SuppressWarnings("unused")
+ boolean done = config.getBoolean("preop.SizePanel.done"); // check whether it's first time
+ } catch (Exception e) {
+ context.put("firsttime", "true");
+ }
+
+ try {
+ default_ecc_curve_name = config.getString("keys.ecc.curve.default", "nistp256");
+ } catch (Exception e) {
+ }
+
+ try {
+ default_rsa_key_size = config.getString("keys.rsa.keysize.default", "2048");
+ } catch (Exception e) {
+ }
+
+ try {
+ // same token for now
+ String token = config.getString(PRE_CONF_CA_TOKEN);
+ String certTags = config.getString("preop.cert.list");
+ String rsaCertTags = config.getString("preop.cert.rsalist", "");
+ context.put("rsaTags", rsaCertTags);
+ StringTokenizer st = new StringTokenizer(certTags, ",");
+ mShowSigning = false;
+
+ while (st.hasMoreTokens()) {
+ String certTag = st.nextToken();
+ String nn = config.getString(PCERT_PREFIX + certTag + ".nickname");
+ Cert c = new Cert(token, nn, certTag);
+
+ String s = config.getString(PCERT_PREFIX + certTag + ".keysize.select", "default");
+
+ if (s.equals("default")) {
+ c.setKeyOption("default");
+ }
+ if (s.equals("custom")) {
+ c.setKeyOption("custom");
+ }
+
+ s = config.getString(PCERT_PREFIX + certTag + ".keysize.custom_size",
+ default_rsa_key_size);
+ c.setCustomKeysize(s);
+
+ s = config.getString(PCERT_PREFIX + certTag + ".curvename.custom_name",
+ default_ecc_curve_name);
+ c.setCustomCurvename(s);
+
+ boolean signingRequired = config.getBoolean(
+ PCERT_PREFIX + certTag + ".signing.required",
+ false);
+ c.setSigningRequired(signingRequired);
+ if (signingRequired)
+ mShowSigning = true;
+
+ String userfriendlyname = config.getString(
+ PCERT_PREFIX + certTag + ".userfriendlyname");
+ c.setUserFriendlyName(userfriendlyname);
+ boolean enable = config.getBoolean(PCERT_PREFIX + certTag + ".enable", true);
+ c.setEnable(enable);
+ mCerts.addElement(c);
+ }// while
+ } catch (Exception e) {
+ CMS.debug("SizePanel: display() " + e.toString());
+ }
+ CMS.debug("SizePanel: display() 1");
+
+ context.put("show_signing", mShowSigning ? "true" : "false");
+ context.put("certs", mCerts);
+ context.put("errorString", errorString);
+ context.put("default_keysize", default_rsa_key_size);
+ context.put("default_ecc_curvename", default_ecc_curve_name);
+ context.put("panel", "admin/console/config/sizepanel.vm");
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException, NumberFormatException {
+ CMS.debug("SizePanel: update()");
+ boolean hasErr = false;
+ IConfigStore config = CMS.getConfigStore();
+ String select1 = "";
+ String val1 = null;
+ boolean hasChanged = false;
+ try {
+ select1 = config.getString("preop.subsystem.select", "");
+ } catch (Exception e) {
+ }
+
+ context.put("firsttime", "false");
+ try {
+ @SuppressWarnings("unused")
+ boolean done = config.getBoolean("preop.SizePanel.done"); // check whether it's first time
+ } catch (Exception e) {
+ context.put("firsttime", "true");
+ if (select1.equals("clone")) {
+ // preset the sslserver dn for cloning case
+ try {
+ String val = config.getString("preop.cert.sslserver.dn", "");
+ config.putString("preop.cert.sslserver.dn", val + ",o=clone");
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ String token = "";
+ try {
+ token = config.getString(PRE_CONF_CA_TOKEN, "");
+ Enumeration<Cert> c = mCerts.elements();
+
+ while (c.hasMoreElements()) {
+ Cert cert = c.nextElement();
+ String ct = cert.getCertTag();
+ boolean enable = config.getBoolean(PCERT_PREFIX + ct + ".enable", true);
+ if (!enable)
+ continue;
+
+ String keytype = HttpInput.getKeyType(request, ct + "_keytype"); // rsa or ecc
+
+ String keyalgorithm = HttpInput.getString(request, ct + "_keyalgorithm");
+ if (keyalgorithm == null) {
+ if (keytype != null && keytype.equals("ecc")) {
+ keyalgorithm = "SHA256withEC";
+ } else {
+ keyalgorithm = "SHA256withRSA";
+ }
+ }
+
+ String signingalgorithm = HttpInput.getString(request, ct + "_signingalgorithm");
+ if (signingalgorithm == null) {
+ signingalgorithm = keyalgorithm;
+ }
+
+ String select = HttpInput.getID(request, ct + "_choice");
+
+ if (select == null) {
+ CMS.debug("SizePanel: " + ct + "_choice not found");
+ throw new IOException(
+ "SizePanel: " + ct + "_choice not found");
+ }
+ CMS.debug("SizePanel: update() keysize choice selected:" + select);
+ String oldkeysize = config.getString(PCERT_PREFIX + ct + ".keysize.size", "");
+ String oldkeytype = config.getString(PCERT_PREFIX + ct + ".keytype", "");
+ String oldkeyalgorithm = config.getString(PCERT_PREFIX + ct + ".keyalgorithm", "");
+ String oldsigningalgorithm = config.getString(PCERT_PREFIX + ct + ".signingalgorithm", "");
+ String oldcurvename = config.getString(PCERT_PREFIX + ct + ".curvename.name", "");
+
+ if (select.equals("default")) {
+ // XXXrenaming these...keep for now just in case
+ config.putString("preop.keysize.select", "default");
+ if (keytype != null && keytype.equals("ecc")) {
+ config.putString("preop.curvename.custom_name", default_ecc_curve_name);
+ config.putString("preop.curvename.name", default_ecc_curve_name);
+ } else {
+ config.putString("preop.keysize.custom_size", default_rsa_key_size);
+ config.putString("preop.keysize.size", default_rsa_key_size);
+ }
+
+ config.putString(PCERT_PREFIX + ct + ".keytype", keytype);
+ config.putString(PCERT_PREFIX + ct + ".keyalgorithm", keyalgorithm);
+ config.putString(PCERT_PREFIX + ct + ".signingalgorithm", signingalgorithm);
+ config.putString(PCERT_PREFIX + ct + ".keysize.select", "default");
+
+ if (keytype != null && keytype.equals("ecc")) {
+ config.putString(PCERT_PREFIX + ct +".curvename.custom_name",
+ default_ecc_curve_name);
+ config.putString(PCERT_PREFIX + ct + ".curvename.name",
+ default_ecc_curve_name);
+ } else {
+ config.putString(PCERT_PREFIX + ct + ".keysize.custom_size",
+ default_rsa_key_size);
+ config.putString(PCERT_PREFIX + ct + ".keysize.size",
+ default_rsa_key_size);
+ }
+ } else if (select.equals("custom")) {
+ // XXXrenaming these...keep for now just in case
+ config.putString("preop.keysize.select", "custom");
+ if (keytype != null && keytype.equals("ecc")) {
+ config.putString("preop.curvename.name",
+ HttpInput.getString(request, ct + "_custom_curvename"));
+ config.putString("preop.curvename.custom_name",
+ HttpInput.getString(request, ct + "_custom_curvename"));
+ } else {
+ config.putString("preop.keysize.size",
+ HttpInput.getKeySize(request, ct + "_custom_size", keytype));
+ config.putString("preop.keysize.custom_size",
+ HttpInput.getKeySize(request, ct + "_custom_size", keytype));
+ }
+
+ config.putString(PCERT_PREFIX + ct + ".keytype", keytype);
+ config.putString(PCERT_PREFIX + ct + ".keyalgorithm", keyalgorithm);
+ config.putString(PCERT_PREFIX + ct + ".signingalgorithm", signingalgorithm);
+ config.putString(PCERT_PREFIX + ct + ".keysize.select", "custom");
+
+ if (keytype != null && keytype.equals("ecc")) {
+ config.putString(PCERT_PREFIX + ct + ".curvename.custom_name",
+ HttpInput.getString(request, ct + "_custom_curvename"));
+ config.putString(PCERT_PREFIX + ct + ".curvename.name",
+ HttpInput.getString(request, ct + "_custom_curvename"));
+ } else {
+ config.putString(PCERT_PREFIX + ct + ".keysize.custom_size",
+ HttpInput.getKeySize(request, ct + "_custom_size"));
+ config.putString(PCERT_PREFIX + ct + ".keysize.size",
+ HttpInput.getKeySize(request, ct + "_custom_size"));
+ }
+ } else {
+ CMS.debug("SizePanel: invalid choice " + select);
+ throw new IOException("invalid choice " + select);
+ }
+
+ String newkeysize = config.getString(PCERT_PREFIX + ct + ".keysize.size", "");
+ String newkeytype = config.getString(PCERT_PREFIX + ct + ".keytype", "");
+ String newkeyalgorithm = config.getString(PCERT_PREFIX + ct + ".keyalgorithm", "");
+ String newsigningalgorithm = config.getString(PCERT_PREFIX + ct + ".signingalgorithm", "");
+ String newcurvename = config.getString(PCERT_PREFIX + ct + ".curvename.name", "");
+
+ if (!oldkeysize.equals(newkeysize) ||
+ !oldkeytype.equals(newkeytype) ||
+ !oldkeyalgorithm.equals(newkeyalgorithm) ||
+ !oldsigningalgorithm.equals(newsigningalgorithm) ||
+ !oldcurvename.equals(newcurvename))
+ hasChanged = true;
+ }// while
+
+ try {
+ config.commit(false);
+ } catch (EBaseException e) {
+ CMS.debug("SizePanel: update() Exception caught at config commit: " + e.toString());
+ }
+
+ val1 = HttpInput.getID(request, "generateKeyPair");
+
+ if (hasChanged || (val1 != null && !val1.equals(""))) {
+ mServlet.cleanUpFromPanel(mServlet.getPanelNo(request));
+ } else if (isPanelDone()) {
+ context.put("updateStatus", "success");
+ return;
+ }
+ } catch (IOException e) {
+ CMS.debug("SizePanel: update() IOException caught: " + e.toString());
+ context.put("updateStatus", "failure");
+ throw e;
+ } catch (NumberFormatException e) {
+ CMS.debug("SizePanel: update() NumberFormatException caught: " + e.toString());
+ context.put("updateStatus", "failure");
+ throw e;
+ } catch (Exception e) {
+ CMS.debug("SizePanel: update() Exception caught: " + e.toString());
+ }
+
+ // generate key pair
+ Enumeration<Cert> c = mCerts.elements();
+
+ while (c.hasMoreElements()) {
+ Cert cert = c.nextElement();
+ String ct = cert.getCertTag();
+ String friendlyName = ct;
+ boolean enable = true;
+ try {
+ enable = config.getBoolean(PCERT_PREFIX + ct + ".enable", true);
+ friendlyName = config.getString(PCERT_PREFIX + ct + ".userfriendlyname", ct);
+ } catch (Exception e) {
+ }
+
+ if (!enable)
+ continue;
+
+ try {
+ String keytype = config.getString(PCERT_PREFIX + ct + ".keytype");
+
+ if (keytype.equals("rsa")) {
+ int keysize = config.getInteger(PCERT_PREFIX + ct + ".keysize.size");
+ ConfigurationUtils.createRSAKeyPair(token, keysize, config, ct);
+ } else {
+ String curveName = config.getString(PCERT_PREFIX + ct + ".curvename.name", default_ecc_curve_name);
+ ConfigurationUtils.createECCKeyPair(token, curveName, config, ct);
+ }
+ config.commit(false);
+ } catch (Exception e) {
+ CMS.debug(e);
+ CMS.debug("SizePanel: key generation failure: " + e.toString());
+ context.put("updateStatus", "failure");
+ throw new IOException("key generation failure for the certificate: " + friendlyName +
+ ". See the logs for details.");
+ }
+ } // while
+
+ if (hasErr == false) {
+ config.putBoolean("preop.SizePanel.done", true);
+ try {
+ config.commit(false);
+ } catch (EBaseException e) {
+ CMS.debug("SizePanel: update() Exception caught at config commit: "+ e.toString());
+ }
+ }
+ CMS.debug("SizePanel: update() done");
+ context.put("updateStatus", "success");
+ }
+
+ public void initParams(HttpServletRequest request, Context context)
+ throws IOException {
+ IConfigStore config = CMS.getConfigStore();
+ String s = "";
+ try {
+ context.put("title", "Key Pairs");
+
+ s = config.getString("preop.subsystem.select", "");
+ context.put("select", s);
+
+ s = config.getString("preop.hierarchy.select", "root");
+ context.put("hselect", s);
+
+ s = config.getString("preop.ecc.algorithm.list", "SHA256withEC,SHA1withEC,SHA384withEC,SHA512withEC");
+ context.put("ecclist", s);
+
+ s =
+ config.getString("preop.rsa.algorithm.list",
+ "SHA256withRSA,SHA1withRSA,SHA512withRSA,MD5withRSA,MD2withRSA");
+ context.put("rsalist", s);
+
+ s = config.getString("keys.ecc.curve.list", "nistp256");
+ context.put("curvelist", s);
+
+ s = config.getString("keys.ecc.curve.display.list", "nistp256");
+ context.put("displaycurvelist", s);
+
+ s = config.getString("pkicreate.subsystem_type");
+ context.put("subsystemtype", s);
+
+ } catch (Exception e) {
+ CMS.debug("SizePanel(): initParams: unable to set all initial parameters:" + e);
+ }
+ }
+
+ /**
+ * If validiate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ try {
+ initParams(request, context);
+ } catch (IOException e) {
+ }
+
+ context.put("certs", mCerts);
+ context.put("show_signing", mShowSigning ? "true" : "false");
+ context.put("default_keysize", default_rsa_key_size);
+ context.put("default_ecc_curvename", default_ecc_curve_name);
+
+ context.put("panel", "admin/console/config/sizepanel.vm");
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/SystemCertDataFactory.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SystemCertDataFactory.java
new file mode 100644
index 000000000..aaaf17163
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SystemCertDataFactory.java
@@ -0,0 +1,48 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.csadmin;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import com.netscape.certsrv.system.SystemCertData;
+
+/**
+ * @author edewata
+ */
+public class SystemCertDataFactory {
+
+ public static SystemCertData create(Cert cert) {
+ SystemCertData data = new SystemCertData();
+ data.setCert(cert.getCert());
+ data.setRequest(cert.getRequest());
+ data.setTag(cert.getCertTag());
+ data.setCertChain(cert.getCertChain());
+ return data;
+ }
+
+ public static List<SystemCertData> create(Collection<Cert> certs) {
+ List<SystemCertData> result = new ArrayList<SystemCertData>();
+ for (Cert cert : certs) {
+ result.add(create(cert));
+ }
+ return result;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/SystemConfigService.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SystemConfigService.java
new file mode 100644
index 000000000..c6100148f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SystemConfigService.java
@@ -0,0 +1,1277 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.math.BigInteger;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Random;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.UriInfo;
+
+import netscape.security.x509.X509CertImpl;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.NoSuchTokenException;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.util.IncorrectPasswordException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.ocsp.IOCSPAuthority;
+import com.netscape.certsrv.system.ConfigurationRequest;
+import com.netscape.certsrv.system.ConfigurationResponse;
+import com.netscape.certsrv.system.SystemCertData;
+import com.netscape.certsrv.system.SystemConfigResource;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cms.servlet.base.PKIService;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * @author alee
+ *
+ */
+public class SystemConfigService extends PKIService implements SystemConfigResource {
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ IConfigStore cs;
+ String csType;
+ String csSubsystem;
+ String csState;
+ boolean isMasterCA = false;
+ String instanceRoot;
+
+ public static String SUCCESS = "0";
+ public static final String RESTART_SERVER_AFTER_CONFIGURATION =
+ "restart_server_after_configuration";
+
+ public SystemConfigService() throws EPropertyNotFound, EBaseException {
+ cs = CMS.getConfigStore();
+ csType = cs.getString("cs.type");
+ csSubsystem = csType.toLowerCase();
+ csState = cs.getString("cs.state");
+ String domainType = cs.getString("securitydomain.select", "existingdomain");
+ if (csType.equals("CA") && domainType.equals("new")) {
+ isMasterCA = true;
+ }
+ instanceRoot = cs.getString("instanceRoot");
+ }
+
+ /* (non-Javadoc)
+ * @see com.netscape.cms.servlet.csadmin.SystemConfigurationResource#configure(javax.ws.rs.core.MultivaluedMap)
+ */
+ @Override
+ public ConfigurationResponse configure(MultivaluedMap<String, String> form) {
+ ConfigurationRequest data = new ConfigurationRequest(form);
+ return configure(data);
+ }
+
+ /* (non-Javadoc)
+ * @see com.netscape.cms.servlet.csadmin.SystemConfigurationResource#configure(com.netscape.cms.servlet.csadmin.data.ConfigurationData)
+ */
+ @Override
+ public ConfigurationResponse configure(ConfigurationRequest data){
+ if (csState.equals("1")) {
+ throw new BadRequestException("System is already configured");
+ }
+
+ String certList;
+ try {
+ certList = cs.getString("preop.cert.list");
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Unable to get certList from config file");
+ }
+
+ CMS.debug("SystemConfigService(): configure() called");
+ CMS.debug(data.toString());
+
+ validateData(data);
+ ConfigurationResponse response = new ConfigurationResponse();
+
+ if (data.getStandAlone() && data.getStepTwo()) {
+ // Stand-alone PKI (Step 2)
+ // Special case to import the external CA and its Chain
+ certList = "external_signing" + "," + certList;
+ }
+
+ // specify module and log into token
+ CMS.debug("=== Token Panel ===");
+ String token = data.getToken();
+ if (token == null) {
+ token = ConfigurationRequest.TOKEN_DEFAULT;
+ }
+ tokenPanel(data, token);
+
+ //configure security domain
+ CMS.debug("=== Security Domain Panel ===");
+ String securityDomainType = data.getSecurityDomainType();
+ String domainXML = securityDomainPanel(data, securityDomainType);
+
+ //subsystem panel
+ CMS.debug("=== Subsystem Panel ===");
+ cs.putString("preop.subsystem.name", data.getSubsystemName());
+
+ // is this a clone of another subsystem?
+ if (data.getIsClone().equals("false")) {
+ cs.putString("preop.subsystem.select", "new");
+ cs.putString("subsystem.select", "New");
+ } else {
+ cs.putString("preop.subsystem.select", "clone");
+ cs.putString("subsystem.select", "Clone");
+ getCloningData(data, certList, token, domainXML);
+ }
+
+ // Hierarchy Panel
+ CMS.debug("=== Hierarchy Panel ===");
+ hierarchyPanel(data);
+
+ // TPS Panels
+ if (csType.equals("TPS")) {
+
+ // get subsystem certificate nickname
+ String subsystemNick = null;
+ for (SystemCertData cdata: data.getSystemCerts()) {
+ if (cdata.getTag().equals("subsystem")) {
+ subsystemNick = cdata.getNickname();
+ break;
+ }
+ }
+ if ((subsystemNick == null) || subsystemNick.isEmpty()) {
+ throw new BadRequestException("No nickname provided for subsystem certificate");
+ }
+
+ // CA Info Panel
+ caInfoPanel(data, subsystemNick);
+
+ // retrieve and import CA cert
+
+ // TKS Info Panel
+ tksInfoPanel(data, subsystemNick);
+
+ //DRM Info Panel
+ kraInfoPanel(data, subsystemNick);
+
+ //AuthDBPanel
+ ConfigurationUtils.updateAuthdbInfo(data.getAuthdbBaseDN(),
+ data.getAuthdbHost(), data.getAuthdbPort(),
+ data.getAuthdbSecureConn());
+
+ }
+
+ // Database Panel
+ CMS.debug("=== Database Panel ===");
+ databasePanel(data);
+
+ // SizePanel, NamePanel, CertRequestPanel
+ //handle the CA URL
+ CMS.debug("=== Size Panel, Name Panel, CertRequest Panel ===");
+ try {
+ if ((data.getHierarchy() == null) || (data.getHierarchy().equals("join"))) {
+ String url = data.getIssuingCA();
+ if (url.equals("External CA")) {
+ CMS.debug("external CA selected");
+ cs.putString("preop.ca.type", "otherca");
+ cs.putString("preop.ca.pkcs7", "");
+ cs.putInteger("preop.ca.certchain.size", 0);
+ if (csType.equals("CA")) {
+ cs.putString("preop.cert.signing.type", "remote");
+ }
+ } else {
+ CMS.debug("local CA selected");
+ url = url.substring(url.indexOf("https"));
+ cs.putString("preop.ca.url", url);
+
+ URL urlx = new URL(url);
+ String host = urlx.getHost();
+ int port = urlx.getPort();
+ int admin_port = ConfigurationUtils.getPortFromSecurityDomain(domainXML,
+ host, port, "CA", "SecurePort", "SecureAdminPort");
+
+ cs.putString("preop.ca.type", "sdca");
+ cs.putString("preop.ca.hostname", host);
+ cs.putInteger("preop.ca.httpsport", port);
+ cs.putInteger("preop.ca.httpsadminport", admin_port);
+
+ if (!data.getIsClone().equals("true")) {
+ ConfigurationUtils.importCertChain(host, admin_port, "/ca/admin/ca/getCertChain", "ca");
+ }
+
+ if (csType.equals("CA")) {
+ cs.putString("preop.cert.signing.type", "remote");
+ cs.putString("preop.cert.signing.profile","caInstallCACert");
+ }
+ }
+ }
+ } catch (Exception e) {
+ throw new PKIException("Error in obtaining certificate chain from issuing CA: " + e);
+ }
+
+ boolean generateServerCert = data.getGenerateServerCert().equalsIgnoreCase("false")? false : true;
+ boolean hasSigningCert = false;
+ Vector<Cert> certs = new Vector<Cert>();
+ try {
+ StringTokenizer t = new StringTokenizer(certList, ",");
+ while (t.hasMoreTokens()) {
+ String ct = t.nextToken();
+ String certStr;
+ boolean enable = cs.getBoolean("preop.cert." + ct + ".enable", true);
+ if (!enable) continue;
+
+ Collection<SystemCertData> certData = data.getSystemCerts();
+ Iterator<SystemCertData> iterator = certData.iterator();
+ SystemCertData cdata = null;
+ boolean cdata_found = false;
+ while (iterator.hasNext()) {
+ cdata = iterator.next();
+ if (cdata.getTag().equals(ct)) {
+ cdata_found = true;
+ CMS.debug("Found data for '" + ct + "'");
+ break;
+ }
+ }
+ if (!cdata_found) {
+ CMS.debug("No data for '" + ct + "' was found!");
+ throw new BadRequestException("No data for '" + ct + "' was found!");
+ }
+
+ if (data.getStandAlone() && data.getStepTwo()) {
+ // Stand-alone PKI (Step 2)
+ if (ct.equals("external_signing")) {
+ String b64 = cdata.getCert();
+ if ((b64!= null) && (b64.length()>0) && (!b64.startsWith("..."))) {
+ hasSigningCert = true;
+ if (data.getIssuingCA().equals("External CA")) {
+ String nickname = (cdata.getNickname() != null) ? cdata.getNickname() : "caSigningCert External CA";
+ String tokenName = cdata.getToken() != null ? cdata.getToken() : token;
+ Cert certObj = new Cert(tokenName, nickname, ct);
+ ConfigurationUtils.setExternalCACert(b64, csSubsystem, cs, certObj);
+ CMS.debug("Step 2: certStr for '" + ct + "' is " + b64);
+ String certChainStr = cdata.getCertChain();
+ if (certChainStr != null) {
+ ConfigurationUtils.setExternalCACertChain(certChainStr, csSubsystem, cs, certObj);
+ CMS.debug("Step 2: certChainStr for '" + ct + "' is " + certChainStr);
+ certs.addElement(certObj);
+ } else {
+ throw new BadRequestException("CertChain not provided");
+ }
+ }
+ continue;
+ }
+ }
+ }
+
+ if (!generateServerCert && ct.equals("sslserver")) {
+ if (!cdata.getToken().equals("internal")) {
+ cs.putString(csSubsystem + ".cert.sslserver.nickname", cdata.getNickname());
+ } else {
+ cs.putString(csSubsystem + ".cert.sslserver.nickname", data.getToken() +
+ ":" + cdata.getNickname());
+ }
+ cs.putString(csSubsystem + ".sslserver.nickname", cdata.getNickname());
+ cs.putString(csSubsystem + ".sslserver.cert", cdata.getCert());
+ cs.putString(csSubsystem + ".sslserver.certreq", cdata.getRequest());
+ cs.putString(csSubsystem + ".sslserver.tokenname", cdata.getToken());
+ continue;
+ }
+
+ String keytype = (cdata.getKeyType() != null) ? cdata.getKeyType() : "rsa";
+
+ String keyalgorithm = cdata.getKeyAlgorithm();
+ if (keyalgorithm == null) {
+ keyalgorithm = (keytype.equals("ecc")) ? "SHA256withEC" : "SHA256withRSA";
+ }
+
+ String signingalgorithm = (cdata.getSigningAlgorithm() != null)? cdata.getSigningAlgorithm(): keyalgorithm ;
+ String nickname = (cdata.getNickname() != null) ? cdata.getNickname() :
+ cs.getString("preop.cert." + ct + ".nickname");
+ String dn = (cdata.getSubjectDN() != null)? cdata.getSubjectDN() :
+ cs.getString("preop.cert." + ct + ".dn");
+
+
+ cs.putString("preop.cert." + ct + ".keytype", keytype);
+ cs.putString("preop.cert." + ct + ".keyalgorithm", keyalgorithm);
+ cs.putString("preop.cert." + ct + ".signingalgorithm", signingalgorithm);
+ cs.putString("preop.cert." + ct + ".nickname", nickname);
+ cs.putString("preop.cert." + ct + ".dn", dn);
+
+ if (!data.getStepTwo()) {
+ if (keytype.equals("ecc")) {
+ String curvename = (cdata.getKeyCurveName() != null) ?
+ cdata.getKeyCurveName() : cs.getString("keys.ecc.curve.default");
+ cs.putString("preop.cert." + ct + ".curvename.name", curvename);
+ ConfigurationUtils.createECCKeyPair(token, curvename, cs, ct);
+ } else {
+ String keysize = cdata.getKeySize() != null ? cdata.getKeySize() : cs
+ .getString("keys.rsa.keysize.default");
+ cs.putString("preop.cert." + ct + ".keysize.size", keysize);
+ ConfigurationUtils.createRSAKeyPair(token, Integer.parseInt(keysize), cs, ct);
+ }
+ } else {
+ CMS.debug("configure(): step two selected. keys will not be generated for '" + ct + "'");
+ }
+
+ String tokenName = cdata.getToken() != null ? cdata.getToken() : token;
+ Cert certObj = new Cert(tokenName, nickname, ct);
+ certObj.setDN(dn);
+ certObj.setSubsystem(cs.getString("preop.cert." + ct + ".subsystem"));
+ certObj.setType(cs.getString("preop.cert." + ct + ".type"));
+
+ if (!data.getStepTwo()) {
+ ConfigurationUtils.configCert(null, null, null, certObj, null);
+ } else {
+ String subsystem = cs.getString("preop.cert." + ct + ".subsystem");
+ if (data.getStandAlone()) {
+ // Stand-alone PKI (Step 2)
+ certStr = cdata.getCert();
+ certStr = CryptoUtil.stripCertBrackets(certStr.trim());
+ certStr = CryptoUtil.normalizeCertStr(certStr);
+ cs.putString(subsystem + "." + ct + ".cert", certStr);
+ } else {
+ certStr = cs.getString(subsystem + "." + ct + ".cert" );
+ }
+
+ certObj.setCert(certStr);
+ CMS.debug("Step 2: certStr for '" + ct + "' is " + certStr);
+ }
+
+ // Handle Cert Requests for everything EXCEPT Stand-alone PKI (Step 2)
+ if (data.getStandAlone()) {
+ if (!data.getStepTwo()) {
+ // Stand-alone PKI (Step 1)
+ ConfigurationUtils.handleCertRequest(cs, ct, certObj);
+
+ CMS.debug("Stand-alone " + csType + " Admin CSR");
+ String adminSubjectDN = data.getAdminSubjectDN();
+ String certreqStr = data.getAdminCertRequest();
+ certreqStr = CryptoUtil.normalizeCertAndReq(certreqStr);
+ cs.putString("preop.cert.admin.dn", adminSubjectDN);
+ cs.putString(csSubsystem + ".admin.certreq", certreqStr);
+ cs.putString(csSubsystem + ".admin.cert", "...paste certificate here...");
+ }
+ } else {
+ ConfigurationUtils.handleCertRequest(cs, ct, certObj);
+ }
+
+ if (data.getIsClone().equals("true")) {
+ ConfigurationUtils.updateCloneConfig();
+ }
+
+ // to determine if we have the signing cert when using an external ca
+ // this will only execute on a ca or stand-alone pki
+ String b64 = cdata.getCert();
+ if ((ct.equals("signing") || ct.equals("external_signing")) && (b64!= null) && (b64.length()>0) && (!b64.startsWith("..."))) {
+ hasSigningCert = true;
+ if (data.getIssuingCA().equals("External CA")) {
+ b64 = CryptoUtil.stripCertBrackets(b64.trim());
+ certObj.setCert(CryptoUtil.normalizeCertStr(b64));
+
+ if (cdata.getCertChain() != null) {
+ certObj.setCertChain(cdata.getCertChain());
+ } else {
+ throw new BadRequestException("CertChain not provided");
+ }
+ }
+ }
+
+ certs.addElement(certObj);
+ }
+ // make sure to commit changes here for step 1
+ cs.commit(false);
+
+ } catch (NumberFormatException e) {
+ // move these validations to validate()?
+ throw new BadRequestException("Non-integer value for key size");
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ throw new BadRequestException("Invalid algorithm " + e);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Error in setting certificate names and key sizes: " + e);
+ }
+
+ // non-Stand-alone PKI submitting CSRs to external ca
+ if ((data.getIssuingCA()!= null) && data.getIssuingCA().equals("External CA") && (!hasSigningCert)) {
+ CMS.debug("Submit CSRs to external ca . . .");
+ response.setSystemCerts(SystemCertDataFactory.create(certs));
+ response.setStatus(SUCCESS);
+ return response;
+ }
+
+ Enumeration<Cert> c = certs.elements();
+ while (c.hasMoreElements()) {
+ Cert cert = c.nextElement();
+ int ret;
+ try {
+ CMS.debug("Processing '" + cert.getCertTag() + "' certificate:");
+ ret = ConfigurationUtils.handleCerts(cert);
+ ConfigurationUtils.setCertPermissions(cert.getCertTag());
+ CMS.debug("Processed '" + cert.getCertTag() + "' certificate.");
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Error in configuring system certificates" + e);
+ }
+ if (ret != 0) {
+ throw new PKIException("Error in configuring system certificates");
+ }
+ }
+ response.setSystemCerts(SystemCertDataFactory.create(certs));
+
+ // BackupKeyCertPanel/SavePKCS12Panel
+ CMS.debug("=== BackupKeyCert Panel/SavePKCS12 Panel ===");
+ if (data.getBackupKeys().equals("true")) {
+ try {
+ ConfigurationUtils.backupKeys(data.getBackupPassword(), data.getBackupFile());
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Error in creating pkcs12 to backup keys and certs: " + e);
+ }
+ }
+
+ // AdminPanel
+ CMS.debug("=== Admin Panel ===");
+ adminPanel(data, response);
+
+ // Done Panel
+ // Create or update security domain
+ CMS.debug("=== Done Panel ===");
+ try {
+ if (securityDomainType.equals(ConfigurationRequest.NEW_DOMAIN)) {
+ ConfigurationUtils.createSecurityDomain();
+ } else {
+ ConfigurationUtils.updateSecurityDomain();
+ }
+ cs.putString("service.securityDomainPort", CMS.getAgentPort());
+ cs.putString("securitydomain.store", "ldap");
+ cs.commit(false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Error while updating security domain: " + e);
+ }
+
+ // need to push connector information to the CA
+ String ca_host="";
+ try {
+ ca_host = cs.getString("preop.ca.hostname", "");
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ }
+
+ // need to push connector information to the CA
+ try {
+ if (csType.equals("KRA") && (!data.getStandAlone()) && (!ca_host.equals(""))) {
+ ConfigurationUtils.updateConnectorInfo(CMS.getAgentHost(), CMS.getAgentPort());
+ ConfigurationUtils.setupClientAuthUser();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Errors in pushing KRA connector information to the CA: " + e);
+ }
+
+ // import the CA certificate into the OCSP
+ // configure the CRL Publishing to OCSP in CA
+ try {
+ if (csType.equals("OCSP") && (!ca_host.equals(""))) {
+ CMS.reinit(IOCSPAuthority.ID);
+ ConfigurationUtils.importCACertToOCSP();
+ if (!data.getStandAlone()) {
+ ConfigurationUtils.updateOCSPConfig();
+ ConfigurationUtils.setupClientAuthUser();
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Errors in configuring CA publishing to OCSP: " + e);
+ }
+
+ if (!data.getIsClone().equals("true")) {
+ try {
+ if (csType.equals("CA") || csType.equals("KRA")) {
+ ConfigurationUtils.updateNextRanges();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Errors in updating next serial number ranges in DB: " + e);
+ }
+ }
+
+ try {
+ if (data.getIsClone().equals("true") && csType.equalsIgnoreCase("CA")
+ && ConfigurationUtils.isSDHostDomainMaster(cs)) {
+ // cloning a domain master CA, the clone is also master of its domain
+ cs.putString("securitydomain.host", CMS.getEEHost());
+ cs.putString("securitydomain.httpport", CMS.getEENonSSLPort());
+ cs.putString("securitydomain.httpsadminport", CMS.getAdminPort());
+ cs.putString("securitydomain.httpsagentport", CMS.getAgentPort());
+ cs.putString("securitydomain.httpseeport", CMS.getEESSLPort());
+ cs.putString("securitydomain.select", "new");
+
+ }
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ throw new PKIException("Errors in determining if security domain host is a master CA");
+ }
+
+ try {
+ ConfigurationUtils.setupDBUser();
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Errors in creating or updating dbuser: " + e);
+ }
+
+ if (csType.equals("TPS")) {
+ try {
+ ConfigurationUtils.addProfilesToTPSUser(data.getAdminUID());
+
+ URI secdomainURI = new URI(data.getSecurityDomainUri());
+
+ // register TPS with CA
+ URI caURI = new URI(data.getCaUri());
+ ConfigurationUtils.registerUser(secdomainURI, caURI, "ca");
+
+ // register TPS with TKS
+ URI tksURI = new URI(data.getTksUri());
+ ConfigurationUtils.registerUser(secdomainURI, tksURI, "tks");
+
+ if (data.getEnableServerSideKeyGen().equalsIgnoreCase("true")) {
+ URI kraURI = new URI(data.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(data.getImportSharedSecret()));
+
+ } catch (URISyntaxException e) {
+ throw new BadRequestException("Invalid URI for CA, TKS or KRA");
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Errors in registering TPS to CA, TKS or KRA: " + e);
+ }
+ }
+
+ cs.putInteger("cs.state", 1);
+
+ // update serial numbers for clones
+
+ // save some variables, remove remaining preops
+ try {
+ ConfigurationUtils.removePreopConfigEntries();
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ throw new PKIException("Errors when removing preop config entries: " + e);
+ }
+
+ // Create an empty file that designates the fact that although
+ // this server instance has been configured, it has NOT yet
+ // been restarted!
+ String restart_server = instanceRoot + "/conf/" + RESTART_SERVER_AFTER_CONFIGURATION;
+ Utils.exec("touch " + restart_server);
+ Utils.exec("chmod 00660 " + restart_server);
+
+ response.setStatus(SUCCESS);
+ return response;
+ }
+
+ private void caInfoPanel(ConfigurationRequest data, String subsystemNick) {
+ URI caUri = null;
+ try {
+ caUri = new URI(data.getCaUri());
+ } catch (URISyntaxException e) {
+ throw new BadRequestException("Invalid caURI " + caUri);
+ }
+ ConfigurationUtils.updateCAConnInfo(caUri, subsystemNick);
+ }
+
+ private void tksInfoPanel(ConfigurationRequest data, String subsystemNick) {
+ URI tksUri = null;
+ try {
+ tksUri = new URI(data.getTksUri());
+ } catch (URISyntaxException e) {
+ throw new BadRequestException("Invalid tksURI " + tksUri);
+ }
+
+ ConfigurationUtils.updateTKSConnInfo(tksUri, subsystemNick);
+ }
+
+ private void kraInfoPanel(ConfigurationRequest data, String subsystemNick) {
+ URI kraUri = null;
+ try {
+ kraUri = new URI(data.getCaUri());
+ } catch (URISyntaxException e) {
+ throw new BadRequestException("Invalid kraURI " + kraUri);
+ }
+ boolean keyGen = data.getEnableServerSideKeyGen().equalsIgnoreCase("true");
+ ConfigurationUtils.updateKRAConnInfo(keyGen, kraUri, subsystemNick);
+ }
+
+ private void adminPanel(ConfigurationRequest data, ConfigurationResponse response) {
+ if (!data.getIsClone().equals("true")) {
+ try {
+ X509CertImpl admincerts[] = new X509CertImpl[1];
+ ConfigurationUtils.createAdmin(data.getAdminUID(), data.getAdminEmail(),
+ data.getAdminName(), data.getAdminPassword());
+ if (data.getImportAdminCert().equalsIgnoreCase("true")) {
+ String b64 = CryptoUtil.stripCertBrackets(data.getAdminCert().trim());
+ if (data.getStandAlone() && data.getStepTwo()) {
+ // Stand-alone PKI (Step 2)
+ CMS.debug("adminPanel: Stand-alone " + csType + " Admin Cert");
+ cs.putString(csSubsystem + ".admin.cert", b64);
+ cs.commit(false);
+ }
+ // Convert Admin Cert to X509CertImpl
+ byte[] b = CryptoUtil.base64Decode(b64);
+ admincerts[0] = new X509CertImpl(b);
+ } else {
+ if (csType.equals("CA")) {
+ ConfigurationUtils.createAdminCertificate(data.getAdminCertRequest(),
+ data.getAdminCertRequestType(), data.getAdminSubjectDN());
+
+ String serialno = cs.getString("preop.admincert.serialno.0");
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(ICertificateAuthority.ID);
+ ICertificateRepository repo = ca.getCertificateRepository();
+ admincerts[0] = repo.getX509Certificate(new BigInteger(serialno, 16));
+ } else {
+ String type = cs.getString("preop.ca.type", "");
+ String ca_hostname = "";
+ int ca_port = -1;
+ if (type.equals("sdca")) {
+ ca_hostname = cs.getString("preop.ca.hostname");
+ ca_port = cs.getInteger("preop.ca.httpsport");
+ } else {
+ ca_hostname = cs.getString("securitydomain.host", "");
+ ca_port = cs.getInteger("securitydomain.httpseeport");
+ }
+ String b64 = ConfigurationUtils.submitAdminCertRequest(ca_hostname, ca_port,
+ data.getAdminProfileID(), data.getAdminCertRequestType(),
+ data.getAdminCertRequest(), data.getAdminSubjectDN());
+ b64 = CryptoUtil.stripCertBrackets(b64.trim());
+ byte[] b = CryptoUtil.base64Decode(b64);
+ admincerts[0] = new X509CertImpl(b);
+ }
+ }
+ CMS.reinit(IUGSubsystem.ID);
+
+ IUGSubsystem ug = (IUGSubsystem) CMS.getSubsystem(IUGSubsystem.ID);
+ IUser user = ug.getUser(data.getAdminUID());
+ user.setX509Certificates(admincerts);
+ ug.addUserCert(user);
+ response.setAdminCert(admincerts[0]);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Error in creating admin user: " + e);
+ }
+ }
+ }
+
+ private void databasePanel(ConfigurationRequest data) {
+ cs.putString("internaldb.ldapconn.host", data.getDsHost());
+ cs.putString("internaldb.ldapconn.port", data.getDsPort());
+ cs.putString("internaldb.database", data.getDatabase());
+ cs.putString("internaldb.basedn", data.getBaseDN());
+ cs.putString("internaldb.ldapauth.bindDN", data.getBindDN());
+ cs.putString("internaldb.ldapconn.secureConn", (data.getSecureConn().equals("on") ? "true" : "false"));
+ cs.putString("preop.database.removeData", data.getRemoveData());
+
+ if (csType.equals("TPS")) {
+ cs.putString("tokendb.activityBaseDN", "ou=Activities," + data.getBaseDN());
+ cs.putString("tokendb.baseDN", "ou=Tokens," + data.getBaseDN());
+ cs.putString("tokendb.certBaseDN", "ou=Certificates," + data.getBaseDN());
+ cs.putString("tokendb.userBaseDN", data.getBaseDN());
+ cs.putString("tokendb.hostport", data.getDsHost() + ":" + data.getDsPort());
+ }
+
+ try {
+ cs.commit(false);
+ } catch (EBaseException e2) {
+ e2.printStackTrace();
+ throw new PKIException("Unable to commit config parameters to file");
+ }
+
+ if (data.getIsClone().equals("true")) {
+ String masterhost = "";
+ String masterport = "";
+ String masterbasedn = "";
+ String realhostname = "";
+ try {
+ masterhost = cs.getString("preop.internaldb.master.ldapconn.host", "");
+ masterport = cs.getString("preop.internaldb.master.ldapconn.port", "");
+ masterbasedn = cs.getString("preop.internaldb.master.basedn", "");
+ realhostname = cs.getString("machineName", "");
+ } catch (Exception e) {
+ }
+
+ if (masterhost.equals(realhostname) && masterport.equals(data.getDsPort())) {
+ throw new BadRequestException("Master and clone must not share the same internal database");
+ }
+
+ if (!masterbasedn.equals(data.getBaseDN())) {
+ throw new BadRequestException("Master and clone should have the same base DN");
+ }
+
+ String masterReplicationPort = data.getMasterReplicationPort();
+ if ((masterReplicationPort != null) && (!masterReplicationPort.equals(""))) {
+ cs.putString("internaldb.ldapconn.masterReplicationPort", masterReplicationPort);
+ } else {
+ cs.putString("internaldb.ldapconn.masterReplicationPort", masterport);
+ }
+
+ String cloneReplicationPort = data.getCloneReplicationPort();
+ if ((cloneReplicationPort == null) || (cloneReplicationPort.length() == 0)) {
+ cloneReplicationPort = data.getDsPort();
+ }
+ cs.putString("internaldb.ldapconn.cloneReplicationPort", cloneReplicationPort);
+
+ String replicationSecurity = data.getReplicationSecurity();
+ if ((cloneReplicationPort == data.getDsPort()) && (data.getSecureConn().equals("on"))) {
+ replicationSecurity = "SSL";
+ } else if (replicationSecurity == null) {
+ replicationSecurity = "None";
+ }
+ cs.putString("internaldb.ldapconn.replicationSecurity", replicationSecurity);
+
+ cs.putString("preop.internaldb.replicateSchema", data.getReplicateSchema());
+ }
+
+ try {
+ /* BZ 430745 create password for replication manager */
+ String replicationpwd = Integer.toString(new Random().nextInt());
+
+ IConfigStore psStore = null;
+ String passwordFile = null;
+ passwordFile = cs.getString("passwordFile");
+ psStore = CMS.createFileConfigStore(passwordFile);
+ psStore.putString("internaldb", data.getBindpwd());
+ psStore.putString("replicationdb", replicationpwd);
+ psStore.commit(false);
+
+ if (!data.getStepTwo()) {
+ ConfigurationUtils.populateDB();
+
+ cs.putString("preop.internaldb.replicationpwd", replicationpwd);
+ cs.putString("preop.database.removeData", "false");
+ cs.commit(false);
+
+ if (data.getIsClone().equals("true")) {
+ CMS.debug("Start setting up replication.");
+ ConfigurationUtils.setupReplication();
+ }
+
+ ConfigurationUtils.reInitSubsystem(csType);
+ ConfigurationUtils.populateDBManager();
+ ConfigurationUtils.populateVLVIndexes();
+ }
+ } catch (Exception e) {
+ throw new PKIException("Error in populating database" + e);
+ }
+ }
+
+ private void hierarchyPanel(ConfigurationRequest data) {
+ if (csType.equals("CA") && data.getIsClone().equals("false")) {
+ if (data.getHierarchy().equals("root")) {
+ cs.putString("preop.hierarchy.select", "root");
+ cs.putString("hierarchy.select", "Root");
+ cs.putString("preop.ca.type", "sdca");
+ } else if (data.getHierarchy().equals("join")) {
+ cs.putString("preop.cert.signing.type", "remote");
+ cs.putString("preop.hierarchy.select", "join");
+ cs.putString("hierarchy.select", "Subordinate");
+ } else {
+ throw new BadRequestException("Invalid hierarchy provided");
+ }
+ }
+ }
+
+ private void getCloningData(ConfigurationRequest data, String certList, String token, String domainXML) {
+ StringTokenizer t = new StringTokenizer(certList, ",");
+ while (t.hasMoreTokens()) {
+ String tag = t.nextToken();
+ if (tag.equals("sslserver")) {
+ cs.putBoolean("preop.cert." + tag + ".enable", true);
+ } else {
+ cs.putBoolean("preop.cert." + tag + ".enable", false);
+ }
+ }
+
+ String cloneUri = data.getCloneUri();
+ URL url = null;
+ try {
+ url = new URL(cloneUri);
+ } catch (MalformedURLException e) {
+ // should not reach here as this check is done in validate()
+ }
+ String masterHost = url.getHost();
+ int masterPort = url.getPort();
+
+ // check and store cloneURI information
+ boolean validCloneUri;
+ try {
+ validCloneUri = ConfigurationUtils.isValidCloneURI(domainXML, masterHost, masterPort);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Error in determining whether clone URI is valid");
+ }
+
+ if (!validCloneUri) {
+ throw new BadRequestException(
+ "Invalid clone URI provided. Does not match the available subsystems in the security domain");
+ }
+
+ if (csType.equals("CA")) {
+ try {
+ int masterAdminPort = ConfigurationUtils.getPortFromSecurityDomain(domainXML,
+ masterHost, masterPort, "CA", "SecurePort", "SecureAdminPort");
+ ConfigurationUtils.importCertChain(masterHost, masterAdminPort, "/ca/admin/ca/getCertChain",
+ "clone");
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Failed to import certificate chain from master" + e);
+ }
+ }
+
+ try {
+ ConfigurationUtils.getConfigEntriesFromMaster();
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Failed to obtain configuration entries from the master for cloning " + e);
+ }
+
+ // restore certs from P12 file
+ if (token.equals(ConfigurationRequest.TOKEN_DEFAULT)) {
+ String p12File = data.getP12File();
+ String p12Pass = data.getP12Password();
+ try {
+ ConfigurationUtils.restoreCertsFromP12(p12File, p12Pass);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Failed to restore certificates from p12 file" + e);
+ }
+ }
+
+ boolean cloneReady = ConfigurationUtils.isCertdbCloned();
+ if (!cloneReady) {
+ CMS.debug("clone does not have all the certificates.");
+ throw new PKIException("Clone does not have all the required certificates");
+ }
+ }
+
+ private String securityDomainPanel(ConfigurationRequest data, String securityDomainType) {
+ String domainXML = null;
+ String securityDomainName = data.getSecurityDomainName();
+ String securityDomainURL = data.getSecurityDomainUri();
+
+ if (securityDomainType.equals(ConfigurationRequest.NEW_DOMAIN)) {
+ cs.putString("preop.securitydomain.select", "new");
+ cs.putString("securitydomain.select", "new");
+ cs.putString("preop.securitydomain.name", securityDomainName);
+ cs.putString("securitydomain.name", securityDomainName);
+ cs.putString("securitydomain.host", CMS.getEENonSSLHost());
+ cs.putString("securitydomain.httpport", CMS.getEENonSSLPort());
+ cs.putString("securitydomain.httpsagentport", CMS.getAgentPort());
+ cs.putString("securitydomain.httpseeport", CMS.getEESSLPort());
+ cs.putString("securitydomain.httpsadminport", CMS.getAdminPort());
+ // Stand-alone PKI (Step 1)
+ if (data.getStandAlone()) {
+ cs.putString("preop.cert.subsystem.type", "remote");
+ } else {
+ cs.putString("preop.cert.subsystem.type", "local");
+ }
+ cs.putString("preop.cert.subsystem.profile", "subsystemCert.profile");
+ } else {
+ cs.putString("preop.securitydomain.select", "existing");
+ cs.putString("securitydomain.select", "existing");
+ cs.putString("preop.cert.subsystem.type", "remote");
+ cs.putString("preop.cert.subsystem.profile", "caInternalAuthSubsystemCert");
+
+ // contact and log onto security domain
+ URL secdomainURL;
+ String host;
+ int port;
+ try {
+ secdomainURL = new URL(securityDomainURL);
+ host = secdomainURL.getHost();
+ port = secdomainURL.getPort();
+ cs.putString("securitydomain.host", host);
+ cs.putInteger("securitydomain.httpsadminport",port);
+ ConfigurationUtils.importCertChain(host, port, "/ca/admin/ca/getCertChain", "securitydomain");
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Failed to import certificate chain from security domain master: " + e);
+ }
+
+ // log onto security domain and get token
+ String user = data.getSecurityDomainUser();
+ String pass = data.getSecurityDomainPassword();
+ String installToken;
+ try {
+ installToken = ConfigurationUtils.getInstallToken(host, port, user, pass);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Failed to obtain installation token from security domain: " + e);
+ }
+
+ if (installToken == null) {
+ throw new PKIException("Failed to obtain installation token from security domain");
+ }
+ CMS.setConfigSDSessionId(installToken);
+
+ try {
+ domainXML = ConfigurationUtils.getDomainXML(host, port, true);
+ ConfigurationUtils.getSecurityDomainPorts(domainXML, host, port);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException("Failed to obtain security domain decriptor from security domain master: " + e);
+ }
+ }
+ return domainXML;
+ }
+
+ private void tokenPanel(ConfigurationRequest data, String token) {
+ cs.putString("preop.module.token", token);
+
+ if (! token.equals(ConfigurationRequest.TOKEN_DEFAULT)) {
+ try {
+ CryptoManager cryptoManager = CryptoManager.getInstance();
+ CryptoToken ctoken = cryptoManager.getTokenByName(token);
+ String tokenpwd = data.getTokenPassword();
+ ConfigurationUtils.loginToken(ctoken, tokenpwd);
+ } catch (NotInitializedException e) {
+ throw new PKIException("Token is not initialized");
+ } catch (NoSuchTokenException e) {
+ throw new BadRequestException("Invalid Token provided. No such token.");
+ } catch (TokenException e) {
+ e.printStackTrace();
+ throw new PKIException("Token Exception" + e);
+ } catch (IncorrectPasswordException e) {
+ throw new BadRequestException("Incorrect Password provided for token.");
+ }
+ }
+ }
+
+ private void validateData(ConfigurationRequest data) {
+ // get required info from CS.cfg
+ String preopPin;
+ try {
+ preopPin = cs.getString("preop.pin");
+ } catch (Exception e) {
+ CMS.debug("validateData: Failed to get required config form CS.cfg");
+ e.printStackTrace();
+ throw new PKIException("Unable to retrieve required configuration from configuration files");
+ }
+
+ // get the preop pin and validate it
+ String pin = data.getPin();
+ if (pin == null) {
+ throw new BadRequestException("No preop pin provided");
+ }
+ if (!preopPin.equals(pin)) {
+ throw new BadRequestException("Incorrect pin provided");
+ }
+
+ // validate legal stand-alone PKI subsystems
+ if (data.getStandAlone()) {
+ // ADD checks for valid types of Stand-alone PKI subsystems here
+ // AND to the 'checkStandalonePKI()' Python method of
+ // the 'ConfigurationFile' Python class in the Python file called
+ // 'pkihelper.py'
+ if (!csType.equals("KRA")) {
+ throw new BadRequestException("Stand-alone PKI " + csType + " subsystems are currently NOT supported!");
+ }
+ if ((data.getIsClone() != null) && (data.getIsClone().equals("true"))) {
+ throw new BadRequestException("A stand-alone PKI subsystem cannot be a clone");
+ }
+ }
+
+ // validate security domain settings
+ String domainType = data.getSecurityDomainType();
+ if (domainType == null) {
+ throw new BadRequestException("Security Domain Type not provided");
+ }
+
+ if (domainType.equals(ConfigurationRequest.NEW_DOMAIN)) {
+ if (!(data.getStandAlone() || csType.equals("CA"))) {
+ throw new BadRequestException("New Domain is only valid for stand-alone PKI or CA subsytems");
+ }
+ if (data.getSecurityDomainName() == null) {
+ throw new BadRequestException("Security Domain Name is not provided");
+ }
+ } else if (domainType.equals(ConfigurationRequest.EXISTING_DOMAIN)) {
+ if (data.getStandAlone()) {
+ throw new BadRequestException("Existing security domains are not valid for stand-alone PKI subsytems");
+ }
+
+ String domainURI = data.getSecurityDomainUri();
+ if (domainURI == null) {
+ throw new BadRequestException("Existing security domain requested, but no security domain URI provided");
+ }
+
+ try {
+ @SuppressWarnings("unused")
+ URL admin_u = new URL(domainURI); // check for invalid URL
+ } catch (MalformedURLException e) {
+ throw new BadRequestException("Invalid security domain URI");
+ }
+ if ((data.getSecurityDomainUser() == null) || (data.getSecurityDomainPassword() == null)) {
+ throw new BadRequestException("Security domain user or password not provided");
+ }
+
+ } else {
+ throw new BadRequestException("Invalid security domain URI provided");
+ }
+
+ if ((data.getSubsystemName() == null) || (data.getSubsystemName().length() ==0)) {
+ throw new BadRequestException("Invalid or no subsystem name provided");
+ }
+
+ if ((data.getIsClone() != null) && (data.getIsClone().equals("true"))) {
+ String cloneUri = data.getCloneUri();
+ if (cloneUri == null) {
+ throw new BadRequestException("Clone selected, but no clone URI provided");
+ }
+ try {
+ @SuppressWarnings("unused")
+ URL url = new URL(cloneUri); // check for invalid URL
+ // confirm protocol is https
+ } catch (MalformedURLException e) {
+ throw new BadRequestException("Invalid clone URI");
+ }
+
+ if (data.getToken().equals(ConfigurationRequest.TOKEN_DEFAULT)) {
+ if (data.getP12File() == null) {
+ throw new BadRequestException("P12 filename not provided");
+ }
+
+ if (data.getP12Password() == null) {
+ throw new BadRequestException("P12 password not provided");
+ }
+ }
+ } else {
+ data.setIsClone("false");
+ }
+
+ String dsHost = data.getDsHost();
+ if (dsHost == null || dsHost.length() == 0) {
+ throw new BadRequestException("Internal database host not provided");
+ }
+
+ try {
+ Integer.parseInt(data.getDsPort()); // check for errors
+ } catch (NumberFormatException e) {
+ throw new BadRequestException("Internal database port is invalid");
+ }
+
+ String basedn = data.getBaseDN();
+ if (basedn == null || basedn.length() == 0) {
+ throw new BadRequestException("Internal database basedn not provided");
+ }
+
+ String binddn = data.getBindDN();
+ if (binddn == null || binddn.length() == 0) {
+ throw new BadRequestException("Internal database basedn not provided");
+ }
+
+ String database = data.getDatabase();
+ if (database == null || database.length() == 0) {
+ throw new BadRequestException("Internal database database name not provided");
+ }
+
+ String bindpwd = data.getBindpwd();
+ if (bindpwd == null || bindpwd.length() == 0) {
+ throw new BadRequestException("Internal database database name not provided");
+ }
+
+ String masterReplicationPort = data.getMasterReplicationPort();
+ if (masterReplicationPort != null && masterReplicationPort.length() > 0) {
+ try {
+ Integer.parseInt(masterReplicationPort); // check for errors
+ } catch (NumberFormatException e) {
+ throw new BadRequestException("Master replication port is invalid");
+ }
+ }
+
+ String cloneReplicationPort = data.getCloneReplicationPort();
+ if (cloneReplicationPort != null && cloneReplicationPort.length() > 0) {
+ try {
+ Integer.parseInt(cloneReplicationPort); // check for errors
+ } catch (Exception e) {
+ throw new BadRequestException("Clone replication port is invalid");
+ }
+ }
+
+ if ((data.getReplicateSchema() != null) && (data.getReplicateSchema().equalsIgnoreCase("false"))) {
+ data.setReplicateSchema("false");
+ } else {
+ data.setReplicateSchema("true");
+ }
+
+ if ((data.getBackupKeys() != null) && data.getBackupKeys().equals("true")) {
+ if ((data.getBackupFile() == null) || (data.getBackupFile().length()<=0)) {
+ //TODO: also check for valid path, perhaps by touching file there
+ throw new BadRequestException("Invalid key backup file name");
+ }
+
+ if ((data.getBackupPassword() == null) || (data.getBackupPassword().length()<8)) {
+ throw new BadRequestException("key backup password must be at least 8 characters");
+ }
+ } else {
+ data.setBackupKeys("false");
+ }
+
+ if (csType.equals("CA") && (data.getHierarchy() == null)) {
+ throw new BadRequestException("Hierarchy is required for CA, not provided");
+ }
+
+ if (data.getIsClone().equals("false")) {
+ if ((data.getAdminUID() == null) || (data.getAdminUID().length() == 0)) {
+ throw new BadRequestException("Admin UID not provided");
+ }
+ if ((data.getAdminPassword() == null) || (data.getAdminPassword().length() == 0)) {
+ throw new BadRequestException("Admin Password not provided");
+ }
+ if ((data.getAdminEmail() == null) || (data.getAdminEmail().length() == 0)) {
+ throw new BadRequestException("Admin UID not provided");
+ }
+ if ((data.getAdminName() == null) || (data.getAdminName().length() == 0)) {
+ throw new BadRequestException("Admin name not provided");
+ }
+
+ if (data.getImportAdminCert() == null) {
+ data.setImportAdminCert("false");
+ }
+
+ if (data.getImportAdminCert().equalsIgnoreCase("true")) {
+ if (data.getAdminCert() == null) {
+ throw new BadRequestException("Admin Cert not provided");
+ }
+ } else {
+ if ((data.getAdminCertRequest() == null) || (data.getAdminCertRequest().length() == 0)) {
+ throw new BadRequestException("Admin cert request not provided");
+ }
+ if ((data.getAdminCertRequestType() == null) || (data.getAdminCertRequestType().length() == 0)) {
+ throw new BadRequestException("Admin cert request type not provided");
+ }
+ if ((data.getAdminSubjectDN() == null) || (data.getAdminSubjectDN().length() == 0)) {
+ throw new BadRequestException("Admin subjectDN not provided");
+ }
+ }
+ }
+
+ if (data.getGenerateServerCert() == null) {
+ data.setGenerateServerCert("true");
+ }
+
+ if (csType.equals("TPS")) {
+ if ((data.getCaUri() == null) || data.getCaUri().isEmpty()) {
+ throw new BadRequestException("CA URI not provided");
+ }
+ try {
+ @SuppressWarnings("unused")
+ URI ca_uri = new URI(data.getCaUri());
+ } catch (URISyntaxException e) {
+ throw new BadRequestException("Invalid CA URI");
+ }
+
+ if ((data.getTksUri() == null) || data.getTksUri().isEmpty()) {
+ throw new BadRequestException("TKS URI not provided");
+ }
+ try {
+ @SuppressWarnings("unused")
+ URI tks_uri = new URI(data.getTksUri());
+ } catch (URISyntaxException e) {
+ throw new BadRequestException("Invalid TKS URI");
+ }
+
+ if (data.getEnableServerSideKeyGen().equalsIgnoreCase("true")) {
+ if ((data.getKraUri() == null) || data.getKraUri().isEmpty()) {
+ throw new BadRequestException("KRA URI required if server-side key generation requested");
+ }
+ try {
+ @SuppressWarnings("unused")
+ URI kra_uri = new URI(data.getKraUri());
+ } catch (URISyntaxException e) {
+ throw new BadRequestException("Invalid KRA URI");
+ }
+ }
+
+ if ((data.getAuthdbBaseDN()==null) || data.getAuthdbBaseDN().isEmpty()) {
+ throw new BadRequestException("Authentication Database baseDN not provided");
+ }
+ if ((data.getAuthdbHost()==null) || data.getAuthdbHost().isEmpty()) {
+ throw new BadRequestException("Authentication Database hostname not provided");
+ }
+ if ((data.getAuthdbPort()==null) || data.getAuthdbPort().isEmpty()) {
+ throw new BadRequestException("Authentication Database port not provided");
+ }
+ if ((data.getAuthdbSecureConn()==null) || data.getAuthdbSecureConn().isEmpty()) {
+ throw new BadRequestException("Authentication Database secure conn not provided");
+ }
+
+ try {
+ Integer.parseInt(data.getAuthdbPort()); // check for errors
+ } catch (NumberFormatException e) {
+ throw new BadRequestException("Authdb port is invalid");
+ }
+
+ // TODO check connection with authdb
+
+ if (data.getImportSharedSecret().equalsIgnoreCase("true")) {
+ data.setImportSharedSecret("true");
+ } else {
+ data.setImportSharedSecret("false");
+ }
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/TKSInfoPanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/TKSInfoPanel.java
new file mode 100644
index 000000000..cb7667193
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/TKSInfoPanel.java
@@ -0,0 +1,145 @@
+package com.netscape.cms.servlet.csadmin;
+
+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.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);
+ }
+
+ ConfigurationUtils.updateTKSConnInfo(tksUri, subsystemNick);
+ context.put("updateStatus", "success");
+ }
+
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/TokenAuthenticate.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/TokenAuthenticate.java
new file mode 100644
index 000000000..745962c72
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/TokenAuthenticate.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISecurityDomainSessionTable;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cmsutil.xml.XMLObject;
+
+public class TokenAuthenticate extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -9098593390260940853L;
+ private final static String SUCCESS = "0";
+
+ public TokenAuthenticate() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+ IConfigStore config = CMS.getConfigStore();
+
+ String sessionId = httpReq.getParameter("sessionID");
+ CMS.debug("TokenAuthentication: sessionId=" + sessionId);
+ String givenHost = httpReq.getParameter("hostname");
+ CMS.debug("TokenAuthentication: givenHost=" + givenHost);
+
+ boolean checkIP = false;
+ try {
+ checkIP = config.getBoolean("securitydomain.checkIP", false);
+ } catch (Exception e) {
+ }
+
+ ISecurityDomainSessionTable table = CMS.getSecurityDomainSessionTable();
+ String uid = "";
+ String gid = "";
+ CMS.debug("TokenAuthentication: checking session in the session table");
+ if (table.isSessionIdExist(sessionId)) {
+ CMS.debug("TokenAuthentication: found session");
+ if (checkIP) {
+ String hostname = table.getIP(sessionId);
+ if (!hostname.equals(givenHost)) {
+ CMS.debug("TokenAuthentication: hostname=" + hostname + " and givenHost="
+ + givenHost + " are different");
+ CMS.debug("TokenAuthenticate authenticate failed, wrong hostname.");
+ outputError(httpResp, "Error: Failed Authentication");
+ return;
+ }
+ }
+
+ uid = table.getUID(sessionId);
+ gid = table.getGroup(sessionId);
+ } else {
+ CMS.debug("TokenAuthentication: session not found");
+ CMS.debug("TokenAuthentication authenticate failed, session id does not exist.");
+ outputError(httpResp, "Error: Failed Authentication");
+ return;
+ }
+
+ CMS.debug("TokenAuthenticate successfully authenticate");
+ try {
+ XMLObject xmlObj = null;
+
+ xmlObj = new XMLObject();
+
+ Node root = xmlObj.createRoot("XMLResponse");
+
+ xmlObj.addItemToContainer(root, "Status", SUCCESS);
+ xmlObj.addItemToContainer(root, "uid", uid);
+ xmlObj.addItemToContainer(root, "gid", gid);
+ byte[] cb = xmlObj.toByteArray();
+
+ outputResult(httpResp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("Failed to send the XML output");
+ }
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java
new file mode 100644
index 000000000..b2d081f22
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateConnector.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.jboss.resteasy.spi.BadRequestException;
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.system.KRAConnectorInfo;
+import com.netscape.cms.servlet.admin.KRAConnectorProcessor;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+import com.netscape.cmsutil.xml.XMLObject;
+
+public class UpdateConnector extends CMSServlet {
+
+ private static final long serialVersionUID = 972871860008509849L;
+ private final static String SUCCESS = "0";
+ private final static String FAILED = "1";
+ private final static String AUTH_FAILURE = "2";
+
+ public UpdateConnector() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ CMS.debug("UpdateConnector: initializing...");
+ super.init(sc);
+ CMS.debug("UpdateConnector: done initializing...");
+ }
+
+ public KRAConnectorInfo createConnectorInfo(HttpServletRequest httpReq) {
+ KRAConnectorInfo info = new KRAConnectorInfo();
+ info.setHost(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".host"));
+ info.setPort(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".port"));
+ info.setTimeout(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".timeout"));
+ info.setTransportCert(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".transportCert"));
+ info.setUri(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".uri"));
+ info.setLocal(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".local"));
+ info.setEnable(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".enable"));
+ return info;
+ }
+
+ /**
+ * Process the HTTP request.
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ CMS.debug("UpdateConnector: processing...");
+
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = null;
+ try {
+ authToken = authenticate(cmsReq);
+ CMS.debug("UpdateConnector authentication successful.");
+ } catch (Exception e) {
+ CMS.debug("UpdateConnector: authentication failed.");
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "",
+ e.toString()));
+ outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated",
+ null);
+ return;
+ }
+
+ if (authToken == null) {
+ CMS.debug("UpdateConnector: authentication failed.");
+ outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated",
+ null);
+ return;
+ }
+
+ AuthzToken authzToken = null;
+ try {
+ authzToken = authorize(mAclMethod, authToken, mAuthzResourceName,
+ "modify");
+ CMS.debug("UpdateConnector authorization successful.");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp,
+ "Error: Encountered problem during authorization.");
+ return;
+ }
+
+ if (authzToken == null) {
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ }
+
+ String status = SUCCESS;
+ String error = "";
+ KRAConnectorProcessor processor = new KRAConnectorProcessor(getLocale(httpReq));
+ KRAConnectorInfo info = createConnectorInfo(httpReq);
+ try {
+ processor.addConnector(info);
+ } catch (BadRequestException | PKIException e) {
+ status = FAILED;
+ error = e.getMessage();
+ }
+
+ // send success status back to the requestor
+ try {
+ CMS.debug("UpdateConnector: Sending response");
+ XMLObject xmlObj = new XMLObject();
+ Node root = xmlObj.createRoot("XMLResponse");
+ if (status.equals(SUCCESS)) {
+ xmlObj.addItemToContainer(root, "Status", SUCCESS);
+ } else {
+ xmlObj.addItemToContainer(root, "Status", FAILED);
+ xmlObj.addItemToContainer(root, "Error", error);
+ }
+
+ byte[] cb = xmlObj.toByteArray();
+
+ outputResult(httpResp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("UpdateConnector: Failed to send the XML output");
+ }
+ }
+
+ protected void setDefaultTemplates(ServletConfig sc) {
+ }
+
+ protected void renderTemplate(
+ CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler)
+ throws IOException {// do nothing
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java
new file mode 100644
index 000000000..b783c359b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java
@@ -0,0 +1,570 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+import com.netscape.cmsutil.xml.XMLObject;
+
+public class UpdateDomainXML extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 4059169588555717548L;
+ private final static String SUCCESS = "0";
+ private final static String FAILED = "1";
+ private final static String LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE =
+ "LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE_1";
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_ROLE =
+ "LOGGING_SIGNED_AUDIT_CONFIG_ROLE_3";
+
+ public UpdateDomainXML() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ CMS.debug("UpdateDomainXML: initializing...");
+ super.init(sc);
+ CMS.debug("UpdateDomainXML: done initializing...");
+ }
+
+ private String remove_from_ldap(String dn) {
+ CMS.debug("UpdateDomainXML: delete_from_ldap: starting dn: " + dn);
+ String status = SUCCESS;
+ ILdapConnFactory connFactory = null;
+ LDAPConnection conn = null;
+ IConfigStore cs = CMS.getConfigStore();
+
+ try {
+ IConfigStore ldapConfig = cs.getSubStore("internaldb");
+ connFactory = CMS.getLdapBoundConnFactory();
+ connFactory.init(ldapConfig);
+ conn = connFactory.getConn();
+ conn.delete(dn);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() != LDAPException.NO_SUCH_OBJECT) {
+ status = FAILED;
+ CMS.debug("Failed to delete entry" + e.toString());
+ }
+ } catch (Exception e) {
+ CMS.debug("Failed to delete entry" + e.toString());
+ } finally {
+ try {
+ if ((conn != null) && (connFactory != null)) {
+ CMS.debug("Releasing ldap connection");
+ connFactory.returnConn(conn);
+ }
+ } catch (Exception e) {
+ CMS.debug("Error releasing the ldap connection" + e.toString());
+ }
+ }
+ return status;
+ }
+
+ private String modify_ldap(String dn, LDAPModification mod) {
+ CMS.debug("UpdateDomainXML: modify_ldap: starting dn: " + dn);
+ String status = SUCCESS;
+ ILdapConnFactory connFactory = null;
+ LDAPConnection conn = null;
+ IConfigStore cs = CMS.getConfigStore();
+
+ try {
+ IConfigStore ldapConfig = cs.getSubStore("internaldb");
+ connFactory = CMS.getLdapBoundConnFactory();
+ connFactory.init(ldapConfig);
+ conn = connFactory.getConn();
+ conn.modify(dn, mod);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() != LDAPException.NO_SUCH_OBJECT) {
+ status = FAILED;
+ CMS.debug("Failed to modify entry" + e.toString());
+ }
+ } catch (Exception e) {
+ CMS.debug("Failed to modify entry" + e.toString());
+ } finally {
+ try {
+ if ((conn != null) && (connFactory != null)) {
+ CMS.debug("Releasing ldap connection");
+ connFactory.returnConn(conn);
+ }
+ } catch (Exception e) {
+ CMS.debug("Error releasing the ldap connection" + e.toString());
+ }
+ }
+ return status;
+ }
+
+ private String add_to_ldap(LDAPEntry entry, String dn) {
+ CMS.debug("UpdateDomainXML: add_to_ldap: starting");
+ String status = SUCCESS;
+ ILdapConnFactory connFactory = null;
+ LDAPConnection conn = null;
+ IConfigStore cs = CMS.getConfigStore();
+
+ try {
+ IConfigStore ldapConfig = cs.getSubStore("internaldb");
+ connFactory = CMS.getLdapBoundConnFactory();
+ connFactory.init(ldapConfig);
+ conn = connFactory.getConn();
+ conn.add(entry);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) {
+ CMS.debug("UpdateDomainXML: Entry already exists");
+ try {
+ conn.delete(dn);
+ conn.add(entry);
+ } catch (LDAPException ee) {
+ CMS.debug("UpdateDomainXML: Error when replacing existing entry " + ee.toString());
+ status = FAILED;
+ }
+ } else {
+ CMS.debug("UpdateDomainXML: Failed to update ldap domain info. Exception: " + e.toString());
+ status = FAILED;
+ }
+ } catch (Exception e) {
+ CMS.debug("Failed to add entry" + e.toString());
+ } finally {
+ try {
+ if ((conn != null) && (connFactory != null)) {
+ CMS.debug("Releasing ldap connection");
+ connFactory.returnConn(conn);
+ }
+ } catch (Exception e) {
+ CMS.debug("Error releasing the ldap connection" + e.toString());
+ }
+ }
+ return status;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param op 'downloadBIN' - return the binary certificate chain
+ * <li>http.param op 'displayIND' - display pretty-print of certificate chain components
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ CMS.debug("UpdateDomainXML: processing...");
+ String status = SUCCESS;
+ String status2 = SUCCESS;
+
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ CMS.debug("UpdateDomainXML process: authentication starts");
+ IAuthToken authToken = null;
+ try {
+ authToken = authenticate(cmsReq);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "",
+ e.toString()));
+ outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated",
+ null);
+ return;
+ }
+ if (authToken == null) {
+ CMS.debug("UpdateDomainXML process: authToken is null");
+ outputError(httpResp, AUTH_FAILURE, "Error: not authenticated",
+ null);
+ return;
+ }
+ CMS.debug("UpdateDomainXML process: authentication done");
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken, mAuthzResourceName,
+ "modify");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp,
+ "Error: Encountered problem during authorization.");
+ return;
+ }
+ if (authzToken == null) {
+ CMS.debug("UpdateDomainXML process: authorization error");
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ }
+
+ String list = httpReq.getParameter("list");
+ String type = httpReq.getParameter("type");
+ String host = httpReq.getParameter("host");
+ String name = httpReq.getParameter("name");
+ String sport = httpReq.getParameter("sport");
+ String agentsport = httpReq.getParameter("agentsport");
+ String adminsport = httpReq.getParameter("adminsport");
+ String eecaport = httpReq.getParameter("eeclientauthsport");
+ String httpport = httpReq.getParameter("httpport");
+ String domainmgr = httpReq.getParameter("dm");
+ String clone = httpReq.getParameter("clone");
+ String operation = httpReq.getParameter("operation");
+
+ // ensure required parameters are present
+ // especially important for DS syntax checking
+ String missing = "";
+ if ((host == null) || host.equals("")) {
+ missing += " host ";
+ }
+ if ((name == null) || name.equals("")) {
+ missing += " name ";
+ }
+ if ((sport == null) || sport.equals("")) {
+ missing += " sport ";
+ }
+ if ((type == null) || type.equals("")) {
+ missing += " type ";
+ }
+ if ((clone == null) || clone.equals("")) {
+ clone = "false";
+ }
+
+ if (!missing.equals("")) {
+ CMS.debug("UpdateDomainXML process: required parameters:" + missing +
+ "not provided in request");
+ outputError(httpResp, "Error: required parameters: " + missing +
+ "not provided in request");
+ return;
+ }
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditParams = "host;;" + host + "+name;;" + name + "+sport;;" + sport +
+ "+clone;;" + clone + "+type;;" + type;
+ if (operation != null) {
+ auditParams += "+operation;;" + operation;
+ } else {
+ auditParams += "+operation;;add";
+ }
+
+ String basedn = null;
+ String secstore = null;
+
+ IConfigStore cs = CMS.getConfigStore();
+
+ try {
+ basedn = cs.getString("internaldb.basedn");
+ secstore = cs.getString("securitydomain.store");
+ } catch (Exception e) {
+ CMS.debug("Unable to determine security domain name or basedn. Please run the domaininfo migration script");
+ }
+
+ if ((basedn != null) && (secstore != null) && (secstore.equals("ldap"))) {
+ // update in ldap
+
+ LDAPEntry entry = null;
+ String listName = type + "List";
+ String cn = host + ":";
+
+ if ((adminsport != null) && (adminsport != "")) {
+ cn += adminsport;
+ } else {
+ cn += sport;
+ }
+
+ String dn = "cn=" + cn + ",cn=" + listName + ",ou=Security Domain," + basedn;
+ CMS.debug("UpdateDomainXML: updating LDAP entry: " + dn);
+
+ LDAPAttributeSet attrs = null;
+ attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass", "top"));
+ attrs.add(new LDAPAttribute("objectclass", "pkiSubsystem"));
+ attrs.add(new LDAPAttribute("cn", cn));
+ attrs.add(new LDAPAttribute("Host", host));
+ attrs.add(new LDAPAttribute("SecurePort", sport));
+
+ if ((agentsport != null) && (!agentsport.equals(""))) {
+ attrs.add(new LDAPAttribute("SecureAgentPort", agentsport));
+ }
+ if ((adminsport != null) && (!adminsport.equals(""))) {
+ attrs.add(new LDAPAttribute("SecureAdminPort", adminsport));
+ }
+ if ((httpport != null) && (!httpport.equals(""))) {
+ attrs.add(new LDAPAttribute("UnSecurePort", httpport));
+ }
+ if ((eecaport != null) && (!eecaport.equals(""))) {
+ attrs.add(new LDAPAttribute("SecureEEClientAuthPort", eecaport));
+ }
+ if ((domainmgr != null) && (!domainmgr.equals(""))) {
+ attrs.add(new LDAPAttribute("DomainManager", domainmgr.toUpperCase()));
+ }
+ attrs.add(new LDAPAttribute("clone", clone.toUpperCase()));
+ attrs.add(new LDAPAttribute("SubsystemName", name));
+ entry = new LDAPEntry(dn, attrs);
+
+ if ((operation != null) && (operation.equals("remove"))) {
+ status = remove_from_ldap(dn);
+ String adminUserDN;
+ if ((agentsport != null) && (!agentsport.equals(""))) {
+ adminUserDN = "uid=" + type + "-" + host + "-" + agentsport + ",ou=People," + basedn;
+ } else {
+ adminUserDN = "uid=" + type + "-" + host + "-" + sport + ",ou=People," + basedn;
+ }
+ String userAuditParams = "Scope;;users+Operation;;OP_DELETE+source;;UpdateDomainXML" +
+ "+resource;;" + adminUserDN;
+ if (status.equals(SUCCESS)) {
+ // remove the user for this subsystem's admin
+ status2 = remove_from_ldap(adminUserDN);
+ if (status2.equals(SUCCESS)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ userAuditParams);
+ audit(auditMessage);
+
+ // remove this user from the subsystem group
+ userAuditParams = "Scope;;groups+Operation;;OP_DELETE_USER" +
+ "+source;;UpdateDomainXML" +
+ "+resource;;Subsystem Group+user;;" + adminUserDN;
+ dn = "cn=Subsystem Group, ou=groups," + basedn;
+ LDAPModification mod = new LDAPModification(LDAPModification.DELETE,
+ new LDAPAttribute("uniqueMember", adminUserDN));
+ status2 = modify_ldap(dn, mod);
+ if (status2.equals(SUCCESS)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ userAuditParams);
+ } else {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ userAuditParams);
+ }
+ audit(auditMessage);
+ } else { // error deleting user
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_ROLE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ userAuditParams);
+ audit(auditMessage);
+ }
+ }
+ } else {
+ status = add_to_ldap(entry, dn);
+ }
+ } else {
+ // update the domain.xml file
+ String path = CMS.getConfigStore().getString("instanceRoot", "")
+ + "/conf/domain.xml";
+
+ CMS.debug("UpdateDomainXML: got path=" + path);
+
+ try {
+ // using domain.xml file
+ CMS.debug("UpdateDomainXML: Inserting new domain info");
+ XMLObject parser = new XMLObject(new FileInputStream(path));
+ Node n = parser.getContainer(list);
+ int count = 0;
+
+ if ((operation != null) && (operation.equals("remove"))) {
+ // delete node
+ Document doc = parser.getDocument();
+ NodeList nodeList = doc.getElementsByTagName(type);
+ int len = nodeList.getLength();
+
+ for (int i = 0; i < len; i++) {
+ Node nn = nodeList.item(i);
+ Vector<String> v_name = parser.getValuesFromContainer(nn, "SubsystemName");
+ Vector<String> v_host = parser.getValuesFromContainer(nn, "Host");
+ Vector<String> v_adminport = parser.getValuesFromContainer(nn, "SecureAdminPort");
+ if ((v_name.elementAt(0).equals(name)) && (v_host.elementAt(0).equals(host))
+ && (v_adminport.elementAt(0).equals(adminsport))) {
+ Node parent = nn.getParentNode();
+ parent.removeChild(nn);
+ count--;
+ break;
+ }
+ }
+ } else {
+ // add node
+ Node parent = parser.createContainer(n, type);
+ parser.addItemToContainer(parent, "SubsystemName", name);
+ parser.addItemToContainer(parent, "Host", host);
+ parser.addItemToContainer(parent, "SecurePort", sport);
+ parser.addItemToContainer(parent, "SecureAgentPort", agentsport);
+ parser.addItemToContainer(parent, "SecureAdminPort", adminsport);
+ parser.addItemToContainer(parent, "SecureEEClientAuthPort", eecaport);
+ parser.addItemToContainer(parent, "UnSecurePort", httpport);
+ parser.addItemToContainer(parent, "DomainManager", domainmgr.toUpperCase());
+ parser.addItemToContainer(parent, "Clone", clone.toUpperCase());
+ count++;
+ }
+ //update count
+
+ String countS = "";
+ NodeList nlist = n.getChildNodes();
+ Node countnode = null;
+ for (int i = 0; i < nlist.getLength(); i++) {
+ Element nn = (Element) nlist.item(i);
+ String tagname = nn.getTagName();
+ if (tagname.equals("SubsystemCount")) {
+ countnode = nn;
+ NodeList nlist1 = nn.getChildNodes();
+ Node nn1 = nlist1.item(0);
+ countS = nn1.getNodeValue();
+ break;
+ }
+ }
+
+ CMS.debug("UpdateDomainXML process: SubsystemCount=" + countS);
+ try {
+ count += Integer.parseInt(countS);
+ } catch (Exception ee) {
+ }
+
+ n.removeChild(countnode);
+ parser.addItemToContainer(n, "SubsystemCount", "" + count);
+
+ // recreate domain.xml
+ CMS.debug("UpdateDomainXML: Recreating domain.xml");
+ byte[] b = parser.toByteArray();
+ FileOutputStream fos = new FileOutputStream(path);
+ fos.write(b);
+ fos.close();
+ } catch (Exception e) {
+ CMS.debug("Failed to update domain.xml file" + e.toString());
+ status = FAILED;
+ }
+
+ }
+
+ if (status.equals(SUCCESS)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams);
+ } else {
+ // what if already exists or already deleted
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams);
+ }
+ audit(auditMessage);
+
+ if (status.equals(SUCCESS) && status2.equals(SUCCESS)) {
+ status = SUCCESS;
+ } else {
+ status = FAILED;
+ }
+
+ try {
+ // send success status back to the requestor
+ CMS.debug("UpdateDomainXML: Sending response");
+ XMLObject xmlObj = new XMLObject();
+ Node root = xmlObj.createRoot("XMLResponse");
+
+ xmlObj.addItemToContainer(root, "Status", status);
+ byte[] cb = xmlObj.toByteArray();
+
+ outputResult(httpResp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("UpdateDomainXML: Failed to send the XML output" + e.toString());
+ }
+ }
+
+ protected String securityDomainXMLtoLDAP(String xmltag) {
+ if (xmltag.equals("Host"))
+ return "host";
+ else
+ return xmltag;
+ }
+
+ protected void setDefaultTemplates(ServletConfig sc) {
+ }
+
+ protected void renderTemplate(
+ CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler)
+ throws IOException {// do nothing
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java
new file mode 100644
index 000000000..b99a298a9
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java
@@ -0,0 +1,290 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.repository.IRepository;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+import com.netscape.cmsutil.xml.XMLObject;
+
+public class UpdateNumberRange extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1584171713024263331L;
+ private final static String SUCCESS = "0";
+ private final static String AUTH_FAILURE = "2";
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_SERIAL_NUMBER =
+ "LOGGING_SIGNED_AUDIT_CONFIG_SERIAL_NUMBER_1";
+
+ public UpdateNumberRange() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ CMS.debug("UpdateNumberRange: initializing...");
+ super.init(sc);
+ CMS.debug("UpdateNumberRange: done initializing...");
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param op 'downloadBIN' - return the binary certificate chain
+ * <li>http.param op 'displayIND' - display pretty-print of certificate chain components
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ CMS.debug("UpdateNumberRange: processing...");
+
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ CMS.debug("UpdateNumberRange process: authentication starts");
+ IAuthToken authToken = authenticate(cmsReq);
+ if (authToken == null) {
+ CMS.debug("UpdateNumberRange process: authToken is null");
+ outputError(httpResp, AUTH_FAILURE, "Error: not authenticated",
+ null);
+ }
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken, mAuthzResourceName,
+ "modify");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp,
+ "Error: Encountered problem during authorization.");
+ return;
+ }
+ if (authzToken == null) {
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ }
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditParams = "source;;updateNumberRange";
+
+ try {
+ String type = httpReq.getParameter("type");
+ IConfigStore cs = CMS.getConfigStore();
+ String cstype = cs.getString("cs.type", "");
+
+ auditParams += "+type;;" + type;
+
+ BigInteger beginNum = null;
+ BigInteger endNum = null;
+ BigInteger oneNum = new BigInteger("1");
+ String endNumConfig = null;
+ String cloneNumConfig = null;
+ String nextEndConfig = null;
+ int radix = 10;
+
+ IRepository repo = null;
+ if (cstype.equals("KRA")) {
+ IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority) CMS.getSubsystem(
+ IKeyRecoveryAuthority.ID);
+ if (type.equals("request")) {
+ repo = kra.getRequestQueue().getRequestRepository();
+ } else if (type.equals("serialNo")) {
+ repo = kra.getKeyRepository();
+ } else if (type.equals("replicaId")) {
+ repo = kra.getReplicaRepository();
+ }
+ } else { // CA
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(
+ ICertificateAuthority.ID);
+ if (type.equals("request")) {
+ repo = ca.getRequestQueue().getRequestRepository();
+ } else if (type.equals("serialNo")) {
+ repo = ca.getCertificateRepository();
+ } else if (type.equals("replicaId")) {
+ repo = ca.getReplicaRepository();
+ }
+ }
+
+ // checkRanges for replicaID - we do this each time a replica is created.
+ // This needs to be done beforehand to ensure that we always have enough
+ // replica numbers
+ if (type.equals("replicaId")) {
+ CMS.debug("Checking replica number ranges");
+ repo.checkRanges();
+ }
+
+ if (type.equals("request")) {
+ radix = 10;
+ endNumConfig = "dbs.endRequestNumber";
+ cloneNumConfig = "dbs.requestCloneTransferNumber";
+ nextEndConfig = "dbs.nextEndRequestNumber";
+ } else if (type.equals("serialNo")) {
+ radix = 16;
+ endNumConfig = "dbs.endSerialNumber";
+ cloneNumConfig = "dbs.serialCloneTransferNumber";
+ nextEndConfig = "dbs.nextEndSerialNumber";
+ } else if (type.equals("replicaId")) {
+ radix = 10;
+ endNumConfig = "dbs.endReplicaNumber";
+ cloneNumConfig = "dbs.replicaCloneTransferNumber";
+ nextEndConfig = "dbs.nextEndReplicaNumber";
+ }
+
+ String endNumStr = cs.getString(endNumConfig, "");
+ endNum = new BigInteger(endNumStr, radix);
+ String decrementStr = cs.getString(cloneNumConfig, "");
+ BigInteger decrement = new BigInteger(decrementStr, radix);
+ beginNum = endNum.subtract(decrement).add(oneNum);
+
+ if (beginNum.compareTo(repo.getTheSerialNumber()) < 0) {
+ String nextEndNumStr = cs.getString(nextEndConfig, "");
+ BigInteger endNum2 = new BigInteger(nextEndNumStr, radix);
+ CMS.debug("Transferring from the end of on-deck range");
+ String newValStr = endNum2.subtract(decrement).toString(radix);
+ repo.setNextMaxSerial(newValStr);
+ cs.putString(nextEndConfig, newValStr);
+ beginNum = endNum2.subtract(decrement).add(oneNum);
+ endNum = endNum2;
+ } else {
+ CMS.debug("Transferring from the end of the current range");
+ String newValStr = beginNum.subtract(oneNum).toString(radix);
+ repo.setMaxSerial(newValStr);
+ cs.putString(endNumConfig, newValStr);
+ }
+
+ if (beginNum == null) {
+ CMS.debug("UpdateNumberRange::process() - " +
+ "beginNum is null!");
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SERIAL_NUMBER,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams);
+ audit(auditMessage);
+ return;
+ }
+
+ // Enable serial number management in master for certs and requests
+ if (type.equals("replicaId")) {
+ repo.setEnableSerialMgmt(true);
+ }
+
+ // insert info
+ CMS.debug("UpdateNumberRange: Sending response");
+
+ // send success status back to the requestor
+ XMLObject xmlObj = new XMLObject();
+ Node root = xmlObj.createRoot("XMLResponse");
+
+ xmlObj.addItemToContainer(root, "Status", SUCCESS);
+ xmlObj.addItemToContainer(root, "beginNumber", beginNum.toString(radix));
+ xmlObj.addItemToContainer(root, "endNumber", endNum.toString(radix));
+ byte[] cb = xmlObj.toByteArray();
+
+ outputResult(httpResp, "application/xml", cb);
+ cs.commit(false);
+
+ auditParams += "+beginNumber;;" + beginNum.toString(radix) +
+ "+endNumber;;" + endNum.toString(radix);
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SERIAL_NUMBER,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditParams);
+ audit(auditMessage);
+
+ } catch (Exception e) {
+ CMS.debug("UpdateNumberRange: Failed to update number range. Exception: " + e.toString());
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_SERIAL_NUMBER,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditParams);
+ audit(auditMessage);
+
+ outputError(httpResp, "Error: Failed to update number range.");
+ }
+ }
+
+ protected void setDefaultTemplates(ServletConfig sc) {
+ }
+
+ protected void renderTemplate(
+ CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler)
+ throws IOException {// do nothing
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateOCSPConfig.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateOCSPConfig.java
new file mode 100644
index 000000000..c34df8b9c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateOCSPConfig.java
@@ -0,0 +1,180 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ICMSTemplateFiller;
+import com.netscape.cmsutil.xml.XMLObject;
+
+public class UpdateOCSPConfig extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 42812270761684404L;
+ private final static String SUCCESS = "0";
+ private final static String AUTH_FAILURE = "2";
+
+ public UpdateOCSPConfig() {
+ super();
+ }
+
+ /**
+ * initialize the servlet.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ CMS.debug("UpdateOCSPConfig: initializing...");
+ super.init(sc);
+ CMS.debug("UpdateOCSPConfig: done initializing...");
+ }
+
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ CMS.debug("UpdateOCSPConfig: processing...");
+
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ CMS.debug("UpdateOCSPConfig process: authentication starts");
+ IAuthToken authToken = authenticate(cmsReq);
+ if (authToken == null) {
+ CMS.debug("UpdateOCSPConfig process: authToken is null");
+ outputError(httpResp, AUTH_FAILURE, "Error: not authenticated",
+ null);
+ }
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken, mAuthzResourceName,
+ "modify");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ outputError(httpResp,
+ "Error: Encountered problem during authorization.");
+ return;
+ }
+ if (authzToken == null) {
+ outputError(httpResp, "Error: Not authorized");
+ return;
+ }
+
+ IConfigStore cs = CMS.getConfigStore();
+ String nickname = "";
+
+ // get nickname
+ try {
+ nickname = cs.getString("ca.subsystem.nickname", "");
+ String tokenname = cs.getString("ca.subsystem.tokenname", "");
+ if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token"))
+ nickname = tokenname + ":" + nickname;
+ } catch (Exception e) {
+ }
+
+ CMS.debug("UpdateOCSPConfig process: nickname=" + nickname);
+
+ String ocsphost = httpReq.getParameter("ocsp_host");
+ String ocspport = httpReq.getParameter("ocsp_port");
+ String ocspname = ocsphost.replace('.', '-')+"-"+ocspport;
+ String publisherPrefix = "ca.publish.publisher.instance.OCSPPublisher-"+ocspname;
+ String rulePrefix = "ca.publish.rule.instance.ocsprule-"+ocspname;
+ try {
+ cs.putString("ca.publish.enable", "true");
+ cs.putString(publisherPrefix+".host", ocsphost);
+ cs.putString(publisherPrefix+".port", ocspport);
+ cs.putString(publisherPrefix+".nickName", nickname);
+ cs.putString(publisherPrefix+".path", "/ocsp/agent/ocsp/addCRL");
+ cs.putString(publisherPrefix+".pluginName", "OCSPPublisher");
+ cs.putString(publisherPrefix+".enableClientAuth", "true");
+ cs.putString(rulePrefix+".enable", "true");
+ cs.putString(rulePrefix+".mapper", "NoMap");
+ cs.putString(rulePrefix+".pluginName", "Rule");
+ cs.putString(rulePrefix+".publisher", "OCSPPublisher-"+ocspname);
+ cs.putString(rulePrefix+".type", "crl");
+ cs.commit(false);
+ // insert info
+ CMS.debug("UpdateOCSPConfig: Sending response");
+
+ // send success status back to the requestor
+ XMLObject xmlObj = new XMLObject();
+ Node root = xmlObj.createRoot("XMLResponse");
+
+ xmlObj.addItemToContainer(root, "Status", SUCCESS);
+ byte[] cb = xmlObj.toByteArray();
+
+ outputResult(httpResp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("UpdateOCSPConfig: Failed to update OCSP configuration. Exception: " + e.toString());
+ outputError(httpResp, "Error: Failed to update OCSP configuration.");
+ }
+ }
+
+ protected void setDefaultTemplates(ServletConfig sc) {
+ }
+
+ protected void renderTemplate(
+ CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler)
+ throws IOException {// do nothing
+ }
+
+ protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/WelcomePanel.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/WelcomePanel.java
new file mode 100644
index 000000000..b5e921822
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/WelcomePanel.java
@@ -0,0 +1,128 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+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.cms.servlet.wizard.WizardServlet;
+
+public class WelcomePanel extends WizardPanelBase {
+
+ public WelcomePanel() {
+ }
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("Welcome");
+ setId(id);
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ cs.putBoolean("preop.welcome.done", false);
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ return cs.getBoolean("preop.welcome.done");
+ } catch (EBaseException e) {
+ }
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = new PropertySet();
+
+ /* XXX */
+
+ return set;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ IConfigStore cs = CMS.getConfigStore();
+ CMS.debug("WelcomePanel: display()");
+ context.put("title", "Welcome");
+ try {
+ context.put("cstype", cs.getString("cs.type"));
+ context.put("wizardname", cs.getString("preop.wizard.name"));
+ context.put("panelname",
+ cs.getString("preop.system.fullname") + " Configuration Wizard");
+ context.put("systemname",
+ cs.getString("preop.system.name"));
+ context.put("fullsystemname",
+ cs.getString("preop.system.fullname"));
+ context.put("productname",
+ cs.getString("preop.product.name"));
+ context.put("productversion",
+ cs.getString("cms.product.version"));
+ } catch (EBaseException e) {
+ }
+ context.put("panel", "admin/console/config/welcomepanel.vm");
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ cs.putBoolean("preop.welcome.done", true);
+ cs.commit(false);
+ } catch (EBaseException e) {
+ }
+ }
+
+ /**
+ * If validiate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {/* This should never be called */
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java
new file mode 100644
index 000000000..4fe641240
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java
@@ -0,0 +1,306 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+import org.mozilla.jss.ssl.SSLCertificateApprovalCallback;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.property.PropertySet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.wizard.IWizardPanel;
+import com.netscape.cms.servlet.wizard.WizardServlet;
+import com.netscape.cmsutil.xml.XMLObject;
+
+public class WizardPanelBase implements IWizardPanel {
+ public static String PCERT_PREFIX = "preop.cert.";
+ public static String SUCCESS = "0";
+ public static String FAILURE = "1";
+ public static String AUTH_FAILURE = "2";
+
+ /**
+ * Definition for static variables in CS.cfg
+ */
+ public static final String CONF_CA_CERT = "ca.signing.cert";
+ public static final String CONF_CA_CERTREQ = "ca.signing.certreq";
+ public static final String CONF_CA_CERTNICKNAME = "ca.signing.certnickname";
+
+ public static final String PRE_CONF_ADMIN_NAME = "preop.admin.name";
+ public static final String PRE_CONF_AGENT_GROUP = "preop.admin.group";
+
+ /**
+ * Definition for "preop" static variables in CS.cfg
+ * -- "preop" config parameters should not assumed to exist after configuation
+ */
+
+ public static final String PRE_CONF_CA_TOKEN = "preop.module.token";
+ public static final String PRE_CA_TYPE = "preop.ca.type";
+ public static final String PRE_OTHER_CA = "otherca";
+ public static final String PRE_ROOT_CA = "rootca";
+
+ private String mName = null;
+ private int mPanelNo = 0;
+ private String mId = null;
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ mPanelNo = panelno;
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ mPanelNo = panelno;
+ }
+
+ /**
+ * Cleans up this panel so that isPanelDone() will return false.
+ */
+ public void cleanUp() throws IOException {
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public int getPanelNo() {
+ return mPanelNo;
+ }
+
+ public void setPanelNo(int num) {
+ mPanelNo = num;
+ }
+
+ public void setName(String name) {
+ mName = name;
+ }
+
+ public void setId(String id) {
+ mId = id;
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ public PropertySet getUsage() {
+ PropertySet set = null;
+
+ return set;
+ }
+
+ /**
+ * Should we skip this panel?
+ */
+ public boolean shouldSkip() {
+ return false;
+ }
+
+ /**
+ * Is this panel done
+ */
+ public boolean isPanelDone() {
+ return false;
+ }
+
+ /**
+ * Show "Apply" button on frame?
+ */
+ public boolean showApplyButton() {
+ return false;
+ }
+
+ /**
+ * Is this a subPanel?
+ */
+ public boolean isSubPanel() {
+ return false;
+ }
+
+ public boolean isLoopbackPanel() {
+ return false;
+ }
+
+ /**
+ * has subPanels?
+ */
+ public boolean hasSubPanel() {
+ return false;
+ }
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ }
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ /**
+ * If validiate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ public Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader("accept-language");
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+
+ public boolean authenticate(String hostname, int port, boolean https,
+ String servlet, String uri) throws IOException {
+ CMS.debug("WizardPanelBase authenticate start");
+ String c = ConfigurationUtils.getHttpResponse(hostname, port, https, servlet, uri, null);
+ IConfigStore cs = CMS.getConfigStore();
+
+ if (c != null) {
+ try {
+ ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes());
+ XMLObject parser = null;
+
+ try {
+ parser = new XMLObject(bis);
+ } catch (Exception e) {
+ CMS.debug("WizardPanelBase::authenticate() - "
+ + "Exception=" + e.toString());
+ throw new IOException(e.toString());
+ }
+
+ String status = parser.getValue("Status");
+
+ CMS.debug("WizardPanelBase authenticate: status=" + status);
+
+ if (status.equals(SUCCESS)) {
+ String cookie = parser.getValue("Cookie");
+ cs.putString("preop.cookie", cookie);
+ return true;
+ } else {
+ return false;
+ }
+ } catch (Exception e) {
+ CMS.debug("WizardPanelBase: authenticate: " + e.toString());
+ throw new IOException(e.toString());
+ }
+ }
+
+ return false;
+ }
+
+ public String pingCS(String hostname, int port, boolean https,
+ SSLCertificateApprovalCallback certApprovalCallback)
+ throws IOException {
+ CMS.debug("WizardPanelBase pingCS: started");
+
+ String c = ConfigurationUtils.getHttpResponse(hostname, port, https,
+ "/ca/admin/ca/getStatus",
+ null, null, certApprovalCallback);
+
+ if (c != null) {
+ try {
+ ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes());
+ XMLObject parser = null;
+ String state = null;
+
+ try {
+ parser = new XMLObject(bis);
+ CMS.debug("WizardPanelBase pingCS: got XML parsed");
+ state = parser.getValue("State");
+
+ if (state != null) {
+ CMS.debug("WizardPanelBase pingCS: state=" + state);
+ }
+ } catch (Exception e) {
+ CMS.debug("WizardPanelBase: pingCS: parser failed"
+ + e.toString());
+ }
+
+ return state;
+ } catch (Exception e) {
+ CMS.debug("WizardPanelBase: pingCS: " + e.toString());
+ throw new IOException(e.toString());
+ }
+ }
+
+ CMS.debug("WizardPanelBase pingCS: stopped");
+ return null;
+ }
+
+ public void reloginSecurityDomain(HttpServletResponse response) {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String hostname = cs.getString("securitydomain.host", "");
+ int port = cs.getInteger("securitydomain.httpsadminport", -1);
+ String cs_hostname = cs.getString("machineName", "");
+ int cs_port = cs.getInteger("pkicreate.admin_secure_port", -1);
+ int panel = getPanelNo();
+ String subsystem = cs.getString("cs.type", "");
+ String urlVal =
+ "https://"
+ + cs_hostname + ":" + cs_port + "/" + subsystem.toLowerCase()
+ + "/admin/console/config/wizard?p=" + panel + "&subsystem=" + subsystem;
+ String encodedValue = URLEncoder.encode(urlVal, "UTF-8");
+ String sdurl = "https://" + hostname + ":" + port + "/ca/admin/ca/securityDomainLogin?url=" + encodedValue;
+ response.sendRedirect(sdurl);
+ } catch (Exception e) {
+ CMS.debug("WizardPanelBase reloginSecurityDomain: Exception=" + e.toString());
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/filter/AdminRequestFilter.java b/base/server/cms/src/com/netscape/cms/servlet/filter/AdminRequestFilter.java
new file mode 100644
index 000000000..c7532c7aa
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/filter/AdminRequestFilter.java
@@ -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.
+//
+// (C) 2009 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.filter;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+
+public class AdminRequestFilter implements Filter {
+ private static final String HTTPS_SCHEME = "https";
+ private static final String HTTPS_PORT = "https_port";
+ private static final String HTTPS_ROLE = "Admin";
+ private static final String PROXY_PORT = "proxy_port";
+
+ private FilterConfig config;
+
+ /* Create a new AdminRequestFilter */
+ public AdminRequestFilter() {
+ }
+
+ public void init(FilterConfig filterConfig)
+ throws ServletException {
+ this.config = filterConfig;
+ }
+
+ public void doFilter(ServletRequest request,
+ ServletResponse response,
+ FilterChain chain)
+ throws java.io.IOException,
+ ServletException {
+ String filterName = getClass().getName();
+
+ String scheme = null;
+ int port = 0;
+
+ String request_port = null;
+ String param_https_port = null;
+ String param_proxy_port = null;
+ String msg = null;
+ String param_active = null;
+
+ // CMS.debug("Entering the admin filter");
+ param_active = config.getInitParameter("active");
+
+ if (request instanceof HttpServletRequest) {
+ HttpServletResponse resp = (HttpServletResponse) response;
+
+ // RFC 1738: verify that scheme is "https"
+ scheme = request.getScheme();
+ if (!scheme.equals(HTTPS_SCHEME)) {
+ msg = "The scheme MUST be '" + HTTPS_SCHEME
+ + "', NOT '" + scheme + "'!";
+ CMS.debug(filterName + ": " + msg);
+ resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, msg);
+ return;
+ }
+
+ // Always obtain an "https" port from request
+ port = request.getLocalPort();
+ request_port = Integer.toString(port);
+
+ // Always obtain the "https" port passed in as a parameter
+ param_https_port = config.getInitParameter(HTTPS_PORT);
+ if (param_https_port == null) {
+ msg = "The <param-name> '" + HTTPS_PORT
+ + "' </param-name> " + "MUST be specified in 'web.xml'!";
+ CMS.debug(filterName + ": " + msg);
+ resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, msg);
+ return;
+ }
+
+ param_proxy_port = config.getInitParameter(PROXY_PORT);
+ boolean bad_port = false;
+
+ // Compare the request and param "https" ports
+ if (!param_https_port.equals(request_port)) {
+ String uri = ((HttpServletRequest) request).getRequestURI();
+ if (param_proxy_port != null) {
+ if (!param_proxy_port.equals(request_port)) {
+ msg = "Use HTTPS port '" + param_https_port
+ + "' or proxy port '" + param_proxy_port
+ + "' instead of '" + request_port
+ + "' when performing " + HTTPS_ROLE + " tasks!";
+ bad_port = true;
+ }
+ } else {
+ msg = "Use HTTPS port '" + param_https_port
+ + "' instead of '" + request_port
+ + "' when performing " + HTTPS_ROLE + " tasks!";
+ bad_port = true;
+ }
+ if (bad_port) {
+ CMS.debug(filterName + ": " + msg);
+ CMS.debug(filterName + ": uri is " + uri);
+ if ((param_active != null) && (param_active.equals("false"))) {
+ CMS.debug("Filter is disabled .. continuing");
+ } else {
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, msg);
+ return;
+ }
+ }
+ }
+ }
+
+ // CMS.debug("Exiting the admin filter");
+
+ chain.doFilter(request, response);
+ }
+
+ public void destroy() {
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/filter/AgentRequestFilter.java b/base/server/cms/src/com/netscape/cms/servlet/filter/AgentRequestFilter.java
new file mode 100644
index 000000000..4225aed77
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/filter/AgentRequestFilter.java
@@ -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.
+//
+// (C) 2009 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.filter;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+
+public class AgentRequestFilter implements Filter {
+ private static final String HTTPS_SCHEME = "https";
+ private static final String HTTPS_PORT = "https_port";
+ private static final String HTTPS_ROLE = "Agent";
+ private static final String PROXY_PORT = "proxy_port";
+
+ private FilterConfig config;
+
+ /* Create a new AgentRequestFilter */
+ public AgentRequestFilter() {
+ }
+
+ public void init(FilterConfig filterConfig)
+ throws ServletException {
+ this.config = filterConfig;
+ }
+
+ public void doFilter(ServletRequest request,
+ ServletResponse response,
+ FilterChain chain)
+ throws java.io.IOException,
+ ServletException {
+ String filterName = getClass().getName();
+
+ String scheme = null;
+ int port = 0;
+
+ String request_port = null;
+ String param_https_port = null;
+ String param_proxy_port = null;
+ String msg = null;
+
+ String param_active = null;
+
+ // CMS.debug("Entering the agent filter");
+ param_active = config.getInitParameter("active");
+
+ if (request instanceof HttpServletRequest) {
+ HttpServletResponse resp = (HttpServletResponse) response;
+
+ // RFC 1738: verify that scheme is "https"
+ scheme = request.getScheme();
+ if (!scheme.equals(HTTPS_SCHEME)) {
+ msg = "The scheme MUST be '" + HTTPS_SCHEME
+ + "', NOT '" + scheme + "'!";
+ CMS.debug(filterName + ": " + msg);
+ resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, msg);
+ return;
+ }
+
+ // Always obtain an "https" port from request
+ port = request.getLocalPort();
+ request_port = Integer.toString(port);
+
+ // Always obtain the "https" port passed in as a parameter
+ param_https_port = config.getInitParameter(HTTPS_PORT);
+ if (param_https_port == null) {
+ msg = "The <param-name> '" + HTTPS_PORT
+ + "' </param-name> " + "MUST be specified in 'web.xml'!";
+ CMS.debug(filterName + ": " + msg);
+ resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, msg);
+ return;
+ }
+
+ param_proxy_port = config.getInitParameter(PROXY_PORT);
+ boolean bad_port = false;
+
+ // Compare the request and param "https" ports
+ if (!param_https_port.equals(request_port)) {
+ String uri = ((HttpServletRequest) request).getRequestURI();
+ if (param_proxy_port != null) {
+ if (!param_proxy_port.equals(request_port)) {
+ msg = "Use HTTPS port '" + param_https_port
+ + "' or proxy port '" + param_proxy_port
+ + "' instead of '" + request_port
+ + "' when performing " + HTTPS_ROLE + " tasks!";
+ bad_port = true;
+ }
+ } else {
+ msg = "Use HTTPS port '" + param_https_port
+ + "' instead of '" + request_port
+ + "' when performing " + HTTPS_ROLE + " tasks!";
+ bad_port = true;
+ }
+ if (bad_port) {
+ CMS.debug(filterName + ": " + msg);
+ CMS.debug(filterName + ": uri is " + uri);
+ if ((param_active != null) && (param_active.equals("false"))) {
+ CMS.debug("Filter is disabled .. continuing");
+ } else {
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, msg);
+ return;
+ }
+ }
+ }
+ }
+ // CMS.debug("Exiting the Agent filter");
+
+ chain.doFilter(request, response);
+ }
+
+ public void destroy() {
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/filter/EEClientAuthRequestFilter.java b/base/server/cms/src/com/netscape/cms/servlet/filter/EEClientAuthRequestFilter.java
new file mode 100644
index 000000000..8c62cd311
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/filter/EEClientAuthRequestFilter.java
@@ -0,0 +1,133 @@
+// --- 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) 2010 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.filter;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+
+public class EEClientAuthRequestFilter implements Filter {
+ private static final String HTTPS_SCHEME = "https";
+ private static final String HTTPS_PORT = "https_port";
+ private static final String HTTPS_ROLE = "EE Client Auth";
+ private static final String PROXY_PORT = "proxy_port";
+
+ private FilterConfig config;
+
+ /* Create a new EEClientAuthRequestFilter */
+ public EEClientAuthRequestFilter() {
+ }
+
+ public void init(FilterConfig filterConfig)
+ throws ServletException {
+ this.config = filterConfig;
+ }
+
+ public void doFilter(ServletRequest request,
+ ServletResponse response,
+ FilterChain chain)
+ throws java.io.IOException,
+ ServletException {
+ String filterName = getClass().getName();
+
+ String scheme = null;
+ int port = 0;
+
+ String request_port = null;
+ String param_https_port = null;
+ String msg = null;
+ String param_active = null;
+ String param_proxy_port = null;
+
+ // CMS.debug("Entering the EECA filter");
+ param_active = config.getInitParameter("active");
+
+ if (request instanceof HttpServletRequest) {
+ HttpServletResponse resp = (HttpServletResponse) response;
+
+ // RFC 1738: verify that scheme is "https"
+ scheme = request.getScheme();
+ if (!scheme.equals(HTTPS_SCHEME)) {
+ msg = "The scheme MUST be '" + HTTPS_SCHEME
+ + "', NOT '" + scheme + "'!";
+ CMS.debug(filterName + ": " + msg);
+ resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, msg);
+ return;
+ }
+
+ // Always obtain an "https" port from request
+ port = request.getLocalPort();
+ request_port = Integer.toString(port);
+
+ // Always obtain the "https" port passed in as a parameter
+ param_https_port = config.getInitParameter(HTTPS_PORT);
+ if (param_https_port == null) {
+ msg = "The <param-name> '" + HTTPS_PORT
+ + "' </param-name> " + "MUST be specified in 'web.xml'!";
+ CMS.debug(filterName + ": " + msg);
+ resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, msg);
+ return;
+ }
+
+ param_proxy_port = config.getInitParameter(PROXY_PORT);
+ boolean bad_port = false;
+
+ // Compare the request and param "https" ports
+ if (!param_https_port.equals(request_port)) {
+ String uri = ((HttpServletRequest) request).getRequestURI();
+ if (param_proxy_port != null) {
+ if (!param_proxy_port.equals(request_port)) {
+ msg = "Use HTTPS port '" + param_https_port
+ + "' or proxy port '" + param_proxy_port
+ + "' instead of '" + request_port
+ + "' when performing " + HTTPS_ROLE + " tasks!";
+ bad_port = true;
+ }
+ } else {
+ msg = "Use HTTPS port '" + param_https_port
+ + "' instead of '" + request_port
+ + "' when performing " + HTTPS_ROLE + " tasks!";
+ bad_port = true;
+ }
+ if (bad_port) {
+ CMS.debug(filterName + ": " + msg);
+ CMS.debug(filterName + ": uri is " + uri);
+ if ((param_active != null) && (param_active.equals("false"))) {
+ CMS.debug("Filter is disabled .. continuing");
+ } else {
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, msg);
+ return;
+ }
+ }
+ }
+ }
+ // CMS.debug("exiting the EECA filter");
+
+ chain.doFilter(request, response);
+ }
+
+ public void destroy() {
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/filter/EERequestFilter.java b/base/server/cms/src/com/netscape/cms/servlet/filter/EERequestFilter.java
new file mode 100644
index 000000000..8a8bea01c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/filter/EERequestFilter.java
@@ -0,0 +1,186 @@
+// --- 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) 2009 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.filter;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+
+public class EERequestFilter implements Filter {
+ private static final String HTTP_SCHEME = "http";
+ private static final String HTTP_PORT = "http_port";
+ private static final String HTTP_ROLE = "EE";
+ private static final String HTTPS_SCHEME = "https";
+ private static final String HTTPS_PORT = "https_port";
+ private static final String HTTPS_ROLE = "EE";
+ private static final String PROXY_PORT = "proxy_port";
+ private static final String PROXY_HTTP_PORT = "proxy_http_port";
+
+ private FilterConfig config;
+
+ /* Create a new EERequestFilter */
+ public EERequestFilter() {
+ }
+
+ public void init(FilterConfig filterConfig)
+ throws ServletException {
+ this.config = filterConfig;
+ }
+
+ public void doFilter(ServletRequest request,
+ ServletResponse response,
+ FilterChain chain)
+ throws java.io.IOException,
+ ServletException {
+ String filterName = getClass().getName();
+
+ String scheme = null;
+ int port = 0;
+
+ String request_port = null;
+ String param_http_port = null;
+ String param_https_port = null;
+ String param_proxy_port = null;
+ String param_proxy_http_port = null;
+ String msg = null;
+ String param_active = null;
+
+ // CMS.debug("Entering the EE filter");
+ param_active = config.getInitParameter("active");
+
+ if (request instanceof HttpServletRequest) {
+ HttpServletResponse resp = (HttpServletResponse) response;
+
+ // RFC 1738: verify that scheme is either "http" or "https"
+ scheme = request.getScheme();
+ if ((!scheme.equals(HTTP_SCHEME)) &&
+ (!scheme.equals(HTTPS_SCHEME))) {
+ msg = "The scheme MUST be either '" + HTTP_SCHEME
+ + "' or '" + HTTPS_SCHEME
+ + "', NOT '" + scheme + "'!";
+ CMS.debug(filterName + ": " + msg);
+ resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, msg);
+ return;
+ }
+
+ // Always obtain either an "http" or an "https" port from request
+ port = request.getLocalPort();
+ request_port = Integer.toString(port);
+
+ // Always obtain the "http" port passed in as a parameter
+ param_http_port = config.getInitParameter(HTTP_PORT);
+ if (param_http_port == null) {
+ msg = "The <param-name> '" + HTTP_PORT
+ + "' </param-name> " + "MUST be specified in 'web.xml'!";
+ CMS.debug(filterName + ": " + msg);
+ resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, msg);
+ return;
+ }
+
+ // Always obtain the "https" port passed in as a parameter
+ param_https_port = config.getInitParameter(HTTPS_PORT);
+ if (param_https_port == null) {
+ msg = "The <param-name> '" + HTTPS_PORT
+ + "' </param-name> " + "MUST be specified in 'web.xml'!";
+ CMS.debug(filterName + ": " + msg);
+ resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, msg);
+ return;
+ }
+
+ param_proxy_http_port = config.getInitParameter(PROXY_HTTP_PORT);
+ param_proxy_port = config.getInitParameter(PROXY_PORT);
+ boolean bad_port = false;
+
+ // If the scheme is "http", compare
+ // the request and param "http" ports;
+ // otherwise, if the scheme is "https", compare
+ // the request and param "https" ports
+ if (scheme.equals(HTTP_SCHEME)) {
+ if (!param_http_port.equals(request_port)) {
+ String uri = ((HttpServletRequest) request).getRequestURI();
+ if (param_proxy_http_port != null) {
+ if (!param_proxy_http_port.equals(request_port)) {
+ msg = "Use HTTP port '" + param_http_port
+ + "' or proxy port '" + param_proxy_http_port
+ + "' instead of '" + request_port
+ + "' when performing " + HTTP_ROLE + " tasks!";
+ bad_port = true;
+ }
+ } else {
+ msg = "Use HTTP port '" + param_http_port
+ + "' instead of '" + request_port
+ + "' when performing " + HTTP_ROLE + " tasks!";
+ bad_port = true;
+ }
+ if (bad_port) {
+ CMS.debug(filterName + ": " + msg);
+ CMS.debug(filterName + ": uri is " + uri);
+ if ((param_active != null) && (param_active.equals("false"))) {
+ CMS.debug("Filter is disabled .. continuing");
+ } else {
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, msg);
+ return;
+ }
+ }
+ }
+ } else if (scheme.equals(HTTPS_SCHEME)) {
+ if (!param_https_port.equals(request_port)) {
+ String uri = ((HttpServletRequest) request).getRequestURI();
+ if (param_proxy_port != null) {
+ if (!param_proxy_port.equals(request_port)) {
+ msg = "Use HTTPS port '" + param_https_port
+ + "' or proxy port '" + param_proxy_port
+ + "' instead of '" + request_port
+ + "' when performing " + HTTPS_ROLE + " tasks!";
+ bad_port = true;
+ }
+ } else {
+ msg = "Use HTTPS port '" + param_https_port
+ + "' instead of '" + request_port
+ + "' when performing " + HTTPS_ROLE + " tasks!";
+ bad_port = true;
+ }
+ if (bad_port) {
+ CMS.debug(filterName + ": " + msg);
+ CMS.debug(filterName + ": uri is " + uri);
+ if ((param_active != null) && (param_active.equals("false"))) {
+ CMS.debug("Filter is disabled .. continuing");
+ } else {
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, msg);
+ return;
+ }
+ }
+ }
+ }
+
+ }
+ // CMS.debug("Exiting the EE filter");
+
+ chain.doFilter(request, response);
+ }
+
+ public void destroy() {
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/ConfirmRecoverBySerial.java b/base/server/cms/src/com/netscape/cms/servlet/key/ConfirmRecoverBySerial.java
new file mode 100644
index 000000000..e9faca86d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/ConfirmRecoverBySerial.java
@@ -0,0 +1,188 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+import com.netscape.certsrv.dbs.keydb.IKeyRepository;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.kra.IKeyService;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * A class representing a recoverKey servlet. This servlet
+ * shows key information and presents a list of text boxes
+ * so that recovery agents can type in their identifiers
+ * and passwords.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ConfirmRecoverBySerial extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2221819191344494389L;
+ private final static String INFO = "recoverBySerial";
+ private final static String TPL_FILE =
+ "confirmRecoverBySerial.template";
+
+ private final static String IN_SERIALNO = "serialNumber";
+ private final static String OUT_SERIALNO = IN_SERIALNO;
+ private final static String OUT_OP = "op";
+ private final static String OUT_SERVICE_URL = "serviceURL";
+ private final static String OUT_M = "noOfRequiredAgents";
+ private final static String OUT_ERROR = "errorDetails";
+
+ private IKeyRepository mKeyDB = null;
+ private IKeyService mRecoveryService = null;
+ private String mFormPath = null;
+
+ /**
+ * Constructs ConfirmRecoverBySerial servlet.
+ */
+ public ConfirmRecoverBySerial() {
+ super();
+ }
+
+ /**
+ * Initializes the servlet.
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ mRecoveryService = (IKeyService) mAuthority;
+ mKeyDB = ((IKeyRecoveryAuthority) mAuthority).getKeyRepository();
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Serves HTTP request. The format of this request is
+ * as follows:
+ * confirmRecoverBySerial?
+ * [serialNumber=<serialno>]
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+
+ // Note that we should try to handle all the exceptions
+ // instead of passing it up back to the servlet
+ // framework.
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ authenticate(cmsReq);
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ BigInteger seqNum = BigInteger.ZERO;
+
+ try {
+ if (req.getParameter(IN_SERIALNO) != null) {
+ seqNum = new BigInteger(req.getParameter(IN_SERIALNO));
+ }
+
+ // make sure this page, which contains password
+ // information, is not cache. Too bad, this is
+ // only good for NS browser, not IE specifically.
+ resp.setHeader("pragma", "no-cache");
+
+ process(argSet, header, seqNum, req, resp, locale[0]);
+ } catch (NumberFormatException e) {
+ header.addStringValue(OUT_ERROR,
+ CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Requests for a list of agent passwords.
+ */
+ private void process(CMSTemplateParams argSet,
+ IArgBlock header, BigInteger seq,
+ HttpServletRequest req, HttpServletResponse resp,
+ Locale locale) {
+ try {
+ header.addBigIntegerValue(OUT_SERIALNO, seq, 10);
+ header.addIntegerValue(OUT_M,
+ mRecoveryService.getNoOfRequiredAgents());
+ header.addStringValue(OUT_OP,
+ req.getParameter(OUT_OP));
+ header.addStringValue(OUT_SERVICE_URL,
+ req.getRequestURI());
+
+ IKeyRecord rec = mKeyDB.readKeyRecord(seq);
+
+ KeyRecordParser.fillRecordIntoArg(rec, header);
+ } catch (EBaseException e) {
+ header.addStringValue(OUT_ERROR, e.toString(locale));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerial.java b/base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerial.java
new file mode 100644
index 000000000..03af65c1f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerial.java
@@ -0,0 +1,195 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+import com.netscape.certsrv.dbs.keydb.IKeyRepository;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Display a specific Key Archival Request
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class DisplayBySerial extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -537957487396615246L;
+ private final static String INFO = "displayBySerial";
+ private final static String TPL_FILE = "displayBySerial.template";
+
+ private final static String IN_SERIALNO = "serialNumber";
+ private final static String OUT_OP = "op";
+ private final static String OUT_SERVICE_URL = "serviceURL";
+ private final static String OUT_ERROR = "errorDetails";
+
+ private IKeyRepository mKeyDB = null;
+ private String mFormPath = null;
+
+ /**
+ * Constructs displayBySerial servlet.
+ */
+ public DisplayBySerial() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "displayBySerial.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ mKeyDB = ((IKeyRecoveryAuthority) mAuthority).getKeyRepository();
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param serialNumber serial number of the key archival request
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ // Note that we should try to handle all the exceptions
+ // instead of passing it up back to the servlet
+ // framework.
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+ BigInteger seqNum = BigInteger.ZERO;
+
+ try {
+ if (req.getParameter(IN_SERIALNO) != null) {
+ seqNum = new BigInteger(req.getParameter(IN_SERIALNO));
+ }
+ process(argSet, header, seqNum, req, resp, locale[0]);
+ } catch (NumberFormatException e) {
+ header.addStringValue(OUT_ERROR,
+ CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ /**
+ * Display information about a particular key.
+ */
+ private void process(CMSTemplateParams argSet,
+ IArgBlock header, BigInteger seq,
+ HttpServletRequest req, HttpServletResponse resp,
+ Locale locale) {
+ try {
+ header.addStringValue(OUT_OP,
+ req.getParameter(OUT_OP));
+ header.addStringValue(OUT_SERVICE_URL,
+ req.getRequestURI());
+ IKeyRecord rec = mKeyDB.readKeyRecord(seq);
+
+ KeyRecordParser.fillRecordIntoArg(rec, header);
+ } catch (EBaseException e) {
+ header.addStringValue(OUT_ERROR, e.toString(locale));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerialForRecovery.java b/base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerialForRecovery.java
new file mode 100644
index 000000000..48cac3785
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/DisplayBySerialForRecovery.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+import com.netscape.certsrv.dbs.keydb.IKeyRepository;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.kra.IKeyService;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Display a Specific Key Archival Request, and initiate
+ * key recovery process
+ *
+ * @version $Revision$, $Date$
+ */
+public class DisplayBySerialForRecovery extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 6876016034084761827L;
+ private final static String INFO = "displayBySerial";
+ private final static String TPL_FILE = "displayBySerialForRecovery.template";
+
+ private final static String IN_SERIALNO = "serialNumber";
+ private final static String OUT_OP = "op";
+ private final static String OUT_SERVICE_URL = "serviceURL";
+ private final static String OUT_ERROR = "errorDetails";
+
+ private IKeyRepository mKeyDB = null;
+ private String mFormPath = null;
+ private IKeyService mService = null;
+
+ /**
+ * Constructor
+ */
+ public DisplayBySerialForRecovery() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "displayBySerialForRecovery.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/agent/" + mAuthority.getId() + "/" + TPL_FILE;
+ mKeyDB = ((IKeyRecoveryAuthority) mAuthority).getKeyRepository();
+ mService = (IKeyService) mAuthority;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param serialNumber request ID of key archival request
+ * <li>http.param publicKeyData
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ // Note that we should try to handle all the exceptions
+ // instead of passing it up back to the servlet
+ // framework.
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ BigInteger seqNum = BigInteger.ZERO;
+
+ try {
+ if (req.getParameter(IN_SERIALNO) != null) {
+ seqNum = new BigInteger(req.getParameter(IN_SERIALNO));
+ }
+ process(argSet, header,
+ req.getParameter("publicKeyData"),
+ seqNum, req, resp, locale[0]);
+ } catch (NumberFormatException e) {
+ header.addStringValue(OUT_ERROR,
+ CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString()));
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.out.println(e.toString());
+ }
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Display information about a particular key.
+ */
+ private synchronized void process(CMSTemplateParams argSet,
+ IArgBlock header, String publicKeyData, BigInteger seq,
+ HttpServletRequest req, HttpServletResponse resp,
+ Locale locale) {
+ try {
+ header.addIntegerValue("noOfRequiredAgents",
+ mService.getNoOfRequiredAgents());
+ header.addStringValue(OUT_OP,
+ req.getParameter(OUT_OP));
+ header.addStringValue("keySplitting",
+ CMS.getConfigStore().getString("kra.keySplitting"));
+ header.addStringValue(OUT_SERVICE_URL,
+ req.getRequestURI());
+ if (publicKeyData != null) {
+ header.addStringValue("publicKeyData",
+ publicKeyData);
+ }
+ IKeyRecord rec = mKeyDB.readKeyRecord(seq);
+
+ KeyRecordParser.fillRecordIntoArg(rec, header);
+
+ // recovery identifier
+ header.addStringValue("recoveryID", mService.getRecoveryID());
+ } catch (EBaseException e) {
+ header.addStringValue(OUT_ERROR, e.toString(locale));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/DisplayTransport.java b/base/server/cms/src/com/netscape/cms/servlet/key/DisplayTransport.java
new file mode 100644
index 000000000..e59550af3
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/DisplayTransport.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.security.ITransportKeyUnit;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Retrieve Transport Certificate used to
+ * wrap Private key Archival requests
+ *
+ * @version $Revision$, $Date$
+ */
+public class DisplayTransport extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6509083753395783705L;
+ private final static String INFO = "displayTransport";
+
+ /**
+ * Constructs displayTransport servlet.
+ */
+ public DisplayTransport() {
+ super();
+ }
+
+ /**
+ * Initializes the servlet.
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ try {
+ IKeyRecoveryAuthority kra =
+ (IKeyRecoveryAuthority) mAuthority;
+ ITransportKeyUnit tu = kra.getTransportKeyUnit();
+ org.mozilla.jss.crypto.X509Certificate transportCert =
+ tu.getCertificate();
+
+ resp.setStatus(HttpServletResponse.SC_OK);
+ resp.setContentType("text/html");
+ String content = "";
+
+ content += "<HTML><PRE>";
+ String mime64 =
+ "-----BEGIN CERTIFICATE-----\n" +
+ CMS.BtoA(transportCert.getEncoded()) + "\n" +
+ "-----END CERTIFICATE-----\n";
+
+ content += mime64;
+ content += "</PRE></HTML>";
+ resp.setContentType("text/html");
+ resp.getOutputStream().write(content.getBytes());
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/ExamineRecovery.java b/base/server/cms/src/com/netscape/cms/servlet/key/ExamineRecovery.java
new file mode 100644
index 000000000..cd3988944
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/ExamineRecovery.java
@@ -0,0 +1,240 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Hashtable;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+import com.netscape.certsrv.dbs.keydb.IKeyRepository;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.kra.IKeyService;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * View the Key Recovery Request
+ *
+ * @version $Revision$, $Date$
+ */
+public class ExamineRecovery extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -953282265332774966L;
+ private final static String INFO = "examineRecovery";
+ private final static String TPL_FILE = "examineRecovery.template";
+
+ private final static String OUT_OP = "op";
+ private final static String OUT_SERVICE_URL = "serviceURL";
+
+ private IKeyService mService = null;
+ private String mFormPath = null;
+
+ /**
+ * Constructs EA servlet.
+ */
+ public ExamineRecovery() {
+ super();
+ }
+
+ /**
+ * Initializes the servlet.
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mService = (IKeyService) mAuthority;
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param recoveryID recovery request ID
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+
+ public void process(CMSRequest cmsReq) throws EBaseException {
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ EBaseException error = null;
+
+ try {
+ process(argSet, header,
+ req.getParameter("recoveryID"),
+ req, resp, locale[0]);
+ } catch (EBaseException e) {
+ error = e;
+ } catch (Exception e) {
+ error = new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+
+ /*
+ catch (NumberFormatException e) {
+ error = eBaseException(
+
+ header.addStringValue(OUT_ERROR,
+ MessageFormatter.getLocalizedString(
+ locale[0],
+ BaseResources.class.getName(),
+ BaseResources.INTERNAL_ERROR_1,
+ e.toString()));
+ }
+ */
+
+ try {
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ ServletOutputStream out = resp.getOutputStream();
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ /**
+ * Recovers a key. The p12 will be protected by the password
+ * provided by the administrator.
+ */
+ private void process(CMSTemplateParams argSet,
+ IArgBlock header, String recoveryID,
+ HttpServletRequest req, HttpServletResponse resp,
+ Locale locale)
+ throws EBaseException {
+ try {
+ header.addStringValue(OUT_OP,
+ req.getParameter(OUT_OP));
+ header.addStringValue(OUT_SERVICE_URL,
+ req.getRequestURI());
+ header.addStringValue("keySplitting",
+ CMS.getConfigStore().getString("kra.keySplitting"));
+ Hashtable<String, Object> params = mService.getRecoveryParams(
+ recoveryID);
+
+ if (params == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_NO_RECOVERY_TOKEN_FOUND_1", recoveryID));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_NO_RECOVERY_TOKEN_FOUND", recoveryID));
+ }
+ String keyID = (String) params.get("keyID");
+ header.addStringValue("serialNumber", keyID);
+ header.addStringValue("recoveryID", recoveryID);
+
+ IKeyRepository mKeyDB =
+ ((IKeyRecoveryAuthority) mAuthority).getKeyRepository();
+ IKeyRecord rec = mKeyDB.readKeyRecord(new
+ BigInteger(keyID));
+ KeyRecordParser.fillRecordIntoArg(rec, header);
+
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, "Error e " + e);
+ throw e;
+ }
+
+ /*
+ catch (Exception e) {
+ header.addStringValue(OUT_ERROR, e.toString());
+ }
+ */
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/GetApprovalStatus.java b/base/server/cms/src/com/netscape/cms/servlet/key/GetApprovalStatus.java
new file mode 100644
index 000000000..7d24c7ceb
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/GetApprovalStatus.java
@@ -0,0 +1,236 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.security.Credential;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Check to see if a Key Recovery Request has been approved
+ *
+ * @version $Revision$, $Date$
+ */
+public class GetApprovalStatus extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -8257339915430654983L;
+ private final static String INFO = "getApprovalStatus";
+ private final static String TPL_FILE = "getApprovalStatus.template";
+ private final static String TPL_FINISH = "finishRecovery.template";
+
+ private final static String OUT_ERROR = "errorDetails";
+ private final static String OUT_STATUS = "status";
+
+ private com.netscape.certsrv.kra.IKeyService mService = null;
+ private String mFormPath = null;
+
+ /**
+ * Constructs getApprovalStatus servlet.
+ */
+ public GetApprovalStatus() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template files
+ * "getApprovalStatus.template" and "finishRecovery.template"
+ * to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // mFormPath = "/"+authority.getId()+"/"+TPL_FILE;
+ mService = (com.netscape.certsrv.kra.IKeyService) mAuthority;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param recoveryID request ID to check
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+ int rComplete = 0;
+
+ // get status and populate argSet
+ try {
+ String recoveryID = req.getParameter("recoveryID");
+
+ header.addStringValue("recoveryID", recoveryID);
+
+ Hashtable<String, Object> params = mService.getRecoveryParams(recoveryID);
+
+ if (params == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_NO_RECOVERY_TOKEN_FOUND_1", recoveryID));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_NO_RECOVERY_TOKEN_FOUND", recoveryID));
+ }
+ header.addStringValue("serialNumber",
+ (String) params.get("keyID"));
+ header.addStringValue("serialNumberInHex",
+ new BigInteger((String) params.get("keyID")).toString(16));
+
+ int requiredNumber = mService.getNoOfRequiredAgents();
+
+ header.addIntegerValue("noOfRequiredAgents", requiredNumber);
+
+ Vector<Credential> dc = ((IKeyRecoveryAuthority) mService).getAppAgents(recoveryID);
+ Enumeration<Credential> agents = dc.elements();
+
+ while (agents.hasMoreElements()) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addStringValue("agentName", agents.nextElement().getIdentifier());
+ argSet.addRepeatRecord(rarg);
+ }
+ if (dc.size() >= requiredNumber) {
+ // got all approval, return pk12
+ byte pkcs12[] = ((IKeyRecoveryAuthority) mService).getPk12(recoveryID);
+
+ if (pkcs12 != null) {
+ rComplete = 1;
+ header.addStringValue(OUT_STATUS, "complete");
+
+ /*
+ mService.destroyRecoveryParams(recoveryID);
+ try {
+ resp.setContentType("application/x-pkcs12");
+ resp.getOutputStream().write(pkcs12);
+ return;
+ } catch (IOException e) {
+ header.addStringValue(OUT_ERROR,
+ MessageFormatter.getLocalizedString(
+ locale[0],
+ BaseResources.class.getName(),
+ BaseResources.INTERNAL_ERROR_1,
+ e.toString()));
+ }
+ */
+ } else if (((IKeyRecoveryAuthority) mService).getError(recoveryID) != null) {
+ // error in recovery process
+ header.addStringValue(OUT_ERROR,
+ ((IKeyRecoveryAuthority) mService).getError(recoveryID));
+ rComplete = 1;
+ } else {
+ // pk12 hasn't been created yet.
+ }
+ }
+ } catch (EBaseException e) {
+ header.addStringValue(OUT_ERROR, e.toString(locale[0]));
+ rComplete = 1;
+ }
+
+ try {
+ if (rComplete == 1) {
+ mFormPath = "/" + ((IAuthority) mService).getId() + "/" + TPL_FINISH;
+ } else {
+ mFormPath = "/" + ((IAuthority) mService).getId() + "/" + TPL_FILE;
+ }
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ ServletOutputStream out = resp.getOutputStream();
+
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/GetAsyncPk12.java b/base/server/cms/src/com/netscape/cms/servlet/key/GetAsyncPk12.java
new file mode 100644
index 000000000..773b91e65
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/GetAsyncPk12.java
@@ -0,0 +1,265 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Get the recovered key in PKCS#12 format
+ * - for asynchronous key recovery only
+ *
+ */
+public class GetAsyncPk12 extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 6933634840339605800L;
+
+ private final static String INFO = "getAsyncPk12";
+
+ private final static String TPL_FILE = "finishAsyncRecovery.template";
+
+ private final static String IN_PASSWORD = "p12Password";
+ private final static String IN_PASSWORD_AGAIN = "p12PasswordAgain";
+ private final static String OUT_ERROR = "errorDetails";
+
+ private com.netscape.certsrv.kra.IKeyService mService = null;
+
+ private final static String LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS_4";
+
+ private final static String LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE =
+ "LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE_4";
+
+ private String mFormPath = null;
+
+ /**
+ * Constructs getAsyncPk12 servlet.
+ */
+ public GetAsyncPk12() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "finishAsyncRecovery.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/agent/" + mAuthority.getId() + "/" + TPL_FILE;
+ mService = (com.netscape.certsrv.kra.IKeyService) mAuthority;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param reqID request id for recovery
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+ String auditMessage = null;
+ String agent = null;
+ String reqID = null;
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "download");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ // get status and populate argSet
+ try {
+ reqID = req.getParameter("reqID");
+ header.addStringValue("reqID", reqID);
+
+ // only the init DRM agent can get the pkcs12
+ SessionContext sContext = SessionContext.getContext();
+
+ if (sContext != null) {
+ agent = (String) sContext.get(SessionContext.USER_ID);
+ }
+
+ if (agent == null) {
+ CMS.debug("GetAsyncPk12::process() - agent is null!");
+ throw new EBaseException("agent is null");
+ }
+
+ String initAgent = "undefined";
+ initAgent = mService.getInitAgentAsyncKeyRecovery(reqID);
+
+ if ((initAgent.equals("undefined")) || !agent.equals(initAgent)) {
+ log(ILogger.LL_SECURITY,
+ CMS.getLogMessage("CMSGW_INVALID_AGENT_ASYNC_3",
+ reqID, initAgent));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_AGENT_ASYNC",
+ reqID, initAgent));
+ }
+
+ // The async recovery request must be in "approved" state
+ // i.e. all required # of recovery agents approved
+ if (mService.isApprovedAsyncKeyRecovery(reqID) != true) {
+ CMS.debug("GetAsyncPk12::process() - # required recovery agents not met");
+ throw new EBaseException("# required recovery agents not met");
+ }
+
+ String password = req.getParameter(IN_PASSWORD);
+ String passwordAgain = req.getParameter(IN_PASSWORD_AGAIN);
+
+ if (password == null || password.equals("")) {
+ header.addStringValue(OUT_ERROR, "PKCS12 password not found");
+ throw new EBaseException("PKCS12 password not found");
+ }
+ if (passwordAgain == null || !passwordAgain.equals(password)) {
+ header.addStringValue(OUT_ERROR, "PKCS12 password not matched");
+ throw new EBaseException("PKCS12 password not matched");
+ }
+
+ // got all approval, return pk12
+ byte pkcs12[] = mService.doKeyRecovery(reqID, password);
+
+ if (pkcs12 != null) {
+ try {
+ resp.setContentType("application/x-pkcs12");
+ resp.getOutputStream().write(pkcs12);
+ mRenderResult = false;
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS,
+ agent,
+ ILogger.SUCCESS,
+ reqID,
+ "");
+
+ audit(auditMessage);
+
+ return;
+ } catch (IOException e) {
+ header.addStringValue(OUT_ERROR,
+ CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+ } else if (((IKeyRecoveryAuthority) mService).getError(reqID) != null) {
+ // error in recovery process
+ header.addStringValue(OUT_ERROR,
+ ((IKeyRecoveryAuthority) mService).getError(reqID));
+ } else {
+ // pk12 hasn't been created yet. Shouldn't get here
+ }
+ } catch (EBaseException e) {
+ header.addStringValue(OUT_ERROR, e.toString(locale[0]));
+ }
+
+ if ((agent != null) && (reqID != null)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE,
+ agent,
+ ILogger.FAILURE,
+ reqID,
+ "");
+
+ audit(auditMessage);
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/GetPk12.java b/base/server/cms/src/com/netscape/cms/servlet/key/GetPk12.java
new file mode 100644
index 000000000..c79a82f4d
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/GetPk12.java
@@ -0,0 +1,259 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Get the recovered key in PKCS#12 format
+ *
+ * @version $Revision$, $Date$
+ */
+public class GetPk12 extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8974964964333880697L;
+
+ private final static String INFO = "getPk12";
+
+ private final static String TPL_FILE = "finishRecovery.template";
+
+ private final static String OUT_ERROR = "errorDetails";
+
+ private com.netscape.certsrv.kra.IKeyService mService = null;
+
+ private final static String LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS_4";
+
+ private final static String LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE =
+ "LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE_4";
+
+ private String mFormPath = null;
+
+ /**
+ * Constructs getPk12 servlet.
+ */
+ public GetPk12() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "finishRecovery.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/agent/" + mAuthority.getId() + "/" + TPL_FILE;
+ mService = (com.netscape.certsrv.kra.IKeyService) mAuthority;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param recoveryID ID of request to recover
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+ String auditMessage = null;
+ String recoveryID = null;
+ String agent = null;
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "download");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ // get status and populate argSet
+ try {
+ recoveryID = req.getParameter("recoveryID");
+
+ header.addStringValue("recoveryID", recoveryID);
+
+ Hashtable<String, Object> params = mService.getRecoveryParams(recoveryID);
+
+ if (params == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_NO_RECOVERY_TOKEN_FOUND_1", recoveryID));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_NO_RECOVERY_TOKEN_FOUND", recoveryID));
+ }
+
+ // only the init DRM agent can get the pkcs12
+ SessionContext sContext = SessionContext.getContext();
+ if (sContext != null) {
+ agent = (String) sContext.get(SessionContext.USER_ID);
+ }
+
+ if (agent == null) {
+ CMS.debug("GetPk12::process() - agent is null!");
+ throw new EBaseException("agent is null");
+ }
+
+ String initAgent = (String) params.get("agent");
+
+ if (!agent.equals(initAgent)) {
+ log(ILogger.LL_SECURITY,
+
+ CMS.getLogMessage("CMSGW_INVALID_AGENT_3",
+ recoveryID,
+ initAgent));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_AGENT",
+ agent, initAgent, recoveryID));
+ }
+
+ header.addStringValue("serialNumber",
+ (String) params.get("keyID"));
+
+ // got all approval, return pk12
+ byte pkcs12[] = ((IKeyRecoveryAuthority) mService).getPk12(recoveryID);
+
+ if (pkcs12 != null) {
+ mService.destroyRecoveryParams(recoveryID);
+ try {
+ resp.setContentType("application/x-pkcs12");
+ resp.getOutputStream().write(pkcs12);
+ mRenderResult = false;
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS,
+ agent,
+ ILogger.SUCCESS,
+ recoveryID,
+ "");
+
+ audit(auditMessage);
+
+ return;
+ } catch (IOException e) {
+ header.addStringValue(OUT_ERROR,
+ CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+ } else if (((IKeyRecoveryAuthority) mService).getError(recoveryID) != null) {
+ // error in recovery process
+ header.addStringValue(OUT_ERROR,
+ ((IKeyRecoveryAuthority) mService).getError(recoveryID));
+ } else {
+ // pk12 hasn't been created yet. Shouldn't get here
+ }
+ } catch (EBaseException e) {
+ header.addStringValue(OUT_ERROR, e.toString(locale[0]));
+ }
+
+ if ((agent != null) && (recoveryID != null)) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE,
+ agent,
+ ILogger.FAILURE,
+ recoveryID,
+ "");
+
+ audit(auditMessage);
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/GrantAsyncRecovery.java b/base/server/cms/src/com/netscape/cms/servlet/key/GrantAsyncRecovery.java
new file mode 100644
index 000000000..410039133
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/GrantAsyncRecovery.java
@@ -0,0 +1,274 @@
+// --- 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) 2010 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.kra.IKeyService;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Approve an asynchronous key recovery request
+ *
+ */
+public class GrantAsyncRecovery extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4200111795169532676L;
+ private final static String INFO = "grantAsyncRecovery";
+ private final static String TPL_FILE = "grantAsyncRecovery.template";
+
+ private final static String OUT_OP = "op";
+ private final static String OUT_SERVICE_URL = "serviceURL";
+ private final static String OUT_ERROR = "errorDetails";
+
+ private IKeyService mService = null;
+ private String mFormPath = null;
+
+ private final static String LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN =
+ "LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN_4";
+
+ /**
+ * Constructs EA servlet.
+ */
+ public GrantAsyncRecovery() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * 'grantAsyncRecovery.template' to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ mService = (IKeyService) mAuthority;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param reqID request ID of the request to approve
+ * <li>http.param agentID User ID of the agent approving the request
+ *
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ CMS.debug("GrantAsyncRecovery: process() begins");
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "recover");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ String agentID = authToken.getInString("uid");
+ CMS.debug("GrantAsyncRecovery: process() agent uid=" + agentID);
+ CMS.debug("GrantAsyncRecovery: process() request id=" + req.getParameter("reqID"));
+ try {
+ process(argSet, header,
+ req.getParameter("reqID"),
+ agentID,
+ req, resp, locale[0]);
+ } catch (NumberFormatException e) {
+ header.addStringValue(OUT_ERROR,
+ CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Update agent approval list
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN used whenever DRM agents login as recovery agents
+ * to approve key recovery requests
+ * </ul>
+ *
+ * @param argSet CMS template parameters
+ * @param header argument block
+ * @param reqID string containing the recovery request ID
+ * @param agentID string containing the agent ID
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param locale the system locale
+ */
+ private void process(CMSTemplateParams argSet,
+ IArgBlock header, String reqID,
+ String agentID,
+ HttpServletRequest req, HttpServletResponse resp,
+ Locale locale) {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRequestID = reqID;
+ String auditAgentID = agentID;
+
+ // "normalize" the "reqID"
+ if (auditRequestID != null) {
+ auditRequestID = auditRequestID.trim();
+
+ if (auditRequestID.equals("")) {
+ auditRequestID = ILogger.UNIDENTIFIED;
+ }
+ } else {
+ auditRequestID = ILogger.UNIDENTIFIED;
+ }
+
+ // "normalize" the "auditAgentID"
+ if (auditAgentID != null) {
+ auditAgentID = auditAgentID.trim();
+
+ if (auditAgentID.equals("")) {
+ auditAgentID = ILogger.UNIDENTIFIED;
+ }
+ } else {
+ auditAgentID = ILogger.UNIDENTIFIED;
+ }
+
+ try {
+ header.addStringValue(OUT_OP,
+ req.getParameter(OUT_OP));
+ header.addStringValue(OUT_SERVICE_URL,
+ req.getRequestURI());
+
+ // update approving agent list
+ mService.addAgentAsyncKeyRecovery(reqID, agentID);
+
+ header.addStringValue("requestID", reqID);
+ header.addStringValue("agentID", agentID);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequestID,
+ auditAgentID);
+
+ audit(auditMessage);
+
+ } catch (EBaseException e) {
+ header.addStringValue(OUT_ERROR, e.toString(locale));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequestID,
+ auditAgentID);
+
+ audit(auditMessage);
+ } catch (Exception e) {
+ header.addStringValue(OUT_ERROR, e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequestID,
+ auditAgentID);
+
+ audit(auditMessage);
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/GrantRecovery.java b/base/server/cms/src/com/netscape/cms/servlet/key/GrantRecovery.java
new file mode 100644
index 000000000..9d57fbe7c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/GrantRecovery.java
@@ -0,0 +1,303 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Hashtable;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.kra.IKeyService;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Approve a key recovery request
+ *
+ * @version $Revision$, $Date$
+ */
+public class GrantRecovery extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 991970686415492L;
+ private final static String INFO = "grantRecovery";
+ private final static String TPL_FILE = "grantRecovery.template";
+
+ private final static String OUT_OP = "op";
+ private final static String OUT_SERVICE_URL = "serviceURL";
+ private final static String OUT_ERROR = "errorDetails";
+
+ private IKeyService mService = null;
+ private String mFormPath = null;
+
+ private final static String LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN =
+ "LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN_4";
+
+ /**
+ * Constructs EA servlet.
+ */
+ public GrantRecovery() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * 'grantRecovery.template' to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ mService = (IKeyService) mAuthority;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param recoveryID ID of the request to approve
+ * <li>http.param agentID User ID of the agent approving the request
+ * <li>http.param agentPWD Password of the agent approving the request
+ *
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "recover");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ String agentID = authToken.getInString("uid");
+ if (CMS.getConfigStore().getBoolean("kra.keySplitting")) {
+ agentID = req.getParameter("agentID");
+ }
+ try {
+ process(argSet, header,
+ req.getParameter("recoveryID"),
+ agentID,
+ req.getParameter("agentPWD"),
+ req, resp, locale[0]);
+ } catch (NumberFormatException e) {
+ header.addStringValue(OUT_ERROR,
+ CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Recovers a key. The p12 will be protected by the password
+ * provided by the administrator.
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN used whenever DRM agents login as recovery agents
+ * to approve key recovery requests
+ * </ul>
+ *
+ * @param argSet CMS template parameters
+ * @param header argument block
+ * @param recoveryID string containing the recovery ID
+ * @param agentID string containing the agent ID
+ * @param agentPWD string containing the agent password
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param locale the system locale
+ */
+ private void process(CMSTemplateParams argSet,
+ IArgBlock header, String recoveryID,
+ String agentID, String agentPWD,
+ HttpServletRequest req, HttpServletResponse resp,
+ Locale locale) {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRecoveryID = recoveryID;
+ String auditAgentID = agentID;
+
+ // "normalize" the "auditRecoveryID"
+ if (auditRecoveryID != null) {
+ auditRecoveryID = auditRecoveryID.trim();
+
+ if (auditRecoveryID.equals("")) {
+ auditRecoveryID = ILogger.UNIDENTIFIED;
+ }
+ } else {
+ auditRecoveryID = ILogger.UNIDENTIFIED;
+ }
+
+ // "normalize" the "auditAgentID"
+ if (auditAgentID != null) {
+ auditAgentID = auditAgentID.trim();
+
+ if (auditAgentID.equals("")) {
+ auditAgentID = ILogger.UNIDENTIFIED;
+ }
+ } else {
+ auditAgentID = ILogger.UNIDENTIFIED;
+ }
+
+ try {
+ header.addStringValue(OUT_OP,
+ req.getParameter(OUT_OP));
+ header.addStringValue(OUT_SERVICE_URL,
+ req.getRequestURI());
+
+ Hashtable<String, Object> h = mService.getRecoveryParams(recoveryID);
+
+ if (h == null) {
+ header.addStringValue(OUT_ERROR,
+ "No such token found");
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRecoveryID,
+ auditAgentID);
+
+ audit(auditMessage);
+
+ return;
+ }
+ header.addStringValue("serialNumber",
+ (String) h.get("keyID"));
+ header.addStringValue("serialNumberInHex",
+ new BigInteger((String) h.get("keyID")).toString(16));
+
+ mService.addDistributedCredential(recoveryID, agentID, agentPWD);
+ header.addStringValue("agentID",
+ agentID);
+ header.addStringValue("recoveryID",
+ recoveryID);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRecoveryID,
+ auditAgentID);
+
+ audit(auditMessage);
+
+ } catch (EBaseException e) {
+ header.addStringValue(OUT_ERROR, e.toString(locale));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRecoveryID,
+ auditAgentID);
+
+ audit(auditMessage);
+ } catch (Exception e) {
+ header.addStringValue(OUT_ERROR, e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRecoveryID,
+ auditAgentID);
+
+ audit(auditMessage);
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/KeyRecordParser.java b/base/server/cms/src/com/netscape/cms/servlet/key/KeyRecordParser.java
new file mode 100644
index 000000000..256f72879
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/KeyRecordParser.java
@@ -0,0 +1,102 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import java.util.Date;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IPrettyPrintFormat;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+
+/**
+ * Output a 'pretty print' of a Key Archival record
+ *
+ * @version $Revision$, $Date$
+ */
+public class KeyRecordParser {
+
+ public final static String OUT_STATE = "state";
+ public final static String OUT_OWNER_NAME = "ownerName";
+ public final static String OUT_SERIALNO = "serialNumber";
+ public final static String OUT_SERIALNO_IN_HEX = "serialNumberInHex";
+ public final static String OUT_KEY_ALGORITHM = "keyAlgorithm";
+ public final static String OUT_PUBLIC_KEY = "publicKey";
+ public final static String OUT_KEY_LEN = "keyLength";
+ public final static String OUT_KEY_EC_CURVE = "EllipticCurve";
+ public final static String OUT_ARCHIVED_BY = "archivedBy";
+ public final static String OUT_ARCHIVED_ON = "archivedOn";
+ public final static String OUT_RECOVERED_BY = "recoveredBy";
+ public final static String OUT_RECOVERED_ON = "recoveredOn";
+
+ /**
+ * Fills key record into argument block.
+ */
+ public static void fillRecordIntoArg(IKeyRecord rec, IArgBlock rarg)
+ throws EBaseException {
+ if (rec == null)
+ return;
+ rarg.addStringValue(OUT_STATE,
+ rec.getState().toString());
+ rarg.addStringValue(OUT_OWNER_NAME,
+ rec.getOwnerName());
+ rarg.addBigIntegerValue(OUT_SERIALNO,
+ rec.getSerialNumber(), 10);
+ rarg.addBigIntegerValue(OUT_SERIALNO_IN_HEX,
+ rec.getSerialNumber(), 16);
+ rarg.addStringValue(OUT_KEY_ALGORITHM,
+ rec.getAlgorithm());
+ // Possible Enhancement: sun's BASE64Encode is not
+ // fast. We may may to have our native implmenetation.
+ IPrettyPrintFormat pp = CMS.getPrettyPrintFormat(":");
+
+ rarg.addStringValue(OUT_PUBLIC_KEY,
+ pp.toHexString(rec.getPublicKeyData(), 0, 20));
+ Integer keySize = rec.getKeySize();
+
+ if (keySize == null) {
+ rarg.addIntegerValue(OUT_KEY_LEN, 512);
+ } else {
+ rarg.addIntegerValue(OUT_KEY_LEN, keySize.intValue());
+ }
+
+ // handles EC
+ MetaInfo metaInfo = rec.getMetaInfo();
+ if (metaInfo != null) {
+ String curve = (String)metaInfo.get(OUT_KEY_EC_CURVE);
+ if (curve != null) {
+ rarg.addStringValue(OUT_KEY_EC_CURVE, curve);
+ }
+ }
+
+ rarg.addStringValue(OUT_ARCHIVED_BY,
+ rec.getArchivedBy());
+ rarg.addLongValue(OUT_ARCHIVED_ON,
+ rec.getCreateTime().getTime() / 1000);
+ Date dateOfRevocation[] = rec.getDateOfRevocation();
+
+ if (dateOfRevocation != null) {
+ rarg.addStringValue(OUT_RECOVERED_BY,
+ "null");
+ rarg.addStringValue(OUT_RECOVERED_ON,
+ "null");
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java b/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java
new file mode 100644
index 000000000..bef0455a9
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java
@@ -0,0 +1,263 @@
+// --- 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) 2011 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+import com.netscape.certsrv.dbs.keydb.IKeyRepository;
+import com.netscape.certsrv.dbs.keydb.KeyId;
+import com.netscape.certsrv.key.KeyArchivalRequest;
+import com.netscape.certsrv.key.KeyRecoveryRequest;
+import com.netscape.certsrv.key.KeyRequestInfo;
+import com.netscape.certsrv.key.KeyRequestInfos;
+import com.netscape.certsrv.key.KeyRequestResource;
+import com.netscape.certsrv.key.KeyResource;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.request.CMSRequestInfo;
+import com.netscape.certsrv.request.CMSRequestInfos;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.request.CMSRequestDAO;
+
+/**
+ * @author alee
+ *
+ */
+public class KeyRequestDAO extends CMSRequestDAO {
+
+ private static String REQUEST_ARCHIVE_OPTIONS = IEnrollProfile.REQUEST_ARCHIVE_OPTIONS;
+ public static final String ATTR_SERIALNO = "serialNumber";
+
+ private IKeyRepository repo;
+ private IKeyRecoveryAuthority kra;
+
+ public KeyRequestDAO() {
+ super("kra");
+ kra = ( IKeyRecoveryAuthority ) CMS.getSubsystem( "kra" );
+ repo = kra.getKeyRepository();
+ }
+
+ /**
+ * Finds list of requests matching the specified search filter.
+ *
+ * If the filter corresponds to a VLV search, then that search is executed and the pageSize
+ * and start parameters are used. Otherwise, the maxResults and maxTime parameters are
+ * used in the regularly indexed search.
+ *
+ * @param filter - ldap search filter
+ * @param start - start position for VLV search
+ * @param pageSize - page size for VLV search
+ * @param maxResults - max results to be returned in normal search
+ * @param maxTime - max time for normal search
+ * @param uriInfo - uri context of request
+ * @return collection of key request info
+ * @throws EBaseException
+ */
+ @SuppressWarnings("unchecked")
+ public KeyRequestInfos listRequests(String filter, RequestId start, int pageSize, int maxResults, int maxTime,
+ UriInfo uriInfo) throws EBaseException {
+
+ KeyRequestInfos ret = new KeyRequestInfos();
+
+ CMSRequestInfos cmsInfos = listCMSRequests(filter, start, pageSize, maxResults, maxTime, uriInfo);
+
+ Collection<? extends CMSRequestInfo> cmsList = cmsInfos.getRequests();
+
+ // We absolutely know 100% that this list is a list
+ // of KeyRequestInfo objects. This is because the method
+ // createCMSRequestInfo. Is the only one adding to it
+
+ List<KeyRequestInfo> list = (List<KeyRequestInfo>) cmsList;
+ ret.setRequests(list);
+
+ ret.setLinks(cmsInfos.getLinks());
+
+ return ret;
+ }
+
+ /**
+ * Gets info for a specific request
+ *
+ * @param id
+ * @return info for specific request
+ * @throws EBaseException
+ */
+ public KeyRequestInfo getRequest(RequestId id, UriInfo uriInfo) throws EBaseException {
+ IRequest request = queue.findRequest(id);
+ if (request == null) {
+ return null;
+ }
+ KeyRequestInfo info = createKeyRequestInfo(request, uriInfo);
+ return info;
+ }
+
+ /**
+ * Submits an archival request and processes it.
+ *
+ * @param data
+ * @return info for the request submitted.
+ * @throws EBaseException
+ */
+ public KeyRequestInfo submitRequest(KeyArchivalRequest data, UriInfo uriInfo) throws EBaseException {
+ String clientId = data.getClientId();
+ String wrappedSecurityData = data.getWrappedPrivateData();
+ String dataType = data.getDataType();
+
+ boolean keyExists = doesKeyExist(clientId, "active", uriInfo);
+
+ if (keyExists == true) {
+ throw new EBaseException("Can not archive already active existing key!");
+ }
+
+ IRequest request = queue.newRequest(IRequest.SECURITY_DATA_ENROLLMENT_REQUEST);
+
+ request.setExtData(REQUEST_ARCHIVE_OPTIONS, wrappedSecurityData);
+ request.setExtData(IRequest.SECURITY_DATA_CLIENT_ID, clientId);
+ request.setExtData(IRequest.SECURITY_DATA_TYPE, dataType);
+
+ queue.processRequest(request);
+
+ queue.markAsServiced(request);
+
+ return createKeyRequestInfo(request, uriInfo);
+ }
+
+ /**
+ * Submits a key recovery request.
+ *
+ * @param data
+ * @return info on the recovery request created
+ * @throws EBaseException
+ */
+ public KeyRequestInfo submitRequest(KeyRecoveryRequest data, UriInfo uriInfo) throws EBaseException {
+ // set data using request.setExtData(field, data)
+
+ String wrappedSessionKeyStr = data.getTransWrappedSessionKey();
+ String wrappedPassPhraseStr = data.getSessionWrappedPassphrase();
+ String nonceDataStr = data.getNonceData();
+
+ IRequest request = queue.newRequest(IRequest.SECURITY_DATA_RECOVERY_REQUEST);
+
+ KeyId keyId = data.getKeyId();
+
+ Hashtable<String, Object> requestParams;
+
+ requestParams = ((IKeyRecoveryAuthority) authority).createVolatileRequest(request.getRequestId());
+
+ if (requestParams == null) {
+ throw new EBaseException("Can not create Volatile params in submitRequest!");
+ }
+
+ CMS.debug("Create volatile params for recovery request. " + requestParams);
+
+ if (wrappedPassPhraseStr != null) {
+ requestParams.put(IRequest.SECURITY_DATA_SESS_PASS_PHRASE, wrappedPassPhraseStr);
+ }
+
+ if (wrappedSessionKeyStr != null) {
+ requestParams.put(IRequest.SECURITY_DATA_TRANS_SESS_KEY, wrappedSessionKeyStr);
+ }
+
+ if (nonceDataStr != null) {
+ requestParams.put(IRequest.SECURITY_DATA_IV_STRING_IN, nonceDataStr);
+ }
+
+ request.setExtData(ATTR_SERIALNO, keyId.toString());
+
+ queue.processRequest(request);
+
+ return createKeyRequestInfo(request, uriInfo);
+ }
+
+ public void approveRequest(RequestId id) throws EBaseException {
+ IRequest request = queue.findRequest(id);
+ request.setRequestStatus(RequestStatus.APPROVED);
+ queue.updateRequest(request);
+ }
+
+ public void rejectRequest(RequestId id) throws EBaseException {
+ IRequest request = queue.findRequest(id);
+ request.setRequestStatus(RequestStatus.CANCELED);
+ queue.updateRequest(request);
+ }
+
+ public void cancelRequest(RequestId id) throws EBaseException {
+ IRequest request = queue.findRequest(id);
+ request.setRequestStatus(RequestStatus.REJECTED);
+ queue.updateRequest(request);
+ }
+
+ private KeyRequestInfo createKeyRequestInfo(IRequest request, UriInfo uriInfo) {
+ KeyRequestInfo ret = new KeyRequestInfo();
+
+ ret.setRequestType(request.getRequestType());
+ ret.setRequestStatus(request.getRequestStatus());
+
+ Path keyRequestPath = KeyRequestResource.class.getAnnotation(Path.class);
+ RequestId rid = request.getRequestId();
+
+ UriBuilder reqBuilder = uriInfo.getBaseUriBuilder();
+ reqBuilder.path(keyRequestPath.value() + "/" + rid);
+ ret.setRequestURL(reqBuilder.build().toString());
+
+ Path keyPath = KeyResource.class.getAnnotation(Path.class);
+ String kid = request.getExtDataInString("keyrecord");
+
+ UriBuilder keyBuilder = uriInfo.getBaseUriBuilder();
+ keyBuilder.path(keyPath.value() + "/" + kid);
+ ret.setKeyURL(keyBuilder.build().toString());
+
+ return ret;
+ }
+
+ @Override
+ public KeyRequestInfo createCMSRequestInfo(IRequest request, UriInfo uriInfo) {
+ return createKeyRequestInfo(request, uriInfo);
+ }
+
+ //We only care if the key exists or not
+ private boolean doesKeyExist(String clientId, String keyStatus, UriInfo uriInfo) {
+ String state = "active";
+ String filter = "(&(" + IRequest.SECURITY_DATA_CLIENT_ID + "=" + clientId + ")"
+ + "(" + IRequest.SECURITY_DATA_STATUS + "=" + state + "))";
+ try {
+ Enumeration<IKeyRecord> existingKeys = null;
+
+ existingKeys = repo.searchKeys(filter, 1, 10);
+ if (existingKeys != null && existingKeys.hasMoreElements()) {
+ return true;
+ }
+ } catch (EBaseException e) {
+ return false;
+ }
+
+ return false;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/KeyService.java b/base/server/cms/src/com/netscape/cms/servlet/key/KeyService.java
new file mode 100644
index 000000000..f642417e2
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/KeyService.java
@@ -0,0 +1,372 @@
+// --- 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) 2011 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.key;
+
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.HTTPGoneException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.base.UnauthorizedException;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+import com.netscape.certsrv.dbs.keydb.IKeyRepository;
+import com.netscape.certsrv.dbs.keydb.KeyId;
+import com.netscape.certsrv.key.KeyData;
+import com.netscape.certsrv.key.KeyDataInfo;
+import com.netscape.certsrv.key.KeyDataInfos;
+import com.netscape.certsrv.key.KeyRecoveryRequest;
+import com.netscape.certsrv.key.KeyRequestInfo;
+import com.netscape.certsrv.key.KeyResource;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.base.PKIService;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+/**
+ * @author alee
+ *
+ */
+public class KeyService extends PKIService implements KeyResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ private IKeyRepository repo;
+ private IKeyRecoveryAuthority kra;
+ private IRequestQueue queue;
+
+ private final static String LOGGING_SIGNED_AUDIT_SECURITY_DATA_RETRIEVE_KEY =
+ "LOGGING_SIGNED_AUDIT_SECURITY_DATA_RETRIEVE_KEY_5";
+
+ public static final int DEFAULT_MAXRESULTS = 100;
+ public static final int DEFAULT_MAXTIME = 10;
+
+ public KeyService() {
+ kra = ( IKeyRecoveryAuthority ) CMS.getSubsystem( "kra" );
+ repo = kra.getKeyRepository();
+ queue = kra.getRequestQueue();
+ }
+
+ /**
+ * Used to retrieve a key
+ * @param data
+ * @return
+ */
+ public KeyData retrieveKey(KeyRecoveryRequest data) {
+ // auth and authz
+ KeyId keyId = validateRequest(data);
+ RequestId requestID = data.getRequestId();
+ KeyData keyData;
+ try {
+ keyData = getKey(keyId, data);
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ auditRetrieveKey(ILogger.FAILURE, requestID, keyId, e.getMessage());
+ throw new PKIException(e.getMessage());
+ }
+ if (keyData == null) {
+ // no key record
+ auditRetrieveKey(ILogger.FAILURE, requestID, keyId, "No key record");
+ throw new HTTPGoneException("No key record.");
+ }
+ auditRetrieveKey(ILogger.SUCCESS, requestID, keyId, "None");
+ return keyData;
+ }
+
+ // retrieval - used to test integration with a browser
+ public KeyData retrieveKey(MultivaluedMap<String, String> form) {
+ KeyRecoveryRequest data = new KeyRecoveryRequest(form);
+ return retrieveKey(data);
+ }
+
+ public KeyData getKey(KeyId keyId, KeyRecoveryRequest data) throws EBaseException {
+ KeyData keyData;
+
+ RequestId rId = data.getRequestId();
+
+ String transWrappedSessionKey;
+ String sessionWrappedPassphrase;
+
+ IRequest request = queue.findRequest(rId);
+
+ if (request == null) {
+ return null;
+ }
+
+ // get wrapped key
+ IKeyRecord rec = repo.readKeyRecord(keyId.toBigInteger());
+ if (rec == null) {
+ return null;
+ }
+
+ Hashtable<String, Object> requestParams = kra.getVolatileRequest(
+ request.getRequestId());
+
+ if(requestParams == null) {
+ auditRetrieveKey(ILogger.FAILURE, rId, keyId, "cannot obtain volatile requestParams");
+ throw new EBaseException("Can't obtain Volatile requestParams in getKey!");
+ }
+
+ String sessWrappedKeyData = (String) requestParams.get(IRequest.SECURITY_DATA_SESS_WRAPPED_DATA);
+ String passWrappedKeyData = (String) requestParams.get(IRequest.SECURITY_DATA_PASS_WRAPPED_DATA);
+ String nonceData = (String) requestParams.get(IRequest.SECURITY_DATA_IV_STRING_OUT);
+
+ if (sessWrappedKeyData != null || passWrappedKeyData != null) {
+ //The recovery process has already placed a valid recovery
+ //package, either session key wrapped or pass wrapped, into the request.
+ //Request already has been processed.
+ keyData = new KeyData();
+
+ } else {
+ // The request has not yet been processed, let's see if the RecoveryRequestData contains
+ // the info now needed to process the recovery request.
+
+ transWrappedSessionKey = data.getTransWrappedSessionKey();
+ sessionWrappedPassphrase = data.getSessionWrappedPassphrase();
+ nonceData = data.getNonceData();
+
+ if (transWrappedSessionKey == null) {
+ //There must be at least a transWrappedSessionKey input provided.
+ //The command AND the request have provided insufficient data, end of the line.
+ auditRetrieveKey(ILogger.FAILURE, rId, keyId, "insufficient input data");
+ throw new EBaseException("Can't retrieve key, insufficient input data!");
+ }
+
+ if (sessionWrappedPassphrase != null) {
+ requestParams.put(IRequest.SECURITY_DATA_SESS_PASS_PHRASE, sessionWrappedPassphrase);
+ }
+
+ if (transWrappedSessionKey != null) {
+ requestParams.put(IRequest.SECURITY_DATA_TRANS_SESS_KEY, transWrappedSessionKey);
+ }
+
+ if (nonceData != null) {
+ requestParams.put(IRequest.SECURITY_DATA_IV_STRING_IN, nonceData);
+ }
+
+ try {
+ // Has to be in this state or it won't go anywhere.
+ request.setRequestStatus(RequestStatus.BEGIN);
+ queue.processRequest(request);
+ } catch (EBaseException e) {
+ kra.destroyVolatileRequest(request.getRequestId());
+ throw new EBaseException(e.toString());
+ }
+
+ nonceData = null;
+ keyData = new KeyData();
+
+ sessWrappedKeyData = (String) requestParams.get(IRequest.SECURITY_DATA_SESS_WRAPPED_DATA);
+ passWrappedKeyData = (String) requestParams.get(IRequest.SECURITY_DATA_PASS_WRAPPED_DATA);
+ nonceData = (String) requestParams.get(IRequest.SECURITY_DATA_IV_STRING_OUT);
+
+ }
+
+ if (sessWrappedKeyData != null) {
+ keyData.setWrappedPrivateData(sessWrappedKeyData);
+ }
+ if (passWrappedKeyData != null) {
+ keyData.setWrappedPrivateData(passWrappedKeyData);
+ }
+ if (nonceData != null) {
+ keyData.setNonceData(nonceData);
+ }
+
+ kra.destroyVolatileRequest(request.getRequestId());
+
+ queue.markAsServiced(request);
+
+ return keyData;
+ }
+
+ private KeyId validateRequest(KeyRecoveryRequest data) {
+
+ // confirm request exists
+ RequestId reqId = data.getRequestId();
+ if (reqId == null) {
+ auditRetrieveKey(ILogger.FAILURE, null, null, "Request id not found");
+ // log error
+ throw new BadRequestException("Request id not found.");
+ }
+
+ // confirm that at least one wrapping method exists
+ // There must be at least the wrapped session key method.
+ if ((data.getTransWrappedSessionKey() == null)) {
+ auditRetrieveKey(ILogger.FAILURE, reqId, null, "No wrapping method found");
+ // log error
+ throw new BadRequestException("No wrapping method found.");
+ }
+
+ KeyRequestDAO reqDAO = new KeyRequestDAO();
+ KeyRequestInfo reqInfo;
+ try {
+ reqInfo = reqDAO.getRequest(reqId, uriInfo);
+ } catch (EBaseException e1) {
+ auditRetrieveKey(ILogger.FAILURE, reqId, null, "failed to get request");
+ // failed to get request
+ e1.printStackTrace();
+ throw new PKIException(e1.getMessage());
+ }
+ if (reqInfo == null) {
+ auditRetrieveKey(ILogger.FAILURE, reqId, null, "no request info available");
+ // request not found
+ throw new HTTPGoneException("No request information available.");
+ }
+
+ //confirm request is of the right type
+ String type = reqInfo.getRequestType();
+ if (!type.equals(IRequest.SECURITY_DATA_RECOVERY_REQUEST)) {
+ auditRetrieveKey(ILogger.FAILURE, reqId, null, "invalid request type");
+ // log error
+ throw new BadRequestException("Invalid request type");
+ }
+
+ //confirm that agent is originator of request, else throw 401
+ // TO-DO
+
+ // confirm request is in approved state
+ RequestStatus status = reqInfo.getRequestStatus();
+ if (!status.equals(RequestStatus.APPROVED)) {
+ auditRetrieveKey(ILogger.FAILURE, reqId, null, "recovery request not approved");
+ // log error
+ throw new UnauthorizedException("Unauthorized request. Recovery request not approved.");
+ }
+
+ return reqInfo.getKeyId();
+ }
+
+ /**
+ * Used to generate list of key infos based on the search parameters
+ */
+ public KeyDataInfos listKeys(String clientID, String status, Integer maxResults, Integer maxTime) {
+ // auth and authz
+
+ // get ldap filter
+ String filter = createSearchFilter(status, clientID);
+ CMS.debug("listKeys: filter is " + filter);
+
+ maxResults = maxResults == null ? DEFAULT_MAXRESULTS : maxResults;
+ maxTime = maxTime == null ? DEFAULT_MAXTIME : maxTime;
+
+ KeyDataInfos infos = new KeyDataInfos();
+ try {
+ Enumeration<IKeyRecord> e = null;
+
+ e = repo.searchKeys(filter, maxResults, maxTime);
+ if (e == null) {
+ throw new EBaseException("search results are null");
+ }
+
+ while (e.hasMoreElements()) {
+ IKeyRecord rec = e.nextElement();
+ if (rec != null) {
+ infos.addKeyInfo(createKeyDataInfo(rec));
+ }
+ }
+
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ return infos;
+ }
+
+
+ public KeyDataInfo createKeyDataInfo(IKeyRecord rec) throws EBaseException {
+ KeyDataInfo ret = new KeyDataInfo();
+ ret.setClientID(rec.getClientId());
+ ret.setStatus(rec.getKeyStatus());
+ ret.setAlgorithm(rec.getAlgorithm());
+ ret.setSize(rec.getKeySize());
+ ret.setOwnerName(rec.getOwnerName());
+
+ Path keyPath = KeyResource.class.getAnnotation(Path.class);
+ BigInteger serial = rec.getSerialNumber();
+
+ UriBuilder keyBuilder = uriInfo.getBaseUriBuilder();
+ keyBuilder.path(keyPath.value() + "/" + serial);
+ ret.setKeyURL(keyBuilder.build().toString());
+
+ return ret;
+ }
+
+ private String createSearchFilter(String status, String clientID) {
+ String filter = "";
+ int matches = 0;
+
+ if ((status == null) && (clientID == null)) {
+ filter = "(serialno=*)";
+ return filter;
+ }
+
+ if (status != null) {
+ filter += "(status=" + LDAPUtil.escapeFilter(status) + ")";
+ matches ++;
+ }
+
+ if (clientID != null) {
+ filter += "(clientID=" + LDAPUtil.escapeFilter(clientID) + ")";
+ matches ++;
+ }
+
+ if (matches > 1) {
+ filter = "(&" + filter + ")";
+ }
+
+ return filter;
+ }
+
+ public void auditRetrieveKey(String status, RequestId requestID, KeyId keyID, String reason) {
+ String msg = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SECURITY_DATA_RETRIEVE_KEY,
+ servletRequest.getUserPrincipal().getName(),
+ status,
+ requestID != null ? requestID.toString(): "null",
+ keyID != null ? keyID.toString(): "null",
+ reason);
+ auditor.log(msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/RecoverBySerial.java b/base/server/cms/src/com/netscape/cms/servlet/key/RecoverBySerial.java
new file mode 100644
index 000000000..7b961c0b2
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/RecoverBySerial.java
@@ -0,0 +1,534 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.security.Credential;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cmsutil.util.Cert;
+
+/**
+ * A class representing a recoverBySerial servlet.
+ *
+ * @version $Revision$, $Date$
+ */
+public class RecoverBySerial extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4544485601409309840L;
+ private final static String INFO = "recoverBySerial";
+ private final static String TPL_FILE = "recoverBySerial.template";
+
+ private final static String IN_SERIALNO = "serialNumber";
+ private final static String IN_UID = "uid";
+ private final static String IN_PWD = "pwd";
+ private final static String IN_PASSWORD = "p12Password";
+ private final static String IN_PASSWORD_AGAIN = "p12PasswordAgain";
+ private final static String IN_DELIVERY = "p12Delivery";
+ private final static String IN_CERT = "cert";
+ private final static String IN_NICKNAME = "nickname";
+
+ private final static String OUT_OP = "op";
+ private final static String OUT_SERIALNO = IN_SERIALNO;
+ private final static String OUT_SERIALNO_IN_HEX = "serialNumberInHex";
+ private final static String OUT_SERVICE_URL = "serviceURL";
+ private final static String OUT_ERROR = "errorDetails";
+
+ private final static String SCHEME = "scheme";
+ private final static String HOST = "host";
+ private final static String PORT = "port";
+
+ private com.netscape.certsrv.kra.IKeyService mService = null;
+ private String mFormPath = null;
+
+ /**
+ * Constructs EA servlet.
+ */
+ public RecoverBySerial() {
+ super();
+ }
+
+ /**
+ * Initializes the servlet.
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ mService = (com.netscape.certsrv.kra.IKeyService) mAuthority;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Serves HTTP request. The format of this request is as follows:
+ * recoverBySerial?
+ * [serialNumber=<number>]
+ * [uid#=<uid>]
+ * [pwd#=<password>]
+ * [localAgents=yes|null]
+ * [recoveryID=recoveryID]
+ * [pkcs12Password=<password of pkcs12>]
+ * [pkcs12PasswordAgain=<password of pkcs12>]
+ * [pkcs12Delivery=<delivery mechanism for pkcs12>]
+ * [cert=<encryption certificate>]
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "recover");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ // set host name and port.
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ String host = httpReq.getServerName();
+ int port = httpReq.getServerPort();
+ String scheme = httpReq.getScheme();
+
+ fixed.set(HOST, host);
+ fixed.set(PORT, Integer.valueOf(port));
+ fixed.set(SCHEME, scheme);
+
+ SessionContext ctx = null;
+
+ try {
+ String initAsyncRecovery = req.getParameter("initAsyncRecovery");
+
+ // this information is needed within the server for
+ // various signed audit log messages to report
+ ctx = SessionContext.getContext();
+
+ /*
+ When Recovery is first initiated, if it is in asynch mode,
+ no pkcs#12 password is needed.
+ The initiating agent uid will be recorded in the recovery
+ request.
+ Later, as approving agents submit their approvals, they will
+ also be listed in the request.
+ */
+ if ((initAsyncRecovery != null) &&
+ initAsyncRecovery.equalsIgnoreCase("ON")) {
+ process(form, argSet, header,
+ req.getParameter(IN_SERIALNO),
+ req.getParameter(IN_CERT),
+ req, resp, locale[0]);
+
+ int requiredNumber = mService.getNoOfRequiredAgents();
+ header.addIntegerValue("noOfRequiredAgents", requiredNumber);
+ } else {
+ String recoveryID = req.getParameter("recoveryID");
+
+ if (recoveryID != null && !recoveryID.equals("")) {
+ ctx.put(SessionContext.RECOVERY_ID,
+ req.getParameter("recoveryID"));
+ }
+ byte pkcs12[] = process(form, argSet, header,
+ req.getParameter(IN_SERIALNO),
+ req.getParameter("localAgents"),
+ req.getParameter(IN_PASSWORD),
+ req.getParameter(IN_PASSWORD_AGAIN),
+ req.getParameter(IN_CERT),
+ req.getParameter(IN_DELIVERY),
+ req.getParameter(IN_NICKNAME),
+ req, resp, locale[0]);
+
+ if (pkcs12 != null) {
+ //resp.setStatus(HttpServletResponse.SC_OK);
+ resp.setContentType("application/x-pkcs12");
+ //resp.setContentLength(pkcs12.length);
+ resp.getOutputStream().write(pkcs12);
+ mRenderResult = false;
+ return;
+ }
+ }
+ } catch (NumberFormatException e) {
+ header.addStringValue(OUT_ERROR,
+ CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString()));
+ } catch (IOException e) {
+ header.addStringValue(OUT_ERROR,
+ CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString()));
+ } finally {
+ SessionContext.releaseContext();
+ }
+
+ // return status page
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Async Key Recovery - request initiation
+ */
+ private void process(CMSTemplate form, CMSTemplateParams argSet,
+ IArgBlock header, String seq, String cert,
+ HttpServletRequest req, HttpServletResponse resp,
+ Locale locale) {
+
+ // seq is the key id
+ if (seq == null) {
+ header.addStringValue(OUT_ERROR, "sequence number not found");
+ return;
+ }
+ X509CertImpl x509cert = null;
+
+ if (cert == null || cert.trim().length() == 0) {
+ header.addStringValue(OUT_ERROR, "certificate not found");
+ return;
+ } else {
+ try {
+ x509cert = Cert.mapCert(cert);
+ } catch (IOException e) {
+ header.addStringValue(OUT_ERROR, e.toString());
+ }
+ }
+ if (x509cert == null) {
+ header.addStringValue(OUT_ERROR, "invalid X.509 certificate");
+ return;
+ }
+
+ SessionContext sContext = SessionContext.getContext();
+
+ try {
+ String reqID = mService.initAsyncKeyRecovery(
+ new BigInteger(seq), x509cert,
+ (String) sContext.get(SessionContext.USER_ID));
+ header.addStringValue(OUT_SERIALNO, req.getParameter(IN_SERIALNO));
+ header.addStringValue(OUT_SERIALNO_IN_HEX,
+ new BigInteger(req.getParameter(IN_SERIALNO)).toString(16));
+ header.addStringValue("requestID", reqID);
+ } catch (EBaseException e) {
+ String error =
+ "Failed to recover key for key id " +
+ seq + ".\nException: " + e.toString();
+
+ CMS.getLogger().log(ILogger.EV_SYSTEM,
+ ILogger.S_KRA, ILogger.LL_FAILURE, error);
+ try {
+ ((IKeyRecoveryAuthority) mService).createError(seq, error);
+ } catch (EBaseException eb) {
+ CMS.getLogger().log(ILogger.EV_SYSTEM,
+ ILogger.S_KRA, ILogger.LL_FAILURE, eb.toString());
+ }
+ }
+ return;
+ }
+
+ /**
+ * Recovers a key. The p12 will be protected by the password
+ * provided by the administrator.
+ */
+ private byte[] process(CMSTemplate form, CMSTemplateParams argSet,
+ IArgBlock header, String seq, String localAgents,
+ String password, String passwordAgain,
+ String cert, String delivery, String nickname,
+ HttpServletRequest req, HttpServletResponse resp,
+ Locale locale) {
+ if (seq == null) {
+ header.addStringValue(OUT_ERROR, "sequence number not found");
+ return null;
+ }
+ if (password == null || password.equals("")) {
+ header.addStringValue(OUT_ERROR, "PKCS12 password not found");
+ return null;
+ }
+ if (passwordAgain == null || !passwordAgain.equals(password)) {
+ header.addStringValue(OUT_ERROR, "PKCS12 password not matched");
+ return null;
+ }
+ X509CertImpl x509cert = null;
+
+ if (cert == null || cert.trim().length() == 0) {
+ // perform recovery
+ header.addStringValue(OUT_ERROR, "certificate not found");
+ return null;
+ } else {
+ try {
+ x509cert = Cert.mapCert(cert);
+ } catch (IOException e) {
+ header.addStringValue(OUT_ERROR, e.toString());
+ }
+ }
+ if (x509cert == null) {
+ header.addStringValue(OUT_ERROR, "invalid X.509 certificate");
+ return null;
+ }
+ try {
+ Credential creds[] = null;
+
+ SessionContext sContext = SessionContext.getContext();
+ String agent = null;
+
+ if (sContext != null) {
+ agent = (String) sContext.get(SessionContext.USER_ID);
+ }
+ if (CMS.getConfigStore().getBoolean("kra.keySplitting")) {
+ if (localAgents == null) {
+ String recoveryID = req.getParameter("recoveryID");
+
+ if (recoveryID == null || recoveryID.equals("")) {
+ header.addStringValue(OUT_ERROR, "No recovery ID specified");
+ return null;
+ }
+ Hashtable<String, Object> params = mService.createRecoveryParams(recoveryID);
+
+ params.put("keyID", req.getParameter(IN_SERIALNO));
+
+ header.addStringValue("recoveryID", recoveryID);
+
+ params.put("agent", agent);
+
+ // new thread to wait for pk12
+ Thread waitThread = new WaitApprovalThread(recoveryID,
+ seq, password, x509cert, delivery, nickname,
+ SessionContext.getContext());
+
+ waitThread.start();
+ return null;
+ } else {
+ Vector<Credential> v = new Vector<Credential>();
+
+ for (int i = 0; i < mService.getNoOfRequiredAgents(); i++) {
+ String uid = req.getParameter(IN_UID + i);
+ String pwd = req.getParameter(IN_PWD + i);
+
+ if (uid != null && pwd != null && !uid.equals("") &&
+ !pwd.equals("")) {
+ v.addElement(new Credential(uid, pwd));
+ } else {
+ header.addStringValue(OUT_ERROR, "Uid(s) or password(s) are not provided");
+ return null;
+ }
+ }
+ if (v.size() != mService.getNoOfRequiredAgents()) {
+ header.addStringValue(OUT_ERROR, "Uid(s) or password(s) are not provided");
+ return null;
+ }
+ creds = new Credential[v.size()];
+ v.copyInto(creds);
+ }
+
+ header.addStringValue(OUT_OP,
+ req.getParameter(OUT_OP));
+ header.addBigIntegerValue(OUT_SERIALNO,
+ new BigInteger(seq), 10);
+ header.addBigIntegerValue(OUT_SERIALNO_IN_HEX,
+ new BigInteger(seq), 16);
+ header.addStringValue(OUT_SERVICE_URL,
+ req.getRequestURI());
+ byte pkcs12[] = mService.doKeyRecovery(
+ new BigInteger(seq),
+ creds, password, x509cert,
+ delivery, nickname, agent);
+
+ return pkcs12;
+ } else {
+ String recoveryID = req.getParameter("recoveryID");
+
+ if (recoveryID == null || recoveryID.equals("")) {
+ header.addStringValue(OUT_ERROR, "No recovery ID specified");
+ return null;
+ }
+ Hashtable<String, Object> params = mService.createRecoveryParams(recoveryID);
+
+ params.put("keyID", req.getParameter(IN_SERIALNO));
+
+ header.addStringValue("recoveryID", recoveryID);
+
+ params.put("agent", agent);
+
+ // new thread to wait for pk12
+ Thread waitThread = new WaitApprovalThread(recoveryID,
+ seq, password, x509cert, delivery, nickname,
+ SessionContext.getContext());
+
+ waitThread.start();
+ return null;
+ }
+ } catch (EBaseException e) {
+ header.addStringValue(OUT_ERROR, e.toString(locale));
+ } catch (Exception e) {
+ header.addStringValue(OUT_ERROR, e.toString());
+ }
+ return null;
+ }
+
+ /**
+ * Wait approval thread. Wait for recovery agents' approval
+ * exit when required number of approval received
+ */
+ final class WaitApprovalThread extends Thread {
+ String theRecoveryID = null;
+ String theSeq = null;
+ String thePassword = null;
+ X509CertImpl theCert = null;
+ String theDelivery = null;
+ String theNickname = null;
+ SessionContext theSc = null;
+
+ /**
+ * Wait approval thread constructor including thread name
+ */
+ public WaitApprovalThread(String recoveryID, String seq,
+ String password, X509CertImpl cert,
+ String delivery, String nickname, SessionContext sc) {
+ super();
+ super.setName("waitApproval." + recoveryID + "-" +
+ (Thread.activeCount() + 1));
+ theRecoveryID = recoveryID;
+ theSeq = seq;
+ thePassword = password;
+ theCert = cert;
+ theDelivery = delivery;
+ theNickname = nickname;
+ theSc = sc;
+ }
+
+ public void run() {
+ SessionContext.setContext(theSc);
+ Credential creds[] = null;
+
+ try {
+ creds = mService.getDistributedCredentials(theRecoveryID);
+ } catch (EBaseException e) {
+ String error =
+ "Failed to get required approvals for recovery id " +
+ theRecoveryID + ".\nException: " + e.toString();
+
+ CMS.getLogger().log(ILogger.EV_SYSTEM,
+ ILogger.S_KRA, ILogger.LL_FAILURE, error);
+ try {
+ ((IKeyRecoveryAuthority) mService).createError(theRecoveryID, error);
+ } catch (EBaseException eb) {
+ CMS.getLogger().log(ILogger.EV_SYSTEM,
+ ILogger.S_KRA, ILogger.LL_FAILURE, eb.toString());
+ }
+ return;
+ }
+
+ SessionContext sContext = SessionContext.getContext();
+
+ try {
+ byte pkcs12[] = mService.doKeyRecovery(
+ new BigInteger(theSeq),
+ creds, thePassword, theCert,
+ theDelivery, theNickname,
+ (String) sContext.get(SessionContext.USER_ID));
+
+ ((IKeyRecoveryAuthority) mService).createPk12(theRecoveryID, pkcs12);
+ } catch (EBaseException e) {
+ String error =
+ "Failed to recover key for recovery id " +
+ theRecoveryID + ".\nException: " + e.toString();
+
+ CMS.getLogger().log(ILogger.EV_SYSTEM,
+ ILogger.S_KRA, ILogger.LL_FAILURE, error);
+ try {
+ ((IKeyRecoveryAuthority) mService).createError(theRecoveryID, error);
+ } catch (EBaseException eb) {
+ CMS.getLogger().log(ILogger.EV_SYSTEM,
+ ILogger.S_KRA, ILogger.LL_FAILURE, eb.toString());
+ }
+ }
+ return;
+ }
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/SrchKey.java b/base/server/cms/src/com/netscape/cms/servlet/key/SrchKey.java
new file mode 100644
index 000000000..5bedf1f58
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/SrchKey.java
@@ -0,0 +1,298 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X500Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+import com.netscape.certsrv.dbs.keydb.IKeyRepository;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Retrieve archived keys matching search criteria
+ *
+ * @version $Revision$, $Date$
+ */
+public class SrchKey extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6404955402865756665L;
+ private final static String TPL_FILE = "srchKey.template";
+ private final static String INFO = "srchKey";
+ private final static String PROP_MAX_SEARCH_RETURNS = "maxSearchReturns";
+
+ // input parameters
+ private final static String IN_MAXCOUNT = "maxCount";
+ private final static String IN_FILTER = "queryFilter";
+ private final static String IN_SENTINEL = "querySentinel";
+
+ // output parameters
+ private final static String OUT_FILTER = IN_FILTER;
+ private final static String OUT_MAXCOUNT = IN_MAXCOUNT;
+ private final static String OUT_SENTINEL = IN_SENTINEL;
+ private final static String OUT_OP = "op";
+ private final static String OUT_ERROR = "errorDetails";
+ private final static String OUT_ARCHIVER = "archiverName";
+ private final static String OUT_SERVICE_URL = "serviceURL";
+ private final static String OUT_TOTAL_COUNT = "totalRecordCount";
+ private final static String OUT_TEMPLATE = "templateName";
+
+ private IKeyRepository mKeyDB = null;
+ private X500Name mAuthName = null;
+ private String mFormPath = null;
+ private int mMaxReturns = 100;
+ private int mTimeLimits = 30; /* in seconds */
+
+ /**
+ * Constructs query key servlet.
+ */
+ public SrchKey() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "srchKey.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ /* maxReturns doesn't seem to do anything useful in this
+ servlet!!! */
+ try {
+ String tmp =
+ sc.getInitParameter(PROP_MAX_SEARCH_RETURNS);
+
+ if (tmp == null)
+ mMaxReturns = 100;
+ else
+ mMaxReturns = Integer.parseInt(tmp);
+ } catch (Exception e) {
+ // do nothing
+ }
+
+ mKeyDB = ((IKeyRecoveryAuthority) mAuthority).getKeyRepository();
+ mAuthName = ((IKeyRecoveryAuthority) mAuthority).getX500Name();
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+
+ /* Server-Side time limit */
+ try {
+ mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits"));
+ } catch (Exception e) {
+ /* do nothing, just use the default if integer parsing failed */
+ }
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param maxCount maximum number of matches to show in result
+ * <li>http.param maxResults maximum number of matches to run in ldapsearch
+ * <li>http.param queryFilter ldap-style filter to search with
+ * <li>http.param querySentinel ID of first request to show
+ * <li>http.param timeLimit number of seconds to limit ldap search to
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "list");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ // process query if authentication is successful
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ int maxCount = -1;
+ int sentinel = 0;
+ int maxResults = -1;
+ int timeLimit = -1;
+
+ try {
+ if (req.getParameter(IN_MAXCOUNT) != null) {
+ maxCount = Integer.parseInt(
+ req.getParameter(IN_MAXCOUNT));
+ }
+ if (req.getParameter(IN_SENTINEL) != null) {
+ sentinel = Integer.parseInt(
+ req.getParameter(IN_SENTINEL));
+ }
+ String maxResultsStr = req.getParameter("maxResults");
+
+ if (maxResultsStr != null && maxResultsStr.length() > 0)
+ maxResults = Integer.parseInt(maxResultsStr);
+ String timeLimitStr = req.getParameter("timeLimit");
+
+ if (timeLimitStr != null && timeLimitStr.length() > 0)
+ timeLimit = Integer.parseInt(timeLimitStr);
+ process(argSet, header, ctx, maxCount, maxResults,
+ timeLimit, sentinel,
+ req.getParameter(IN_FILTER), req, resp, locale[0]);
+ } catch (NumberFormatException e) {
+ header.addStringValue(OUT_ERROR,
+ CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Process the key search.
+ */
+ private void process(CMSTemplateParams argSet,
+ IArgBlock header, IArgBlock ctx,
+ int maxCount, int maxResults, int timeLimit, int sentinel, String filter,
+ HttpServletRequest req, HttpServletResponse resp, Locale locale) {
+
+ try {
+ // Fill header
+ header.addStringValue(OUT_OP,
+ req.getParameter(OUT_OP));
+ header.addStringValue(OUT_ARCHIVER,
+ mAuthName.toString());
+ // STRANGE: IE does not like the following:
+ // header.addStringValue(OUT_SERVICE_URL,
+ // req.getRequestURI());
+ // XXX
+ header.addStringValue(OUT_SERVICE_URL,
+ "/kra?");
+ header.addStringValue(OUT_TEMPLATE,
+ TPL_FILE);
+ header.addStringValue(OUT_FILTER,
+ filter);
+
+ if (timeLimit == -1 || timeLimit > mTimeLimits) {
+ CMS.debug("Resetting timelimit from " + timeLimit + " to " + mTimeLimits);
+ timeLimit = mTimeLimits;
+ }
+ CMS.debug("Start searching ... timelimit=" + timeLimit);
+ Enumeration<IKeyRecord> e = mKeyDB.searchKeys(filter,
+ maxResults, timeLimit);
+ int count = 0;
+
+ if (e == null) {
+ header.addStringValue(OUT_SENTINEL,
+ null);
+ } else {
+ while (e.hasMoreElements()) {
+ IKeyRecord rec = e.nextElement();
+ // rec is null when we specify maxResults
+ // DS will return an err=4, which triggers
+ // a LDAPException.SIZE_LIMIT_ExCEEDED
+ // in DSSearchResults.java
+ if (rec != null) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ KeyRecordParser.fillRecordIntoArg(rec, rarg);
+ argSet.addRepeatRecord(rarg);
+ count++;
+ }
+ }
+ }
+
+ header.addIntegerValue("maxSize", mMaxReturns);
+ header.addIntegerValue(OUT_TOTAL_COUNT, count);
+ ctx.addIntegerValue(OUT_MAXCOUNT, maxCount);
+ } catch (EBaseException e) {
+ header.addStringValue(OUT_ERROR, e.toString(locale));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/SrchKeyForRecovery.java b/base/server/cms/src/com/netscape/cms/servlet/key/SrchKeyForRecovery.java
new file mode 100644
index 000000000..897acfc76
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/SrchKeyForRecovery.java
@@ -0,0 +1,318 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.key;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X500Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+import com.netscape.certsrv.dbs.keydb.IKeyRepository;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Retrieve archived keys matching given public key material
+ *
+ *
+ * @version $Revision$, $Date$
+ */
+public class SrchKeyForRecovery extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5426987963811540460L;
+ private final static String TPL_FILE = "srchKeyForRecovery.template";
+ private final static String INFO = "srchKey";
+ private final static String PROP_MAX_SEARCH_RETURNS = "maxSearchReturns";
+
+ // input parameters
+ private final static String IN_MAXCOUNT = "maxCount";
+ private final static String IN_FILTER = "queryFilter";
+ private final static String IN_SENTINEL = "querySentinel";
+
+ // output parameters
+ private final static String OUT_FILTER = IN_FILTER;
+ private final static String OUT_MAXCOUNT = IN_MAXCOUNT;
+ private final static String OUT_SENTINEL = IN_SENTINEL;
+ private final static String OUT_OP = "op";
+ private final static String OUT_ARCHIVER = "archiverName";
+ private final static String OUT_SERVICE_URL = "serviceURL";
+ private final static String OUT_TOTAL_COUNT = "totalRecordCount";
+ private final static String OUT_TEMPLATE = "templateName";
+
+ private IKeyRepository mKeyDB = null;
+ private X500Name mAuthName = null;
+ private String mFormPath = null;
+ private int mMaxReturns = 100;
+ private int mTimeLimits = 30; /* in seconds */
+
+ /**
+ * Constructs query key servlet.
+ */
+ public SrchKeyForRecovery() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "srchKeyForRecovery.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ try {
+ String tmp =
+ sc.getInitParameter(PROP_MAX_SEARCH_RETURNS);
+
+ if (tmp == null)
+ mMaxReturns = 100;
+ else
+ mMaxReturns = Integer.parseInt(tmp);
+ } catch (Exception e) {
+ // do nothing
+ }
+
+ mKeyDB = ((IKeyRecoveryAuthority) mAuthority).getKeyRepository();
+ mAuthName = ((IKeyRecoveryAuthority) mAuthority).getX500Name();
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+
+ /* Server-Side time limit */
+ try {
+ mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits"));
+ } catch (Exception e) {
+ /* do nothing, just use the default if integer parsing failed */
+ }
+ }
+
+ /**
+ * Returns serlvet information.
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param maxCount maximum number of matches to show in result
+ * <li>http.param maxResults maximum number of matches to run in ldapsearch
+ * <li>http.param publicKeyData public key data to search on
+ * <li>http.param querySentinel ID of first request to show
+ * <li>http.param timeLimit number of seconds to limit ldap search to
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+
+ public void process(CMSRequest cmsReq) throws EBaseException {
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "list");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ // process query if authentication is successful
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+ EBaseException error = null;
+
+ int maxCount = -1;
+ int sentinel = 0;
+ int maxResults = -1;
+ int timeLimit = -1;
+
+ try {
+ if (req.getParameter(IN_MAXCOUNT) != null) {
+ maxCount = Integer.parseInt(
+ req.getParameter(IN_MAXCOUNT));
+ }
+ if (req.getParameter(IN_SENTINEL) != null) {
+ sentinel = Integer.parseInt(
+ req.getParameter(IN_SENTINEL));
+ }
+ String maxResultsStr = req.getParameter("maxResults");
+
+ if (maxResultsStr != null && maxResultsStr.length() > 0)
+ maxResults = Integer.parseInt(maxResultsStr);
+ String timeLimitStr = req.getParameter("timeLimit");
+
+ if (timeLimitStr != null && timeLimitStr.length() > 0)
+ timeLimit = Integer.parseInt(timeLimitStr);
+ process(argSet, header, ctx, maxCount, maxResults, timeLimit, sentinel,
+ req.getParameter("publicKeyData"), req.getParameter(IN_FILTER), req, resp, locale[0]);
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT"));
+ error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT"));
+ }
+
+ /*
+ catch (Exception e) {
+ error = new EBaseException(BaseResources.INTERNAL_ERROR_1, e);
+ }
+ */
+
+ try {
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ ServletOutputStream out = resp.getOutputStream();
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ /**
+ * Process the key search.
+ */
+ private void process(CMSTemplateParams argSet,
+ IArgBlock header, IArgBlock ctx,
+ int maxCount, int maxResults, int timeLimit, int sentinel, String publicKeyData,
+ String filter,
+ HttpServletRequest req, HttpServletResponse resp, Locale locale)
+ throws EBaseException {
+
+ try {
+ // Fill header
+ header.addStringValue(OUT_OP,
+ req.getParameter(OUT_OP));
+ header.addStringValue(OUT_ARCHIVER,
+ mAuthName.toString());
+ // STRANGE: IE does not like the following:
+ // header.addStringValue(OUT_SERVICE_URL,
+ // req.getRequestURI());
+ // XXX
+ header.addStringValue(OUT_SERVICE_URL,
+ "/kra?");
+ header.addStringValue(OUT_TEMPLATE,
+ TPL_FILE);
+ header.addStringValue(OUT_FILTER,
+ filter);
+ if (publicKeyData != null) {
+ header.addStringValue("publicKeyData",
+ publicKeyData);
+ }
+
+ if (timeLimit == -1 || timeLimit > mTimeLimits) {
+ CMS.debug("Resetting timelimit from " + timeLimit + " to " + mTimeLimits);
+ timeLimit = mTimeLimits;
+ }
+ CMS.debug("Start searching ... timelimit=" + timeLimit);
+ Enumeration<IKeyRecord> e = mKeyDB.searchKeys(filter, maxResults, timeLimit);
+ int count = 0;
+
+ if (e == null) {
+ header.addStringValue(OUT_SENTINEL,
+ null);
+ } else {
+ while (e.hasMoreElements()) {
+ IKeyRecord rec = e.nextElement();
+ // rec is null when we specify maxResults
+ // DS will return an err=4, which triggers
+ // a LDAPException.SIZE_LIMIT_ExCEEDED
+ // in DSSearchResults.java
+ if (rec != null) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ KeyRecordParser.fillRecordIntoArg(rec, rarg);
+ argSet.addRepeatRecord(rarg);
+ count++;
+ }
+ }
+ }
+
+ header.addIntegerValue("maxSize", mMaxReturns);
+ header.addIntegerValue(OUT_TOTAL_COUNT, count);
+ ctx.addIntegerValue(OUT_MAXCOUNT, maxCount);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, "Error " + e);
+ throw e;
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/ocsp/AddCAServlet.java b/base/server/cms/src/com/netscape/cms/servlet/ocsp/AddCAServlet.java
new file mode 100644
index 000000000..f19a9d646
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/ocsp/AddCAServlet.java
@@ -0,0 +1,311 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.ocsp;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ocsp.IDefStore;
+import com.netscape.certsrv.ocsp.IOCSPAuthority;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cmsutil.util.Cert;
+
+/**
+ * Configure the CA to respond to OCSP requests for a CA
+ *
+ * @version $Revision$ $Date$
+ */
+public class AddCAServlet extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1065151608542115340L;
+ public static final String BEGIN_HEADER =
+ "-----BEGIN CERTIFICATE-----";
+ public static final String END_HEADER =
+ "-----END CERTIFICATE-----";
+
+ public static final BigInteger BIG_ZERO = new BigInteger("0");
+ public static final Long MINUS_ONE = Long.valueOf(-1);
+
+ private final static String TPL_FILE = "addCA.template";
+ private String mFormPath = null;
+ private IOCSPAuthority mOCSPAuthority = null;
+
+ private final static String LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST =
+ "LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_3";
+ private final static String LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED =
+ "LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED_3";
+
+ public AddCAServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "addCA.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success to display own output.
+
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ mOCSPAuthority = (IOCSPAuthority) mAuthority;
+
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param cert ca certificate. The format is base-64, DER encoded, wrapped with -----BEGIN CERTIFICATE-----,
+ * -----END CERTIFICATE----- strings
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST used when a CA is attempted to be added to the OCSP
+ * responder
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED used when an add CA request to the OCSP
+ * Responder is processed
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditCA = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ String auditCASubjectDN = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "add");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ if (auditSubjectID.equals(ILogger.NONROLEUSER) ||
+ auditSubjectID.equals(ILogger.UNIDENTIFIED)) {
+ String uid = authToken.getInString(IAuthToken.USER_ID);
+ if (uid != null) {
+ CMS.debug("AddCAServlet: auditSubjectID set to " + uid);
+ auditSubjectID = uid;
+ }
+ }
+ String b64 = cmsReq.getHttpReq().getParameter("cert");
+
+ if (b64 == null) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CA_CERT"));
+ }
+
+ auditCA = Cert.normalizeCertStr(Cert.stripCertBrackets(b64.trim()));
+ // record the fact that a request to add CA is made
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditCA);
+
+ audit(auditMessage);
+
+ if (b64.indexOf(BEGIN_HEADER) == -1) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditCASubjectDN);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CERT_HEADER"));
+ }
+ if (b64.indexOf(END_HEADER) == -1) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditCASubjectDN);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CERT_FOOTER"));
+ }
+
+ IDefStore defStore = mOCSPAuthority.getDefaultStore();
+
+ X509Certificate leafCert = null;
+ X509Certificate certs[] = null;
+
+ try {
+ X509Certificate cert = Cert.mapCert(b64);
+
+ if (cert == null) {
+ CMS.debug("AddCAServlet::process() - cert is null!");
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditCASubjectDN);
+
+ audit(auditMessage);
+
+ throw new EBaseException("cert is null");
+ } else {
+ certs = new X509Certificate[1];
+ }
+
+ certs[0] = cert;
+ leafCert = cert;
+ auditCASubjectDN = leafCert.getSubjectDN().getName();
+ } catch (Exception e) {
+ }
+ if (certs == null) {
+ try {
+ // this could be a chain
+ certs = Cert.mapCertFromPKCS7(b64);
+ if (certs[0].getSubjectDN().getName().equals(certs[0].getIssuerDN().getName())) {
+ leafCert = certs[certs.length - 1];
+ } else {
+ leafCert = certs[0];
+ }
+ auditCASubjectDN = leafCert.getSubjectDN().getName();
+ } catch (Exception e) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditCASubjectDN);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_ENCODING_CA_CHAIN_ERROR"));
+ }
+ }
+ if (certs != null && certs.length > 0) {
+ // (1) need to normalize (sort) the chain
+
+ // (2) store certificate (and certificate chain) into
+ // database
+ ICRLIssuingPointRecord rec = defStore.createCRLIssuingPointRecord(
+ leafCert.getSubjectDN().getName(),
+ BIG_ZERO,
+ MINUS_ONE, null, null);
+
+ try {
+ rec.set(ICRLIssuingPointRecord.ATTR_CA_CERT, leafCert.getEncoded());
+ } catch (Exception e) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditCASubjectDN);
+
+ audit(auditMessage);
+
+ // error
+ }
+ defStore.addCRLIssuingPoint(leafCert.getSubjectDN().getName(), rec);
+ log(ILogger.EV_AUDIT, AuditFormat.LEVEL, "Added CA certificate " + leafCert.getSubjectDN().getName());
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditCASubjectDN);
+
+ audit(auditMessage);
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/ocsp/AddCRLServlet.java b/base/server/cms/src/com/netscape/cms/servlet/ocsp/AddCRLServlet.java
new file mode 100644
index 000000000..ac1aad373
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/ocsp/AddCRLServlet.java
@@ -0,0 +1,614 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.ocsp;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CRLException;
+import java.security.cert.X509CRL;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X509CRLImpl;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509ExtensionException;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+import com.netscape.certsrv.dbs.repository.IRepositoryRecord;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ocsp.IDefStore;
+import com.netscape.certsrv.ocsp.IOCSPAuthority;
+import com.netscape.certsrv.util.IStatsSubsystem;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cmsutil.util.Cert;
+
+/**
+ * Update the OCSP responder with a new CRL
+ *
+ * @version $Revision$ $Date$
+ */
+public class AddCRLServlet extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1476080474638590902L;
+ public static final String BEGIN_HEADER =
+ "-----BEGIN CERTIFICATE REVOCATION LIST-----";
+ public static final String END_HEADER =
+ "-----END CERTIFICATE REVOCATION LIST-----";
+
+ private final static String TPL_FILE = "addCRL.template";
+ private String mFormPath = null;
+ private IOCSPAuthority mOCSPAuthority = null;
+
+ private final static String LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL =
+ "LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL_3";
+ private final static String LOGGING_SIGNED_AUDIT_CRL_VALIDATION =
+ "LOGGING_SIGNED_AUDIT_CRL_VALIDATION_2";
+
+ public AddCRLServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "addCRL.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success to display own output.
+
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ mOCSPAuthority = (IOCSPAuthority) mAuthority;
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <P>
+ *
+ * <ul>
+ * <li>http.param crl certificate revocation list, base-64, DER encoded wrapped in -----BEGIN CERTIFICATE REVOCATION
+ * LIST-----, -----END CERTIFICATE REVOCATION LIST----- strings
+ * <li>http.param noui if true, use minimal hardcoded text response
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL used when CRLs are retrieved by the OCSP Responder ("agent"
+ * or "EE")
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CRL_VALIDATION used when CRL is retrieved and validation process occurs
+ * ("agent" or "EE")
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ * @exception EBaseException an error has occurred
+ */
+ protected synchronized void process(CMSRequest cmsReq)
+ throws EBaseException {
+ boolean CRLFetched = false;
+ boolean CRLValidated = false;
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditCRLNum = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ statsSub.startTiming("add_crl", true /* main action */);
+ }
+
+ try {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "add");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditCRLNum);
+
+ audit(auditMessage);
+
+ return;
+ }
+
+ if (auditSubjectID.equals(ILogger.NONROLEUSER) ||
+ auditSubjectID.equals(ILogger.UNIDENTIFIED)) {
+ if (authToken != null) {
+ String uid = authToken.getInString(IAuthToken.USER_ID);
+ if (uid != null) {
+ CMS.debug("AddCAServlet: auditSubjectID set to " + uid);
+ auditSubjectID = uid;
+ }
+ }
+ }
+ log(ILogger.LL_INFO, "AddCRLServlet");
+ String b64 = cmsReq.getHttpReq().getParameter("crl");
+ if (CMS.debugOn())
+ CMS.debug("AddCRLServlet: b64=" + b64);
+
+ if (b64 == null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditCRLNum);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_CRL"));
+ }
+
+ String nouiParm = cmsReq.getHttpReq().getParameter("noui");
+ boolean noUI = false;
+
+ if (nouiParm != null && nouiParm.equals("true")) {
+ noUI = true;
+ CMS.debug("AddCRLServlet: noUI=true");
+ } else {
+ CMS.debug("AddCRLServlet: noUI=false");
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ if (!noUI) {
+ form = getTemplate(mFormPath, req, locale);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath,
+ e.toString()));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditCRLNum);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ if (b64.indexOf(BEGIN_HEADER) == -1) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_CRL_HEADER"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditCRLNum);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(CMS.getUserMessage(getLocale(req),
+ "CMS_GW_MISSING_CRL_HEADER"));
+ }
+ if (b64.indexOf(END_HEADER) == -1) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_CRL_FOOTER"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditCRLNum);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(CMS.getUserMessage(getLocale(req),
+ "CMS_GW_MISSING_CRL_FOOTER"));
+ }
+
+ IDefStore defStore = mOCSPAuthority.getDefaultStore();
+
+ X509CRLImpl crl = null;
+
+ try {
+ long startTime = CMS.getCurrentDate().getTime();
+ CMS.debug("AddCRLServlet: mapCRL start startTime=" + startTime);
+ if (statsSub != null) {
+ statsSub.startTiming("decode_crl");
+ }
+ crl = mapCRL1(b64);
+ if (statsSub != null) {
+ statsSub.endTiming("decode_crl");
+ }
+ long endTime = CMS.getCurrentDate().getTime();
+ CMS.debug("AddCRLServlet: mapCRL done endTime=" + endTime +
+ " diff=" + (endTime - startTime));
+
+ // Retrieve the actual CRL number
+ BigInteger crlNum = crl.getCRLNumber();
+ if (crlNum != null) {
+ auditCRLNum = crlNum.toString();
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditCRLNum);
+
+ audit(auditMessage);
+
+ // acknowledge that the CRL has been retrieved
+ CRLFetched = true;
+ } catch (Exception e) {
+ // error
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditCRLNum);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DECODING_CRL_ERROR"));
+ }
+ log(ILogger.LL_INFO, "AddCRLServlet: CRL Issuer DN " +
+ crl.getIssuerDN().getName());
+
+ ICRLIssuingPointRecord pt = null;
+
+ try {
+ pt = defStore.readCRLIssuingPoint(
+ crl.getIssuerDN().getName());
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_NO_CRL_ISSUING_POINT_FOUND",
+ crl.getIssuerDN().getName()));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CRL_VALIDATION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DECODING_CRL_ERROR"));
+ }
+ log(ILogger.LL_INFO, "AddCRLServlet: IssuingPoint " +
+ pt.getThisUpdate());
+
+ // verify CRL
+ CryptoManager cmanager = null;
+ boolean tokenSwitched = false;
+ CryptoToken verToken = null;
+ CryptoToken savedToken = null;
+ byte caCertData[] = pt.getCACert();
+ if (caCertData != null) {
+ try {
+ cmanager = CryptoManager.getInstance();
+ X509CertImpl caCert = new X509CertImpl(caCertData);
+ CMS.debug("AddCRLServlet: start verify");
+
+ String tokenName =
+ CMS.getConfigStore().getString("ocsp.crlVerify.token", "internal");
+ savedToken = cmanager.getThreadToken();
+ if (tokenName.equals("internal")) {
+ verToken = cmanager.getInternalCryptoToken();
+ } else {
+ verToken = cmanager.getTokenByName(tokenName);
+ }
+ if (!savedToken.getName().equals(verToken.getName())) {
+ cmanager.setThreadToken(verToken);
+ tokenSwitched = true;
+ }
+
+ org.mozilla.jss.crypto.X509Certificate jssCert = null;
+ try {
+ jssCert = cmanager.importCACertPackage(
+ caCert.getEncoded());
+ } catch (Exception e2) {
+ CMS.debug("AddCRLServlet: importCACertPackage " +
+ e2.toString());
+ throw new EBaseException(e2.toString());
+ }
+
+ if (statsSub != null) {
+ statsSub.startTiming("verify_crl");
+ }
+ crl.verify(jssCert.getPublicKey(), "Mozilla-JSS");
+ if (statsSub != null) {
+ statsSub.endTiming("verify_crl");
+ }
+ CMS.debug("AddCRLServlet: done verify");
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CRL_VALIDATION,
+ auditSubjectID,
+ ILogger.SUCCESS);
+
+ audit(auditMessage);
+
+ // acknowledge that the CRL has been validated
+ CRLValidated = true;
+ } catch (Exception e) {
+ CMS.debug("AddCRLServlet: failed to verify CRL " + e.toString());
+ CMS.debug(e);
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_NO_CRL_ISSUING_POINT_FOUND",
+ crl.getIssuerDN().getName()));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CRL_VALIDATION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DECODING_CRL_ERROR"));
+ } finally {
+ if (tokenSwitched == true){
+ cmanager.setThreadToken(savedToken);
+ }
+ }
+ }
+
+ if ((pt.getThisUpdate() != null) &&
+ (pt.getThisUpdate().getTime() >=
+ crl.getThisUpdate().getTime())) {
+ // error, the uploaded CRL is older than the current
+ CMS.debug("AddCRLServlet: no update, CRL is older");
+ log(ILogger.LL_INFO,
+ "AddCRLServlet: no update, received CRL is older " +
+ "than current CRL");
+ if (noUI) {
+ try {
+ resp.setContentType("application/text");
+ resp.getOutputStream().write("status=1\n".getBytes());
+ resp.getOutputStream().write(
+ "error=Sent CRL is older than the current CRL\n".getBytes());
+ resp.getOutputStream().flush();
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+
+ // NOTE: The signed audit events
+ // LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL and
+ // LOGGING_SIGNED_AUDIT_CRL_VALIDATION have
+ // already been logged at this point!
+
+ return;
+ } catch (Exception e) {
+ }
+ } else {
+ CMS.debug("AddCRLServlet: CRL is older");
+
+ // NOTE: The signed audit events
+ // LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL and
+ // LOGGING_SIGNED_AUDIT_CRL_VALIDATION have
+ // already been logged at this point!
+
+ throw new ECMSGWException(CMS.getUserMessage(
+ "CMS_GW_OLD_CRL_ERROR"));
+ }
+ }
+
+ if (crl.isDeltaCRL()) {
+ CMS.debug("AddCRLServlet: no update, Delta CRLs are not supported.");
+ log(ILogger.LL_INFO, "AddCRLServlet: no update, " +
+ CMS.getUserMessage("CMS_GW_DELTA_CRL_NOT_SUPPORTED"));
+ if (noUI) {
+ try {
+ resp.setContentType("application/text");
+ resp.getOutputStream().write("status=1\n".getBytes());
+ resp.getOutputStream().write(
+ "error=Delta CRLs are not supported.\n".getBytes());
+ resp.getOutputStream().flush();
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+
+ return;
+ } catch (Exception e) {
+ }
+ } else {
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DELTA_CRL_NOT_SUPPORTED"));
+ }
+ }
+
+ CMS.debug("AddCRLServlet: strt committing CRL");
+ log(ILogger.LL_INFO, "AddCRLServlet: Start Committing CRL");
+
+ // *****************************************************
+ // The commit transaction may take long time and
+ // there may have a system crash during the transaction
+ // *****************************************************
+
+ IRepositoryRecord repRec = defStore.createRepositoryRecord();
+
+ repRec.set(IRepositoryRecord.ATTR_SERIALNO,
+ new BigInteger(Long.toString(crl.getThisUpdate().getTime())));
+ try {
+ defStore.addRepository(
+ crl.getIssuerDN().getName(),
+ Long.toString(crl.getThisUpdate().getTime()),
+ repRec);
+ log(ILogger.EV_AUDIT, AuditFormat.LEVEL, "Added CRL Updated " +
+ Long.toString(crl.getThisUpdate().getTime()));
+ } catch (Exception e) {
+ CMS.debug("AddCRLServlet: add repository e=" + e.toString());
+ }
+ log(ILogger.LL_INFO, "AddCRLServlet: Created CRL Repository " +
+ Long.toString(crl.getThisUpdate().getTime()));
+
+ if (defStore.waitOnCRLUpdate()) {
+ defStore.updateCRL(crl);
+ } else {
+ // when the CRL large, the thread is terminiated by the
+ // servlet framework before it can finish its work
+ UpdateCRLThread uct = new UpdateCRLThread(defStore, crl);
+
+ uct.start();
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (noUI) {
+ CMS.debug("AddCRLServlet: return result noUI=true");
+ resp.setContentType("application/text");
+ resp.getOutputStream().write("status=0".getBytes());
+ resp.getOutputStream().flush();
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } else {
+ CMS.debug("AddCRLServlet: return result noUI=false");
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ }
+ } catch (IOException e) {
+ CMS.debug("AddCRLServlet: return result error=" + e.toString());
+ mOCSPAuthority.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE",
+ e.toString()));
+
+ // NOTE: The signed audit events
+ // LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL and
+ // LOGGING_SIGNED_AUDIT_CRL_VALIDATION have
+ // already been logged at this point!
+
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ } catch (EBaseException eAudit1) {
+ if (!CRLFetched) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditCRLNum);
+
+ audit(auditMessage);
+ } else {
+ if (!CRLValidated) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CRL_VALIDATION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+ }
+ }
+ throw eAudit1;
+ }
+ if (statsSub != null) {
+ statsSub.endTiming("add_crl");
+ }
+ }
+
+ public X509CRLImpl mapCRL1(String mime64)
+ throws IOException {
+ mime64 = Cert.stripCRLBrackets(mime64.trim());
+
+ byte rawPub[] = CMS.AtoB(mime64);
+ X509CRLImpl crl = null;
+
+ try {
+ crl = new X509CRLImpl(rawPub, false);
+ } catch (Exception e) {
+ throw new IOException(e.toString());
+ }
+ return crl;
+ }
+}
+
+class UpdateCRLThread extends Thread {
+ private IDefStore mDefStore = null;
+ private X509CRL mCRL = null;
+
+ public UpdateCRLThread(
+ IDefStore defStore, X509CRL crl) {
+ mDefStore = defStore;
+ mCRL = crl;
+ }
+
+ public void run() {
+ try {
+ if (!((X509CRLImpl) mCRL).areEntriesIncluded())
+ mCRL = new X509CRLImpl(((X509CRLImpl) mCRL).getEncoded());
+ mDefStore.updateCRL(mCRL);
+ } catch (CRLException e) {
+ } catch (X509ExtensionException e) {
+ } catch (EBaseException e) {
+ // ignore
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/ocsp/CheckCertServlet.java b/base/server/cms/src/com/netscape/cms/servlet/ocsp/CheckCertServlet.java
new file mode 100644
index 000000000..8f44bf739
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/ocsp/CheckCertServlet.java
@@ -0,0 +1,217 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.ocsp;
+
+import java.io.IOException;
+import java.security.cert.X509CRLEntry;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X509CRLImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ocsp.IDefStore;
+import com.netscape.certsrv.ocsp.IOCSPAuthority;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cmsutil.util.Cert;
+
+/**
+ * Check the status of a specific certificate
+ *
+ * @version $Revision$ $Date$
+ */
+public class CheckCertServlet extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7782198059640825050L;
+ public static final String BEGIN_HEADER =
+ "-----BEGIN CERTIFICATE-----";
+ public static final String END_HEADER =
+ "-----END CERTIFICATE-----";
+
+ public static final String ATTR_STATUS = "status";
+ public static final String ATTR_ISSUERDN = "issuerDN";
+ public static final String ATTR_SUBJECTDN = "subjectDN";
+ public static final String ATTR_SERIALNO = "serialno";
+
+ public static final String STATUS_GOOD = "good";
+ public static final String STATUS_REVOKED = "revoked";
+ public static final String STATUS_UNKNOWN = "unknown";
+
+ private final static String TPL_FILE = "checkCert.template";
+ private String mFormPath = null;
+ private IOCSPAuthority mOCSPAuthority = null;
+
+ public CheckCertServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "checkCert.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success to display own output.
+
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ mOCSPAuthority = (IOCSPAuthority) mAuthority;
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param cert certificate to check. Base64, DER encoded, wrapped in -----BEGIN CERTIFICATE-----, -----END
+ * CERTIFICATE----- strings
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "validate");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ IDefStore defStore = mOCSPAuthority.getDefaultStore();
+
+ String b64 = cmsReq.getHttpReq().getParameter("cert");
+
+ if (b64.indexOf(BEGIN_HEADER) == -1) {
+ // error
+ throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CERT_HEADER"));
+
+ }
+ if (b64.indexOf(END_HEADER) == -1) {
+ // error
+ throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CERT_FOOTER"));
+ }
+
+ X509Certificate cert = null;
+
+ try {
+ cert = Cert.mapCert(b64);
+ } catch (Exception e) {
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DECODING_CERT_ERROR"));
+ }
+ if (cert == null) {
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DECODING_CERT_ERROR"));
+ }
+
+ ICRLIssuingPointRecord pt = defStore.readCRLIssuingPoint(
+ cert.getIssuerDN().getName());
+
+ header.addStringValue(ATTR_ISSUERDN, cert.getIssuerDN().getName());
+ header.addStringValue(ATTR_SUBJECTDN, cert.getSubjectDN().getName());
+ header.addStringValue(ATTR_SERIALNO, "0x" + cert.getSerialNumber().toString(16));
+ try {
+ X509CRLImpl crl = null;
+
+ crl = new X509CRLImpl(pt.getCRL());
+ X509CRLEntry crlentry = crl.getRevokedCertificate(cert.getSerialNumber());
+
+ if (crlentry == null) {
+ if (defStore.isNotFoundGood()) {
+ header.addStringValue(ATTR_STATUS, STATUS_GOOD);
+ } else {
+ header.addStringValue(ATTR_STATUS, STATUS_UNKNOWN);
+ }
+ } else {
+ header.addStringValue(ATTR_STATUS, STATUS_REVOKED);
+ }
+ } catch (Exception e) {
+ header.addStringValue(ATTR_STATUS, STATUS_UNKNOWN);
+ }
+ log(ILogger.EV_AUDIT, AuditFormat.LEVEL, "Checked Certificate Status "
+ + cert.getIssuerDN().getName() + " " + cert.getSerialNumber().toString());
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/ocsp/GetOCSPInfo.java b/base/server/cms/src/com/netscape/cms/servlet/ocsp/GetOCSPInfo.java
new file mode 100644
index 000000000..593f2de88
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/ocsp/GetOCSPInfo.java
@@ -0,0 +1,165 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.ocsp;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ocsp.IOCSPService;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Retrieve information about the number of OCSP requests the OCSP
+ * has serviced
+ *
+ * @version $Revision$, $Date$
+ */
+public class GetOCSPInfo extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3633557968127876119L;
+ private final static String TPL_FILE = "getOCSPInfo.template";
+ private String mFormPath = null;
+
+ public GetOCSPInfo() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template
+ * file "getOCSPInfo.template" to render the result page.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success to display own output.
+
+ // coming from agent
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ if (!(mAuthority instanceof IOCSPService)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CA_FROM_RA_NOT_IMP"));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_NOT_YET_IMPLEMENTED")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, httpReq, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ return;
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ IOCSPService ca = (IOCSPService) mAuthority;
+
+ header.addLongValue("numReq", ca.getNumOCSPRequest());
+ header.addLongValue("totalSec", ca.getOCSPRequestTotalTime());
+ header.addLongValue("totalSignSec", ca.getOCSPTotalSignTime());
+ header.addLongValue("totalLookupSec", ca.getOCSPTotalLookupTime());
+ header.addLongValue("totalData", ca.getOCSPTotalData());
+ long secs = 0;
+ if (ca.getOCSPRequestTotalTime() != 0) {
+ secs = (ca.getNumOCSPRequest() * 1000) / ca.getOCSPRequestTotalTime();
+ }
+ header.addLongValue("ReqSec", secs);
+ try {
+ ServletOutputStream out = httpResp.getOutputStream();
+
+ httpResp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ cmsReq.setError(new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")));
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/ocsp/ListCAServlet.java b/base/server/cms/src/com/netscape/cms/servlet/ocsp/ListCAServlet.java
new file mode 100644
index 000000000..4894c574a
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/ocsp/ListCAServlet.java
@@ -0,0 +1,199 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.ocsp;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ocsp.IDefStore;
+import com.netscape.certsrv.ocsp.IOCSPAuthority;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Show the list of CA's that the OCSP responder can service
+ *
+ * @version $Revision$ $Date$
+ */
+public class ListCAServlet extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3764395161795483452L;
+ public static final String BEGIN_HEADER =
+ "-----BEGIN CERTIFICATE-----";
+ public static final String END_HEADER =
+ "-----END CERTIFICATE-----";
+
+ private final static String TPL_FILE = "listCAs.template";
+ private String mFormPath = null;
+ private IOCSPAuthority mOCSPAuthority = null;
+
+ public ListCAServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "listCAs.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success to display own output.
+
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ mOCSPAuthority = (IOCSPAuthority) mAuthority;
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "list");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ IDefStore defStore = mOCSPAuthority.getDefaultStore();
+ Enumeration<ICRLIssuingPointRecord> recs = defStore.searchAllCRLIssuingPointRecord(100);
+
+ // show the current CRL number if present
+ header.addStringValue("stateCount",
+ Integer.toString(defStore.getStateCount()));
+
+ while (recs.hasMoreElements()) {
+ ICRLIssuingPointRecord rec = recs.nextElement();
+ IArgBlock rarg = CMS.createArgBlock();
+ String thisId = rec.getId();
+
+ rarg.addStringValue("Id", thisId);
+ Date thisUpdate = rec.getThisUpdate();
+
+ if (thisUpdate == null) {
+ rarg.addStringValue("ThisUpdate", "UNKNOWN");
+ } else {
+ rarg.addStringValue("ThisUpdate", thisUpdate.toString());
+ }
+ Date nextUpdate = rec.getNextUpdate();
+
+ if (nextUpdate == null) {
+ rarg.addStringValue("NextUpdate", "UNKNOWN");
+ } else {
+ rarg.addStringValue("NextUpdate", nextUpdate.toString());
+ }
+ Long rc = rec.getCRLSize();
+
+ if (rc == null) {
+ rarg.addLongValue("NumRevoked", 0);
+ } else {
+ if (rc.longValue() == -1) {
+ rarg.addStringValue("NumRevoked", "UNKNOWN");
+ } else {
+ rarg.addLongValue("NumRevoked", rc.longValue());
+ }
+ }
+
+ BigInteger crlNumber = rec.getCRLNumber();
+ if (crlNumber == null || crlNumber.equals(new BigInteger("-1"))) {
+ rarg.addStringValue("CRLNumber", "UNKNOWN");
+ } else {
+ rarg.addStringValue("CRLNumber", crlNumber.toString());
+ }
+
+ rarg.addLongValue("ReqCount", defStore.getReqCount(thisId));
+ argSet.addRepeatRecord(rarg);
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java b/base/server/cms/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java
new file mode 100644
index 000000000..940bf657c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java
@@ -0,0 +1,277 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.ocsp;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.mozilla.jss.asn1.ASN1Util;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.ocsp.IOCSPService;
+import com.netscape.certsrv.util.IStatsSubsystem;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cmsutil.ocsp.BasicOCSPResponse;
+import com.netscape.cmsutil.ocsp.OCSPRequest;
+import com.netscape.cmsutil.ocsp.OCSPResponse;
+import com.netscape.cmsutil.ocsp.ResponseBytes;
+import com.netscape.cmsutil.ocsp.ResponseData;
+import com.netscape.cmsutil.ocsp.SingleResponse;
+import com.netscape.cmsutil.ocsp.TBSRequest;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Process OCSP messages, According to RFC 2560
+ * See http://www.ietf.org/rfc/rfc2560.txt
+ *
+ * @version $Revision$ $Date$
+ */
+public class OCSPServlet extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 120903601883352030L;
+ public final static String PROP_AUTHORITY = "authority";
+ public final static String PROP_CLIENTAUTH = "GetClientCert";
+ public final static String PROP_MAX_REQUEST_SIZE = "MaxRequestSize";
+ public final static String PROP_ID = "ID";
+
+ private int m_maxRequestSize = 5000;
+
+ public OCSPServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "ImportCert.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ String s = sc.getInitParameter(PROP_MAX_REQUEST_SIZE);
+ if (s != null) {
+ try {
+ m_maxRequestSize = Integer.parseInt(s);
+ } catch (Exception e) {
+ }
+ }
+
+ }
+
+ /**
+ * Process the HTTP request.
+ * This method is invoked when the OCSP service receives a OCSP
+ * request. Based on RFC 2560, the request should have the OCSP
+ * request in the HTTP body as binary blob.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ statsSub.startTiming("ocsp", true /* main action */);
+ }
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "submit");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMS.debug("Servlet Path=" + httpReq.getServletPath());
+ CMS.debug("RequestURI=" + httpReq.getRequestURI());
+ String pathInfo = httpReq.getPathInfo();
+ if (pathInfo != null && pathInfo.indexOf('%') != -1) {
+ try {
+ pathInfo = URLDecoder.decode(pathInfo, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ throw new EBaseException("OCSPServlet: Unsupported encoding" + e);
+ }
+ }
+ CMS.debug("PathInfo=" + pathInfo);
+
+ OCSPRequest ocspReq = null;
+
+ try {
+ InputStream is = httpReq.getInputStream();
+ byte reqbuf[] = null;
+ String method = httpReq.getMethod();
+ CMS.debug("Method=" + method);
+ if (method != null && method.equals("POST")) {
+ int reqlen = httpReq.getContentLength();
+
+ if (reqlen == -1) {
+ throw new Exception("OCSPServlet: Content-Length not supplied");
+ }
+ if (reqlen == 0) {
+ throw new Exception("OCSPServlet: Invalid Content-Length");
+ }
+ if (reqlen > m_maxRequestSize) {
+ throw new Exception("OCSPServlet: Client sending too much OCSP request data (" + reqlen + ")");
+ }
+
+ // for debugging
+ reqbuf = new byte[reqlen];
+ int bytesread = 0;
+ boolean partial = false;
+
+ while (bytesread < reqlen) {
+ int r = is.read(reqbuf, bytesread, reqlen - bytesread);
+ if (r == -1) {
+ throw new Exception("OCSPServlet: Client did not supply enough OCSP data");
+ }
+ bytesread += r;
+ if (partial == false) {
+ if (bytesread < reqlen) {
+ partial = true;
+ }
+ }
+ }
+ is = new ByteArrayInputStream(reqbuf);
+ } else {
+ // GET method
+ if ((pathInfo == null) ||
+ (pathInfo.equals("")) ||
+ (pathInfo.substring(1) == null) ||
+ (pathInfo.substring(1).equals(""))) {
+ throw new Exception("OCSPServlet: OCSP request not provided in GET method");
+ }
+ is = new ByteArrayInputStream(
+ Utils.base64decode(pathInfo.substring(1)));
+ }
+
+ // (1) retrieve OCSP request
+ // (2) decode request
+ OCSPResponse response = null;
+
+ try {
+ OCSPRequest.Template reqTemplate =
+ new OCSPRequest.Template();
+
+ if ((is == null) ||
+ (is.toString().equals(""))) {
+ throw new Exception("OCSPServlet: OCSP request is "
+ + "empty or malformed");
+ }
+ ocspReq = (OCSPRequest) reqTemplate.decode(is);
+ if ((ocspReq == null) ||
+ (ocspReq.toString().equals(""))) {
+ throw new Exception("OCSPServlet: Decoded OCSP request "
+ + "is empty or malformed");
+ }
+ response = ((IOCSPService) mAuthority).validate(ocspReq);
+ } catch (Exception e) {
+ ;
+ CMS.debug("OCSPServlet: " + e.toString());
+ }
+
+ if (response != null) {
+ ByteArrayOutputStream fos1 = new ByteArrayOutputStream();
+
+ response.encode(fos1);
+ fos1.close();
+
+ byte[] respbytes;
+
+ respbytes = fos1.toByteArray();
+
+ // print out OCSP response in debug mode so that
+ // we can validate the response
+ if (CMS.debugOn()) {
+ CMS.debug("OCSPServlet: OCSP Request:");
+ CMS.debug("OCSPServlet: " + CMS.BtoA(ASN1Util.encode(ocspReq)));
+ TBSRequest tbsReq = ocspReq.getTBSRequest();
+ for (int i = 0; i < tbsReq.getRequestCount(); i++) {
+ com.netscape.cmsutil.ocsp.Request req = tbsReq.getRequestAt(i);
+ CMS.debug("Serial Number: " + req.getCertID().getSerialNumber());
+ }
+ CMS.debug("OCSPServlet: OCSP Response Size:");
+ CMS.debug("OCSPServlet: " + Integer.toString(respbytes.length));
+ CMS.debug("OCSPServlet: OCSP Response Data:");
+ CMS.debug("OCSPServlet: " + CMS.BtoA(respbytes));
+ ResponseBytes rbytes = response.getResponseBytes();
+ if (rbytes == null) {
+ CMS.debug("Response bytes is null");
+ } else if (rbytes.getObjectIdentifier().equals(
+ ResponseBytes.OCSP_BASIC)) {
+ BasicOCSPResponse basicRes = (BasicOCSPResponse)
+ BasicOCSPResponse.getTemplate().decode(
+ new ByteArrayInputStream(rbytes.getResponse().toByteArray()));
+ if (basicRes == null) {
+ CMS.debug("Basic Res is null");
+ } else {
+ ResponseData data = basicRes.getResponseData();
+ for (int i = 0; i < data.getResponseCount(); i++) {
+ SingleResponse res = data.getResponseAt(i);
+ CMS.debug("Serial Number: " +
+ res.getCertID().getSerialNumber() +
+ " Status: " +
+ res.getCertStatus().getClass().getName());
+ }
+ }
+ }
+ }
+
+ httpResp.setContentType("application/ocsp-response");
+
+ httpResp.setContentLength(respbytes.length);
+ OutputStream ooss = httpResp.getOutputStream();
+
+ ooss.write(respbytes);
+ ooss.flush();
+ if (statsSub != null) {
+ statsSub.endTiming("ocsp");
+ }
+
+ mRenderResult = false;
+ }
+ } catch (Exception e) {
+ CMS.debug("OCSPServlet: " + e.toString());
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/ocsp/RemoveCAServlet.java b/base/server/cms/src/com/netscape/cms/servlet/ocsp/RemoveCAServlet.java
new file mode 100644
index 000000000..55f688a0b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/ocsp/RemoveCAServlet.java
@@ -0,0 +1,215 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.ocsp;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ocsp.IDefStore;
+import com.netscape.certsrv.ocsp.IOCSPAuthority;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Configure the CA to no longer respond to OCSP requests for a CA
+ *
+ * @version $Revision: 1274 $ $Date: 2010-09-07 22:14:41 -0700 (Tue, 07 Sep 2010) $
+ */
+public class RemoveCAServlet extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4519898238552366358L;
+ private final static String TPL_FILE = "removeCA.template";
+ private String mFormPath = null;
+ private IOCSPAuthority mOCSPAuthority = null;
+
+ private final static String LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST =
+ "LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_3";
+ private final static String LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS_3";
+
+ private final static String LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE =
+ "LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE_3";
+
+ public RemoveCAServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "addCA.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success to display own output.
+
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ mOCSPAuthority = (IOCSPAuthority) mAuthority;
+
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param ca id. The format is string.
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST used when a CA is attempted to be removed from the
+ * OCSP responder
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS and
+ * LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE are used when a remove CA request to the OCSP
+ * Responder is processed successfully or not.
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "add");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ if (auditSubjectID.equals(ILogger.NONROLEUSER) ||
+ auditSubjectID.equals(ILogger.UNIDENTIFIED)) {
+ String uid = authToken.getInString(IAuthToken.USER_ID);
+ if (uid != null) {
+ CMS.debug("RemoveCAServlet: auditSubjectID set to " + uid);
+ auditSubjectID = uid;
+ }
+ }
+
+ String caID = cmsReq.getHttpReq().getParameter("caID");
+
+ if (caID == null) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+
+ throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CA_ID"));
+ }
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ caID);
+
+ audit(auditMessage);
+
+ IDefStore defStore = mOCSPAuthority.getDefaultStore();
+
+ try {
+ defStore.deleteCRLIssuingPointRecord(caID);
+
+ } catch (EBaseException e) {
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE,
+ auditSubjectID,
+ ILogger.FAILURE,
+ caID);
+ audit(auditMessage);
+
+ CMS.debug("RemoveCAServlet::process: Error deleting CRL IssuingPoint: " + caID);
+ throw new EBaseException(e.toString());
+ }
+
+ CMS.debug("RemoveCAServlet::process: CRL IssuingPoint for CA successfully removed: " + caID);
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ caID);
+ audit(auditMessage);
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/CMCProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/CMCProcessor.java
new file mode 100644
index 000000000..3c5c4080b
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/CMCProcessor.java
@@ -0,0 +1,407 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.processors;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.PublicKey;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Hashtable;
+
+import netscape.security.pkcs.PKCS10;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import org.mozilla.jss.asn1.ANY;
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
+import org.mozilla.jss.asn1.OCTET_STRING;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.asn1.SET;
+import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.pkcs10.CertificationRequest;
+import org.mozilla.jss.pkcs11.PK11PubKey;
+import org.mozilla.jss.pkix.cert.Certificate;
+import org.mozilla.jss.pkix.cert.CertificateInfo;
+import org.mozilla.jss.pkix.cmc.PKIData;
+import org.mozilla.jss.pkix.cmc.TaggedAttribute;
+import org.mozilla.jss.pkix.cmc.TaggedCertificationRequest;
+import org.mozilla.jss.pkix.cmc.TaggedRequest;
+import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo;
+import org.mozilla.jss.pkix.cms.IssuerAndSerialNumber;
+import org.mozilla.jss.pkix.cms.SignedData;
+import org.mozilla.jss.pkix.cms.SignerIdentifier;
+import org.mozilla.jss.pkix.crmf.CertReqMsg;
+import org.mozilla.jss.pkix.crmf.CertRequest;
+import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier;
+import org.mozilla.jss.pkix.primitive.Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Process CMC messages according to RFC 2797
+ * See http://www.ietf.org/rfc/rfc2797.txt
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMCProcessor extends PKIProcessor {
+
+ private boolean enforcePop = false;
+
+ public CMCProcessor() {
+ super();
+ }
+
+ public CMCProcessor(ICMSRequest cmsReq, CMSServlet servlet, boolean doEnforcePop) {
+
+ super(cmsReq, servlet);
+ enforcePop = doEnforcePop;
+
+ }
+
+ public void process(ICMSRequest cmsReq)
+ throws EBaseException {
+ }
+
+ public void fillCertInfo(
+ String protocolString, X509CertInfo certInfo,
+ IAuthToken authToken, IArgBlock httpParams)
+ throws EBaseException {
+ }
+
+ public X509CertInfo[] fillCertInfoArray(
+ String protocolString, IAuthToken authToken, IArgBlock httpParams, IRequest req)
+ throws EBaseException {
+
+ CMS.debug("CMCProcessor: In CMCProcessor.fillCertInfoArray!");
+ String cmc = protocolString;
+
+ try {
+ byte[] cmcBlob = CMS.AtoB(cmc);
+ ByteArrayInputStream cmcBlobIn =
+ new ByteArrayInputStream(cmcBlob);
+
+ org.mozilla.jss.pkix.cms.ContentInfo cmcReq = (org.mozilla.jss.pkix.cms.ContentInfo)
+ org.mozilla.jss.pkix.cms.ContentInfo.getTemplate().decode(cmcBlobIn);
+
+ if (!cmcReq.getContentType().equals(org.mozilla.jss.pkix.cms.ContentInfo.SIGNED_DATA)
+ || !cmcReq.hasContent())
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_CMC_CONTENT"));
+
+ SignedData cmcFullReq = (SignedData)
+ cmcReq.getInterpretedContent();
+
+ EncapsulatedContentInfo ci = cmcFullReq.getContentInfo();
+
+ OBJECT_IDENTIFIER id = ci.getContentType();
+
+ if (!id.equals(OBJECT_IDENTIFIER.id_cct_PKIData) || !ci.hasContent()) {
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_NO_PKIDATA"));
+ }
+ OCTET_STRING content = ci.getContent();
+
+ ByteArrayInputStream s = new ByteArrayInputStream(content.toByteArray());
+ PKIData pkiData = (PKIData) (new PKIData.Template()).decode(s);
+
+ SEQUENCE reqSequence = pkiData.getReqSequence();
+
+ int numReqs = reqSequence.size();
+ X509CertInfo[] certInfoArray = new X509CertInfo[numReqs];
+ String[] reqIdArray = new String[numReqs];
+
+ for (int i = 0; i < numReqs; i++) {
+ // decode message.
+ TaggedRequest taggedRequest = (TaggedRequest) reqSequence.elementAt(i);
+
+ TaggedRequest.Type type = taggedRequest.getType();
+
+ if (type.equals(TaggedRequest.PKCS10)) {
+ TaggedCertificationRequest tcr = taggedRequest.getTcr();
+ int p10Id = tcr.getBodyPartID().intValue();
+
+ reqIdArray[i] = String.valueOf(p10Id);
+
+ CertificationRequest p10 =
+ tcr.getCertificationRequest();
+
+ // transfer to sun class
+ ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+
+ p10.encode(ostream);
+
+ PKCS10Processor pkcs10Processor = new PKCS10Processor(mRequest, mServlet);
+
+ try {
+ PKCS10 pkcs10 = new PKCS10(ostream.toByteArray());
+ //xxx do we need to do anything else?
+ X509CertInfo certInfo = CMS.getDefaultX509CertInfo();
+
+ pkcs10Processor.fillCertInfo(pkcs10, certInfo, authToken, httpParams);
+
+ /* fillPKCS10(pkcs10,certInfo,
+ authToken, httpParams);
+ */
+
+ certInfoArray[i] = certInfo;
+ } catch (Exception e) {
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_PKCS10_ERROR", e.toString()));
+ }
+ } else if (type.equals(TaggedRequest.CRMF)) {
+
+ CRMFProcessor crmfProc = new CRMFProcessor(mRequest, mServlet, enforcePop);
+
+ CertReqMsg crm = taggedRequest.getCrm();
+ CertRequest certReq = crm.getCertReq();
+
+ INTEGER certReqId = certReq.getCertReqId();
+ int srcId = certReqId.intValue();
+
+ reqIdArray[i] = String.valueOf(srcId);
+
+ certInfoArray[i] = crmfProc.processIndividualRequest(crm, authToken, httpParams);
+
+ } else {
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_CMC_CONTENT"));
+ }
+ }
+
+ // verify the signerInfo
+ SET dais = cmcFullReq.getDigestAlgorithmIdentifiers();
+ int numDig = dais.size();
+ Hashtable<String, byte[]> digs = new Hashtable<String, byte[]>();
+
+ for (int i = 0; i < numDig; i++) {
+ AlgorithmIdentifier dai =
+ (AlgorithmIdentifier) dais.elementAt(i);
+ String name =
+ DigestAlgorithm.fromOID(dai.getOID()).toString();
+
+ MessageDigest md =
+ MessageDigest.getInstance(name);
+
+ byte[] digest = md.digest(content.toByteArray());
+
+ digs.put(name, digest);
+ }
+
+ SET sis = cmcFullReq.getSignerInfos();
+ int numSis = sis.size();
+
+ for (int i = 0; i < numSis; i++) {
+ org.mozilla.jss.pkix.cms.SignerInfo si =
+ (org.mozilla.jss.pkix.cms.SignerInfo)
+ sis.elementAt(i);
+
+ String name = si.getDigestAlgorithm().toString();
+ byte[] digest = digs.get(name);
+
+ if (digest == null) {
+ MessageDigest md = MessageDigest.getInstance(name);
+ ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+
+ pkiData.encode(ostream);
+ digest = md.digest(ostream.toByteArray());
+
+ }
+
+ SignerIdentifier sid = si.getSignerIdentifier();
+
+ if (sid.getType().equals(SignerIdentifier.ISSUER_AND_SERIALNUMBER)) {
+ IssuerAndSerialNumber issuerAndSerialNumber = sid.getIssuerAndSerialNumber();
+ // find from the certs in the signedData
+ X509Certificate cert = null;
+
+ if (cmcFullReq.hasCertificates()) {
+ SET certs = cmcFullReq.getCertificates();
+ int numCerts = certs.size();
+
+ for (int j = 0; j < numCerts; j++) {
+ Certificate certJss =
+ (Certificate) certs.elementAt(j);
+ CertificateInfo certI =
+ certJss.getInfo();
+ Name issuer = certI.getIssuer();
+ byte[] issuerB = ASN1Util.encode(issuer);
+
+ INTEGER sn = certI.getSerialNumber();
+
+ if (new String(issuerB).equals(new
+ String(ASN1Util.encode(issuerAndSerialNumber.getIssuer())))
+ && sn.toString().equals(issuerAndSerialNumber.getSerialNumber().toString())) {
+ ByteArrayOutputStream os = new
+ ByteArrayOutputStream();
+
+ certJss.encode(os);
+ cert = new X509CertImpl(os.toByteArray());
+ // xxx validate the cert length
+
+ }
+ }
+
+ }
+ // find from internaldb if it's ca. (ra does not have that.)
+ // find from internaldb usrgrp info
+
+ if (cert == null) {
+ // find from certDB
+ si.verify(digest, id);
+ } else {
+ PublicKey signKey = cert.getPublicKey();
+ PK11PubKey pubK = PK11PubKey.fromSPKI(((X509Key) signKey).getKey());
+ si.verify(digest, id, pubK);
+ }
+
+ } else {
+ OCTET_STRING ski = sid.getSubjectKeyIdentifier();
+ // find the publicKey using ski
+ int j = 0;
+ PublicKey signKey = null;
+
+ while (signKey == null && j < numReqs) {
+ X509Key subjectKeyInfo =
+ (X509Key) ((CertificateX509Key) certInfoArray[j].get(X509CertInfo.KEY))
+ .get(CertificateX509Key.KEY);
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+
+ md.update(subjectKeyInfo.getEncoded());
+ byte[] skib = md.digest();
+
+ if (new String(skib).equals(new String(ski.toByteArray()))) {
+ signKey = subjectKeyInfo;
+ }
+ j++;
+ }
+ if (signKey == null) {
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_CMC_ERROR",
+ "SubjectKeyIdentifier in SignerInfo does not match any publicKey in the request."));
+ } else {
+ PK11PubKey pubK = PK11PubKey.fromSPKI(((X509Key) signKey).getKey());
+ si.verify(digest, id, pubK);
+ }
+ }
+ }
+ // end verify signerInfo
+
+ // Get control sequence
+ // verisign has transactionId, senderNonce, regInfo
+ // identification, identityproof
+ SEQUENCE controls = pkiData.getControlSequence();
+ int numControls = controls.size();
+
+ for (int i = 0; i < numControls; i++) {
+ TaggedAttribute control =
+ (TaggedAttribute) controls.elementAt(i);
+ OBJECT_IDENTIFIER type = control.getType();
+ SET values = control.getValues();
+ int numVals = values.size();
+
+ if (type.equals(OBJECT_IDENTIFIER.id_cmc_transactionId)) {
+ String[] vals = null;
+
+ if (numVals > 0)
+ vals = new String[numVals];
+ for (int j = 0; j < numVals; j++) {
+ ANY val = (ANY)
+ values.elementAt(j);
+ INTEGER transId = (INTEGER) val.decodeWith(
+ INTEGER.getTemplate());
+
+ if (transId != null) {
+ vals[j] = transId.toString();
+ }
+ }
+ if (vals != null)
+ req.setExtData(IRequest.CMC_TRANSID, vals);
+ } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_senderNonce)) {
+ String[] vals = null;
+
+ if (numVals > 0)
+ vals = new String[numVals];
+ for (int j = 0; j < numVals; j++) {
+ ANY val = (ANY)
+ values.elementAt(j);
+ OCTET_STRING nonce = (OCTET_STRING)
+ val.decodeWith(OCTET_STRING.getTemplate());
+
+ if (nonce != null) {
+ vals[j] = new String(nonce.toByteArray());
+ }
+ }
+ if (vals != null)
+ req.setExtData(IRequest.CMC_SENDERNONCE, vals);
+
+ } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_regInfo)) {
+ // what can we do here
+ // for verisign, we just debug.print()
+ } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_identification)) {
+ // what can we do here
+ // for verisign, we just debug.print()
+ } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_identityProof)) {
+ // what can we do here
+ // for verisign, we just debug.print()
+ }
+ }
+
+ req.setExtData(IRequest.CMC_REQIDS, reqIdArray);
+ return certInfoArray;
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_CMC_TO_CERTINFO_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CMC_TO_CERTINFO_ERROR"));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_CMC_TO_CERTINFO_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CMC_TO_CERTINFO_ERROR"));
+ } catch (InvalidBERException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_CMC_TO_CERTINFO_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CMC_TO_CERTINFO_ERROR"));
+ } catch (InvalidKeyException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_CMC_TO_CERTINFO_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CMC_TO_CERTINFO_ERROR"));
+ } catch (Exception e) {
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CMC_ERROR", e.toString()));
+ }
+
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/CRMFProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/CRMFProcessor.java
new file mode 100644
index 000000000..1da0cf3c4
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/CRMFProcessor.java
@@ -0,0 +1,373 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.processors;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.cert.CertificateException;
+
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.Extension;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.pkix.crmf.CertReqMsg;
+import org.mozilla.jss.pkix.crmf.CertRequest;
+import org.mozilla.jss.pkix.crmf.CertTemplate;
+import org.mozilla.jss.pkix.crmf.ProofOfPossession;
+import org.mozilla.jss.pkix.primitive.Name;
+import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Process CRMF requests, according to RFC 2511
+ * See http://www.ietf.org/rfc/rfc2511.txt
+ *
+ * @version $Revision$, $Date$
+ */
+public class CRMFProcessor extends PKIProcessor {
+
+ @SuppressWarnings("unused")
+ private ICMSRequest mRequest;
+
+ private boolean enforcePop = false;
+
+ private final static String LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION =
+ "LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION_2";
+
+ public CRMFProcessor() {
+ super();
+ }
+
+ public CRMFProcessor(ICMSRequest cmsReq, CMSServlet servlet, boolean doEnforcePop) {
+ super(cmsReq, servlet);
+
+ enforcePop = doEnforcePop;
+ mRequest = cmsReq;
+ }
+
+ public void process(ICMSRequest cmsReq)
+ throws EBaseException {
+ }
+
+ /**
+ * Verify Proof of Possession (POP)
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION used when proof of possession is checked during
+ * certificate enrollment
+ * </ul>
+ *
+ * @param certReqMsg the certificate request message
+ * @exception EBaseException an error has occurred
+ */
+ private void verifyPOP(CertReqMsg certReqMsg)
+ throws EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+
+ try {
+ CMS.debug("CRMFProcessor: verifyPOP");
+
+ if (certReqMsg.hasPop()) {
+ ProofOfPossession pop = certReqMsg.getPop();
+
+ ProofOfPossession.Type popType = pop.getType();
+
+ if (popType == ProofOfPossession.SIGNATURE) {
+ CMS.debug("CRMFProcessor: Request has pop.");
+ try {
+ certReqMsg.verify();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION,
+ auditSubjectID,
+ ILogger.SUCCESS);
+
+ audit(auditMessage);
+ } catch (Exception e) {
+ CMS.debug("CRMFProcessor: Failed POP verify!");
+
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_POP_VERIFY"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_POP_VERIFY"));
+ }
+ }
+ } else {
+ if (enforcePop == true) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_NO_POP"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ throw new ECMSGWException(
+ CMS.getLogMessage("CMSGW_ERROR_NO_POP"));
+ }
+ }
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION,
+ auditSubjectID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+ }
+ }
+
+ public X509CertInfo processIndividualRequest(CertReqMsg certReqMsg, IAuthToken authToken, IArgBlock httpParams)
+ throws EBaseException {
+ CMS.debug("CRMFProcessor::processIndividualRequest!");
+
+ try {
+
+ verifyPOP(certReqMsg);
+
+ CertRequest certReq = certReqMsg.getCertReq();
+
+ CertTemplate certTemplate = certReq.getCertTemplate();
+ X509CertInfo certInfo = CMS.getDefaultX509CertInfo();
+
+ // get key
+ SubjectPublicKeyInfo spki = certTemplate.getPublicKey();
+ ByteArrayOutputStream keyout = new ByteArrayOutputStream();
+
+ spki.encode(keyout);
+ byte[] keybytes = keyout.toByteArray();
+ X509Key key = new X509Key();
+
+ key.decode(keybytes);
+ certInfo.set(X509CertInfo.KEY, new CertificateX509Key(key));
+
+ // field suggested notBefore and notAfter in CRMF
+ // Tech Support #383184
+ if (certTemplate.getNotBefore() != null || certTemplate.getNotAfter() != null) {
+ CertificateValidity certValidity =
+ new CertificateValidity(certTemplate.getNotBefore(), certTemplate.getNotAfter());
+
+ certInfo.set(X509CertInfo.VALIDITY, certValidity);
+ }
+
+ if (certTemplate.hasSubject()) {
+ Name subjectdn = certTemplate.getSubject();
+ ByteArrayOutputStream subjectEncStream =
+ new ByteArrayOutputStream();
+
+ subjectdn.encode(subjectEncStream);
+ byte[] subjectEnc = subjectEncStream.toByteArray();
+ X500Name subject = new X500Name(subjectEnc);
+
+ certInfo.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(subject));
+ } else if (authToken == null ||
+ authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) == null) {
+ // No subject name - error!
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN"));
+ }
+
+ // get extensions
+ CertificateExtensions extensions = null;
+
+ try {
+ extensions = (CertificateExtensions)
+ certInfo.get(X509CertInfo.EXTENSIONS);
+ } catch (CertificateException e) {
+ extensions = null;
+ } catch (IOException e) {
+ extensions = null;
+ }
+ if (certTemplate.hasExtensions()) {
+ // put each extension from CRMF into CertInfo.
+ // index by extension name, consistent with
+ // CertificateExtensions.parseExtension() method.
+ if (extensions == null)
+ extensions = new CertificateExtensions();
+ int numexts = certTemplate.numExtensions();
+
+ for (int j = 0; j < numexts; j++) {
+ org.mozilla.jss.pkix.cert.Extension jssext =
+ certTemplate.extensionAt(j);
+ boolean isCritical = jssext.getCritical();
+ org.mozilla.jss.asn1.OBJECT_IDENTIFIER jssoid =
+ jssext.getExtnId();
+ long[] numbers = jssoid.getNumbers();
+ int[] oidNumbers = new int[numbers.length];
+
+ for (int k = numbers.length - 1; k >= 0; k--) {
+ oidNumbers[k] = (int) numbers[k];
+ }
+ ObjectIdentifier oid =
+ new ObjectIdentifier(oidNumbers);
+ org.mozilla.jss.asn1.OCTET_STRING jssvalue =
+ jssext.getExtnValue();
+ ByteArrayOutputStream jssvalueout =
+ new ByteArrayOutputStream();
+
+ jssvalue.encode(jssvalueout);
+ byte[] extValue = jssvalueout.toByteArray();
+
+ Extension ext =
+ new Extension(oid, isCritical, extValue);
+
+ extensions.parseExtension(ext);
+ }
+
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+
+ }
+
+ // Added a new configuration parameter
+ // eeGateway.Enrollment.authTokenOverride=[true|false]
+ // By default, it is set to true. In most
+ // of the case, administrator would want
+ // to have the control of the subject name
+ // formulation.
+ // -- CRMFfillCert
+ if (authToken != null &&
+ authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) != null) {
+ // if authenticated override subect name, validity and
+ // extensions if any from authtoken.
+ fillCertInfoFromAuthToken(certInfo, authToken);
+ }
+
+ // SPECIAL CASE:
+ // if it is adminEnroll servlet, get the validity
+ // from the http parameters.
+ if (mServletId.equals(PKIProcessor.ADMIN_ENROLL_SERVLET_ID)) {
+ fillValidityFromForm(certInfo, httpParams);
+ }
+
+ return certInfo;
+
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR"));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR"));
+ } /* catch (InvalidBERException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1",e.toString()));
+ throw new ECMSGWException(
+ CMSGWResources.ERROR_CRMF_TO_CERTINFO);
+ } */catch (InvalidKeyException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR"));
+ }
+
+ }
+
+ public X509CertInfo[] fillCertInfoArray(
+ String protocolString, IAuthToken authToken, IArgBlock httpParams, IRequest req)
+ throws EBaseException {
+
+ CMS.debug("CRMFProcessor.fillCertInfoArray!");
+
+ String crmf = protocolString;
+
+ try {
+ byte[] crmfBlob = CMS.AtoB(crmf);
+ ByteArrayInputStream crmfBlobIn =
+ new ByteArrayInputStream(crmfBlob);
+
+ SEQUENCE crmfMsgs = (SEQUENCE)
+ new SEQUENCE.OF_Template(new CertReqMsg.Template()).decode(crmfBlobIn);
+
+ int nummsgs = crmfMsgs.size();
+ X509CertInfo[] certInfoArray = new X509CertInfo[nummsgs];
+
+ for (int i = 0; i < nummsgs; i++) {
+ // decode message.
+ CertReqMsg certReqMsg = (CertReqMsg) crmfMsgs.elementAt(i);
+
+ CertRequest certReq = certReqMsg.getCertReq();
+ INTEGER certReqId = certReq.getCertReqId();
+ int srcId = certReqId.intValue();
+
+ req.setExtData(IRequest.CRMF_REQID, String.valueOf(srcId));
+
+ certInfoArray[i] = processIndividualRequest(certReqMsg, authToken, httpParams);
+
+ }
+
+ //do_testbed_hack(nummsgs, certInfoArray, httpParams);
+
+ return certInfoArray;
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR"));
+ } catch (InvalidBERException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR"));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/IPKIProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/IPKIProcessor.java
new file mode 100644
index 000000000..3fd42db08
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/IPKIProcessor.java
@@ -0,0 +1,33 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.processors;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.common.ICMSRequest;
+
+/**
+ * This represents the request parser.
+ *
+ * @version $Revision$, $Date$
+ */
+public interface IPKIProcessor {
+
+ public void process(ICMSRequest cmsReq)
+ throws EBaseException;
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/KeyGenProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/KeyGenProcessor.java
new file mode 100644
index 000000000..d3f8ba655
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/KeyGenProcessor.java
@@ -0,0 +1,120 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.processors;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.KeyGenInfo;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * KeyGenProcess parses Certificate request matching the
+ * KEYGEN tag format used by Netscape Communicator 4.x
+ *
+ * @version $Revision$, $Date$
+ */
+public class KeyGenProcessor extends PKIProcessor {
+
+ public KeyGenProcessor() {
+ super();
+ }
+
+ public KeyGenProcessor(ICMSRequest cmsReq, CMSServlet servlet) {
+ super(cmsReq, servlet);
+
+ }
+
+ public void process(ICMSRequest cmsReq)
+ throws EBaseException {
+ }
+
+ public void fillCertInfo(
+ String protocolString, X509CertInfo certInfo,
+ IAuthToken authToken, IArgBlock httpParams)
+ throws EBaseException {
+
+ CMS.debug("KeyGenProcessor: fillCertInfo");
+
+ if (mServlet == null) {
+ return;
+ }
+
+ KeyGenInfo keyGenInfo = httpParams.getValueAsKeyGenInfo(
+ PKIProcessor.SUBJECT_KEYGEN_INFO, null);
+
+ // fill key
+ X509Key key = null;
+
+ key = keyGenInfo.getSPKI();
+ if (key == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_MISSING_KEY_IN_KEYGENINFO"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_KEY_IN_KEYGENINFO"));
+ }
+ try {
+ certInfo.set(X509CertInfo.KEY, new CertificateX509Key(key));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ "Could not set key into certInfo from keygen. Error " + e);
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_KEYGEN_FAILED", e.toString()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_KEYGEN_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_KEYGEN_FAILED", e.toString()));
+ }
+
+ String authMgr = mServlet.getAuthMgr();
+
+ // if not authenticated, fill subject name, validity & extensions
+ // from authtoken.
+ if (authToken == null) {
+ fillCertInfoFromForm(certInfo, httpParams);
+ } else {
+ if (authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) == null) {
+ // allow special case for agent gateway in admin enroll
+ // and bulk issuance.
+ if (!authMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID) &&
+ !authMgr.equals(IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID)) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN"));
+ }
+ fillCertInfoFromForm(certInfo, httpParams);
+ } else {
+ fillCertInfoFromAuthToken(certInfo, authToken);
+ }
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/PKCS10Processor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/PKCS10Processor.java
new file mode 100644
index 000000000..184216972
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/PKCS10Processor.java
@@ -0,0 +1,285 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.processors;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+
+import netscape.security.pkcs.PKCS10;
+import netscape.security.pkcs.PKCS10Attribute;
+import netscape.security.pkcs.PKCS10Attributes;
+import netscape.security.pkcs.PKCS9Attribute;
+import netscape.security.util.DerInputStream;
+import netscape.security.util.DerOutputStream;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.Extensions;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * PKCS10Processor process Certificate Requests in
+ * PKCS10 format, as defined here:
+ * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-10/index.html
+ *
+ * @version $Revision$, $Date$
+ */
+public class PKCS10Processor extends PKIProcessor {
+
+ private PKCS10 mPkcs10 = null;
+
+ private final String USE_INTERNAL_PKCS10 = "internal";
+
+ public PKCS10Processor() {
+
+ super();
+ }
+
+ public PKCS10Processor(ICMSRequest cmsReq, CMSServlet servlet) {
+ super(cmsReq, servlet);
+
+ }
+
+ public void process(ICMSRequest cmsReq)
+ throws EBaseException {
+ }
+
+ public void fillCertInfo(
+ PKCS10 pkcs10, X509CertInfo certInfo,
+ IAuthToken authToken, IArgBlock httpParams)
+ throws EBaseException {
+
+ mPkcs10 = pkcs10;
+
+ fillCertInfo(USE_INTERNAL_PKCS10, certInfo, authToken, httpParams);
+
+ }
+
+ public void fillCertInfo(
+ String protocolString, X509CertInfo certInfo,
+ IAuthToken authToken, IArgBlock httpParams)
+ throws EBaseException {
+
+ PKCS10 p10 = null;
+
+ CMS.debug("PKCS10Processor:fillCertInfo");
+
+ if (protocolString == null) {
+ p10 = getPKCS10(httpParams);
+ } else if (protocolString.equals(USE_INTERNAL_PKCS10)) {
+ p10 = mPkcs10;
+ } else {
+ CMS.debug("PKCS10Processor::fillCertInfo() - p10 is null!");
+ throw new EBaseException("p10 is null");
+ }
+
+ if (mServlet == null) {
+ EBaseException ex = new ECMSGWException("Servlet property of PKCS10Processor is null.");
+
+ throw ex;
+
+ }
+
+ // fill key
+ X509Key key = p10.getSubjectPublicKeyInfo();
+
+ if (key == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_MISSING_KEY_IN_P10"));
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_MISSING_KEY_IN_P10"));
+ }
+ CertificateX509Key certKey = new CertificateX509Key(key);
+
+ try {
+ certInfo.set(X509CertInfo.KEY, certKey);
+ } catch (CertificateException e) {
+ EBaseException ex = new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString()));
+
+ log(ILogger.LL_FAILURE, ex.toString());
+ throw ex;
+ } catch (IOException e) {
+ EBaseException ex = new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString()));
+
+ log(ILogger.LL_FAILURE, ex.toString());
+ throw ex;
+ }
+
+ X500Name subject = p10.getSubjectName();
+
+ if (subject != null) {
+ try {
+ certInfo.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(subject));
+ log(ILogger.LL_INFO,
+ "Setting subject name " + subject + " from p10.");
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_SUBJECT_FROM_P10", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_SUBJECT_FROM_P10_FAILED", e.toString()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_SUBJECT_FROM_P10", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_SUBJECT_FROM_P10_FAILED", e.toString()));
+ } catch (Exception e) {
+ // if anything bad happens in X500 name parsing,
+ // this will catch it.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_SUBJECT_FROM_P10", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_SUBJECT_FROM_P10_FAILED", e.toString()));
+ }
+ } else if (authToken == null ||
+ authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_SUBJECT_IN_P10"));
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_MISSING_SUBJECT_IN_P10"));
+ }
+
+ // fill extensions from pkcs 10 attributes if any.
+ // other pkcs10 attributes are not recognized.
+ // ExtensionReq ::= SEQUENCE OF Extension
+ // ExtensionReq {pkcs-9 14}.
+ try {
+ PKCS10Attributes p10Attrs = p10.getAttributes();
+
+ if (p10Attrs != null) {
+ PKCS10Attribute p10Attr = p10Attrs.getAttribute(CertificateExtensions.NAME);
+
+ if (p10Attr != null && p10Attr.getAttributeId().equals(
+ PKCS9Attribute.EXTENSION_REQUEST_OID)) {
+ Extensions exts0 = (Extensions) p10Attr.getAttributeValue();
+ DerOutputStream extOut = new DerOutputStream();
+
+ exts0.encode(extOut);
+ byte[] extB = extOut.toByteArray();
+ DerInputStream extIn = new DerInputStream(extB);
+ CertificateExtensions exts = new CertificateExtensions(extIn);
+
+ if (exts != null) {
+ certInfo.set(X509CertInfo.EXTENSIONS, exts);
+ }
+ }
+ }
+ CMS.debug(
+ "PKCS10Processor: Seted cert extensions from pkcs10. ");
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_EXTENSIONS_FROM_P10", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString()));
+
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_EXTENSIONS_FROM_P10", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString()));
+ } catch (Exception e) {
+ // if anything bad happens in extensions parsing,
+ // this will catch it.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_FAILED_SET_EXTENSIONS_FROM_P10", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString()));
+ }
+
+ // override pkcs10 attributes with authtoken attributes
+ // like subject name, validity and extensions if any.
+ // adminEnroll is an exception
+ String authMgr = mServlet.getAuthMgr();
+
+ if (authToken != null &&
+ authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) != null &&
+ !(authMgr.equals(IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID))) {
+ fillCertInfoFromAuthToken(certInfo, authToken);
+ }
+
+ // SPECIAL CASE:
+ // if it is adminEnroll servlet, get the validity
+ // from the http parameters.
+ if (mServletId.equals(PKIProcessor.ADMIN_ENROLL_SERVLET_ID)) {
+ fillValidityFromForm(certInfo, httpParams);
+ }
+
+ }
+
+ private PKCS10 getPKCS10(IArgBlock httpParams)
+ throws EBaseException {
+
+ PKCS10 pkcs10 = null;
+
+ String certType = null;
+
+ // support Enterprise 3.5.1 server where CERT_TYPE=csrCertType
+ // instead of certType
+ certType = httpParams.getValueAsString(PKIProcessor.OLD_CERT_TYPE, null);
+ if (certType == null) {
+ certType = httpParams.getValueAsString(PKIProcessor.CERT_TYPE, "client");
+ } else {
+ // some policies may rely on the fact that
+ // CERT_TYPE is set. So for 3.5.1 or eariler
+ // we need to set CERT_TYPE but not here.
+ }
+ if (certType.equals("client")) {
+ // coming from MSIE
+ String p10b64 = httpParams.getValueAsString(PKIProcessor.PKCS10_REQUEST, null);
+
+ if (p10b64 != null) {
+ try {
+ byte[] bytes = CMS.AtoB(p10b64);
+
+ pkcs10 = new PKCS10(bytes);
+ } catch (Exception e) {
+ // ok, if the above fails, it could
+ // be a PKCS10 with header
+ pkcs10 = httpParams.getValueAsPKCS10(PKIProcessor.PKCS10_REQUEST, false, null);
+ // e.printStackTrace();
+ }
+ }
+
+ //pkcs10 = httpParams.getValuePKCS10(PKCS10_REQUEST, null);
+
+ } else {
+ try {
+ // coming from server cut & paste blob.
+ pkcs10 = httpParams.getValueAsPKCS10(PKIProcessor.PKCS10_REQUEST, false, null);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ return pkcs10;
+
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/PKIProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/PKIProcessor.java
new file mode 100644
index 000000000..bea899368
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/PKIProcessor.java
@@ -0,0 +1,355 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.processors;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Date;
+
+import javax.servlet.http.HttpServletRequest;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Process Certificate Requests
+ *
+ * @version $Revision$, $Date$
+ */
+public class PKIProcessor implements IPKIProcessor {
+
+ public final static String ADMIN_ENROLL_SERVLET_ID = "caadminEnroll";
+ public static final String SUBJECT_NAME = "subject";
+ public static final String OLD_CERT_TYPE = "csrCertType";
+ public static final String CERT_TYPE = "certType";
+ public static final String PKCS10_REQUEST = "pkcs10Request";
+ public static final String SUBJECT_KEYGEN_INFO = "subjectKeyGenInfo";
+
+ protected ICMSRequest mRequest = null;
+
+ protected HttpServletRequest httpReq = null;
+ protected String mServletId = null;
+ protected CMSServlet mServlet = null;
+
+ protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+
+ public PKIProcessor() {
+ }
+
+ public PKIProcessor(ICMSRequest cmsReq, CMSServlet servlet) {
+ mRequest = cmsReq;
+
+ mServlet = servlet;
+
+ if (mServlet == null || mRequest == null) {
+ return;
+ }
+
+ mServletId = servlet.getId();
+
+ }
+
+ public void process(ICMSRequest cmsReq)
+ throws EBaseException {
+ }
+
+ protected void fillCertInfo(
+ String protocolString, X509CertInfo certInfo,
+ IAuthToken authToken, IArgBlock httpParams)
+ throws EBaseException {
+ }
+
+ protected X509CertInfo[] fillCertInfoArray(
+ String protocolString, IAuthToken authToken, IArgBlock httpParams, IRequest req)
+ throws EBaseException {
+ return null;
+ }
+
+ /**
+ * fill subject name, validity, extensions from authoken if any,
+ * overriding what was in pkcs10.
+ * fill subject name, extensions from http input if not authenticated.
+ * requests not authenticated will need to be approved by an agent.
+ */
+ public static void fillCertInfoFromAuthToken(
+ X509CertInfo certInfo, IAuthToken authToken)
+ throws EBaseException {
+ // override subject, validity and extensions from auth token
+ // CA determines algorithm, version and issuer.
+ // take key from keygen, cmc, pkcs10 or crmf.
+
+ CMS.debug("PKIProcessor: fillCertInfoFromAuthToken");
+ // subject name.
+ try {
+ String subjectname =
+ authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT);
+
+ if (subjectname != null) {
+ CertificateSubjectName certSubject = new CertificateSubjectName(new X500Name(subjectname));
+
+ certInfo.set(X509CertInfo.SUBJECT, certSubject);
+ log(ILogger.LL_INFO,
+ "cert subject set to " + certSubject + " from authtoken");
+ }
+ } catch (CertificateException e) {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1",
+ e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR"));
+ } catch (IOException e) {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME",
+ e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR"));
+ }
+
+ // validity
+ try {
+ CertificateValidity validity = null;
+ Date notBefore =
+ authToken.getInDate(AuthToken.TOKEN_CERT_NOTBEFORE);
+ Date notAfter =
+ authToken.getInDate(AuthToken.TOKEN_CERT_NOTAFTER);
+
+ if (notBefore != null && notAfter != null) {
+ validity = new CertificateValidity(notBefore, notAfter);
+ certInfo.set(X509CertInfo.VALIDITY, validity);
+ log(ILogger.LL_INFO,
+ "cert validity set to " + validity + " from authtoken");
+ }
+ } catch (CertificateException e) {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_ERROR_SET_VALIDITY_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_VALIDITY_ERROR"));
+ } catch (IOException e) {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_ERROR_SET_VALIDITY_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_VALIDITY_ERROR"));
+ }
+
+ // extensions
+ try {
+ CertificateExtensions extensions =
+ authToken.getInCertExts(X509CertInfo.EXTENSIONS);
+
+ if (extensions != null) {
+ certInfo.set(X509CertInfo.EXTENSIONS, extensions);
+ log(ILogger.LL_INFO, "cert extensions set from authtoken");
+ }
+ } catch (CertificateException e) {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_ERROR_SET_EXTENSIONS_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_EXTENSIONS_ERROR"));
+ } catch (IOException e) {
+ log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSGW_ERROR_SET_EXTENSIONS_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_EXTENSIONS_ERROR"));
+ }
+ }
+
+ /**
+ * fill subject name, extension from form.
+ * this is done for unauthenticated requests.
+ * unauthenticated requests must be approved by agents so these will
+ * all be seen by and agent.
+ */
+ public static void fillCertInfoFromForm(
+ X509CertInfo certInfo, IArgBlock httpParams)
+ throws EBaseException {
+
+ CMS.debug("PKIProcessor: fillCertInfoFromForm");
+ // subject name.
+ try {
+ String subject = httpParams.getValueAsString(PKIProcessor.SUBJECT_NAME, null);
+
+ if (subject == null) {
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_SUBJECT_FROM_FORM"));
+ }
+
+ X500Name x500name = new X500Name(subject);
+
+ certInfo.set(
+ X509CertInfo.SUBJECT, new CertificateSubjectName(x500name));
+
+ fillValidityFromForm(certInfo, httpParams);
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR"));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR"));
+ } catch (IllegalArgumentException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString()));
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_REQ_ILLEGAL_CHARACTERS"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CONVERT_DN_TO_X500NAME_ERROR"));
+ }
+
+ // requested extensions.
+ // let polcies form extensions from http input.
+ }
+
+ public static void fillValidityFromForm(
+ X509CertInfo certInfo, IArgBlock httpParams)
+ throws EBaseException {
+ CMS.debug("PKIProcessor: fillValidityFromForm!");
+ try {
+ String notValidBeforeStr = httpParams.getValueAsString("notValidBefore", null);
+ String notValidAfterStr = httpParams.getValueAsString("notValidAfter", null);
+
+ if (notValidBeforeStr != null && notValidAfterStr != null) {
+ long notValidBefore = 0;
+ long notValidAfter = 0;
+
+ try {
+ notValidBefore = Long.parseLong(notValidBeforeStr);
+ } catch (NumberFormatException e) {
+ }
+ try {
+ notValidAfter = Long.parseLong(notValidAfterStr);
+ } catch (NumberFormatException e) {
+ }
+
+ if (notValidBefore > 0 && notValidAfter > 0) {
+ CertificateValidity validity = null;
+ Date notBefore = new Date(notValidBefore);
+ Date notAfter = new Date(notValidAfter);
+
+ if (notBefore != null && notAfter != null) {
+ validity = new CertificateValidity(notBefore, notAfter);
+ certInfo.set(X509CertInfo.VALIDITY, validity);
+ log(ILogger.LL_INFO,
+ "cert validity set to " + validity + " from authtoken");
+ }
+ }
+ }
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR"));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR"));
+ }
+ }
+
+ /**
+ * log according to authority category.
+ */
+ public static void log(int event, int level, String msg) {
+ CMS.getLogger().log(event, ILogger.S_OTHER, level,
+ "PKIProcessor " + ": " + msg);
+ }
+
+ public static void log(int level, String msg) {
+ CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER, level,
+ "PKIProcessor " + ": " + msg);
+ }
+
+ /**
+ * Signed Audit Log
+ *
+ * This method is inherited by all extended "CMSServlet"s,
+ * and is called to store messages to the signed audit log.
+ * <P>
+ *
+ * @param msg signed audit log message
+ */
+ protected void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+
+ if (mSignedAuditLogger == null) {
+ return;
+ }
+
+ mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+
+ /**
+ * Signed Audit Log Subject ID
+ *
+ * This method is inherited by all extended "CMSServlet"s,
+ * and is called to obtain the "SubjectID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @return id string containing the signed audit log message SubjectID
+ */
+ protected String auditSubjectID() {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String subjectID = null;
+
+ // Initialize subjectID
+ SessionContext auditContext = SessionContext.getExistingContext();
+
+ if (auditContext != null) {
+ subjectID = (String)
+ auditContext.get(SessionContext.USER_ID);
+
+ if (subjectID != null) {
+ subjectID = subjectID.trim();
+ } else {
+ subjectID = ILogger.NONROLEUSER;
+ }
+ } else {
+ subjectID = ILogger.UNIDENTIFIED;
+ }
+
+ return subjectID;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/Processor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/Processor.java
new file mode 100644
index 000000000..5a3b27063
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/Processor.java
@@ -0,0 +1,1312 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.processors;
+
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.StringTokenizer;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.FormParam;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.IAuthzSubsystem;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.ForbiddenException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.IAuditor;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.usrgrp.ICertUserLocator;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.util.IStatsSubsystem;
+import com.netscape.cms.servlet.common.AuthCredentials;
+import com.netscape.cms.servlet.common.CMSGateway;
+import com.netscape.cms.servlet.common.ServletUtils;
+import com.netscape.cmsutil.util.Utils;
+
+public class Processor {
+
+ public final static String ARG_AUTH_TOKEN = "auth_token";
+ public final static String ARG_REQUEST_OWNER = "requestOwner";
+ public final static String HDR_LANG = "accept-language";
+ public final static String ARG_PROFILE = "profile";
+ public final static String ARG_REQUEST_NOTES = "requestNotes";
+ public final static String ARG_PROFILE_ID = "profileId";
+ public final static String ARG_RENEWAL_PROFILE_ID = "rprofileId";
+ public final static String ARG_PROFILE_IS_ENABLED = "profileIsEnable";
+ public final static String ARG_PROFILE_IS_VISIBLE = "profileIsVisible";
+ public final static String ARG_PROFILE_ENABLED_BY = "profileEnableBy";
+ public final static String ARG_PROFILE_APPROVED_BY = "profileApprovedBy";
+ public final static String ARG_PROFILE_NAME = "profileName";
+ public final static String ARG_PROFILE_DESC = "profileDesc";
+ public final static String ARG_PROFILE_REMOTE_HOST = "profileRemoteHost";
+ public final static String ARG_PROFILE_REMOTE_ADDR = "profileRemoteAddr";
+ public final static String ARG_PROFILE_SET_ID = "profileSetId";
+ public final static String ARG_OUTPUT_LIST = "outputList";
+ public final static String ARG_OUTPUT_ID = "outputId";
+ public final static String ARG_OUTPUT_SYNTAX = "outputSyntax";
+ public final static String ARG_OUTPUT_CONSTRAINT = "outputConstraint";
+ public final static String ARG_OUTPUT_NAME = "outputName";
+ public final static String ARG_OUTPUT_VAL = "outputVal";
+ public final static String ARG_REQUEST_LIST = "requestList";
+ public final static String ARG_REQUEST_ID = "requestId";
+ public final static String ARG_REQUEST_TYPE = "requestType";
+ public final static String ARG_REQUEST_STATUS = "requestStatus";
+ public final static String ARG_REQUEST_CREATION_TIME = "requestCreationTime";
+ public final static String ARG_REQUEST_MODIFICATION_TIME = "requestModificationTime";
+ public final static String ARG_REQUEST_NONCE = "nonce";
+ public final static String ARG_OP = "op";
+ public final static String ARG_REQUESTS = "requests";
+ public final static String ARG_ERROR_CODE = "errorCode";
+ public final static String ARG_ERROR_REASON = "errorReason";
+ public final static String CERT_ATTR = "javax.servlet.request.X509Certificate";
+
+ // servlet config constants
+ public static final String PROFILE_ID = "profileId";
+ public static final String AUTH_ID = "authId";
+ public static final String ACL_METHOD = "aclMethod";
+ public static final String AUTHZ_RESOURCE_NAME = "authzResourceName";
+ public static final String AUTH_MGR = "authMgr";
+ public static final String AUTHZ_MGR = "authzMgr";
+ public static final String GET_CLIENT_CERT = "getClientCert";
+ public static final String ACL_INFO = "ACLinfo";
+ public static final String AUTHORITY_ID = "authorityId";
+ public static final String PROFILE_SUB_ID = "profileSubId";
+
+ public final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED =
+ "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5";
+ public final static String LOGGING_SIGNED_AUDIT_AUTH_FAIL =
+ "LOGGING_SIGNED_AUDIT_AUTH_FAIL_4";
+ public final static String LOGGING_SIGNED_AUDIT_AUTH_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_AUTH_SUCCESS_3";
+ public final static String LOGGING_SIGNED_AUDIT_AUTHZ_FAIL =
+ "LOGGING_SIGNED_AUDIT_AUTHZ_FAIL_4";
+ public final static String LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS_4";
+ public final static String LOGGING_SIGNED_AUDIT_ROLE_ASSUME =
+ "LOGGING_SIGNED_AUDIT_ROLE_ASSUME_3";
+ public final static String SIGNED_AUDIT_CERT_REQUEST_REASON =
+ "requestNotes";
+
+ protected String profileID;
+ protected String profileSubId;
+ protected String aclMethod;
+ protected String authzResourceName;
+ protected String authMgr;
+ protected String getClientCert = "false";
+ protected Locale locale;
+
+ // subsystems
+ protected ICertificateAuthority authority = (ICertificateAuthority) CMS.getSubsystem("ca");
+ protected IAuthzSubsystem authz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ);
+ protected IUGSubsystem ug = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+ protected ICertUserLocator ul = ug.getCertUserLocator();
+ protected IRequestQueue queue;
+ protected IProfileSubsystem ps;
+ protected ICertificateRepository certdb;
+
+ //logging and stats
+
+ protected ILogger logger = CMS.getLogger();
+ protected IAuditor auditor = CMS.getAuditor();
+ protected ILogger signedAuditLogger = CMS.getSignedAuditLogger();
+ protected LinkedHashSet<String> statEvents = new LinkedHashSet<String>();
+
+ public Processor(String id, Locale locale) throws EPropertyNotFound, EBaseException {
+ IConfigStore cs = CMS.getConfigStore().getSubStore("processor." + id);
+ this.locale = locale;
+ this.profileID = cs.getString(PROFILE_ID, "").isEmpty() ? null : cs.getString(PROFILE_ID);
+ this.authzResourceName = cs.getString(AUTHZ_RESOURCE_NAME, "").isEmpty() ? null :
+ cs.getString(AUTHZ_RESOURCE_NAME);
+ this.authMgr = cs.getString(AUTH_MGR, "").isEmpty() ? null : cs.getString(AUTH_MGR);
+ this.getClientCert = cs.getString(GET_CLIENT_CERT, "").isEmpty() ? "false" : cs.getString(GET_CLIENT_CERT);
+ this.profileSubId = cs.getString(PROFILE_SUB_ID, "").isEmpty() ? IProfileSubsystem.ID :
+ cs.getString(PROFILE_SUB_ID);
+
+ String aclInfo = cs.getString(ACL_INFO, "").isEmpty() ? null : cs.getString(ACL_INFO);
+ String authzMgr = cs.getString(AUTHZ_MGR, "").isEmpty() ? null : cs.getString(AUTHZ_MGR);
+ this.aclMethod = ServletUtils.getACLMethod(aclInfo, authzMgr, id);
+
+ // currently unused but in servlet config
+ // authId = cs.getString(AUTH_ID, "").isEmpty() ? null : cs.getString(AUTH_ID);
+
+ if (authority == null) {
+ throw new EBaseException("CertProcessor: authority is null");
+ }
+
+ queue = authority.getRequestQueue();
+ if (queue == null) {
+ throw new EBaseException("CertProcessor: cannot get request queue");
+ }
+
+ if (profileSubId == null || profileSubId.equals("")) {
+ profileSubId = IProfileSubsystem.ID;
+ }
+
+ ps = (IProfileSubsystem) CMS.getSubsystem(profileSubId);
+ if (ps == null) {
+ throw new EBaseException("CertProcessor: Profile Subsystem not found");
+ }
+
+ certdb = authority.getCertificateRepository();
+ if (certdb == null) {
+ throw new EBaseException("CertProcessor: Certificate repository not found");
+ }
+ }
+
+ /******************************************
+ * Stats - to be moved to Stats module
+ ******************************************/
+
+ public void startTiming(String event) {
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ statsSub.startTiming(event, true);
+ }
+ statEvents.add(event);
+ }
+
+ public void endTiming(String event) {
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ statsSub.endTiming(event);
+ }
+ statEvents.remove(event);
+ }
+
+ public void endAllEvents() {
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ Iterator<String> iter = statEvents.iterator();
+ while (iter.hasNext()) {
+ String event = iter.next();
+ statsSub.endTiming(event);
+ iter.remove();
+ }
+ }
+ }
+
+ /******************************************
+ * Utility Functions
+ ******************************************/
+
+ public IRequest getRequest(String rid) throws EBaseException {
+ IRequest request = queue.findRequest(new RequestId(rid));
+ return request;
+ }
+
+ protected IRequest getOriginalRequest(BigInteger certSerial, ICertRecord rec) throws EBaseException {
+ MetaInfo metaInfo = (MetaInfo) rec.get(ICertRecord.ATTR_META_INFO);
+ if (metaInfo == null) {
+ CMS.debug("getOriginalRequest: cert record locating MetaInfo failed for serial number "
+ + certSerial.toString());
+ return null;
+ }
+
+ String rid = (String) metaInfo.get(ICertRecord.META_REQUEST_ID);
+ if (rid == null) {
+ CMS.debug("getOriginalRequest: cert record locating request id in MetaInfo failed " +
+ "for serial number " + certSerial.toString());
+ return null;
+ }
+
+ IRequest request = queue.findRequest(new RequestId(rid));
+ return request;
+ }
+
+ protected void printParameterValues(HashMap<String, String> data) {
+ CMS.debug("Start of CertProcessor Input Parameters");
+
+ for (Entry<String, String> entry : data.entrySet()) {
+ String paramName = entry.getKey();
+ // added this facility so that password can be hidden,
+ // all sensitive parameters should be prefixed with
+ // __ (double underscores); however, in the event that
+ // a security parameter slips through, we perform multiple
+ // additional checks to insure that it is NOT displayed
+ if (paramName.startsWith("__") ||
+ paramName.endsWith("password") ||
+ paramName.endsWith("passwd") ||
+ paramName.endsWith("pwd") ||
+ paramName.equalsIgnoreCase("admin_password_again") ||
+ paramName.equalsIgnoreCase("directoryManagerPwd") ||
+ paramName.equalsIgnoreCase("bindpassword") ||
+ paramName.equalsIgnoreCase("bindpwd") ||
+ paramName.equalsIgnoreCase("passwd") ||
+ paramName.equalsIgnoreCase("password") ||
+ paramName.equalsIgnoreCase("pin") ||
+ paramName.equalsIgnoreCase("pwd") ||
+ paramName.equalsIgnoreCase("pwdagain") ||
+ paramName.equalsIgnoreCase("uPasswd")) {
+ CMS.debug("CertProcessor Input Parameter " + paramName + "='(sensitive)'");
+ } else {
+ CMS.debug("CertProcessor Input Parameter " + paramName + "='" + entry.getValue() + "'");
+ }
+ }
+
+ CMS.debug("End of CertProcessor Input Parameters");
+ }
+
+ /**
+ * get ssl client authenticated certificate
+ */
+ public static X509Certificate getSSLClientCertificate(HttpServletRequest httpReq)
+ throws EBaseException {
+ X509Certificate cert = null;
+
+ CMS.debug(CMS.getLogMessage("CMSGW_GETTING_SSL_CLIENT_CERT"));
+
+ // iws60 support Java Servlet Spec V2.2, attribute
+ // javax.servlet.request.X509Certificate now contains array
+ // of X509Certificates instead of one X509Certificate object
+ X509Certificate[] allCerts = (X509Certificate[]) httpReq.getAttribute(CERT_ATTR);
+
+ if (allCerts == null || allCerts.length == 0) {
+ throw new EBaseException("You did not provide a valid certificate for this operation");
+ }
+
+ cert = allCerts[0];
+
+ if (cert == null) {
+ // just don't have a cert.
+
+ CMS.debug(CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL"));
+ return null;
+ }
+
+ // convert to sun's x509 cert interface.
+ try {
+ byte[] certEncoded = cert.getEncoded();
+ cert = new X509CertImpl(certEncoded);
+ } catch (CertificateEncodingException e) {
+ CMS.debug(CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL_ENCODE", e.getMessage()));
+ return null;
+
+ } catch (CertificateException e) {
+ CMS.debug(CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL_DECODE", e.getMessage()));
+ return null;
+ }
+ return cert;
+ }
+
+ public void log(int source, int level, String message) {
+
+ if (logger == null) return;
+
+ logger.log(ILogger.EV_SYSTEM,
+ null,
+ source,
+ level,
+ getClass().getSimpleName() + ": " + message);
+ }
+
+ protected static Hashtable<String, String> toHashtable(HttpServletRequest req) {
+ Hashtable<String, String> httpReqHash = new Hashtable<String, String>();
+ Enumeration<?> names = req.getParameterNames();
+
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+
+ httpReqHash.put(name, req.getParameter(name));
+ }
+ return httpReqHash;
+ }
+
+ /******************************************
+ * AUTHENTICATION FUNCTIONS (move to Realm?)
+ ******************************************/
+
+ /*
+ * authenticate for renewal - more to add necessary params/values
+ * to the session context
+ */
+ public IAuthToken authenticate(IProfileAuthenticator authenticator,
+ HttpServletRequest request, IRequest origReq, SessionContext context) throws EBaseException
+ {
+ IAuthToken authToken = authenticate(authenticator, request);
+ // For renewal, fill in necessary params
+ if (authToken != null) {
+ String ouid = origReq.getExtDataInString("auth_token.uid");
+ // if the orig cert was manually approved, then there was
+ // no auth token uid. Try to get the uid from the cert dn
+ // itself, if possible
+ if (ouid == null) {
+ String sdn = (String) context.get("origSubjectDN");
+ if (sdn != null) {
+ ouid = getUidFromDN(sdn);
+ if (ouid != null)
+ CMS.debug("CertProcessor: renewal: authToken original uid not found");
+ }
+ } else {
+ CMS.debug("CertProcessor: renewal: authToken original uid found in orig request auth_token");
+ }
+ String auid = authToken.getInString("uid");
+ if (auid != null) { // not through ssl client auth
+ CMS.debug("CertProcessor: renewal: authToken uid found:" + auid);
+ // authenticated with uid
+ // put "orig_req.auth_token.uid" so that authz with
+ // UserOrigReqAccessEvaluator will work
+ if (ouid != null) {
+ context.put("orig_req.auth_token.uid", ouid);
+ CMS.debug("CertProcessor: renewal: authToken original uid found:" + ouid);
+ } else {
+ CMS.debug("CertProcessor: renewal: authToken original uid not found");
+ }
+ } else { // through ssl client auth?
+ CMS.debug("CertProcessor: renewal: authToken uid not found:");
+ // put in orig_req's uid
+ if (ouid != null) {
+ CMS.debug("CertProcessor: renewal: origReq uid not null:" + ouid + ". Setting authtoken");
+ authToken.set("uid", ouid);
+ context.put(SessionContext.USER_ID, ouid);
+ } else {
+ CMS.debug("CertProcessor: renewal: origReq uid not found");
+ // throw new EBaseException("origReq uid not found");
+ }
+ }
+
+ String userdn = origReq.getExtDataInString("auth_token.userdn");
+ if (userdn != null) {
+ CMS.debug("CertProcessor: renewal: origReq userdn not null:" + userdn + ". Setting authtoken");
+ authToken.set("userdn", userdn);
+ } else {
+ CMS.debug("CertProcessor: renewal: origReq userdn not found");
+ // throw new EBaseException("origReq userdn not found");
+ }
+ } else {
+ CMS.debug("CertProcessor: renewal: authToken null");
+ }
+ return authToken;
+ }
+
+ public IAuthToken authenticate(IProfileAuthenticator authenticator,
+ HttpServletRequest request) throws EBaseException {
+ AuthCredentials credentials = new AuthCredentials();
+
+ // build credential
+ Enumeration<String> authNames = authenticator.getValueNames();
+
+ if (authNames != null) {
+ while (authNames.hasMoreElements()) {
+ String authName = authNames.nextElement();
+
+ credentials.set(authName, request.getParameter(authName));
+ }
+ }
+
+ credentials.set("clientHost", request.getRemoteHost());
+ IAuthToken authToken = authenticator.authenticate(credentials);
+
+ SessionContext sc = SessionContext.getContext();
+ if (sc != null) {
+ sc.put(SessionContext.AUTH_MANAGER_ID, authenticator.getName());
+ String userid = authToken.getInString(IAuthToken.USER_ID);
+ if (userid != null) {
+ sc.put(SessionContext.USER_ID, userid);
+ }
+ }
+
+ return authToken;
+ }
+
+ public IAuthToken authenticate(HttpServletRequest request, IRequest origReq, IProfileAuthenticator authenticator,
+ SessionContext context, boolean isRenewal) throws EBaseException {
+ startTiming("profile_authentication");
+
+ IAuthToken authToken = null;
+ if (authenticator != null) {
+ CMS.debug("authenticate: authentication required.");
+ String uid_cred = "Unidentified";
+ String uid_attempted_cred = "Unidentified";
+ Enumeration<String> authIds = authenticator.getValueNames();
+ //Attempt to possibly fetch attempted uid, may not always be available.
+ if (authIds != null) {
+ while (authIds.hasMoreElements()) {
+ String authName = authIds.nextElement();
+ String value = request.getParameter(authName);
+ if (value != null) {
+ if (authName.equals("uid")) {
+ uid_attempted_cred = value;
+ }
+ }
+ }
+ }
+
+ String authSubjectID = auditSubjectID();
+ String authMgrID = authenticator.getName();
+ String auditMessage = null;
+ try {
+ if (isRenewal) {
+ authToken = authenticate(authenticator, request, origReq, context);
+ } else {
+ authToken = authenticate(authenticator, request);
+ }
+ } catch (EBaseException e) {
+ CMS.debug("CertProcessor: authentication error " + e.toString());
+
+ authSubjectID += " : " + uid_cred;
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ authSubjectID,
+ ILogger.FAILURE,
+ authMgrID,
+ uid_attempted_cred);
+ audit(auditMessage);
+
+ throw e;
+ }
+
+ //Log successful authentication
+ //Attempt to get uid from authToken, most tokens respond to the "uid" cred.
+ uid_cred = authToken.getInString("uid");
+
+ if (uid_cred == null || uid_cred.length() == 0) {
+ uid_cred = "Unidentified";
+ }
+
+ authSubjectID = authSubjectID + " : " + uid_cred;
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_SUCCESS,
+ authSubjectID,
+ ILogger.SUCCESS,
+ authMgrID);
+
+ audit(auditMessage);
+ }
+ endTiming("profile_authentication");
+ return authToken;
+ }
+
+ public IAuthToken authenticate(HttpServletRequest httpReq)
+ throws EBaseException {
+ return authenticate(httpReq, authMgr);
+ }
+
+ public static void saveAuthToken(IAuthToken token, IRequest req) {
+ if (token != null && req != null)
+ req.setExtData(IRequest.AUTH_TOKEN, token);
+
+ // # 56230 - expose auth token parameters to the policy predicate
+ if (token != null && req != null) {
+ Enumeration<String> e = token.getElements();
+ while (e.hasMoreElements()) {
+ String n = e.nextElement();
+ String[] x1 = token.getInStringArray(n);
+ if (x1 != null) {
+ for (int i = 0; i < x1.length; i++) {
+ CMS.debug("Setting " + IRequest.AUTH_TOKEN + "-" + n +
+ "(" + i + ")=" + x1[i]);
+ req.setExtData(IRequest.AUTH_TOKEN + "-" + n + "(" + i + ")",
+ x1[i]);
+ }
+ } else {
+ String x = token.getInString(n);
+ if (x != null) {
+ CMS.debug("Setting " + IRequest.AUTH_TOKEN + "-" + n + "=" + x);
+ req.setExtData(IRequest.AUTH_TOKEN + "-" + n, x);
+ }
+ }
+ } // while
+ } // if
+ }
+
+ public IAuthToken authenticate(HttpServletRequest httpReq, String authMgrName)
+ throws EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = ILogger.UNIDENTIFIED;
+ String auditAuthMgrID = ILogger.UNIDENTIFIED;
+ String auditUID = ILogger.UNIDENTIFIED;
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ IArgBlock httpArgs = CMS.createArgBlock(toHashtable(httpReq));
+ SessionContext ctx = SessionContext.getContext();
+ String ip = httpReq.getRemoteAddr();
+ CMS.debug("IP: " + ip);
+
+ if (ip != null) {
+ ctx.put(SessionContext.IPADDRESS, ip);
+ }
+ if (authMgrName != null) {
+ CMS.debug("AuthMgrName: " + authMgrName);
+ ctx.put(SessionContext.AUTH_MANAGER_ID, authMgrName);
+ }
+ // put locale into session context
+ ctx.put(SessionContext.LOCALE, locale);
+
+ //
+ // check ssl client authentication if specified.
+ //
+ X509Certificate clientCert = null;
+
+ if (getClientCert != null && getClientCert.equals("true")) {
+ CMS.debug("CMSServlet: retrieving SSL certificate");
+ clientCert = getSSLClientCertificate(httpReq);
+ }
+
+ //
+ // check authentication by auth manager if any.
+ //
+ if (authMgrName == null) {
+
+ // Fixed Blackflag Bug #613900: Since this code block does
+ // NOT actually constitute an authentication failure, but
+ // rather the case in which a given servlet has been correctly
+ // configured to NOT require an authentication manager, the
+ // audit message called LOGGING_SIGNED_AUDIT_AUTH_FAIL has
+ // been removed.
+
+ CMS.debug("CMSServlet: no authMgrName");
+ return null;
+ } else {
+ // save the "Subject DN" of this certificate in case it
+ // must be audited as an authentication failure
+ if (clientCert == null) {
+ CMS.debug("CMSServlet: no client certificate found");
+ } else {
+ String certUID = clientCert.getSubjectDN().getName();
+ CMS.debug("CMSServlet: certUID=" + certUID);
+
+ if (certUID != null) {
+ certUID = certUID.trim();
+
+ if (!(certUID.equals(""))) {
+ // reset the "auditUID"
+ auditUID = certUID;
+ }
+ }
+ }
+
+ // reset the "auditAuthMgrID"
+ auditAuthMgrID = authMgrName;
+ }
+ AuthToken authToken = CMSGateway.checkAuthManager(httpReq,
+ httpArgs,
+ clientCert,
+ authMgrName);
+ if (authToken == null) {
+ return null;
+ }
+ String userid = authToken.getInString(IAuthToken.USER_ID);
+
+ CMS.debug("CMSServlet: userid=" + userid);
+
+ if (userid != null) {
+ ctx.put(SessionContext.USER_ID, userid);
+ }
+
+ // reset the "auditSubjectID"
+ auditSubjectID = auditSubjectID();
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditAuthMgrID);
+
+ audit(auditMessage);
+
+ return authToken;
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTH_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditAuthMgrID,
+ auditUID);
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ }
+ }
+
+ String getUidFromDN(String userdn) {
+ StringTokenizer st = new StringTokenizer(userdn, ",");
+ while (st.hasMoreTokens()) {
+ String t = st.nextToken();
+ int i = t.indexOf("=");
+
+ if (i == -1) {
+ continue;
+ }
+ String n = t.substring(0, i);
+ if (n.equalsIgnoreCase("uid")) {
+ String v = t.substring(i + 1);
+ CMS.debug("CertProcessor:: getUidFromDN(): uid found:" + v);
+ return v;
+ } else {
+ continue;
+ }
+ }
+ return null;
+ }
+
+ /******************************************
+ * AUTHZ FNCTIONS (to be moved to Realm?)
+ *****************************************/
+
+ public AuthzToken authorize(String authzMgrName, String resource, IAuthToken authToken,
+ String exp) throws EBaseException {
+ AuthzToken authzToken = null;
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditGroupID = auditGroupID();
+ String auditACLResource = resource;
+ String auditOperation = "enroll";
+
+ try {
+ authzToken = authz.authorize(authzMgrName, authToken, exp);
+ if (authzToken != null) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditGroupID);
+
+ audit(auditMessage);
+ } else {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditGroupID);
+
+ audit(auditMessage);
+ }
+ return authzToken;
+ } catch (EBaseException e) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditGroupID);
+
+ audit(auditMessage);
+ throw e;
+ }
+ }
+
+ /**
+ * Authorize must occur after Authenticate
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_FAIL used when authorization has failed
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS used when authorization is successful
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_ROLE_ASSUME used when user assumes a role (in current CS that's when one
+ * accesses a role port)
+ * </ul>
+ *
+ * @param authzMgrName string representing the name of the authorization
+ * manager
+ * @param authToken the authentication token
+ * @param resource a string representing the ACL resource id as defined in
+ * the ACL resource list
+ * @param operation a string representing one of the operations as defined
+ * within the ACL statement (e. g. - "read" for an ACL statement containing
+ * "(read,write)")
+ * @exception EBaseException an error has occurred
+ * @return the authorization token
+ */
+ public AuthzToken authorize(String authzMgrName, IAuthToken authToken,
+ String resource, String operation) {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditGroupID = auditGroupID();
+ String auditID = auditSubjectID;
+ String auditACLResource = resource;
+ String auditOperation = operation;
+
+ SessionContext auditContext = SessionContext.getExistingContext();
+ String authManagerId = null;
+
+ if (auditContext != null) {
+ authManagerId = (String) auditContext.get(SessionContext.AUTH_MANAGER_ID);
+
+ if (authManagerId != null && authManagerId.equals("TokenAuth")) {
+ if (auditSubjectID.equals(ILogger.NONROLEUSER) ||
+ auditSubjectID.equals(ILogger.UNIDENTIFIED)) {
+ CMS.debug("CMSServlet: in authorize... TokenAuth auditSubjectID unavailable, changing to auditGroupID");
+ auditID = auditGroupID;
+ }
+ }
+ }
+
+ // "normalize" the "auditACLResource" value
+ if (auditACLResource != null) {
+ auditACLResource = auditACLResource.trim();
+ }
+
+ // "normalize" the "auditOperation" value
+ if (auditOperation != null) {
+ auditOperation = auditOperation.trim();
+ }
+
+ if (authzMgrName == null) {
+ // Fixed Blackflag Bug #613900: Since this code block does
+ // NOT actually constitute an authorization failure, but
+ // rather the case in which a given servlet has been correctly
+ // configured to NOT require an authorization manager, the
+ // audit message called LOGGING_SIGNED_AUDIT_AUTHZ_FAIL and
+ // the audit message called LOGGING_SIGNED_AUDIT_ROLE_ASSUME
+ // (marked as a failure) have been removed.
+
+ return null;
+ }
+
+ try {
+ AuthzToken authzTok = authz.authorize(authzMgrName,
+ authToken,
+ resource,
+ operation);
+
+ if (authzTok != null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditID,
+ ILogger.SUCCESS,
+ auditGroups(auditSubjectID));
+
+ audit(auditMessage);
+ } else {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditID,
+ ILogger.FAILURE,
+ auditGroups(auditSubjectID));
+
+ audit(auditMessage);
+ }
+
+ return authzTok;
+ } catch (Exception eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_AUTHZ_FAIL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditACLResource,
+ auditOperation);
+
+ audit(auditMessage);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+ auditID,
+ ILogger.FAILURE,
+ auditGroups(auditSubjectID));
+
+ audit(auditMessage);
+
+ return null;
+ }
+ }
+
+ public void authorize(String profileId, IProfile profile, IAuthToken authToken) throws EBaseException {
+ if (authToken != null) {
+ CMS.debug("CertProcessor authToken not null");
+
+ String acl = profile.getAuthzAcl();
+ CMS.debug("CertProcessor: authz using acl: " + acl);
+ if (acl != null && acl.length() > 0) {
+ String resource = profileId + ".authz.acl";
+ authorize(aclMethod, resource, authToken, acl);
+ }
+ }
+ }
+
+ /******************************************
+ * AUDIT FUNCTIONS (to be moved to Auditor?)
+ ******************************************/
+ protected void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+
+ if (signedAuditLogger == null) {
+ return;
+ }
+
+ signedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+
+ /**
+ * Signed Audit Log Requester ID
+ *
+ * This method is called to obtain the "RequesterID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param request the actual request
+ * @return id string containing the signed audit log message RequesterID
+ */
+ protected String auditRequesterID(IRequest request) {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) {
+ return null;
+ }
+
+ String requesterID = ILogger.UNIDENTIFIED;
+
+ if (request != null) {
+ // overwrite "requesterID" if and only if "id" != null
+ String id = request.getRequestId().toString();
+
+ if (id != null) {
+ requesterID = id.trim();
+ }
+ }
+
+ return requesterID;
+ }
+
+ /**
+ * Signed Audit Log Info Certificate Value
+ *
+ * This method is called to obtain the certificate from the passed in
+ * "X509CertImpl" for a signed audit log message.
+ * <P>
+ *
+ * @param request request containing an X509CertImpl
+ * @return cert string containing the certificate
+ */
+ protected String auditInfoCertValue(IRequest request) {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) {
+ return null;
+ }
+
+ X509CertImpl x509cert = request.getExtDataInCert(
+ IEnrollProfile.REQUEST_ISSUED_CERT);
+
+ if (x509cert == null) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ byte rawData[] = null;
+
+ try {
+ rawData = x509cert.getEncoded();
+ } catch (CertificateEncodingException e) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ String cert = null;
+
+ // convert "rawData" into "base64Data"
+ if (rawData != null) {
+ String base64Data = null;
+
+ base64Data = Utils.base64encode(rawData).trim();
+
+ // extract all line separators from the "base64Data"
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < base64Data.length(); i++) {
+ if (!Character.isWhitespace(base64Data.charAt(i))) {
+ sb.append(base64Data.charAt(i));
+
+ }
+ }
+ cert = sb.toString();
+ }
+
+ if (cert != null) {
+ cert = cert.trim();
+
+ if (cert.equals("")) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ } else {
+ return cert;
+ }
+ } else {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+
+ protected String auditSubjectID() {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) {
+ return null;
+ }
+
+ CMS.debug("CMSServlet: in auditSubjectID");
+ String subjectID = null;
+
+ // Initialize subjectID
+ SessionContext auditContext = SessionContext.getExistingContext();
+
+ CMS.debug("CMSServlet: auditSubjectID auditContext " + auditContext);
+ if (auditContext != null) {
+ subjectID = (String)
+ auditContext.get(SessionContext.USER_ID);
+
+ CMS.debug("CMSServlet auditSubjectID: subjectID: " + subjectID);
+ if (subjectID != null) {
+ subjectID = subjectID.trim();
+ } else {
+ subjectID = ILogger.NONROLEUSER;
+ }
+ } else {
+ subjectID = ILogger.UNIDENTIFIED;
+ }
+
+ return subjectID;
+ }
+
+ protected String auditGroupID() {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) {
+ return null;
+ }
+
+ CMS.debug("CMSServlet: in auditGroupID");
+ String groupID = null;
+
+ // Initialize groupID
+ SessionContext auditContext = SessionContext.getExistingContext();
+
+ CMS.debug("CMSServlet: auditGroupID auditContext " + auditContext);
+ if (auditContext != null) {
+ groupID = (String)
+ auditContext.get(SessionContext.GROUP_ID);
+
+ CMS.debug("CMSServlet auditGroupID: groupID: " + groupID);
+ if (groupID != null) {
+ groupID = groupID.trim();
+ } else {
+ groupID = ILogger.NONROLEUSER;
+ }
+ } else {
+ groupID = ILogger.UNIDENTIFIED;
+ }
+
+ return groupID;
+ }
+
+ /**
+ * Signed Audit Log Info Value
+ *
+ * This method is called to obtain the "reason" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param request the actual request
+ * @return reason string containing the signed audit log message reason
+ */
+ protected String auditInfoValue(IRequest request) {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) {
+ return null;
+ }
+
+ String reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+
+ if (request != null) {
+ // overwrite "reason" if and only if "info" != null
+ String info =
+ request.getExtDataInString(SIGNED_AUDIT_CERT_REQUEST_REASON);
+
+ if (info != null) {
+ reason = info.trim();
+
+ // overwrite "reason" if and only if "reason" is empty
+ if (reason.equals("")) {
+ reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+ }
+
+ return reason;
+ }
+
+ /**
+ * Signed Audit Log Info Certificate Value
+ *
+ * This method is called to obtain the certificate from the passed in
+ * "X509CertImpl" for a signed audit log message.
+ * <P>
+ *
+ * @param x509cert an X509CertImpl
+ * @return cert string containing the certificate
+ */
+ protected String auditInfoCertValue(X509CertImpl x509cert) {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) {
+ return null;
+ }
+
+ if (x509cert == null) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ byte rawData[] = null;
+
+ try {
+ rawData = x509cert.getEncoded();
+ } catch (CertificateEncodingException e) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ String cert = null;
+
+ // convert "rawData" into "base64Data"
+ if (rawData != null) {
+ String base64Data = null;
+
+ base64Data = Utils.base64encode(rawData).trim();
+
+ // extract all line separators from the "base64Data"
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < base64Data.length(); i++) {
+ if (!Character.isWhitespace(base64Data.charAt(i))) {
+ sb.append(base64Data.charAt(i));
+ }
+ }
+ cert = sb.toString();
+ }
+
+ if (cert != null) {
+ cert = cert.trim();
+
+ if (cert.equals("")) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ } else {
+ return cert;
+ }
+ } else {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+
+ /**
+ * Signed Audit Groups
+ *
+ * This method is called to extract all "groups" associated
+ * with the "auditSubjectID()".
+ * <P>
+ *
+ * @param SubjectID string containing the signed audit log message SubjectID
+ * @return a delimited string of groups associated
+ * with the "auditSubjectID()"
+ */
+ protected String auditGroups(String SubjectID) {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) {
+ return null;
+ }
+
+ if ((SubjectID == null) ||
+ (SubjectID.equals(ILogger.UNIDENTIFIED))) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ Enumeration<IGroup> groups = null;
+
+ try {
+ groups = ug.findGroups("*");
+ } catch (Exception e) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ StringBuffer membersString = new StringBuffer();
+
+ while (groups.hasMoreElements()) {
+ IGroup group = groups.nextElement();
+
+ if (group.isMember(SubjectID) == true) {
+ if (membersString.length() != 0) {
+ membersString.append(", ");
+ }
+
+ membersString.append(group.getGroupID());
+ }
+ }
+
+ if (membersString.length() != 0) {
+ return membersString.toString();
+ } else {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+
+ public void validateNonce(
+ HttpServletRequest servletRequest,
+ String name,
+ Object id,
+ Long nonce) throws EBaseException {
+
+ if (nonce == null) {
+ throw new BadRequestException("Missing nonce.");
+ }
+
+ Map<Object, Long> nonces = authority.getNonces(servletRequest, name);
+
+ Long storedNonce = nonces.get(id);
+ if (storedNonce == null) {
+ throw new BadRequestException("Nonce for "+name+" "+id+" does not exist.");
+ }
+
+ if (!nonce.equals(storedNonce)) {
+ throw new ForbiddenException("Invalid nonce");
+ }
+
+ nonces.remove(id);
+
+ CMS.debug("Processor: Nonce verified");
+ }
+
+ public String getUserMessage(String messageId, String... params) {
+ return CMS.getUserMessage(locale, messageId, params);
+ }
+
+ public void audit(String message, String scope, String type, String id, Map<String, String> params, String status) {
+
+ if (auditor == null) return;
+
+ String auditMessage = CMS.getLogMessage(
+ message,
+ auditor.getSubjectID(),
+ status,
+ auditor.getParamString(scope, type, id, params));
+
+ auditor.log(auditMessage);
+ }
+
+ /**
+ * Get the values of the fields annotated with @FormParam.
+ */
+ public Map<String, String> getParams(Object object) {
+
+ Map<String, String> map = new HashMap<String, String>();
+
+ // for each fields in the object
+ for (Method method : object.getClass().getMethods()) {
+ FormParam element = method.getAnnotation(FormParam.class);
+ if (element == null) continue;
+
+ String name = element.value();
+
+ try {
+ // get the value from the object
+ Object value = method.invoke(object);
+
+ // put the value in the map
+ map.put(name, value == null ? null : value.toString());
+
+ } catch (Exception e) {
+ // ignore inaccessible fields
+ e.printStackTrace();
+ }
+ }
+
+ return map;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/PolicyConstraintFactory.java b/base/server/cms/src/com/netscape/cms/servlet/profile/PolicyConstraintFactory.java
new file mode 100644
index 000000000..648e8bc57
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/PolicyConstraintFactory.java
@@ -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.
+//
+// (C) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.profile;
+
+import java.util.Enumeration;
+import java.util.Locale;
+
+import com.netscape.certsrv.profile.IPolicyConstraint;
+import com.netscape.certsrv.profile.PolicyConstraint;
+import com.netscape.certsrv.profile.PolicyConstraintValue;
+import com.netscape.certsrv.property.Descriptor;
+
+public class PolicyConstraintFactory {
+
+ public static PolicyConstraint create(Locale locale, IPolicyConstraint cons, String classId) {
+ PolicyConstraint ret = new PolicyConstraint();
+ ret.setName(cons.getName(locale));
+ ret.setText(cons.getText(locale));
+ ret.setClassId(classId);
+
+ Enumeration<String> conNames = cons.getConfigNames();
+ while (conNames.hasMoreElements()) {
+ String conName = conNames.nextElement();
+ PolicyConstraintValue dataVal =
+ new PolicyConstraintValue(conName, (Descriptor) cons.getConfigDescriptor(locale, conName),
+ cons.getConfig(conName));
+ ret.addConstraint(dataVal);
+ }
+
+ return ret;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/PolicyDefaultFactory.java b/base/server/cms/src/com/netscape/cms/servlet/profile/PolicyDefaultFactory.java
new file mode 100644
index 000000000..0d6ab0495
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/PolicyDefaultFactory.java
@@ -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.
+//
+// (C) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.profile;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Locale;
+
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.PolicyDefault;
+import com.netscape.certsrv.profile.ProfileAttribute;
+import com.netscape.certsrv.profile.ProfileParameter;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.request.IRequest;
+
+public class PolicyDefaultFactory {
+
+ public static PolicyDefault create(IRequest request, Locale locale, IPolicyDefault def) throws EPropertyException {
+ PolicyDefault ret = new PolicyDefault();
+ ret.setName(def.getName(locale));
+ ret.setText(def.getText(locale));
+
+ Enumeration<String> defNames = def.getValueNames();
+ while (defNames.hasMoreElements()) {
+ String defName = defNames.nextElement();
+ ProfileAttribute attr = new ProfileAttribute(
+ defName,
+ def.getValue(defName, locale, request),
+ (Descriptor) def.getValueDescriptor(locale, defName));
+ ret.addAttribute(attr);
+ }
+ return ret;
+ }
+
+ public static PolicyDefault create(IArgBlock params, Locale locale, IPolicyDefault def) throws EPropertyException {
+ PolicyDefault ret = new PolicyDefault();
+ ret.setName(def.getName(locale));
+ ret.setText(def.getText(locale));
+
+ Enumeration<String> defNames = def.getValueNames();
+ while (defNames.hasMoreElements()) {
+ String defName = defNames.nextElement();
+ ProfileAttribute attr = new ProfileAttribute(
+ defName,
+ params.getValueAsString(defName, ""),
+ (Descriptor) def.getValueDescriptor(locale, defName));
+ ret.addAttribute(attr);
+ }
+ return ret;
+ }
+
+ public static PolicyDefault create(Locale locale, IPolicyDefault def, String classId) throws EPropertyException {
+ PolicyDefault ret = new PolicyDefault();
+ ret.setName(def.getName(locale));
+ ret.setText(def.getText(locale));
+ ret.setClassId(classId);
+
+ Enumeration<String> defNames = def.getValueNames();
+ while (defNames.hasMoreElements()) {
+ String defName = defNames.nextElement();
+ ProfileAttribute attr = new ProfileAttribute();
+ attr.setName(defName);
+ attr.setDescriptor((Descriptor) def.getValueDescriptor(locale, defName));
+ ret.addAttribute(attr);
+ }
+
+ List<ProfileParameter> pList = new ArrayList<ProfileParameter>();
+ Enumeration<String> paramNames = def.getConfigNames();
+ while (paramNames.hasMoreElements()) {
+ String paramName = paramNames.nextElement();
+ ProfileParameter p = new ProfileParameter(paramName, def.getConfig(paramName));
+ pList.add(p);
+ }
+ ret.setParams(pList);
+
+ return ret;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileApproveServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileApproveServlet.java
new file mode 100644
index 000000000..7b5343000
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileApproveServlet.java
@@ -0,0 +1,532 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.profile;
+
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IPolicyConstraint;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfilePolicy;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.template.ArgList;
+import com.netscape.certsrv.template.ArgSet;
+import com.netscape.cms.servlet.common.CMSRequest;
+
+/**
+ * Toggle the approval state of a profile
+ *
+ * @version $Revision$, $Date$
+ */
+public class ProfileApproveServlet extends ProfileServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3956879326742839550L;
+ private static final String PROP_AUTHORITY_ID = "authorityId";
+ private String mAuthorityId = null;
+
+ private final static String LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL =
+ "LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL_4";
+ private final static String OP_APPROVE = "approve";
+ private final static String OP_DISAPPROVE = "disapprove";
+
+ public ProfileApproveServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "ImportCert.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID);
+ }
+
+ /**
+ * Process the HTTP request.
+ * <P>
+ *
+ * <ul>
+ * <li>http.param profileId the id of the profile to change
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL used when an agent approves/disapproves a cert
+ * profile set by the administrator for automatic approval
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ * @exception EBaseException an error has occurred
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest request = cmsReq.getHttpReq();
+ HttpServletResponse response = cmsReq.getHttpResp();
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditProfileID = auditProfileID(request);
+ String auditProfileOp = auditProfileOp(request);
+
+ String userid = null;
+ IAuthToken authToken = null;
+ ArgSet args = new ArgSet();
+
+ Locale locale = getLocale(request);
+
+ IProfile profile = null;
+
+ String profileId = null;
+
+ IProfileSubsystem ps = null;
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ try {
+ authToken = authenticate(cmsReq);
+ auditSubjectID = auditSubjectID();
+ CMS.debug("uid=" + authToken.getInString("userid"));
+ userid = authToken.getInString("userid");
+ } catch (Exception e) {
+ auditSubjectID = auditSubjectID();
+ CMS.debug(e.toString());
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE",
+ e.toString()));
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_AUTHENTICATION_ERROR"));
+ outputTemplate(request, response, args);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProfileID,
+ auditProfileOp);
+
+ audit(auditMessage);
+
+ return;
+ }
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "approve");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE",
+ e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE",
+ e.toString()));
+ }
+
+ if (authzToken == null) {
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_AUTHORIZATION_ERROR"));
+ outputTemplate(request, response, args);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProfileID,
+ auditProfileOp);
+
+ audit(auditMessage);
+
+ return;
+ }
+
+ CMS.debug("ProfileApproveServlet: start serving");
+ // (1) Read request from the database
+
+ // (2) Get profile id from the request
+ if (mProfileSubId == null || mProfileSubId.equals("")) {
+ mProfileSubId = IProfileSubsystem.ID;
+ }
+ CMS.debug("ProfileApproveServlet: SubId=" + mProfileSubId);
+ ps = (IProfileSubsystem) CMS.getSubsystem(mProfileSubId);
+
+ if (ps == null) {
+ CMS.debug("ProfileApproveServlet: ProfileSubsystem not found");
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_INTERNAL_ERROR"));
+ outputTemplate(request, response, args);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProfileID,
+ auditProfileOp);
+
+ audit(auditMessage);
+
+ return;
+ }
+
+ // retrieve request
+ IAuthority authority = (IAuthority) CMS.getSubsystem(mAuthorityId);
+
+ if (authority == null) {
+ CMS.debug("ProfileApproveServlet: Authority " + mAuthorityId +
+ " not found");
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_INTERNAL_ERROR"));
+ outputTemplate(request, response, args);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProfileID,
+ auditProfileOp);
+
+ audit(auditMessage);
+
+ return;
+ }
+ IRequestQueue queue = authority.getRequestQueue();
+
+ if (queue == null) {
+ CMS.debug("ProfileApproveServlet: Request Queue of " +
+ mAuthorityId + " not found");
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_INTERNAL_ERROR"));
+ outputTemplate(request, response, args);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProfileID,
+ auditProfileOp);
+
+ audit(auditMessage);
+
+ return;
+ }
+
+ profileId = request.getParameter("profileId");
+
+ CMS.debug("ProfileApproveServlet: profileId=" + profileId);
+
+ args.set(ARG_ERROR_CODE, "0");
+ args.set(ARG_ERROR_REASON, "");
+
+ try {
+ if (ps.isProfileEnable(profileId)) {
+ if (ps.checkOwner()) {
+ if (ps.getProfileEnableBy(profileId).equals(userid)) {
+ ps.disableProfile(profileId);
+ } else {
+ // only enableBy can disable profile
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_PROFILE_NOT_OWNER"));
+ outputTemplate(request, response, args);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProfileID,
+ auditProfileOp);
+
+ audit(auditMessage);
+
+ return;
+ }
+ } else {
+ ps.disableProfile(profileId);
+ }
+ } else {
+ ps.enableProfile(profileId, userid);
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditProfileID,
+ auditProfileOp);
+
+ audit(auditMessage);
+ } catch (EProfileException e) {
+ // profile not enabled
+ CMS.debug("ProfileApproveServlet: profile not error " +
+ e.toString());
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_INTERNAL_ERROR"));
+ outputTemplate(request, response, args);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProfileID,
+ auditProfileOp);
+
+ audit(auditMessage);
+
+ return;
+ }
+ } catch (EBaseException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditProfileID,
+ auditProfileOp);
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ // } catch( ServletException eAudit2 ) {
+ // // store a message in the signed audit log file
+ // auditMessage = CMS.getLogMessage(
+ // LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL,
+ // auditSubjectID,
+ // ILogger.FAILURE,
+ // auditProfileID,
+ // auditProfileOp );
+ //
+ // audit( auditMessage );
+ //
+ // // rethrow the specific exception to be handled later
+ // throw eAudit2;
+ }
+
+ try {
+ profile = ps.getProfile(profileId);
+ } catch (EProfileException e) {
+ // profile not found
+ CMS.debug("ProfileApproveServlet: profile not found " +
+ e.toString());
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, e.toString());
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_PROFILE_NOT_FOUND", profileId));
+ outputTemplate(request, response, args);
+ return;
+ }
+ if (profile == null) {
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_PROFILE_NOT_FOUND", profileId));
+ outputTemplate(request, response, args);
+ return;
+ }
+
+ Enumeration<String> policySetIds = profile.getProfilePolicySetIds();
+
+ ArgList setlist = new ArgList();
+
+ while (policySetIds.hasMoreElements()) {
+ String setId = policySetIds.nextElement();
+
+ Enumeration<String> policyIds = profile.getProfilePolicyIds(setId);
+ ArgList list = new ArgList();
+
+ while (policyIds.hasMoreElements()) {
+ String id = policyIds.nextElement();
+ IProfilePolicy policy = profile.getProfilePolicy(setId, id);
+
+ // (3) query all the profile policies
+ // (4) default plugins convert request parameters
+ // into string http parameters
+ handlePolicy(list, response, locale,
+ id, policy);
+ }
+ ArgSet setArg = new ArgSet();
+
+ setArg.set(ARG_POLICY_SET_ID, setId);
+ setArg.set(ARG_POLICY, list);
+ setlist.add(setArg);
+ }
+ args.set(ARG_POLICY_SET_LIST, setlist);
+
+ args.set(ARG_PROFILE_ID, profileId);
+ args.set(ARG_PROFILE_IS_ENABLED,
+ Boolean.toString(ps.isProfileEnable(profileId)));
+ args.set(ARG_PROFILE_ENABLED_BY, ps.getProfileEnableBy(profileId));
+ args.set(ARG_PROFILE_NAME, profile.getName(locale));
+ args.set(ARG_PROFILE_DESC, profile.getDescription(locale));
+
+ // (5) return info as template
+ outputTemplate(request, response, args);
+ }
+
+ private void handlePolicy(ArgList list, ServletResponse response,
+ Locale locale, String id, IProfilePolicy policy) {
+ ArgSet set = new ArgSet();
+
+ set.set(ARG_POLICY_ID, id);
+
+ // handle default policy
+ IPolicyDefault def = policy.getDefault();
+ String dDesc = def.getText(locale);
+
+ set.set(ARG_DEF_DESC, dDesc);
+
+ ArgList deflist = new ArgList();
+ Enumeration<String> defNames = def.getValueNames();
+
+ if (defNames != null) {
+ while (defNames.hasMoreElements()) {
+ ArgSet defset = new ArgSet();
+ String defName = defNames.nextElement();
+ IDescriptor defDesc = def.getValueDescriptor(locale, defName);
+ if (defDesc == null) {
+ CMS.debug("defName=" + defName);
+ } else {
+ String defSyntax = defDesc.getSyntax();
+ String defConstraint = defDesc.getConstraint();
+ String defValueName = defDesc.getDescription(locale);
+ String defValue = null;
+
+ defset.set(ARG_DEF_ID, defName);
+ defset.set(ARG_DEF_SYNTAX, defSyntax);
+ defset.set(ARG_DEF_CONSTRAINT, defConstraint);
+ defset.set(ARG_DEF_NAME, defValueName);
+ defset.set(ARG_DEF_VAL, defValue);
+ deflist.add(defset);
+ }
+ }
+ }
+ set.set(ARG_DEF_LIST, deflist);
+
+ // handle constraint policy
+ IPolicyConstraint con = policy.getConstraint();
+ String conDesc = con.getText(locale);
+
+ set.set(ARG_CON_DESC, conDesc);
+
+ list.add(set);
+ }
+
+ /**
+ * Signed Audit Log Profile ID
+ *
+ * This method is called to obtain the "ProfileID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param req HTTP request
+ * @return id string containing the signed audit log message ProfileID
+ */
+ private String auditProfileID(HttpServletRequest req) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String profileID = null;
+
+ // Obtain the profileID
+ profileID = req.getParameter("profileId");
+
+ if (profileID != null) {
+ profileID = profileID.trim();
+ } else {
+ profileID = ILogger.UNIDENTIFIED;
+ }
+
+ return profileID;
+ }
+
+ /**
+ * Signed Audit Log Profile Operation
+ *
+ * This method is called to obtain the "Profile Operation" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param req HTTP request
+ * @return operation string containing either OP_APPROVE, OP_DISAPPROVE,
+ * or SIGNED_AUDIT_EMPTY_VALUE
+ */
+ private String auditProfileOp(HttpServletRequest req) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ if (mProfileSubId == null ||
+ mProfileSubId.equals("")) {
+ mProfileSubId = IProfileSubsystem.ID;
+ }
+
+ IProfileSubsystem ps = (IProfileSubsystem)
+ CMS.getSubsystem(mProfileSubId);
+
+ if (ps == null) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ String profileID = auditProfileID(req);
+
+ if (profileID == ILogger.UNIDENTIFIED) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ if (ps.isProfileEnable(profileID)) {
+ return OP_DISAPPROVE;
+ } else {
+ return OP_APPROVE;
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileInputFactory.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileInputFactory.java
new file mode 100644
index 000000000..f89d8224e
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileInputFactory.java
@@ -0,0 +1,44 @@
+package com.netscape.cms.servlet.profile;
+
+import java.util.Enumeration;
+import java.util.Locale;
+
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.ProfileAttribute;
+import com.netscape.certsrv.profile.ProfileInput;
+import com.netscape.certsrv.request.IRequest;
+
+public class ProfileInputFactory {
+
+ public static ProfileInput create(IProfileInput input, IRequest request, Locale locale) throws EProfileException {
+ ProfileInput ret = new ProfileInput();
+ ret.setName(input.getName(locale));
+ ret.setClassId(input.getClass().getSimpleName());
+ Enumeration<String> names = input.getValueNames();
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ String value = input.getValue(name, locale, request);
+ if (value != null) {
+ ret.addAttribute(new ProfileAttribute(name, value, null));
+ }
+ }
+ return ret;
+ }
+
+ public static ProfileInput create(IProfileInput input, IArgBlock params, Locale locale) throws EProfileException {
+ ProfileInput ret = new ProfileInput();
+ ret.setName(input.getName(locale));
+ ret.setClassId(input.getClass().getSimpleName());
+ Enumeration<String> names = input.getValueNames();
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ String value = params.getValueAsString(name, null);
+ if (value != null) {
+ ret.addAttribute(new ProfileAttribute(name, value, null));
+ }
+ }
+ return ret;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileListServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileListServlet.java
new file mode 100644
index 000000000..6acc1634c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileListServlet.java
@@ -0,0 +1,171 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.profile;
+
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.template.ArgList;
+import com.netscape.certsrv.template.ArgSet;
+import com.netscape.cms.servlet.common.CMSRequest;
+
+/**
+ * List all enabled profiles.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ProfileListServlet extends ProfileServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5118812083812548395L;
+
+ public ProfileListServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "ImportCert.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest request = cmsReq.getHttpReq();
+ HttpServletResponse response = cmsReq.getHttpResp();
+
+ CMS.debug("ProfileListServlet: start serving");
+
+ Locale locale = getLocale(request);
+
+ ArgSet args = new ArgSet();
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "list");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_AUTHORIZATION_ERROR"));
+ outputTemplate(request, response, args);
+ return;
+ }
+
+ // (1) Read request from the database
+
+ // (2) Get profile id from the request
+ if (mProfileSubId == null || mProfileSubId.equals("")) {
+ mProfileSubId = IProfileSubsystem.ID;
+ }
+ CMS.debug("ProfileListServlet: SubId=" + mProfileSubId);
+ IProfileSubsystem ps = (IProfileSubsystem)
+ CMS.getSubsystem(mProfileSubId);
+
+ if (ps == null) {
+ CMS.debug("ProfileListServlet: ProfileSubsystem " +
+ mProfileSubId + " not found");
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_INTERNAL_ERROR"));
+ outputTemplate(request, response, args);
+ return;
+ }
+
+ ArgList list = new ArgList();
+ Enumeration<String> e = ps.getProfileIds();
+
+ if (e != null) {
+ while (e.hasMoreElements()) {
+ String id = e.nextElement();
+ IProfile profile = null;
+
+ try {
+ profile = ps.getProfile(id);
+ } catch (EBaseException e1) {
+ // skip bad profile
+ CMS.debug("ProfileListServlet: profile " + id +
+ " not found (skipped) " + e1.toString());
+ continue;
+ }
+ if (profile == null) {
+ CMS.debug("ProfileListServlet: profile " + id +
+ " not found (skipped)");
+ continue;
+ }
+
+ String name = profile.getName(locale);
+ String desc = profile.getDescription(locale);
+
+ ArgSet profileArgs = new ArgSet();
+
+ profileArgs.set(ARG_PROFILE_IS_ENABLED,
+ Boolean.toString(ps.isProfileEnable(id)));
+ profileArgs.set(ARG_PROFILE_ENABLED_BY,
+ ps.getProfileEnableBy(id));
+ profileArgs.set(ARG_PROFILE_ID, id);
+ profileArgs.set(ARG_PROFILE_IS_VISIBLE,
+ Boolean.toString(profile.isVisible()));
+ profileArgs.set(ARG_PROFILE_NAME, name);
+ profileArgs.set(ARG_PROFILE_DESC, desc);
+ list.add(profileArgs);
+
+ }
+ }
+ args.set(ARG_RECORD, list);
+ args.set(ARG_ERROR_CODE, "0");
+ args.set(ARG_ERROR_REASON, "");
+
+ // (5) return info as template
+ outputTemplate(request, response, args);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileOutputFactory.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileOutputFactory.java
new file mode 100644
index 000000000..278acf488
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileOutputFactory.java
@@ -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.
+//
+//(C) 2012 Red Hat, Inc.
+//All rights reserved.
+//--- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.profile;
+
+import java.util.Enumeration;
+import java.util.Locale;
+
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfileOutput;
+import com.netscape.certsrv.profile.ProfileAttribute;
+import com.netscape.certsrv.profile.ProfileOutput;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.request.IRequest;
+
+public class ProfileOutputFactory {
+
+ public static ProfileOutput create(IProfileOutput output, IRequest request, Locale locale) throws EProfileException {
+ ProfileOutput ret = new ProfileOutput();
+ ret.setName(output.getName(locale));
+ ret.setText(output.getText(locale));
+
+ Enumeration<String> attrNames = output.getValueNames();
+ while (attrNames.hasMoreElements()) {
+ String attrName = attrNames.nextElement();
+ ProfileAttribute attr = new ProfileAttribute(
+ attrName,
+ output.getValue(attrName, locale, request),
+ (Descriptor) output.getValueDescriptor(locale, attrName));
+ ret.addAttribute(attr);
+ }
+ return ret;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java
new file mode 100644
index 000000000..82b168e6f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java
@@ -0,0 +1,181 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.profile;
+
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.authorization.EAuthzException;
+import com.netscape.certsrv.base.BadRequestDataException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.ForbiddenException;
+import com.netscape.certsrv.cert.CertReviewResponse;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EDeferException;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.ProfileAttribute;
+import com.netscape.certsrv.profile.ProfileOutput;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.template.ArgList;
+import com.netscape.certsrv.template.ArgSet;
+import com.netscape.certsrv.template.ArgString;
+import com.netscape.cms.servlet.cert.RequestProcessor;
+import com.netscape.cms.servlet.common.CMSRequest;
+
+/**
+ * This servlet approves profile-based request.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ProfileProcessServlet extends ProfileServlet {
+
+ private static final long serialVersionUID = 5244627530516577838L;
+
+ public ProfileProcessServlet() {
+ }
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ }
+
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest request = cmsReq.getHttpReq();
+ HttpServletResponse response = cmsReq.getHttpResp();
+
+ Locale locale = getLocale(request);
+ ArgSet args = new ArgSet();
+ args.set(ARG_ERROR_CODE, "0");
+ args.set(ARG_ERROR_REASON, "");
+
+ RequestProcessor processor = new RequestProcessor("caProfileProcess", locale);
+
+ String op = request.getParameter("op");
+ if (op == null) {
+ CMS.debug("ProfileProcessServlet: No op found");
+ setError(args, CMS.getUserMessage(locale, "CMS_OP_NOT_FOUND"), request, response);
+ return;
+ }
+
+ String requestId = request.getParameter("requestId");
+ if (requestId == null || requestId.equals("")) {
+ CMS.debug("ProfileProcessServlet: Request Id not found");
+ setError(args, CMS.getUserMessage(locale, "CMS_REQUEST_ID_NOT_FOUND"), request, response);
+ return;
+ }
+
+ IRequest req = processor.getRequest(requestId);
+ if (req == null) {
+ setError(args, CMS.getUserMessage(locale, "CMS_REQUEST_NOT_FOUND", requestId), request, response);
+ return;
+ }
+
+ String profileId = req.getExtDataInString("profileId");
+ if (profileId == null || profileId.equals("")) {
+ CMS.debug("ProfileProcessServlet: Profile Id not found");
+ setError(args, CMS.getUserMessage(locale, "CMS_PROFILE_ID_NOT_FOUND"), request, response);
+ return;
+ }
+ CMS.debug("ProfileProcessServlet: profileId=" + profileId);
+
+ // set request in cmsReq for later retrieval
+ cmsReq.setIRequest(req);
+
+ CertReviewResponse data = null;
+ try {
+ data = processor.processRequest(cmsReq, req, op);
+
+ } catch (ForbiddenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ setError(args, e.getMessage(), request, response);
+ return;
+ } catch (EAuthException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ setError(args, e.getMessage(), request, response);
+ return;
+ } catch (EAuthzException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ setError(args, e.getMessage(), request, response);
+ return;
+ } catch (BadRequestDataException e) {
+ setError(args, e.getMessage(), request, response);
+ return;
+ } catch (ERejectException e) {
+ CMS.debug("ProfileProcessServlet: execution rejected " + e.toString());
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, "CMS_PROFILE_REJECTED", e.toString()));
+ } catch (EDeferException e) {
+ CMS.debug("ProfileProcessServlet: execution defered " + e.toString());
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, "CMS_PROFILE_DEFERRED", e.toString()));
+ } catch (EPropertyException e) {
+ CMS.debug("ProfileProcessServlet: execution error " + e.toString());
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, "CMS_PROFILE_PROPERTY_ERROR", e.toString()));
+ } catch (EProfileException e) {
+ CMS.debug("ProfileProcessServlet: execution error " + e.toString());
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR"));
+ } catch (EBaseException e) {
+ setError(args, e.getMessage(), request, response);
+ return;
+ }
+
+ args.set(ARG_OP, op);
+ args.set(ARG_REQUEST_ID, req.getRequestId().toString());
+ args.set(ARG_REQUEST_STATUS, req.getRequestStatus().toString());
+ args.set(ARG_REQUEST_TYPE, req.getRequestType());
+ args.set(ARG_PROFILE_ID, profileId);
+
+ String errorCode = ((ArgString) args.get(ARG_ERROR_CODE)).getValue();
+
+ if (op.equals("approve") && errorCode.equals("0") && (data != null)) {
+ ArgList outputlist = new ArgList();
+ for (ProfileOutput output: data.getOutputs()) {
+ for (ProfileAttribute attr: output.getAttrs()){
+ ArgSet outputset = new ArgSet();
+ IDescriptor desc = attr.getDescriptor();
+ outputset.set(ARG_OUTPUT_ID, attr.getName());
+ outputset.set(ARG_OUTPUT_SYNTAX, desc.getSyntax());
+ outputset.set(ARG_OUTPUT_CONSTRAINT, desc.getConstraint());
+ outputset.set(ARG_OUTPUT_NAME, desc.getDescription(locale));
+ outputset.set(ARG_OUTPUT_VAL, attr.getValue());
+ outputlist.add(outputset);
+ }
+ }
+ args.set(ARG_OUTPUT_LIST, outputlist);
+ }
+
+ outputTemplate(request, response, args);
+ }
+
+ private void setError(ArgSet args, String reason, HttpServletRequest request, HttpServletResponse response)
+ throws EBaseException {
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, reason);
+ outputTemplate(request, response, args);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java
new file mode 100644
index 000000000..2b3ef83bb
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java
@@ -0,0 +1,450 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.profile;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Random;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IPolicyConstraint;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.IProfileOutput;
+import com.netscape.certsrv.profile.IProfilePolicy;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.template.ArgList;
+import com.netscape.certsrv.template.ArgSet;
+import com.netscape.cms.servlet.common.CMSRequest;
+
+/**
+ * This servlet allows reviewing of profile-based request.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ProfileReviewServlet extends ProfileServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6559751428547928511L;
+
+ private static final String PROP_AUTHORITY_ID = "authorityId";
+
+ private String mAuthorityId = null;
+ ICertificateAuthority authority = null;
+ private Random mRandom = null;
+
+ public ProfileReviewServlet() {
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "ImportCert.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID);
+
+ if (mAuthorityId != null)
+ authority = (ICertificateAuthority) CMS.getSubsystem(mAuthorityId);
+
+ if (authority != null && authority.noncesEnabled()) {
+ mRandom = new Random();
+ }
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param requestId the ID of the profile to review
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest request = cmsReq.getHttpReq();
+ HttpServletResponse response = cmsReq.getHttpResp();
+
+ CMS.debug("ProfileReviewServlet: start serving");
+
+ Locale locale = getLocale(request);
+ ArgSet args = new ArgSet();
+ IAuthToken authToken = null;
+
+ if (mAuthMgr != null) {
+ try {
+ authToken = authenticate(request);
+ } catch (EBaseException e) {
+ CMS.debug("ReviewReqServlet: " + e.toString());
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_AUTHENTICATION_ERROR"));
+ outputTemplate(request, response, args);
+ return;
+ }
+ }
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_AUTHORIZATION_ERROR"));
+ outputTemplate(request, response, args);
+ return;
+ }
+
+ // (1) Read request from the database
+
+ // (2) Get profile id from the request
+ if (mProfileSubId == null || mProfileSubId.equals("")) {
+ mProfileSubId = IProfileSubsystem.ID;
+ }
+ CMS.debug("ProfileReviewServlet: SubId=" + mProfileSubId);
+ IProfileSubsystem ps = (IProfileSubsystem)
+ CMS.getSubsystem(mProfileSubId);
+
+ if (ps == null) {
+ CMS.debug("ProfileReviewServlet: ProfileSubsystem not found");
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_INTERNAL_ERROR"));
+ outputTemplate(request, response, args);
+ return;
+ }
+
+ // retrieve request
+
+ if (authority == null) {
+ CMS.debug("ProfileReviewServlet: Authority " + mAuthorityId +
+ " not found");
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_INTERNAL_ERROR"));
+ outputTemplate(request, response, args);
+ return;
+ }
+ IRequestQueue queue = authority.getRequestQueue();
+
+ if (queue == null) {
+ CMS.debug("ProfileReviewServlet: Request Queue of " +
+ mAuthorityId + " not found");
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_INTERNAL_ERROR"));
+ outputTemplate(request, response, args);
+ return;
+ }
+
+ String requestId = request.getParameter("requestId");
+ IRequest req = null;
+
+ CMS.debug("ProfileReviewServlet: requestId=" + requestId);
+ try {
+ req = queue.findRequest(new RequestId(requestId));
+ } catch (EBaseException e) {
+ // request not found
+ CMS.debug("ProfileReviewServlet: request not found requestId=" +
+ requestId + " " + e.toString());
+ }
+ if (req == null) {
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_REQUEST_NOT_FOUND", requestId));
+ outputTemplate(request, response, args);
+ return;
+ }
+
+ String profileId = req.getExtDataInString("profileId");
+
+ CMS.debug("ProfileReviewServlet: requestId=" +
+ requestId + " profileId=" + profileId);
+ IProfile profile = null;
+
+ try {
+ profile = ps.getProfile(profileId);
+ } catch (EProfileException e) {
+ // profile not found
+ CMS.debug("ProfileReviewServlet: profile not found requestId=" +
+ requestId + " profileId=" + profileId + " " + e.toString());
+ }
+ if (profile == null) {
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_PROFILE_NOT_FOUND", profileId));
+ outputTemplate(request, response, args);
+ return;
+ }
+
+ String profileSetId = req.getExtDataInString("profileSetId");
+
+ CMS.debug("ProfileReviewServlet: profileSetId=" + profileSetId);
+ Enumeration<String> policyIds = (profileSetId != null && profileSetId.length() > 0) ?
+ profile.getProfilePolicyIds(profileSetId) : null;
+ ArgList list = new ArgList();
+
+ if (policyIds != null) {
+ while (policyIds.hasMoreElements()) {
+ String id = policyIds.nextElement();
+ IProfilePolicy policy =
+ profile.getProfilePolicy(req.getExtDataInString("profileSetId"),
+ id);
+
+ // (3) query all the profile policies
+ // (4) default plugins convert request parameters into string
+ // http parameters
+ handlePolicy(list, response, locale,
+ id, policy, req);
+ }
+ }
+
+ if (authority != null && authority.noncesEnabled()) {
+ long n = mRandom.nextLong();
+ Map<Object, Long> nonces = authority.getNonces(request, "cert-request");
+ nonces.put(req.getRequestId().toBigInteger(), n);
+ args.set(ARG_REQUEST_NONCE, Long.toString(n));
+ }
+
+ args.set(ARG_REQUEST_ID, req.getRequestId().toString());
+ args.set(ARG_REQUEST_TYPE, req.getRequestType());
+ args.set(ARG_REQUEST_STATUS, req.getRequestStatus().toString());
+ if (req.getRequestOwner() == null) {
+ args.set(ARG_REQUEST_OWNER, "");
+ } else {
+ args.set(ARG_REQUEST_OWNER, req.getRequestOwner());
+ }
+ args.set(ARG_REQUEST_CREATION_TIME, req.getCreationTime().toString());
+ args.set(ARG_REQUEST_MODIFICATION_TIME,
+ req.getModificationTime().toString());
+
+ args.set(ARG_PROFILE_ID, profileId);
+ args.set(ARG_PROFILE_APPROVED_BY,
+ req.getExtDataInString("profileApprovedBy"));
+ args.set(ARG_PROFILE_SET_ID, req.getExtDataInString("profileSetId"));
+ if (profile.isVisible()) {
+ args.set(ARG_PROFILE_IS_VISIBLE, "true");
+ } else {
+ args.set(ARG_PROFILE_IS_VISIBLE, "false");
+ }
+ args.set(ARG_PROFILE_NAME, profile.getName(locale));
+ args.set(ARG_PROFILE_DESC, profile.getDescription(locale));
+ args.set(ARG_PROFILE_REMOTE_HOST,
+ req.getExtDataInString("profileRemoteHost"));
+ args.set(ARG_PROFILE_REMOTE_ADDR,
+ req.getExtDataInString("profileRemoteAddr"));
+ if (req.getExtDataInString("requestNotes") == null) {
+ args.set(ARG_REQUEST_NOTES, "");
+ } else {
+ args.set(ARG_REQUEST_NOTES,
+ req.getExtDataInString("requestNotes"));
+ }
+
+ args.set(ARG_RECORD, list);
+ args.set(ARG_ERROR_CODE, "0");
+ args.set(ARG_ERROR_REASON, "");
+
+ ArgList inputlist = new ArgList();
+
+ // populate authentication parameters
+
+ // populate input parameters
+ Enumeration<String> inputIds = profile.getProfileInputIds();
+
+ if (inputIds != null) {
+ while (inputIds.hasMoreElements()) {
+ String inputId = inputIds.nextElement();
+ IProfileInput profileInput = profile.getProfileInput(inputId);
+
+ Enumeration<String> inputNames = profileInput.getValueNames();
+
+ if (inputNames != null) {
+ while (inputNames.hasMoreElements()) {
+ ArgSet inputset = new ArgSet();
+ String inputName = inputNames.nextElement();
+
+ IDescriptor inputDesc = profileInput.getValueDescriptor(locale, inputName);
+
+ if (inputDesc == null)
+ continue;
+ String inputSyntax = inputDesc.getSyntax();
+ String inputConstraint = inputDesc.getConstraint();
+ String inputValueName = inputDesc.getDescription(locale);
+ String inputValue = null;
+
+ try {
+ inputValue = profileInput.getValue(inputName, locale, req);
+ } catch (EBaseException e) {
+ CMS.debug("ProfileReviewServlet: " + e.toString());
+ }
+
+ inputset.set(ARG_INPUT_ID, inputName);
+ inputset.set(ARG_INPUT_SYNTAX, inputSyntax);
+ inputset.set(ARG_INPUT_CONSTRAINT, inputConstraint);
+ inputset.set(ARG_INPUT_NAME, inputValueName);
+ inputset.set(ARG_INPUT_VAL, inputValue);
+ inputlist.add(inputset);
+ }
+ }
+ }
+ }
+ args.set(ARG_INPUT_LIST, inputlist);
+
+ // if request in complete state
+
+ ArgList outputlist = new ArgList();
+ Enumeration<String> outputIds = profile.getProfileOutputIds();
+
+ if (outputIds != null) {
+ while (outputIds.hasMoreElements()) {
+ String outputId = outputIds.nextElement();
+ IProfileOutput profileOutput = profile.getProfileOutput(outputId
+ );
+
+ Enumeration<String> outputNames = profileOutput.getValueNames();
+
+ if (outputNames != null) {
+ while (outputNames.hasMoreElements()) {
+ ArgSet outputset = new ArgSet();
+ String outputName = outputNames.nextElement
+ ();
+ IDescriptor outputDesc =
+ profileOutput.getValueDescriptor(locale, outputName);
+
+ if (outputDesc == null)
+ continue;
+ String outputSyntax = outputDesc.getSyntax();
+ String outputConstraint = outputDesc.getConstraint();
+ String outputValueName = outputDesc.getDescription(locale);
+ String outputValue = null;
+
+ try {
+ outputValue = profileOutput.getValue(outputName,
+ locale, req);
+ } catch (EProfileException e) {
+ CMS.debug("ProfileSubmitServlet: " + e.toString(
+ ));
+ }
+
+ outputset.set(ARG_OUTPUT_ID, outputName);
+ outputset.set(ARG_OUTPUT_SYNTAX, outputSyntax);
+ outputset.set(ARG_OUTPUT_CONSTRAINT, outputConstraint);
+ outputset.set(ARG_OUTPUT_NAME, outputValueName);
+ outputset.set(ARG_OUTPUT_VAL, outputValue);
+ outputlist.add(outputset);
+ }
+ }
+ }
+ }
+ args.set(ARG_OUTPUT_LIST, outputlist);
+
+ // (5) return info as template
+ outputTemplate(request, response, args);
+ }
+
+ private void handlePolicy(ArgList list, ServletResponse response,
+ Locale locale, String id, IProfilePolicy policy,
+ IRequest req) {
+ ArgSet set = new ArgSet();
+
+ set.set(ARG_POLICY_ID, id);
+
+ // handle default policy
+ IPolicyDefault def = policy.getDefault();
+ String dDesc = def.getText(locale);
+
+ set.set(ARG_DEF_DESC, dDesc);
+ ArgList deflist = new ArgList();
+ Enumeration<String> defNames = def.getValueNames();
+
+ if (defNames != null) {
+ while (defNames.hasMoreElements()) {
+ ArgSet defset = new ArgSet();
+ String defName = defNames.nextElement();
+ IDescriptor defDesc = def.getValueDescriptor(locale, defName);
+
+ if (defDesc == null)
+ continue;
+ String defSyntax = defDesc.getSyntax();
+ String defConstraint = defDesc.getConstraint();
+ String defValueName = defDesc.getDescription(locale);
+ String defValue = null;
+
+ try {
+ defValue = def.getValue(defName, locale, req);
+ } catch (EPropertyException ee) {
+ CMS.debug("ProfileReviewServlet: " + ee.toString());
+ }
+
+ defset.set(ARG_DEF_ID, defName);
+ defset.set(ARG_DEF_SYNTAX, defSyntax);
+ defset.set(ARG_DEF_CONSTRAINT, defConstraint);
+ defset.set(ARG_DEF_NAME, defValueName);
+ defset.set(ARG_DEF_VAL, defValue);
+ deflist.add(defset);
+ }
+ }
+ set.set(ARG_DEF_LIST, deflist);
+
+ // handle constraint policy
+ IPolicyConstraint con = policy.getConstraint();
+
+ if (con != null) {
+ String conDesc = con.getText(locale);
+
+ set.set(ARG_CON_DESC, conDesc);
+ }
+
+ list.add(set);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java
new file mode 100644
index 000000000..10013c88c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java
@@ -0,0 +1,410 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.profile;
+
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IPolicyConstraint;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.IProfilePolicy;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.template.ArgList;
+import com.netscape.certsrv.template.ArgSet;
+import com.netscape.cms.servlet.common.CMSRequest;
+
+/**
+ * Retrieve detailed information of a particular profile.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ProfileSelectServlet extends ProfileServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3765390650830903602L;
+ private static final String PROP_AUTHORITY_ID = "authorityId";
+ private String mAuthorityId = null;
+
+ public ProfileSelectServlet() {
+ }
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID);
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param profileId the id of the profile to select
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest request = cmsReq.getHttpReq();
+ HttpServletResponse response = cmsReq.getHttpResp();
+
+ CMS.debug("ProfileSelectServlet: start serving");
+
+ Locale locale = getLocale(request);
+
+ IAuthToken authToken = null;
+ ArgSet args = new ArgSet();
+
+ if (mAuthMgr != null) {
+ try {
+ authToken = authenticate(request);
+ } catch (EBaseException e) {
+ CMS.debug("ProcessReqServlet: " + e.toString());
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_AUTHENTICATION_ERROR"));
+ outputTemplate(request, response, args);
+ return;
+ }
+ }
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_AUTHORIZATION_ERROR"));
+ outputTemplate(request, response, args);
+ return;
+ }
+
+ // (1) Read request from the database
+
+ // (2) Get profile id from the request
+ if (mProfileSubId == null || mProfileSubId.equals("")) {
+ mProfileSubId = IProfileSubsystem.ID;
+ }
+ CMS.debug("ProfileSelectServlet: SubId=" + mProfileSubId);
+ IProfileSubsystem ps = (IProfileSubsystem)
+ CMS.getSubsystem(mProfileSubId);
+
+ if (ps == null) {
+ CMS.debug("ProfileSelectServlet: ProfileSubsystem not found");
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_INTERNAL_ERROR"));
+ outputTemplate(request, response, args);
+ return;
+ }
+
+ // retrieve request
+ IAuthority authority = (IAuthority) CMS.getSubsystem(mAuthorityId);
+
+ if (authority == null) {
+ CMS.debug("ProfileSelectServlet: Authority " + mAuthorityId +
+ " not found");
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_INTERNAL_ERROR"));
+ outputTemplate(request, response, args);
+ return;
+ }
+ IRequestQueue queue = authority.getRequestQueue();
+
+ if (queue == null) {
+ CMS.debug("ProfileSelectServlet: Request Queue of " +
+ mAuthorityId + " not found");
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_INTERNAL_ERROR"));
+ outputTemplate(request, response, args);
+ return;
+ }
+
+ IProfile profile = null;
+
+ String profileId = request.getParameter("profileId");
+
+ CMS.debug("ProfileSelectServlet: profileId=" + profileId);
+
+ try {
+ profile = ps.getProfile(profileId);
+ } catch (EProfileException e) {
+ // profile not found
+ CMS.debug("ProfileSelectServlet: profile not found profileId=" +
+ profileId + " " + e.toString());
+ }
+ if (profile == null) {
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_PROFILE_NOT_FOUND", profileId));
+ outputTemplate(request, response, args);
+ return;
+ }
+
+ ArgList setlist = new ArgList();
+ Enumeration<String> policySetIds = profile.getProfilePolicySetIds();
+
+ if (policySetIds != null) {
+ while (policySetIds.hasMoreElements()) {
+ String setId = policySetIds.nextElement();
+
+ ArgList list = new ArgList();
+ Enumeration<String> policyIds = profile.getProfilePolicyIds(setId);
+
+ if (policyIds != null) {
+ while (policyIds.hasMoreElements()) {
+ String id = policyIds.nextElement();
+ IProfilePolicy policy = profile.getProfilePolicy(setId, id);
+
+ // (3) query all the profile policies
+ // (4) default plugins convert request parameters into string
+ // http parameters
+ handlePolicy(list, response, locale,
+ id, policy);
+ }
+ }
+ ArgSet setArg = new ArgSet();
+
+ setArg.set(ARG_POLICY_SET_ID, setId);
+ setArg.set(ARG_POLICY, list);
+ setlist.add(setArg);
+ }
+ }
+ args.set(ARG_POLICY_SET_LIST, setlist);
+
+ args.set(ARG_PROFILE_ID, profileId);
+ args.set(ARG_PROFILE_IS_ENABLED,
+ Boolean.toString(ps.isProfileEnable(profileId)));
+ args.set(ARG_PROFILE_ENABLED_BY, ps.getProfileEnableBy(profileId));
+ args.set(ARG_PROFILE_NAME, profile.getName(locale));
+ args.set(ARG_PROFILE_DESC, profile.getDescription(locale));
+ args.set(ARG_PROFILE_IS_VISIBLE,
+ Boolean.toString(profile.isVisible()));
+ args.set(ARG_ERROR_CODE, "0");
+ args.set(ARG_ERROR_REASON, "");
+
+ try {
+ boolean keyArchivalEnabled = CMS.getConfigStore().getBoolean("ca.connector.KRA.enable", false);
+ if (keyArchivalEnabled == true) {
+ CMS.debug("ProfileSelectServlet: keyArchivalEnabled is true");
+
+ // output transport certificate if present
+ args.set("transportCert",
+ CMS.getConfigStore().getString("ca.connector.KRA.transportCert", ""));
+ } else {
+ CMS.debug("ProfileSelectServlet: keyArchivalEnabled is false");
+ args.set("transportCert", "");
+ }
+ } catch (EBaseException e) {
+ CMS.debug("ProfileSelectServlet: exception caught:" + e.toString());
+ }
+
+ // build authentication
+ ArgList authlist = new ArgList();
+ IProfileAuthenticator authenticator = null;
+
+ try {
+ authenticator = profile.getAuthenticator();
+ } catch (EProfileException e) {
+ // authenticator not installed correctly
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale,
+ "CMS_AUTHENTICATION_MANAGER_NOT_FOUND",
+ profile.getAuthenticatorId()));
+ outputTemplate(request, response, args);
+ return;
+ }
+
+ if (authenticator != null) {
+ Enumeration<String> authNames = authenticator.getValueNames();
+
+ if (authNames != null) {
+ while (authNames.hasMoreElements()) {
+ ArgSet authset = new ArgSet();
+ String authName = authNames.nextElement();
+ IDescriptor authDesc =
+ authenticator.getValueDescriptor(locale, authName);
+
+ if (authDesc == null)
+ continue;
+ String authSyntax = authDesc.getSyntax();
+ String authConstraint = authDesc.getConstraint();
+ String authValueName = authDesc.getDescription(locale);
+
+ authset.set(ARG_AUTH_ID, authName);
+ authset.set(ARG_AUTH_SYNTAX, authSyntax);
+ authset.set(ARG_AUTH_CONSTRAINT, authConstraint);
+ authset.set(ARG_AUTH_NAME, authValueName);
+ authlist.add(authset);
+ }
+ }
+ args.set(ARG_AUTH_LIST, authlist);
+ args.set(ARG_AUTH_NAME, authenticator.getName(locale));
+ args.set(ARG_AUTH_DESC, authenticator.getText(locale));
+ args.set(ARG_AUTH_IS_SSL,
+ Boolean.toString(authenticator.isSSLClientRequired()));
+ }
+
+ // build input list
+ ArgList inputlist = new ArgList();
+ ArgList inputPluginlist = new ArgList();
+ Enumeration<String> inputIds = profile.getProfileInputIds();
+
+ if (inputIds != null) {
+ while (inputIds.hasMoreElements()) {
+ String inputId = inputIds.nextElement();
+ IProfileInput profileInput = profile.getProfileInput(inputId);
+
+ if (profileInput != null) {
+
+ ArgSet inputpluginset = new ArgSet();
+ inputpluginset.set(ARG_INPUT_PLUGIN_ID, inputId);
+ inputpluginset.set(ARG_INPUT_PLUGIN_NAME,
+ profileInput.getName(locale));
+ inputpluginset.set(ARG_INPUT_PLUGIN_DESC,
+ profileInput.getText(locale));
+ inputPluginlist.add(inputpluginset);
+
+ Enumeration<String> inputNames = profileInput.getValueNames();
+
+ if (inputNames != null) {
+ while (inputNames.hasMoreElements()) {
+ ArgSet inputset = new ArgSet();
+ String inputName = inputNames.nextElement();
+ IDescriptor inputDesc = profileInput.getValueDescriptor(
+ locale, inputName);
+
+ if (inputDesc == null)
+ continue;
+ String inputSyntax = inputDesc.getSyntax();
+ String inputConstraint = inputDesc.getConstraint();
+ String inputValueName = inputDesc.getDescription(locale);
+ String inputValue = null;
+
+ inputset.set(ARG_INPUT_PLUGIN_ID, inputId);
+ inputset.set(ARG_INPUT_ID, inputName);
+ inputset.set(ARG_INPUT_SYNTAX, inputSyntax);
+ inputset.set(ARG_INPUT_CONSTRAINT, inputConstraint);
+ inputset.set(ARG_INPUT_NAME, inputValueName);
+ inputset.set(ARG_INPUT_VAL, inputValue);
+ inputlist.add(inputset);
+ }
+ }
+ }
+ }
+ }
+ args.set(ARG_INPUT_LIST, inputlist);
+ args.set(ARG_INPUT_PLUGIN_LIST, inputPluginlist);
+ args.set(ARG_IS_RENEWAL, profile.isRenewal());
+ args.set(ARG_XML_OUTPUT, profile.isXmlOutput());
+
+ // (5) return info as template
+ outputTemplate(request, response, args);
+ }
+
+ private void handlePolicy(ArgList list, ServletResponse response,
+ Locale locale, String id, IProfilePolicy policy) {
+ ArgSet set = new ArgSet();
+
+ set.set(ARG_POLICY_ID, id);
+
+ // handle default policy
+ IPolicyDefault def = policy.getDefault();
+ String dDesc = def.getText(locale);
+
+ set.set(ARG_DEF_DESC, dDesc);
+ ArgList deflist = new ArgList();
+ Enumeration<String> defNames = def.getValueNames();
+
+ if (defNames != null) {
+ while (defNames.hasMoreElements()) {
+ ArgSet defset = new ArgSet();
+ String defName = defNames.nextElement();
+ IDescriptor defDesc = def.getValueDescriptor(locale, defName);
+
+ if (defDesc == null)
+ continue;
+ String defSyntax = defDesc.getSyntax();
+ String defConstraint = defDesc.getConstraint();
+ String defValueName = defDesc.getDescription(locale);
+ String defValue = null;
+
+ defset.set(ARG_DEF_ID, defName);
+ defset.set(ARG_DEF_SYNTAX, defSyntax);
+ defset.set(ARG_DEF_CONSTRAINT, defConstraint);
+ defset.set(ARG_DEF_NAME, defValueName);
+ defset.set(ARG_DEF_VAL, defValue);
+ deflist.add(defset);
+ }
+ }
+ set.set(ARG_DEF_LIST, deflist);
+
+ // handle constraint policy
+ IPolicyConstraint con = policy.getConstraint();
+ String conDesc = con.getText(locale);
+
+ set.set(ARG_CON_DESC, conDesc);
+ ArgList conlist = new ArgList();
+ Enumeration<String> conNames = con.getConfigNames();
+ if (conNames != null) {
+ while (conNames.hasMoreElements()) {
+ ArgSet conset = new ArgSet();
+ String conName = conNames.nextElement();
+ conset.set(ARG_CON_NAME, conName);
+ conset.set(ARG_CON_VALUE, con.getConfig(conName));
+ conlist.add(conset);
+ }
+ }
+ set.set(ARG_CON_LIST, conlist);
+
+ list.add(set);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileService.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileService.java
new file mode 100644
index 000000000..edb8b2248
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileService.java
@@ -0,0 +1,952 @@
+//--- 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) 2011 Red Hat, Inc.
+//All rights reserved.
+//--- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.profile;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Vector;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.commons.lang.StringUtils;
+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.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.base.UnauthorizedException;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileEx;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.IProfileOutput;
+import com.netscape.certsrv.profile.IProfilePolicy;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.profile.PolicyConstraint;
+import com.netscape.certsrv.profile.PolicyConstraintValue;
+import com.netscape.certsrv.profile.PolicyDefault;
+import com.netscape.certsrv.profile.ProfileData;
+import com.netscape.certsrv.profile.ProfileDataInfo;
+import com.netscape.certsrv.profile.ProfileDataInfos;
+import com.netscape.certsrv.profile.ProfileInput;
+import com.netscape.certsrv.profile.ProfileNotFoundException;
+import com.netscape.certsrv.profile.ProfileOutput;
+import com.netscape.certsrv.profile.ProfileParameter;
+import com.netscape.certsrv.profile.ProfilePolicy;
+import com.netscape.certsrv.profile.ProfileResource;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.registry.IPluginInfo;
+import com.netscape.certsrv.registry.IPluginRegistry;
+import com.netscape.cms.realm.PKIPrincipal;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author alee
+ *
+ */
+public class ProfileService extends PKIService implements ProfileResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ private IProfileSubsystem ps = (IProfileSubsystem) CMS.getSubsystem(IProfileSubsystem.ID);
+ private IPluginRegistry registry = (IPluginRegistry) CMS.getSubsystem(CMS.SUBSYSTEM_REGISTRY);
+ private IConfigStore cs = CMS.getConfigStore().getSubStore("profile");
+
+ private final static String LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL =
+ "LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL_4";
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE =
+ "LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE_3";
+
+ public ProfileDataInfos listProfiles() {
+ List<ProfileDataInfo> list = new ArrayList<ProfileDataInfo>();
+ ProfileDataInfos infos = new ProfileDataInfos();
+ boolean visibleOnly = true;
+
+ if (ps == null) {
+ return null;
+ }
+
+ PKIPrincipal principal = (PKIPrincipal) servletRequest.getUserPrincipal();
+ if ((principal != null) &&
+ (principal.hasRole("Certificate Manager Agents") ||
+ principal.hasRole("Certificate Manager Administrators"))) {
+ visibleOnly = false;
+ }
+ Enumeration<String> profileIds = ps.getProfileIds();
+ if (profileIds != null) {
+ while (profileIds.hasMoreElements()) {
+ String id = profileIds.nextElement();
+ ProfileDataInfo info = null;
+ try {
+ info = createProfileDataInfo(id, visibleOnly, uriInfo, getLocale(headers));
+ } catch (EBaseException e) {
+ continue;
+ }
+
+ if (info != null) {
+ list.add(info);
+ }
+ }
+ }
+
+ infos.setProfileInfos(list);
+ return infos;
+ }
+
+ public ProfileData retrieveProfile(String profileId) throws ProfileNotFoundException {
+ ProfileData data = null;
+ boolean visibleOnly = true;
+
+ if (ps == null) {
+ return null;
+ }
+
+ PKIPrincipal principal = (PKIPrincipal) servletRequest.getUserPrincipal();
+ if ((principal != null) &&
+ (principal.hasRole("Certificate Manager Agents") ||
+ principal.hasRole("Certificate Manager Administrators"))) {
+ visibleOnly = false;
+ }
+
+ Enumeration<String> profileIds = ps.getProfileIds();
+
+ IProfile profile = null;
+ if (profileIds != null) {
+ while (profileIds.hasMoreElements()) {
+ String id = profileIds.nextElement();
+
+ if (id.equals(profileId)) {
+
+ try {
+ profile = ps.getProfile(profileId);
+ } catch (EProfileException e) {
+ e.printStackTrace();
+ throw new ProfileNotFoundException(profileId);
+ }
+ break;
+ }
+ }
+ }
+
+ if (profile == null) {
+ throw new ProfileNotFoundException(profileId);
+ }
+
+ if (visibleOnly && !profile.isVisible()) {
+ throw new ProfileNotFoundException(profileId);
+ }
+
+ try {
+ data = createProfileData(profileId);
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ throw new ProfileNotFoundException(profileId);
+ }
+
+ UriBuilder profileBuilder = uriInfo.getBaseUriBuilder();
+ URI uri = profileBuilder.path(ProfileResource.class).path("{id}").
+ build(profileId);
+ data.setLink(new Link("self", uri));
+
+ return data;
+ }
+
+ public ProfileData createProfileData(String profileId) throws EBaseException {
+
+ IProfile profile;
+
+ try {
+ profile = ps.getProfile(profileId);
+ } catch (EProfileException e) {
+ e.printStackTrace();
+ throw new ProfileNotFoundException(profileId);
+ }
+
+ ProfileData data = new ProfileData();
+
+ data.setAuthenticatorId(profile.getAuthenticatorId());
+ data.setAuthzAcl(profile.getAuthzAcl());
+ data.setClassId(cs.getString(profileId + ".class_id"));
+ data.setDescription(profile.getDescription(getLocale(headers)));
+ data.setEnabled(ps.isProfileEnable(profileId));
+ data.setEnabledBy(ps.getProfileEnableBy(profileId));
+ data.setId(profileId);
+ data.setName(profile.getName(getLocale(headers)));
+ data.setRenewal(Boolean.getBoolean(profile.isRenewal()));
+ data.setVisible(profile.isVisible());
+ data.setXMLOutput(Boolean.getBoolean(profile.isXmlOutput()));
+
+ Enumeration<String> inputIds = profile.getProfileInputIds();
+ if (inputIds != null) {
+ while (inputIds.hasMoreElements()) {
+ ProfileInput input = createProfileInput(profile, inputIds.nextElement(), getLocale(headers));
+ if (input == null)
+ continue;
+ data.addProfileInput(input);
+ }
+ }
+
+ // profile outputs
+ Enumeration<String> outputIds = profile.getProfileOutputIds();
+ if (outputIds != null) {
+ while (outputIds.hasMoreElements()) {
+ ProfileOutput output = createProfileOutput(profile, outputIds.nextElement(), getLocale(headers));
+ if (output == null)
+ continue;
+ data.addProfileOutput(output);
+ }
+ }
+
+ // profile policies
+ Enumeration<String> policySetIds = profile.getProfilePolicySetIds();
+ if (policySetIds != null) {
+ while (policySetIds.hasMoreElements()) {
+ Vector<ProfilePolicy> pset = new Vector<ProfilePolicy>();
+ String policySetId = policySetIds.nextElement();
+ Enumeration<String> policyIds = profile.getProfilePolicyIds(policySetId);
+ while (policyIds.hasMoreElements()) {
+ String policyId = policyIds.nextElement();
+ pset.add(createProfilePolicy(profile, policySetId, policyId));
+ }
+
+ if (!pset.isEmpty()) {
+ data.addProfilePolicySet(policySetId, pset);
+ }
+ }
+ }
+
+ UriBuilder profileBuilder = uriInfo.getBaseUriBuilder();
+ URI uri = profileBuilder.path(ProfileResource.class).path("{id}").
+ build(profileId);
+ data.setLink(new Link("self", uri));
+
+ return data;
+ }
+
+ public ProfilePolicy createProfilePolicy(IProfile profile, String setId, String policyId) throws EBaseException {
+ IProfilePolicy policy = profile.getProfilePolicy(setId, policyId);
+ IConfigStore policyStore = profile.getConfigStore().getSubStore(
+ "policyset." + setId + "." + policy.getId());
+
+ ProfilePolicy p = new ProfilePolicy();
+ String constraintClassId = policyStore.getString("constraint.class_id");
+ p.setConstraint(PolicyConstraintFactory.create(getLocale(headers), policy.getConstraint(), constraintClassId));
+ String defaultClassId = policyStore.getString("default.class_id");
+ p.setDef(PolicyDefaultFactory.create(getLocale(headers), policy.getDefault(), defaultClassId));
+ p.setId(policy.getId());
+ return p;
+ }
+
+ public static ProfileInput createProfileInput(IProfile profile, String inputId, Locale locale) throws EBaseException {
+ IProfileInput profileInput = profile.getProfileInput(inputId);
+ if (profileInput == null)
+ return null;
+
+ IConfigStore inputStore = profile.getConfigStore().getSubStore("input");
+ String classId = inputStore.getString(inputId + ".class_id");
+
+ return new ProfileInput(profileInput, inputId, classId, locale);
+ }
+
+ public static ProfileOutput createProfileOutput(IProfile profile, String outputId, Locale locale) throws EBaseException {
+ IProfileOutput profileOutput = profile.getProfileOutput(outputId);
+ if (profileOutput == null)
+ return null;
+
+ IConfigStore outputStore = profile.getConfigStore().getSubStore("output");
+ String classId = outputStore.getString(outputId + ".class_id");
+
+ return new ProfileOutput(profileOutput, outputId, classId, locale);
+ }
+
+ public static ProfileDataInfo createProfileDataInfo(String profileId, boolean visibleOnly, UriInfo uriInfo,
+ Locale locale) throws EBaseException {
+
+ IProfileSubsystem ps = (IProfileSubsystem) CMS.getSubsystem(IProfileSubsystem.ID);
+ if (profileId == null) {
+ throw new EBaseException("Error creating ProfileDataInfo.");
+ }
+ ProfileDataInfo ret = null;
+
+ IProfile profile = null;
+
+ profile = ps.getProfile(profileId);
+ if (profile == null) {
+ return null;
+ }
+
+ if (visibleOnly && !profile.isVisible()) {
+ return null;
+ }
+
+ ret = new ProfileDataInfo();
+
+ ret.setProfileId(profileId);
+ ret.setProfileName(profile.getName(locale));
+ ret.setProfileDescription(profile.getDescription(locale));
+
+ UriBuilder profileBuilder = uriInfo.getBaseUriBuilder();
+ URI uri = profileBuilder.path(ProfileResource.class).path("{id}").
+ build(profileId);
+
+ ret.setProfileURL(uri.toString());
+
+ return ret;
+ }
+
+ public void modifyProfileState(String profileId, String action) {
+ if (ps == null) {
+ CMS.debug("modifyProfileState: ps is null");
+ throw new PKIException("Error modifying profile state. Profile Service not available");
+ }
+
+ if (profileId == null) {
+ CMS.debug("modifyProfileState: invalid request. profileId is null");
+ throw new BadRequestException("Invalid ProfileId");
+ }
+
+ Principal principal = servletRequest.getUserPrincipal();
+
+ switch (action) {
+ case "enable":
+ if (ps.isProfileEnable(profileId)) {
+ throw new BadRequestException("Profile already enabled");
+ }
+ try {
+ ps.enableProfile(profileId, principal.getName());
+ auditProfileChangeState(profileId, "approve", ILogger.SUCCESS);
+ } catch (EProfileException e) {
+ CMS.debug("modifyProfileState: error enabling profile. " + e);
+ e.printStackTrace();
+ auditProfileChangeState(profileId, "approve", ILogger.FAILURE);
+ throw new PKIException("Error enabling profile");
+ }
+ break;
+ case "disable":
+ if (!ps.isProfileEnable(profileId)) {
+ throw new BadRequestException("Profile already disabled");
+ }
+ String userid = principal.getName();
+ try {
+ if (ps.checkOwner()) {
+ if (ps.getProfileEnableBy(profileId).equals(userid)) {
+ ps.disableProfile(profileId);
+ auditProfileChangeState(profileId, "disapprove", ILogger.SUCCESS);
+ } else {
+ auditProfileChangeState(profileId, "disapprove", ILogger.FAILURE);
+ throw new UnauthorizedException(
+ "Profile can only be disabled by the agent that enabled it");
+ }
+ } else {
+ ps.disableProfile(profileId);
+ auditProfileChangeState(profileId, "disapprove", ILogger.SUCCESS);
+ }
+ } catch (EProfileException e) {
+ CMS.debug("modifyProfileState: Error disabling profile: " + e);
+ e.printStackTrace();
+ auditProfileChangeState(profileId, "disapprove", ILogger.FAILURE);
+ throw new PKIException("Error disabling profile");
+ }
+ break;
+ default:
+ auditProfileChangeState(profileId, "invalid", ILogger.FAILURE);
+ throw new BadRequestException("Invalid operation");
+ }
+ }
+
+ public void createProfile(ProfileData data) {
+ if (ps == null) {
+ CMS.debug("createProfile: ps is null");
+ throw new PKIException("Error creating profile. Profile Service not available");
+ }
+
+ IProfile profile = null;
+ String profileId = data.getId();
+ Map<String, String> auditParams = new LinkedHashMap<String, String>();
+ try {
+ profile = ps.getProfile(profileId);
+ if (profile != null) {
+ throw new BadRequestException("Profile already exists");
+ }
+
+ auditParams.put("class_id", data.getClassId());
+ auditParams.put("name", data.getName());
+ auditParams.put("description", data.getDescription());
+ auditParams.put("visible", Boolean.toString(data.isVisible()));
+
+ String config = CMS.getConfigStore().getString("instanceRoot") + "/ca/profiles/ca/" +
+ profileId + ".cfg";
+ File configFile = new File(config);
+ configFile.createNewFile();
+ IPluginInfo info = registry.getPluginInfo("profile", data.getClassId());
+
+ profile = ps.createProfile(profileId, data.getClassId(), info.getClassName(), config);
+ profile.setName(getLocale(headers), data.getName());
+ profile.setDescription(getLocale(headers), data.getDescription());
+ profile.setVisible(data.isVisible());
+ profile.getConfigStore().commit(false);
+ ps.createProfileConfig(profileId, data.getClassId(), config);
+
+ if (profile instanceof IProfileEx) {
+ // populates profile specific plugins such as
+ // policies, inputs and outputs with defaults
+ ((IProfileEx) profile).populate();
+ }
+
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_RULES,
+ OpDef.OP_ADD,
+ profileId,
+ ILogger.SUCCESS,
+ auditParams);
+ } catch (EBaseException | IOException e) {
+ CMS.debug("createProfile: error in creating profile: " + e);
+ e.printStackTrace();
+
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_RULES,
+ OpDef.OP_ADD,
+ profileId,
+ ILogger.FAILURE,
+ auditParams);
+
+ throw new PKIException("Error in creating profile");
+ }
+
+ changeProfileData(data, profile);
+ }
+
+ public void modifyProfile(String profileId, ProfileData data) {
+ if (ps == null) {
+ CMS.debug("modifyProfile: ps is null");
+ throw new PKIException("Error modifying profile. Profile Service not available");
+ }
+
+ IProfile profile = null;
+ try {
+ profile = ps.getProfile(profileId);
+ if (profile == null) {
+ throw new ProfileNotFoundException("Cannot modify profile `" + profileId +
+ "`. Profile not found");
+ }
+ } catch (EBaseException e) {
+ CMS.debug("modifyProfile: error obtaining profile `" + profileId + "`: " + e);
+ e.printStackTrace();
+ throw new PKIException("Error modifying profile. Cannot obtain profile.");
+ }
+
+ changeProfileData(data, profile);
+ }
+
+ private void changeProfileData(ProfileData data, IProfile profile) {
+ String profileId = data.getId();
+ if (profile == null) {
+ CMS.debug("changeProfileData - profile is null");
+ throw new PKIException("Error changing profile data. Profile not available.");
+ }
+ if (ps.isProfileEnable(profileId)) {
+ throw new BadRequestException("Cannot change profile data. Profile must be disabled");
+ }
+
+ Map<String, String> auditParams = new LinkedHashMap<String, String>();
+
+ if (differs(profile.getAuthenticatorId(), data.getAuthenticatorId())) {
+ profile.setAuthenticatorId(data.getAuthenticatorId());
+ auditParams.put("authenticatorId", data.getAuthenticatorId());
+ }
+
+ if (differs(profile.getAuthzAcl(), data.getAuthzAcl())) {
+ profile.setAuthzAcl(data.getAuthzAcl());
+ auditParams.put("authzAcl", data.getAuthzAcl());
+ }
+
+ if (differs(profile.getDescription(getLocale(headers)), data.getDescription())) {
+ profile.setDescription(getLocale(headers), data.getDescription());
+ auditParams.put("description", data.getDescription());
+ }
+
+ if (differs(profile.getId(), data.getId())) {
+ profile.setId(data.getId());
+ auditParams.put("id", data.getId());
+ }
+
+ if (differs(profile.getName(getLocale(headers)), data.getName())) {
+ profile.setName(getLocale(headers), data.getName());
+ auditParams.put("name", data.getName());
+ }
+
+ // TODO renewal is a string in Profile, should be changed
+ if (differs(profile.isRenewal(), Boolean.toString(data.isRenewal()))) {
+ profile.setRenewal(data.isRenewal());
+ auditParams.put("renewal", Boolean.toString(data.isRenewal()));
+ }
+
+ if (!profile.isVisible() == data.isVisible()) {
+ profile.setVisible(data.isVisible());
+ auditParams.put("visible", Boolean.toString(data.isVisible()));
+ }
+
+ // TODO xmloutput is a string in Profile, should be changed
+ if (differs(profile.isXmlOutput(), Boolean.toString(data.isXMLOutput()))) {
+ profile.setXMLOutput(data.isXMLOutput());
+ auditParams.put("xmloutput", Boolean.toString(data.isXMLOutput()));
+ }
+
+ if (!auditParams.isEmpty()) {
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_RULES,
+ OpDef.OP_MODIFY,
+ profileId,
+ ILogger.SUCCESS,
+ auditParams);
+ }
+
+ try {
+ populateProfileInputs(data, profile);
+ populateProfileOutputs(data, profile);
+ populateProfilePolicies(data, profile);
+ profile.getConfigStore().commit(false);
+ } catch (EBaseException e) {
+ CMS.debug("changeProfileData: Error changing profile inputs/outputs/policies: " + e);
+ e.printStackTrace();
+ throw new PKIException("Error changing profile data");
+ }
+ }
+
+ private boolean differs(String v1, String v2) {
+ if (v1 != null) {
+ if (!v1.equals(v2)) {
+ return true;
+ }
+ } else {
+ if (v2 != null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void populateProfilePolicies(ProfileData data, IProfile profile) throws EBaseException {
+ // get list of changes for auditing
+ List<String> auditAdd = new ArrayList<String>();
+ List<String> auditModify = new ArrayList<String>();
+
+ Enumeration<String> existingSetIds = profile.getProfilePolicySetIds();
+ Map<String, ProfilePolicy> existingPolicies = new LinkedHashMap<String, ProfilePolicy>();
+ while (existingSetIds.hasMoreElements()) {
+ String setId = existingSetIds.nextElement();
+ Enumeration<String> policyIds = profile.getProfilePolicyIds(setId);
+ while (policyIds.hasMoreElements()) {
+ String policyId = policyIds.nextElement();
+ existingPolicies.put(
+ setId + ":" + policyId,
+ createProfilePolicy(profile, setId, policyId));
+ }
+ }
+
+ for (Map.Entry<String, List<ProfilePolicy>> policySet : data.getPolicySets().entrySet()) {
+ String setId = policySet.getKey();
+ for (ProfilePolicy policy : policySet.getValue()) {
+ String id = setId + ":" + policy.getId();
+ if (!existingPolicies.containsKey(id)) {
+ auditAdd.add(id);
+ } else {
+ if (!policy.equals(existingPolicies.get(id))) {
+ auditModify.add(id);
+ }
+ }
+ existingPolicies.remove(id);
+ }
+ }
+
+ List<String> auditDelete = new ArrayList<String>(existingPolicies.keySet());
+
+ //perform actions
+ try {
+ profile.deleteAllProfilePolicies();
+ for (Map.Entry<String, List<ProfilePolicy>> policySet : data.getPolicySets().entrySet()) {
+ String setId = policySet.getKey();
+ for (ProfilePolicy policy : policySet.getValue()) {
+ PolicyDefault def = policy.getDef();
+ PolicyConstraint con = policy.getConstraint();
+
+ // create policy using defaults for PolicyDefault and PolicyConstraint
+ IProfilePolicy p = profile.createProfilePolicy(setId, policy.getId(),
+ def.getClassId(), con.getClassId());
+
+ // change specific elements to match incoming data for PolicyDefault
+ IConfigStore pstore = profile.getConfigStore().getSubStore(
+ "policyset." + setId + "." + policy.getId());
+ if (!def.getName().isEmpty()) {
+ pstore.putString("default.name", def.getName());
+ }
+ /*if (!def.getText().isEmpty()) {
+ pstore.putString("default.description", def.getText());
+ }*/
+ for (ProfileParameter param : def.getParams()) {
+ if (!param.getValue().isEmpty()) {
+ p.getDefault().setConfig(param.getName(), param.getValue());
+ }
+ }
+
+ // change specific elements to match incoming data for PolicyConstraint
+ if (!con.getName().isEmpty()) {
+ pstore.putString("constraint.name", con.getName());
+ }
+ /*if (!con.getText().isEmpty()) {
+ pstore.putString("constraint.description", con.getText());
+ }*/
+ for (PolicyConstraintValue pcv : con.getConstraints()) {
+ if (!pcv.getValue().isEmpty()) {
+ p.getConstraint().setConfig(pcv.getName(), pcv.getValue());
+ }
+ }
+ }
+ }
+
+ if (!auditDelete.isEmpty()) {
+ Map<String, String> auditParams = new LinkedHashMap<String, String>();
+ auditParams.put("inputs", StringUtils.join(auditDelete, ","));
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_POLICIES,
+ OpDef.OP_DELETE,
+ profile.getId(),
+ ILogger.SUCCESS,
+ auditParams);
+ }
+
+ if (!auditAdd.isEmpty()) {
+ Map<String, String> auditParams = new LinkedHashMap<String, String>();
+ auditParams.put("inputs", StringUtils.join(auditAdd, ","));
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_POLICIES,
+ OpDef.OP_ADD,
+ profile.getId(),
+ ILogger.SUCCESS,
+ auditParams);
+ }
+
+ if (!auditModify.isEmpty()) {
+ Map<String, String> auditParams = new LinkedHashMap<String, String>();
+ auditParams.put("inputs", StringUtils.join(auditModify, ","));
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_POLICIES,
+ OpDef.OP_MODIFY,
+ profile.getId(),
+ ILogger.SUCCESS,
+ auditParams);
+ }
+ } catch (EProfileException | EPropertyException e) {
+ Map<String, String> auditParams = new LinkedHashMap<String, String>();
+ auditParams.put("added", StringUtils.join(auditAdd, ","));
+ auditParams.put("deleted", StringUtils.join(auditDelete, ","));
+ auditParams.put("modified", StringUtils.join(auditModify, ","));
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_POLICIES,
+ OpDef.OP_MODIFY,
+ profile.getId(),
+ ILogger.FAILURE,
+ auditParams);
+ throw e;
+ }
+ }
+
+ private void populateProfileOutputs(ProfileData data, IProfile profile) throws EBaseException {
+ // get list of changes for auditing
+ List<String> auditAdd = new ArrayList<String>();
+ List<String> auditModify = new ArrayList<String>();
+
+ Enumeration<String> existingIds = profile.getProfileOutputIds();
+ Map<String, ProfileOutput> existingOutputs = new LinkedHashMap<String, ProfileOutput>();
+ while (existingIds.hasMoreElements()) {
+ String id = existingIds.nextElement();
+ ProfileOutput output = createProfileOutput(profile, id, getLocale(headers));
+ if (output == null)
+ continue;
+ existingOutputs.put(id, output);
+ }
+
+ List<ProfileOutput> outputs = data.getOutputs();
+ for (ProfileOutput output : outputs) {
+ String id = output.getId();
+ if (!existingOutputs.containsKey(id)) {
+ auditAdd.add(id);
+ } else {
+ if (!output.equals(existingOutputs.get(id))) {
+ auditModify.add(id);
+ }
+ existingOutputs.remove(id);
+ }
+ }
+ List<String> auditDelete = new ArrayList<String>(existingOutputs.keySet());
+
+ // perform operations
+
+ try {
+ profile.deleteAllProfileOutputs();
+ for (ProfileOutput output : outputs) {
+ String id = output.getId();
+ String classId = output.getClassId();
+
+ NameValuePairs nvp = new NameValuePairs();
+ // TODO - add a field for params in ProfileOuput
+ // No current examples
+ profile.createProfileOutput(id, classId, nvp);
+ }
+
+ if (!auditDelete.isEmpty()) {
+ Map<String, String> auditParams = new LinkedHashMap<String, String>();
+ auditParams.put("outputs", StringUtils.join(auditDelete, ","));
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_OUTPUT,
+ OpDef.OP_DELETE,
+ profile.getId(),
+ ILogger.SUCCESS,
+ auditParams);
+ }
+
+ if (!auditAdd.isEmpty()) {
+ Map<String, String> auditParams = new LinkedHashMap<String, String>();
+ auditParams.put("outputs", StringUtils.join(auditAdd, ","));
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_OUTPUT,
+ OpDef.OP_ADD,
+ profile.getId(),
+ ILogger.SUCCESS,
+ auditParams);
+ }
+
+ if (!auditModify.isEmpty()) {
+ Map<String, String> auditParams = new LinkedHashMap<String, String>();
+ auditParams.put("outputs", StringUtils.join(auditModify, ","));
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_OUTPUT,
+ OpDef.OP_MODIFY,
+ profile.getId(),
+ ILogger.SUCCESS,
+ auditParams);
+ }
+ } catch (EProfileException e) {
+ Map<String, String> auditParams = new LinkedHashMap<String, String>();
+
+ auditParams.put("added", StringUtils.join(auditAdd, ","));
+ auditParams.put("deleted", StringUtils.join(auditDelete, ","));
+ auditParams.put("modified", StringUtils.join(auditModify, ","));
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_OUTPUT,
+ OpDef.OP_MODIFY,
+ profile.getId(),
+ ILogger.FAILURE,
+ auditParams);
+ throw e;
+ }
+ }
+
+ private void populateProfileInputs(ProfileData data, IProfile profile) throws EBaseException {
+ // get list of changes for auditing
+ List<String> auditAdd = new ArrayList<String>();
+ List<String> auditModify = new ArrayList<String>();
+ Enumeration<String> existingIds = profile.getProfileInputIds();
+ Map<String, ProfileInput> existingInputs = new LinkedHashMap<String, ProfileInput>();
+
+ while (existingIds.hasMoreElements()) {
+ String id = existingIds.nextElement();
+ ProfileInput input = createProfileInput(profile, id, getLocale(headers));
+ if (input == null)
+ continue;
+ existingInputs.put(id, input);
+ }
+
+ List<ProfileInput> inputs = data.getInputs();
+ for (ProfileInput input : inputs) {
+ String id = input.getId();
+ if (!existingInputs.containsKey(id)) {
+ auditAdd.add(id);
+ } else {
+ if (!input.equals(existingInputs.get(id))) {
+ auditModify.add(id);
+ }
+ existingInputs.remove(id);
+ }
+ }
+ List<String> auditDelete = new ArrayList<String>(existingInputs.keySet());
+
+ try {
+ // perform the operations
+ profile.deleteAllProfileInputs();
+
+ for (ProfileInput input : inputs) {
+ String id = input.getId();
+ String classId = input.getClassId();
+
+ NameValuePairs nvp = new NameValuePairs();
+ // TODO - add a field for params in ProfileInput.
+ // an example of this is DomainController.cfg
+ profile.createProfileInput(id, classId, nvp);
+ }
+
+ if (!auditDelete.isEmpty()) {
+ Map<String, String> auditParams = new LinkedHashMap<String, String>();
+ auditParams.put("inputs", StringUtils.join(auditDelete, ","));
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_INPUT,
+ OpDef.OP_DELETE,
+ profile.getId(),
+ ILogger.SUCCESS,
+ auditParams);
+ }
+
+ if (!auditAdd.isEmpty()) {
+ Map<String, String> auditParams = new LinkedHashMap<String, String>();
+ auditParams.put("inputs", StringUtils.join(auditAdd, ","));
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_INPUT,
+ OpDef.OP_ADD,
+ profile.getId(),
+ ILogger.SUCCESS,
+ auditParams);
+ }
+
+ if (!auditModify.isEmpty()) {
+ Map<String, String> auditParams = new LinkedHashMap<String, String>();
+ auditParams.put("inputs", StringUtils.join(auditModify, ","));
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_INPUT,
+ OpDef.OP_MODIFY,
+ profile.getId(),
+ ILogger.SUCCESS,
+ auditParams);
+ }
+ } catch (EProfileException e) {
+ Map<String, String> auditParams = new LinkedHashMap<String, String>();
+
+ auditParams.put("added", StringUtils.join(auditAdd, ","));
+ auditParams.put("deleted", StringUtils.join(auditDelete, ","));
+ auditParams.put("modified", StringUtils.join(auditModify, ","));
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_INPUT,
+ OpDef.OP_MODIFY,
+ profile.getId(),
+ ILogger.FAILURE,
+ auditParams);
+ throw e;
+ }
+ }
+
+ public void deleteProfile(@PathParam("id") String profileId) {
+ if (ps == null) {
+ CMS.debug("deleteProfile: ps is null");
+ throw new PKIException("Error deleting profile. Profile Service not available");
+ }
+
+ try {
+ IProfile profile = ps.getProfile(profileId);
+ if (profile == null) {
+ CMS.debug("Trying to delete profile: " + profileId + ". Profile already deleted.");
+ return;
+ }
+
+ if (ps.isProfileEnable(profileId)) {
+ CMS.debug("Delete profile not permitted. Profile must be disabled first.");
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_RULES,
+ OpDef.OP_DELETE,
+ profileId,
+ ILogger.FAILURE,
+ null);
+
+ throw new BadRequestException("Cannot delete profile `" + profileId +
+ "`. Profile must be disabled first.");
+ }
+
+ String configFile = CMS.getConfigStore().getString("profile." + profileId + ".config");
+
+ ps.deleteProfile(profileId, configFile);
+
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_RULES,
+ OpDef.OP_DELETE,
+ profileId,
+ ILogger.FAILURE,
+ null);
+ } catch (EBaseException e) {
+ CMS.debug("deleteProfile: error in deleting profile `" + profileId + "`: " + e);
+ e.printStackTrace();
+
+ auditProfileChange(
+ ScopeDef.SC_PROFILE_RULES,
+ OpDef.OP_DELETE,
+ profileId,
+ ILogger.FAILURE,
+ null);
+
+ throw new PKIException("Error deleting profile.");
+ }
+ }
+
+ public void auditProfileChangeState(String profileId, String op, String status) {
+ String msg = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL,
+ auditor.getSubjectID(),
+ status,
+ profileId,
+ op);
+ auditor.log(msg);
+ }
+
+ public void auditProfileChange(String scope, String type, String id, String status, Map<String, String> params) {
+ String msg = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditor.getSubjectID(),
+ status,
+ auditor.getParamString(scope, type, id, params));
+ auditor.log(msg);
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileServlet.java
new file mode 100644
index 000000000..be331d6ef
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileServlet.java
@@ -0,0 +1,578 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.profile;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authorization.IAuthzSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.template.ArgList;
+import com.netscape.certsrv.template.ArgSet;
+import com.netscape.certsrv.template.ArgString;
+import com.netscape.certsrv.template.IArgValue;
+import com.netscape.certsrv.util.IStatsSubsystem;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.base.UserInfo;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.ServletUtils;
+
+/**
+ * This servlet is the base class of all profile servlets.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ProfileServlet extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7011378748671762375L;
+ public final static String ARG_ERROR_CODE = "errorCode";
+ public final static String ARG_ERROR_REASON = "errorReason";
+ public final static String ARG_RECORD = "record";
+ public final static String ARG_OP = "op";
+
+ public final static String ARG_REQUEST_LIST = "requestList";
+ public final static String ARG_REQUEST_ID = "requestId";
+ public final static String ARG_REQUEST_TYPE = "requestType";
+ public final static String ARG_REQUEST_STATUS = "requestStatus";
+ public final static String ARG_REQUEST_OWNER =
+ "requestOwner";
+ public final static String ARG_REQUEST_CREATION_TIME =
+ "requestCreationTime";
+ public final static String ARG_REQUEST_MODIFICATION_TIME =
+ "requestModificationTime";
+ public final static String ARG_REQUEST_NONCE = "nonce";
+
+ public final static String ARG_AUTH_ID = "authId";
+ public final static String ARG_AUTH_SYNTAX = "authSyntax";
+ public final static String ARG_AUTH_CONSTRAINT = "authConstraint";
+ public final static String ARG_AUTH_NAME = "authName";
+ public final static String ARG_AUTH_LIST = "authList";
+ public final static String ARG_AUTH_DESC = "authDesc";
+ public final static String ARG_AUTH_IS_SSL = "authIsSSLClientRequired";
+ public final static String ARG_PROFILE = "profile";
+ public final static String ARG_REQUEST_NOTES = "requestNotes";
+ public final static String ARG_PROFILE_ID = "profileId";
+ public final static String ARG_RENEWAL_PROFILE_ID = "rprofileId";
+ public final static String ARG_PROFILE_IS_ENABLED = "profileIsEnable";
+ public final static String ARG_PROFILE_IS_VISIBLE = "profileIsVisible";
+ public final static String ARG_PROFILE_ENABLED_BY = "profileEnableBy";
+ public final static String ARG_PROFILE_APPROVED_BY = "profileApprovedBy";
+ public final static String ARG_PROFILE_NAME = "profileName";
+ public final static String ARG_PROFILE_DESC = "profileDesc";
+ public final static String ARG_PROFILE_REMOTE_HOST = "profileRemoteHost";
+ public final static String ARG_PROFILE_REMOTE_ADDR = "profileRemoteAddr";
+ public final static String ARG_DEF_ID = "defId";
+ public final static String ARG_DEF_SYNTAX = "defSyntax";
+ public final static String ARG_DEF_CONSTRAINT = "defConstraint";
+ public final static String ARG_DEF_NAME = "defName";
+ public final static String ARG_DEF_VAL = "defVal";
+ public final static String ARG_DEF_DESC = "defDesc";
+ public final static String ARG_DEF_LIST = "defList";
+ public final static String ARG_CON_DESC = "conDesc";
+ public final static String ARG_CON_LIST = "constraint";
+ public final static String ARG_CON_NAME = "name";
+ public final static String ARG_CON_VALUE = "value";
+ public final static String ARG_PROFILE_SET_ID = "profileSetId";
+ public final static String ARG_POLICY_SET_ID = "setId";
+ public final static String ARG_POLICY = "policy";
+ public final static String ARG_POLICY_ID = "policyId";
+ public final static String ARG_POLICY_SET_LIST = "policySetList";
+ public final static String ARG_INPUT_PLUGIN_LIST = "inputPluginList";
+ public final static String ARG_INPUT_PLUGIN_ID = "inputPluginId";
+ public final static String ARG_INPUT_PLUGIN_NAME = "inputPluginName";
+ public final static String ARG_INPUT_PLUGIN_DESC = "inputPluginDesc";
+ public final static String ARG_INPUT_LIST = "inputList";
+ public final static String ARG_INPUT_ID = "inputId";
+ public final static String ARG_INPUT_SYNTAX = "inputSyntax";
+ public final static String ARG_INPUT_CONSTRAINT = "inputConstraint";
+ public final static String ARG_INPUT_NAME = "inputName";
+ public final static String ARG_INPUT_VAL = "inputVal";
+ public final static String ARG_IS_RENEWAL = "renewal";
+ public final static String ARG_XML_OUTPUT = "xmlOutput";
+ public final static String ARG_OUTPUT_LIST = "outputList";
+ public final static String ARG_OUTPUT_ID = "outputId";
+ public final static String ARG_OUTPUT_SYNTAX = "outputSyntax";
+ public final static String ARG_OUTPUT_CONSTRAINT = "outputConstraint";
+ public final static String ARG_OUTPUT_NAME = "outputName";
+ public final static String ARG_OUTPUT_VAL = "outputVal";
+
+ private static final String PROP_TEMPLATE = "templatePath";
+ private final static String PROP_AUTHMGR = "AuthMgr";
+ private final static String PROP_CLIENTAUTH = "GetClientCert";
+ private static final String PROP_PROFILE_SUB_ID = "profileSubId";
+ private static final String PROP_ID = "ID";
+ public final static String PROP_RESOURCEID = "resourceID";
+ public final static String AUTHZ_SRC_LDAP = "ldap";
+ public final static String AUTHZ_SRC_TYPE = "sourceType";
+ public final static String AUTHZ_CONFIG_STORE = "authz";
+ public final static String AUTHZ_SRC_XML = "web.xml";
+ public final static String PROP_AUTHZ_MGR = "AuthzMgr";
+ public final static String PROP_ACL = "ACLinfo";
+ public final static String AUTHZ_MGR_BASIC = "BasicAclAuthz";
+ public final static String AUTHZ_MGR_LDAP = "DirAclAuthz";
+
+ private final static String HDR_LANG = "accept-language";
+
+ private String mTemplate = null;
+
+ protected String mId = null;
+ protected String mGetClientCert = "false";
+ protected String mAuthMgr = null;
+ protected IAuthzSubsystem mAuthz = null;
+ protected String mAclMethod = null;
+ protected String mAuthzResourceName = null;
+ protected ILogger mLogger = CMS.getLogger();
+ protected int mLogCategory = ILogger.S_OTHER;
+ protected String mProfileSubId = null;
+
+ protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+
+ // stats
+ protected LinkedHashSet<String> statEvents = new LinkedHashSet<String>();
+
+ public ProfileServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. Servlets implementing this method
+ * must specify the template to use as a parameter called
+ * "templatePath" in the servletConfig
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mTemplate = sc.getServletContext().getRealPath(
+ sc.getInitParameter(PROP_TEMPLATE));
+ mGetClientCert = sc.getInitParameter(PROP_CLIENTAUTH);
+ mAuthMgr = sc.getInitParameter(PROP_AUTHMGR);
+ mAuthz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ);
+ mAuthzResourceName = sc.getInitParameter(PROP_RESOURCEID);
+ mProfileSubId = sc.getInitParameter(PROP_PROFILE_SUB_ID);
+ mId = sc.getInitParameter(PROP_ID);
+
+ try {
+ mAclMethod = ServletUtils.initializeAuthz(sc, mAuthz, mId);
+ } catch (ServletException e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ throw e;
+ }
+ }
+
+ protected String escapeXML(String v) {
+ if (v == null) {
+ return "";
+ }
+ v = v.replaceAll("&", "&amp;");
+ return v;
+ }
+
+ protected void outputArgValueAsXML(PrintStream ps, String name, IArgValue v) {
+ ps.println("<" + name + ">");
+ if (v != null) {
+ if (v instanceof ArgList) {
+ ArgList list = (ArgList) v;
+ ps.println("<list>");
+ for (int i = 0; i < list.size(); i++) {
+ outputArgValueAsXML(ps, name, list.get(i));
+ }
+ ps.println("</list>");
+ } else if (v instanceof ArgString) {
+ ArgString str = (ArgString) v;
+ ps.println(escapeXML(str.getValue()));
+ } else if (v instanceof ArgSet) {
+ ArgSet set = (ArgSet) v;
+ ps.println("<set>");
+ Enumeration<String> names = set.getNames();
+ while (names.hasMoreElements()) {
+ String n = names.nextElement();
+ outputArgValueAsXML(ps, n, set.get(n));
+ }
+ ps.println("</set>");
+ } else {
+ ps.println(v);
+ }
+ }
+ ps.println("</" + name + ">");
+ }
+
+ protected void outputThisAsXML(ByteArrayOutputStream bos, ArgSet args) {
+ PrintStream ps = new PrintStream(bos);
+ ps.println("<xml>");
+ outputArgValueAsXML(ps, "output", args);
+ ps.println("</xml>");
+ ps.flush();
+ }
+
+ public void outputTemplate(HttpServletRequest request,
+ HttpServletResponse response, ArgSet args)
+ throws EBaseException {
+
+ String xmlOutput = request.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ response.setContentType("text/xml");
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ outputThisAsXML(bos, args);
+ try {
+ response.setContentLength(bos.size());
+ bos.writeTo(response.getOutputStream());
+ } catch (Exception e) {
+ CMS.debug("outputTemplate error " + e);
+ }
+ return;
+ }
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ statsSub.startTiming("output_template");
+ }
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(
+ new FileReader(mTemplate));
+
+ response.setContentType("text/html; charset=UTF-8");
+
+ PrintWriter writer = response.getWriter();
+
+ // output template
+ String line = null;
+
+ do {
+ line = reader.readLine();
+ if (line != null) {
+ if (line.indexOf("<CMS_TEMPLATE>") == -1) {
+ writer.println(line);
+ } else {
+ // output javascript parameters
+ writer.println("<script type=\"text/javascript\">");
+ outputData(writer, args);
+ writer.println("</script>");
+ }
+ }
+ } while (line != null);
+ reader.close();
+ } catch (IOException e) {
+ CMS.debug(e);
+ throw new EBaseException(e.toString());
+ } finally {
+ if (statsSub != null) {
+ statsSub.endTiming("output_template");
+ }
+ }
+ }
+
+ public void outputTemplate(boolean isXML, HttpServletResponse response, ArgSet args)
+ throws EBaseException {
+ if (isXML) {
+ response.setContentType("text/xml");
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ outputThisAsXML(bos, args);
+ try {
+ response.setContentLength(bos.size());
+ bos.writeTo(response.getOutputStream());
+ } catch (Exception e) {
+ CMS.debug("outputTemplate error " + e);
+ }
+ return;
+ }
+ startTiming("output_template");
+
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(mTemplate));
+
+ response.setContentType("text/html; charset=UTF-8");
+
+ PrintWriter writer = response.getWriter();
+
+ // output template
+ String line = null;
+
+ do {
+ line = reader.readLine();
+ if (line != null) {
+ if (line.indexOf("<CMS_TEMPLATE>") == -1) {
+ writer.println(line);
+ } else {
+ // output javascript parameters
+ writer.println("<script type=\"text/javascript\">");
+ outputData(writer, args);
+ writer.println("</script>");
+ }
+ }
+ } while (line != null);
+ reader.close();
+ } catch (IOException e) {
+ CMS.debug(e);
+ throw new EBaseException(e.toString());
+ } finally {
+ endTiming("output_template");
+ }
+ }
+
+ protected void outputArgList(PrintWriter writer, String name, ArgList list)
+ throws IOException {
+
+ String h_name = null;
+
+ if (name.indexOf('.') == -1) {
+ h_name = name;
+ } else {
+ h_name = name.substring(name.indexOf('.') + 1);
+ }
+ writer.println(name + "Set = new Array;");
+ // writer.println(h_name + "Count = 0;");
+
+ for (int i = 0; i < list.size(); i++) {
+ writer.println(h_name + " = new Object;");
+ IArgValue val = list.get(i);
+
+ if (val instanceof ArgString) {
+ ArgString str = (ArgString) val;
+
+ outputArgString(writer, name, str);
+ } else if (val instanceof ArgSet) {
+ ArgSet set = (ArgSet) val;
+
+ outputArgSet(writer, h_name, set);
+ writer.println(name + "Set[" + i + "] = " + h_name + ";");
+ }
+ }
+ }
+
+ public void startTiming(String event) {
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ statsSub.startTiming(event, true);
+ }
+ statEvents.add(event);
+ }
+
+ public void endTiming(String event) {
+ IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ statsSub.endTiming(event);
+ }
+ statEvents.remove(event);
+ }
+
+ protected String escapeJavaScriptString(String v) {
+ int l = v.length();
+ char in[] = new char[l];
+ char out[] = new char[l * 4];
+ int j = 0;
+
+ v.getChars(0, l, in, 0);
+
+ for (int i = 0; i < l; i++) {
+ char c = in[i];
+
+ /* presumably this gives better performance */
+ if ((c > 0x23) && (c != 0x5c) && (c != 0x3c) && (c != 0x3e)) {
+ out[j++] = c;
+ continue;
+ }
+
+ /* some inputs are coming in as '\' and 'n' */
+ /* see BZ 500736 for details */
+ if ((c == 0x5c) && ((i + 1) < l) && (in[i + 1] == 'n' ||
+ in[i + 1] == 'r' || in[i + 1] == 'f' || in[i + 1] == 't' ||
+ in[i + 1] == '<' || in[i + 1] == '>' ||
+ in[i + 1] == '\"' || in[i + 1] == '\'' || in[i + 1] == '\\')) {
+ if (in[i + 1] == 'x' && ((i + 3) < l) && in[i + 2] == '3' &&
+ (in[i + 3] == 'c' || in[i + 3] == 'e')) {
+ out[j++] = '\\';
+ out[j++] = in[i + 1];
+ out[j++] = in[i + 2];
+ out[j++] = in[i + 3];
+ i += 3;
+ } else {
+ out[j++] = '\\';
+ out[j++] = in[i + 1];
+ i++;
+ }
+ continue;
+ }
+
+ switch (c) {
+ case '\n':
+ out[j++] = '\\';
+ out[j++] = 'n';
+ break;
+
+ case '\\':
+ out[j++] = '\\';
+ out[j++] = '\\';
+ break;
+
+ case '\"':
+ out[j++] = '\\';
+ out[j++] = '\"';
+ break;
+
+ case '\r':
+ out[j++] = '\\';
+ out[j++] = 'r';
+ break;
+
+ case '\f':
+ out[j++] = '\\';
+ out[j++] = 'f';
+ break;
+
+ case '\t':
+ out[j++] = '\\';
+ out[j++] = 't';
+ break;
+
+ case '<':
+ out[j++] = '\\';
+ out[j++] = 'x';
+ out[j++] = '3';
+ out[j++] = 'c';
+ break;
+
+ case '>':
+ out[j++] = '\\';
+ out[j++] = 'x';
+ out[j++] = '3';
+ out[j++] = 'e';
+ break;
+
+ default:
+ out[j++] = c;
+ }
+ }
+ return new String(out, 0, j);
+ }
+
+ protected void outputArgString(PrintWriter writer, String name, ArgString str)
+ throws IOException {
+ String s = str.getValue();
+
+ // sub \n with "\n"
+ if (s != null) {
+ s = escapeJavaScriptString(s);
+ }
+ writer.println(name + "=\"" + s + "\";");
+ }
+
+ protected void outputArgSet(PrintWriter writer, String name, ArgSet set)
+ throws IOException {
+ Enumeration<String> e = set.getNames();
+
+ while (e.hasMoreElements()) {
+ String n = e.nextElement();
+ IArgValue val = set.get(n);
+
+ if (val instanceof ArgSet) {
+ ArgSet set1 = (ArgSet) val;
+
+ outputArgSet(writer, name + "." + n, set1);
+ } else if (val instanceof ArgList) {
+ ArgList list = (ArgList) val;
+
+ outputArgList(writer, name + "." + n, list);
+ } else if (val instanceof ArgString) {
+ ArgString str = (ArgString) val;
+
+ outputArgString(writer, name + "." + n, str);
+ }
+ }
+ }
+
+ protected void outputData(PrintWriter writer, ArgSet set)
+ throws IOException {
+ if (set == null)
+ return;
+ Enumeration<String> e = set.getNames();
+
+ while (e.hasMoreElements()) {
+ String n = e.nextElement();
+ IArgValue val = set.get(n);
+
+ if (val instanceof ArgSet) {
+ ArgSet set1 = (ArgSet) val;
+
+ outputArgSet(writer, n, set1);
+ } else if (val instanceof ArgList) {
+ ArgList list = (ArgList) val;
+
+ outputArgList(writer, n, list);
+ } else if (val instanceof ArgString) {
+ ArgString str = (ArgString) val;
+
+ outputArgString(writer, n, str);
+ }
+ }
+ }
+
+ /**
+ * log according to authority category.
+ */
+ protected void log(int event, int level, String msg) {
+ mLogger.log(event, mLogCategory, level,
+ "Servlet " + mId + ": " + msg);
+ }
+
+ protected void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, mLogCategory, level,
+ "Servlet " + mId + ": " + msg);
+ }
+
+ /**
+ * Retrieves locale based on the request.
+ */
+ protected Locale getLocale(HttpServletRequest req) {
+ Locale locale = null;
+ String lang = req.getHeader(HDR_LANG);
+
+ if (lang == null) {
+ // use server locale
+ locale = Locale.getDefault();
+ } else {
+ locale = new Locale(UserInfo.getUserLanguage(lang),
+ UserInfo.getUserCountry(lang));
+ }
+ return locale;
+ }
+
+ protected void renderResult(CMSRequest cmsReq)
+ throws IOException {
+ // do nothing
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
new file mode 100644
index 000000000..1ee527c97
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
@@ -0,0 +1,890 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.profile;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.cert.CertificateEncodingException;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X509CertImpl;
+
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.asn1.SET;
+import org.mozilla.jss.asn1.UTF8String;
+import org.mozilla.jss.pkix.cmc.LraPopWitness;
+import org.mozilla.jss.pkix.cmc.OtherInfo;
+import org.mozilla.jss.pkix.cmc.TaggedAttribute;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EDeferException;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.profile.IProfileContext;
+import com.netscape.certsrv.profile.IProfileInput;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.request.INotify;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.common.AuthCredentials;
+import com.netscape.cms.servlet.common.CMCOutputTemplate;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * This servlet submits end-user request into the profile framework.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ProfileSubmitCMCServlet extends ProfileServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -8017841111435988197L;
+ private static final String ARG_AUTH_TOKEN = "auth_token";
+ private static final String PROP_PROFILE_ID = "profileId";
+
+ private String mProfileId = null;
+ private String mProfileSubId = null;
+ private String requestB64 = null;
+
+ private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED =
+ "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5";
+
+ public ProfileSubmitCMCServlet() {
+ }
+
+ /**
+ * initialize the servlet. And instance of this servlet can
+ * be set up to always issue certificates against a certain profile
+ * by setting the 'profileId' configuration in the servletConfig
+ * If not, the user must specify the profileID when submitting the request
+ *
+ * "ImportCert.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mProfileId = sc.getInitParameter(PROP_PROFILE_ID);
+ mRenderResult = false;
+ }
+
+ private void setInputsIntoContext(HttpServletRequest request, IProfile profile, IProfileContext ctx) {
+
+ // passing inputs into context
+ Enumeration<String> inputIds = profile.getProfileInputIds();
+
+ if (inputIds != null) {
+ while (inputIds.hasMoreElements()) {
+ String inputId = inputIds.nextElement();
+ IProfileInput profileInput = profile.getProfileInput(inputId);
+ Enumeration<String> inputNames = profileInput.getValueNames();
+
+ while (inputNames.hasMoreElements()) {
+ String inputName = inputNames.nextElement();
+
+ if (request.getParameter(inputName) != null) {
+ ctx.set(inputName, request.getParameter(inputName));
+ }
+ }
+ }
+ }
+
+ }
+
+ private void setCredentialsIntoContext(HttpServletRequest request, IProfileAuthenticator authenticator,
+ IProfileContext ctx) {
+ Enumeration<String> authIds = authenticator.getValueNames();
+
+ if (authIds != null) {
+ while (authIds.hasMoreElements()) {
+ String authName = authIds.nextElement();
+
+ if (request.getParameter(authName) != null) {
+ ctx.set(authName, request.getParameter(authName));
+ }
+ }
+ }
+ }
+
+ public IAuthToken authenticate(IProfileAuthenticator authenticator,
+ HttpServletRequest request) throws EBaseException {
+ AuthCredentials credentials = new AuthCredentials();
+
+ // build credential
+ Enumeration<String> authNames = authenticator.getValueNames();
+
+ if (authNames != null) {
+ while (authNames.hasMoreElements()) {
+ String authName = authNames.nextElement();
+
+ if (authName.equals("cert_request"))
+ credentials.set(authName, requestB64);
+ else
+ credentials.set(authName, request.getParameter(authName));
+ }
+ }
+ IAuthToken authToken = authenticator.authenticate(credentials);
+
+ SessionContext sc = SessionContext.getContext();
+ if (sc != null) {
+ sc.put(SessionContext.AUTH_MANAGER_ID, authenticator.getName());
+ String userid = authToken.getInString(IAuthToken.USER_ID);
+ if (userid != null) {
+ sc.put(SessionContext.USER_ID, userid);
+ }
+ }
+
+ return authToken;
+ }
+
+ private void setInputsIntoRequest(HttpServletRequest request, IProfile
+ profile, IRequest req) {
+ Enumeration<String> inputIds = profile.getProfileInputIds();
+
+ if (inputIds != null) {
+ while (inputIds.hasMoreElements()) {
+ String inputId = inputIds.nextElement();
+ IProfileInput profileInput = profile.getProfileInput(inputId);
+ Enumeration<String> inputNames = profileInput.getValueNames();
+
+ if (inputNames != null) {
+ while (inputNames.hasMoreElements()) {
+ String inputName = inputNames.nextElement();
+
+ if (request.getParameter(inputName) != null) {
+ req.setExtData(inputName, request.getParameter(inputName));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Process the HTTP request
+ * <P>
+ *
+ * (Certificate Request Processed - either an automated "EE" profile based cert acceptance, or an automated "EE"
+ * profile based cert rejection)
+ * <P>
+ *
+ * <ul>
+ * <li>http.param profileId ID of profile to use to process request
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been
+ * through the approval process
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ * @exception EBaseException an error has occurred
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest request = cmsReq.getHttpReq();
+ HttpServletResponse response = cmsReq.getHttpResp();
+
+ Locale locale = getLocale(request);
+ String cert_request_type =
+ mServletConfig.getInitParameter("cert_request_type");
+ String outputFormat = mServletConfig.getInitParameter("outputFormat");
+
+ int reqlen = request.getContentLength();
+ InputStream is = null;
+ try {
+ is = request.getInputStream();
+ } catch (Exception ee) {
+ }
+ byte reqbuf[] = new byte[reqlen];
+ int bytesread = 0;
+ boolean partial = false;
+
+ while (bytesread < reqlen) {
+ try {
+ bytesread += is.read(reqbuf, bytesread, reqlen - bytesread);
+ } catch (Exception ee) {
+ }
+
+ if (partial == false) {
+ if (bytesread < reqlen)
+ partial = true;
+ }
+ }
+
+ requestB64 = Utils.base64encode(reqbuf);
+
+ if (CMS.debugOn()) {
+ CMS.debug("Start of ProfileSubmitCMCServlet Input Parameters");
+ Enumeration<String> paramNames = request.getParameterNames();
+
+ while (paramNames.hasMoreElements()) {
+ String paramName = paramNames.nextElement();
+ // added this facility so that password can be hidden,
+ // all sensitive parameters should be prefixed with
+ // __ (double underscores); however, in the event that
+ // a security parameter slips through, we perform multiple
+ // additional checks to insure that it is NOT displayed
+ if (paramName.startsWith("__") ||
+ paramName.endsWith("password") ||
+ paramName.endsWith("passwd") ||
+ paramName.endsWith("pwd") ||
+ paramName.equalsIgnoreCase("admin_password_again") ||
+ paramName.equalsIgnoreCase("directoryManagerPwd") ||
+ paramName.equalsIgnoreCase("bindpassword") ||
+ paramName.equalsIgnoreCase("bindpwd") ||
+ paramName.equalsIgnoreCase("passwd") ||
+ paramName.equalsIgnoreCase("password") ||
+ paramName.equalsIgnoreCase("pin") ||
+ paramName.equalsIgnoreCase("pwd") ||
+ paramName.equalsIgnoreCase("pwdagain") ||
+ paramName.equalsIgnoreCase("uPasswd")) {
+ CMS.debug("ProfileSubmitCMCServlet Input Parameter " +
+ paramName + "='(sensitive)'");
+ } else {
+ CMS.debug("ProfileSubmitCMCServlet Input Parameter " +
+ paramName + "='" +
+ request.getParameter(paramName) + "'");
+ }
+ }
+ CMS.debug("End of ProfileSubmitCMCServlet Input Parameters");
+ }
+
+ CMS.debug("ProfileSubmitCMCServlet: start serving");
+
+ if (mProfileSubId == null || mProfileSubId.equals("")) {
+ mProfileSubId = IProfileSubsystem.ID;
+ }
+ CMS.debug("ProfileSubmitCMCServlet: SubId=" + mProfileSubId);
+ IProfileSubsystem ps = (IProfileSubsystem)
+ CMS.getSubsystem(mProfileSubId);
+
+ if (ps == null) {
+ CMS.debug("ProfileSubmitCMCServlet: ProfileSubsystem not found");
+ CMCOutputTemplate template = new CMCOutputTemplate();
+ SEQUENCE seq = new SEQUENCE();
+ seq.addElement(new INTEGER(0));
+ UTF8String s = null;
+ try {
+ s = new UTF8String(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR"));
+ } catch (Exception ee) {
+ }
+ template.createFullResponseWithFailedStatus(response, seq,
+ OtherInfo.INTERNAL_CA_ERROR, s);
+ return;
+ }
+
+ // if we did not configure profileId in xml file,
+ // then accept the user-provided one
+ String profileId = null;
+
+ if (mProfileId == null) {
+ profileId = request.getParameter("profileId");
+ } else {
+ profileId = mProfileId;
+ }
+
+ IProfile profile = null;
+
+ try {
+ CMS.debug("ProfileSubmitCMCServlet: profileId " + profileId);
+ profile = ps.getProfile(profileId);
+ } catch (EProfileException e) {
+ CMS.debug("ProfileSubmitCMCServlet: profile not found profileId " +
+ profileId + " " + e.toString());
+ }
+ if (profile == null) {
+ CMCOutputTemplate template = new CMCOutputTemplate();
+ SEQUENCE seq = new SEQUENCE();
+ seq.addElement(new INTEGER(0));
+ UTF8String s = null;
+ try {
+ s = new UTF8String(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId));
+ } catch (Exception ee) {
+ }
+ template.createFullResponseWithFailedStatus(response, seq,
+ OtherInfo.INTERNAL_CA_ERROR, s);
+ return;
+ }
+
+ if (!ps.isProfileEnable(profileId)) {
+ CMS.debug("ProfileSubmitCMCServlet: Profile " + profileId +
+ " not enabled");
+ CMCOutputTemplate template = new CMCOutputTemplate();
+ SEQUENCE seq = new SEQUENCE();
+ seq.addElement(new INTEGER(0));
+ UTF8String s = null;
+ try {
+ s = new UTF8String(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId));
+ } catch (Exception ee) {
+ }
+ template.createFullResponseWithFailedStatus(response, seq,
+ OtherInfo.INTERNAL_CA_ERROR, s);
+ return;
+ }
+
+ IProfileContext ctx = profile.createContext();
+ if (requestB64 != null) {
+ ctx.set("cert_request_type", cert_request_type);
+ ctx.set("cert_request", requestB64);
+ }
+ // passing auths into context
+ IProfileAuthenticator authenticator = null;
+
+ try {
+ authenticator = profile.getAuthenticator();
+ } catch (EProfileException e) {
+ // authenticator not installed correctly
+ }
+ if (authenticator == null) {
+ CMS.debug("ProfileSubmitCMCServlet: authenticator not found");
+ } else {
+ CMS.debug("ProfileSubmitCMCServlet: authenticator " +
+ authenticator.getName() + " found");
+ setCredentialsIntoContext(request, authenticator, ctx);
+ }
+
+ setInputsIntoContext(request, profile, ctx);
+ CMS.debug("ProfileSubmistServlet: set Inputs into Context");
+
+ // before creating the request, authenticate the request
+
+ IAuthToken authToken = null;
+
+ // for ssl authentication; pass in servlet for retrieving
+ // ssl client certificates
+ SessionContext context = SessionContext.getContext();
+
+ // insert profile context so that input parameter can be retrieved
+ context.put("profileContext", ctx);
+ context.put("sslClientCertProvider",
+ new SSLClientCertProvider(request));
+ CMS.debug("ProfileSubmitCMCServlet: set sslClientCertProvider");
+ if (authenticator != null) {
+ try {
+ authToken = authenticate(authenticator, request);
+ // authentication success
+ } catch (EBaseException e) {
+ CMCOutputTemplate template = new CMCOutputTemplate();
+ SEQUENCE seq = new SEQUENCE();
+ seq.addElement(new INTEGER(0));
+ UTF8String s = null;
+ try {
+ s = new UTF8String(e.toString());
+ } catch (Exception ee) {
+ }
+ template.createFullResponseWithFailedStatus(response, seq,
+ OtherInfo.BAD_REQUEST, s);
+ CMS.debug("ProfileSubmitCMCServlet: authentication error " +
+ e.toString());
+ return;
+ }
+
+ //authorization only makes sense when request is authenticated
+ AuthzToken authzToken = null;
+ if (authToken != null) {
+ CMS.debug("ProfileSubmitCMCServlet authToken not null");
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "submit");
+ } catch (Exception e) {
+ CMS.debug("ProfileSubmitCMCServlet authorization failure: " + e.toString());
+ }
+ }
+
+ if (authzToken == null) {
+ CMS.debug("ProfileSubmitCMCServlet authorization failure: authzToken is null");
+ CMCOutputTemplate template = new CMCOutputTemplate();
+ SEQUENCE seq = new SEQUENCE();
+ seq.addElement(new INTEGER(0));
+ UTF8String s = null;
+ try {
+ s = new UTF8String("ProfileSubmitCMCServlet authorization failure");
+ } catch (Exception ee) {
+ }
+ template.createFullResponseWithFailedStatus(response, seq,
+ OtherInfo.BAD_REQUEST, s);
+ return;
+ }
+ }
+
+ IRequest reqs[] = null;
+
+ ///////////////////////////////////////////////
+ // create request
+ ///////////////////////////////////////////////
+ try {
+ reqs = profile.createRequests(ctx, locale);
+ } catch (EProfileException e) {
+ CMS.debug("ProfileSubmitCMCServlet: createRequests " + e.toString());
+ CMCOutputTemplate template = new CMCOutputTemplate();
+ SEQUENCE seq = new SEQUENCE();
+ seq.addElement(new INTEGER(0));
+ UTF8String s = null;
+ try {
+ s = new UTF8String(e.toString());
+ } catch (Exception ee) {
+ }
+ template.createFullResponseWithFailedStatus(response, seq,
+ OtherInfo.INTERNAL_CA_ERROR, s);
+ return;
+ } catch (Throwable e) {
+ CMS.debug("ProfileSubmitCMCServlet: createRequests " + e.toString());
+ CMCOutputTemplate template = new CMCOutputTemplate();
+ SEQUENCE seq = new SEQUENCE();
+ seq.addElement(new INTEGER(0));
+ UTF8String s = null;
+ try {
+ s = new UTF8String(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR"));
+ } catch (Exception ee) {
+ }
+ template.createFullResponseWithFailedStatus(response, seq,
+ OtherInfo.INTERNAL_CA_ERROR, s);
+ return;
+ }
+
+ TaggedAttribute attr =
+ (TaggedAttribute) (context.get(OBJECT_IDENTIFIER.id_cmc_lraPOPWitness));
+ if (attr != null) {
+ boolean verifyAllow = true;
+ try {
+ verifyAllow = CMS.getConfigStore().getBoolean(
+ "cmc.lraPopWitness.verify.allow", true);
+ } catch (EBaseException ee) {
+ }
+
+ if (!verifyAllow) {
+ LraPopWitness lraPop = null;
+ SET vals = attr.getValues();
+ if (vals.size() > 0) {
+ try {
+ lraPop = (LraPopWitness) (ASN1Util.decode(LraPopWitness.getTemplate(),
+ ASN1Util.encode(vals.elementAt(0))));
+ } catch (InvalidBERException e) {
+ CMS.debug(
+ CMS.getUserMessage(locale, "CMS_PROFILE_ENCODING_ERROR"));
+ }
+
+ SEQUENCE bodyIds = lraPop.getBodyIds();
+
+ CMCOutputTemplate template = new CMCOutputTemplate();
+ template.createFullResponseWithFailedStatus(response, bodyIds,
+ OtherInfo.POP_FAILED, null);
+ return;
+ }
+ }
+ }
+
+ // for CMC, requests may be zero. Then check if controls exist.
+ if (reqs == null) {
+ Integer nums = (Integer) (context.get("numOfControls"));
+ CMCOutputTemplate template = new CMCOutputTemplate();
+ // if there is only one control GetCert, then simple response
+ // must be returned.
+ if (nums != null && nums.intValue() == 1) {
+ TaggedAttribute attr1 = (TaggedAttribute) (context.get(OBJECT_IDENTIFIER.id_cmc_getCert));
+ if (attr1 != null) {
+ template.createSimpleResponse(response, reqs);
+ } else
+ template.createFullResponse(response, reqs,
+ cert_request_type, null);
+ } else
+ template.createFullResponse(response, reqs,
+ cert_request_type, null);
+ return;
+ }
+
+ String errorCode = null;
+ String errorReason = null;
+
+ ///////////////////////////////////////////////
+ // populate request
+ ///////////////////////////////////////////////
+ for (int k = 0; k < reqs.length; k++) {
+ // adding parameters to request
+ setInputsIntoRequest(request, profile, reqs[k]);
+
+ // serial auth token into request
+ if (authToken != null) {
+ Enumeration<String> tokenNames = authToken.getElements();
+ while (tokenNames.hasMoreElements()) {
+ String tokenName = tokenNames.nextElement();
+ String[] vals = authToken.getInStringArray(tokenName);
+ if (vals != null) {
+ for (int i = 0; i < vals.length; i++) {
+ reqs[k].setExtData(ARG_AUTH_TOKEN + "." +
+ tokenName + "[" + i + "]", vals[i]);
+ }
+ } else {
+ String val = authToken.getInString(tokenName);
+ if (val != null) {
+ reqs[k].setExtData(ARG_AUTH_TOKEN + "." + tokenName,
+ val);
+ }
+ }
+ }
+ }
+
+ // put profile framework parameters into the request
+ reqs[k].setExtData(ARG_PROFILE, "true");
+ reqs[k].setExtData(ARG_PROFILE_ID, profileId);
+ reqs[k].setExtData(ARG_PROFILE_APPROVED_BY, profile.getApprovedBy());
+ String setId = profile.getPolicySetId(reqs[k]);
+
+ if (setId == null) {
+ // no profile set found
+ CMCOutputTemplate template = new CMCOutputTemplate();
+ SEQUENCE seq = new SEQUENCE();
+ seq.addElement(new INTEGER(0));
+ UTF8String s = null;
+ try {
+ s = new UTF8String(CMS.getUserMessage("CMS_PROFILE_NO_POLICY_SET_FOUND"));
+ } catch (Exception ee) {
+ }
+ template.createFullResponseWithFailedStatus(response, seq,
+ OtherInfo.INTERNAL_CA_ERROR, s);
+ return;
+ }
+
+ CMS.debug("ProfileSubmitCMCServlet profileSetid=" + setId);
+ reqs[k].setExtData(ARG_PROFILE_SET_ID, setId);
+ reqs[k].setExtData(ARG_PROFILE_REMOTE_HOST, request.getRemoteHost());
+ reqs[k].setExtData(ARG_PROFILE_REMOTE_ADDR, request.getRemoteAddr());
+
+ CMS.debug("ProfileSubmitCMCServlet: request " +
+ reqs[k].getRequestId().toString());
+
+ try {
+ CMS.debug("ProfileSubmitCMCServlet: populating request inputs");
+ // give authenticator a chance to populate the request
+ if (authenticator != null) {
+ authenticator.populate(authToken, reqs[k]);
+ }
+ profile.populateInput(ctx, reqs[k]);
+ profile.populate(reqs[k]);
+ } catch (EProfileException e) {
+ CMS.debug("ProfileSubmitCMCServlet: populate " + e.toString());
+ CMCOutputTemplate template = new CMCOutputTemplate();
+ SEQUENCE seq = new SEQUENCE();
+ seq.addElement(new INTEGER(0));
+ UTF8String s = null;
+ try {
+ s = new UTF8String(e.toString());
+ } catch (Exception ee) {
+ }
+ template.createFullResponseWithFailedStatus(response, seq,
+ OtherInfo.BAD_REQUEST, s);
+ return;
+ } catch (Throwable e) {
+ CMS.debug("ProfileSubmitCMCServlet: populate " + e.toString());
+ // throw new IOException("Profile " + profileId +
+ // " cannot populate");
+ CMCOutputTemplate template = new CMCOutputTemplate();
+ SEQUENCE seq = new SEQUENCE();
+ seq.addElement(new INTEGER(0));
+ UTF8String s = null;
+ try {
+ s = new UTF8String(e.toString());
+ } catch (Exception ee) {
+ }
+ template.createFullResponseWithFailedStatus(response, seq,
+ OtherInfo.INTERNAL_CA_ERROR, s);
+ return;
+ }
+ }
+
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRequesterID = ILogger.UNIDENTIFIED;
+ String auditInfoCertValue = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+
+ try {
+ ///////////////////////////////////////////////
+ // submit request
+ ///////////////////////////////////////////////
+ int error_codes[] = null;
+ if (reqs != null && reqs.length > 0)
+ error_codes = new int[reqs.length];
+ for (int k = 0; k < reqs.length; k++) {
+ try {
+ // reset the "auditRequesterID"
+ auditRequesterID = auditRequesterID(reqs[k]);
+
+ // print request debug
+ if (reqs[k] != null) {
+ Enumeration<String> reqKeys = reqs[k].getExtDataKeys();
+ while (reqKeys.hasMoreElements()) {
+ String reqKey = reqKeys.nextElement();
+ String reqVal = reqs[k].getExtDataInString(reqKey);
+ if (reqVal != null) {
+ CMS.debug("ProfileSubmitCMCServlet: key=$request." + reqKey + "$ value=" + reqVal);
+ }
+ }
+ }
+
+ profile.submit(authToken, reqs[k]);
+ reqs[k].setRequestStatus(RequestStatus.COMPLETE);
+
+ // reset the "auditInfoCertValue"
+ auditInfoCertValue = auditInfoCertValue(reqs[k]);
+
+ if (auditInfoCertValue != null) {
+ if (!(auditInfoCertValue.equals(
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE))) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_ACCEPTANCE,
+ auditInfoCertValue);
+
+ audit(auditMessage);
+ }
+ }
+ } catch (EDeferException e) {
+ // return defer message to the user
+ reqs[k].setRequestStatus(RequestStatus.PENDING);
+ // need to notify
+ INotify notify = profile.getRequestQueue().getPendingNotify();
+ if (notify != null) {
+ notify.notify(reqs[k]);
+ }
+
+ CMS.debug("ProfileSubmitCMCServlet: submit " + e.toString());
+ errorCode = "2";
+ errorReason = CMS.getUserMessage(locale,
+ "CMS_PROFILE_DEFERRED",
+ e.toString());
+ } catch (ERejectException e) {
+ // return error to the user
+ reqs[k].setRequestStatus(RequestStatus.REJECTED);
+ CMS.debug("ProfileSubmitCMCServlet: submit " + e.toString());
+ errorCode = "3";
+ errorReason = CMS.getUserMessage(locale,
+ "CMS_PROFILE_REJECTED",
+ e.toString());
+ } catch (Throwable e) {
+ // return error to the user
+ CMS.debug("ProfileSubmitCMCServlet: submit " + e.toString());
+ errorCode = "1";
+ errorReason = CMS.getUserMessage(locale,
+ "CMS_INTERNAL_ERROR");
+ }
+
+ try {
+ if (errorCode == null) {
+ profile.getRequestQueue().markAsServiced(reqs[k]);
+ } else {
+ profile.getRequestQueue().updateRequest(reqs[k]);
+ }
+ } catch (EBaseException e) {
+ CMS.debug("ProfileSubmitCMCServlet: updateRequest " +
+ e.toString());
+ }
+
+ if (errorCode != null) {
+ if (errorCode.equals("1")) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_REJECTION,
+ errorReason);
+
+ audit(auditMessage);
+ } else if (errorCode.equals("2")) {
+ // do NOT store a message in the signed audit log file
+ // as this errorCode indicates that a process has been
+ // deferred for manual acceptance/cancellation/rejection
+ } else if (errorCode.equals("3")) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ ILogger.SIGNED_AUDIT_REJECTION,
+ errorReason);
+
+ audit(auditMessage);
+ }
+ error_codes[k] = Integer.parseInt(errorCode);
+ } else
+ error_codes[k] = 0;
+ }
+
+ if (errorCode != null) {
+ // create the CMC full enrollment response
+ CMCOutputTemplate template = new CMCOutputTemplate();
+ template.createFullResponse(response, reqs, cert_request_type, error_codes);
+
+ return;
+ }
+
+ ///////////////////////////////////////////////
+ // output output list
+ ///////////////////////////////////////////////
+
+ CMS.debug("ProfileSubmitCMCServlet: done serving");
+ CMCOutputTemplate template = new CMCOutputTemplate();
+ if (cert_request_type.equals("pkcs10") || cert_request_type.equals("crmf")) {
+
+ if (outputFormat != null && outputFormat.equals("pkcs7")) {
+ byte[] pkcs7 = CMS.getPKCS7(locale, reqs[0]);
+ response.setContentType("application/pkcs7-mime");
+ response.setContentLength(pkcs7.length);
+ try {
+ OutputStream os = response.getOutputStream();
+ os.write(pkcs7);
+ os.flush();
+ } catch (Exception ee) {
+ }
+ return;
+ }
+ template.createSimpleResponse(response, reqs);
+ } else if (cert_request_type.equals("cmc")) {
+ Integer nums = (Integer) (context.get("numOfControls"));
+ if (nums != null && nums.intValue() == 1) {
+ TaggedAttribute attr1 =
+ (TaggedAttribute) (context.get(OBJECT_IDENTIFIER.id_cmc_getCert));
+ if (attr1 != null) {
+ template.createSimpleResponse(response, reqs);
+ return;
+ }
+ }
+ template.createFullResponse(response, reqs, cert_request_type,
+ error_codes);
+ }
+ } finally {
+ SessionContext.releaseContext();
+ }
+ }
+
+ /**
+ * Signed Audit Log Requester ID
+ *
+ * This method is called to obtain the "RequesterID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param request the actual request
+ * @return id string containing the signed audit log message RequesterID
+ */
+ private String auditRequesterID(IRequest request) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String requesterID = ILogger.UNIDENTIFIED;
+
+ if (request != null) {
+ // overwrite "requesterID" if and only if "id" != null
+ String id = request.getRequestId().toString();
+
+ if (id != null) {
+ requesterID = id.trim();
+ }
+ }
+
+ return requesterID;
+ }
+
+ /**
+ * Signed Audit Log Info Certificate Value
+ *
+ * This method is called to obtain the certificate from the passed in
+ * "X509CertImpl" for a signed audit log message.
+ * <P>
+ *
+ * @param request request containing an X509CertImpl
+ * @return cert string containing the certificate
+ */
+ private String auditInfoCertValue(IRequest request) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ X509CertImpl x509cert = request.getExtDataInCert(
+ IEnrollProfile.REQUEST_ISSUED_CERT);
+
+ if (x509cert == null) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ byte rawData[] = null;
+
+ try {
+ rawData = x509cert.getEncoded();
+ } catch (CertificateEncodingException e) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ String cert = null;
+
+ // convert "rawData" into "base64Data"
+ if (rawData != null) {
+ String base64Data = null;
+
+ base64Data = Utils.base64encode(rawData).trim();
+
+ // extract all line separators from the "base64Data"
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < base64Data.length(); i++) {
+ if (!Character.isWhitespace(base64Data.charAt(i))) {
+ sb.append(base64Data.charAt(i));
+ }
+ }
+ cert = sb.toString();
+ }
+
+ if (cert != null) {
+ cert = cert.trim();
+
+ if (cert.equals("")) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ } else {
+ return cert;
+ }
+ } else {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java
new file mode 100644
index 000000000..7b0813d71
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java
@@ -0,0 +1,347 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.profile;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import org.w3c.dom.Node;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.authorization.EAuthzException;
+import com.netscape.certsrv.base.BadRequestDataException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileOutput;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.template.ArgList;
+import com.netscape.certsrv.template.ArgSet;
+import com.netscape.cms.servlet.cert.EnrollmentProcessor;
+import com.netscape.cms.servlet.cert.RenewalProcessor;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.processors.Processor;
+import com.netscape.cmsutil.util.Cert;
+import com.netscape.cmsutil.xml.XMLObject;
+
+/**
+ * This servlet submits end-user request into the profile framework.
+ *
+ * @author Christina Fu (renewal support)
+ * @version $Revision$, $Date$
+ */
+public class ProfileSubmitServlet extends ProfileServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7557922703180866442L;
+ private final static String SUCCESS = "0";
+ private final static String FAILED = "1";
+
+ public ProfileSubmitServlet() {
+ }
+
+ /**
+ * initialize the servlet. And instance of this servlet can
+ * be set up to always issue certificates against a certain profile
+ * by setting the 'profileId' configuration in the servletConfig
+ * If not, the user must specify the profileID when submitting the request
+ *
+ * "ImportCert.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ }
+
+ /**
+ * Process the HTTP request
+ * <P>
+ *
+ * (Certificate Request Processed - either an automated "EE" profile based cert acceptance, or an automated "EE"
+ * profile based cert rejection)
+ * <P>
+ *
+ * <ul>
+ * <li>http.param profileId ID of profile to use to process request
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been
+ * through the approval process
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ * @exception EBaseException an error has occurred
+ */
+
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest request = cmsReq.getHttpReq();
+ HttpServletResponse response = cmsReq.getHttpResp();
+ boolean xmlOutput = getXMLOutput(request);
+
+ Locale locale = getLocale(request);
+
+ HashMap<String, Object> results = null;
+ String renewal = request.getParameter("renewal");
+
+ try {
+ if ((renewal != null) && (renewal.equalsIgnoreCase("true"))) {
+ CMS.debug("ProfileSubmitServlet: isRenewal true");
+ RenewalProcessor processor = new RenewalProcessor("caProfileSubmit", locale);
+ results = processor.processRenewal(cmsReq);
+ } else {
+ CMS.debug("ProfileSubmitServlet: isRenewal false");
+ EnrollmentProcessor processor = new EnrollmentProcessor("caProfileSubmit", locale);
+ results = processor.processEnrollment(cmsReq);
+ }
+ } catch (BadRequestDataException e) {
+ CMS.debug("ProfileSubmitServlet: bad data provided in processing request: " + e.toString());
+ errorExit(response, xmlOutput, e.getMessage(), null);
+ return;
+ } catch (EAuthzException e) {
+ CMS.debug("ProfileSubmitServlet: authorization error in processing request: " + e.toString());
+ errorExit(response, xmlOutput, e.getMessage(), null);
+ return;
+ } catch (EAuthException e) {
+ CMS.debug("ProfileSubmitServlet: authentication error in processing request: " + e.toString());
+ errorExit(response, xmlOutput, e.getMessage(), null);
+ return;
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ CMS.debug("ProfileSubmitServlet: error in processing request: " + e.toString());
+ errorExit(response, xmlOutput, e.getMessage(), null);
+ return;
+ }
+
+ IRequest[] reqs = (IRequest []) results.get(Processor.ARG_REQUESTS);
+ String errorCode = (String) results.get(Processor.ARG_ERROR_CODE);
+ String errorReason = (String) results.get(Processor.ARG_ERROR_REASON);
+ IProfile profile = (IProfile) results.get(Processor.ARG_PROFILE);
+ ArgSet args = new ArgSet();
+
+ if (errorCode != null) {
+ if (xmlOutput) {
+ String requestIds = "";
+ for (IRequest req : reqs) {
+ requestIds += " " + req.getRequestId().toString();
+ }
+
+ outputError(response, errorCode, errorReason, requestIds);
+ } else {
+ ArgList requestlist = new ArgList();
+
+ for (IRequest req : reqs) {
+ ArgSet requestset = new ArgSet();
+ requestset.set(ARG_REQUEST_ID, req.getRequestId().toString());
+ requestlist.add(requestset);
+ }
+ args.set(ARG_REQUEST_LIST, requestlist);
+ args.set(ARG_ERROR_CODE, errorCode);
+ args.set(ARG_ERROR_REASON, errorReason);
+ outputTemplate(request, response, args);
+ }
+ return;
+ }
+
+ if (xmlOutput) {
+ xmlOutput(response, profile, locale, reqs);
+ } else {
+ ArgList outputlist = new ArgList();
+ for (int k = 0; k < reqs.length; k++) {
+
+ setOutputIntoArgs(profile, outputlist, locale, reqs[k]);
+ args.set(ARG_OUTPUT_LIST, outputlist);
+ }
+
+ CMS.debug("ProfileSubmitServlet: done serving");
+
+ ArgList requestlist = new ArgList();
+
+ for (int k = 0; k < reqs.length; k++) {
+ ArgSet requestset = new ArgSet();
+
+ requestset.set(ARG_REQUEST_ID,
+ reqs[k].getRequestId().toString());
+ requestlist.add(requestset);
+ }
+ args.set(ARG_REQUEST_LIST, requestlist);
+ args.set(ARG_ERROR_CODE, "0");
+ args.set(ARG_ERROR_REASON, "");
+
+ outputTemplate(request, response, args);
+ }
+ }
+
+ private void setOutputIntoArgs(IProfile profile, ArgList outputlist, Locale locale, IRequest req) {
+ Enumeration<String> outputIds = profile.getProfileOutputIds();
+
+ if (outputIds != null) {
+ while (outputIds.hasMoreElements()) {
+ String outputId = outputIds.nextElement();
+ IProfileOutput profileOutput = profile.getProfileOutput(outputId);
+
+ Enumeration<String> outputNames = profileOutput.getValueNames();
+
+ if (outputNames != null) {
+ while (outputNames.hasMoreElements()) {
+ ArgSet outputset = new ArgSet();
+ String outputName = outputNames.nextElement();
+ IDescriptor outputDesc =
+ profileOutput.getValueDescriptor(locale, outputName);
+
+ if (outputDesc == null)
+ continue;
+ String outputSyntax = outputDesc.getSyntax();
+ String outputConstraint = outputDesc.getConstraint();
+ String outputValueName = outputDesc.getDescription(locale);
+ String outputValue = null;
+
+ try {
+ outputValue = profileOutput.getValue(outputName,
+ locale, req);
+ } catch (EProfileException e) {
+ CMS.debug("ProfileSubmitServlet: " + e.toString());
+ }
+
+ outputset.set(ARG_OUTPUT_ID, outputName);
+ outputset.set(ARG_OUTPUT_SYNTAX, outputSyntax);
+ outputset.set(ARG_OUTPUT_CONSTRAINT, outputConstraint);
+ outputset.set(ARG_OUTPUT_NAME, outputValueName);
+ outputset.set(ARG_OUTPUT_VAL, outputValue);
+ outputlist.add(outputset);
+ }
+ }
+ }
+ }
+ }
+
+ private void errorExit(HttpServletResponse response, boolean xmlOutput, String message, String requestId)
+ throws EBaseException {
+ if (xmlOutput) {
+ outputError(response, FAILED, message, requestId);
+ } else {
+ ArgSet args = new ArgSet();
+ args.set(ARG_ERROR_CODE, "1");
+ args.set(ARG_ERROR_REASON, message);
+ outputTemplate(xmlOutput, response, args);
+ }
+
+ for (String event : statEvents) {
+ endTiming(event);
+ }
+ }
+
+ private boolean getXMLOutput(HttpServletRequest request) {
+ boolean xmlOutput = false;
+
+ String v = request.getParameter("xml");
+ if ((v != null) && (v.equalsIgnoreCase("true"))) {
+ xmlOutput = true;
+ }
+ v = request.getParameter("xmlOutput");
+ if ((v != null) && (v.equalsIgnoreCase("true"))) {
+ xmlOutput = true;
+ }
+ if (xmlOutput) {
+ CMS.debug("xmlOutput true");
+ } else {
+ CMS.debug("xmlOutput false");
+ }
+ return xmlOutput;
+ }
+
+ private void xmlOutput(HttpServletResponse httpResp, IProfile profile, Locale locale, IRequest[] reqs) {
+ try {
+ XMLObject xmlObj = null;
+ xmlObj = new XMLObject();
+
+ Node root = xmlObj.createRoot("XMLResponse");
+ xmlObj.addItemToContainer(root, "Status", SUCCESS);
+ Node n = xmlObj.createContainer(root, "Requests");
+ CMS.debug("ProfileSubmitServlet xmlOutput: req len = " + reqs.length);
+
+ for (int i = 0; i < reqs.length; i++) {
+ Node subnode = xmlObj.createContainer(n, "Request");
+ xmlObj.addItemToContainer(subnode, "Id", reqs[i].getRequestId().toString());
+ X509CertInfo certInfo =
+ reqs[i].getExtDataInCertInfo(IEnrollProfile.REQUEST_CERTINFO);
+ if (certInfo != null) {
+ String subject = "";
+ subject = certInfo.get(X509CertInfo.SUBJECT).toString();
+ xmlObj.addItemToContainer(subnode, "SubjectDN", subject);
+ } else {
+ CMS.debug("ProfileSubmitServlet xmlOutput: no certInfo found in request");
+ }
+ Enumeration<String> outputIds = profile.getProfileOutputIds();
+ if (outputIds != null) {
+ while (outputIds.hasMoreElements()) {
+ String outputId = outputIds.nextElement();
+ IProfileOutput profileOutput = profile.getProfileOutput(outputId);
+ Enumeration<String> outputNames = profileOutput.getValueNames();
+ if (outputNames != null) {
+ while (outputNames.hasMoreElements()) {
+ String outputName = outputNames.nextElement();
+ if (!outputName.equals("b64_cert") && !outputName.equals("pkcs7"))
+ continue;
+ try {
+ String outputValue = profileOutput.getValue(outputName, locale, reqs[i]);
+ if (outputName.equals("b64_cert")) {
+ String ss = Cert.normalizeCertStrAndReq(outputValue);
+ outputValue = Cert.stripBrackets(ss);
+ byte[] bcode = CMS.AtoB(outputValue);
+ X509CertImpl impl = new X509CertImpl(bcode);
+ xmlObj.addItemToContainer(subnode,
+ "serialno", impl.getSerialNumber().toString(16));
+ xmlObj.addItemToContainer(subnode, "b64", outputValue);
+ }// if b64_cert
+ else if (outputName.equals("pkcs7")) {
+ String ss = Cert.normalizeCertStrAndReq(outputValue);
+ xmlObj.addItemToContainer(subnode, "pkcs7", ss);
+ }
+
+ } catch (EProfileException e) {
+ CMS.debug("ProfileSubmitServlet xmlOutput: " + e.toString());
+ } catch (Exception e) {
+ CMS.debug("ProfileSubmitServlet xmlOutput: " + e.toString());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ byte[] cb = xmlObj.toByteArray();
+ outputResult(httpResp, "application/xml", cb);
+ } catch (Exception e) {
+ CMS.debug("Failed to send the XML output");
+ }
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/SSLClientCertProvider.java b/base/server/cms/src/com/netscape/cms/servlet/profile/SSLClientCertProvider.java
new file mode 100644
index 000000000..0114f6323
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/SSLClientCertProvider.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.profile;
+
+import java.security.cert.X509Certificate;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.netscape.certsrv.authentication.ISSLClientCertProvider;
+
+public class SSLClientCertProvider implements ISSLClientCertProvider {
+ private HttpServletRequest mRequest = null;
+
+ public SSLClientCertProvider(HttpServletRequest request) {
+ mRequest = request;
+ }
+
+ public X509Certificate[] getClientCertificateChain() {
+ X509Certificate[] allCerts = (X509Certificate[])
+ mRequest.getAttribute("javax.servlet.request.X509Certificate");
+
+ return allCerts;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/CMSRequestDAO.java b/base/server/cms/src/com/netscape/cms/servlet/request/CMSRequestDAO.java
new file mode 100644
index 000000000..e54f8a4c6
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/CMSRequestDAO.java
@@ -0,0 +1,163 @@
+// --- 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) 2011 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.request;
+
+import java.net.URI;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.Link;
+import com.netscape.certsrv.request.CMSRequestInfo;
+import com.netscape.certsrv.request.CMSRequestInfos;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestList;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.IRequestVirtualList;
+import com.netscape.certsrv.request.RequestId;
+
+/**
+ * @author alee
+ *
+ */
+
+public abstract class CMSRequestDAO {
+ protected IRequestQueue queue;
+ protected IAuthority authority;
+
+ private String[] vlvFilters = {
+ "(requeststate=*)", "(requesttype=enrollment)",
+ "(requesttype=recovery)", "(requeststate=canceled)",
+ "(&(requeststate=canceled)(requesttype=enrollment))",
+ "(&(requeststate=canceled)(requesttype=recovery))",
+ "(requeststate=rejected)",
+ "(&(requeststate=rejected)(requesttype=enrollment))",
+ "(&(requeststate=rejected)(requesttype=recovery))",
+ "(requeststate=complete)",
+ "(&(requeststate=complete)(requesttype=enrollment))",
+ "(&(requeststate=complete)(requesttype=recovery))"
+ };
+
+ public static final String ATTR_SERIALNO = "serialNumber";
+
+ public CMSRequestDAO(String authorityName) {
+ authority = (IAuthority) CMS.getSubsystem(authorityName);
+ queue = authority.getRequestQueue();
+ }
+
+ /**
+ * Finds list of requests matching the specified search filter.
+ *
+ * If the filter corresponds to a VLV search, then that search is executed and the pageSize
+ * and start parameters are used. Otherwise, the maxResults and maxTime parameters are
+ * used in the regularly indexed search.
+ *
+ * @param filter - ldap search filter
+ * @param start - start position for VLV search
+ * @param pageSize - page size for VLV search
+ * @param maxResults - max results to be returned in normal search
+ * @param maxTime - max time for normal search
+ * @param uriInfo - uri context of request
+ * @return collection of key request info
+ * @throws EBaseException
+ */
+ public CMSRequestInfos listCMSRequests(String filter, RequestId start, int pageSize, int maxResults, int maxTime,
+ UriInfo uriInfo) throws EBaseException {
+
+ CMSRequestInfos ret = new CMSRequestInfos();
+ int totalSize = 0;
+ int current = 0;
+
+ if (isVLVSearch(filter)) {
+ IRequestVirtualList vlvlist = queue.getPagedRequestsByFilter(start, false, filter,
+ pageSize + 1, "requestId");
+ totalSize = vlvlist.getSize();
+ current = vlvlist.getCurrentIndex();
+
+ int numRecords = (totalSize > (current + pageSize)) ? pageSize :
+ totalSize - current;
+
+ for (int i = 0; i < numRecords; i++) {
+ IRequest request = vlvlist.getElementAt(i);
+ ret.addRequest(createCMSRequestInfo(request, uriInfo));
+ }
+ } else {
+ // The non-vlv requests are indexed, but are not paginated.
+ // We should think about whether they should be, or if we need to
+ // limit the number of results returned.
+ IRequestList requests = queue.listRequestsByFilter(filter, maxResults, maxTime);
+
+ if (requests == null) {
+ return ret;
+ }
+ while (requests.hasMoreElements()) {
+ RequestId rid = requests.nextElement();
+ IRequest request = queue.findRequest(rid);
+ if (request != null) {
+ ret.addRequest(createCMSRequestInfo(request, uriInfo));
+ }
+ }
+ }
+
+ // builder for vlv links
+ MultivaluedMap<String, String> params = uriInfo.getQueryParameters();
+ UriBuilder builder = uriInfo.getAbsolutePathBuilder();
+ if (params.containsKey("requestState")) {
+ builder.queryParam("requestState", params.getFirst("requestState"));
+ }
+ if (params.containsKey("requestType")) {
+ builder.queryParam("requestType", params.getFirst("requestType"));
+ }
+ builder.queryParam("start", "{start}");
+ builder.queryParam("pageSize", "{pageSize}");
+
+ // next link
+ if (totalSize > current + pageSize) {
+ int next = current + pageSize + 1;
+ URI nextUri = builder.clone().build(next, pageSize);
+ Link nextLink = new Link("next", nextUri.toString(), "application/xml");
+ ret.addLink(nextLink);
+ }
+
+ // previous link
+ if (current > 0) {
+ int previous = current - pageSize;
+ URI previousUri = builder.clone().build(previous, pageSize);
+ Link previousLink = new Link("previous", previousUri.toString(), "application/xml");
+ ret.addLink(previousLink);
+ }
+
+ return ret;
+ }
+
+ private boolean isVLVSearch(String filter) {
+ for (int i = 0; i < vlvFilters.length; i++) {
+ if (vlvFilters[i].equalsIgnoreCase(filter)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected abstract CMSRequestInfo createCMSRequestInfo(IRequest request, UriInfo uriInfo);
+}
+
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/CertReqParser.java b/base/server/cms/src/com/netscape/cms/servlet/request/CertReqParser.java
new file mode 100644
index 000000000..fd4589437
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/CertReqParser.java
@@ -0,0 +1,918 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.request;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.lang.reflect.Array;
+import java.math.BigInteger;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import netscape.security.extensions.NSCertTypeExtension;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.Extension;
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IPrettyPrintFormat;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.RawJS;
+
+/**
+ * Output a 'pretty print' of a certificate request
+ *
+ * @version $Revision$, $Date$
+ */
+public class CertReqParser extends ReqParser {
+
+ public static final CertReqParser DETAIL_PARSER = new CertReqParser(true);
+ public static final CertReqParser NODETAIL_PARSER = new CertReqParser(false);
+
+ private boolean mDetails = true;
+ private IPrettyPrintFormat pp = null;
+
+ /**
+ * Constructs a certificate request parser.
+ */
+ public CertReqParser() {
+ pp = CMS.getPrettyPrintFormat(":");
+ }
+
+ /**
+ * Constructs a certificate request parser.
+ *
+ * @param details return detailed information (this can be time consuming)
+ */
+ public CertReqParser(boolean details) {
+ mDetails = details;
+ pp = CMS.getPrettyPrintFormat(":");
+ }
+
+ private static final String EXT_PRETTYPRINT = "ext_prettyprint";
+
+ private static final String LB = "[";
+ private static final String RB = "]";
+ private static final String EQ = " = ";
+
+ /**
+ * Fills in certificate specific request attributes.
+ */
+ public void fillRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg)
+ throws EBaseException {
+ if (req.getExtDataInCertInfoArray(IRequest.CERT_INFO) != null) {
+ fillX509RequestIntoArg(l, req, argSet, arg);
+ } else if (req.getExtDataInRevokedCertArray(IRequest.CERT_INFO) != null) {
+ fillRevokeRequestIntoArg(l, req, argSet, arg);
+ } else {
+ //o = req.get(IRequest.OLD_CERTS);
+ //if (o != null)
+ fillRevokeRequestIntoArg(l, req, argSet, arg);
+ }
+ }
+
+ private void fillX509RequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg)
+ throws EBaseException {
+
+ // fill in the standard attributes
+ super.fillRequestIntoArg(l, req, argSet, arg);
+
+ arg.addStringValue("certExtsEnabled", "yes");
+
+ int saCounter = 0;
+ Enumeration<String> enum1 = req.getExtDataKeys();
+
+ // gross hack
+ String prefix = "record.";
+
+ if (argSet.getHeader() == arg)
+ prefix = "header.";
+
+ while (enum1.hasMoreElements()) {
+ String name = enum1.nextElement();
+
+ if (mDetails) {
+ // show all http parameters stored in request.
+ if (name.equalsIgnoreCase(IRequest.HTTP_PARAMS)) {
+ Hashtable<String, String> http_params = req.getExtDataInHashtable(name);
+ // show certType specially
+ String certType = http_params.get(IRequest.CERT_TYPE);
+
+ if (certType != null) {
+ arg.addStringValue(IRequest.CERT_TYPE, certType);
+ }
+ String presenceServerExt = http_params.get("PresenceServerExtension");
+
+ if (presenceServerExt != null) {
+ arg.addStringValue("PresenceServerExtension", presenceServerExt);
+ }
+ // show all http parameters in request
+ int counter = 0;
+ Enumeration<String> elms = http_params.keys();
+
+ while (elms.hasMoreElements()) {
+ String parami =
+ IRequest.HTTP_PARAMS + LB + String.valueOf(counter++) + RB;
+ // hack
+ String n = elms.nextElement();
+ String rawJS = "new Object;\n\r" +
+ prefix + parami + ".name=\"" +
+ CMSTemplate.escapeJavaScriptString(n) + "\";\n\r" +
+ prefix + parami + ".value=\"" +
+ CMSTemplate.escapeJavaScriptStringHTML(
+ http_params.get(n).toString()) + "\"";
+
+ arg.set(parami, new RawJS(rawJS));
+ }
+ } // show all http headers stored in request.
+ else if (name.equalsIgnoreCase(IRequest.HTTP_HEADERS)) {
+ Hashtable<String, String> http_hdrs = req.getExtDataInHashtable(name);
+ Enumeration<String> elms = http_hdrs.keys();
+ int counter = 0;
+
+ while (elms.hasMoreElements()) {
+ String parami =
+ IRequest.HTTP_HEADERS + LB + String.valueOf(counter++) + RB;
+ // hack
+ String n = elms.nextElement();
+ String rawJS = "new Object;\n\r" +
+ prefix + parami + ".name=\"" +
+ CMSTemplate.escapeJavaScriptString(n) + "\";\n\r" +
+ prefix + parami + ".value=\"" +
+ CMSTemplate.escapeJavaScriptStringHTML(
+ http_hdrs.get(n).toString()) + "\"";
+
+ arg.set(parami, new RawJS(rawJS));
+ }
+ } // show all auth token stored in request.
+ else if (name.equalsIgnoreCase(IRequest.AUTH_TOKEN)) {
+ IAuthToken auth_token = req.getExtDataInAuthToken(name);
+ Enumeration<String> elms = auth_token.getElements();
+ int counter = 0;
+
+ while (elms.hasMoreElements()) {
+ String parami =
+ IRequest.AUTH_TOKEN + LB + String.valueOf(counter++) + RB;
+ // hack
+ String n = elms.nextElement();
+ Object authTokenValue = auth_token.getInStringArray(n);
+ if (authTokenValue == null) {
+ authTokenValue = auth_token.getInString(n);
+ }
+ String v = expandValue(prefix + parami + ".value",
+ authTokenValue);
+ String rawJS = "new Object;\n\r" +
+ prefix + parami + ".name=\"" +
+ CMSTemplate.escapeJavaScriptString(n) + "\";\n" + v;
+
+ arg.set(parami, new RawJS(rawJS));
+ }
+ } // all others are request attrs from policy or internal modules.
+ else {
+ Object val;
+ if (req.isSimpleExtDataValue(name)) {
+ val = req.getExtDataInString(name);
+ } else {
+ val = req.getExtDataInStringArray(name);
+ if (val == null) {
+ val = req.getExtDataInHashtable(name);
+ }
+ }
+ String valstr = "";
+ // hack
+ String parami =
+ IRequest.SERVER_ATTRS + LB + String.valueOf(saCounter++) + RB;
+
+ if (name.equalsIgnoreCase(IRequest.ISSUED_CERTS) && mDetails &&
+ (req.getRequestStatus() == RequestStatus.COMPLETE ||
+ req.getRequestType().equals(IRequest.GETREVOCATIONINFO_REQUEST))) {
+ X509CertImpl issuedCert[] =
+ req.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+ if (issuedCert != null && issuedCert[0] != null) {
+ val = "<pre>" + CMS.getCertPrettyPrint(issuedCert[0]).toString(l) + "</pre>";
+ }
+ } else if (name.equalsIgnoreCase(IRequest.CERT_INFO) && mDetails) {
+ X509CertInfo[] certInfo =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+ if (certInfo != null && certInfo[0] != null) {
+ val = "<pre>" + certInfo[0].toString() + "</pre>";
+ }
+ }
+
+ valstr = expandValue(prefix + parami + ".value", val);
+ String rawJS = "new Object;\n\r" +
+ prefix + parami + ".name=\"" +
+ CMSTemplate.escapeJavaScriptString(name) + "\";\n" +
+ valstr; // java string already escaped in expandValue.
+
+ arg.set(parami, new RawJS(rawJS));
+ }
+ }
+
+ if (name.equalsIgnoreCase(IRequest.REQUESTOR_PHONE)
+ || name.equalsIgnoreCase(IRequest.REQUESTOR_EMAIL)
+ || name.equalsIgnoreCase(IRequest.REQUESTOR_COMMENTS)
+ || name.equalsIgnoreCase(IRequest.RESULT)
+ || name.equalsIgnoreCase(IRequest.REQUEST_TRUSTEDMGR_PRIVILEGE)) {
+ arg.addStringValue(name, req.getExtDataInString(name));
+ }
+
+ if (name.equalsIgnoreCase(IRequest.REQUESTOR_NAME)) {
+ String requestorName = req.getExtDataInString(name);
+
+ requestorName = requestorName.trim();
+ if (requestorName.length() > 0) {
+ arg.addStringValue(name, requestorName);
+ }
+ }
+
+ if (name.equalsIgnoreCase(IRequest.ERRORS)) {
+ Vector<String> errorStrings = req.getExtDataInStringVector(name);
+ if (errorStrings != null) {
+ StringBuffer errInfo = new StringBuffer();
+
+ for (int i = 0; i < errorStrings.size(); i++) {
+ errInfo.append(errorStrings.elementAt(i));
+ errInfo.append("\n");
+ }
+ arg.addStringValue(IRequest.ERRORS, errInfo.toString());
+ }
+ }
+ if (name.equalsIgnoreCase(IRequest.ERROR)) {
+ arg.addStringValue(IRequest.ERRORS, req.getExtDataInString(name));
+ }
+
+ if (name.equalsIgnoreCase(IRequest.CERT_INFO)) {
+ // Get the certificate info from the request
+ X509CertInfo[] certInfo =
+ req.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (certInfo != null && certInfo[0] != null) {
+ // Get the subject name if any set.
+ CertificateSubjectName subjectName = null;
+ String signatureAlgorithm = null;
+ String signatureAlgorithmName = null;
+
+ try {
+ subjectName = (CertificateSubjectName) certInfo[0].get(X509CertInfo.SUBJECT);
+ } catch (IOException e) {
+ // XXX raise exception
+ } catch (CertificateException e) {
+ // XXX raise exception
+ }
+ if (subjectName != null) {
+ String sn;
+
+ try {
+ sn = subjectName.toString();
+ } catch (java.lang.IllegalArgumentException e) {
+ sn = "* * Malformed Subject Name * *";
+ }
+ String subjectnamevalue = sn;
+
+ arg.addStringValue("subject", subjectnamevalue);
+ }
+
+ if (mDetails) {
+ try {
+ CertificateAlgorithmId certAlgId = (CertificateAlgorithmId)
+ certInfo[0].get(X509CertInfo.ALGORITHM_ID);
+ AlgorithmId algId = (AlgorithmId)
+ certAlgId.get(CertificateAlgorithmId.ALGORITHM);
+
+ signatureAlgorithm = (algId.getOID()).toString();
+ signatureAlgorithmName = algId.getName();
+ } catch (Exception e) {
+ // XXX raise exception
+ }
+ if (signatureAlgorithm != null) {
+ arg.addStringValue("signatureAlgorithm", signatureAlgorithm);
+ }
+ if (signatureAlgorithmName != null) {
+ arg.addStringValue("signatureAlgorithmName", signatureAlgorithmName);
+ }
+
+ CertificateExtensions extensions = null;
+
+ try {
+ extensions = (CertificateExtensions) certInfo[0].get(X509CertInfo.EXTENSIONS);
+ } catch (Exception e) {
+ }
+ if (extensions != null) {
+ Enumeration<Extension> exts = extensions.getAttributes();
+
+ while (exts.hasMoreElements()) {
+ Extension ext = exts.nextElement();
+
+ // only know about ns cert type
+ if (ext instanceof NSCertTypeExtension) {
+ NSCertTypeExtension nsExtensions =
+ (NSCertTypeExtension) ext;
+
+ try {
+ arg.addStringValue("ext_" + NSCertTypeExtension.SSL_SERVER,
+ nsExtensions.get(NSCertTypeExtension.SSL_SERVER).toString());
+
+ arg.addStringValue("ext_" + NSCertTypeExtension.SSL_CLIENT,
+ nsExtensions.get(NSCertTypeExtension.SSL_CLIENT).toString());
+
+ arg.addStringValue("ext_" + NSCertTypeExtension.EMAIL,
+ nsExtensions.get(NSCertTypeExtension.EMAIL).toString());
+
+ arg.addStringValue("ext_" + NSCertTypeExtension.OBJECT_SIGNING,
+ nsExtensions.get(NSCertTypeExtension.OBJECT_SIGNING).toString());
+
+ arg.addStringValue("ext_" + NSCertTypeExtension.SSL_CA,
+ nsExtensions.get(NSCertTypeExtension.SSL_CA).toString());
+
+ arg.addStringValue("ext_" + NSCertTypeExtension.EMAIL_CA,
+ nsExtensions.get(NSCertTypeExtension.EMAIL_CA).toString());
+
+ arg.addStringValue("ext_" + NSCertTypeExtension.OBJECT_SIGNING_CA,
+ nsExtensions.get(NSCertTypeExtension.OBJECT_SIGNING_CA).toString());
+
+ } catch (Exception e) {
+ }
+ } else if (ext instanceof BasicConstraintsExtension) {
+ BasicConstraintsExtension bcExt =
+ (BasicConstraintsExtension) ext;
+ Integer pathLength = null;
+ Boolean isCA = null;
+
+ try {
+ pathLength = (Integer) bcExt.get(BasicConstraintsExtension.PATH_LEN);
+ isCA = (Boolean) bcExt.get(BasicConstraintsExtension.IS_CA);
+ } catch (IOException e) {
+ }
+ if (pathLength != null)
+ arg.addIntegerValue("pathLenBasicConstraints", pathLength.intValue());
+ if (isCA != null)
+ arg.addBooleanValue("isCABasicConstraints", isCA.booleanValue());
+ } // pretty print all others.
+ else {
+ if (argSet != null) {
+ IArgBlock rr = CMS.createArgBlock();
+
+ rr.addStringValue(
+ EXT_PRETTYPRINT,
+ CMS.getExtPrettyPrint(ext, 0).toString());
+ argSet.addRepeatRecord(rr);
+ }
+ }
+ }
+
+ }
+
+ // Get the public key
+ CertificateX509Key certKey = null;
+
+ try {
+ certKey = (CertificateX509Key) certInfo[0].get(X509CertInfo.KEY);
+ } catch (IOException e) {
+ // XXX raise exception
+ } catch (CertificateException e) {
+ // XXX raise exception
+ }
+
+ X509Key key = null;
+
+ try {
+ key = (X509Key) certKey.get(CertificateX509Key.KEY);
+ } catch (IOException e) {
+ // XXX raise exception
+ }
+
+ if (key != null) {
+ arg.addStringValue("subjectPublicKeyInfo",
+ key.getAlgorithm() + " - " + key.getAlgorithmId().getOID().toString());
+ arg.addStringValue("subjectPublicKey",
+ pp.toHexString(key.getKey(), 0, 16));
+ }
+
+ // Get the validity period
+ CertificateValidity validity = null;
+
+ try {
+ validity =
+ (CertificateValidity)
+ certInfo[0].get(X509CertInfo.VALIDITY);
+ if (validity != null) {
+ long validityLength = (((Date) validity.get(CertificateValidity.NOT_AFTER)).getTime() -
+ ((Date) validity.get(CertificateValidity.NOT_BEFORE)).getTime()) / 1000;
+ arg.addLongValue("validityLength", validityLength);
+ }
+ } catch (IOException e) {
+ // XXX raise exception
+ } catch (CertificateException e) {
+ // XXX raise exception
+ }
+ }
+ }
+ }
+
+ if (name.equalsIgnoreCase(IRequest.OLD_SERIALS) && mDetails) {
+ BigInteger oldSerialNo[] = req.getExtDataInBigIntegerArray(IRequest.OLD_SERIALS);
+
+ if (oldSerialNo != null) {
+ if (argSet != null) {
+ for (int i = 0; i < oldSerialNo.length; i++) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ oldSerialNo[i], 16);
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ }
+ }
+
+ if (name.equalsIgnoreCase(IRequest.ISSUED_CERTS) && mDetails &&
+ (req.getRequestStatus() == RequestStatus.COMPLETE ||
+ req.getRequestType().equals(IRequest.GETREVOCATIONINFO_REQUEST))) {
+ X509CertImpl issuedCert[] =
+ req.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ arg.addBigIntegerValue("serialNumber", issuedCert[0].getSerialNumber(), 16);
+ // Set Serial No for 2nd certificate
+ if (issuedCert.length == 2)
+ arg.addBigIntegerValue("serialNumber2", issuedCert[1].getSerialNumber(), 16);
+ }
+ if (name.equalsIgnoreCase(IRequest.OLD_CERTS) && mDetails) {
+ X509CertImpl oldCert[] =
+ req.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ if (oldCert != null && oldCert.length > 0) {
+ arg.addBigIntegerValue("serialNumber", oldCert[0].getSerialNumber(), 16);
+ arg.addStringValue("subject", oldCert[0].getSubjectDN().toString());
+ if (req.getRequestType().equals(IRequest.GETCERTS_REQUEST)) {
+ for (int i = 0; i < oldCert.length; i++) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ oldCert[i].getSerialNumber(), 16);
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ }
+ }
+
+ if (name.equalsIgnoreCase(IRequest.CACERTCHAIN) && mDetails) {
+ byte[] certChainData = req.getExtDataInByteArray(
+ IRequest.CACERTCHAIN);
+ if (certChainData != null) {
+ CertificateChain certChain = new CertificateChain();
+ try {
+ certChain.decode(new ByteArrayInputStream(certChainData));
+
+ X509Certificate cert[] = certChain.getChain();
+
+ for (int i = 0; i < cert.length; i++) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ cert[i].getSerialNumber(), 16);
+ argSet.addRepeatRecord(rarg);
+ }
+ } catch (IOException e) {
+ // XXX
+ }
+ }
+ }
+ if (name.equalsIgnoreCase(IRequest.FINGERPRINTS) && mDetails) {
+ Hashtable<String, String> fingerprints =
+ req.getExtDataInHashtable(IRequest.FINGERPRINTS);
+
+ if (fingerprints != null) {
+ String namesAndHashes = null;
+ Enumeration<String> enumFingerprints = fingerprints.keys();
+
+ while (enumFingerprints.hasMoreElements()) {
+ String hashname = enumFingerprints.nextElement();
+ String hashvalue = fingerprints.get(hashname);
+ byte[] fingerprint = CMS.AtoB(hashvalue);
+ String ppFingerprint = pp.toHexString(fingerprint, 0);
+
+ if (hashname != null && ppFingerprint != null) {
+ if (namesAndHashes != null) {
+ namesAndHashes += "+" + hashname + "+" + ppFingerprint;
+ } else {
+ namesAndHashes = hashname + "+" + ppFingerprint;
+ }
+ }
+ }
+ if (namesAndHashes != null) {
+ arg.addStringValue("fingerprints", namesAndHashes);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * print value out nicely in request attributes.
+ */
+ protected String expandValue(String valuename, Object v) {
+ try {
+ String valstr = "";
+
+ // if it's a vector
+ if (v instanceof Vector) {
+ valstr = valuename + "= new Array";
+ int j = 0;
+
+ StringBuffer sb = new StringBuffer();
+ for (@SuppressWarnings("unchecked")
+ Enumeration<String> n = ((Vector<String>) v).elements(); n.hasMoreElements(); j++) {
+ sb.append(";\n");
+ sb.append(valuename);
+ sb.append(LB);
+ sb.append(j);
+ sb.append(RB);
+ sb.append(EQ);
+ sb.append("\"");
+ sb.append(
+ CMSTemplate.escapeJavaScriptStringHTML(
+ n.nextElement().toString()));
+ sb.append("\";\n");
+ }
+ sb.append("\n");
+ valstr = sb.toString();
+ return valstr;
+ }
+
+ // if an array.
+ int len = -1;
+
+ try {
+ len = Array.getLength(v);
+ } catch (IllegalArgumentException e) {
+ }
+ if (len >= 0) { // is an array; access each object in array.
+ valstr = valuename + "= new Array";
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (Array.get(v, i) != null)
+ valstr += ";\n" + valuename + LB + i + RB + EQ + "\"" +
+ CMSTemplate.escapeJavaScriptStringHTML(
+ Array.get(v, i).toString()) + "\";\n";
+ }
+ return valstr;
+ }
+ } catch (Throwable e) {
+ }
+
+ // if string or unrecognized type, just call its toString method.
+ return valuename + "=\"" +
+ CMSTemplate.escapeJavaScriptStringHTML(v.toString()) + "\"";
+ }
+
+ public String getRequestorDN(IRequest request) {
+ try {
+ X509CertInfo info = request.getExtDataInCertInfo(IEnrollProfile.REQUEST_CERTINFO);
+ // retrieve the subject name
+ CertificateSubjectName sn = (CertificateSubjectName)
+ info.get(X509CertInfo.SUBJECT);
+
+ return sn.toString();
+ } catch (Exception e) {
+ CMS.debug("CertReqParser: getRequestorDN " + e.toString());
+ }
+ return null;
+ }
+
+ public String getKeyID(IRequest request) {
+ try {
+ String kid = null;
+
+ String cid = request.getExtDataInString(IRequest.NETKEY_ATTR_CUID);
+ if (cid == null) {
+ cid = "";
+ }
+ String uid = request.getExtDataInString(IRequest.NETKEY_ATTR_USERID);
+ if (uid == null) {
+ uid = "";
+ }
+ kid = cid + ":" + uid;
+ if (kid.equals(":")) {
+ kid = "";
+ }
+
+ return kid;
+ } catch (Exception e) {
+ CMS.debug("CertReqParser: getKeyID " + e.toString());
+ }
+ return null;
+ }
+
+ private void fillRevokeRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg)
+ throws EBaseException {
+ // fill in the standard attributes
+ super.fillRequestIntoArg(l, req, argSet, arg);
+
+ arg.addStringValue("certExtsEnabled", "yes");
+ String profile = req.getExtDataInString("profile");
+
+ //CMS.debug("CertReqParser: profile=" + profile);
+ if (profile != null) {
+ arg.addStringValue("profile", profile);
+ String requestorDN = getRequestorDN(req);
+
+ if (requestorDN != null) {
+ arg.addStringValue("subject", requestorDN);
+ }
+ } else {
+ arg.addStringValue("profile", "false");
+ String keyID = getKeyID(req);
+
+ if (keyID != null) {
+ arg.addStringValue("subject", keyID);
+ }
+ }
+
+ int saCounter = 0;
+ Enumeration<String> enum1 = req.getExtDataKeys();
+
+ // gross hack
+ String prefix = "record.";
+
+ if (argSet.getHeader() == arg)
+ prefix = "header.";
+
+ while (enum1.hasMoreElements()) {
+ String name = enum1.nextElement();
+
+ if (mDetails) {
+ // show all http parameters stored in request.
+ if (name.equalsIgnoreCase(IRequest.HTTP_PARAMS)) {
+ Hashtable<String, String> http_params = req.getExtDataInHashtable(name);
+ // show certType specially
+ String certType = http_params.get(IRequest.CERT_TYPE);
+
+ if (certType != null) {
+ arg.addStringValue(IRequest.CERT_TYPE, certType);
+ }
+ // show all http parameters in request
+ int counter = 0;
+ Enumeration<String> elms = http_params.keys();
+
+ while (elms.hasMoreElements()) {
+ String parami =
+ IRequest.HTTP_PARAMS + LB + String.valueOf(counter++) + RB;
+ // hack
+ String n = elms.nextElement();
+ String rawJS = "new Object;\n\r" +
+ prefix + parami + ".name=\"" +
+ CMSTemplate.escapeJavaScriptString(n) + "\";\n\r" +
+ prefix + parami + ".value=\"" +
+ CMSTemplate.escapeJavaScriptStringHTML(
+ http_params.get(n).toString()) + "\"";
+
+ arg.set(parami, new RawJS(rawJS));
+ }
+ } // show all http headers stored in request.
+ else if (name.equalsIgnoreCase(IRequest.HTTP_HEADERS)) {
+ Hashtable<String, String> http_hdrs = req.getExtDataInHashtable(name);
+ Enumeration<String> elms = http_hdrs.keys();
+ int counter = 0;
+
+ while (elms.hasMoreElements()) {
+ String parami =
+ IRequest.HTTP_HEADERS + LB + String.valueOf(counter++) + RB;
+ // hack
+ String n = elms.nextElement();
+ String rawJS = "new Object;\n\r" +
+ prefix + parami + ".name=\"" +
+ CMSTemplate.escapeJavaScriptString(n) + "\";\n\r" +
+ prefix + parami + ".value=\"" +
+ CMSTemplate.escapeJavaScriptStringHTML(
+ http_hdrs.get(n).toString()) + "\"";
+
+ arg.set(parami, new RawJS(rawJS));
+ }
+ } // show all auth token stored in request.
+ else if (name.equalsIgnoreCase(IRequest.AUTH_TOKEN)) {
+ IAuthToken auth_token = req.getExtDataInAuthToken(name);
+ Enumeration<String> elms = auth_token.getElements();
+ int counter = 0;
+
+ while (elms.hasMoreElements()) {
+ String parami =
+ IRequest.AUTH_TOKEN + LB + String.valueOf(counter++) + RB;
+ // hack
+ String n = elms.nextElement();
+ String v =
+ expandValue(prefix + parami + ".value",
+ auth_token.getInString(n));
+ String rawJS = "new Object;\n\r" +
+ prefix + parami + ".name=\"" +
+ CMSTemplate.escapeJavaScriptString(n) + "\";\n" + v;
+
+ arg.set(parami, new RawJS(rawJS));
+ }
+ } // all others are request attrs from policy or internal modules.
+ else {
+ Object val;
+ if (req.isSimpleExtDataValue(name)) {
+ val = req.getExtDataInString(name);
+ } else {
+ val = req.getExtDataInStringArray(name);
+ if (val == null) {
+ val = req.getExtDataInHashtable(name);
+ }
+ }
+ String valstr = "";
+ // hack
+ String parami =
+ IRequest.SERVER_ATTRS + LB + String.valueOf(saCounter++) + RB;
+
+ valstr = expandValue(prefix + parami + ".value", val);
+ String rawJS = "new Object;\n\r" +
+ prefix + parami + ".name=\"" +
+ CMSTemplate.escapeJavaScriptString(name) + "\";\n" +
+ valstr; // java string already escaped in expandValue.
+
+ arg.set(parami, new RawJS(rawJS));
+ }
+ }
+
+ if (name.equalsIgnoreCase(IRequest.REQUESTOR_PHONE)
+ || name.equalsIgnoreCase(IRequest.REQUESTOR_EMAIL)
+ || name.equalsIgnoreCase(IRequest.REQUESTOR_COMMENTS)
+ || name.equalsIgnoreCase(IRequest.RESULT)
+ || name.equalsIgnoreCase(IRequest.REQUEST_TRUSTEDMGR_PRIVILEGE)) {
+ arg.addStringValue(name, req.getExtDataInString(name));
+ }
+
+ if (name.equalsIgnoreCase(IRequest.REQUESTOR_NAME)) {
+ String requestorName = req.getExtDataInString(name);
+
+ requestorName = requestorName.trim();
+ if (requestorName.length() > 0) {
+ arg.addStringValue(name, requestorName);
+ }
+ }
+
+ if (name.equalsIgnoreCase(IRequest.ERRORS)) {
+ Vector<String> errorsVector = req.getExtDataInStringVector(name);
+ if (errorsVector != null) {
+ StringBuffer errInfo = new StringBuffer();
+
+ for (int i = 0; i < errorsVector.size(); i++) {
+ errInfo.append(errorsVector.elementAt(i));
+ errInfo.append("\n");
+ }
+ arg.addStringValue(IRequest.ERRORS, errInfo.toString());
+ }
+ }
+ if (name.equalsIgnoreCase(IRequest.ERROR)) {
+ arg.addStringValue(IRequest.ERRORS, req.getExtDataInString(name));
+ }
+
+ if (name.equalsIgnoreCase(IRequest.CERT_INFO)) {
+ // Get the certificate info from the request
+ RevokedCertImpl revokedCert[] = req.getExtDataInRevokedCertArray(IRequest.CERT_INFO);
+
+ if (mDetails && revokedCert != null) {
+ if (argSet != null) {
+ for (int i = 0; i < revokedCert.length; i++) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ revokedCert[i].getSerialNumber(), 16);
+
+ CRLExtensions crlExtensions = revokedCert[i].getExtensions();
+
+ if (crlExtensions != null) {
+ for (int k = 0; k < crlExtensions.size(); k++) {
+ Extension ext = crlExtensions.elementAt(k);
+
+ if (ext instanceof CRLReasonExtension) {
+ rarg.addStringValue("reason",
+ ((CRLReasonExtension) ext).getReason().toString());
+ }
+ }
+ } else {
+ rarg.addStringValue("reason",
+ RevocationReason.UNSPECIFIED.toString());
+ }
+
+ argSet.addRepeatRecord(rarg);
+ }
+ } else {
+ arg.addBigIntegerValue("serialNumber",
+ revokedCert[0].getSerialNumber(), 16);
+ }
+ }
+ }
+
+ if (name.equalsIgnoreCase(IRequest.OLD_SERIALS) && mDetails) {
+ BigInteger oldSerialNo[] = req.getExtDataInBigIntegerArray(IRequest.OLD_SERIALS);
+
+ if (oldSerialNo != null) {
+ if (argSet != null) {
+ for (int i = 0; i < oldSerialNo.length; i++) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ oldSerialNo[i], 16);
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ }
+ }
+
+ if (name.equalsIgnoreCase(IRequest.OLD_CERTS) && mDetails) {
+ //X509CertImpl oldCert[] =
+ // (X509CertImpl[])req.get(IRequest.OLD_CERTS);
+ Certificate oldCert[] =
+ req.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ if (oldCert != null && oldCert.length > 0) {
+ if (oldCert[0] instanceof X509CertImpl) {
+ X509CertImpl xcert = (X509CertImpl) oldCert[0];
+
+ arg.addBigIntegerValue("serialNumber", xcert.getSerialNumber(), 16);
+ arg.addStringValue("subject", xcert.getSubjectDN().toString());
+ if (req.getRequestType().equals(IRequest.GETCERTS_REQUEST)) {
+ for (int i = 0; i < oldCert.length; i++) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ xcert = (X509CertImpl) oldCert[i];
+ rarg.addBigIntegerValue("serialNumber",
+ xcert.getSerialNumber(), 16);
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ }
+ }
+ }
+
+ if (name.equalsIgnoreCase(IRequest.REVOKED_CERTS) && mDetails &&
+ req.getRequestType().equals("getRevocationInfo")) {
+ RevokedCertImpl revokedCert[] =
+ req.getExtDataInRevokedCertArray(IRequest.REVOKED_CERTS);
+
+ if (revokedCert != null && revokedCert[0] != null) {
+ boolean reasonFound = false;
+ CRLExtensions crlExtensions = revokedCert[0].getExtensions();
+
+ for (int k = 0; k < crlExtensions.size(); k++) {
+ Extension ext = crlExtensions.elementAt(k);
+
+ if (ext instanceof CRLReasonExtension) {
+ arg.addStringValue("reason",
+ ((CRLReasonExtension) ext).getReason().toString());
+ reasonFound = true;
+ }
+ }
+ if (reasonFound == false) {
+ arg.addStringValue("reason", "unknown");
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/CertRequestService.java b/base/server/cms/src/com/netscape/cms/servlet/request/CertRequestService.java
new file mode 100644
index 000000000..dd3065427
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/CertRequestService.java
@@ -0,0 +1,368 @@
+// --- 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) 2011 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.request;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.UriInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.authorization.EAuthzException;
+import com.netscape.certsrv.base.BadRequestDataException;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.base.UnauthorizedException;
+import com.netscape.certsrv.cert.CertEnrollmentRequest;
+import com.netscape.certsrv.cert.CertRequestInfo;
+import com.netscape.certsrv.cert.CertRequestInfos;
+import com.netscape.certsrv.cert.CertRequestResource;
+import com.netscape.certsrv.cert.CertReviewResponse;
+import com.netscape.certsrv.profile.EDeferException;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.profile.ProfileAttribute;
+import com.netscape.certsrv.profile.ProfileDataInfo;
+import com.netscape.certsrv.profile.ProfileDataInfos;
+import com.netscape.certsrv.profile.ProfileInput;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestNotFoundException;
+import com.netscape.cms.servlet.base.PKIService;
+import com.netscape.cms.servlet.cert.CertRequestDAO;
+import com.netscape.cms.servlet.profile.ProfileService;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+/**
+ * @author alee
+ *
+ */
+public class CertRequestService extends PKIService implements CertRequestResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public static final int DEFAULT_START = 0;
+ public static final int DEFAULT_PAGESIZE = 20;
+ public static final int DEFAULT_MAXRESULTS = 100;
+ public static final int DEFAULT_MAXTIME = 10;
+
+ /**
+ * Used to retrieve key request info for a specific request
+ */
+ public CertRequestInfo getRequestInfo(RequestId id) {
+ // auth and authz
+ CertRequestInfo info;
+
+ CertRequestDAO dao = new CertRequestDAO();
+ try {
+ info = dao.getRequest(id, uriInfo);
+ } catch (EBaseException e) {
+ // log error
+ e.printStackTrace();
+ throw new PKIException("Error getting Cert request info!");
+ }
+
+ if (info == null) {
+ // request does not exist
+ throw new RequestNotFoundException(id);
+ }
+
+ return info;
+ }
+
+ // Enrollment - used to test integration with a browser
+ public CertRequestInfos enrollCert(MultivaluedMap<String, String> form) {
+ CertEnrollmentRequest data = new CertEnrollmentRequest(form);
+ return enrollCert(data);
+ }
+
+ public CertRequestInfos enrollCert(CertEnrollmentRequest data) {
+ CertRequestInfos infos;
+ if (data == null) {
+ throw new BadRequestException("Bad data input into CertRequestResourceService.enrollCert!");
+ }
+ CertRequestDAO dao = new CertRequestDAO();
+
+ try {
+ infos = dao.submitRequest(data, servletRequest, uriInfo, getLocale(headers));
+ } catch (EAuthException e) {
+ CMS.debug("enrollCert: authentication failed: " + e);
+ throw new UnauthorizedException(e.toString());
+ } catch (EAuthzException e) {
+ CMS.debug("enrollCert: authorization failed: " + e);
+ throw new UnauthorizedException(e.toString());
+ } catch (BadRequestDataException e) {
+ CMS.debug("enrollCert: bad request data: " + e);
+ throw new BadRequestException(e.toString());
+ } catch (EBaseException e) {
+ throw new PKIException(e.toString());
+ }
+
+ return infos;
+ }
+
+ public void approveRequest(RequestId id, CertReviewResponse data) {
+ changeRequestState(id, data, "approve");
+ }
+
+ public void rejectRequest(RequestId id, CertReviewResponse data) {
+ changeRequestState(id, data, "reject");
+ }
+
+ public void cancelRequest(RequestId id, CertReviewResponse data) {
+ changeRequestState(id, data, "cancel");
+ }
+
+ public void updateRequest(RequestId id, CertReviewResponse data) {
+ changeRequestState(id, data, "update");
+ }
+
+ public void validateRequest(RequestId id, CertReviewResponse data) {
+ changeRequestState(id, data, "validate");
+ }
+
+ public void unassignRequest(RequestId id, CertReviewResponse data) {
+ changeRequestState(id, data, "unassign");
+ }
+
+ public void assignRequest(RequestId id, CertReviewResponse data) {
+ changeRequestState(id, data, "assign");
+ }
+
+ public void changeRequestState(RequestId id, CertReviewResponse data, String op) {
+ if (id == null) {
+ throw new BadRequestException("Bad data input in CertRequestResourceService. op:" + op);
+ }
+ CertRequestDAO dao = new CertRequestDAO();
+ try {
+ dao.changeRequestState(id, servletRequest, data, getLocale(headers), op);
+ } catch (ERejectException e) {
+ CMS.debug("changeRequestState: execution rejected " + e);
+ throw new BadRequestException(CMS.getUserMessage(getLocale(headers), "CMS_PROFILE_REJECTED", e.toString()));
+ } catch (EDeferException e) {
+ CMS.debug("changeRequestState: execution defered " + e);
+ // TODO do we throw an exception here?
+ throw new BadRequestException(CMS.getUserMessage(getLocale(headers), "CMS_PROFILE_DEFERRED", e.toString()));
+ } catch (BadRequestDataException e) {
+ CMS.debug("changeRequestState: bad request data: " + e);
+ throw new BadRequestException(e.toString());
+ } catch (EPropertyException e) {
+ CMS.debug("changeRequestState: execution error " + e);
+ throw new PKIException(CMS.getUserMessage(getLocale(headers),
+ "CMS_PROFILE_PROPERTY_ERROR", e.toString()));
+ } catch (EProfileException e) {
+ CMS.debug("ProfileProcessServlet: execution error " + e);
+ throw new PKIException(CMS.getUserMessage(getLocale(headers), "CMS_INTERNAL_ERROR"));
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ throw new PKIException("Problem approving request in CertRequestResource.assignRequest! " + e);
+ } catch (RequestNotFoundException e) {
+ CMS.debug(e);
+ throw new BadRequestException(CMS.getUserMessage(getLocale(headers), "CMS_REQUEST_NOT_FOUND", id.toString()));
+ }
+ }
+
+ public CertReviewResponse reviewRequest(@PathParam("id") RequestId id) {
+ // auth and authz
+ CertReviewResponse info;
+
+ CertRequestDAO dao = new CertRequestDAO();
+ try {
+ info = dao.reviewRequest(servletRequest, id, uriInfo, getLocale(headers));
+ } catch (EBaseException e) {
+ // log error
+ e.printStackTrace();
+ throw new PKIException("Error getting Cert request info!");
+ }
+
+ if (info == null) {
+ // request does not exist
+ throw new RequestNotFoundException(id);
+ }
+
+ return info;
+ }
+
+ /**
+ * Used to generate list of cert requests based on the search parameters
+ */
+ public CertRequestInfos listRequests(String requestState, String requestType,
+ RequestId start, Integer pageSize, Integer maxResults, Integer maxTime) {
+ // auth and authz
+
+ // get ldap filter
+ String filter = createSearchFilter(requestState, requestType);
+ CMS.debug("listRequests: filter is " + filter);
+
+ start = start == null ? new RequestId(CertRequestService.DEFAULT_START) : start;
+ pageSize = pageSize == null ? DEFAULT_PAGESIZE : pageSize;
+ maxResults = maxResults == null ? DEFAULT_MAXRESULTS : maxResults;
+ maxTime = maxTime == null ? DEFAULT_MAXTIME : maxTime;
+
+ CertRequestDAO reqDAO = new CertRequestDAO();
+ CertRequestInfos requests;
+ try {
+ requests = reqDAO.listRequests(filter, start, pageSize, maxResults, maxTime, uriInfo);
+ } catch (EBaseException e) {
+ CMS.debug("listRequests: error in obtaining request results" + e);
+ e.printStackTrace();
+ throw new PKIException("Error listing cert requests!");
+ }
+ return requests;
+ }
+
+ private String createSearchFilter(String requestState, String requestType) {
+ String filter = "";
+ int matches = 0;
+
+ if ((requestState == null) && (requestType == null)) {
+ filter = "(requeststate=*)";
+ return filter;
+ }
+
+ if (requestState != null) {
+ filter += "(requeststate=" + LDAPUtil.escapeFilter(requestState) + ")";
+ matches++;
+ }
+
+ if (requestType != null) {
+ filter += "(requesttype=" + LDAPUtil.escapeFilter(requestType) + ")";
+ matches++;
+ }
+
+ if (matches > 1) {
+ filter = "(&" + filter + ")";
+ }
+
+ return filter;
+ }
+
+ @Override
+ public CertEnrollmentRequest getEnrollmentTemplate(String profileId) {
+ IProfileSubsystem ps = (IProfileSubsystem) CMS.getSubsystem(IProfileSubsystem.ID);
+ if (ps == null) {
+ CMS.debug("getEnrollmentTemplate: ps is null");
+ throw new PKIException("Error modifying profile state. Profile Service not available");
+ }
+
+ if (profileId == null) {
+ CMS.debug("getEnrollmenTemplate: invalid request. profileId is null");
+ throw new BadRequestException("Invalid ProfileId");
+ }
+
+ IProfile profile = null;
+ try {
+ profile = ps.getProfile(profileId);
+ if (profile == null) {
+ throw new BadRequestException("Cannot provide enrollment template for profile `" + profileId +
+ "`. Profile not found");
+ }
+ } catch (EBaseException e) {
+ CMS.debug("getEnrollmentTemplate(): error obtaining profile `" + profileId + "`: " + e);
+ e.printStackTrace();
+ throw new PKIException("Error generating enrollment template. Cannot obtain profile.");
+ }
+
+ if (! profile.isVisible()) {
+ CMS.debug("getEnrollmentTemplate(): attempt to get enrollment template for non-visible profile");
+ throw new BadRequestException("Cannot provide enrollment template for profile `" + profileId +
+ "`. Profile not marked as visible");
+ }
+
+ CertEnrollmentRequest request = new CertEnrollmentRequest();
+ request.setProfileId(profileId);
+ request.setRenewal(Boolean.parseBoolean(profile.isRenewal()));
+ request.setRemoteAddr("");
+ request.setRemoteHost("");
+ request.setSerialNum("");
+
+ // populate inputs
+ Enumeration<String> inputIds = profile.getProfileInputIds();
+ while (inputIds.hasMoreElements()) {
+ String id = inputIds.nextElement();
+ try {
+ ProfileInput input = ProfileService.createProfileInput(profile, id, getLocale(headers));
+ for (ProfileAttribute attr: input.getAttrs()) {
+ attr.setValue("");
+ }
+ request.addInput(input);
+ } catch (EBaseException e) {
+ CMS.debug("getEnrollmentTemplate(): Failed to add input " + id + " to request template: " + e);
+ e.printStackTrace();
+ throw new PKIException("Failed to add input" + id + "to request template");
+ }
+ }
+
+ return request;
+ }
+
+ @Override
+ public ProfileDataInfos listEnrollmentTemplates() {
+ IProfileSubsystem ps = (IProfileSubsystem) CMS.getSubsystem(IProfileSubsystem.ID);
+ List<ProfileDataInfo> list = new ArrayList<ProfileDataInfo>();
+ ProfileDataInfos infos = new ProfileDataInfos();
+ boolean visibleOnly = true;
+
+ if (ps == null) {
+ return null;
+ }
+
+ Enumeration<String> profileIds = ps.getProfileIds();
+ if (profileIds != null) {
+ while (profileIds.hasMoreElements()) {
+ String id = profileIds.nextElement();
+ ProfileDataInfo info = null;
+ try {
+ info = ProfileService.createProfileDataInfo(id, visibleOnly, uriInfo, getLocale(headers));
+ } catch (EBaseException e) {
+ continue;
+ }
+
+ if (info != null) {
+ list.add(info);
+ }
+ }
+ }
+
+ infos.setProfileInfos(list);
+ return infos;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/CheckRequest.java b/base/server/cms/src/com/netscape/cms/servlet/request/CheckRequest.java
new file mode 100644
index 000000000..246cefd8c
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/CheckRequest.java
@@ -0,0 +1,618 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.request;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.pkcs.PKCS7;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
+import org.mozilla.jss.asn1.OCTET_STRING;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.asn1.SET;
+import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.crypto.SignatureAlgorithm;
+import org.mozilla.jss.pkix.cmc.CMCStatusInfo;
+import org.mozilla.jss.pkix.cmc.PKIData;
+import org.mozilla.jss.pkix.cmc.ResponseBody;
+import org.mozilla.jss.pkix.cmc.TaggedAttribute;
+import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo;
+import org.mozilla.jss.pkix.cms.IssuerAndSerialNumber;
+import org.mozilla.jss.pkix.cms.SignedData;
+import org.mozilla.jss.pkix.cms.SignerIdentifier;
+import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier;
+import org.mozilla.jss.pkix.primitive.Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Check the status of a certificate request
+ *
+ * @version $Revision$, $Date$
+ */
+public class CheckRequest extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2791195859767119636L;
+ // constants
+ public static String FULL_RESPONSE = "cmcFullEnrollmentResponse";
+ private final static String REQ_ID = "requestId";
+ private final static String STATUS = "status";
+ private final static String CREATE_ON = "createdOn";
+ private final static String UPDATE_ON = "updatedOn";
+
+ private final static String TPL_FILE = "requestStatus.template";
+
+ // variables
+ private IRequestQueue mQueue = null;
+ private String mFormPath = null;
+ private String mAuthorityId = null;
+
+ public CMSRequest newCMSRequest() {
+ return new CMSRequest();
+ }
+
+ /**
+ * Constructs request query servlet.
+ */
+ public CheckRequest()
+ throws EBaseException {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "requestStatus.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mQueue = mAuthority.getRequestQueue();
+ mAuthorityId = mAuthority.getId();
+ mFormPath = "/" + mAuthorityId + "/" + TPL_FILE;
+
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param requestId ID of the request to check
+ * <li>http.param format if 'id', then check the request based on the request ID parameter. If set to CMC, then use
+ * the 'queryPending' parameter.
+ * <li>http.param queryPending query formatted as a CMC request
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ CMS.debug("checkRequest: in process!");
+ SET transIds = null, sNonces = null;
+ boolean isCMCReq = false;
+ INTEGER bodyPartId = null;
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ // Note error is covered in the same template as success.
+ EBaseException error = null;
+
+ String requestId = req.getParameter("requestId");
+ String format = req.getParameter("format");
+
+ CMS.debug("checkRequest: requestId " + requestId);
+
+ // They may check the status using CMC queryPending
+ String queryPending = req.getParameter("queryPending");
+
+ if (format != null && format.equals("cmc") && queryPending != null && !queryPending.equals("")) {
+ try {
+ isCMCReq = true;
+ byte[] cmcBlob = CMS.AtoB(queryPending);
+ ByteArrayInputStream cmcBlobIn =
+ new ByteArrayInputStream(cmcBlob);
+
+ org.mozilla.jss.pkix.cms.ContentInfo cii = (org.mozilla.jss.pkix.cms.ContentInfo)
+ org.mozilla.jss.pkix.cms.ContentInfo.getTemplate().decode(cmcBlobIn);
+ SignedData cmcFullReq = (SignedData)
+ cii.getInterpretedContent();
+
+ EncapsulatedContentInfo ci = cmcFullReq.getContentInfo();
+
+ OBJECT_IDENTIFIER id = ci.getContentType();
+
+ if (!id.equals(OBJECT_IDENTIFIER.id_cct_PKIData) || !ci.hasContent()) {
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_PKIDATA"));
+ }
+ OCTET_STRING content = ci.getContent();
+ ByteArrayInputStream s = new ByteArrayInputStream(content.toByteArray());
+ PKIData pkiData = (PKIData) (new PKIData.Template()).decode(s);
+
+ SEQUENCE controlSequence = pkiData.getControlSequence();
+ int numControls = controlSequence.size();
+
+ for (int i = 0; i < numControls; i++) {
+ // decode message.
+ TaggedAttribute taggedAttr = (TaggedAttribute) controlSequence.elementAt(i);
+ OBJECT_IDENTIFIER type = taggedAttr.getType();
+
+ if (type.equals(OBJECT_IDENTIFIER.id_cmc_QueryPending)) {
+ bodyPartId = taggedAttr.getBodyPartID();
+ SET requestIds = taggedAttr.getValues();
+ int numReq = requestIds.size();
+
+ // We only process one for now.
+ if (numReq > 0) {
+ OCTET_STRING reqId = (OCTET_STRING)
+ ASN1Util.decode(OCTET_STRING.getTemplate(),
+ ASN1Util.encode(requestIds.elementAt(0)));
+
+ requestId = new String(reqId.toByteArray());
+ }
+ } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_transactionId)) {
+ transIds = taggedAttr.getValues();
+ } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_recipientNonce)) {
+ // recipient nonce
+ } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_senderNonce)) {
+ sNonces = taggedAttr.getValues();
+ }
+ }
+ } catch (Exception e) {
+ error = new EBaseException(e.toString());
+ }
+ }
+
+ IArgBlock httpParams = cmsReq.getHttpParams();
+ boolean importCert = httpParams.getValueAsBoolean("importCert",
+ false);
+ // xxx need to check why this is not available at startup
+ X509Certificate mCACerts[] = null;
+
+ try {
+ mCACerts = ((ICertAuthority) mAuthority).getCACertChain().getChain();
+ } catch (Exception e) {
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_CA_CHAIN_NOT_AVAILABLE"));
+ }
+
+ if (requestId == null || requestId.trim().equals("")) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_NO_REQUEST_ID_PROVIDED"));
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_REQUEST_ID_PROVIDED"));
+ }
+ try {
+ new BigInteger(requestId);
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT_1", requestId));
+ throw new EBaseException(
+ CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT_1", requestId));
+ }
+
+ IRequest r = mQueue.findRequest(new RequestId(requestId));
+
+ if (r == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_REQUEST_ID_NOT_FOUND_1", requestId));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_REQUEST_ID_NOT_FOUND", requestId));
+ }
+
+ if (authToken != null) {
+ // if RA, requestOwner must match the group
+ String group = authToken.getInString("group");
+ if ((group != null) && (group != "")) {
+ if (group.equals("Registration Manager Agents")) {
+ boolean groupMatched = false;
+ String requestOwner = r.getExtDataInString("requestOwner");
+ if (requestOwner != null) {
+ if (requestOwner.equals(group))
+ groupMatched = true;
+ }
+ if (groupMatched == false) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT_1", requestId.toString()));
+ throw new EBaseException(
+ CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT_1", requestId));
+ }
+ }
+ }
+ }
+
+ RequestStatus status = r.getRequestStatus();
+ String note = r.getExtDataInString("requestNotes");
+
+ header.addStringValue("authority", mAuthorityId);
+ header.addStringValue(REQ_ID, r.getRequestId().toString());
+ header.addStringValue(STATUS, status.toString());
+ header.addLongValue(CREATE_ON, r.getCreationTime().getTime() / 1000);
+ header.addLongValue(UPDATE_ON, r.getModificationTime().getTime() / 1000);
+ if (note != null && note.length() > 0)
+ header.addStringValue("requestNotes", note);
+
+ String type = r.getRequestType();
+ Integer result = r.getExtDataInInteger(IRequest.RESULT);
+
+ /* if (type.equals(IRequest.ENROLLMENT_REQUEST) && (r.get("profile") != null) && status.equals(RequestStatus.COMPLETE)) {
+ X509CertImpl cert = (X509CertImpl) r.get(IEnrollProfile.REQUEST_ISSUED_CERT);
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ cert.getSerialNumber(), 16);
+ argSet.addRepeatRecord(rarg);
+ }
+ */
+ String profileId = r.getExtDataInString("profileId");
+ if (profileId != null) {
+ result = IRequest.RES_SUCCESS;
+ }
+ if ((type != null) && (type.equals(IRequest.ENROLLMENT_REQUEST) ||
+ type.equals(IRequest.RENEWAL_REQUEST)) && (status != null) &&
+ status.equals(RequestStatus.COMPLETE) && (result != null) &&
+ result.equals(IRequest.RES_SUCCESS)) {
+ Object o = r.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ if (profileId != null) {
+ X509CertImpl impl[] = new X509CertImpl[1];
+ impl[0] = r.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
+ o = impl;
+ }
+ if (o != null && (o instanceof X509CertImpl[])) {
+ X509CertImpl[] certs = (X509CertImpl[]) o;
+
+ if (certs != null && certs.length > 0) {
+ for (int i = 0; i < certs.length; i++) {
+ if (certs[i] != null) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addBigIntegerValue("serialNumber",
+ certs[i].getSerialNumber(), 16);
+ // add pkcs7 cert for importing
+ if (importCert || isCMCReq) {
+ //byte[] ba = certs[i].getEncoded();
+ X509CertImpl[] certsInChain = new X509CertImpl[1];
+ ;
+ if (mCACerts != null) {
+ for (int ii = 0; ii < mCACerts.length; ii++) {
+ if (certs[i].equals(mCACerts[ii])) {
+ certsInChain = new
+ X509CertImpl[mCACerts.length];
+ break;
+ }
+ certsInChain = new X509CertImpl[mCACerts.length + 1];
+ }
+ }
+
+ // Set the EE cert
+ certsInChain[0] = certs[i];
+
+ // Set the Ca certificate chain
+ if (mCACerts != null) {
+ for (int ii = 0; ii < mCACerts.length; ii++) {
+ if (!certs[i].equals(mCACerts[ii]))
+ certsInChain[ii + 1] = (X509CertImpl) mCACerts[ii];
+ }
+ }
+ // Wrap the chain into a degenerate P7 object
+ String p7Str;
+
+ try {
+ PKCS7 p7 = new PKCS7(new AlgorithmId[0],
+ new netscape.security.pkcs.ContentInfo(new byte[0]),
+ certsInChain,
+ new netscape.security.pkcs.SignerInfo[0]);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ p7.encodeSignedData(bos);
+ byte[] p7Bytes = bos.toByteArray();
+
+ p7Str = CMS.BtoA(p7Bytes);
+
+ StringTokenizer tokenizer = null;
+
+ if (File.separator.equals("\\")) {
+ char[] nl = new char[2];
+
+ nl[0] = 10;
+ nl[1] = 13;
+ String nlstr = new String(nl);
+
+ tokenizer = new StringTokenizer(p7Str, nlstr);
+ } else
+ tokenizer = new StringTokenizer(p7Str, "\n");
+ StringBuffer res = new StringBuffer();
+
+ while (tokenizer.hasMoreTokens()) {
+ String elem = tokenizer.nextToken();
+
+ res.append(elem);
+ }
+
+ header.addStringValue("pkcs7ChainBase64", res.toString());
+
+ // compose full response
+ if (isCMCReq) {
+ SEQUENCE controlSeq = new SEQUENCE();
+ int bpid = 1;
+ SEQUENCE bpids = new SEQUENCE();
+
+ if (bodyPartId != null)
+ bpids.addElement(bodyPartId);
+ CMCStatusInfo cmcStatusInfo = new
+ CMCStatusInfo(CMCStatusInfo.SUCCESS, bpids);
+ TaggedAttribute ta = new TaggedAttribute(new
+ INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo,
+ cmcStatusInfo);
+
+ controlSeq.addElement(ta);
+
+ // copy transactionID, senderNonce,
+ // create recipientNonce
+ if (transIds != null) {
+ ta = new TaggedAttribute(new
+ INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_transactionId,
+ transIds);
+ controlSeq.addElement(ta);
+ }
+
+ if (sNonces != null) {
+ ta = new TaggedAttribute(new
+ INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_recipientNonce,
+ sNonces);
+ controlSeq.addElement(ta);
+ }
+
+ String salt = CMSServlet.generateSalt();
+ byte[] dig;
+
+ try {
+ MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+
+ dig = SHA1Digest.digest(salt.getBytes());
+ } catch (NoSuchAlgorithmException ex) {
+ dig = salt.getBytes();
+ }
+ String b64E = CMS.BtoA(dig);
+ String[] newNonce = { b64E };
+
+ ta = new TaggedAttribute(new
+ INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_senderNonce,
+ new OCTET_STRING(newNonce[0].getBytes()));
+ controlSeq.addElement(ta);
+
+ ResponseBody rb = new ResponseBody(controlSeq, new
+ SEQUENCE(), new
+ SEQUENCE());
+ EncapsulatedContentInfo ci = new
+ EncapsulatedContentInfo(OBJECT_IDENTIFIER.id_cct_PKIResponse,
+ rb);
+
+ org.mozilla.jss.crypto.X509Certificate x509cert = null;
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ x509cert = ((ICertificateAuthority) mAuthority).getCaX509Cert();
+ } else if (mAuthority instanceof IRegistrationAuthority) {
+ x509cert = ((IRegistrationAuthority) mAuthority).getRACert();
+ }
+ if (x509cert == null)
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_CMC_ERROR",
+ "No signing cert found."));
+
+ X509CertImpl cert = new X509CertImpl(x509cert.getEncoded());
+ ByteArrayInputStream issuer1 = new
+ ByteArrayInputStream(((X500Name) cert.getIssuerDN()).getEncoded());
+ Name issuer = (Name) Name.getTemplate().decode(issuer1);
+ IssuerAndSerialNumber ias =
+ new
+ IssuerAndSerialNumber(issuer, new INTEGER(cert.getSerialNumber()
+ .toString()));
+ SignerIdentifier si = new
+ SignerIdentifier(SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null);
+
+ // SHA1 is the default digest Alg for now.
+ DigestAlgorithm digestAlg = null;
+ SignatureAlgorithm signAlg = null;
+ org.mozilla.jss.crypto.PrivateKey privKey =
+ CryptoManager.getInstance().findPrivKeyByCert(x509cert);
+ org.mozilla.jss.crypto.PrivateKey.Type keyType = privKey.getType();
+
+ if (keyType.equals(org.mozilla.jss.crypto.PrivateKey.RSA))
+ signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest;
+ else if (keyType.equals(org.mozilla.jss.crypto.PrivateKey.DSA))
+ signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest;
+ MessageDigest SHADigest = null;
+ byte[] digest = null;
+
+ try {
+ SHADigest = MessageDigest.getInstance("SHA1");
+ digestAlg = DigestAlgorithm.SHA1;
+ ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+
+ rb.encode(ostream);
+ digest = SHADigest.digest(ostream.toByteArray());
+ } catch (NoSuchAlgorithmException ex) {
+ //log("digest fail");
+ }
+
+ org.mozilla.jss.pkix.cms.SignerInfo signInfo = new
+ org.mozilla.jss.pkix.cms.SignerInfo(si, null, null,
+ OBJECT_IDENTIFIER.id_cct_PKIResponse,
+ digest, signAlg,
+ privKey);
+ SET signInfos = new SET();
+
+ signInfos.addElement(signInfo);
+
+ SET digestAlgs = new SET();
+
+ if (digestAlg != null) {
+ AlgorithmIdentifier ai = new
+ AlgorithmIdentifier(digestAlg.toOID(),
+ null);
+
+ digestAlgs.addElement(ai);
+ }
+
+ SET jsscerts = new SET();
+
+ for (int j = 0; j < certsInChain.length; j++) {
+ ByteArrayInputStream is = new
+ ByteArrayInputStream(certsInChain[j].getEncoded());
+ org.mozilla.jss.pkix.cert.Certificate certJss =
+ (org.mozilla.jss.pkix.cert.Certificate)
+ org.mozilla.jss.pkix.cert.Certificate.getTemplate().decode(is);
+
+ jsscerts.addElement(certJss);
+ }
+
+ SignedData fResponse = new
+ SignedData(digestAlgs, ci,
+ jsscerts, null, signInfos);
+ org.mozilla.jss.pkix.cms.ContentInfo fullResponse =
+ new
+ org.mozilla.jss.pkix.cms.ContentInfo(
+ org.mozilla.jss.pkix.cms.ContentInfo.SIGNED_DATA, fResponse);
+ ByteArrayOutputStream ostream = new
+ ByteArrayOutputStream();
+
+ fullResponse.encode(ostream);
+ byte[] fr = ostream.toByteArray();
+
+ header.addStringValue(FULL_RESPONSE, CMS.BtoA(fr));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_FORMING_PKCS7_1", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_FORMING_PKCS7_ERROR"));
+ }
+ }
+ argSet.addRepeatRecord(rarg);
+ }
+ }
+ }
+ }
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/IReqParser.java b/base/server/cms/src/com/netscape/cms/servlet/request/IReqParser.java
new file mode 100644
index 000000000..7731efcb4
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/IReqParser.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.request;
+
+import java.util.Locale;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+
+/**
+ * An interface representing a request parser which
+ * converts Java request object into name value
+ * pairs and vice versa.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public interface IReqParser {
+
+ /**
+ * Maps request object into argument block.
+ */
+ public void fillRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg)
+ throws EBaseException;
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/KeyReqParser.java b/base/server/cms/src/com/netscape/cms/servlet/request/KeyReqParser.java
new file mode 100644
index 000000000..9e1247520
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/KeyReqParser.java
@@ -0,0 +1,81 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.request;
+
+import java.math.BigInteger;
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.key.KeyRecordParser;
+
+/**
+ * Output a 'pretty print' of a Key Archival request
+ *
+ * @version $Revision$, $Date$
+ */
+public class KeyReqParser extends ReqParser {
+
+ public static final KeyReqParser PARSER = new KeyReqParser();
+ public static final String OUTPUT_SERIALNO = "serialNumber";
+
+ /**
+ * Constructs a certificate request parser.
+ */
+ public KeyReqParser() {
+ }
+
+ /**
+ * Fills in certificate specific request attributes.
+ */
+ public void fillRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg)
+ throws EBaseException {
+ // fill in the standard attributes
+ super.fillRequestIntoArg(l, req, argSet, arg);
+
+ String type = req.getRequestType();
+
+ if (type.equals(IRequest.ENROLLMENT_REQUEST)) {
+ BigInteger recSerialNo = req.getExtDataInBigInteger("keyRecord");
+ IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority) CMS.getSubsystem("kra");
+ if (kra != null) {
+ KeyRecordParser.fillRecordIntoArg(
+ kra.getKeyRepository().readKeyRecord(recSerialNo),
+ arg);
+ } else {
+ throw new EBaseException("KRA is not available");
+ }
+
+ } else if (type.equals(IRequest.KEYRECOVERY_REQUEST)) {
+ BigInteger kid = req.getExtDataInBigInteger("serialNumber");
+
+ arg.addStringValue(OUTPUT_SERIALNO, kid.toString());
+
+ // for async recovery
+ String agents = req.getExtDataInString("approvingAgents");
+ arg.addStringValue("approvingAgents", agents);
+ } else {
+ System.out.println("Bad Request " + type);
+ // invalid request
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/KeyRequestService.java b/base/server/cms/src/com/netscape/cms/servlet/request/KeyRequestService.java
new file mode 100644
index 000000000..8db16b51f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/KeyRequestService.java
@@ -0,0 +1,297 @@
+// --- 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) 2011 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.servlet.request;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.UriInfo;
+
+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.dbs.keydb.KeyId;
+import com.netscape.certsrv.key.KeyArchivalRequest;
+import com.netscape.certsrv.key.KeyRecoveryRequest;
+import com.netscape.certsrv.key.KeyRequestInfo;
+import com.netscape.certsrv.key.KeyRequestInfos;
+import com.netscape.certsrv.key.KeyRequestResource;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestNotFoundException;
+import com.netscape.cms.servlet.base.PKIService;
+import com.netscape.cms.servlet.key.KeyRequestDAO;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+/**
+ * @author alee
+ *
+ */
+public class KeyRequestService extends PKIService implements KeyRequestResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ private static final String LOGGING_SIGNED_AUDIT_SECURITY_DATA_ARCHIVAL_REQUEST =
+ "LOGGING_SIGNED_AUDIT_SECURITY_DATA_ARCHIVAL_REQUEST_4";
+
+ private static final String LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST =
+ "LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_4";
+
+ private static final String LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_STATE_CHANGE =
+ "LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_STATE_CHANGE_4";
+
+ public static final int DEFAULT_START = 0;
+ public static final int DEFAULT_PAGESIZE = 20;
+ public static final int DEFAULT_MAXRESULTS = 100;
+ public static final int DEFAULT_MAXTIME = 10;
+
+ /**
+ * Used to retrieve key request info for a specific request
+ */
+ public KeyRequestInfo getRequestInfo(RequestId id) {
+ // auth and authz
+ KeyRequestDAO dao = new KeyRequestDAO();
+ KeyRequestInfo info;
+ try {
+ info = dao.getRequest(id, uriInfo);
+ } catch (EBaseException e) {
+ // log error
+ e.printStackTrace();
+ throw new PKIException(e.getMessage(), e);
+ }
+ if (info == null) {
+ // request does not exist
+ throw new RequestNotFoundException(id);
+ }
+ return info;
+ }
+
+ // Archiving - used to test integration with a browser
+ public KeyRequestInfo archiveKey(MultivaluedMap<String, String> form) {
+ KeyArchivalRequest data = new KeyArchivalRequest(form);
+ return archiveKey(data);
+ }
+
+ public KeyRequestInfo archiveKey(KeyArchivalRequest data) {
+ // auth and authz
+ // Catch this before internal server processing has to deal with it
+
+ if (data == null || data.getClientId() == null
+ || data.getWrappedPrivateData() == null
+ || data.getDataType() == null) {
+ throw new BadRequestException("Invalid key archival request.");
+ }
+
+ KeyRequestDAO dao = new KeyRequestDAO();
+ KeyRequestInfo info;
+ try {
+ info = dao.submitRequest(data, uriInfo);
+ auditArchivalRequestMade(info.getRequestId(), ILogger.SUCCESS, data.getClientId());
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ auditArchivalRequestMade(null, ILogger.FAILURE, data.getClientId());
+ throw new PKIException(e.toString());
+ }
+ return info;
+ }
+
+ //Recovery - used to test integration with a browser
+ public KeyRequestInfo recoverKey(MultivaluedMap<String, String> form) {
+ KeyRecoveryRequest data = new KeyRecoveryRequest(form);
+ return recoverKey(data);
+ }
+
+ public KeyRequestInfo recoverKey(KeyRecoveryRequest data) {
+ // auth and authz
+
+ //Check for entirely illegal data combination here
+ //Catch this before the internal server processing has to deal with it
+ //If data has been provided, we need at least the wrapped session key,
+ //or the command is invalid.
+
+ if (data == null) {
+ throw new BadRequestException("Invalid request.");
+ }
+ if (data.getTransWrappedSessionKey() == null
+ && data.getSessionWrappedPassphrase() != null) {
+ throw new BadRequestException("No wrapped session key.");
+ }
+ KeyRequestDAO dao = new KeyRequestDAO();
+ KeyRequestInfo info;
+ try {
+ info = dao.submitRequest(data, uriInfo);
+ auditRecoveryRequestMade(info.getRequestId(), ILogger.SUCCESS, data.getKeyId());
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ auditRecoveryRequestMade(null, ILogger.FAILURE, data.getKeyId());
+ throw new PKIException(e.toString());
+ }
+ return info;
+ }
+
+ public void approveRequest(RequestId id) {
+ if (id == null) {
+ throw new BadRequestException("Invalid request id.");
+ }
+ // auth and authz
+ KeyRequestDAO dao = new KeyRequestDAO();
+ try {
+ dao.approveRequest(id);
+ auditRecoveryRequestChange(id, ILogger.SUCCESS, "approve");
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ auditRecoveryRequestChange(id, ILogger.FAILURE, "approve");
+ throw new PKIException(e.toString());
+ }
+ }
+
+ public void rejectRequest(RequestId id) {
+ if (id == null) {
+ throw new BadRequestException("Invalid request id.");
+ }
+ // auth and authz
+ KeyRequestDAO dao = new KeyRequestDAO();
+ try {
+ dao.rejectRequest(id);
+ auditRecoveryRequestChange(id, ILogger.SUCCESS, "reject");
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ auditRecoveryRequestChange(id, ILogger.FAILURE, "reject");
+ throw new PKIException(e.toString());
+ }
+ }
+
+ public void cancelRequest(RequestId id) {
+ if (id == null) {
+ throw new BadRequestException("Request id is null.");
+ }
+ // auth and authz
+ KeyRequestDAO dao = new KeyRequestDAO();
+ try {
+ dao.cancelRequest(id);
+ auditRecoveryRequestChange(id, ILogger.SUCCESS, "cancel");
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ auditRecoveryRequestChange(id, ILogger.FAILURE, "cancel");
+ throw new PKIException(e.toString());
+ }
+ }
+
+ /**
+ * Used to generate list of key requests based on the search parameters
+ */
+ public KeyRequestInfos listRequests(String requestState, String requestType, String clientID,
+ RequestId start, Integer pageSize, Integer maxResults, Integer maxTime) {
+ // auth and authz
+
+ // get ldap filter
+ String filter = createSearchFilter(requestState, requestType, clientID);
+ CMS.debug("listRequests: filter is " + filter);
+
+ start = start == null ? new RequestId(KeyRequestService.DEFAULT_START) : start;
+ pageSize = pageSize == null ? DEFAULT_PAGESIZE : pageSize;
+ maxResults = maxResults == null ? DEFAULT_MAXRESULTS : maxResults;
+ maxTime = maxTime == null ? DEFAULT_MAXTIME : maxTime;
+
+ KeyRequestDAO reqDAO = new KeyRequestDAO();
+ KeyRequestInfos requests;
+ try {
+ requests = reqDAO.listRequests(filter, start, pageSize, maxResults, maxTime, uriInfo);
+ } catch (EBaseException e) {
+ CMS.debug("listRequests: error in obtaining request results" + e);
+ e.printStackTrace();
+ throw new PKIException(e.toString());
+ }
+ return requests;
+ }
+
+ private String createSearchFilter(String requestState, String requestType, String clientID) {
+ String filter = "";
+ int matches = 0;
+
+ if ((requestState == null) && (requestType == null) && (clientID == null)) {
+ filter = "(requeststate=*)";
+ return filter;
+ }
+
+ if (requestState != null) {
+ filter += "(requeststate=" + LDAPUtil.escapeFilter(requestState) + ")";
+ matches ++;
+ }
+
+ if (requestType != null) {
+ filter += "(requesttype=" + LDAPUtil.escapeFilter(requestType) + ")";
+ matches ++;
+ }
+
+ if (clientID != null) {
+ filter += "(clientID=" + LDAPUtil.escapeFilter(clientID) + ")";
+ matches ++;
+ }
+
+ if (matches > 1) {
+ filter = "(&" + filter + ")";
+ }
+
+ return filter;
+ }
+
+ public void auditRecoveryRequestChange(RequestId requestId, String status, String operation) {
+ String msg = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST_STATE_CHANGE,
+ servletRequest.getUserPrincipal().getName(),
+ status,
+ requestId.toString(),
+ operation);
+ auditor.log(msg);
+ }
+
+ public void auditRecoveryRequestMade(RequestId requestId, String status, KeyId dataId) {
+ String msg = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SECURITY_DATA_RECOVERY_REQUEST,
+ servletRequest.getUserPrincipal().getName(),
+ status,
+ requestId != null? requestId.toString(): "null",
+ dataId.toString());
+ auditor.log(msg);
+ }
+
+ public void auditArchivalRequestMade(RequestId requestId, String status, String clientId) {
+ String msg = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SECURITY_DATA_ARCHIVAL_REQUEST,
+ servletRequest.getUserPrincipal().getName(),
+ status,
+ requestId != null? requestId.toString(): "null",
+ clientId);
+ auditor.log(msg);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java b/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java
new file mode 100644
index 000000000..367c558cb
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java
@@ -0,0 +1,1927 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.request;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.extensions.NSCertTypeExtension;
+import netscape.security.extensions.PresenceServerExtension;
+import netscape.security.util.DerValue;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.Extension;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.cert.ImportCertsTemplateFiller;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Agent operations on Certificate requests. This servlet is used
+ * by an Agent to approve, reject, reassign, or change a certificate
+ * request.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ProcessCertReq extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 812464895240811318L;
+ private final static String SEQNUM = "seqNum";
+ private final static String TPL_FILE = "processCertReq.template";
+
+ private IRequestQueue mQueue = null;
+ private String mFormPath = null;
+ private IReqParser mParser = null;
+ private IPublisherProcessor mPublisherProcessor = null;
+ private boolean mExtraAgentParams = false;
+
+ // for RA only since it does not have a database.
+ private final static String REQ_COMPLETED_TEMPLATE = "ra/RequestCompleted.template";
+ private final static String PROP_REQ_COMPLETED_TEMPLATE = "requestCompletedTemplate";
+ private final static String PROP_EXTRA_AGENT_PARAMS = "extraAgentParams";
+ private String mReqCompletedTemplate = null;
+
+ private String auditServiceID = ILogger.UNIDENTIFIED;
+ private final static String AGENT_CA_CLONE_ENROLLMENT_SERVLET =
+ "caProcessCertReq";
+ private final static String AGENT_RA_CLONE_ENROLLMENT_SERVLET =
+ "raProcessCertReq";
+ private final static String SIGNED_AUDIT_ACCEPTANCE = "accept";
+ private final static String SIGNED_AUDIT_CANCELLATION = "cancel";
+ private final static String SIGNED_AUDIT_CLONING = "clone";
+ private final static String SIGNED_AUDIT_REJECTION = "reject";
+ private final static byte EOL[] = { Character.LINE_SEPARATOR };
+ private final static String[] SIGNED_AUDIT_MANUAL_CANCELLATION_REASON = new String[] {
+
+ /* 0 */"manual non-profile cert request cancellation: "
+ + "request cannot be processed due to an "
+ + "authorization failure",
+
+ /* 1 */"manual non-profile cert request cancellation: "
+ + "no reason has been given for cancelling this "
+ + "cert request",
+
+ /* 2 */"manual non-profile cert request cancellation: "
+ + "indeterminate reason for inability to process "
+ + "cert request due to an EBaseException",
+
+ /* 3 */"manual non-profile cert request cancellation: "
+ + "indeterminate reason for inability to process "
+ + "cert request due to an IOException",
+
+ /* 4 */"manual non-profile cert request cancellation: "
+ + "indeterminate reason for inability to process "
+ + "cert request due to a CertificateException",
+
+ /* 5 */"manual non-profile cert request cancellation: "
+ + "indeterminate reason for inability to process "
+ + "cert request due to a NoSuchAlgorithmException"
+ };
+ private final static String[] SIGNED_AUDIT_MANUAL_REJECTION_REASON = new String[] {
+
+ /* 0 */"manual non-profile cert request rejection: "
+ + "request cannot be processed due to an "
+ + "authorization failure",
+
+ /* 1 */"manual non-profile cert request rejection: "
+ + "no reason has been given for rejecting this "
+ + "cert request",
+
+ /* 2 */"manual non-profile cert request rejection: "
+ + "indeterminate reason for inability to process "
+ + "cert request due to an EBaseException",
+
+ /* 3 */"manual non-profile cert request rejection: "
+ + "indeterminate reason for inability to process "
+ + "cert request due to an IOException",
+
+ /* 4 */"manual non-profile cert request rejection: "
+ + "indeterminate reason for inability to process "
+ + "cert request due to a CertificateException",
+
+ /* 5 */"manual non-profile cert request rejection: "
+ + "indeterminate reason for inability to process "
+ + "cert request due to a NoSuchAlgorithmException"
+ };
+ private final static String LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST =
+ "LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST_5";
+ private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED =
+ "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5";
+
+ /**
+ * Process request.
+ */
+ public ProcessCertReq()
+ throws EBaseException {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "processCertReq.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ try {
+ super.init(sc);
+
+ // determine the service ID for signed audit log messages
+ String id = sc.getInitParameter(CMSServlet.PROP_ID);
+
+ if (id != null) {
+ if (!(auditServiceID.equals(
+ AGENT_CA_CLONE_ENROLLMENT_SERVLET))
+ && !(auditServiceID.equals(
+ AGENT_RA_CLONE_ENROLLMENT_SERVLET))) {
+ auditServiceID = ILogger.UNIDENTIFIED;
+ } else {
+ auditServiceID = id.trim();
+ }
+ }
+
+ mQueue = mAuthority.getRequestQueue();
+ mPublisherProcessor =
+ ((ICertAuthority) mAuthority).getPublisherProcessor();
+
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ mParser = CertReqParser.DETAIL_PARSER;
+
+ // override success and error templates to null -
+ // handle templates locally.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+
+ try {
+ mReqCompletedTemplate = sc.getInitParameter(
+ PROP_REQ_COMPLETED_TEMPLATE);
+ if (mReqCompletedTemplate == null)
+ mReqCompletedTemplate = REQ_COMPLETED_TEMPLATE;
+ String tmp = sc.getInitParameter(PROP_EXTRA_AGENT_PARAMS);
+
+ if (tmp != null && tmp.trim().equalsIgnoreCase("true"))
+ mExtraAgentParams = true;
+ else
+ mExtraAgentParams = false;
+ } catch (Exception e) {
+ // does not happen.
+ }
+ } catch (ServletException eAudit1) {
+ // rethrow caught exception
+ throw eAudit1;
+ }
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param seqNum request id
+ * <li>http.param notValidBefore certificate validity - notBefore - in seconds since jan 1, 1970
+ * <li>http.param notValidAfter certificate validity - notAfter - in seconds since jan 1, 1970
+ * <li>http.param subject certificate subject name
+ * <li>http.param toDo requested action (can be one of: clone, reject, accept, cancel)
+ * <li>http.param signatureAlgorithm certificate signing algorithm
+ * <li>http.param addExts base-64, DER encoded Extension or SEQUENCE OF Extensions to add to certificate
+ * <li>http.param pathLenConstraint integer path length constraint to use in BasicConstraint extension if applicable
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ long startTime = CMS.getCurrentDate().getTime();
+ String toDo = null;
+ String subject = null;
+ String signatureAlgorithm = null;
+ long notValidBefore = 0;
+ long notValidAfter = 0;
+ BigInteger seqNum = BigInteger.ONE.negate();
+ EBaseException error = null;
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ try {
+ if (req.getParameter(SEQNUM) != null) {
+ CMS.debug(
+ "ProcessCertReq: parameter seqNum " + req.getParameter(SEQNUM));
+ seqNum = new BigInteger(req.getParameter(SEQNUM));
+ }
+ String notValidBeforeStr = req.getParameter("notValidBefore");
+
+ if (notValidBeforeStr != null && notValidBeforeStr.length() > 0) {
+ notValidBefore = Long.parseLong(notValidBeforeStr);
+ notValidBefore *= 1000;
+ }
+ String notValidAfterStr = req.getParameter("notValidAfter");
+
+ if (notValidAfterStr != null && notValidAfterStr.length() > 0) {
+ notValidAfter = Long.parseLong(notValidAfterStr);
+ notValidAfter *= 1000;
+ }
+
+ toDo = req.getParameter("toDo");
+
+ subject = req.getParameter("subject");
+ signatureAlgorithm = req.getParameter("signatureAlgorithm");
+
+ IRequest r = null;
+
+ if (seqNum.compareTo(BigInteger.ONE.negate()) > 0) {
+ r = mQueue.findRequest(new RequestId(seqNum));
+ }
+
+ if (seqNum.compareTo(BigInteger.ONE.negate()) > 0 && r != null) {
+ processX509(cmsReq, argSet, header, seqNum, req, resp,
+ toDo, signatureAlgorithm, subject,
+ notValidBefore, notValidAfter, locale[0], startTime);
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_REQUEST_ID_1", seqNum.toString()));
+ error = new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_REQUEST_ID",
+ seqNum.toString()));
+ }
+ } catch (EBaseException e) {
+ error = e;
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE, "Error " + e);
+ error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT"));
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ return;
+ }
+
+ /**
+ * Process X509 certificate enrollment request and send request information
+ * to the caller.
+ * <P>
+ *
+ * (Certificate Request - an "agent" cert request for "cloning")
+ * <P>
+ *
+ * (Certificate Request Processed - either a manual "agent" non-profile based cert acceptance, a manual "agent"
+ * non-profile based cert cancellation, or a manual "agent" non-profile based cert rejection)
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST used when a non-profile cert request is made
+ * (before approval process)
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been
+ * through the approval process
+ * </ul>
+ *
+ * @param cmsReq a certificate enrollment request
+ * @param argSet CMS template parameters
+ * @param header argument block
+ * @param seqNum sequence number
+ * @param req HTTP servlet request
+ * @param resp HTTP servlet response
+ * @param toDo string representing the requested action (can be one of:
+ * clone, reject, accept, cancel)
+ * @param signatureAlgorithm string containing the signature algorithm
+ * @param subject string containing the subject name of the certificate
+ * @param notValidBefore certificate validity - notBefore - in seconds
+ * since Jan 1, 1970
+ * @param notValidAfter certificate validity - notAfter - in seconds since
+ * Jan 1, 1970
+ * @param locale the system locale
+ * @param startTime the current date
+ * @exception EBaseException an error has occurred
+ */
+ private void processX509(CMSRequest cmsReq,
+ CMSTemplateParams argSet, IArgBlock header,
+ BigInteger seqNum, HttpServletRequest req,
+ HttpServletResponse resp,
+ String toDo, String signatureAlgorithm,
+ String subject,
+ long notValidBefore, long notValidAfter,
+ Locale locale, long startTime)
+ throws EBaseException {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRequesterID = ILogger.UNIDENTIFIED;
+ String auditCertificateSubjectName = subject;
+ String auditInfoName = auditInfoName(toDo);
+ String id = null;
+
+ // "normalize" the "auditCertificateSubjectName"
+ if (auditCertificateSubjectName != null) {
+ // NOTE: This is ok even if the cert subject name is "" (empty)!
+ auditCertificateSubjectName = auditCertificateSubjectName.trim();
+ } else {
+ // NOTE: Here, the cert subject name is MISSING, not "" (empty)!
+ auditCertificateSubjectName = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ try {
+ IRequest r = mQueue.findRequest(new RequestId(seqNum));
+
+ if (r != null) {
+ // overwrite "auditRequesterID" if and only if "id" != null
+ id = r.getRequestId().toString();
+ if (id != null) {
+ auditRequesterID = id.trim();
+ }
+ }
+
+ if (mAuthority != null)
+ header.addStringValue("authorityid", mAuthority.getId());
+
+ if (toDo != null) {
+ // for audit log
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "execute");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE",
+ e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE",
+ e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+
+ // store a message in the signed audit log file
+ if (toDo.equals(SIGNED_AUDIT_CLONING)) {
+ // ("agent" cert request for "cloning")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) {
+ // (manual "agent" cert request processed - "accepted")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) {
+ // (manual "agent" cert request processed - "cancelled")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[0]);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) {
+ // (manual "agent" cert request processed - "rejected")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ SIGNED_AUDIT_MANUAL_REJECTION_REASON[0]);
+
+ audit(auditMessage);
+ }
+
+ return;
+ }
+
+ String authMgr = AuditFormat.NOAUTH;
+
+ if (authToken != null) {
+ authMgr =
+ authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+ }
+ String agentID = authToken.getInString("userid");
+ String initiative = AuditFormat.FROMAGENT + " agentID: " + agentID;
+
+ // Get the certificate info from the request
+ X509CertInfo certInfo[] = r.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ header.addStringValue("toDo", toDo);
+ if (toDo.equals("accept")) {
+
+ if (certInfo != null) {
+ int alterationCounter = 0;
+
+ for (int i = 0; i < certInfo.length; i++) {
+ CertificateAlgorithmId certAlgId =
+ (CertificateAlgorithmId)
+ certInfo[i].get(X509CertInfo.ALGORITHM_ID);
+
+ AlgorithmId algId = (AlgorithmId)
+ certAlgId.get(CertificateAlgorithmId.ALGORITHM);
+
+ if (!(algId.getName().equals(signatureAlgorithm))) {
+ alterationCounter++;
+ AlgorithmId newAlgId = AlgorithmId.get(signatureAlgorithm);
+
+ certInfo[i].set(X509CertInfo.ALGORITHM_ID,
+ new CertificateAlgorithmId(newAlgId));
+ }
+
+ CertificateSubjectName certSubject =
+ (CertificateSubjectName)
+ certInfo[i].get(X509CertInfo.SUBJECT);
+
+ if (subject != null &&
+ !(certSubject.toString().equals(subject))) {
+
+ alterationCounter++;
+ certInfo[i].set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(
+ (new X500Name(subject))));
+ }
+
+ CertificateValidity certValidity =
+ (CertificateValidity)
+ certInfo[i].get(X509CertInfo.VALIDITY);
+ Date currentTime = CMS.getCurrentDate();
+ boolean validityChanged = false;
+
+ // only override these values if agent specified them
+ if (notValidBefore > 0) {
+ Date notBefore = (Date) certValidity.get(
+ CertificateValidity.NOT_BEFORE);
+
+ if (notBefore.getTime() == 0 ||
+ notBefore.getTime() != notValidBefore) {
+ Date validFrom = new Date(notValidBefore);
+
+ notBefore = (notValidBefore == 0) ? currentTime : validFrom;
+ certValidity.set(CertificateValidity.NOT_BEFORE,
+ notBefore);
+ validityChanged = true;
+ }
+ }
+ if (notValidAfter > 0) {
+ Date validTo = new Date(notValidAfter);
+ Date notAfter = (Date)
+ certValidity.get(CertificateValidity.NOT_AFTER);
+
+ if (notAfter.getTime() == 0 ||
+ notAfter.getTime() != notValidAfter) {
+ notAfter = currentTime;
+ notAfter = (notValidAfter == 0) ? currentTime : validTo;
+ certValidity.set(CertificateValidity.NOT_AFTER,
+ notAfter);
+ validityChanged = true;
+ }
+ }
+ if (validityChanged) {
+ // this set() trigger this rebuild of internal
+ // raw der encoding cache of X509CertInfo.
+ // Otherwise, the above change wont have effect.
+ certInfo[i].set(X509CertInfo.VALIDITY, certValidity);
+ }
+
+ if (certInfo[i].get(X509CertInfo.VERSION) == null) {
+ certInfo[i].set(X509CertInfo.VERSION,
+ new CertificateVersion(
+ CertificateVersion.V3));
+ }
+
+ CertificateExtensions extensions = null;
+
+ try {
+ extensions = (CertificateExtensions)
+ certInfo[i].get(X509CertInfo.EXTENSIONS);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_PARSING_EXTENS", e.toString()));
+ }
+
+ // 99/08/31 #361906 - handling additional extensions
+ String addExts = req.getParameter("addExts");
+
+ if (addExts != null && !addExts.trim().equals("")) {
+ Vector<Extension> extsToBeAdded = new Vector<Extension>();
+
+ byte[] b = Utils.base64decode(addExts);
+
+ // this b can be "Extension" Or "SEQUENCE OF Extension"
+ try {
+ DerValue b_der = new DerValue(b);
+
+ while (b_der.data.available() != 0) {
+ Extension de = new Extension(b_der.data.getDerValue());
+
+ extsToBeAdded.addElement(de);
+ }
+ } catch (IOException e) {
+ // it could be a single extension
+ Extension de = new Extension(new DerValue(b));
+
+ extsToBeAdded.addElement(de);
+ }
+ if (extsToBeAdded.size() > 0) {
+ if (extensions == null) {
+ extensions = new CertificateExtensions();
+ certInfo[i].set(X509CertInfo.EXTENSIONS, extensions);
+ }
+ for (int j = 0; j < extsToBeAdded.size(); j++) {
+ Extension theExt = extsToBeAdded.elementAt(j);
+
+ extensions.set(theExt.getExtensionId().toString(), theExt);
+ }
+ }
+ }
+
+ if (extensions != null) {
+ try {
+ NSCertTypeExtension nsExtensions =
+ (NSCertTypeExtension)
+ extensions.get(
+ NSCertTypeExtension.NAME);
+
+ if (nsExtensions != null) {
+ updateNSExtension(req, nsExtensions);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_PROCESS_NETSCAPE_EXTENSION", e.toString()));
+ }
+
+ String pathLength = req.getParameter("pathLenConstraint");
+
+ if (pathLength != null) {
+ try {
+ int pathLen = Integer.parseInt(pathLength);
+ BasicConstraintsExtension bcExt =
+ (BasicConstraintsExtension)
+ extensions.get(
+ BasicConstraintsExtension.NAME);
+
+ if (bcExt != null) {
+ Integer bcPathLen = (Integer) bcExt.get(BasicConstraintsExtension.PATH_LEN);
+ Boolean isCA = (Boolean) bcExt.get(BasicConstraintsExtension.IS_CA);
+
+ if (bcPathLen != null &&
+ bcPathLen.intValue() != pathLen &&
+ isCA != null) {
+ BasicConstraintsExtension bcExt0 =
+ new BasicConstraintsExtension(isCA.booleanValue(), pathLen);
+
+ extensions.delete(BasicConstraintsExtension.NAME);
+ extensions.set(BasicConstraintsExtension.NAME, bcExt0);
+ alterationCounter++;
+ }
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_PROCESS_CONSTRAINTS_EXTENSION",
+ e.toString()));
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_PROCESS_CONSTRAINTS_EXTENSION",
+ e.toString()));
+ }
+ }
+
+ // handle Presence Server Extension
+ String PSE_Enable = req.getParameter("PSE_Enable");
+
+ if (PSE_Enable != null) {
+ boolean Critical = (req.getParameter("PSE_Critical") != null);
+ int Version = 0;
+
+ try {
+ Version = Integer.parseInt(req.getParameter("PSE_Version"));
+ } catch (Exception e1) {
+ }
+ String StreetAddress = req.getParameter("PSE_StreetAddress");
+
+ if (StreetAddress == null) {
+ StreetAddress = "";
+ }
+ String TelephoneNumber = req.getParameter("PSE_TelephoneNumber");
+
+ if (TelephoneNumber == null) {
+ TelephoneNumber = "";
+ }
+ String RFC822Name = req.getParameter("PSE_RFC822Name");
+
+ if (RFC822Name == null) {
+ RFC822Name = "";
+ }
+ String IMID = req.getParameter("PSE_IMID");
+
+ if (IMID == null) {
+ IMID = "";
+ }
+ String HostName = req.getParameter("PSE_HostName");
+
+ if (HostName == null) {
+ HostName = "";
+ }
+ int PortNumber = 0;
+
+ try {
+ PortNumber = Integer.parseInt(req.getParameter("PSE_PortNumber"));
+ } catch (Exception e1) {
+ }
+ int MaxUsers = 0;
+
+ try {
+ MaxUsers = Integer.parseInt(req.getParameter("PSE_MaxUsers"));
+ } catch (Exception e1) {
+ }
+ int ServiceLevel = 0;
+
+ try {
+ ServiceLevel = Integer.parseInt(req.getParameter("PSE_ServiceLevel"));
+ } catch (Exception e1) {
+ }
+ // create extension
+ PresenceServerExtension pseExt =
+ new PresenceServerExtension(Critical, Version, StreetAddress,
+ TelephoneNumber, RFC822Name, IMID, HostName, PortNumber, MaxUsers,
+ ServiceLevel);
+
+ extensions.set(pseExt.getExtensionId().toString(), pseExt);
+ }
+
+ if (mExtraAgentParams) {
+ Enumeration<String> extraparams = req.getParameterNames();
+ int l = IRequest.AGENT_PARAMS.length() + 1;
+ int ap_counter = 0;
+ Hashtable<String, String> agentparamsargblock = new Hashtable<String, String>();
+
+ if (extraparams != null) {
+ while (extraparams.hasMoreElements()) {
+ String s = extraparams.nextElement();
+
+ if (s.startsWith(IRequest.AGENT_PARAMS)) {
+ String param_value = req.getParameter(s);
+
+ if (param_value != null) {
+ String new_name = s.substring(l);
+
+ agentparamsargblock.put(new_name, param_value);
+ ap_counter += 1;
+ }
+ }
+ }
+ }
+ if (ap_counter > 0) {
+ r.setExtData(IRequest.AGENT_PARAMS, agentparamsargblock);
+ alterationCounter++;
+ }
+ }
+
+ // this set() trigger this rebuild of internal
+ // raw der encoding cache of X509CertInfo.
+ // Otherwise, the above change wont have effect.
+ certInfo[i].set(X509CertInfo.EXTENSIONS, extensions);
+ }
+ alterationCounter += updateExtensionsInRequest(req, r);
+ }
+ if (alterationCounter > 0) {
+ mQueue.updateRequest(r);
+ }
+ }
+
+ mQueue.approveRequest(r);
+
+ if (r.getRequestStatus().equals(RequestStatus.PENDING)) {
+ cmsReq.setResult(r);
+ cmsReq.setStatus(ICMSRequest.PENDING);
+ if (certInfo != null) {
+ for (int i = 0; i < certInfo.length; i++) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "pending",
+ certInfo[i].get(X509CertInfo.SUBJECT),
+ "" }
+ );
+ }
+ } else {
+ if (subject != null) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "pending",
+ subject,
+ "" }
+ );
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "pending" }
+ );
+ }
+ }
+ } else if (r.getRequestStatus().equals(
+ RequestStatus.APPROVED) ||
+ r.getRequestStatus().equals(
+ RequestStatus.SVC_PENDING)) {
+ cmsReq.setResult(r);
+ cmsReq.setStatus(ICMSRequest.SVC_PENDING);
+ if (certInfo != null) {
+ for (int i = 0; i < certInfo.length; i++) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ r.getRequestStatus(),
+ certInfo[i].get(X509CertInfo.SUBJECT),
+ "" }
+ );
+ }
+ } else {
+ if (subject != null) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ r.getRequestStatus(),
+ subject,
+ "" }
+ );
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ r.getRequestStatus() }
+ );
+ }
+ }
+ } else if (r.getRequestStatus().equals(
+ RequestStatus.COMPLETE)) {
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+
+ // XXX make the repeat record.
+ // Get the certificate(s) from the request
+ X509CertImpl issuedCerts[] =
+ r.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ // return potentially more than one certificates.
+ if (issuedCerts != null) {
+ long endTime = CMS.getCurrentDate().getTime();
+ StringBuffer sbuf = new StringBuffer();
+
+ //header.addBigIntegerValue("serialNumber",
+ //issuedCerts[0].getSerialNumber(),16);
+ for (int i = 0; i < issuedCerts.length; i++) {
+ if (i != 0)
+ sbuf.append(", ");
+ sbuf.append("0x" +
+ issuedCerts[i].getSerialNumber().toString(16));
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "completed",
+ issuedCerts[i].getSubjectDN(),
+ "cert issued serial number: 0x"
+ +
+ issuedCerts[i].getSerialNumber().toString(16) + " time: "
+ + (endTime - startTime) }
+ );
+
+ // store a message in the signed audit log file
+ // (one for each manual "agent"
+ // cert request processed - "accepted")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditInfoName,
+ auditInfoCertValue(issuedCerts[i]));
+
+ audit(auditMessage);
+ }
+ header.addStringValue(
+ "serialNumber", sbuf.toString());
+ } else {
+ if (subject != null) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "completed",
+ subject,
+ "" }
+ );
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "completed" }
+ );
+ }
+
+ // store a message in the signed audit log file
+ // (manual "agent" cert request processed
+ // - "accepted")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditInfoName,
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+
+ audit(auditMessage);
+ }
+
+ // grant trusted manager or agent privileges
+ try {
+ int res = grant_privileges(
+ cmsReq, r, issuedCerts, header);
+
+ if (res != 0) {
+ header.addStringValue(GRANT_ERROR, "SUCCESS");
+ }
+ } catch (EBaseException e) {
+ header.addStringValue(GRANT_ERROR, e.toString());
+ }
+
+ // if this is a RA, show the certificate right away
+ // since ther is no cert database.
+ /*
+ if (mAuthority instanceof RegistrationAuthority) {
+ Object[] results =
+ new Object[] { issuedCerts, grantError };
+ cmsReq.setResult(results);
+ renderTemplate(cmsReq,
+ mReqCompletedTemplate, REQ_COMPLETED_FILLER);
+
+ return;
+ }
+ */
+
+ cmsReq.setResult(r);
+
+ String scheme = req.getScheme();
+
+ if (scheme.equals("http") &&
+ connectionIsSSL(req))
+ scheme = "https";
+
+ /*
+ header.addStringValue(
+ "authorityid", mAuthority.getId());
+ header.addStringValue("serviceURL", scheme +"://"+
+ req.getServerName() + ":"+
+ req.getServerPort() +
+ req.getRequestURI());
+ */
+
+ if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) {
+ header.addStringValue("dirEnabled", "yes");
+
+ Integer[] ldapPublishStatus =
+ r.getExtDataInIntegerArray("ldapPublishStatus");
+ int certsUpdated = 0;
+
+ if (ldapPublishStatus != null) {
+ for (int i = 0; i < ldapPublishStatus.length; i++) {
+ if (ldapPublishStatus[i] == IRequest.RES_SUCCESS) {
+ certsUpdated++;
+ }
+ }
+ }
+ header.addIntegerValue("certsUpdated", certsUpdated);
+
+ } else {
+ header.addStringValue("dirEnabled", "no");
+ }
+ }
+
+ } else if (toDo.equals("reject")) {
+ mQueue.rejectRequest(r);
+ if (certInfo != null) {
+ for (int i = 0; i < certInfo.length; i++) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "rejected",
+ certInfo[i].get(X509CertInfo.SUBJECT),
+ "" }
+ );
+ }
+ } else {
+ if (subject != null) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "rejected",
+ subject,
+ "" }
+ );
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "rejected" }
+ );
+ }
+ }
+
+ // store a message in the signed audit log file
+ // (manual "agent" cert request processed - "rejected")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditInfoName,
+ SIGNED_AUDIT_MANUAL_REJECTION_REASON[1]);
+
+ audit(auditMessage);
+
+ } else if (toDo.equals("cancel")) {
+ mQueue.cancelRequest(r);
+
+ if (certInfo != null) {
+ for (int i = 0; i < certInfo.length; i++) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "canceled",
+ certInfo[i].get(X509CertInfo.SUBJECT),
+ "" }
+ );
+ }
+ } else {
+ if (subject != null) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "canceled",
+ subject,
+ "" }
+ );
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "canceled" }
+ );
+ }
+
+ }
+
+ // store a message in the signed audit log file
+ // (manual "agent" cert request processed - "cancelled")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditInfoName,
+ SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[1]);
+
+ audit(auditMessage);
+
+ } else if (toDo.equals("clone")) {
+ IRequest clonedRequest = mQueue.cloneAndMarkPending(r);
+
+ header.addStringValue("clonedRequestId",
+ clonedRequest.getRequestId().toString());
+
+ if (certInfo != null) {
+ for (int i = 0; i < certInfo.length; i++) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "cloned to reqID: " +
+ clonedRequest.getRequestId().toString(),
+ certInfo[i].get(X509CertInfo.SUBJECT),
+ "" }
+ );
+ }
+ } else {
+ if (subject != null) {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.FORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "cloned to reqID: " +
+ clonedRequest.getRequestId().toString(),
+ subject,
+ "" }
+ );
+ } else {
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ AuditFormat.NODNFORMAT,
+ new Object[] {
+ r.getRequestType(),
+ r.getRequestId(),
+ initiative,
+ authMgr,
+ "cloned to reqID: " +
+ clonedRequest.getRequestId().toString() }
+ );
+ }
+ }
+
+ // store a message in the signed audit log file
+ // ("agent" cert request for "cloning")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+ }
+ }
+
+ // add authority names to know what privileges can be requested.
+ if (CMS.getSubsystem("kra") != null)
+ header.addStringValue("localkra", "yes");
+ if (CMS.getSubsystem("ca") != null)
+ header.addStringValue("localca", "yes");
+ if (CMS.getSubsystem("ra") != null)
+ header.addStringValue("localra", "yes");
+
+ header.addBigIntegerValue("seqNum", seqNum, 10);
+ mParser.fillRequestIntoArg(locale, r, argSet, header);
+ String rid = r.getExtDataInString(IRequest.REMOTE_REQID);
+
+ if (rid != null)
+ header.addStringValue("remoteReqID", rid);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString()));
+
+ // store a message in the signed audit log file
+ if (toDo != null) {
+ if (toDo.equals(SIGNED_AUDIT_CLONING)) {
+ // ("agent" cert request for "cloning")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) {
+ // (manual "agent" cert request processed - "accepted")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) {
+ // (manual "agent" cert request processed - "cancelled")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[2]);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) {
+ // (manual "agent" cert request processed - "rejected")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ SIGNED_AUDIT_MANUAL_REJECTION_REASON[2]);
+
+ audit(auditMessage);
+ }
+ }
+
+ throw e;
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString()));
+
+ // store a message in the signed audit log file
+ if (toDo != null) {
+ if (toDo.equals(SIGNED_AUDIT_CLONING)) {
+ // ("agent" cert request for "cloning")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) {
+ // (manual "agent" cert request processed - "accepted")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) {
+ // (manual "agent" cert request processed - "cancelled")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[3]);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) {
+ // (manual "agent" cert request processed - "rejected")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ SIGNED_AUDIT_MANUAL_REJECTION_REASON[3]);
+
+ audit(auditMessage);
+ }
+ }
+
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_ENCODING_ISSUED_CERT_ERROR"));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString()));
+
+ // store a message in the signed audit log file
+ if (toDo != null) {
+ if (toDo.equals(SIGNED_AUDIT_CLONING)) {
+ // ("agent" cert request for "cloning")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) {
+ // (manual "agent" cert request processed - "accepted")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) {
+ // (manual "agent" cert request processed - "cancelled")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[4]);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) {
+ // (manual "agent" cert request processed - "rejected")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ SIGNED_AUDIT_MANUAL_REJECTION_REASON[4]);
+
+ audit(auditMessage);
+ }
+ }
+
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_ENCODING_ISSUED_CERT_ERROR"));
+ } catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString()));
+
+ // store a message in the signed audit log file
+ if (toDo != null) {
+ if (toDo.equals(SIGNED_AUDIT_CLONING)) {
+ // ("agent" cert request for "cloning")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditServiceID,
+ auditCertificateSubjectName);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) {
+ // (manual "agent" cert request processed - "accepted")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) {
+ // (manual "agent" cert request processed - "cancelled")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[5]);
+
+ audit(auditMessage);
+ } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) {
+ // (manual "agent" cert request processed - "rejected")
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditInfoName,
+ SIGNED_AUDIT_MANUAL_REJECTION_REASON[5]);
+
+ audit(auditMessage);
+ }
+ }
+
+ throw new EBaseException(CMS.getUserMessage(locale, "CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+ return;
+ }
+
+ private void updateNSExtension(HttpServletRequest req,
+ NSCertTypeExtension ext) throws IOException {
+ try {
+
+ if (req.getParameter("certTypeSSLServer") == null) {
+ ext.set(NSCertTypeExtension.SSL_SERVER, Boolean.valueOf(false));
+ } else {
+ ext.set(NSCertTypeExtension.SSL_SERVER, Boolean.valueOf(true));
+ }
+
+ if (req.getParameter("certTypeSSLClient") == null) {
+ ext.set(NSCertTypeExtension.SSL_CLIENT, Boolean.valueOf(false));
+ } else {
+ ext.set(NSCertTypeExtension.SSL_CLIENT, Boolean.valueOf(true));
+ }
+
+ if (req.getParameter("certTypeEmail") == null) {
+ ext.set(NSCertTypeExtension.EMAIL, Boolean.valueOf(false));
+ } else {
+ ext.set(NSCertTypeExtension.EMAIL, Boolean.valueOf(true));
+ }
+
+ if (req.getParameter("certTypeObjSigning") == null) {
+ ext.set(NSCertTypeExtension.OBJECT_SIGNING, Boolean.valueOf(false));
+ } else {
+ ext.set(NSCertTypeExtension.OBJECT_SIGNING, Boolean.valueOf(true));
+ }
+
+ if (req.getParameter("certTypeEmailCA") == null) {
+ ext.set(NSCertTypeExtension.EMAIL_CA, Boolean.valueOf(false));
+ } else {
+ ext.set(NSCertTypeExtension.EMAIL_CA, Boolean.valueOf(true));
+ }
+
+ if (req.getParameter("certTypeSSLCA") == null) {
+ ext.set(NSCertTypeExtension.SSL_CA, Boolean.valueOf(false));
+ } else {
+ ext.set(NSCertTypeExtension.SSL_CA, Boolean.valueOf(true));
+ }
+
+ if (req.getParameter("certTypeObjSigningCA") == null) {
+ ext.set(NSCertTypeExtension.OBJECT_SIGNING_CA, Boolean.valueOf(false));
+ } else {
+ ext.set(NSCertTypeExtension.OBJECT_SIGNING_CA, Boolean.valueOf(true));
+ }
+ } catch (CertificateException e) {
+ }
+ }
+
+ /**
+ * This method sets extensions parameter into the request so
+ * that the NSCertTypeExtension policy creates new
+ * NSCertTypExtension with this setting. Note that this
+ * setting will not be used if the NSCertType Extension
+ * already exist in CertificateExtension. In that case,
+ * updateExtensions() will be called to set the extension
+ * parameter into the extension directly.
+ */
+ private int updateExtensionsInRequest(HttpServletRequest req, IRequest r) {
+ int nChanges = 0;
+
+ if (req.getParameter("certTypeSSLServer") != null) {
+ r.setExtData(NSCertTypeExtension.SSL_SERVER, "true");
+ nChanges++;
+ } else {
+ r.deleteExtData(NSCertTypeExtension.SSL_SERVER);
+ nChanges++;
+ }
+
+ if (req.getParameter("certTypeSSLClient") != null) {
+ r.setExtData(NSCertTypeExtension.SSL_CLIENT, "true");
+ nChanges++;
+ } else {
+ r.deleteExtData(NSCertTypeExtension.SSL_CLIENT);
+ nChanges++;
+ }
+
+ if (req.getParameter("certTypeEmail") != null) {
+ r.setExtData(NSCertTypeExtension.EMAIL, "true");
+ nChanges++;
+ } else {
+ r.deleteExtData(NSCertTypeExtension.EMAIL);
+ nChanges++;
+ }
+
+ if (req.getParameter("certTypeObjSigning") != null) {
+ r.setExtData(NSCertTypeExtension.OBJECT_SIGNING, "true");
+ nChanges++;
+ } else {
+ r.deleteExtData(NSCertTypeExtension.OBJECT_SIGNING);
+ nChanges++;
+ }
+
+ if (req.getParameter("certTypeEmailCA") != null) {
+ r.setExtData(NSCertTypeExtension.EMAIL_CA, "true");
+ nChanges++;
+ } else {
+ r.deleteExtData(NSCertTypeExtension.EMAIL_CA);
+ nChanges++;
+ }
+
+ if (req.getParameter("certTypeSSLCA") != null) {
+ r.setExtData(NSCertTypeExtension.SSL_CA, "true");
+ nChanges++;
+ } else {
+ r.deleteExtData(NSCertTypeExtension.SSL_CA);
+ nChanges++;
+ }
+
+ if (req.getParameter("certTypeObjSigningCA") != null) {
+ r.setExtData(NSCertTypeExtension.OBJECT_SIGNING_CA, "true");
+ nChanges++;
+ } else {
+ r.deleteExtData(NSCertTypeExtension.OBJECT_SIGNING_CA);
+ nChanges++;
+ }
+
+ return nChanges;
+ }
+
+ protected static final String GRANT_ERROR = "grantError";
+
+ public static final String GRANT_TRUSTEDMGR_PRIVILEGE = "grantTrustedManagerPrivilege";
+ public static final String GRANT_CMAGENT_PRIVILEGE = "grantCMAgentPrivilege";
+ public static final String GRANT_RMAGENT_PRIVILEGE = "grantRMAgentPrivilege";
+ public static final String GRANT_DRMAGENT_PRIVILEGE = "grantDRMAgentPrivilege";
+ public static final String GRANT_UID = "grantUID";
+ public static final String GRANT_PRIVILEGE = "grantPrivilege";
+
+ protected int grant_privileges(
+ CMSRequest cmsReq, IRequest req, Certificate[] certs, IArgBlock header)
+ throws EBaseException {
+ // get privileges to grant
+ IArgBlock httpParams = cmsReq.getHttpParams();
+
+ boolean grantTrustedMgr =
+ httpParams.getValueAsBoolean(GRANT_TRUSTEDMGR_PRIVILEGE, false);
+ boolean grantRMAgent =
+ httpParams.getValueAsBoolean(GRANT_RMAGENT_PRIVILEGE, false);
+ boolean grantCMAgent =
+ httpParams.getValueAsBoolean(GRANT_CMAGENT_PRIVILEGE, false);
+ boolean grantDRMAgent =
+ httpParams.getValueAsBoolean(GRANT_DRMAGENT_PRIVILEGE, false);
+
+ if (!grantTrustedMgr &&
+ !grantCMAgent && !grantRMAgent && !grantDRMAgent) {
+ return 0;
+ } else {
+ IAuthToken authToken = getAuthToken(req);
+ AuthzToken authzToken = null;
+ String resourceName = "certServer." + mAuthority.getId() + ".group";
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ resourceName, "add");
+ } catch (Exception e) {
+ // do nothing for now
+ }
+
+ if (authzToken == null) {
+ String[] obj = new String[1];
+
+ if (grantTrustedMgr)
+ obj[0] = TRUSTED_RA_GROUP;
+ else if (grantRMAgent)
+ obj[0] = RA_AGENT_GROUP;
+ else if (grantCMAgent)
+ obj[0] = CA_AGENT_GROUP;
+ else if (grantDRMAgent)
+ obj[0] = KRA_AGENT_GROUP;
+ else
+ obj[0] = "unknown group";
+
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_UNAUTHORIZED_CREATE_GROUP", obj[0]));
+ }
+ }
+
+ String uid = httpParams.getValueAsString(GRANT_UID, null);
+
+ if (uid == null || uid.length() == 0) {
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_MISSING_GRANT_UID"));
+ }
+ header.addStringValue(GRANT_UID, uid);
+
+ String groupname = null, groupname1 = null;
+ String userType = "";
+
+ if (grantTrustedMgr) {
+ groupname = TRUSTED_RA_GROUP;
+ userType = Constants.PR_SUBSYSTEM_TYPE;
+ } else {
+ if (grantCMAgent)
+ groupname = CA_AGENT_GROUP;
+ else if (grantRMAgent)
+ groupname = RA_AGENT_GROUP;
+
+ if (grantDRMAgent) {
+ if (groupname != null)
+ groupname1 = KRA_AGENT_GROUP;
+ else
+ groupname = KRA_AGENT_GROUP;
+ }
+ userType = Constants.PR_AGENT_TYPE;
+ }
+
+ String privilege =
+ (groupname1 == null) ? groupname : groupname + " and " + groupname1;
+
+ header.addStringValue(GRANT_PRIVILEGE, privilege);
+
+ IUGSubsystem ug = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+ IUser user = ug.createUser(uid);
+
+ user.setFullName(uid);
+ user.setEmail("");
+ user.setPhone("");
+ user.setPassword("");
+ user.setUserType(userType);
+ user.setState("1");
+ IGroup group = ug.findGroup(groupname), group1 = null;
+
+ if (group == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_FIND_GROUP_1", groupname));
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_FIND_GROUP_ERROR", groupname));
+ }
+ if (groupname1 != null) {
+ group1 = ug.findGroup(groupname1);
+ if (group1 == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_FIND_GROUP_1", groupname));
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_FIND_GROUP_ERROR", groupname1));
+ }
+ }
+ try {
+ ug.addUser(user);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_ADDING_USER_1", uid));
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_ADDING_USER_ERROR", uid));
+ }
+ try {
+ if (certs[0] instanceof X509CertImpl) {
+ X509CertImpl tmp[] = (X509CertImpl[]) certs;
+
+ user.setX509Certificates(tmp);
+ }
+
+ ug.addUserCert(user);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERROR_ADDING_CERT_1", uid));
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_ADDING_CERT_ERROR", uid));
+ }
+ try {
+ group.addMemberName(uid);
+ ug.modifyGroup(group);
+ // for audit log
+ SessionContext sContext = SessionContext.getContext();
+ String adminId = (String) sContext.get(SessionContext.USER_ID);
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP,
+ AuditFormat.LEVEL, AuditFormat.ADDUSERGROUPFORMAT,
+ new Object[] { adminId, uid, groupname }
+ );
+
+ if (group1 != null) {
+ group1.addMemberName(uid);
+ ug.modifyGroup(group1);
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP,
+ AuditFormat.LEVEL, AuditFormat.ADDUSERGROUPFORMAT,
+ new Object[] { adminId, uid, groupname1 }
+ );
+
+ }
+ } catch (Exception e) {
+ String msg =
+ "Could not add user " + uid + " to group " + groupname;
+
+ if (group1 != null)
+ msg += " or group " + groupname1;
+ log(ILogger.LL_FAILURE, msg);
+ if (group1 == null)
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_ADDING_MEMBER", uid, groupname));
+ else
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_ADDING_MEMBER_1", uid, groupname, groupname1));
+ }
+ return 1;
+ }
+
+ /**
+ * Signed Audit Log Info Name
+ *
+ * This method is called to obtain the "InfoName" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @param type signed audit log request processing type
+ * @return id string containing the signed audit log message InfoName
+ */
+ private String auditInfoName(String type) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters (this is done below)
+
+ String infoName = ILogger.UNIDENTIFIED;
+
+ if (mSignedAuditLogger == null) {
+ return infoName;
+ }
+
+ if (type != null) {
+ type = type.trim();
+
+ if (type.equals(SIGNED_AUDIT_ACCEPTANCE)) {
+ infoName = ILogger.SIGNED_AUDIT_ACCEPTANCE;
+ } else if (type.equals(SIGNED_AUDIT_CANCELLATION)) {
+ infoName = ILogger.SIGNED_AUDIT_CANCELLATION;
+ } else if (type.equals(SIGNED_AUDIT_REJECTION)) {
+ infoName = ILogger.SIGNED_AUDIT_REJECTION;
+ }
+ }
+
+ return infoName;
+ }
+
+ /**
+ * Signed Audit Log Info Certificate Value
+ *
+ * This method is called to obtain the certificate from the passed in
+ * "X509CertImpl" for a signed audit log message.
+ * <P>
+ *
+ * @param x509cert an X509CertImpl
+ * @return cert string containing the certificate
+ */
+ private String auditInfoCertValue(X509CertImpl x509cert) {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ if (x509cert == null) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ byte rawData[] = null;
+
+ try {
+ rawData = x509cert.getEncoded();
+ } catch (CertificateEncodingException e) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ String cert = null;
+
+ // convert "rawData" into "base64Data"
+ if (rawData != null) {
+ String base64Data = null;
+
+ base64Data = Utils.base64encode(rawData).trim();
+
+ // extract all line separators from the "base64Data"
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < base64Data.length(); i++) {
+ if (base64Data.substring(i, i).getBytes() != EOL) {
+ sb.append(base64Data.substring(i, i));
+ }
+ }
+ cert = sb.toString();
+ }
+
+ if (cert != null) {
+ cert = cert.trim();
+
+ if (cert.equals("")) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ } else {
+ return cert;
+ }
+ } else {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+ }
+}
+
+class RAReqCompletedFiller extends ImportCertsTemplateFiller {
+ private static final String RA_AGENT_GROUP = "Registration Manager Agents";
+ private static final String KRA_AGENT_GROUP = "Data Recovery Manager Agents";
+
+ public RAReqCompletedFiller() {
+ super();
+ }
+
+ public CMSTemplateParams getTemplateParams(
+ CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e)
+ throws Exception {
+
+ Object[] results = (Object[]) cmsReq.getResult();
+ Object grantError = results[1];
+ //X509CertImpl[] issuedCerts = (X509CertImpl[])results[0];
+ Certificate[] issuedCerts = (Certificate[]) results[0];
+
+ cmsReq.setResult(issuedCerts);
+ CMSTemplateParams params =
+ super.getTemplateParams(cmsReq, authority, locale, e);
+
+ if (grantError != null) {
+ IArgBlock header = params.getHeader();
+
+ if (grantError instanceof String) {
+ header.addStringValue(
+ ProcessCertReq.GRANT_ERROR, (String) grantError);
+ } else {
+ EBaseException ex = (EBaseException) grantError;
+
+ header.addStringValue(
+ ProcessCertReq.GRANT_ERROR, ex.toString(locale));
+ }
+ IArgBlock httpParams = cmsReq.getHttpParams();
+ String uid = httpParams.getValueAsString(
+ ProcessCertReq.GRANT_UID, null);
+
+ header.addStringValue(ProcessCertReq.GRANT_UID, uid);
+ boolean grantRMAgent = httpParams.getValueAsBoolean(
+ ProcessCertReq.GRANT_RMAGENT_PRIVILEGE, false);
+ boolean grantDRMAgent = httpParams.getValueAsBoolean(
+ ProcessCertReq.GRANT_DRMAGENT_PRIVILEGE, false);
+ String privilege = null;
+
+ if (grantRMAgent) {
+ privilege = RA_AGENT_GROUP;
+ }
+ if (grantDRMAgent) {
+ if (privilege != null)
+ privilege += " and " + KRA_AGENT_GROUP;
+ else
+ privilege = KRA_AGENT_GROUP;
+ }
+ header.addStringValue(ProcessCertReq.GRANT_PRIVILEGE, privilege);
+ }
+ return params;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/ProcessReq.java b/base/server/cms/src/com/netscape/cms/servlet/request/ProcessReq.java
new file mode 100644
index 000000000..66c7129f6
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/ProcessReq.java
@@ -0,0 +1,330 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.request;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Display Generic Request detail to the user.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ProcessReq extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6941843162486565610L;
+ private final static String SEQNUM = "seqNum";
+ private final static String DO_ASSIGN = "doAssign";
+ private final static String TPL_FILE = "processReq.template";
+ private final static String PROP_PARSER = "parser";
+
+ private IRequestQueue mQueue = null;
+ private String mFormPath = null;
+ private IReqParser mParser = null;
+ private String[] mSigningAlgorithms = null;
+
+ /**
+ * Process request.
+ */
+ public ProcessReq() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "processReq.template" to process the response.
+ * The initialization parameter 'parser' is read from the
+ * servlet configration, and is used to set the type of request.
+ * The value of this parameter can be:
+ * <UL>
+ * <LI><B>CertReqParser.NODETAIL_PARSER</B> - Show certificate Summary
+ * <LI><B>CertReqParser.DETAIL_PARSER</B> - Show certificate detail
+ * <LI><B>KeyReqParser.PARSER</B> - Show key archival detail
+ * </UL>
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mQueue = mAuthority.getRequestQueue();
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ String tmp = sc.getInitParameter(PROP_PARSER);
+
+ if (tmp != null) {
+ if (tmp.trim().equals("CertReqParser.NODETAIL_PARSER"))
+ mParser = CertReqParser.NODETAIL_PARSER;
+ else if (tmp.trim().equals("CertReqParser.DETAIL_PARSER"))
+ mParser = CertReqParser.DETAIL_PARSER;
+ else if (tmp.trim().equals("KeyReqParser.PARSER"))
+ mParser = KeyReqParser.PARSER;
+ }
+
+ // override success and error templates to null -
+ // handle templates locally.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ mTemplates.remove(ICMSRequest.ERROR);
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param seqNum
+ * <li>http.param doAssign reassign request. Value can be reassignToMe reassignToNobody
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ BigInteger seqNum = BigInteger.ONE.negate();
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock fixed = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, fixed);
+
+ String doAssign = null;
+ EBaseException error = null;
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ "Error getting template " + mFormPath + " Error " + e);
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ try {
+ if (req.getParameter(SEQNUM) != null) {
+ seqNum = new BigInteger(req.getParameter(SEQNUM));
+ }
+ doAssign = req.getParameter(DO_ASSIGN);
+
+ if (seqNum.compareTo(BigInteger.ONE.negate()) > 0) {
+ // start authorization
+ AuthzToken authzToken = null;
+
+ try {
+ if (doAssign == null) {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "read");
+ } else if (doAssign.equals("toMe") ||
+ doAssign.equals("reassignToMe")) {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "assign");
+ } else if (doAssign.equals("reassignToNobody")) {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "unassign");
+ }
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ process(argSet, header, seqNum, req, resp,
+ doAssign, locale[0]);
+ } else {
+ log(ILogger.LL_FAILURE, "Invalid sequence number " + seqNum);
+ error = new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_REQUEST_ID",
+ String.valueOf(seqNum)));
+ }
+ } catch (EBaseException e) {
+ error = e;
+ } catch (NumberFormatException e) {
+ error = new EBaseException(CMS.getUserMessage(locale[0], "CMS_BASE_INVALID_NUMBER_FORMAT"));
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ }
+ } else {
+ cmsReq.setError(error);
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ "Error getting servlet output stream for rendering template. " +
+ "Error " + e);
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ return;
+ }
+
+ /**
+ * Sends request information to the calller.
+ * returns whether there was an error or not.
+ */
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ BigInteger seqNum, HttpServletRequest req,
+ HttpServletResponse resp,
+ String doAssign, Locale locale)
+ throws EBaseException {
+
+ header.addBigIntegerValue("seqNum", seqNum, 10);
+
+ IRequest r = mQueue.findRequest(new RequestId(seqNum));
+
+ if (r != null) {
+ if (doAssign != null) {
+ if ((doAssign.equals("toMe"))
+ || (doAssign.equals("reassignToMe"))) {
+ SessionContext ctx = SessionContext.getContext();
+ String id = (String) ctx.get(SessionContext.USER_ID);
+
+ r.setRequestOwner(id);
+ mQueue.updateRequest(r);
+ } else if (doAssign.equals("reassignToNobody")) {
+ r.setRequestOwner(null);
+ mQueue.updateRequest(r);
+ }
+ }
+
+ // add authority names to know what privileges can be requested.
+ if (CMS.getSubsystem("kra") != null)
+ header.addStringValue("localkra", "yes");
+ if (CMS.getSubsystem("ca") != null)
+ header.addStringValue("localca", "yes");
+ if (CMS.getSubsystem("ra") != null)
+ header.addStringValue("localra", "yes");
+
+ // DONT NEED TO DO THIS FOR DRM
+ if (mAuthority instanceof ICertAuthority) {
+ // Check/set signing algorithms dynamically.
+ // In RA mSigningAlgorithms could be null at startup if CA is not
+ // up and set later when CA comes back up.
+ // Once it's set assumed that it won't change.
+ String[] allAlgorithms = mSigningAlgorithms;
+
+ if (allAlgorithms == null) {
+ allAlgorithms = mSigningAlgorithms =
+ ((ICertAuthority) mAuthority).getCASigningAlgorithms();
+ if (allAlgorithms == null) {
+ CMS.debug(
+ "ProcessReq: signing algorithms set to All algorithms");
+ allAlgorithms = AlgorithmId.ALL_SIGNING_ALGORITHMS;
+ } else
+ CMS.debug(
+ "ProcessReq: First signing algorithms is " + allAlgorithms[0]);
+ }
+ String validAlgorithms = null;
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < allAlgorithms.length; i++) {
+ if (i > 0) {
+ sb.append("+");
+ sb.append(allAlgorithms[i]);
+ } else {
+ sb.append(allAlgorithms[i]);
+ }
+ }
+ validAlgorithms = sb.toString();
+ if (validAlgorithms != null)
+ header.addStringValue("validAlgorithms", validAlgorithms);
+ if (mAuthority instanceof ICertificateAuthority) {
+ String signingAlgorithm = ((ICertificateAuthority) mAuthority).getDefaultAlgorithm();
+
+ if (signingAlgorithm != null)
+ header.addStringValue("caSigningAlgorithm", signingAlgorithm);
+ header.addLongValue("defaultValidityLength",
+ ((ICertificateAuthority) mAuthority).getDefaultValidity() / 1000);
+ } else if (mAuthority instanceof IRegistrationAuthority) {
+ header.addLongValue("defaultValidityLength",
+ ((IRegistrationAuthority) mAuthority).getDefaultValidity() / 1000);
+ }
+ X509CertImpl caCert = ((ICertAuthority) mAuthority).getCACert();
+
+ if (caCert != null) {
+ int caPathLen = caCert.getBasicConstraints();
+
+ header.addIntegerValue("caPathLen", caPathLen);
+ }
+ }
+
+ mParser.fillRequestIntoArg(locale, r, argSet, header);
+ } else {
+ log(ILogger.LL_FAILURE, "Invalid sequence number " + seqNum.toString());
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_REQUEST_ID",
+ seqNum.toString()));
+ }
+
+ return;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/QueryReq.java b/base/server/cms/src/com/netscape/cms/servlet/request/QueryReq.java
new file mode 100644
index 000000000..09bf3a0b8
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/QueryReq.java
@@ -0,0 +1,540 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.request;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.IRequestVirtualList;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Show paged list of requests matching search criteria
+ *
+ * @version $Revision$, $Date$
+ */
+public class QueryReq extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -8729364426329835378L;
+ // constants
+ private final static String IN_SHOW_ALL = "showAll";
+ private final static String IN_SHOW_WAITING = "showWaiting";
+ private final static String IN_SHOW_IN_SERVICE = "showInService";
+ private final static String IN_SHOW_PENDING = "showPending";
+ private final static String IN_SHOW_CANCELLED = "showCancelled";
+ private final static String IN_SHOW_REJECTED = "showRejected";
+ private final static String IN_SHOW_COMPLETED = "showCompleted";
+ private final static String IN_MAXCOUNT = "maxCount";
+ private final static String IN_TOTALCOUNT = "totalRecordCount";
+ private final static String PROP_PARSER = "parser";
+
+ private final static String TPL_FILE = "queryReq.template";
+
+ private final static String OUT_TOTALCOUNT = IN_TOTALCOUNT;
+ private final static String OUT_CURRENTCOUNT = "currentRecordCount";
+ private final static String OUT_REQUESTING_USER = "requestingUser";
+ //keeps track of where to begin if page down
+ private final static String OUT_FIRST_ENTRY_ON_PAGE = "firstEntryOnPage";
+ //keeps track of where to begin if page up
+ private final static String OUT_LAST_ENTRY_ON_PAGE = "lastEntryOnPage";
+ private final static String OUT_ERROR = "error";
+ private final static String OUT_AUTHORITY_ID = "authorityid";
+
+ // variables
+ private IReqParser mParser = null;
+ private IRequestQueue mQueue = null;
+ private String mFormPath = null;
+ private int mMaxReturns = 2000;
+
+ public CMSRequest newCMSRequest() {
+ return new CMSRequest();
+ }
+
+ /**
+ * Constructor
+ */
+ public QueryReq() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses the template file
+ * "queryReq.template" to process the response.
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ mQueue = mAuthority.getRequestQueue();
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ try {
+ mMaxReturns = Integer.parseInt(sc.getInitParameter("maxResults"));
+ } catch (Exception e) {
+ /* do nothing, just use the default if integer parsing failed */
+ }
+
+ String tmp = sc.getInitParameter(PROP_PARSER);
+
+ if (tmp != null) {
+ if (tmp.trim().equals("CertReqParser.NODETAIL_PARSER"))
+ mParser = CertReqParser.NODETAIL_PARSER;
+ else if (tmp.trim().equals("CertReqParser.DETAIL_PARSER"))
+ mParser = CertReqParser.DETAIL_PARSER;
+ else if (tmp.trim().equals("KeyReqParser.PARSER"))
+ mParser = KeyReqParser.PARSER;
+ }
+
+ // override success and error templates to null -
+ // handle templates locally.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ mTemplates.remove(ICMSRequest.ERROR);
+
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ private String getRequestType(String p) {
+ String filter = "(requestType=*)";
+
+ if (p == null)
+ return filter;
+ if (p.equals(IRequest.ENROLLMENT_REQUEST)) {
+ filter = "(requestType=" + IRequest.ENROLLMENT_REQUEST + ")";
+ } else if (p.equals(IRequest.RENEWAL_REQUEST)) {
+ filter = "(requestType=" + IRequest.RENEWAL_REQUEST + ")";
+ } else if (p.equals(IRequest.REVOCATION_REQUEST)) {
+ filter = "(requestType=" + IRequest.REVOCATION_REQUEST + ")";
+ } else if (p.equals(IRequest.UNREVOCATION_REQUEST)) {
+ filter = "(requestType=" + IRequest.UNREVOCATION_REQUEST + ")";
+ } else if (p.equals(IRequest.KEYARCHIVAL_REQUEST)) {
+ filter = "(requestType=" + IRequest.KEYARCHIVAL_REQUEST + ")";
+ } else if (p.equals(IRequest.KEYRECOVERY_REQUEST)) {
+ filter = "(requestType=" + IRequest.KEYRECOVERY_REQUEST + ")";
+ } else if (p.equals(IRequest.GETCACHAIN_REQUEST)) {
+ filter = "(requestType=" + IRequest.GETCACHAIN_REQUEST + ")";
+ } else if (p.equals(IRequest.GETREVOCATIONINFO_REQUEST)) {
+ filter = "(requestType=" + IRequest.GETREVOCATIONINFO_REQUEST + ")";
+ } else if (p.equals(IRequest.GETCRL_REQUEST)) {
+ filter = "(requestType=" + IRequest.GETCRL_REQUEST + ")";
+ } else if (p.equals(IRequest.GETCERTS_REQUEST)) {
+ filter = "(requestType=" + IRequest.GETCERTS_REQUEST + ")";
+ } else if (p.equals(IRequest.NETKEY_KEYGEN_REQUEST)) {
+ filter = "(requestType=" + IRequest.NETKEY_KEYGEN_REQUEST + ")";
+ } else if (p.equals(IN_SHOW_ALL)) {
+ filter = "(requestType=*)";
+ }
+ return filter;
+ }
+
+ private String getRequestState(String p) {
+ String filter = "(requeststate=*)";
+
+ if (p == null)
+ return filter;
+ if (p.equals(IN_SHOW_WAITING)) {
+ filter = "(requeststate=pending)";
+ } else if (p.equals(IN_SHOW_IN_SERVICE)) {
+ filter = "(requeststate=svc_pending)";
+ } else if (p.equals(IN_SHOW_PENDING)) {
+ filter = "(requeststate=pending)";
+ } else if (p.equals(IN_SHOW_CANCELLED)) {
+ filter = "(requeststate=canceled)";
+ } else if (p.equals(IN_SHOW_REJECTED)) {
+ filter = "(requeststate=rejected)";
+ } else if (p.equals(IN_SHOW_COMPLETED)) {
+ filter = "(requeststate=complete)";
+ } else if (p.equals(IN_SHOW_ALL)) {
+ filter = "(requeststate=*)";
+ }
+ return filter;
+ }
+
+ /**
+ * Process the HTTP request.
+ * <ul>
+ * <li>http.param reqState request state (one of showAll, showWaiting, showInService, showCancelled, showRejected,
+ * showCompleted)
+ * <li>http.param reqType
+ * <li>http.param seqNumFromDown request ID to start at (decimal, or hex if when paging down seqNumFromDown starts
+ * with 0x)
+ * <li>http.param seqNumFromUp request ID to start at (decimal, or hex if when paging up seqNumFromUp starts with
+ * 0x)
+ * <li>http.param maxCount maximum number of records to show
+ * <li>http.param totalCount total number of records in set of pages
+ * <li>http.param direction "up", "down", "begin", or "end"
+ * </ul>
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ CMS.debug("in QueryReq servlet");
+
+ // Authentication / Authorization
+
+ HttpServletRequest req = cmsReq.getHttpReq();
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "list");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ // if get a EBaseException we just throw it.
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ /**
+ * WARNING:
+ *
+ * PLEASE DO NOT TOUCH THE FILTER HERE. ALL FILTERS ARE INDEXED.
+ *
+ **/
+ String filter = null;
+ String reqState = req.getParameter("reqState");
+ String reqType = req.getParameter("reqType");
+
+ if (reqState == null || reqType == null) {
+ filter = "(requeststate=*)";
+ } else if (reqState.equals(IN_SHOW_ALL) &&
+ reqType.equals(IN_SHOW_ALL)) {
+ filter = "(requeststate=*)";
+ } else if (reqState.equals(IN_SHOW_ALL)) {
+ filter = getRequestType(reqType);
+ } else if (reqType.equals(IN_SHOW_ALL)) {
+ filter = getRequestState(reqState);
+ } else {
+ filter = "(&" + getRequestState(reqState) +
+ getRequestType(reqType) + ")";
+ }
+
+ String direction = "begin";
+ if (req.getParameter("direction") != null) {
+ direction = req.getParameter("direction").trim();
+ }
+
+ BigInteger top = BigInteger.ZERO;
+ BigInteger bottom = BigInteger.ZERO;
+
+ try {
+ String top_s = req.getParameter(OUT_FIRST_ENTRY_ON_PAGE);
+ if (top_s == null)
+ top_s = "0";
+
+ String bottom_s = req.getParameter(OUT_LAST_ENTRY_ON_PAGE);
+ if (bottom_s == null)
+ bottom_s = "0";
+
+ if (top_s.trim().startsWith("0x")) {
+ top = new BigInteger(top_s.trim().substring(2), 16);
+ } else {
+ top = new BigInteger(top_s.trim());
+ }
+ if (bottom_s.trim().startsWith("0x")) {
+ bottom = new BigInteger(bottom_s.trim().substring(2), 16);
+ } else {
+ bottom = new BigInteger(bottom_s.trim());
+ }
+
+ } catch (NumberFormatException e) {
+
+ }
+
+ // avoid NumberFormatException to the user interface
+ int maxCount = 10;
+ try {
+ maxCount = Integer.parseInt(req.getParameter(IN_MAXCOUNT));
+ } catch (Exception e) {
+ }
+ if (maxCount > mMaxReturns) {
+ CMS.debug("Resetting page size from " + maxCount + " to " + mMaxReturns);
+ maxCount = mMaxReturns;
+ }
+
+ HttpServletResponse resp = cmsReq.getHttpResp();
+ CMSTemplateParams argset = doSearch(locale[0], filter, maxCount, direction, top, bottom);
+
+ argset.getFixed().addStringValue("reqType", reqType);
+ argset.getFixed().addStringValue("reqState", reqState);
+ argset.getFixed().addIntegerValue("maxCount", maxCount);
+
+ try {
+ form.getOutput(argset);
+ resp.setContentType("text/html");
+ form.renderOutput(resp.getOutputStream(), argset);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ return;
+ }
+
+ /**
+ * Perform search based on direction button pressed
+ *
+ * @param filter ldap filter indicating which VLV to search through. This can be
+ * 'all requests', 'pending', etc
+ * @param count the number of requests to show per page
+ * @param direction either 'begin', 'end', 'previous' or 'next' (defaults to end)
+ * @param top the number of the request shown on at the top of the current page
+ * @param bottom the number of the request shown on at the bottom of the current page
+ * @return
+ */
+
+ private CMSTemplateParams doSearch(Locale l, String filter,
+ int count, String direction, BigInteger top, BigInteger bottom) {
+ CMSTemplateParams ctp = null;
+ if (direction.equals("previous")) {
+ ctp = doSearch(l, filter, -count, top);
+ } else if (direction.equals("next")) {
+ bottom = bottom.add(BigInteger.ONE);
+ ctp = doSearch(l, filter, count, bottom);
+ } else if (direction.equals("begin")) {
+ ctp = doSearch(l, filter, count, BigInteger.ZERO);
+ } else if (direction.equals("first")) {
+ ctp = doSearch(l, filter, count, bottom);
+ } else { // if 'direction is 'end', default here
+ ctp = doSearch(l, filter, -count, BigInteger.ONE.negate());
+ }
+ return ctp;
+ }
+
+ /**
+ *
+ * @param locale
+ * @param filter the types of requests to return - this must match the VLV index
+ * @param count maximum number of records to return
+ * @param marker indication of the request ID where the page is anchored
+ * @return
+ */
+
+ private CMSTemplateParams doSearch(
+ Locale locale,
+ String filter,
+ int count,
+ BigInteger marker) {
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock context = CMS.createArgBlock();
+ CMSTemplateParams argset = new CMSTemplateParams(header, context);
+
+ try {
+ long startTime = CMS.getCurrentDate().getTime();
+ // preserve the type of request that we are
+ // requesting.
+
+ header.addStringValue(OUT_AUTHORITY_ID, mAuthority.getId());
+ header.addStringValue(OUT_REQUESTING_USER, "admin");
+
+ boolean jumptoend = false;
+ if (marker.toString().equals("-1")) {
+ marker = BigInteger.ZERO; // I think this is inconsequential
+ jumptoend = true; // override to '99' during search
+ }
+
+ RequestId id = new RequestId(marker);
+ IRequestVirtualList list = mQueue.getPagedRequestsByFilter(
+ id,
+ jumptoend,
+ filter,
+ ((count < 0) ? count - 1 : count + 1),
+ "requestId");
+
+ int maxCount = 0;
+ if (count < 0 && jumptoend) {
+ maxCount = -count;
+ } else if (count < 0) {
+ maxCount = -count + 1;
+ } else {
+ maxCount = count;
+ }
+ int totalCount = (jumptoend) ? maxCount :
+ (list.getSize() - list.getCurrentIndex());
+ header.addIntegerValue(OUT_TOTALCOUNT, totalCount);
+ header.addIntegerValue(OUT_CURRENTCOUNT, list.getSize());
+
+ Vector<IRequest> v = fetchRecords(list, maxCount);
+ v = normalizeOrder(v);
+ trim(v, id);
+
+ int currentCount = 0;
+ BigInteger curNum = BigInteger.ZERO;
+ BigInteger firstNum = BigInteger.ONE.negate();
+ Enumeration<IRequest> requests = v.elements();
+
+ while (requests.hasMoreElements()) {
+ IRequest request = null;
+ try {
+ request = requests.nextElement();
+ } catch (Exception e) {
+ CMS.debug("Error displaying request:" + e.getMessage());
+ // handled below
+ }
+ if (request == null) {
+ log(ILogger.LL_WARN, "Error display request on page");
+ continue;
+ }
+
+ curNum = new BigInteger(request.getRequestId().toString());
+
+ if (firstNum.equals(BigInteger.ONE.negate())) {
+ firstNum = curNum;
+ }
+
+ IArgBlock rec = CMS.createArgBlock();
+ mParser.fillRequestIntoArg(locale, request, argset, rec);
+ mQueue.releaseRequest(request);
+ argset.addRepeatRecord(rec);
+
+ currentCount++;
+
+ }// while
+ long endTime = CMS.getCurrentDate().getTime();
+
+ header.addIntegerValue(OUT_CURRENTCOUNT, currentCount);
+ header.addStringValue("time", Long.toString(endTime - startTime));
+ header.addBigIntegerValue(OUT_FIRST_ENTRY_ON_PAGE, firstNum, 10);
+ header.addBigIntegerValue(OUT_LAST_ENTRY_ON_PAGE, curNum, 10);
+
+ } catch (EBaseException e) {
+ header.addStringValue(OUT_ERROR, e.toString(locale));
+ } catch (Exception e) {
+ }
+ return argset;
+ }
+
+ /**
+ * If the vector contains the marker element at the end, remove it.
+ *
+ * @param v The vector to trim
+ * @param marker the marker to look for.
+ */
+ private void trim(Vector<IRequest> v, RequestId marker) {
+ int i = v.size() - 1;
+ if (v.elementAt(i).getRequestId().toString().equals(
+ marker.toString())) {
+ v.remove(i);
+ }
+ }
+
+ /**
+ * Sometimes the list comes back from LDAP in reverse order. This function makes
+ * sure the results are in 'forward' order.
+ *
+ * @param list
+ * @return
+ */
+ private Vector<IRequest> fetchRecords(IRequestVirtualList list, int maxCount) {
+
+ Vector<IRequest> v = new Vector<IRequest>();
+ int count = list.getSize();
+ int c = 0;
+ for (int i = 0; i < count; i++) {
+ IRequest request = list.getElementAt(i);
+ if (request != null) {
+ v.add(request);
+ c++;
+ }
+ if (c >= maxCount)
+ break;
+ }
+
+ return v;
+
+ }
+
+ /**
+ * If the requests are in backwards order, reverse the list
+ *
+ * @param list
+ * @return
+ */
+ private Vector<IRequest> normalizeOrder(Vector<IRequest> list) {
+
+ BigInteger firstrequestnum = new BigInteger(list.elementAt(0)
+ .getRequestId().toString());
+ BigInteger lastrequestnum = new BigInteger(list.elementAt(list
+ .size() - 1).getRequestId().toString());
+ boolean reverse = false;
+ if (firstrequestnum.compareTo(lastrequestnum) > 0) {
+ reverse = true; // if the order is backwards, place items at the beginning
+ }
+ Vector<IRequest> v = new Vector<IRequest>();
+ int count = list.size();
+ for (int i = 0; i < count; i++) {
+ IRequest request = list.elementAt(i);
+ if (request != null) {
+ if (reverse)
+ v.add(0, request);
+ else
+ v.add(request);
+ }
+ }
+
+ return v;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/ReqParser.java b/base/server/cms/src/com/netscape/cms/servlet/request/ReqParser.java
new file mode 100644
index 000000000..4a6a79072
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/ReqParser.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.request;
+
+import java.util.Locale;
+import java.math.BigInteger;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+
+/**
+ * A class representing a request parser.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class ReqParser implements IReqParser {
+
+ private final static String TYPE = "requestType";
+ private final static String STATUS = "status";
+ private final static String CREATE_ON = "createdOn";
+ private final static String UPDATE_ON = "updatedOn";
+ private final static String UPDATE_BY = "updatedBy";
+
+ /**
+ * Constructs a request parser.
+ */
+ public ReqParser() {
+ }
+
+ /**
+ * Maps request object into argument block.
+ */
+ public void fillRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg)
+ throws EBaseException {
+ arg.addStringValue(TYPE, req.getRequestType());
+ arg.addBigIntegerValue("seqNum",
+ new BigInteger(req.getRequestId().toString()), 10);
+ arg.addStringValue(STATUS,
+ req.getRequestStatus().toString());
+ arg.addLongValue(CREATE_ON,
+ req.getCreationTime().getTime() / 1000);
+ arg.addLongValue(UPDATE_ON,
+ req.getModificationTime().getTime() / 1000);
+ String updatedBy = req.getExtDataInString(IRequest.UPDATED_BY);
+
+ if (updatedBy == null)
+ updatedBy = "";
+ arg.addStringValue(UPDATE_BY, updatedBy);
+
+ SessionContext ctx = SessionContext.getContext();
+ String id = (String) ctx.get(SessionContext.USER_ID);
+
+ arg.addStringValue("callerName", id);
+
+ String owner = req.getRequestOwner();
+
+ if (owner != null)
+ arg.addStringValue("assignedTo", owner);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/SearchReqs.java b/base/server/cms/src/com/netscape/cms/servlet/request/SearchReqs.java
new file mode 100644
index 000000000..533199ebc
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/SearchReqs.java
@@ -0,0 +1,328 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.request;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Locale;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzAccessDenied;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestList;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.ECMSGWException;
+
+/**
+ * Search for certificates matching complex query filter
+ *
+ * @version $Revision$, $Date$
+ */
+public class SearchReqs extends CMSServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2449481964851735051L;
+ private final static String TPL_FILE = "queryReq.template";
+ private final static String PROP_MAX_SEARCH_RETURNS = "maxSearchReqReturns";
+ private final static String PROP_PARSER = "parser";
+ private final static String CURRENT_TIME = "currentTime";
+ private final static String OUT_TOTALCOUNT = "totalRecordCount";
+ private final static String OUT_CURRENTCOUNT = "currentRecordCount";
+ private final static int MAX_RESULTS = 1000;
+
+ private IRequestQueue mQueue = null;
+ private IReqParser mParser = null;
+ private String mFormPath = null;
+ private int mMaxReturns = MAX_RESULTS;
+ private int mTimeLimits = 30; /* in seconds */
+
+ /**
+ * Constructs query key servlet.
+ */
+ public SearchReqs() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses queryReq.template
+ * to render the response
+ *
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success to render own template.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+
+ if (mAuthority instanceof ISubsystem) {
+ ISubsystem sub = mAuthority;
+ IConfigStore authConfig = sub.getConfigStore();
+
+ if (authConfig != null) {
+ try {
+ mMaxReturns = authConfig.getInteger(PROP_MAX_SEARCH_RETURNS, MAX_RESULTS);
+ } catch (EBaseException e) {
+ // do nothing
+ }
+ }
+ }
+ if (mAuthority instanceof ICertificateAuthority) {
+ ICertificateAuthority ca = (ICertificateAuthority) mAuthority;
+ mQueue = ca.getRequestQueue();
+ }
+
+ mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
+
+ /* Server-Side time limit */
+ try {
+ int maxResults = Integer.parseInt(sc.getInitParameter("maxResults"));
+ if (maxResults < mMaxReturns)
+ mMaxReturns = maxResults;
+ } catch (Exception e) {
+ /* do nothing, just use the default if integer parsing failed */
+ }
+ try {
+ mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits"));
+ } catch (Exception e) {
+ /* do nothing, just use the default if integer parsing failed */
+ }
+
+ String tmp = sc.getInitParameter(PROP_PARSER);
+
+ if (tmp != null) {
+ if (tmp.trim().equals("CertReqParser.NODETAIL_PARSER"))
+ mParser = CertReqParser.NODETAIL_PARSER;
+ else if (tmp.trim().equals("CertReqParser.DETAIL_PARSER"))
+ mParser = CertReqParser.DETAIL_PARSER;
+ else if (tmp.trim().equals("KeyReqParser.PARSER"))
+ mParser = KeyReqParser.PARSER;
+ }
+
+ // override success and error templates to null -
+ // handle templates locally.
+ mTemplates.remove(ICMSRequest.SUCCESS);
+ mTemplates.remove(ICMSRequest.ERROR);
+
+ if (mOutputTemplatePath != null)
+ mFormPath = mOutputTemplatePath;
+ }
+
+ /**
+ * Serves HTTP request. This format of this request is as follows:
+ * queryCert?
+ * [maxCount=<number>]
+ * [queryFilter=<filter>]
+ * [revokeAll=<filter>]
+ */
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "list");
+ } catch (EAuthzAccessDenied e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
+ }
+
+ if (authzToken == null) {
+ cmsReq.setStatus(ICMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ EBaseException error = null;
+ int maxResults = -1;
+ int timeLimit = -1;
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ CMSTemplate form = null;
+ Locale[] locale = new Locale[1];
+
+ try {
+ form = getTemplate(mFormPath, req, locale);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ try {
+ String maxResultsStr = req.getParameter("maxResults");
+
+ if (maxResultsStr != null && maxResultsStr.length() > 0)
+ maxResults = Integer.parseInt(maxResultsStr);
+ String timeLimitStr = req.getParameter("timeLimit");
+
+ if (timeLimitStr != null && timeLimitStr.length() > 0)
+ timeLimit = Integer.parseInt(timeLimitStr);
+
+ process(argSet, header, req.getParameter("queryRequestFilter"), authToken,
+ maxResults, timeLimit, req, resp, locale[0]);
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT"));
+ error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT"));
+ } catch (EBaseException e) {
+ error = e;
+ }
+
+ try {
+ ServletOutputStream out = resp.getOutputStream();
+
+ if (error == null) {
+ String xmlOutput = req.getParameter("xml");
+ if (xmlOutput != null && xmlOutput.equals("true")) {
+ outputXML(resp, argSet);
+ } else {
+ cmsReq.setStatus(ICMSRequest.SUCCESS);
+ resp.setContentType("text/html");
+ form.renderOutput(out, argSet);
+ }
+ } else {
+ cmsReq.setStatus(ICMSRequest.ERROR);
+ cmsReq.setError(error);
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+ }
+
+ /**
+ * Process the key search.
+ */
+ private void process(CMSTemplateParams argSet, IArgBlock header,
+ String filter, IAuthToken token,
+ int maxResults, int timeLimit,
+ HttpServletRequest req, HttpServletResponse resp,
+ Locale locale)
+ throws EBaseException {
+
+ try {
+ long startTime = CMS.getCurrentDate().getTime();
+
+ if (filter.indexOf(CURRENT_TIME, 0) > -1) {
+ filter = insertCurrentTime(filter);
+ }
+
+ String owner = req.getParameter("owner");
+ String requestowner_filter = "";
+ String newfilter = "";
+ if (owner.length() == 0) {
+ newfilter = filter;
+ } else {
+ if (owner.equals("self")) {
+ String self_uid = token.getInString(IAuthToken.USER_ID);
+ requestowner_filter = "(requestowner=" + self_uid + ")";
+ } else {
+ String uid = req.getParameter("uid");
+ requestowner_filter = "(requestowner=" + uid + ")";
+ }
+ newfilter = "(&" + requestowner_filter + filter.substring(2);
+ }
+ // xxx the filter includes serial number range???
+ if (maxResults == -1 || maxResults > mMaxReturns) {
+ CMS.debug("Resetting maximum of returned results from " + maxResults + " to " + mMaxReturns);
+ maxResults = mMaxReturns;
+ }
+ if (timeLimit == -1 || timeLimit > mTimeLimits) {
+ CMS.debug("Resetting timelimit from " + timeLimit + " to " + mTimeLimits);
+ timeLimit = mTimeLimits;
+ }
+ IRequestList list = (timeLimit > 0) ?
+ mQueue.listRequestsByFilter(newfilter, maxResults, timeLimit) :
+ mQueue.listRequestsByFilter(newfilter, maxResults);
+
+ int count = 0;
+
+ while (list != null && list.hasMoreElements()) {
+ IRequest request = list.nextRequestObject();
+
+ if (request != null) {
+ count++;
+ IArgBlock rarg = CMS.createArgBlock();
+ mParser.fillRequestIntoArg(locale, request, argSet, rarg);
+ argSet.addRepeatRecord(rarg);
+ long endTime = CMS.getCurrentDate().getTime();
+
+ header.addIntegerValue(OUT_CURRENTCOUNT, count);
+ header.addStringValue("time", Long.toString(endTime - startTime));
+ }
+ }
+ header.addIntegerValue(OUT_TOTALCOUNT, count);
+ } catch (EBaseException e) {
+ CMS.getLogMessage("CMSGW_ERROR_LISTCERTS", e.toString());
+ throw e;
+ }
+ return;
+ }
+
+ private String insertCurrentTime(String filter) {
+ Date now = null;
+ StringBuffer newFilter = new StringBuffer();
+ int k = 0;
+ int i = filter.indexOf(CURRENT_TIME, k);
+
+ while (i > -1) {
+ if (now == null)
+ now = new Date();
+ newFilter.append(filter.substring(k, i));
+ newFilter.append(now.getTime());
+ k = i + CURRENT_TIME.length();
+ i = filter.indexOf(CURRENT_TIME, k);
+ }
+ if (k > 0) {
+ newFilter.append(filter.substring(k, filter.length()));
+ }
+ return newFilter.toString();
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/TPSConnectorService.java b/base/server/cms/src/com/netscape/cms/servlet/tks/TPSConnectorService.java
new file mode 100644
index 000000000..26f25bd4f
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/TPSConnectorService.java
@@ -0,0 +1,421 @@
+package com.netscape.cms.servlet.tks;
+
+import java.io.IOException;
+import java.net.URI;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.TreeSet;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+import org.jboss.resteasy.plugins.providers.atom.Link;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.crypto.InvalidKeyFormatException;
+import org.mozilla.jss.crypto.TokenException;
+
+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.PKIException;
+import com.netscape.certsrv.base.ResourceNotFoundException;
+import com.netscape.certsrv.base.UnauthorizedException;
+import com.netscape.certsrv.key.KeyData;
+import com.netscape.certsrv.system.TPSConnectorCollection;
+import com.netscape.certsrv.system.TPSConnectorData;
+import com.netscape.certsrv.system.TPSConnectorResource;
+import com.netscape.certsrv.tps.cert.TPSCertResource;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cms.realm.PKIPrincipal;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+import com.netscape.cmsutil.util.Utils;
+
+public class TPSConnectorService implements TPSConnectorResource {
+
+ private static final String TPS_LIST = "tps.list";
+
+ IConfigStore cs = CMS.getConfigStore();
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public IUGSubsystem userGroupManager = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+
+ @Override
+ public TPSConnectorCollection listConnectors() {
+ try {
+ TPSConnectorCollection ret = new TPSConnectorCollection();
+ String tpsList = cs.getString(TPS_LIST, "");
+
+ for (String tpsID : StringUtils.split(tpsList,",")) {
+ ret.addEntry(createTPSConnectorData(tpsID));
+ }
+ return ret;
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ throw new PKIException("Unable to get TPS connection data" + e);
+ }
+ }
+
+ private TPSConnectorData createTPSConnectorData(String tpsID) throws EBaseException {
+ TPSConnectorData data = new TPSConnectorData();
+ data.setID(tpsID);
+ data.setHost(cs.getString("tps." + tpsID + ".host", ""));
+ data.setPort(cs.getString("tps." + tpsID + ".port", ""));
+ data.setUserID(cs.getString("tps." + tpsID + ".userid", ""));
+ data.setNickname(cs.getString("tps." + tpsID + ".nickname", ""));
+ URI uri = uriInfo.getBaseUriBuilder().path(TPSCertResource.class).path("{id}").build(tpsID);
+ data.setLink(new Link("self", uri));
+ return data;
+ }
+
+ @Override
+ public TPSConnectorData getConnector(String id) {
+ try {
+ if (connectorExists(id)) return createTPSConnectorData(id);
+ throw new ResourceNotFoundException("Connector " + id + " not found.");
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ throw new PKIException("Unable to get TPS connection data" + e);
+ }
+ }
+
+ @Override
+ public TPSConnectorData getConnector(String host, String port) {
+ try {
+ String id = getConnectorID(host, port);
+ if (id != null) return createTPSConnectorData(id);
+ throw new ResourceNotFoundException(
+ "Connector not found for " + host + ":" + port);
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ throw new PKIException("Unable to get TPS connection data" + e);
+ }
+ }
+
+ @Override
+ public Response createConnector(String tpsHost, String tpsPort) {
+ try {
+ String id = getConnectorID(tpsHost, tpsPort);
+ if (id != null) {
+ URI uri = uriInfo.getBaseUriBuilder().path(TPSCertResource.class)
+ .path("{id}").build(id);
+ throw new BadRequestException("TPS connection already exists at " + uri.toString());
+ }
+ String newID = findNextConnectorID();
+
+ TPSConnectorData newData = new TPSConnectorData();
+ newData.setID(newID);
+ newData.setHost(tpsHost);
+ newData.setPort(tpsPort);
+ newData.setUserID("TPS-" + tpsHost + "-" + tpsPort);
+ URI uri = uriInfo.getBaseUriBuilder().path(TPSCertResource.class).path("{id}").build(newID);
+ newData.setLink(new Link("self", uri));
+ saveClientData(newData);
+
+ addToConnectorList(newID);
+ cs.commit(true);
+
+ return Response
+ .created(newData.getLink().getHref())
+ .entity(newData)
+ .type(MediaType.APPLICATION_XML)
+ .build();
+
+ } catch (EBaseException e) {
+ CMS.debug("Unable to create new TPS Connector: " + e);
+ e.printStackTrace();
+ throw new PKIException("Unable to create new TPS connector: " + e);
+ }
+ }
+
+ @Override
+ public Response modifyConnector(String id, TPSConnectorData data) {
+ try {
+ if (id == null) {
+ throw new BadRequestException("Invalid connector ID");
+ }
+
+ if (!connectorExists(id)) {
+ throw new ResourceNotFoundException("TPS connection does not exist");
+ }
+
+ // Note: we are deliberately NOT allowing the userid to be modified by the
+ // admin here, because this is what maps to a user cert to retrieve the shared
+ // secret
+ if ((data.getUserID() != null) || (data.getNickname() != null)) {
+ throw new UnauthorizedException("Cannot change userid or nickname using this interface");
+ }
+ TPSConnectorData curData = getConnector(id);
+ curData.setHost(data.getHost());
+ curData.setPort(data.getPort());
+
+ saveClientData(curData);
+ cs.commit(true);
+
+ return Response
+ .ok(curData.getLink().getHref())
+ .entity(curData)
+ .type(MediaType.APPLICATION_XML)
+ .build();
+ } catch (EBaseException e) {
+ CMS.debug("Unable to modify TPS Connector: " + e);
+ e.printStackTrace();
+ throw new PKIException("Unable to modify TPS Connector: " + e);
+ }
+ }
+
+ private void saveClientData(TPSConnectorData newData) throws EBaseException {
+ String id = newData.getID();
+ if (StringUtils.isEmpty(id)) {
+ CMS.debug("saveClientData: Attempt to save tps connection with null or empty id");
+ return;
+ }
+ String prefix = "tps." + id + ".";
+
+ if (newData.getHost() != null)
+ cs.putString(prefix + "host", newData.getHost());
+ if (newData.getPort() != null)
+ cs.putString(prefix + "port", newData.getPort());
+ if (newData.getUserID() != null)
+ cs.putString(prefix + "userid", newData.getUserID());
+ if (newData.getNickname() != null)
+ cs.putString(prefix + "nickname", newData.getNickname());
+ }
+
+ @Override
+ public void deleteConnector(String id) {
+ try {
+ if (StringUtils.isEmpty(id))
+ throw new BadRequestException("Attempt to delete TPS connection with null or empty id");
+
+ if (!connectorExists(id)) return;
+
+ deleteSharedSecret(id);
+ cs.removeSubStore("tps." + id);
+ removeFromConnectorList(id);
+ cs.commit(true);
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ throw new PKIException("Failed to delete TPS connection" + e);
+ }
+ }
+
+ @Override
+ public void deleteConnector(String host, String port) {
+ String id;
+ try {
+ id = getConnectorID(host, port);
+ deleteConnector(id);
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ throw new PKIException("Failed to delete TPS connector: " + e);
+ }
+ }
+
+ @Override
+ public KeyData createSharedSecret(String id) {
+ try {
+ if (!connectorExists(id)) {
+ throw new ResourceNotFoundException("TPS connection does not exist");
+ }
+
+ // get and validate user
+ String userid = validateUser(id);
+
+ // get user cert
+ IUser user = userGroupManager.getUser(userid);
+ X509Certificate[] certs = user.getX509Certificates();
+
+ String nickname = userid + " sharedSecret";
+ if (CryptoUtil.sharedSecretExists(nickname)) {
+ throw new BadRequestException("Shared secret already exists");
+ }
+
+ CryptoUtil.createSharedSecret(nickname);
+
+ cs.putString("tps." + id + ".nickname", nickname);
+ cs.commit(true);
+
+ byte[] wrappedKey = CryptoUtil.exportSharedSecret(nickname, certs[0]);
+ KeyData keyData = new KeyData();
+ keyData.setWrappedPrivateData(Utils.base64encode(wrappedKey));
+ return keyData;
+
+ } catch (InvalidKeyException | IllegalStateException | NoSuchAlgorithmException
+ | InvalidAlgorithmParameterException | EBaseException
+ | NotInitializedException | TokenException | IOException | InvalidKeyFormatException e) {
+ e.printStackTrace();
+ CMS.debug("Error in generating and exporting shared secret: " + e);
+ throw new PKIException("Error in generating and exporting shared secret: " + e);
+ }
+ }
+
+ private String validateUser(String id) throws EBaseException {
+ String userid = cs.getString("tps." + id + ".userid", "");
+ if (userid.isEmpty()) {
+ throw new PKIException("Bad TPS connection configuration: userid not defined");
+ }
+
+ PKIPrincipal principal = (PKIPrincipal) servletRequest.getUserPrincipal();
+ if (principal == null) {
+ throw new UnauthorizedException("User credentials not provided");
+ }
+
+ String uid = principal.getName();
+ if (!uid.equals(userid)) {
+ throw new UnauthorizedException("TPS Connection belongs to another user");
+ }
+ return userid;
+ }
+
+ @Override
+ public KeyData replaceSharedSecret(String id) {
+ try {
+ if (!connectorExists(id)) {
+ throw new ResourceNotFoundException("TPS connection does not exist");
+ }
+
+ // get and validate user
+ String userid = validateUser(id);
+
+ String nickname = userid + " sharedSecret";
+ if (!CryptoUtil.sharedSecretExists(nickname)) {
+ throw new BadRequestException("Cannot replace. Shared secret does not exist");
+ }
+
+ // get user cert
+ IUser user = userGroupManager.getUser(userid);
+ X509Certificate[] certs = user.getX509Certificates();
+
+ CryptoUtil.deleteSharedSecret(nickname);
+ CryptoUtil.createSharedSecret(nickname);
+ byte[] wrappedKey = CryptoUtil.exportSharedSecret(nickname, certs[0]);
+ KeyData keyData = new KeyData();
+ keyData.setWrappedPrivateData(Utils.base64encode(wrappedKey));
+ return keyData;
+ } catch (InvalidKeyException | IllegalStateException | NoSuchAlgorithmException
+ | InvalidAlgorithmParameterException | EBaseException
+ | NotInitializedException | TokenException | IOException | InvalidKeyFormatException e) {
+ e.printStackTrace();
+ CMS.debug("Error in replacing shared secret: " + e);
+ throw new PKIException("Error in replacing shared secret: " + e);
+ }
+ }
+
+ @Override
+ public void deleteSharedSecret(String id) {
+ try {
+ if (!connectorExists(id)) {
+ return;
+ }
+
+ // get user
+ String userid = cs.getString("tps." + id + ".userid", "");
+ if (userid.isEmpty()) {
+ throw new PKIException("Bad TPS connection configuration: userid not defined");
+ }
+
+ String nickname = userid + " sharedSecret";
+ if (!CryptoUtil.sharedSecretExists(nickname)) {
+ return;
+ }
+ CryptoUtil.deleteSharedSecret(nickname);
+
+ cs.putString("tps." + id + ".nickname", "");
+ cs.commit(true);
+ } catch (InvalidKeyException | IllegalStateException | EBaseException
+ | NotInitializedException | TokenException e) {
+ e.printStackTrace();
+ CMS.debug("Error in deleting shared secret: " + e);
+ throw new PKIException("Error in deleting shared secret: " + e);
+ }
+ }
+
+ @Override
+ public KeyData getSharedSecret(String id) {
+ try {
+ if (!connectorExists(id)) {
+ throw new ResourceNotFoundException("TPS connection does not exist");
+ }
+
+ // get and validate user
+ String userid = validateUser(id);
+
+ String nickname = userid + " sharedSecret";
+ if (!CryptoUtil.sharedSecretExists(nickname)) {
+ return null;
+ }
+
+ // get user cert
+ IUser user = userGroupManager.getUser(userid);
+ X509Certificate[] certs = user.getX509Certificates();
+
+ byte[] wrappedKey = CryptoUtil.exportSharedSecret(nickname, certs[0]);
+ KeyData keyData = new KeyData();
+ keyData.setWrappedPrivateData(Utils.base64encode(wrappedKey));
+ return keyData;
+ } catch (InvalidKeyException | IllegalStateException | NoSuchAlgorithmException
+ | InvalidAlgorithmParameterException | EBaseException
+ | NotInitializedException | TokenException | IOException | InvalidKeyFormatException e) {
+ e.printStackTrace();
+ CMS.debug("Error in obtaining shared secret: " + e);
+ throw new PKIException("Error in obtaining shared secret: " + e);
+ }
+ }
+
+ private boolean connectorExists(String id) throws EBaseException {
+ String tpsList = cs.getString(TPS_LIST, "");
+ return ArrayUtils.contains(StringUtils.split(tpsList, ","), id);
+ }
+
+ private String getConnectorID(String host, String port) throws EBaseException {
+ String tpsList = cs.getString(TPS_LIST, "");
+ for (String tpsID : StringUtils.split(tpsList,",")) {
+ TPSConnectorData data = createTPSConnectorData(tpsID);
+ if (data.getHost().equals(host) && data.getPort().equals(port))
+ return tpsID;
+ }
+ return null;
+ }
+
+ private void addToConnectorList(String id) throws EBaseException {
+ String tpsList = cs.getString(TPS_LIST, "");
+ Collection<String> sorted = new TreeSet<String>();
+ sorted.addAll(Arrays.asList(StringUtils.split(tpsList, ",")));
+ sorted.add(id);
+ cs.putString(TPS_LIST, StringUtils.join(sorted, ","));
+ }
+
+ private void removeFromConnectorList(String id) throws EBaseException {
+ String tpsList = cs.getString(TPS_LIST, "");
+ Collection<String> sorted = new TreeSet<String>();
+ sorted.addAll(Arrays.asList(StringUtils.split(tpsList, ",")));
+ sorted.remove(id);
+ cs.putString(TPS_LIST, StringUtils.join(sorted, ","));
+ }
+
+ private String findNextConnectorID() throws EBaseException {
+ String tpsList = cs.getString(TPS_LIST, "");
+ Collection<String> sorted = new TreeSet<String>();
+ sorted.addAll(Arrays.asList(StringUtils.split(tpsList, ",")));
+
+ int index = 0;
+ while (sorted.contains(Integer.toString(index))) index++;
+ return Integer.toString(index);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java b/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java
new file mode 100644
index 000000000..766975651
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java
@@ -0,0 +1,1353 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.tks;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.KeyWrapAlgorithm;
+import org.mozilla.jss.crypto.KeyWrapper;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.pkcs11.PK11SymKey;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IPrettyPrintFormat;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cms.servlet.base.CMSServlet;
+import com.netscape.cms.servlet.common.CMSRequest;
+import com.netscape.symkey.SessionKey;
+
+/**
+ * A class representings an administration servlet for Token Key
+ * Service Authority. This servlet is responsible to serve
+ * tks administrative operation such as configuration
+ * parameter updates.
+ *
+ * @version $Revision$, $Date$
+ */
+public class TokenServlet extends CMSServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8687436109695172791L;
+ protected static final String PROP_ENABLED = "enabled";
+ protected static final String TRANSPORT_KEY_NAME = "sharedSecret";
+ private final static String INFO = "TokenServlet";
+ public static int ERROR = 1;
+ String mKeyNickName = null;
+ String mNewKeyNickName = null;
+ IPrettyPrintFormat pp = CMS.getPrettyPrintFormat(":");
+
+ private final static String LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST =
+ "LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_3";
+
+ private final static String LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS_8";
+
+ private final static String LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE =
+ "LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE_9";
+
+ private final static String LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST =
+ "LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_5";
+
+ private final static String LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS_6";
+
+ private final static String LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE =
+ "LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE_7";
+
+ private final static String LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST =
+ "LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_4";
+
+ private final static String LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS_7";
+
+ private final static String LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE =
+ "LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE_8";
+
+ private final static String LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST =
+ "LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_2";
+
+ private final static String LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS =
+ "LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS_3";
+
+ private final static String LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE =
+ "LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE_4";
+
+ /**
+ * Constructs tks servlet.
+ */
+ public TokenServlet() {
+ super();
+
+ }
+
+ public static String trim(String a) {
+ StringBuffer newa = new StringBuffer();
+ StringTokenizer tokens = new StringTokenizer(a, "\n");
+ while (tokens.hasMoreTokens()) {
+ newa.append(tokens.nextToken());
+ }
+ return newa.toString();
+ }
+
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ }
+
+ /**
+ * Returns serlvet information.
+ *
+ * @return name of this servlet
+ */
+ public String getServletInfo() {
+ return INFO;
+ }
+
+ /**
+ * Process the HTTP request.
+ *
+ * @param s The URL to decode.
+ */
+ protected String URLdecode(String s) {
+ if (s == null)
+ return null;
+ ByteArrayOutputStream out = new ByteArrayOutputStream(s.length());
+
+ for (int i = 0; i < s.length(); i++) {
+ int c = s.charAt(i);
+
+ if (c == '+') {
+ out.write(' ');
+ } else if (c == '%') {
+ int c1 = Character.digit(s.charAt(++i), 16);
+ int c2 = Character.digit(s.charAt(++i), 16);
+
+ out.write((char) (c1 * 16 + c2));
+ } else {
+ out.write(c);
+ }
+ } // end for
+ return out.toString();
+ }
+
+ private void setDefaultSlotAndKeyName(HttpServletRequest req) {
+ try {
+
+ String keySet = req.getParameter("keySet");
+ if (keySet == null || keySet.equals("")) {
+ keySet = "defKeySet";
+ }
+ CMS.debug("keySet selected: " + keySet);
+
+ String masterKeyPrefix = CMS.getConfigStore().getString("tks.master_key_prefix", null);
+ String temp = req.getParameter("KeyInfo"); //#xx#xx
+ String keyInfoMap = "tks." + keySet + ".mk_mappings." + temp;
+ String mappingValue = CMS.getConfigStore().getString(keyInfoMap, null);
+ if (mappingValue != null) {
+ StringTokenizer st = new StringTokenizer(mappingValue, ":");
+ int tokenNumber = 0;
+ while (st.hasMoreTokens()) {
+
+ String currentToken = st.nextToken();
+ if (tokenNumber == 1)
+ mKeyNickName = currentToken;
+ tokenNumber++;
+
+ }
+ }
+ if (req.getParameter("newKeyInfo") != null) // for diversification
+ {
+ temp = req.getParameter("newKeyInfo"); //#xx#xx
+ String newKeyInfoMap = "tks." + keySet + ".mk_mappings." + temp;
+ String newMappingValue = CMS.getConfigStore().getString(newKeyInfoMap, null);
+ if (newMappingValue != null) {
+ StringTokenizer st = new StringTokenizer(newMappingValue, ":");
+ int tokenNumber = 0;
+ while (st.hasMoreTokens()) {
+ String currentToken = st.nextToken();
+ if (tokenNumber == 1)
+ mNewKeyNickName = currentToken;
+ tokenNumber++;
+
+ }
+ }
+ }
+
+ SessionKey.SetDefaultPrefix(masterKeyPrefix);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ CMS.debug("Exception in TokenServlet::setDefaultSlotAndKeyName");
+ }
+
+ }
+
+ private void processComputeSessionKey(HttpServletRequest req,
+ HttpServletResponse resp) throws EBaseException {
+ byte[] card_challenge, host_challenge, keyInfo, xCUID, CUID, session_key;
+ byte[] card_crypto, host_cryptogram, input_card_crypto;
+ byte[] xcard_challenge, xhost_challenge;
+ byte[] enc_session_key, xkeyInfo;
+ String auditMessage = null;
+ String errorMsg = "";
+ String badParams = "";
+ String transportKeyName = "";
+
+ String rCUID = req.getParameter("CUID");
+ String keySet = req.getParameter("keySet");
+ if (keySet == null || keySet.equals("")) {
+ keySet = "defKeySet";
+ }
+ CMS.debug("keySet selected: " + keySet);
+
+ boolean serversideKeygen = false;
+ byte[] drm_trans_wrapped_desKey = null;
+ PK11SymKey desKey = null;
+ // PK11SymKey kek_session_key;
+ PK11SymKey kek_key;
+
+ IConfigStore sconfig = CMS.getConfigStore();
+ boolean isCryptoValidate = true;
+ boolean missingParam = false;
+ session_key = null;
+ card_crypto = null;
+ host_cryptogram = null;
+ enc_session_key = null;
+ // kek_session_key = null;
+
+ SessionContext sContext = SessionContext.getContext();
+
+ String agentId = "";
+ if (sContext != null) {
+ agentId =
+ (String) sContext.get(SessionContext.USER_ID);
+ }
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST,
+ rCUID,
+ ILogger.SUCCESS,
+ agentId);
+
+ audit(auditMessage);
+
+ String kek_wrapped_desKeyString = null;
+ String keycheck_s = null;
+
+ CMS.debug("processComputeSessionKey:");
+ String useSoftToken_s = CMS.getConfigStore().getString("tks.useSoftToken", "true");
+ if (!useSoftToken_s.equalsIgnoreCase("true"))
+ useSoftToken_s = "false";
+
+ String rServersideKeygen = req.getParameter("serversideKeygen");
+ if (rServersideKeygen.equals("true")) {
+ CMS.debug("TokenServlet: serversideKeygen requested");
+ serversideKeygen = true;
+ } else {
+ CMS.debug("TokenServlet: serversideKeygen not requested");
+ }
+
+ try {
+ isCryptoValidate = sconfig.getBoolean("cardcryptogram.validate.enable", true);
+ } catch (EBaseException eee) {
+ }
+
+ transportKeyName = getSharedSecretName(sconfig);
+
+ CMS.debug("TokenServlet: ComputeSessionKey(): tksSharedSymKeyName: " + transportKeyName);
+
+ String rcard_challenge = req.getParameter("card_challenge");
+ String rhost_challenge = req.getParameter("host_challenge");
+ String rKeyInfo = req.getParameter("KeyInfo");
+ String rcard_cryptogram = req.getParameter("card_cryptogram");
+ if ((rCUID == null) || (rCUID.equals(""))) {
+ CMS.debug("TokenServlet: ComputeSessionKey(): missing request parameter: CUID");
+ badParams += " CUID,";
+ missingParam = true;
+ }
+
+ if ((rcard_challenge == null) || (rcard_challenge.equals(""))) {
+ badParams += " card_challenge,";
+ CMS.debug("TokenServlet: ComputeSessionKey(): missing request parameter: card challenge");
+ missingParam = true;
+ }
+
+ if ((rhost_challenge == null) || (rhost_challenge.equals(""))) {
+ badParams += " host_challenge,";
+ CMS.debug("TokenServlet: ComputeSessionKey(): missing request parameter: host challenge");
+ missingParam = true;
+ }
+
+ if ((rKeyInfo == null) || (rKeyInfo.equals(""))) {
+ badParams += " KeyInfo,";
+ CMS.debug("TokenServlet: ComputeSessionKey(): missing request parameter: key info");
+ missingParam = true;
+ }
+
+ String selectedToken = null;
+ String keyNickName = null;
+ boolean sameCardCrypto = true;
+
+ if (!missingParam) {
+
+ xCUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID);
+ if (xCUID == null || xCUID.length != 10) {
+ badParams += " CUID length,";
+ CMS.debug("TokenServlet: Invalid CUID length");
+ missingParam = true;
+ }
+ xkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo);
+ if (xkeyInfo == null || xkeyInfo.length != 2) {
+ badParams += " KeyInfo length,";
+ CMS.debug("TokenServlet: Invalid key info length.");
+ missingParam = true;
+ }
+ xcard_challenge =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(rcard_challenge);
+ if (xcard_challenge == null || xcard_challenge.length != 8) {
+ badParams += " card_challenge length,";
+ CMS.debug("TokenServlet: Invalid card challenge length.");
+ missingParam = true;
+ }
+
+ xhost_challenge = com.netscape.cmsutil.util.Utils.SpecialDecode(rhost_challenge);
+ if (xhost_challenge == null || xhost_challenge.length != 8) {
+ badParams += " host_challenge length,";
+ CMS.debug("TokenServlet: Invalid host challenge length");
+ missingParam = true;
+ }
+
+ }
+
+ CUID = null;
+ if (!missingParam) {
+ card_challenge =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(rcard_challenge);
+
+ host_challenge = com.netscape.cmsutil.util.Utils.SpecialDecode(rhost_challenge);
+ keyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo);
+
+ CUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID);
+
+ String keyInfoMap = "tks." + keySet + ".mk_mappings." + rKeyInfo; //#xx#xx
+ String mappingValue = CMS.getConfigStore().getString(keyInfoMap, null);
+ if (mappingValue == null) {
+ selectedToken =
+ CMS.getConfigStore().getString("tks.defaultSlot", "internal");
+ keyNickName = rKeyInfo;
+ } else {
+ StringTokenizer st = new StringTokenizer(mappingValue, ":");
+ if (st.hasMoreTokens())
+ selectedToken = st.nextToken();
+ if (st.hasMoreTokens())
+ keyNickName = st.nextToken();
+ }
+
+ if (selectedToken != null && keyNickName != null) {
+
+ try {
+
+ byte macKeyArray[] =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks."
+ + keySet + ".mac_key"));
+ CMS.debug("TokenServlet about to try ComputeSessionKey selectedToken="
+ + selectedToken + " keyNickName=" + keyNickName);
+ session_key = SessionKey.ComputeSessionKey(
+ selectedToken, keyNickName, card_challenge,
+ host_challenge, keyInfo, CUID, macKeyArray, useSoftToken_s, keySet, transportKeyName);
+
+ if (session_key == null) {
+ CMS.debug("TokenServlet:Tried ComputeSessionKey, got NULL ");
+ throw new Exception("Can't compute session key!");
+
+ }
+
+ byte encKeyArray[] =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks."
+ + keySet + ".auth_key"));
+ enc_session_key = SessionKey.ComputeEncSessionKey(
+ selectedToken, keyNickName, card_challenge,
+ host_challenge, keyInfo, CUID, encKeyArray, useSoftToken_s, keySet);
+
+ if (enc_session_key == null) {
+ CMS.debug("TokenServlet:Tried ComputeEncSessionKey, got NULL ");
+ throw new Exception("Can't compute enc session key!");
+
+ }
+
+ if (serversideKeygen == true) {
+
+ /**
+ * 0. generate des key
+ * 1. encrypt des key with kek key
+ * 2. encrypt des key with DRM transport key
+ * These two wrapped items are to be sent back to
+ * TPS. 2nd item is to DRM
+ **/
+ CMS.debug("TokenServlet: calling ComputeKekKey");
+
+ byte kekKeyArray[] =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks."
+ + keySet + ".kek_key"));
+
+ kek_key = SessionKey.ComputeKekKey(
+ selectedToken, keyNickName, card_challenge,
+ host_challenge, keyInfo, CUID, kekKeyArray, useSoftToken_s, keySet);
+
+ CMS.debug("TokenServlet: called ComputeKekKey");
+
+ if (kek_key == null) {
+ CMS.debug("TokenServlet:Tried ComputeKekKey, got NULL ");
+ throw new Exception("Can't compute kek key!");
+
+ }
+ // now use kek key to wrap kek session key..
+ CMS.debug("computeSessionKey:kek key len =" +
+ kek_key.getLength());
+
+ // (1) generate DES key
+ /* applet does not support DES3
+ org.mozilla.jss.crypto.KeyGenerator kg =
+ internalToken.getKeyGenerator(KeyGenAlgorithm.DES3);
+ desKey = kg.generate();*/
+
+ /*
+ * GenerateSymkey firt generates a 16 byte DES2 key.
+ * It then pads it into a 24 byte key with last
+ * 8 bytes copied from the 1st 8 bytes. Effectively
+ * making it a 24 byte DES2 key. We need this for
+ * wrapping private keys on DRM.
+ */
+ /*generate it on whichever token the master key is at*/
+ if (useSoftToken_s.equals("true")) {
+ CMS.debug("TokenServlet: key encryption key generated on internal");
+ //cfu audit here? sym key gen
+ desKey = SessionKey.GenerateSymkey("internal");
+ //cfu audit here? sym key gen done
+ } else {
+ CMS.debug("TokenServlet: key encryption key generated on " + selectedToken);
+ desKey = SessionKey.GenerateSymkey(selectedToken);
+ }
+ if (desKey != null)
+ CMS.debug("TokenServlet: key encryption key generated for " + rCUID);
+ else {
+ CMS.debug("TokenServlet: key encryption key generation failed for " + rCUID);
+ throw new Exception("can't generate key encryption key");
+ }
+
+ /*
+ * ECBencrypt actually takes the 24 byte DES2 key
+ * and discard the last 8 bytes before it encrypts.
+ * This is done so that the applet can digest it
+ */
+ byte[] encDesKey =
+ SessionKey.ECBencrypt(kek_key,
+ desKey);
+ /*
+ CMS.debug("computeSessionKey:encrypted desKey size = "+encDesKey.length);
+ CMS.debug(encDesKey);
+ */
+
+ kek_wrapped_desKeyString =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(encDesKey);
+
+ // get keycheck
+ byte[] keycheck =
+ SessionKey.ComputeKeyCheck(desKey);
+ /*
+ CMS.debug("computeSessionKey:keycheck size = "+keycheck.length);
+ CMS.debug(keycheck);
+ */
+ keycheck_s =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(keycheck);
+
+ //use DRM transport cert to wrap desKey
+ String drmTransNickname = CMS.getConfigStore().getString("tks.drm_transport_cert_nickname", "");
+
+ if ((drmTransNickname == null) || (drmTransNickname == "")) {
+ CMS.debug("TokenServlet:did not find DRM transport certificate nickname");
+ throw new Exception("can't find DRM transport certificate nickname");
+ } else {
+ CMS.debug("TokenServlet:drmtransport_cert_nickname=" + drmTransNickname);
+ }
+
+ X509Certificate drmTransCert = null;
+ drmTransCert = CryptoManager.getInstance().findCertByNickname(drmTransNickname);
+ // wrap kek session key with DRM transport public key
+ CryptoToken token = null;
+ if (useSoftToken_s.equals("true")) {
+ //token = CryptoManager.getInstance().getTokenByName(selectedToken);
+ token = CryptoManager.getInstance().getInternalCryptoToken();
+ } else {
+ token = CryptoManager.getInstance().getTokenByName(selectedToken);
+ }
+ PublicKey pubKey = drmTransCert.getPublicKey();
+ String pubKeyAlgo = pubKey.getAlgorithm();
+ CMS.debug("Transport Cert Key Algorithm: " + pubKeyAlgo);
+ KeyWrapper keyWrapper = null;
+ //For wrapping symmetric keys don't need IV, use ECB
+ if (pubKeyAlgo.equals("EC")) {
+ keyWrapper = token.getKeyWrapper(KeyWrapAlgorithm.AES_ECB);
+ keyWrapper.initWrap(pubKey, null);
+ } else {
+ keyWrapper = token.getKeyWrapper(KeyWrapAlgorithm.RSA);
+ keyWrapper.initWrap(pubKey, null);
+ }
+ CMS.debug("desKey token " + desKey.getOwningToken().getName() + " token: " + token.getName());
+ drm_trans_wrapped_desKey = keyWrapper.wrap(desKey);
+ CMS.debug("computeSessionKey:desKey wrapped with drm transportation key.");
+
+ } // if (serversideKeygen == true)
+
+ byte authKeyArray[] =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks."
+ + keySet + ".auth_key"));
+ host_cryptogram = SessionKey.ComputeCryptogram(
+ selectedToken, keyNickName, card_challenge,
+ host_challenge, keyInfo, CUID, 0, authKeyArray, useSoftToken_s, keySet);
+
+ if (host_cryptogram == null) {
+ CMS.debug("TokenServlet:Tried ComputeCryptogram, got NULL ");
+ throw new Exception("Can't compute host cryptogram!");
+
+ }
+ card_crypto = SessionKey.ComputeCryptogram(
+ selectedToken, keyNickName, card_challenge,
+ host_challenge, keyInfo, CUID, 1, authKeyArray, useSoftToken_s, keySet);
+
+ if (card_crypto == null) {
+ CMS.debug("TokenServlet:Tried ComputeCryptogram, got NULL ");
+ throw new Exception("Can't compute card cryptogram!");
+
+ }
+
+ if (isCryptoValidate) {
+ if (rcard_cryptogram == null) {
+ CMS.debug("TokenServlet: ComputeCryptogram(): missing card cryptogram");
+ throw new Exception("Missing card cryptogram");
+ }
+ input_card_crypto =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(rcard_cryptogram);
+ if (card_crypto.length == input_card_crypto.length) {
+ for (int i = 0; i < card_crypto.length; i++) {
+ if (card_crypto[i] != input_card_crypto[i]) {
+ sameCardCrypto = false;
+ break;
+ }
+ }
+ } else {
+ // different length; must be different
+ sameCardCrypto = false;
+ }
+ }
+
+ CMS.getLogger().log(ILogger.EV_AUDIT,
+ ILogger.S_TKS,
+ ILogger.LL_INFO, "processComputeSessionKey for CUID=" +
+ trim(pp.toHexString(CUID)));
+ } catch (Exception e) {
+ CMS.debug(e);
+ CMS.debug("TokenServlet Computing Session Key: " + e.toString());
+ if (isCryptoValidate)
+ sameCardCrypto = false;
+ }
+ }
+ } // ! missingParam
+
+ String value = "";
+
+ resp.setContentType("text/html");
+
+ String outputString = "";
+ String encSessionKeyString = "";
+ String drm_trans_wrapped_desKeyString = "";
+ String cryptogram = "";
+ String status = "0";
+ if (session_key != null && session_key.length > 0) {
+ outputString =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(session_key);
+ } else {
+
+ status = "1";
+ }
+
+ if (enc_session_key != null && enc_session_key.length > 0) {
+ encSessionKeyString =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(enc_session_key);
+ } else {
+ status = "1";
+ }
+
+ if (serversideKeygen == true) {
+ if (drm_trans_wrapped_desKey != null && drm_trans_wrapped_desKey.length > 0)
+ drm_trans_wrapped_desKeyString =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(drm_trans_wrapped_desKey);
+ else {
+ status = "1";
+ }
+ }
+
+ if (host_cryptogram != null && host_cryptogram.length > 0) {
+ cryptogram =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(host_cryptogram);
+ } else {
+ status = "2";
+ }
+
+ if (selectedToken == null || keyNickName == null) {
+ status = "4";
+ }
+
+ if (!sameCardCrypto) {
+ status = "3";
+ }
+
+ if (missingParam) {
+ status = "3";
+ }
+
+ if (!status.equals("0")) {
+
+ if (status.equals("1")) {
+ errorMsg = "Problem generating session key info.";
+ }
+
+ if (status.equals("2")) {
+ errorMsg = "Problem creating host_cryptogram.";
+ }
+
+ if (status.equals("4")) {
+ errorMsg = "Problem obtaining token information.";
+ }
+
+ if (status.equals("3")) {
+ if (badParams.endsWith(",")) {
+ badParams = badParams.substring(0, badParams.length() - 1);
+ }
+ errorMsg = "Missing input parameters :" + badParams;
+ }
+
+ value = "status=" + status;
+ } else {
+ if (serversideKeygen == true) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("status=0&");
+ sb.append("sessionKey=");
+ sb.append(outputString);
+ sb.append("&hostCryptogram=");
+ sb.append(cryptogram);
+ sb.append("&encSessionKey=");
+ sb.append(encSessionKeyString);
+ sb.append("&kek_wrapped_desKey=");
+ sb.append(kek_wrapped_desKeyString);
+ sb.append("&keycheck=");
+ sb.append(keycheck_s);
+ sb.append("&drm_trans_wrapped_desKey=");
+ sb.append(drm_trans_wrapped_desKeyString);
+ value = sb.toString();
+ } else {
+ StringBuffer sb = new StringBuffer();
+ sb.append("status=0&");
+ sb.append("sessionKey=");
+ sb.append(outputString);
+ sb.append("&hostCryptogram=");
+ sb.append(cryptogram);
+ sb.append("&encSessionKey=");
+ sb.append(encSessionKeyString);
+ value = sb.toString();
+ }
+
+ }
+ CMS.debug("TokenServlet:outputString.encode " + value);
+
+ try {
+ resp.setContentLength(value.length());
+ CMS.debug("TokenServlet:outputString.length " + value.length());
+ OutputStream ooss = resp.getOutputStream();
+ ooss.write(value.getBytes());
+ ooss.flush();
+ mRenderResult = false;
+ } catch (IOException e) {
+ CMS.debug("TokenServlet: " + e.toString());
+ }
+
+ if (status.equals("0")) {
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS,
+ rCUID,
+ ILogger.SUCCESS,
+ status,
+ agentId,
+ isCryptoValidate ? "true" : "false",
+ serversideKeygen ? "true" : "false",
+ selectedToken,
+ keyNickName);
+
+ } else {
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,
+ rCUID,
+ ILogger.FAILURE,
+ status,
+ agentId,
+ isCryptoValidate ? "true" : "false",
+ serversideKeygen ? "true" : "false",
+ selectedToken,
+ keyNickName,
+ errorMsg);
+ }
+
+ audit(auditMessage);
+ }
+
+ // This method will return the shared secret name. In new 10.1 subsystems, this
+ // name will be stored in tps.X.nickname.
+ //
+ // Until multiple TKS/TPS connections is fully supported, this method will just
+ // return the first shared secret nickname found, on the assumption that only
+ // one nickname will be configured. This will have to be changed to return the correct
+ // key based on some parameter in the request in future.
+ //
+ // On legacy systems, this method just returns what was previously returned.
+ private String getSharedSecretName(IConfigStore cs) throws EBaseException {
+ boolean useNewNames = cs.getBoolean("tks.useNewSharedSecretNames", false);
+
+ if (useNewNames) {
+ String tpsList = cs.getString("tps.list", "");
+ if (!tpsList.isEmpty()) {
+ for (String tpsID : tpsList.split(",")) {
+ String sharedSecretName = cs.getString("tps." + tpsID + ".nickname", "");
+ if (!sharedSecretName.isEmpty()) {
+ return sharedSecretName;
+ }
+ }
+ }
+ CMS.debug("getSharedSecretName: no shared secret has been configured");
+ throw new EBaseException("No shared secret has been configured");
+ }
+
+ // legacy system - return as before
+ return cs.getString("tks.tksSharedSymKeyName", TRANSPORT_KEY_NAME);
+ }
+
+ private void processDiversifyKey(HttpServletRequest req,
+ HttpServletResponse resp) throws EBaseException {
+ byte[] KeySetData, CUID, xCUID;
+ byte[] xkeyInfo, xnewkeyInfo;
+ boolean missingParam = false;
+ String errorMsg = "";
+ String badParams = "";
+
+ IConfigStore sconfig = CMS.getConfigStore();
+ String rnewKeyInfo = req.getParameter("newKeyInfo");
+ String newMasterKeyName = req.getParameter("newKeyInfo");
+ String oldMasterKeyName = req.getParameter("KeyInfo");
+ String rCUID = req.getParameter("CUID");
+ String auditMessage = "";
+
+ String keySet = req.getParameter("keySet");
+ if (keySet == null || keySet.equals("")) {
+ keySet = "defKeySet";
+ }
+ CMS.debug("keySet selected: " + keySet);
+
+ SessionContext sContext = SessionContext.getContext();
+
+ String agentId = "";
+ if (sContext != null) {
+ agentId =
+ (String) sContext.get(SessionContext.USER_ID);
+ }
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST,
+ rCUID,
+ ILogger.SUCCESS,
+ agentId,
+ oldMasterKeyName,
+ newMasterKeyName);
+
+ audit(auditMessage);
+
+ if ((rCUID == null) || (rCUID.equals(""))) {
+ badParams += " CUID,";
+ CMS.debug("TokenServlet: processDiversifyKey(): missing request parameter: CUID");
+ missingParam = true;
+ }
+ if ((rnewKeyInfo == null) || (rnewKeyInfo.equals(""))) {
+ badParams += " newKeyInfo,";
+ CMS.debug("TokenServlet: processDiversifyKey(): missing request parameter: newKeyInfo");
+ missingParam = true;
+ }
+ if ((oldMasterKeyName == null) || (oldMasterKeyName.equals(""))) {
+ badParams += " KeyInfo,";
+ CMS.debug("TokenServlet: processDiversifyKey(): missing request parameter: KeyInfo");
+ missingParam = true;
+ }
+
+ if (!missingParam) {
+ xkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(oldMasterKeyName);
+ if (xkeyInfo == null || xkeyInfo.length != 2) {
+ badParams += " KeyInfo length,";
+ CMS.debug("TokenServlet: Invalid key info length");
+ missingParam = true;
+ }
+ xnewkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(newMasterKeyName);
+ if (xnewkeyInfo == null || xnewkeyInfo.length != 2) {
+ badParams += " NewKeyInfo length,";
+ CMS.debug("TokenServlet: Invalid new key info length");
+ missingParam = true;
+ }
+ }
+ String useSoftToken_s = CMS.getConfigStore().getString("tks.useSoftToken", "true");
+ if (!useSoftToken_s.equalsIgnoreCase("true"))
+ useSoftToken_s = "false";
+
+ KeySetData = null;
+ if (!missingParam) {
+ xCUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID);
+ if (xCUID == null || xCUID.length != 10) {
+ badParams += " CUID length,";
+ CMS.debug("TokenServlet: Invalid CUID length");
+ missingParam = true;
+ }
+ }
+ if (!missingParam) {
+ CUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID);
+
+ if (mKeyNickName != null)
+ oldMasterKeyName = mKeyNickName;
+ if (mNewKeyNickName != null)
+ newMasterKeyName = mNewKeyNickName;
+
+ String oldKeyInfoMap = "tks." + keySet + ".mk_mappings." + req.getParameter("KeyInfo"); //#xx#xx
+ String oldMappingValue = CMS.getConfigStore().getString(oldKeyInfoMap, null);
+ String oldSelectedToken = null;
+ String oldKeyNickName = null;
+ if (oldMappingValue == null) {
+ oldSelectedToken = CMS.getConfigStore().getString("tks.defaultSlot", "internal");
+ oldKeyNickName = req.getParameter("KeyInfo");
+ } else {
+ StringTokenizer st = new StringTokenizer(oldMappingValue, ":");
+ oldSelectedToken = st.nextToken();
+ oldKeyNickName = st.nextToken();
+ }
+
+ String newKeyInfoMap = "tks.mk_mappings." + rnewKeyInfo; //#xx#xx
+ String newMappingValue = CMS.getConfigStore().getString(newKeyInfoMap, null);
+ String newSelectedToken = null;
+ String newKeyNickName = null;
+ if (newMappingValue == null) {
+ newSelectedToken = CMS.getConfigStore().getString("tks.defaultSlot", "internal");
+ newKeyNickName = rnewKeyInfo;
+ } else {
+ StringTokenizer st = new StringTokenizer(newMappingValue, ":");
+ newSelectedToken = st.nextToken();
+ newKeyNickName = st.nextToken();
+ }
+
+ CMS.debug("process DiversifyKey for oldSelectedToke=" +
+ oldSelectedToken + " newSelectedToken=" + newSelectedToken +
+ " oldKeyNickName=" + oldKeyNickName + " newKeyNickName=" +
+ newKeyNickName);
+
+ byte kekKeyArray[] =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".kek_key"));
+ KeySetData = SessionKey.DiversifyKey(oldSelectedToken,
+ newSelectedToken, oldKeyNickName,
+ newKeyNickName, rnewKeyInfo, CUID, kekKeyArray, useSoftToken_s, keySet);
+
+ if (KeySetData == null || KeySetData.length <= 1) {
+ CMS.getLogger().log(ILogger.EV_AUDIT,
+ ILogger.S_TKS,
+ ILogger.LL_INFO, "process DiversifyKey: Missing MasterKey in Slot");
+ }
+
+ CMS.getLogger().log(ILogger.EV_AUDIT,
+ ILogger.S_TKS,
+ ILogger.LL_INFO, "process DiversifyKey for CUID =" + trim(pp.toHexString(CUID))
+ + ";from oldMasterKeyName=" + oldSelectedToken + ":" + oldKeyNickName
+ + ";to newMasterKeyName=" + newSelectedToken + ":" + newKeyNickName);
+
+ resp.setContentType("text/html");
+ } // ! missingParam
+
+ //CMS.debug("TokenServlet:processDiversifyKey " +outputString);
+ //String value="keySetData=%00" if the KeySetData=byte[0]=0;
+
+ String value = "";
+ String status = "0";
+
+ if (KeySetData != null && KeySetData.length > 1) {
+ value = "status=0&" + "keySetData=" +
+ com.netscape.cmsutil.util.Utils.SpecialEncode(KeySetData);
+ CMS.debug("TokenServlet:process DiversifyKey.encode " + value);
+ } else if (missingParam) {
+ status = "3";
+ if (badParams.endsWith(",")) {
+ badParams = badParams.substring(0, badParams.length() - 1);
+ }
+ errorMsg = "Missing input parameters: " + badParams;
+ value = "status=" + status;
+ } else {
+ errorMsg = "Problem diversifying key data.";
+ status = "1";
+ value = "status=" + status;
+ }
+
+ resp.setContentLength(value.length());
+ CMS.debug("TokenServlet:outputString.length " + value.length());
+
+ try {
+ OutputStream ooss = resp.getOutputStream();
+ ooss.write(value.getBytes());
+ ooss.flush();
+ mRenderResult = false;
+ } catch (Exception e) {
+ CMS.debug("TokenServlet:process DiversifyKey: " + e.toString());
+ }
+
+ if (status.equals("0")) {
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS,
+ rCUID,
+ ILogger.SUCCESS,
+ status,
+ agentId,
+ oldMasterKeyName,
+ newMasterKeyName);
+
+ } else {
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE,
+ rCUID,
+ ILogger.FAILURE,
+ status,
+ agentId,
+ oldMasterKeyName,
+ newMasterKeyName,
+ errorMsg);
+ }
+
+ audit(auditMessage);
+ }
+
+ private void processEncryptData(HttpServletRequest req,
+ HttpServletResponse resp) throws EBaseException {
+ byte[] keyInfo, CUID, xCUID, encryptedData, xkeyInfo;
+ boolean missingParam = false;
+ byte[] data = null;
+ boolean isRandom = true; // randomly generate the data to be encrypted
+
+ String errorMsg = "";
+ String badParams = "";
+ IConfigStore sconfig = CMS.getConfigStore();
+ encryptedData = null;
+ String rdata = req.getParameter("data");
+ String rKeyInfo = req.getParameter("KeyInfo");
+ String rCUID = req.getParameter("CUID");
+ String keySet = req.getParameter("keySet");
+ if (keySet == null || keySet.equals("")) {
+ keySet = "defKeySet";
+ }
+
+ SessionContext sContext = SessionContext.getContext();
+
+ String agentId = "";
+ if (sContext != null) {
+ agentId =
+ (String) sContext.get(SessionContext.USER_ID);
+ }
+
+ CMS.debug("keySet selected: " + keySet);
+
+ String s_isRandom = sconfig.getString("tks.EncryptData.isRandom", "true");
+ if (s_isRandom.equalsIgnoreCase("false")) {
+ CMS.debug("TokenServlet: processEncryptData(): Random number not to be generated");
+ isRandom = false;
+ } else {
+ CMS.debug("TokenServlet: processEncryptData(): Random number generation required");
+ isRandom = true;
+ }
+
+ String auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST,
+ rCUID,
+ ILogger.SUCCESS,
+ agentId,
+ s_isRandom);
+
+ audit(auditMessage);
+
+ if (isRandom) {
+ if ((rdata == null) || (rdata.equals(""))) {
+ CMS.debug("TokenServlet: processEncryptData(): no data in request. Generating random number as data");
+ } else {
+ CMS.debug("TokenServlet: processEncryptData(): contain data in request, however, random generation on TKS is required. Generating...");
+ }
+ try {
+ SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
+ data = new byte[16];
+ random.nextBytes(data);
+ } catch (Exception e) {
+ CMS.debug("TokenServlet: processEncryptData():" + e.toString());
+ badParams += " Random Number,";
+ missingParam = true;
+ }
+ } else if ((!isRandom) && (((rdata == null) || (rdata.equals(""))))) {
+ CMS.debug("TokenServlet: processEncryptData(): missing request parameter: data.");
+ badParams += " data,";
+ missingParam = true;
+ }
+
+ if ((rCUID == null) || (rCUID.equals(""))) {
+ badParams += " CUID,";
+ CMS.debug("TokenServlet: processEncryptData(): missing request parameter: CUID");
+ missingParam = true;
+ }
+
+ if ((rKeyInfo == null) || (rKeyInfo.equals(""))) {
+ badParams += " KeyInfo,";
+ CMS.debug("TokenServlet: processEncryptData(): missing request parameter: key info");
+ missingParam = true;
+ }
+
+ if (!missingParam) {
+ xCUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID);
+ if (xCUID == null || xCUID.length != 10) {
+ badParams += " CUID length,";
+ CMS.debug("TokenServlet: Invalid CUID length");
+ missingParam = true;
+ }
+ xkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo);
+ if (xkeyInfo == null || xkeyInfo.length != 2) {
+ badParams += " KeyInfo length,";
+ CMS.debug("TokenServlet: Invalid key info length");
+ missingParam = true;
+ }
+ }
+
+ String useSoftToken_s = CMS.getConfigStore().getString("tks.useSoftToken", "true");
+ if (!useSoftToken_s.equalsIgnoreCase("true"))
+ useSoftToken_s = "false";
+
+ String selectedToken = null;
+ String keyNickName = null;
+ if (!missingParam) {
+ if (!isRandom)
+ data = com.netscape.cmsutil.util.Utils.SpecialDecode(rdata);
+ keyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo);
+ CUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID);
+
+ String keyInfoMap = "tks." + keySet + ".mk_mappings." + rKeyInfo;
+ String mappingValue = CMS.getConfigStore().getString(keyInfoMap, null);
+ if (mappingValue == null) {
+ selectedToken = CMS.getConfigStore().getString("tks.defaultSlot", "internal");
+ keyNickName = rKeyInfo;
+ } else {
+ StringTokenizer st = new StringTokenizer(mappingValue, ":");
+ selectedToken = st.nextToken();
+ keyNickName = st.nextToken();
+ }
+
+ byte kekKeyArray[] =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".kek_key"));
+ encryptedData = SessionKey.EncryptData(
+ selectedToken, keyNickName, data, keyInfo, CUID, kekKeyArray, useSoftToken_s, keySet);
+
+ CMS.getLogger().log(ILogger.EV_AUDIT,
+ ILogger.S_TKS,
+ ILogger.LL_INFO, "process EncryptData for CUID =" + trim(pp.toHexString(CUID)));
+ } // !missingParam
+
+ resp.setContentType("text/html");
+
+ String value = "";
+ String status = "0";
+ if (encryptedData != null && encryptedData.length > 0) {
+ // sending both the pre-encrypted and encrypted data back
+ value = "status=0&" + "data=" +
+ com.netscape.cmsutil.util.Utils.SpecialEncode(data) +
+ "&encryptedData=" +
+ com.netscape.cmsutil.util.Utils.SpecialEncode(encryptedData);
+ } else if (missingParam) {
+ if (badParams.endsWith(",")) {
+ badParams = badParams.substring(0, badParams.length() - 1);
+ }
+ errorMsg = "Missing input parameters: " + badParams;
+ status = "3";
+ value = "status=" + status;
+ } else {
+ errorMsg = "Problem encrypting data.";
+ status = "1";
+ value = "status=" + status;
+ }
+
+ CMS.debug("TokenServlet:process EncryptData.encode " + value);
+
+ try {
+ resp.setContentLength(value.length());
+ CMS.debug("TokenServlet:outputString.lenght " + value.length());
+
+ OutputStream ooss = resp.getOutputStream();
+ ooss.write(value.getBytes());
+ ooss.flush();
+ mRenderResult = false;
+ } catch (Exception e) {
+ CMS.debug("TokenServlet: " + e.toString());
+ }
+
+ if (status.equals("0")) {
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS,
+ rCUID,
+ ILogger.SUCCESS,
+ status,
+ agentId,
+ s_isRandom,
+ selectedToken,
+ keyNickName);
+
+ } else {
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE,
+ rCUID,
+ ILogger.FAILURE,
+ status,
+ agentId,
+ s_isRandom,
+ selectedToken,
+ keyNickName,
+ errorMsg);
+ }
+
+ audit(auditMessage);
+ }
+
+ /*
+ * For EncryptData:
+ * data=value1
+ * CUID=value2 // missing from RA
+ * versionID=value3 // missing from RA
+ *
+ * For ComputeSession:
+ * card_challenge=value1
+ * host_challenge=value2
+
+ * For DiversifyKey:
+ * new_master_key_index
+ * master_key_index
+ */
+
+ private void processComputeRandomData(HttpServletRequest req,
+ HttpServletResponse resp) throws EBaseException {
+
+ byte[] randomData = null;
+ String status = "0";
+ String errorMsg = "";
+ String badParams = "";
+ boolean missingParam = false;
+ int dataSize = 0;
+
+ CMS.debug("TokenServlet::processComputeRandomData");
+
+ SessionContext sContext = SessionContext.getContext();
+
+ String agentId = "";
+ if (sContext != null) {
+ agentId =
+ (String) sContext.get(SessionContext.USER_ID);
+ }
+
+ String sDataSize = req.getParameter("dataNumBytes");
+
+ if (sDataSize == null || sDataSize.equals("")) {
+ CMS.debug("TokenServlet::processComputeRandomData missing param dataNumBytes");
+ badParams += " Random Data size, ";
+ missingParam = true;
+ status = "1";
+ } else {
+ try {
+ dataSize = Integer.parseInt(sDataSize.trim());
+ } catch (NumberFormatException nfe) {
+ CMS.debug("TokenServlet::processComputeRandomData invalid data size input!");
+ badParams += " Random Data size, ";
+ missingParam = true;
+ status = "1";
+ }
+
+ }
+
+ CMS.debug("TokenServlet::processComputeRandomData data size requested: " + dataSize);
+
+ String auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST,
+ ILogger.SUCCESS,
+ agentId);
+
+ audit(auditMessage);
+
+ if (!missingParam) {
+ try {
+ SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
+ randomData = new byte[dataSize];
+ random.nextBytes(randomData);
+ } catch (Exception e) {
+ CMS.debug("TokenServlet::processComputeRandomData:" + e.toString());
+ errorMsg = "Can't generate random data!";
+ status = "2";
+ }
+ }
+
+ String randomDataOut = "";
+ if (status.equals("0")) {
+ if (randomData != null && randomData.length == dataSize) {
+ randomDataOut =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(randomData);
+ } else {
+ status = "2";
+ errorMsg = "Can't convert random data!";
+ }
+ }
+
+ if (status.equals("1") && missingParam) {
+
+ if (badParams.endsWith(",")) {
+ badParams = badParams.substring(0, badParams.length() - 1);
+ }
+ errorMsg = "Missing input parameters :" + badParams;
+ }
+
+ resp.setContentType("text/html");
+ String value = "";
+
+ value = "status=" + status;
+ if (status.equals("0")) {
+ value = value + "&DATA=" + randomDataOut;
+ }
+
+ try {
+ resp.setContentLength(value.length());
+ CMS.debug("TokenServler::processComputeRandomData :outputString.length " + value.length());
+
+ OutputStream ooss = resp.getOutputStream();
+ ooss.write(value.getBytes());
+ ooss.flush();
+ mRenderResult = false;
+ } catch (Exception e) {
+ CMS.debug("TokenServlet::processComputeRandomData " + e.toString());
+ }
+
+ if (status.equals("0")) {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS,
+ ILogger.SUCCESS,
+ status,
+ agentId);
+ } else {
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE,
+ ILogger.FAILURE,
+ status,
+ agentId,
+ errorMsg);
+ }
+
+ audit(auditMessage);
+ }
+
+ public void process(CMSRequest cmsReq) throws EBaseException {
+ HttpServletRequest req = cmsReq.getHttpReq();
+ HttpServletResponse resp = cmsReq.getHttpResp();
+
+ IAuthToken authToken = authenticate(cmsReq);
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "execute");
+ } catch (Exception e) {
+ }
+
+ if (authzToken == null) {
+
+ try {
+ resp.setContentType("text/html");
+ String value = "unauthorized=";
+ CMS.debug("TokenServlet: Unauthorized");
+
+ resp.setContentLength(value.length());
+ OutputStream ooss = resp.getOutputStream();
+ ooss.write(value.getBytes());
+ ooss.flush();
+ mRenderResult = false;
+ } catch (Exception e) {
+ CMS.debug("TokenServlet: " + e.toString());
+ }
+
+ // cmsReq.setStatus(CMSRequest.UNAUTHORIZED);
+ return;
+ }
+
+ String temp = req.getParameter("card_challenge");
+ setDefaultSlotAndKeyName(req);
+ if (temp != null) {
+ processComputeSessionKey(req, resp);
+ } else if (req.getParameter("data") != null) {
+ processEncryptData(req, resp);
+ } else if (req.getParameter("newKeyInfo") != null) {
+ processDiversifyKey(req, resp);
+ } else if (req.getParameter("dataNumBytes") != null) {
+ processComputeRandomData(req, resp);
+ }
+ }
+
+ /**
+ * Serves HTTP admin request.
+ *
+ * @param req HTTP request
+ * @param resp HTTP response
+ */
+ public void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ super.service(req, resp);
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/wizard/IWizardPanel.java b/base/server/cms/src/com/netscape/cms/servlet/wizard/IWizardPanel.java
new file mode 100644
index 000000000..d9d3ddec7
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/wizard/IWizardPanel.java
@@ -0,0 +1,111 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.wizard;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.context.Context;
+
+import com.netscape.certsrv.property.PropertySet;
+
+public interface IWizardPanel {
+
+ /**
+ * Initializes this panel.
+ */
+ public void init(ServletConfig config, int panelno)
+ throws ServletException;
+
+ public void init(WizardServlet servlet, ServletConfig config,
+ int panelno, String id) throws ServletException;
+
+ public String getName();
+
+ public int getPanelNo();
+
+ public void setId(String id);
+
+ public String getId();
+
+ public PropertySet getUsage();
+
+ /**
+ * Should we skip this panel to the next one?
+ */
+ public boolean shouldSkip();
+
+ /**
+ * Cleans up panel so that isPanelDone returns false
+ */
+ public void cleanUp() throws IOException;
+
+ /**
+ * Is this panel done
+ */
+ public boolean isPanelDone();
+
+ /**
+ * Show "Apply" button on frame?
+ */
+ public boolean showApplyButton();
+
+ /**
+ * Is this a subPanel?
+ */
+ public boolean isSubPanel();
+
+ public boolean isLoopbackPanel();
+
+ /**
+ * has subPanels?
+ */
+ public boolean hasSubPanel();
+
+ /**
+ * Display the panel.
+ */
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context);
+
+ /**
+ * Checks if the given parameters are valid.
+ */
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException;
+
+ /**
+ * Commit parameter changes
+ */
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException;
+
+ /**
+ * If validiate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context);
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/wizard/WizardServlet.java b/base/server/cms/src/com/netscape/cms/servlet/wizard/WizardServlet.java
new file mode 100644
index 000000000..6deab6bc0
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/wizard/WizardServlet.java
@@ -0,0 +1,489 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.wizard;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.Template;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.context.Context;
+import org.apache.velocity.servlet.VelocityServlet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.cms.servlet.csadmin.Cert;
+import com.netscape.cmsutil.crypto.Module;
+
+/**
+ * wizard?p=[panel number]&op=usage <= usage in xml
+ * wizard?p=[panel number]&op=display
+ * wizard?p=[panel number]&op=next&...[additional parameters]...
+ * wizard?p=[panel number]&op=apply
+ * wizard?p=[panel number]&op=back
+ * wizard?op=menu
+ * return menu options
+ */
+@SuppressWarnings("deprecation")
+public class WizardServlet extends VelocityServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4513510177445656799L;
+ private String name = null;
+ private Vector<IWizardPanel> mPanels = new Vector<IWizardPanel>();
+
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+
+ /* load sequence map */
+ name = config.getInitParameter("name");
+ String panels = config.getInitParameter("panels");
+ StringTokenizer st = new StringTokenizer(panels, ",");
+ int pno = 0;
+ while (st.hasMoreTokens()) {
+ String p = st.nextToken();
+ StringTokenizer st1 = new StringTokenizer(p, "=");
+ String id = st1.nextToken();
+ String pvalue = st1.nextToken();
+ try {
+ IWizardPanel panel = (IWizardPanel) Class.forName(pvalue).newInstance();
+ panel.init(this, config, pno, id);
+ CMS.debug("WizardServlet: panel name=" + panel.getName());
+ mPanels.addElement(panel);
+ } catch (Exception e) {
+ CMS.debug("WizardServlet: " + e.toString());
+ }
+ pno++;
+ }
+ CMS.debug("WizardServlet: done");
+
+ }
+
+ public void exposePanels(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ Enumeration<IWizardPanel> e = mPanels.elements();
+ Vector<IWizardPanel> panels = new Vector<IWizardPanel>();
+ while (e.hasMoreElements()) {
+ IWizardPanel p = e.nextElement();
+ panels.addElement(p);
+ }
+ context.put("panels", panels);
+ }
+
+ /**
+ * Cleans up panels from a particular panel.
+ */
+ public void cleanUpFromPanel(int pno) throws IOException {
+ /* panel number starts from zero */
+ int s = mPanels.size();
+ for (int i = pno; i < s; i++) {
+ IWizardPanel panel = mPanels.elementAt(i);
+ panel.cleanUp();
+ }
+ }
+
+ public IWizardPanel getPanelByNo(int p) {
+ IWizardPanel panel = mPanels.elementAt(p);
+ if (panel.shouldSkip()) {
+ panel = getPanelByNo(p + 1);
+ }
+ return panel;
+ }
+
+ public Template displayPanel(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ CMS.debug("WizardServlet: in display");
+ int p = getPanelNo(request);
+
+ if (p == 0) {
+ CMS.debug("WizardServlet: firstpanel");
+ context.put("firstpanel", Boolean.TRUE);
+ }
+ if (p == (mPanels.size() - 1)) {
+ CMS.debug("WizardServlet: lastpanel");
+ context.put("lastpanel", Boolean.TRUE);
+ }
+ IWizardPanel panel = getPanelByNo(p);
+ CMS.debug("WizardServlet: panel=" + panel);
+
+ if (panel.showApplyButton() == true)
+ context.put("showApplyButton", Boolean.TRUE);
+ else
+ context.put("showApplyButton", Boolean.FALSE);
+
+ panel.display(request, response, context);
+ context.put("p", Integer.toString(panel.getPanelNo()));
+
+ try {
+ return Velocity.getTemplate("admin/console/config/wizard.vm");
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ public String xml_value_flatten(Object v) {
+ String ret = "";
+ if (v instanceof String) {
+ ret += v;
+ } else if (v instanceof Integer) {
+ ret += ((Integer) v).toString();
+ } else if (v instanceof Vector) {
+ ret += "<Vector>";
+ Vector<?> v1 = (Vector<?>) v;
+ Enumeration<?> e = v1.elements();
+ StringBuffer sb = new StringBuffer();
+ while (e.hasMoreElements()) {
+ sb.append(xml_value_flatten(e.nextElement()));
+ }
+ ret += sb.toString();
+ ret += "</Vector>";
+ } else if (v instanceof Module) { // for hardware token
+ Module m = (Module) v;
+ ret += "<Module>";
+ ret += "<CommonName>" + m.getCommonName() + "</CommonName>";
+ ret += "<UserFriendlyName>" + m.getUserFriendlyName() + "</UserFriendlyName>";
+ ret += "<ImagePath>" + m.getImagePath() + "</ImagePath>";
+ ret += "</Module>";
+ } else if (v instanceof Cert) {
+ Cert m = (Cert) v;
+ ret += "<CertReqPair>";
+ ret += "<Nickname>" + m.getNickname() + "</Nickname>";
+ ret += "<Tokenname>" + m.getTokenname() + "</Tokenname>";
+ ret += "<Request>" + m.getRequest() + "</Request>";
+ ret += "<Certificate>" + m.getCert() + "</Certificate>";
+ ret += "<Type>" + m.getType() + "</Type>";
+ ret += "<DN>" + m.getDN() + "</DN>";
+ ret += "<CertPP>" + m.getCertpp() + "</CertPP>";
+ ret += "<KeyOption>" + m.getKeyOption() + "</KeyOption>";
+ ret += "</CertReqPair>";
+ } else if (v instanceof IWizardPanel) {
+ IWizardPanel m = (IWizardPanel) v;
+ ret += "<Panel>";
+ ret += "<Id>" + m.getId() + "</Id>";
+ ret += "<Name>" + m.getName() + "</Name>";
+ ret += "</Panel>";
+ } else {
+ CMS.debug("Error: unknown type " + v.getClass().getName());
+ }
+ return ret;
+ }
+
+ public String xml_flatten(Context context) {
+ StringBuffer ret = new StringBuffer();
+ Object o[] = context.getKeys();
+ for (int i = 0; i < o.length; i++) {
+ if (o[i] instanceof String) {
+ String key = (String) o[i];
+ if (key.startsWith("__")) {
+ continue;
+ }
+ ret.append("<");
+ ret.append(key);
+ ret.append(">");
+ if (key.equals("bindpwd")) {
+ ret.append("(sensitive)");
+ } else {
+ Object v = context.get(key);
+ ret.append(xml_value_flatten(v));
+ }
+ ret.append("</");
+ ret.append(key);
+ ret.append(">");
+ }
+ }
+ return ret.toString();
+ }
+
+ public int getPanelNo(HttpServletRequest request) {
+ int p = 0;
+
+ // panel number can be identified by either
+ // panel no (p parameter) directly, or
+ // panel name (panelname parameter).
+ if (request.getParameter("panelname") != null) {
+ String name = request.getParameter("panelname");
+ for (int i = 0; i < mPanels.size(); i++) {
+ IWizardPanel panel = mPanels.elementAt(i);
+ if (panel.getId().equals(name)) {
+ return i;
+ }
+ }
+ } else if (request.getParameter("p") != null) {
+ p = Integer.parseInt(request.getParameter("p"));
+ }
+ return p;
+ }
+
+ public String getNameFromPanelNo(int p) {
+ IWizardPanel wp = mPanels.elementAt(p);
+ return wp.getId();
+ }
+
+ public IWizardPanel getPreviousPanel(int p) {
+ CMS.debug("getPreviousPanel input p=" + p);
+ IWizardPanel backpanel = mPanels.elementAt(p - 1);
+ if (backpanel.isSubPanel()) {
+ backpanel = mPanels.elementAt(p - 1 - 1);
+ }
+ while (backpanel.shouldSkip()) {
+ backpanel = mPanels.elementAt(backpanel.getPanelNo() - 1);
+ }
+ CMS.debug("getPreviousPanel output p=" + backpanel.getPanelNo());
+ return backpanel;
+ }
+
+ public IWizardPanel getNextPanel(int p) {
+ CMS.debug("getNextPanel input p=" + p);
+ IWizardPanel panel = mPanels.elementAt(p);
+ if (p == (mPanels.size() - 1)) {
+ // p = p;
+ } else if (panel.isSubPanel()) {
+ if (panel.isLoopbackPanel()) {
+ p = p - 1; // Login Panel is a loop back panel
+ } else {
+ p = p + 1;
+ }
+ } else if (panel.hasSubPanel()) {
+ p = p + 2;
+ } else {
+ p = p + 1;
+ }
+ IWizardPanel nextpanel = getPanelByNo(p);
+ CMS.debug("getNextPanel output p=" + p);
+ return nextpanel;
+ }
+
+ public Template goApply(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ return goNextApply(request, response, context, true);
+ }
+
+ public Template goNext(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ return goNextApply(request, response, context, false);
+ }
+
+ /*
+ * The parameter "stay" is used to indicate "apply" without
+ * moving to the next panel
+ */
+ public Template goNextApply(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context, boolean stay) {
+ int p = getPanelNo(request);
+ if (stay == true)
+ CMS.debug("WizardServlet: in reply " + p);
+ else
+ CMS.debug("WizardServlet: in next " + p);
+
+ IWizardPanel panel = mPanels.elementAt(p);
+ try {
+ panel.validate(request, response, context);
+ try {
+ panel.update(request, response, context);
+ if (stay == true) { // "apply"
+
+ if (panel.showApplyButton() == true)
+ context.put("showApplyButton", Boolean.TRUE);
+ else
+ context.put("showApplyButton", Boolean.FALSE);
+ panel.display(request, response, context);
+ } else { // "next"
+ IWizardPanel nextpanel = getNextPanel(p);
+
+ if (nextpanel.showApplyButton() == true)
+ context.put("showApplyButton", Boolean.TRUE);
+ else
+ context.put("showApplyButton", Boolean.FALSE);
+ nextpanel.display(request, response, context);
+ panel = nextpanel;
+ }
+ context.put("errorString", "");
+ } catch (Exception e) {
+ context.put("errorString", e.getMessage());
+ panel.displayError(request, response, context);
+ }
+ } catch (IOException eee) {
+ context.put("errorString", eee.getMessage());
+ panel.displayError(request, response, context);
+ }
+ p = panel.getPanelNo();
+ CMS.debug("panel no=" + p);
+ CMS.debug("panel name=" + getNameFromPanelNo(p));
+ CMS.debug("total number of panels=" + mPanels.size());
+ context.put("p", Integer.toString(p));
+ context.put("panelname", getNameFromPanelNo(p));
+ if (p == 0) {
+ CMS.debug("WizardServlet: firstpanel");
+ context.put("firstpanel", Boolean.TRUE);
+ }
+ if (p == (mPanels.size() - 1)) {
+ CMS.debug("WizardServlet: lastpanel");
+ context.put("lastpanel", Boolean.TRUE);
+ }
+ // this is where we handle the xml request
+ String xml = request.getParameter("xml");
+ if (xml != null && xml.equals("true")) {
+ CMS.debug("WizardServlet: found xml");
+
+ response.setContentType("application/xml");
+ String xmlstr = xml_flatten(context);
+ context.put("xml", xmlstr);
+ try {
+ return Velocity.getTemplate("admin/console/config/xml.vm");
+ } catch (Exception e) {
+ CMS.debug("Failing to get template" + e);
+ }
+ } else {
+ try {
+ return Velocity.getTemplate("admin/console/config/wizard.vm");
+ } catch (Exception e) {
+ CMS.debug("Failing to get template" + e);
+ }
+ }
+ return null;
+ }
+
+ public Template goBack(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ int p = getPanelNo(request);
+ CMS.debug("WizardServlet: in back " + p);
+ IWizardPanel backpanel = getPreviousPanel(p);
+
+ if (backpanel.showApplyButton() == true)
+ context.put("showApplyButton", Boolean.TRUE);
+ else
+ context.put("showApplyButton", Boolean.FALSE);
+ backpanel.display(request, response, context);
+ context.put("p", Integer.toString(backpanel.getPanelNo()));
+ context.put("panelname", getNameFromPanelNo(backpanel.getPanelNo()));
+
+ p = backpanel.getPanelNo();
+
+ if (p == 0) {
+ CMS.debug("WizardServlet: firstpanel");
+ context.put("firstpanel", Boolean.TRUE);
+ }
+ if (p == (mPanels.size() - 1)) {
+ CMS.debug("WizardServlet: lastpanel");
+ context.put("lastpanel", Boolean.TRUE);
+ }
+ try {
+ return Velocity.getTemplate("admin/console/config/wizard.vm");
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ public boolean authenticate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ String pin = (String) request.getSession().getAttribute("pin");
+ if (pin == null) {
+ try {
+ response.sendRedirect("login");
+ } catch (IOException e) {
+ }
+ return false;
+ }
+ return true;
+ }
+
+ public void outputHttpParameters(HttpServletRequest httpReq) {
+ CMS.debug("WizardServlet:service() uri = " + httpReq.getRequestURI());
+ Enumeration<String> paramNames = httpReq.getParameterNames();
+ while (paramNames.hasMoreElements()) {
+ String pn = paramNames.nextElement();
+ // added this facility so that password can be hidden,
+ // all sensitive parameters should be prefixed with
+ // __ (double underscores); however, in the event that
+ // a security parameter slips through, we perform multiple
+ // additional checks to insure that it is NOT displayed
+ if (pn.startsWith("__") ||
+ pn.endsWith("password") ||
+ pn.endsWith("passwd") ||
+ pn.endsWith("pwd") ||
+ pn.equalsIgnoreCase("admin_password_again") ||
+ pn.equalsIgnoreCase("directoryManagerPwd") ||
+ pn.equalsIgnoreCase("bindpassword") ||
+ pn.equalsIgnoreCase("bindpwd") ||
+ pn.equalsIgnoreCase("passwd") ||
+ pn.equalsIgnoreCase("password") ||
+ pn.equalsIgnoreCase("pin") ||
+ pn.equalsIgnoreCase("pwd") ||
+ pn.equalsIgnoreCase("pwdagain") ||
+ pn.equalsIgnoreCase("uPasswd")) {
+ CMS.debug("WizardServlet::service() param name='" + pn +
+ "' value='(sensitive)'");
+ } else {
+ CMS.debug("WizardServlet::service() param name='" + pn +
+ "' value='" + httpReq.getParameter(pn) + "'");
+ }
+ }
+ }
+
+ public Template handleRequest(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ CMS.debug("WizardServlet: process");
+
+ if (CMS.debugOn()) {
+ outputHttpParameters(request);
+ }
+
+ if (!authenticate(request, response, context)) {
+ CMS.debug("WizardServlet: authentication failure");
+ return null;
+ }
+
+ String op = request.getParameter("op"); /* operation */
+ if (op == null) {
+ op = "display";
+ }
+ CMS.debug("WizardServlet: op=" + op);
+ CMS.debug("WizardServlet: size=" + mPanels.size());
+
+ context.put("name", name);
+ context.put("size", Integer.toString(mPanels.size()));
+ exposePanels(request, response, context);
+
+ if (op.equals("display")) {
+ return displayPanel(request, response, context);
+ } else if (op.equals("next")) {
+ return goNext(request, response, context);
+ } else if (op.equals("apply")) {
+ return goApply(request, response, context);
+ } else if (op.equals("back")) {
+ return goBack(request, response, context);
+ }
+ return null;
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/shares/OldJoinShares.java b/base/server/cms/src/com/netscape/cms/shares/OldJoinShares.java
new file mode 100644
index 000000000..cda8dddfe
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/shares/OldJoinShares.java
@@ -0,0 +1,86 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.shares;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import com.netscape.certsrv.kra.IJoinShares;
+
+/**
+ * Use Java's reflection API to leverage CMS's
+ * old Share and JoinShares implementations.
+ *
+ * @deprecated
+ * @version $Revision$ $Date$
+ */
+public class OldJoinShares implements IJoinShares {
+
+ public Object mOldImpl = null;
+
+ public OldJoinShares() {
+ }
+
+ public void initialize(int threshold) throws Exception {
+ Class<?> c = Class.forName("com.netscape.cmscore.shares.JoinShares");
+ Class<?> types[] = { int.class };
+ Constructor<?> con = c.getConstructor(types);
+ Object params[] = { Integer.valueOf(threshold) };
+ mOldImpl = con.newInstance(params);
+ }
+
+ public void addShare(int shareNum, byte[] share) {
+ try {
+ Class<?> types[] = { int.class, share.getClass() };
+ Class<?> c = mOldImpl.getClass();
+ Method method = c.getMethod("addShare", types);
+ Object params[] = { Integer.valueOf(shareNum), share };
+ method.invoke(mOldImpl, params);
+ } catch (Exception e) {
+ }
+ }
+
+ public int getShareCount() {
+ if (mOldImpl == null)
+ return -1;
+ try {
+ Class<?> types[] = null;
+ Class<?> c = mOldImpl.getClass();
+ Method method = c.getMethod("getShareCount", types);
+ Object params[] = null;
+ Integer result = (Integer) method.invoke(mOldImpl, params);
+ return result.intValue();
+ } catch (Exception e) {
+ return -1;
+ }
+ }
+
+ public byte[] recoverSecret() {
+ if (mOldImpl == null)
+ return null;
+ try {
+ Class<?> types[] = null;
+ Class<?> c = mOldImpl.getClass();
+ Method method = c.getMethod("recoverSecret", types);
+ Object params[] = null;
+ return (byte[]) method.invoke(mOldImpl, params);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+}
diff --git a/base/server/cms/src/com/netscape/cms/shares/OldShare.java b/base/server/cms/src/com/netscape/cms/shares/OldShare.java
new file mode 100644
index 000000000..2bf27f5ab
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/shares/OldShare.java
@@ -0,0 +1,62 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.shares;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import com.netscape.certsrv.kra.IShare;
+
+/**
+ * Use Java's reflection API to leverage CMS's
+ * old Share and JoinShares implementations.
+ *
+ * @deprecated
+ * @version $Revision$ $Date$
+ */
+public class OldShare implements IShare {
+ public Object mOldImpl = null;
+
+ public OldShare() {
+ }
+
+ public void initialize(byte[] secret, int threshold) throws Exception {
+ try {
+ Class<?> c = Class.forName("com.netscape.cmscore.shares.Share");
+ Class<?> types[] = { secret.getClass(), int.class };
+ Constructor<?> con = c.getConstructor(types);
+ Object params[] = { secret, Integer.valueOf(threshold) };
+ mOldImpl = con.newInstance(params);
+ } catch (Exception e) {
+ }
+ }
+
+ public byte[] createShare(int sharenumber) {
+ if (mOldImpl == null)
+ return null;
+ try {
+ Class<?> types[] = { int.class };
+ Class<?> c = mOldImpl.getClass();
+ Method method = c.getMethod("createShare", types);
+ Object params[] = { Integer.valueOf(sharenumber) };
+ return (byte[]) method.invoke(mOldImpl, params);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+}
diff --git a/base/server/cms/src/pki-cms.mf b/base/server/cms/src/pki-cms.mf
new file mode 100644
index 000000000..4810f3fb0
--- /dev/null
+++ b/base/server/cms/src/pki-cms.mf
@@ -0,0 +1,3 @@
+Name: pki-cms
+Specification-Version: ${APPLICATION_VERSION}
+Implementation-Version: ${VERSION}
diff --git a/base/server/cmscore/CMakeLists.txt b/base/server/cmscore/CMakeLists.txt
new file mode 100644
index 000000000..62ef6ec18
--- /dev/null
+++ b/base/server/cmscore/CMakeLists.txt
@@ -0,0 +1,3 @@
+project(cmscore)
+
+add_subdirectory(src)
diff --git a/base/server/cmscore/src/CMakeLists.txt b/base/server/cmscore/src/CMakeLists.txt
new file mode 100644
index 000000000..94f5f138c
--- /dev/null
+++ b/base/server/cmscore/src/CMakeLists.txt
@@ -0,0 +1,166 @@
+project(pki-cmscore)
+
+find_file(JSS_JAR
+ NAMES
+ jss4.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(LDAPJDK_JAR
+ NAMES
+ ldapjdk.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(COMMONS_CODEC_JAR
+ NAMES
+ commons-codec.jar
+ PATHS
+ /usr/share/java
+)
+
+find_file(COMMONS_HTTPCLIENT_JAR
+ NAMES
+ commons-httpclient.jar
+ PATHS
+ /usr/share/java
+)
+
+find_file(APACHE_COMMONS_LANG_JAR
+ NAMES
+ apache-commons-lang.jar
+ PATHS
+ /usr/share/java
+)
+
+find_file(TOMCAT_CATALINA_JAR
+ NAMES
+ catalina.jar
+ PATHS
+ /usr/share/java/tomcat
+)
+
+find_file(TOMCAT_UTIL_JAR
+ NAMES
+ tomcat-util.jar
+ PATHS
+ /usr/share/java/tomcat
+)
+
+find_file(SERVLET_JAR
+ NAMES
+ servlet.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(VELOCITY_JAR
+ NAMES
+ velocity.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(XALAN_JAR
+ NAMES
+ xalan-j2.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(XERCES_JAR
+ NAMES
+ xerces-j2.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+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(HTTPCLIENT_JAR
+ NAMES
+ httpclient.jar
+ PATHS
+ /usr/share/java/httpcomponents
+)
+
+find_file(HTTPCORE_JAR
+ NAMES
+ httpcore.jar
+ PATHS
+ /usr/share/java/httpcomponents
+)
+
+# build pki-cmscore
+javac(pki-cmscore-classes
+ SOURCES
+ com/netscape/cmscore/*.java
+ CLASSPATH
+ ${PKI_NSUTIL_JAR} ${PKI_CMSUTIL_JAR} ${PKI_CERTSRV_JAR} ${PKI_CMS_JAR} ${PKI_TOMCAT_JAR}
+ ${LDAPJDK_JAR} ${SERVLET_JAR} ${VELOCITY_JAR} ${XALAN_JAR} ${XERCES_JAR}
+ ${JSS_JAR} ${COMMONS_CODEC_JAR} ${COMMONS_HTTPCLIENT_JAR}
+ ${APACHE_COMMONS_LANG_JAR}
+ ${TOMCAT_CATALINA_JAR} ${TOMCAT_UTIL_JAR} ${SYMKEY_JAR}
+ ${JAXRS_API_JAR} ${RESTEASY_JAXRS_JAR} ${RESTEASY_ATOM_PROVIDER_JAR}
+ ${HTTPCLIENT_JAR} ${HTTPCORE_JAR}
+ OUTPUT_DIR
+ ${CMAKE_BINARY_DIR}/classes
+ DEPENDS
+ pki-nsutil-jar pki-cmsutil-jar pki-certsrv-jar pki-cms-jar pki-tomcat-jar
+)
+
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/pki-cmscore.mf
+ ${CMAKE_CURRENT_BINARY_DIR}/pki-cmscore.mf
+)
+
+jar(pki-cmscore-jar
+ CREATE
+ ${CMAKE_BINARY_DIR}/dist/pki-cmscore.jar
+ OPTIONS
+ m
+ PARAMS
+ ${CMAKE_CURRENT_BINARY_DIR}/pki-cmscore.mf
+ INPUT_DIR
+ ${CMAKE_BINARY_DIR}/classes
+ FILES
+ com/netscape/cmscore/*.class
+ DEPENDS
+ pki-cmscore-classes
+)
+
+install(
+ FILES
+ ${CMAKE_BINARY_DIR}/dist/pki-cmscore.jar
+ DESTINATION
+ ${JAVA_JAR_INSTALL_DIR}/pki
+)
+
+set(PKI_CMSCORE_JAR ${CMAKE_BINARY_DIR}/dist/pki-cmscore.jar CACHE INTERNAL "pki-cmscore jar file")
diff --git a/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java b/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java
new file mode 100644
index 000000000..ff44c6dea
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java
@@ -0,0 +1,2025 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.apps;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.text.MessageFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.StringTokenizer;
+import java.util.Timer;
+import java.util.Vector;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSSLSocketFactoryExt;
+import netscape.security.extensions.CertInfo;
+import netscape.security.pkcs.ContentInfo;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.pkcs.SignerInfo;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.Extension;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.X509CRLImpl;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import org.apache.xerces.parsers.DOMParser;
+import org.mozilla.jss.CryptoManager.CertificateUsage;
+import org.mozilla.jss.util.PasswordCallback;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import com.netscape.certsrv.acls.ACL;
+import com.netscape.certsrv.acls.ACLEntry;
+import com.netscape.certsrv.acls.EACLsException;
+import com.netscape.certsrv.acls.IACL;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.apps.ICMSEngine;
+import com.netscape.certsrv.apps.ICommandQueue;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.ICRLPrettyPrint;
+import com.netscape.certsrv.base.ICertPrettyPrint;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtPrettyPrint;
+import com.netscape.certsrv.base.IPrettyPrintFormat;
+import com.netscape.certsrv.base.ISecurityDomainSessionTable;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.ITimeSource;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.ICMSRequest;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.connector.IHttpConnection;
+import com.netscape.certsrv.connector.IPKIMessage;
+import com.netscape.certsrv.connector.IRemoteAuthority;
+import com.netscape.certsrv.connector.IRequestEncoder;
+import com.netscape.certsrv.connector.IResender;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+import com.netscape.certsrv.dbs.repository.IRepositoryRecord;
+import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ILdapAuthInfo;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.ldap.ILdapConnInfo;
+import com.netscape.certsrv.logging.ELogException;
+import com.netscape.certsrv.logging.IAuditor;
+import com.netscape.certsrv.logging.ILogEvent;
+import com.netscape.certsrv.logging.ILogEventListener;
+import com.netscape.certsrv.logging.ILogQueue;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.notification.IEmailFormProcessor;
+import com.netscape.certsrv.notification.IEmailResolver;
+import com.netscape.certsrv.notification.IEmailResolverKeys;
+import com.netscape.certsrv.notification.IEmailTemplate;
+import com.netscape.certsrv.notification.IMailNotification;
+import com.netscape.certsrv.password.IPasswordCheck;
+import com.netscape.certsrv.policy.IGeneralNameAsConstraintsConfig;
+import com.netscape.certsrv.policy.IGeneralNamesAsConstraintsConfig;
+import com.netscape.certsrv.policy.IGeneralNamesConfig;
+import com.netscape.certsrv.policy.ISubjAltNameConfig;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cmscore.authentication.AuthSubsystem;
+import com.netscape.cmscore.authentication.VerifiedCert;
+import com.netscape.cmscore.authentication.VerifiedCerts;
+import com.netscape.cmscore.authorization.AuthzSubsystem;
+import com.netscape.cmscore.base.ArgBlock;
+import com.netscape.cmscore.base.FileConfigStore;
+import com.netscape.cmscore.base.SubsystemRegistry;
+import com.netscape.cmscore.cert.CertPrettyPrint;
+import com.netscape.cmscore.cert.CertUtils;
+import com.netscape.cmscore.cert.CrlCachePrettyPrint;
+import com.netscape.cmscore.cert.CrlPrettyPrint;
+import com.netscape.cmscore.cert.ExtPrettyPrint;
+import com.netscape.cmscore.cert.OidLoaderSubsystem;
+import com.netscape.cmscore.cert.X500NameSubsystem;
+import com.netscape.cmscore.connector.HttpConnection;
+import com.netscape.cmscore.connector.HttpPKIMessage;
+import com.netscape.cmscore.connector.HttpRequestEncoder;
+import com.netscape.cmscore.connector.Resender;
+import com.netscape.cmscore.dbs.CRLIssuingPointRecord;
+import com.netscape.cmscore.dbs.CertificateRepository;
+import com.netscape.cmscore.dbs.DBSubsystem;
+import com.netscape.cmscore.dbs.RepositoryRecord;
+import com.netscape.cmscore.jobs.JobsScheduler;
+import com.netscape.cmscore.ldapconn.LdapAnonConnFactory;
+import com.netscape.cmscore.ldapconn.LdapAuthInfo;
+import com.netscape.cmscore.ldapconn.LdapBoundConnFactory;
+import com.netscape.cmscore.ldapconn.LdapBoundConnection;
+import com.netscape.cmscore.ldapconn.LdapConnInfo;
+import com.netscape.cmscore.ldapconn.LdapJssSSLSocketFactory;
+import com.netscape.cmscore.logging.Auditor;
+import com.netscape.cmscore.logging.LogSubsystem;
+import com.netscape.cmscore.logging.Logger;
+import com.netscape.cmscore.logging.SignedAuditLogger;
+import com.netscape.cmscore.notification.EmailFormProcessor;
+import com.netscape.cmscore.notification.EmailResolverKeys;
+import com.netscape.cmscore.notification.EmailTemplate;
+import com.netscape.cmscore.notification.ReqCertSANameEmailResolver;
+import com.netscape.cmscore.policy.GeneralNameUtil;
+import com.netscape.cmscore.registry.PluginRegistry;
+import com.netscape.cmscore.request.CertRequestConstants;
+import com.netscape.cmscore.request.RequestSubsystem;
+import com.netscape.cmscore.security.JssSubsystem;
+import com.netscape.cmscore.security.PWCBsdr;
+import com.netscape.cmscore.security.PWsdrCache;
+import com.netscape.cmscore.session.LDAPSecurityDomainSessionTable;
+import com.netscape.cmscore.session.SecurityDomainSessionTable;
+import com.netscape.cmscore.session.SessionTimer;
+import com.netscape.cmscore.time.SimpleTimeSource;
+import com.netscape.cmscore.usrgrp.UGSubsystem;
+import com.netscape.cmscore.util.Debug;
+import com.netscape.cmsutil.net.ISocketFactory;
+import com.netscape.cmsutil.password.IPasswordStore;
+import com.netscape.cmsutil.util.Utils;
+
+public class CMSEngine implements ICMSEngine {
+ private static final String ID = "MAIN";
+
+ private static final String PROP_SUBSYSTEM = "subsystem";
+ private static final String PROP_ID = "id";
+ private static final String PROP_CLASS = "class";
+ private static final String SERVER_XML = "server.xml";
+
+ public static final SubsystemRegistry mSSReg = SubsystemRegistry.getInstance();
+
+ public String instanceDir; /* path to instance <server-root>/cert-<instance-name> */
+ private String instanceId;
+ private int pid;
+
+ private IConfigStore mConfig = null;
+ @SuppressWarnings("unused")
+ private ISubsystem mOwner;
+ private long mStartupTime = 0;
+ private boolean isStarted = false;
+ private StringBuffer mWarning = new StringBuffer();
+ private ITimeSource mTimeSource = null;
+ private IPasswordStore mPasswordStore = null;
+ private WarningListener mWarningListener = null;
+ private ILogQueue mQueue = null;
+ private ISecurityDomainSessionTable mSecurityDomainSessionTable = null;
+ private String mConfigSDSessionId = null;
+ private Timer mSDTimer = null;
+ private String mServerCertNickname = null;
+ private String serverStatus = null;
+
+ // static subsystems - must be singletons
+ private static SubsystemInfo[] mStaticSubsystems = {
+ new SubsystemInfo(
+ Debug.ID, Debug.getInstance()),
+ new SubsystemInfo(LogSubsystem.ID,
+ LogSubsystem.getInstance()),
+ new SubsystemInfo(
+ JssSubsystem.ID, JssSubsystem.getInstance()),
+ new SubsystemInfo(
+ DBSubsystem.ID, DBSubsystem.getInstance()),
+ new SubsystemInfo(
+ UGSubsystem.ID, UGSubsystem.getInstance()),
+ new SubsystemInfo(
+ PluginRegistry.ID, new PluginRegistry()),
+ new SubsystemInfo(
+ OidLoaderSubsystem.ID, OidLoaderSubsystem.getInstance()),
+ new SubsystemInfo(
+ X500NameSubsystem.ID, X500NameSubsystem.getInstance()),
+ // skip TP subsystem;
+ // problem in needing dbsubsystem in constructor. and it's not used.
+ new SubsystemInfo(
+ RequestSubsystem.ID, RequestSubsystem.getInstance()),
+ };
+
+ // dynamic subsystems are loaded at init time, not neccessarily singletons.
+ private static SubsystemInfo[] mDynSubsystems = null;
+
+ // final static subsystems - must be singletons.
+ private static SubsystemInfo[] mFinalSubsystems = {
+ new SubsystemInfo(
+ AuthSubsystem.ID, AuthSubsystem.getInstance()),
+ new SubsystemInfo(
+ AuthzSubsystem.ID, AuthzSubsystem.getInstance()),
+ new SubsystemInfo(
+ JobsScheduler.ID, JobsScheduler.getInstance()),
+ };
+
+ private static final int IP = 0;
+ private static final int PORT = 1;
+ @SuppressWarnings("unused")
+ private static final int HOST = 2;
+ private static final int AGENT = 0;
+ private static final int ADMIN = 1;
+ private static final int EE_SSL = 2;
+ private static final int EE_NON_SSL = 3;
+ private static final int EE_CLIENT_AUTH_SSL = 4;
+ private static String info[][] = { { null, null, null },//agent
+ { null, null, null },//admin
+ { null, null, null },//sslEE
+ { null, null, null },//non_sslEE
+ { null, null, null } //ssl_clientauth_EE
+ };
+
+ /**
+ * private constructor.
+ */
+ public CMSEngine() {
+
+ // Shutdown on SIGINT, SIGTERM, or SIGHUP.
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ public void run() {
+ /*LogDoc
+ *
+ * @phase watchdog check
+ */
+ getLogger().log(ILogger.EV_SYSTEM,
+ ILogger.S_OTHER,
+ ILogger.LL_INFO,
+ "OS: Received shutdown signal");
+
+ shutdown();
+ };
+ });
+ }
+
+ /**
+ * gets this ID
+ */
+ public String getId() {
+ return ID;
+ }
+
+ /**
+ * should never be called. returns error.
+ */
+ public void setId(String id) throws EBaseException {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION"));
+ }
+
+ /**
+ * Retrieves the instance roort path of this server.
+ */
+ public String getInstanceDir() {
+ return instanceDir;
+ }
+
+ public synchronized IPasswordStore getPasswordStore() {
+ // initialize the PasswordReader and PasswordWriter
+ try {
+ String pwdPath = mConfig.getString("passwordFile");
+ if (mPasswordStore == null) {
+ CMS.debug("CMSEngine: getPasswordStore(): password store not initialized before.");
+ String pwdClass = mConfig.getString("passwordClass");
+
+ try {
+ mPasswordStore = (IPasswordStore) Class.forName(pwdClass).newInstance();
+ } catch (Exception e) {
+ CMS.debug("CMSEngine: getPasswordStore(): password store initialization failure:"
+ + e.toString());
+ throw e;
+ }
+ } else {
+ CMS.debug("CMSEngine: getPasswordStore(): password store initialized before.");
+ }
+
+ // have to initialize it because other places don't always
+ mPasswordStore.init(pwdPath);
+ CMS.debug("CMSEngine: getPasswordStore(): password store initialized.");
+ } catch (Exception e) {
+ CMS.debug("CMSEngine: getPasswordStore(): failure:" + e.toString());
+ }
+
+ return mPasswordStore;
+ }
+
+ /**
+ * initialize all static, dynamic and final static subsystems.
+ *
+ * @param owner null
+ * @param config main config store.
+ * @exception EBaseException if any error occur in subsystems during
+ * initialization.
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mOwner = owner;
+ mConfig = config;
+ int state = mConfig.getInteger("cs.state");
+
+ serverStatus = "starting";
+
+ // my default is 1 day
+ String flush_timeout = config.getString("securitydomain.flushinterval", "86400000");
+ String secdomain_source = config.getString("securitydomain.source", "memory");
+ String secdomain_check_interval = config.getString("securitydomain.checkinterval", "5000");
+
+ String tsClass = config.getString("timeSourceClass", null);
+
+ if (tsClass != null) {
+ try {
+ mTimeSource = (ITimeSource)
+ Class.forName(tsClass).newInstance();
+ } catch (Exception e) {
+ // nothing to do
+ }
+ }
+ if (mTimeSource == null) {
+ // if time source is not set, set it to simple time source
+ mTimeSource = new SimpleTimeSource();
+ }
+
+ instanceDir = config.getString("instanceRoot");
+ instanceId = config.getString("instanceId");
+
+ loadDynSubsystems();
+
+ java.security.Security.addProvider(
+ new netscape.security.provider.CMS());
+
+ mSSReg.put(ID, this);
+ initSubsystems(mStaticSubsystems, false);
+
+ // Once the log subsystem is initialized, we
+ // want to register a listener to catch
+ // all the warning message so that we can
+ // display them in the console.
+ mQueue = Logger.getLogger().getLogQueue();
+ mWarningListener = new WarningListener(mWarning);
+ mQueue.addLogEventListener(mWarningListener);
+
+ initSubsystems(mDynSubsystems, true);
+ initSubsystems(mFinalSubsystems, false);
+
+ CMS.debug("Java version=" + System.getProperty("java.version"));
+ java.security.Provider ps[] = java.security.Security.getProviders();
+
+ if (ps == null || ps.length <= 0) {
+ CMS.debug("CMSEngine: Java Security Provider NONE");
+ } else {
+ for (int x = 0; x < ps.length; x++) {
+ CMS.debug("CMSEngine: Java Security Provider " + x + " class=" + ps[x]);
+ }
+ }
+ parseServerXML();
+ fixProxyPorts();
+
+ String sd = mConfig.getString("securitydomain.select", "");
+
+ if ((state == 1) && (!sd.equals("existing"))) {
+ // check session domain table only if this is a
+ // configured security domain host
+
+ if (secdomain_source.equals("ldap")) {
+ mSecurityDomainSessionTable = new LDAPSecurityDomainSessionTable((new Long(flush_timeout)).longValue());
+ } else {
+ mSecurityDomainSessionTable = new SecurityDomainSessionTable((new Long(flush_timeout)).longValue());
+ }
+
+ mSDTimer = new Timer();
+ SessionTimer timertask = new SessionTimer(mSecurityDomainSessionTable);
+
+ mSDTimer.schedule(timertask, 5, (new Long(secdomain_check_interval)).longValue());
+ }
+
+ serverStatus = "running";
+ }
+
+ /**
+ * Parse ACL resource attributes
+ *
+ * @param resACLs same format as the resourceACLs attribute:
+ *
+ * <PRE>
+ * <resource name>:<permission1,permission2,...permissionn>:
+ * <allow|deny> (<subset of the permission set>) <evaluator expression>
+ * </PRE>
+ * @exception EACLsException ACL related parsing errors for resACLs
+ * @return an ACL instance built from the parsed resACLs
+ */
+ public IACL parseACL(String resACLs) throws EACLsException {
+ if (resACLs == null) {
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_NULL_VALUE", "resACLs"));
+ }
+
+ ACL acl = null;
+ Vector<String> rights = null;
+ int idx1 = resACLs.indexOf(":");
+
+ if (idx1 <= 0) {
+ acl = new ACL(resACLs, rights, resACLs);
+ } else {
+ // getting resource id
+ String resource = resACLs.substring(0, idx1);
+
+ if (resource == null) {
+ String infoMsg = "resource not specified in resourceACLS attribute:" +
+ resACLs;
+
+ String[] params = new String[2];
+
+ params[0] = resACLs;
+ params[1] = infoMsg;
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_PARSING_ERROR", params));
+ }
+
+ // getting list of applicable rights
+ String st = resACLs.substring(idx1 + 1);
+ int idx2 = st.indexOf(":");
+ String rightsString = null;
+
+ if (idx2 != -1)
+ rightsString = st.substring(0, idx2);
+ else {
+ String infoMsg =
+ "rights not specified in resourceACLS attribute:" + resACLs;
+ String[] params = new String[2];
+
+ params[0] = resACLs;
+ params[1] = infoMsg;
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_PARSING_ERROR", params));
+ }
+
+ if (rightsString != null) {
+ rights = new Vector<String>();
+ StringTokenizer rtok = new StringTokenizer(rightsString, ",");
+
+ while (rtok.hasMoreTokens()) {
+ rights.addElement(rtok.nextToken());
+ }
+ }
+
+ acl = new ACL(resource, rights, resACLs);
+
+ String stx = st.substring(idx2 + 1);
+ int idx3 = stx.indexOf(":");
+ String aclStr = stx.substring(0, idx3);
+
+ // getting list of acl entries
+ if (aclStr != null) {
+ StringTokenizer atok = new StringTokenizer(aclStr, ";");
+
+ while (atok.hasMoreTokens()) {
+ String acs = atok.nextToken();
+
+ // construct ACL entry
+ ACLEntry entry = ACLEntry.parseACLEntry(acl, acs);
+
+ if (entry == null) {
+ String infoMsg = "parseACLEntry() call failed";
+ String[] params = new String[2];
+
+ params[0] = "ACLEntry = " + acs;
+ params[1] = infoMsg;
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_PARSING_ERROR", params));
+ }
+
+ entry.setACLEntryString(acs);
+ acl.addEntry(entry);
+ }
+ } else {
+ // fine
+ String infoMsg = "acls not specified in resourceACLS attribute:" +
+
+ resACLs;
+
+ String[] params = new String[2];
+
+ params[0] = resACLs;
+ params[1] = infoMsg;
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_PARSING_ERROR", params));
+ }
+
+ // getting description
+ String desc = stx.substring(idx3 + 1);
+
+ acl.setDescription(desc);
+ }
+
+ return (acl);
+ }
+
+ /**
+ * Parse server.xml to get the ports and IPs
+ * @throws EBaseException
+ */
+ private void parseServerXML() throws EBaseException {
+ try {
+ String instanceRoot = mConfig.getString("instanceRoot");
+ String path = instanceRoot + File.separator + "conf" + File.separator + SERVER_XML;
+ DOMParser parser = new DOMParser();
+ parser.parse(path);
+ NodeList nodes = parser.getDocument().getElementsByTagName("Connector");
+ String parentName = "";
+ String name = "";
+ String port = "";
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Element n = (Element) nodes.item(i);
+
+ parentName = "";
+ Element p = (Element) n.getParentNode();
+ if (p != null) {
+ parentName = p.getAttribute("name");
+ }
+ name = n.getAttribute("name");
+ port = n.getAttribute("port");
+
+ // The "server.xml" file is parsed from top-to-bottom, and
+ // supports BOTH "Port Separation" (the new default method)
+ // as well as "Shared Ports" (the old legacy method). Since
+ // both methods must be supported, the file structure MUST
+ // conform to ONE AND ONLY ONE of the following formats:
+ //
+ // Port Separation:
+ //
+ // <Catalina>
+ // ...
+ // <!-- Port Separation: Unsecure Port -->
+ // <Connector name="Unsecure" . . .
+ // ...
+ // <!-- Port Separation: Agent Secure Port -->
+ // <Connector name="Agent" . . .
+ // ...
+ // <!-- Port Separation: Admin Secure Port -->
+ // <Connector name="Admin" . . .
+ // ...
+ // <!-- Port Separation: EE Secure Port -->
+ // <Connector name="EE" . . .
+ // ...
+ // </Catalina>
+ //
+ //
+ // Shared Ports:
+ //
+ // <Catalina>
+ // ...
+ // <!-- Shared Ports: Unsecure Port -->
+ // <Connector name="Unsecure" . . .
+ // ...
+ // <!-- Shared Ports: Agent, EE, and Admin Secure Port -->
+ // <Connector name="Secure" . . .
+ // ...
+ // <!--
+ // <Connector name="Unused" . . .
+ // -->
+ // ...
+ // <!--
+ // <Connector name="Unused" . . .
+ // -->
+ // ...
+ // </Catalina>
+ //
+ if (parentName.equals("Catalina")) {
+ if (name.equals("Unsecure")) {
+ // Port Separation: Unsecure Port
+ // OR
+ // Shared Ports: Unsecure Port
+ info[EE_NON_SSL][PORT] = port;
+ } else if (name.equals("Agent")) {
+ // Port Separation: Agent Secure Port
+ info[AGENT][PORT] = port;
+ } else if (name.equals("Admin")) {
+ // Port Separation: Admin Secure Port
+ info[ADMIN][PORT] = port;
+ } else if (name.equals("EE")) {
+ // Port Separation: EE Secure Port
+ info[EE_SSL][PORT] = port;
+ } else if (name.equals("EEClientAuth")) {
+ // Port Separation: EE Client Auth Secure Port
+ info[EE_CLIENT_AUTH_SSL][PORT] = port;
+ } else if (name.equals("Secure")) {
+ // Shared Ports: Agent, EE, and Admin Secure Port
+ info[AGENT][PORT] = port;
+ info[ADMIN][PORT] = port;
+ info[EE_SSL][PORT] = port;
+ info[EE_CLIENT_AUTH_SSL][PORT] = port;
+ }
+ }
+ }
+
+ } catch (Exception e) {
+ CMS.debug("CMSEngine: parseServerXML exception: " + e.toString());
+ throw new EBaseException("CMSEngine: Cannot parse the configuration file. " + e.toString());
+ }
+ }
+
+ private void fixProxyPorts() throws EBaseException {
+ try {
+ String port = mConfig.getString("proxy.securePort", "");
+ if (!port.equals("")) {
+ info[EE_SSL][PORT] = port;
+ info[ADMIN][PORT] = port;
+ info[AGENT][PORT] = port;
+ info[EE_CLIENT_AUTH_SSL][PORT] = port;
+ }
+
+ port = mConfig.getString("proxy.unsecurePort", "");
+ if (!port.equals("")) {
+ info[EE_NON_SSL][PORT] = port;
+ }
+ } catch (EBaseException e) {
+ CMS.debug("CMSEngine: fixProxyPorts exception: " + e.toString());
+ throw e;
+ }
+ }
+
+ public IConfigStore createFileConfigStore(String path) throws EBaseException {
+ try {
+ /* if the file is not there, create one */
+ File f = new File(path);
+ f.createNewFile();
+ } catch (IOException e) {
+ CMS.debug("Cannot create file: " + path + " ." + e.toString());
+ throw new EBaseException("Cannot create file: " + path + " ." + e.toString());
+ }
+ return new FileConfigStore(path);
+ }
+
+ public IArgBlock createArgBlock() {
+ return new ArgBlock();
+ }
+
+ public IArgBlock createArgBlock(Hashtable<String, String> httpReq) {
+ return new ArgBlock(httpReq);
+ }
+
+ public IArgBlock createArgBlock(String realm, Hashtable<String, String> httpReq) {
+ return new ArgBlock(realm, httpReq);
+ }
+
+ public boolean isPreOpMode() {
+ if (getCSState() == CMS.PRE_OP_MODE)
+ return true;
+ return false;
+ }
+
+ public boolean isRunningMode() {
+ if (getCSState() == CMS.RUNNING_MODE)
+ return true;
+ return false;
+ }
+
+ public void setCSState(int mode) {
+ mConfig.putInteger("cs.state", mode);
+ }
+
+ public int getCSState() {
+ int mode = 0;
+ try {
+ mode = mConfig.getInteger("cs.state");
+ } catch (Exception e) {
+ }
+ return mode;
+ }
+
+ public IRepositoryRecord createRepositoryRecord() {
+ return new RepositoryRecord();
+ }
+
+ public ICRLIssuingPointRecord createCRLIssuingPointRecord(String
+ id, BigInteger crlNumber, Long crlSize, Date thisUpdate, Date nextUpdate) {
+ return new CRLIssuingPointRecord(id, crlNumber, crlSize, thisUpdate, nextUpdate);
+ }
+
+ public ISecurityDomainSessionTable getSecurityDomainSessionTable() {
+ return mSecurityDomainSessionTable;
+ }
+
+ public String getCRLIssuingPointRecordName() {
+ return CRLIssuingPointRecord.class.getName();
+ }
+
+ public String getEEHost() {
+ String host = "";
+ try {
+ host = mConfig.getString("machineName");
+ } catch (Exception e) {
+ }
+ return host;
+ }
+
+ public String getEENonSSLHost() {
+ String host = "";
+ try {
+ host = mConfig.getString("machineName");
+ } catch (Exception e) {
+ }
+ return host;
+ }
+
+ public String getEENonSSLIP() {
+ return info[EE_NON_SSL][IP];
+ }
+
+ public String getEENonSSLPort() {
+ return info[EE_NON_SSL][PORT];
+ }
+
+ public String getEESSLHost() {
+ String host = "";
+ try {
+ host = mConfig.getString("machineName");
+ } catch (Exception e) {
+ }
+ return host;
+ }
+
+ public String getEESSLIP() {
+ return info[EE_SSL][IP];
+ }
+
+ public String getEESSLPort() {
+ return info[EE_SSL][PORT];
+ }
+
+ public String getEEClientAuthSSLPort() {
+ return info[EE_CLIENT_AUTH_SSL][PORT];
+ }
+
+ public String getAgentHost() {
+ String host = "";
+ try {
+ host = mConfig.getString("machineName");
+ } catch (Exception e) {
+ }
+ return host;
+ }
+
+ public String getAgentIP() {
+ return info[AGENT][IP];
+ }
+
+ public String getAgentPort() {
+ return info[AGENT][PORT];
+ }
+
+ public String getAdminHost() {
+ String host = "";
+ try {
+ host = mConfig.getString("machineName");
+ } catch (Exception e) {
+ }
+ return host;
+ }
+
+ public String getAdminIP() {
+ return info[ADMIN][IP];
+ }
+
+ public String getAdminPort() {
+ return info[ADMIN][PORT];
+ }
+
+ public IHttpConnection getHttpConnection(IRemoteAuthority authority,
+ ISocketFactory factory) {
+ return new HttpConnection(authority, factory);
+ }
+
+ public IHttpConnection getHttpConnection(IRemoteAuthority authority,
+ ISocketFactory factory, int timeout) {
+ return new HttpConnection(authority, factory, timeout);
+ }
+
+ public IResender getResender(IAuthority authority, String nickname,
+ IRemoteAuthority remote, int interval) {
+ return new Resender(authority, nickname, remote, interval);
+ }
+
+ public IPKIMessage getHttpPKIMessage() {
+ return new HttpPKIMessage();
+ }
+
+ public ILdapConnInfo getLdapConnInfo(IConfigStore config)
+ throws EBaseException, ELdapException {
+ return new LdapConnInfo(config);
+ }
+
+ public LDAPSSLSocketFactoryExt getLdapJssSSLSocketFactory(
+ String certNickname) {
+ return new LdapJssSSLSocketFactory(certNickname);
+ }
+
+ public LDAPSSLSocketFactoryExt getLdapJssSSLSocketFactory() {
+ return new LdapJssSSLSocketFactory();
+ }
+
+ public ILdapAuthInfo getLdapAuthInfo() {
+ return new LdapAuthInfo();
+ }
+
+ public ILdapConnFactory getLdapBoundConnFactory()
+ throws ELdapException {
+ return new LdapBoundConnFactory();
+ }
+
+ public ILdapConnFactory getLdapAnonConnFactory()
+ throws ELdapException {
+ return new LdapAnonConnFactory();
+ }
+
+ public IRequestEncoder getHttpRequestEncoder() {
+ return new HttpRequestEncoder();
+ }
+
+ public Enumeration<String> getSubsystemNames() {
+ return mSSReg.keys();
+ }
+
+ public Enumeration<ISubsystem> getSubsystems() {
+ return mSSReg.elements();
+ }
+
+ public ISubsystem getSubsystem(String name) {
+ return mSSReg.get(name);
+ }
+
+ /**
+ * initialize an array of subsystem info.
+ */
+ private void initSubsystems(SubsystemInfo[] sslist, boolean doSetId)
+ throws EBaseException {
+ if (sslist == null)
+ return;
+ for (int i = 0; i < sslist.length; i++) {
+ initSubsystem(sslist[i], doSetId);
+ }
+ }
+
+ /**
+ * load dynamic subsystems
+ */
+ private void loadDynSubsystems()
+ throws EBaseException {
+ IConfigStore ssconfig = mConfig.getSubStore(PROP_SUBSYSTEM);
+
+ // count number of dyn loaded subsystems.
+ Enumeration<String> ssnames = ssconfig.getSubStoreNames();
+ int nsubsystems = 0;
+
+ for (nsubsystems = 0; ssnames.hasMoreElements(); nsubsystems++)
+ ssnames.nextElement();
+ if (Debug.ON) {
+ Debug.trace(nsubsystems + " dyn subsystems loading..");
+ }
+ if (nsubsystems == 0)
+ return;
+
+ // load dyn subsystems.
+ mDynSubsystems = new SubsystemInfo[nsubsystems];
+ for (int i = 0; i < mDynSubsystems.length; i++) {
+ IConfigStore config =
+ ssconfig.getSubStore(String.valueOf(i));
+ String id = config.getString(PROP_ID);
+ String classname = config.getString(PROP_CLASS);
+ ISubsystem ss = null;
+
+ try {
+ ss = (ISubsystem) Class.forName(classname).newInstance();
+ } catch (InstantiationException e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_LOAD_FAILED_1", id, e.toString()));
+ } catch (IllegalAccessException e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_LOAD_FAILED_1", id, e.toString()));
+ } catch (ClassNotFoundException e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_LOAD_FAILED_1", id, e.toString()));
+ }
+ mDynSubsystems[i] = new SubsystemInfo(id, ss);
+ Debug.trace("loaded dyn subsystem " + id);
+ }
+ }
+
+ public LDAPConnection getBoundConnection(String host, int port,
+ int version, LDAPSSLSocketFactoryExt fac, String bindDN,
+ String bindPW) throws LDAPException {
+ return new LdapBoundConnection(host, port, version, fac,
+ bindDN, bindPW);
+ }
+
+ /**
+ * initialize a subsystem
+ */
+ private void initSubsystem(SubsystemInfo ssinfo, boolean doSetId)
+ throws EBaseException {
+ String id = ssinfo.mId;
+ ISubsystem ss = ssinfo.mInstance;
+ IConfigStore ssConfig = mConfig.getSubStore(id);
+
+ CMS.debug("CMSEngine: initSubsystem id=" + id);
+ if (doSetId)
+ ss.setId(id);
+ CMS.debug("CMSEngine: ready to init id=" + id);
+ ss.init(this, ssConfig);
+ // add to id - subsystem hash table.
+ CMS.debug("CMSEngine: done init id=" + id);
+ mSSReg.put(id, ss);
+ CMS.debug("CMSEngine: initialized " + id);
+
+ if (id.equals("ca") || id.equals("ocsp") ||
+ id.equals("kra") || id.equals("tks")) {
+ CMS.debug("CMSEngine::initSubsystem " + id + " Java subsytem about to calculate serverCertNickname. ");
+ // get SSL server nickname
+ IConfigStore serverCertStore = mConfig.getSubStore(id + "." + "sslserver");
+ if (serverCertStore != null && serverCertStore.size() > 0) {
+ String nickName = serverCertStore.getString("nickname");
+ String tokenName = serverCertStore.getString("tokenname");
+ if (tokenName != null && tokenName.length() > 0 &&
+ nickName != null && nickName.length() > 0) {
+ CMS.setServerCertNickname(tokenName, nickName);
+ CMS.debug("Subsystem " + id + " init sslserver: tokenName:" + tokenName + " nickName:" + nickName);
+ } else if (nickName != null && nickName.length() > 0) {
+ CMS.setServerCertNickname(nickName);
+ CMS.debug("Subsystem " + id + " init sslserver: nickName:" + nickName);
+ } else {
+ CMS.debug("Subsystem " + id + " init error: SSL server certificate nickname is not available.");
+ }
+ }
+ }
+ }
+
+ public void reinit(String id) throws EBaseException {
+ ISubsystem system = getSubsystem(id);
+ IConfigStore cs = mConfig.getSubStore(id);
+ system.init(this, cs);
+ }
+
+ /**
+ * Starts up all subsystems. subsystems must be initialized.
+ *
+ * @exception EBaseException if any subsystem fails to startup.
+ */
+ public void startup() throws EBaseException {
+ startupSubsystems(mStaticSubsystems);
+ if (mDynSubsystems != null)
+ startupSubsystems(mDynSubsystems);
+ startupSubsystems(mFinalSubsystems);
+
+ // global admin servlet. (anywhere else more fit for this ?)
+
+ mStartupTime = System.currentTimeMillis();
+
+ mQueue.removeLogEventListener(mWarningListener);
+ if (!mWarning.toString().equals("")) {
+ System.out.println(Constants.SERVER_STARTUP_WARNING_MESSAGE + mWarning);
+ }
+
+ // check serial number ranges if a CA/KRA
+ ICertificateAuthority ca = (ICertificateAuthority) getSubsystem("ca");
+ if ((ca != null) && !isPreOpMode()) {
+ CMS.debug("CMSEngine: checking request serial number ranges for the CA");
+ ca.getRequestQueue().getRequestRepository().checkRanges();
+
+ CMS.debug("CMSEngine: checking certificate serial number ranges");
+ ca.getCertificateRepository().checkRanges();
+ }
+
+ IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority) getSubsystem("kra");
+ if ((kra != null) && !isPreOpMode()) {
+ CMS.debug("CMSEngine: checking request serial number ranges for the KRA");
+ kra.getRequestQueue().getRequestRepository().checkRanges();
+
+ CMS.debug("CMSEngine: checking key serial number ranges");
+ kra.getKeyRepository().checkRanges();
+ }
+
+ /*LogDoc
+ *
+ * @phase server startup
+ * @reason all subsystems are initialized and started.
+ */
+ Logger.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_ADMIN,
+ ILogger.LL_INFO, CMS.getLogMessage("SERVER_STARTUP"));
+ System.out.println(Constants.SERVER_STARTUP_MESSAGE);
+ isStarted = true;
+
+ }
+
+ public boolean isInRunningState() {
+ return isStarted;
+ }
+
+ public byte[] getPKCS7(Locale locale, IRequest req) {
+ try {
+ X509CertImpl cert = req.getExtDataInCert(
+ IEnrollProfile.REQUEST_ISSUED_CERT);
+ if (cert == null)
+ return null;
+
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem("ca");
+ CertificateChain cachain = ca.getCACertChain();
+ X509Certificate[] cacerts = cachain.getChain();
+
+ X509CertImpl[] userChain = new X509CertImpl[cacerts.length + 1];
+ int m = 1, n = 0;
+
+ for (; n < cacerts.length; m++, n++) {
+ userChain[m] = (X509CertImpl) cacerts[n];
+ }
+
+ userChain[0] = cert;
+ PKCS7 p7 = new PKCS7(new AlgorithmId[0],
+ new ContentInfo(new byte[0]),
+ userChain,
+ new SignerInfo[0]);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ p7.encodeSignedData(bos);
+ return bos.toByteArray();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public String getServerCertNickname() {
+ return mServerCertNickname;
+ }
+
+ public void setServerCertNickname(String tokenName, String
+ nickName) {
+ String newName = null;
+
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME) ||
+ tokenName.equalsIgnoreCase("Internal Key Storage Token"))
+ newName = nickName;
+ else {
+ if (tokenName.equals("") && nickName.equals(""))
+ return; // not sure the logic
+ else
+ newName = tokenName + ":" + nickName;
+ }
+ setServerCertNickname(newName);
+ }
+
+ public void setServerCertNickname(String newName) {
+ // modify server.xml
+ /*
+ String filePrefix = instanceDir + File.separator +
+ "config" + File.separator;
+ String orig = filePrefix + "server.xml";
+ String dest = filePrefix + "server.xml.bak";
+ String newF = filePrefix + "server.xml.new";
+
+ // save the old copy
+ Utils.copy(orig, dest);
+
+ BufferedReader in1 = null;
+ PrintWriter out1 = null;
+
+ try {
+ in1 = new BufferedReader(new FileReader(dest));
+ out1 = new PrintWriter(
+ new BufferedWriter(new FileWriter(newF)));
+ String line = "";
+
+ while (in1.ready()) {
+ line = in1.readLine();
+ if (line != null)
+ out1.println(lineParsing(line, newName));
+ }
+
+ out1.close();
+ in1.close();
+ } catch (Exception eee) {
+ Logger.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_ADMIN,
+ ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", eee.toString()));
+ }
+
+ File file = new File(newF);
+ File nfile = new File(orig);
+
+ try {
+ boolean success = file.renameTo(nfile);
+
+ if (!success) {
+ if (Utils.isNT()) {
+ // NT is very picky on the path
+ Utils.exec("copy " +
+ file.getAbsolutePath().replace('/', '\\') + " " +
+ nfile.getAbsolutePath().replace('/', '\\'));
+ } else {
+ Utils.exec("cp " + file.getAbsolutePath() + " " +
+ nfile.getAbsolutePath());
+ }
+ }
+ } catch (Exception exx) {
+ Logger.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_ADMIN,
+ ILogger.LL_FAILURE, "CMSEngine: Error " + exx.toString());
+ }
+ // update "cache" for CMS.getServerCertNickname()
+ */
+ mServerCertNickname = newName;
+ }
+
+ public String getFingerPrint(Certificate cert)
+ throws CertificateEncodingException, NoSuchAlgorithmException {
+ return CertUtils.getFingerPrint(cert);
+ }
+
+ public String getFingerPrints(Certificate cert)
+ throws NoSuchAlgorithmException, CertificateEncodingException {
+ return CertUtils.getFingerPrints(cert);
+ }
+
+ public String getFingerPrints(byte[] certDer)
+ throws NoSuchAlgorithmException {
+ return CertUtils.getFingerPrints(certDer);
+ }
+
+ public String getUserMessage(Locale locale, String msgID, String params[]) {
+ // if locale is null, try to get it out from session context
+ if (locale == null) {
+ SessionContext sc = SessionContext.getExistingContext();
+
+ if (sc != null)
+ locale = (Locale) sc.get(SessionContext.LOCALE);
+ }
+ ResourceBundle rb = null;
+
+ if (locale == null) {
+ rb = ResourceBundle.getBundle(
+ "UserMessages", Locale.ENGLISH);
+ } else {
+ rb = ResourceBundle.getBundle(
+ "UserMessages", locale);
+ }
+ String msg = rb.getString(msgID);
+
+ if (params == null)
+ return msg;
+ MessageFormat mf = new MessageFormat(msg);
+
+ return mf.format(params);
+ }
+
+ public String getUserMessage(Locale locale, String msgID) {
+ return getUserMessage(locale, msgID, (String[]) null);
+ }
+
+ public String getUserMessage(Locale locale, String msgID, String p1) {
+ String params[] = { p1 };
+
+ return getUserMessage(locale, msgID, params);
+ }
+
+ public String getUserMessage(Locale locale, String msgID, String p1, String p2) {
+ String params[] = { p1, p2 };
+
+ return getUserMessage(locale, msgID, params);
+ }
+
+ public String getUserMessage(Locale locale, String msgID,
+ String p1, String p2, String p3) {
+ String params[] = { p1, p2, p3 };
+
+ return getUserMessage(locale, msgID, params);
+ }
+
+ public String getLogMessage(String msgID, String params[]) {
+ ResourceBundle rb = ResourceBundle.getBundle(
+ "LogMessages");
+ String msg = rb.getString(msgID);
+
+ if (params == null)
+ return msg;
+ MessageFormat mf = new MessageFormat(msg);
+
+ return mf.format(params);
+ }
+
+ public void debug(byte data[]) {
+ if (!debugOn()) {
+ // this helps to not saving stuff to file when debug
+ // is disable
+ return;
+ }
+ Debug.print(data);
+ }
+
+ public void debug(int level, String msg) {
+ if (!debugOn()) {
+ // this helps to not saving stuff to file when debug
+ // is disable
+ return;
+ }
+ Debug.trace(level, msg);
+ }
+
+ public void debug(String msg) {
+ if (!debugOn()) {
+ // this helps to not saving stuff to file when debug
+ // is disable
+ return;
+ }
+ Debug.trace(msg);
+ }
+
+ public void debug(Throwable e) {
+ if (!debugOn()) {
+ // this helps to not saving stuff to file when debug
+ // is disable
+ return;
+ }
+ Debug.printStackTrace(e);
+ }
+
+ public boolean debugOn() {
+ return Debug.on();
+ }
+
+ public void debugStackTrace() {
+ Debug.printStackTrace();
+ }
+
+ public void traceHashKey(String type, String key) {
+ Debug.traceHashKey(type, key);
+ }
+
+ public void traceHashKey(String type, String key, String val) {
+ Debug.traceHashKey(type, key, val);
+ }
+
+ public void traceHashKey(String type, String key, String val, String def) {
+ Debug.traceHashKey(type, key, val, def);
+ }
+
+ public String getLogMessage(String msgID) {
+ return getLogMessage(msgID, (String[]) null);
+ }
+
+ public String getLogMessage(String msgID, String p1) {
+ String params[] = { p1 };
+
+ return getLogMessage(msgID, params);
+ }
+
+ public String getLogMessage(String msgID, String p1, String p2) {
+ String params[] = { p1, p2 };
+
+ return getLogMessage(msgID, params);
+ }
+
+ public String getLogMessage(String msgID, String p1, String p2, String p3) {
+ String params[] = { p1, p2, p3 };
+
+ return getLogMessage(msgID, params);
+ }
+
+ public String getLogMessage(String msgID, String p1, String p2, String p3, String p4) {
+ String params[] = { p1, p2, p3, p4 };
+
+ return getLogMessage(msgID, params);
+ }
+
+ public String getLogMessage(String msgID, String p1, String p2, String p3, String p4, String p5) {
+ String params[] = { p1, p2, p3, p4, p5 };
+
+ return getLogMessage(msgID, params);
+ }
+
+ public String getLogMessage(String msgID, String p1, String p2, String p3, String p4, String p5, String p6) {
+ String params[] = { p1, p2, p3, p4, p5, p6 };
+
+ return getLogMessage(msgID, params);
+ }
+
+ public String getLogMessage(String msgID, String p1, String p2, String p3, String p4, String p5, String p6,
+ String p7) {
+ String params[] = { p1, p2, p3, p4, p5, p6, p7 };
+
+ return getLogMessage(msgID, params);
+ }
+
+ public String getLogMessage(String msgID, String p1, String p2, String p3, String p4, String p5, String p6,
+ String p7, String p8) {
+ String params[] = { p1, p2, p3, p4, p5, p6, p7, p8 };
+
+ return getLogMessage(msgID, params);
+ }
+
+ public String getLogMessage(String msgID, String p1, String p2, String p3, String p4, String p5, String p6,
+ String p7, String p8, String p9) {
+ String params[] = { p1, p2, p3, p4, p5, p6, p7, p8, p9 };
+
+ return getLogMessage(msgID, params);
+ }
+
+ public void getSubjAltNameConfigDefaultParams(String name,
+ Vector<String> params) {
+ GeneralNameUtil.SubjAltNameGN.getDefaultParams(name, params);
+ }
+
+ public void getSubjAltNameConfigExtendedPluginInfo(String name,
+ Vector<String> params) {
+ GeneralNameUtil.SubjAltNameGN.getExtendedPluginInfo(name, params);
+ }
+
+ public ISubjAltNameConfig createSubjAltNameConfig(String name, IConfigStore config, boolean isValueConfigured)
+ throws EBaseException {
+ return new GeneralNameUtil.SubjAltNameGN(name, config, isValueConfigured);
+ }
+
+ public GeneralName form_GeneralNameAsConstraints(String generalNameChoice, String value) throws EBaseException {
+ return GeneralNameUtil.form_GeneralNameAsConstraints(generalNameChoice, value);
+ }
+
+ public GeneralName form_GeneralName(String generalNameChoice,
+ String value) throws EBaseException {
+ return GeneralNameUtil.form_GeneralName(generalNameChoice, value);
+ }
+
+ public void getGeneralNameConfigDefaultParams(String name,
+ boolean isValueConfigured, Vector<String> params) {
+ GeneralNameUtil.GeneralNameConfig.getDefaultParams(name, isValueConfigured, params);
+ }
+
+ public void getGeneralNamesConfigDefaultParams(String name,
+ boolean isValueConfigured, Vector<String> params) {
+ GeneralNameUtil.GeneralNamesConfig.getDefaultParams(name, isValueConfigured, params);
+ }
+
+ public void getGeneralNameConfigExtendedPluginInfo(String name,
+ boolean isValueConfigured, Vector<String> info) {
+ GeneralNameUtil.GeneralNameConfig.getExtendedPluginInfo(name, isValueConfigured, info);
+ }
+
+ public void getGeneralNamesConfigExtendedPluginInfo(String name,
+ boolean isValueConfigured, Vector<String> info) {
+ GeneralNameUtil.GeneralNamesConfig.getExtendedPluginInfo(name, isValueConfigured, info);
+ }
+
+ public IGeneralNamesConfig createGeneralNamesConfig(String name,
+ IConfigStore config, boolean isValueConfigured,
+ boolean isPolicyEnabled) throws EBaseException {
+ return new GeneralNameUtil.GeneralNamesConfig(name, config, isValueConfigured, isPolicyEnabled);
+ }
+
+ public IGeneralNameAsConstraintsConfig createGeneralNameAsConstraintsConfig(String name, IConfigStore config,
+ boolean isValueConfigured,
+ boolean isPolicyEnabled) throws EBaseException {
+ return new GeneralNameUtil.GeneralNameAsConstraintsConfig(name, config, isValueConfigured, isPolicyEnabled);
+ }
+
+ public IGeneralNamesAsConstraintsConfig createGeneralNamesAsConstraintsConfig(String name, IConfigStore config,
+ boolean isValueConfigured,
+ boolean isPolicyEnabled) throws EBaseException {
+ return new GeneralNameUtil.GeneralNamesAsConstraintsConfig(name, config, isValueConfigured, isPolicyEnabled);
+ }
+
+ public ObjectIdentifier checkOID(String attrName, String value)
+ throws EBaseException {
+ return CertUtils.checkOID(attrName, value);
+ }
+
+ public String BtoA(byte data[]) {
+ return Utils.base64encode(data);
+ }
+
+ public byte[] AtoB(String data) {
+ return Utils.base64decode(data);
+ }
+
+ public String getEncodedCert(X509Certificate cert) {
+ try {
+ return "-----BEGIN CERTIFICATE-----\n" +
+ CMS.BtoA(cert.getEncoded()) +
+ "-----END CERTIFICATE-----\n";
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public boolean verifySystemCerts() {
+ return CertUtils.verifySystemCerts();
+ }
+
+ public boolean verifySystemCertByTag(String tag) {
+ return CertUtils.verifySystemCertByTag(tag);
+ }
+
+ public boolean verifySystemCertByNickname(String nickname, String certificateUsage) {
+ return CertUtils.verifySystemCertByNickname(nickname, certificateUsage);
+ }
+
+ public CertificateUsage getCertificateUsage(String certusage) {
+ return CertUtils.getCertificateUsage(certusage);
+ }
+
+ public boolean isSigningCert(X509Certificate cert) {
+ return CertUtils.isSigningCert((X509CertImpl) cert);
+ }
+
+ public boolean isEncryptionCert(X509Certificate cert) {
+ return CertUtils.isEncryptionCert((X509CertImpl) cert);
+ }
+
+ public X509CertInfo getDefaultX509CertInfo() {
+ return new CertInfo();
+ }
+
+ public IEmailResolverKeys getEmailResolverKeys() {
+ return new EmailResolverKeys();
+ }
+
+ public IEmailResolver getReqCertSANameEmailResolver() {
+ return new ReqCertSANameEmailResolver();
+ }
+
+ public IEmailFormProcessor getEmailFormProcessor() {
+ return new EmailFormProcessor();
+ }
+
+ public IEmailTemplate getEmailTemplate(String path) {
+ return new EmailTemplate(path);
+ }
+
+ public IMailNotification getMailNotification() {
+ try {
+ String className = mConfig.getString("notificationClassName",
+ "com.netscape.cms.notification.MailNotification");
+ IMailNotification notification = (IMailNotification)
+ Class.forName(className).newInstance();
+
+ return notification;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public IPrettyPrintFormat getPrettyPrintFormat(String delimiter) {
+ return new com.netscape.cmscore.cert.PrettyPrintFormat(delimiter);
+ }
+
+ public IExtPrettyPrint getExtPrettyPrint(Extension e, int indent) {
+ return new ExtPrettyPrint(e, indent);
+ }
+
+ public ICertPrettyPrint getCertPrettyPrint(X509Certificate cert) {
+ return new CertPrettyPrint(cert);
+ }
+
+ public ICRLPrettyPrint getCRLPrettyPrint(X509CRL crl) {
+ return new CrlPrettyPrint((X509CRLImpl) crl);
+ }
+
+ public ICRLPrettyPrint getCRLCachePrettyPrint(ICRLIssuingPoint ip) {
+ return new CrlCachePrettyPrint(ip);
+ }
+
+ public IPasswordCheck getPasswordChecker() {
+ try {
+ String className = mConfig.getString("passwordCheckerClass",
+ "com.netscape.cms.password.PasswordChecker");
+ IPasswordCheck check = (IPasswordCheck)
+ Class.forName(className).newInstance();
+
+ return check;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public ILogger getLogger() {
+ return Logger.getLogger();
+ }
+
+ public IAuditor getAuditor() {
+ return Auditor.getAuditor();
+ }
+
+ public ILogger getSignedAuditLogger() {
+ return SignedAuditLogger.getLogger();
+ }
+
+ /**
+ * starts up subsystems in a subsystem list..
+ */
+ private void startupSubsystems(SubsystemInfo[] sslist)
+ throws EBaseException {
+ ISubsystem ss = null;
+
+ for (int i = 0; i < sslist.length; i++) {
+ CMS.debug("CMSEngine: " + sslist[i].mId + " startup start");
+ ss = sslist[i].mInstance;
+ ss.startup();
+ CMS.debug("CMSEngine: " + sslist[i].mId + " startup done");
+ }
+ }
+
+ public void disableRequests() {
+ CommandQueue.mShuttingDown = true;
+ }
+
+ public boolean areRequestsDisabled() {
+ return CommandQueue.mShuttingDown;
+ }
+
+ public void terminateRequests() {
+ Enumeration<ICMSRequest> e = CommandQueue.mCommandQueue.keys();
+
+ while (e.hasMoreElements()) {
+ Object thisRequest = e.nextElement();
+
+ HttpServlet thisServlet = (HttpServlet) CommandQueue.mCommandQueue.get(thisRequest);
+
+ if (thisServlet != null) {
+ CommandQueue.mCommandQueue.remove(thisRequest);
+ thisServlet.destroy();
+ }
+ }
+ }
+
+ public static boolean isNT() {
+ return (File.separator.equals("\\"));
+ }
+
+ private void shutdownHttpServer() {
+
+ try {
+ String cmds[] = null;
+ String cmd = "stop-cert";
+ if (isNT()) {
+ // NT
+ cmds = new String[3];
+ cmds[0] = "cmd";
+ cmds[1] = "/c";
+ cmds[2] = instanceDir + "\\" + cmd;
+ } else {
+ // UNIX
+ cmds = new String[3];
+ cmds[0] = "/bin/sh";
+ cmds[1] = "-c";
+ cmds[2] = instanceDir + "/" + cmd;
+ }
+
+ Process process = Runtime.getRuntime().exec(cmds);
+
+ process.waitFor();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ } // end shutdownHttpServer
+
+ /**
+ * Shuts down subsystems in backwards order
+ * exceptions are ignored. process exists at end to force exit.
+ */
+ public void shutdown() {
+ Logger.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_ADMIN,
+ ILogger.LL_INFO, Constants.SERVER_SHUTDOWN_MESSAGE);
+
+ CMS.debug("CMSEngine.shutdown()");
+
+ /*
+ CommandQueue commandQueue = new CommandQueue();
+ Thread t1 = new Thread(commandQueue);
+
+ t1.setDaemon(true);
+ t1.start();
+
+ // wait for command queue to emptied before proceeding to shutting down subsystems
+ Date time = new Date();
+ long startTime = time.getTime();
+ long timeOut = time.getTime();
+
+ while (t1.isAlive() && ((timeOut - startTime) < (60 * 1000))) //wait for 1 minute
+ {
+ try {
+ Thread.currentThread().sleep(5000); // sleep for 5 sec
+ }catch (java.lang.InterruptedException e) {
+ }
+ timeOut = time.getTime();
+ }
+ terminateRequests();
+ */
+
+ shutdownSubsystems(mFinalSubsystems);
+ shutdownSubsystems(mDynSubsystems);
+ shutdownSubsystems(mStaticSubsystems);
+ }
+
+ /**
+ * Shuts down subsystems in backwards order
+ * exceptions are ignored. process exists at end to force exit.
+ * Added extra call to shutdown the web server.
+ */
+
+ public void forceShutdown() {
+
+ Logger.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_ADMIN,
+ ILogger.LL_INFO, Constants.SERVER_SHUTDOWN_MESSAGE);
+
+ CMS.debug("CMSEngine.forceShutdown()");
+
+ CommandQueue commandQueue = new CommandQueue();
+ Thread t1 = new Thread(commandQueue);
+
+ t1.setDaemon(true);
+ t1.start();
+
+ // wait for command queue to emptied before proceeding to shutting down subsystems
+ Date time = new Date();
+ long startTime = time.getTime();
+ long timeOut = time.getTime();
+
+ while (t1.isAlive() && ((timeOut - startTime) < (60 * 1000))) //wait for 1 minute
+ {
+ try {
+ Thread.sleep(5000); // sleep for 5 sec
+ } catch (java.lang.InterruptedException e) {
+ }
+ timeOut = time.getTime();
+ }
+ terminateRequests();
+
+ shutdownSubsystems(mFinalSubsystems);
+ shutdownSubsystems(mDynSubsystems);
+ shutdownSubsystems(mStaticSubsystems);
+ shutdownHttpServer();
+
+ }
+
+ /**
+ * shuts down a subsystem list in reverse order.
+ */
+ private void shutdownSubsystems(SubsystemInfo[] sslist) {
+ if (sslist == null)
+ return;
+
+ for (int i = sslist.length - 1; i >= 0; i--) {
+ if (sslist[i] != null && sslist[i].mInstance != null) {
+ sslist[i].mInstance.shutdown();
+ }
+ }
+ }
+
+ /**
+ * returns the main config store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * get time server started up
+ */
+ public long getStartupTime() {
+ return mStartupTime;
+ }
+
+ public void putPasswordCache(String tag, String pw) {
+ try {
+ PWsdrCache pwc = new PWsdrCache();
+ pwc.addEntry(tag, pw);
+ } catch (EBaseException e) {
+ // intercept this for now -- don't want to change the callers
+ Logger.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SDR_ADD_ERROR", e.toString()));
+ }
+ }
+
+ public PasswordCallback getPasswordCallback() {
+ return new PWCBsdr();
+ }
+
+ public int getPID() {
+ if (pid != 0) return pid;
+
+ BufferedReader bf = null;
+ try {
+ // PID file is be created by wrapper script (e.g. /usr/sbin/tomcat6)
+ // The default is for dogtag 9 systems which did not have this paramater
+ String dir = mConfig.getString("pidDir", "/var/run");
+ String name = dir+File.separator+instanceId+".pid";
+
+ if (dir == null) return pid;
+ File file = new File(name);
+ if (!file.exists()) return pid;
+
+ bf = new BufferedReader(new FileReader(file));
+ String value = bf.readLine();
+ pid = Integer.parseInt(value);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+
+ } finally {
+ if (bf != null) try { bf.close(); } catch (Exception e) { e.printStackTrace(); }
+ }
+
+ return pid;
+ }
+
+ public Date getCurrentDate() {
+ if (mTimeSource == null) {
+ return new Date();
+ }
+ return mTimeSource.getCurrentDate();
+ }
+
+ public void setConfigSDSessionId(String val) {
+ mConfigSDSessionId = val;
+ }
+
+ public String getConfigSDSessionId() {
+ return mConfigSDSessionId;
+ }
+
+ public static void upgradeConfig(IConfigStore c)
+ throws EBaseException {
+ String version = c.getString("cms.version", "pre4.2");
+
+ if (version.equals("4.22")) {
+ Upgrade.perform422to45(c);
+ } else if (version.equals("4.2")) {
+ // SUPPORT UPGRADE FROM 4.2 to 4.2 (SP2)
+ Upgrade.perform42to422(c);
+ Upgrade.perform422to45(c);
+ } else {
+ // ONLY SUPPORT UPGRADE FROM 4.2 to 4.2 (SP2)
+ /**
+ * if (!version.equals("pre4.2"))
+ * return;
+ *
+ * Upgrade.perform(c);
+ **/
+ }
+ }
+
+ public ICommandQueue getCommandQueue() {
+ return new CommandQueue();
+ }
+
+ private ICertificateRepository getCertDB() {
+ ICertificateRepository certDB = null;
+
+ try {
+ ICertificateAuthority ca = (ICertificateAuthority)
+ SubsystemRegistry.getInstance().get("ca");
+
+ if (ca != null) {
+ certDB = ca.getCertificateRepository();
+ }
+ } catch (Exception e) {
+ CMS.debug("CMSEngine: " + CMS.getLogMessage("CMSCORE_AUTH_AGENT_CERT_REPO"));
+ }
+
+ return certDB;
+ }
+
+ private IRequestQueue getReqQueue() {
+ IRequestQueue queue = null;
+
+ try {
+ IRegistrationAuthority ra = (IRegistrationAuthority)
+ SubsystemRegistry.getInstance().get("ra");
+
+ if (ra != null) {
+ queue = ra.getRequestQueue();
+ }
+
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_AGENT_REQUEST_QUEUE"));
+ }
+
+ return queue;
+ }
+
+ private VerifiedCerts mVCList = null;
+ private int mVCListSize = 0;
+
+ public void setListOfVerifiedCerts(int size, long interval, long unknownStateInterval) {
+ if (size > 0 && mVCListSize == 0) {
+ mVCListSize = size;
+ mVCList = new VerifiedCerts(size, interval, unknownStateInterval);
+ }
+ }
+
+ public boolean isRevoked(X509Certificate[] certificates) {
+ boolean revoked = false;
+
+ if (certificates != null) {
+ X509CertImpl cert = (X509CertImpl) certificates[0];
+
+ int result = VerifiedCert.UNKNOWN;
+
+ if (mVCList != null) {
+ result = mVCList.check(cert);
+ }
+ if (result != VerifiedCert.REVOKED &&
+ result != VerifiedCert.NOT_REVOKED &&
+ result != VerifiedCert.CHECKED) {
+
+ CertificateRepository certDB = (CertificateRepository) getCertDB();
+
+ if (certDB != null) {
+ try {
+ if (certDB.isCertificateRevoked(cert) != null) {
+ revoked = true;
+ if (mVCList != null)
+ mVCList.update(cert, VerifiedCert.REVOKED);
+ } else {
+ if (mVCList != null)
+ mVCList.update(cert, VerifiedCert.NOT_REVOKED);
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_AGENT_REVO_STATUS"));
+ }
+ } else {
+ IRequestQueue queue = getReqQueue();
+
+ if (queue != null) {
+ IRequest checkRevReq = null;
+
+ try {
+ checkRevReq = queue.newRequest(CertRequestConstants.GETREVOCATIONINFO_REQUEST);
+ checkRevReq.setExtData(IRequest.REQ_TYPE,
+ CertRequestConstants.GETREVOCATIONINFO_REQUEST);
+ checkRevReq.setExtData(IRequest.REQUESTOR_TYPE,
+ IRequest.REQUESTOR_RA);
+
+ X509CertImpl agentCerts[] = new X509CertImpl[certificates.length];
+
+ for (int i = 0; i < certificates.length; i++) {
+ agentCerts[i] = (X509CertImpl) certificates[i];
+ }
+ checkRevReq.setExtData(IRequest.ISSUED_CERTS, agentCerts);
+
+ queue.processRequest(checkRevReq);
+
+ RequestStatus status = checkRevReq.getRequestStatus();
+
+ if (status == RequestStatus.COMPLETE) {
+ Enumeration<String> enum1 = checkRevReq.getExtDataKeys();
+
+ while (enum1.hasMoreElements()) {
+ String name = enum1.nextElement();
+
+ if (name.equals(IRequest.REVOKED_CERTS)) {
+ revoked = true;
+ if (mVCList != null)
+ mVCList.update(cert, VerifiedCert.REVOKED);
+ }
+ }
+ if (revoked == false) {
+ if (mVCList != null)
+ mVCList.update(cert, VerifiedCert.NOT_REVOKED);
+ }
+
+ } else {
+ if (mVCList != null)
+ mVCList.update(cert, VerifiedCert.CHECKED);
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_AGENT_PROCESS_CHECKING"));
+ }
+ }
+ }
+ } else if (result == VerifiedCert.REVOKED) {
+ revoked = true;
+ }
+ }
+
+ return revoked;
+ }
+
+ private void log(int level, String msg) {
+ Logger.getLogger().log(ILogger.EV_SYSTEM, null,
+ ILogger.S_AUTHENTICATION, level, msg);
+ }
+
+ @Override
+ public String getServerStatus() {
+ return serverStatus;
+ }
+}
+
+class WarningListener implements ILogEventListener {
+ private StringBuffer mSB = null;
+
+ public WarningListener(StringBuffer sb) {
+ mSB = sb;
+ }
+
+ public void log(ILogEvent event) throws ELogException {
+ String str = event.toString();
+
+ // start.cc and restart.cc does not like carriage
+ // return. They are the programs that pass the
+ // log messages to the console
+ str = str.replace('\n', ' ');
+ if (event.getLevel() == ILogger.LL_FAILURE) {
+ mSB.append("FAILURE: " + str + "|");
+ }
+ if (event.getLevel() == ILogger.LL_WARN) {
+ mSB.append("WARNING: " + str + "|");
+ }
+ }
+
+ public void flush() {
+ }
+
+ public void shutdown() {
+ }
+
+ public IConfigStore getConfigStore() {
+ return null;
+ }
+
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ }
+
+ public void startup() {
+ }
+
+ /**
+ * Retrieve last "maxLine" number of system log with log lever >"level"
+ * and from source "source". If the parameter is omitted. All entries
+ * are sent back.
+ */
+ public synchronized NameValuePairs retrieveLogContent(Hashtable<String, String> req) throws ServletException,
+ IOException, EBaseException {
+ return null;
+ }
+
+ /**
+ * Retrieve log file list.
+ */
+ public synchronized NameValuePairs retrieveLogList(Hashtable<String, String> req) throws ServletException,
+ IOException, EBaseException {
+ return null;
+ }
+
+ public String getImplName() {
+ return "ConsoleLog";
+ }
+
+ public String getDescription() {
+ return "ConsoleLog";
+ }
+
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ return v;
+ }
+
+ public Vector<String> getInstanceParams() {
+ Vector<String> v = new Vector<String>();
+
+ return v;
+ }
+}
+
+class SubsystemInfo {
+ public final String mId;
+ public final ISubsystem mInstance;
+
+ public SubsystemInfo(String id, ISubsystem ssInstance) {
+ mId = id;
+ mInstance = ssInstance;
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/apps/CommandQueue.java b/base/server/cmscore/src/com/netscape/cmscore/apps/CommandQueue.java
new file mode 100644
index 000000000..d501de343
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/apps/CommandQueue.java
@@ -0,0 +1,99 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.apps;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.servlet.Servlet;
+
+import com.netscape.certsrv.apps.ICommandQueue;
+import com.netscape.certsrv.common.ICMSRequest;
+
+/*---------------------------------------------------------------
+ ** CommandQueue - Class
+ */
+
+/**
+ * register and unregister proccess for clean shutdown
+ */
+public class CommandQueue implements Runnable, ICommandQueue {
+
+ public static Hashtable<ICMSRequest, Servlet> mCommandQueue = new Hashtable<ICMSRequest, Servlet>();
+ public static boolean mShuttingDown = false;
+
+ /*-----------------------------------------------------------
+ ** CommandQueue - Constructor
+ */
+
+ /**
+ * Main constructor.
+ */
+ public CommandQueue() {
+
+ } // CommandQueue
+
+ /*-----------------------------------------------------------
+ ** run
+ */
+
+ /**
+ * Overrides Thread.run(), calls batchPublish().
+ */
+ public void run() {
+ //int priority = Thread.MIN_PRIORITY;
+ //Thread.currentThread().setPriority(priority);
+ /*-------------------------------------------------
+ ** Loop until queue is empty
+ */
+ mShuttingDown = true;
+ while (mCommandQueue.isEmpty() == false) {
+ try {
+ Thread.sleep(5 * 1000);
+ //gcProcess();
+ } catch (Exception e) {
+
+ }
+ }
+ } // run
+
+ public boolean registerProcess(ICMSRequest currentRequest, Servlet currentServlet) {
+ if (mShuttingDown == false) {
+ if ((currentServlet instanceof com.netscape.cms.servlet.base.CMSStartServlet) == false)
+ mCommandQueue.put(currentRequest, currentServlet);
+ return true;
+ } else
+ return false;
+
+ }
+
+ public void unRegisterProccess(Object currentRequest, Object currentServlet) {
+ Enumeration<ICMSRequest> e = mCommandQueue.keys();
+
+ while (e.hasMoreElements()) {
+ Object thisRequest = e.nextElement();
+
+ if (thisRequest.equals(currentRequest)) {
+ if (mCommandQueue.get(currentRequest).equals(currentServlet))
+ mCommandQueue.remove(currentRequest);
+ }
+ }
+
+ }
+} // CommandQueue
+
diff --git a/base/server/cmscore/src/com/netscape/cmscore/apps/PKIServerEvent.java b/base/server/cmscore/src/com/netscape/cmscore/apps/PKIServerEvent.java
new file mode 100644
index 000000000..c49307a9e
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/apps/PKIServerEvent.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.apps;
+
+/**
+ * A class represents a PKIServer event.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class PKIServerEvent {
+
+ public final static int INITIALIZED = 0;
+ public final static int STARTED_UP = 1;
+ public final static int STOPPED = 2;
+
+ public int mStatus;
+
+ public PKIServerEvent(int status) {
+ mStatus = status;
+ }
+
+ public int getStatus() {
+ return mStatus;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/apps/PKIServerListener.java b/base/server/cmscore/src/com/netscape/cmscore/apps/PKIServerListener.java
new file mode 100644
index 000000000..9cfcb1b31
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/apps/PKIServerListener.java
@@ -0,0 +1,35 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.apps;
+
+/**
+ * A class represents a listener that listens to
+ * PKIServer event.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class PKIServerListener {
+
+ /**
+ * Updates listener with the server event.
+ */
+ public void update(PKIServerEvent e) {
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/apps/Setup.java b/base/server/cmscore/src/com/netscape/cmscore/apps/Setup.java
new file mode 100644
index 000000000..fecf024de
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/apps/Setup.java
@@ -0,0 +1,348 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.apps;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+
+/**
+ * Select certificate server serices.
+ *
+ * @author thomask
+ * @author nicolson
+ * @version $Revision$, $Date$
+ */
+public class Setup {
+
+ // These are a bunch of fixed values that just need to be stored to the
+ // config file before the server is started.
+ public static final String[][] authEntries = new String[][] {
+ { "auths._000", "##" },
+ { "auths._001", "## new authentication" },
+ { "auths._002", "##" },
+ { "auths.impl._000", "##" },
+ { "auths.impl._001", "## authentication manager implementations" },
+ { "auths.impl._002", "##" },
+ { "auths.impl.UidPwdDirAuth.class", "com.netscape.cms.authentication.UidPwdDirAuthentication" },
+ { "auths.impl.UidPwdPinDirAuth.class", "com.netscape.cms.authentication.UidPwdPinDirAuthentication" },
+ { "auths.impl.UdnPwdDirAuth.class", "com.netscape.cms.authentication.UdnPwdDirAuthentication" },
+ { "auths.impl.NISAuth.class", "com.netscape.cms.authentication.NISAuth" },
+ { "auths.impl.CMCAuth.class", "com.netscape.cms.authentication.CMCAuth" },
+ { "auths.impl.AgentCertAuth.class", "com.netscape.cms.authentication.AgentCertAuthentication" },
+ { "auths.impl.PortalEnroll.class", "com.netscape.cms.authentication.PortalEnroll"
+ },
+ { "auths.revocationChecking.bufferSize", "50" },
+ };
+
+ public static void installAuthImpls(IConfigStore c)
+ throws EBaseException {
+ for (int i = 0; i < authEntries.length; i++) {
+ c.putString(authEntries[i][0], authEntries[i][1]);
+ }
+ }
+
+ public static final String[][] oidmapEntries = new String[][] {
+ { "oidmap.pse.class", "netscape.security.extensions.PresenceServerExtension" },
+ { "oidmap.pse.oid", "2.16.840.1.113730.1.18" },
+ { "oidmap.ocsp_no_check.class", "netscape.security.extensions.OCSPNoCheckExtension" },
+ { "oidmap.ocsp_no_check.oid", "1.3.6.1.5.5.7.48.1.5" },
+ { "oidmap.netscape_comment.class", "netscape.security.x509.NSCCommentExtension" },
+ { "oidmap.netscape_comment.oid", "2.16.840.1.113730.1.13" },
+ { "oidmap.extended_key_usage.class", "netscape.security.extensions.ExtendedKeyUsageExtension" },
+ { "oidmap.extended_key_usage.oid", "2.5.29.37" },
+ { "oidmap.subject_info_access.class", "netscape.security.extensions.SubjectInfoAccessExtension" },
+ { "oidmap.subject_info_access.oid", "1.3.6.1.5.5.7.1.11" },
+ { "oidmap.auth_info_access.class", "netscape.security.extensions.AuthInfoAccessExtension" },
+ { "oidmap.auth_info_access.oid", "1.3.6.1.5.5.7.1.1" },
+ { "oidmap.challenge_password.class", "com.netscape.cms.servlet.cert.scep.ChallengePassword" },
+ { "oidmap.challenge_password.oid", "1.2.840.113549.1.9.7" },
+ { "oidmap.extensions_requested_vsgn.class", "com.netscape.cms.servlet.cert.scep.ExtensionsRequested" },
+ { "oidmap.extensions_requested_vsgn.oid", "2.16.840.1.113733.1.9.8" },
+ { "oidmap.extensions_requested_pkcs9.class", "com.netscape.cms.servlet.cert.scep.ExtensionsRequested" },
+ { "oidmap.extensions_requested_pkcs9.oid", "1.2.840.113549.1.9.14" },
+ };
+
+ public static void installOIDMap(IConfigStore c)
+ throws EBaseException {
+ for (int i = 0; i < oidmapEntries.length; i++) {
+ c.putString(oidmapEntries[i][0], oidmapEntries[i][1]);
+ }
+ }
+
+ /**
+ * This function is used for installation and upgrade.
+ */
+ public static void installPolicyImpls(String prefix, IConfigStore c)
+ throws EBaseException {
+ boolean isCA = false;
+
+ if (prefix.equals("ca"))
+ isCA = true;
+
+ //
+ // Policy implementations (class names)
+ //
+ c.putString(prefix + ".Policy.impl._000", "##");
+ c.putString(prefix + ".Policy.impl._001",
+ "## Policy Implementations");
+ c.putString(prefix + ".Policy.impl._002", "##");
+ c.putString(
+ prefix + ".Policy.impl.KeyAlgorithmConstraints.class",
+ "com.netscape.cmscore.policy.KeyAlgorithmConstraints");
+ c.putString(
+ prefix + ".Policy.impl.DSAKeyConstraints.class",
+ "com.netscape.cmscore.policy.DSAKeyConstraints");
+ c.putString(
+ prefix + ".Policy.impl.RSAKeyConstraints.class",
+ "com.netscape.cmscore.policy.RSAKeyConstraints");
+ c.putString(
+ prefix + ".Policy.impl.SigningAlgorithmConstraints.class",
+ "com.netscape.cmscore.policy.SigningAlgorithmConstraints");
+ c.putString(
+ prefix + ".Policy.impl.ValidityConstraints.class",
+ "com.netscape.cmscore.policy.ValidityConstraints");
+
+ /**
+ * c.putString(
+ * prefix + ".Policy.impl.NameConstraints.class",
+ * "com.netscape.cmscore.policy.NameConstraints");
+ **/
+ c.putString(
+ prefix + ".Policy.impl.RenewalConstraints.class",
+ "com.netscape.cmscore.policy.RenewalConstraints");
+ c.putString(
+ prefix + ".Policy.impl.RenewalValidityConstraints.class",
+ "com.netscape.cmscore.policy.RenewalValidityConstraints");
+ c.putString(
+ prefix + ".Policy.impl.RevocationConstraints.class",
+ "com.netscape.cmscore.policy.RevocationConstraints");
+ //getTempCMSConfig().putString(
+ // prefix + ".Policy.impl.DefaultRevocation.class",
+ // "com.netscape.cmscore.policy.DefaultRevocation");
+ c.putString(
+ prefix + ".Policy.impl.NSCertTypeExt.class",
+ "com.netscape.cmscore.policy.NSCertTypeExt");
+ c.putString(
+ prefix + ".Policy.impl.KeyUsageExt.class",
+ "com.netscape.cmscore.policy.KeyUsageExt");
+ c.putString(
+ prefix + ".Policy.impl.SubjectKeyIdentifierExt.class",
+ "com.netscape.cmscore.policy.SubjectKeyIdentifierExt");
+ c.putString(
+ prefix + ".Policy.impl.CertificatePoliciesExt.class",
+ "com.netscape.cmscore.policy.CertificatePoliciesExt");
+ c.putString(
+ prefix + ".Policy.impl.NSCCommentExt.class",
+ "com.netscape.cmscore.policy.NSCCommentExt");
+ c.putString(
+ prefix + ".Policy.impl.IssuerAltNameExt.class",
+ "com.netscape.cmscore.policy.IssuerAltNameExt");
+ c.putString(
+ prefix + ".Policy.impl.PrivateKeyUsagePeriodExt.class",
+ "com.netscape.cmscore.policy.PrivateKeyUsagePeriodExt");
+ c.putString(
+ prefix + ".Policy.impl.AttributePresentConstraints.class",
+ "com.netscape.cmscore.policy.AttributePresentConstraints");
+ c.putString(
+ prefix + ".Policy.impl.SubjectAltNameExt.class",
+ "com.netscape.cmscore.policy.SubjectAltNameExt");
+ c.putString(
+ prefix + ".Policy.impl.SubjectDirectoryAttributesExt.class",
+ "com.netscape.cmscore.policy.SubjectDirectoryAttributesExt");
+ c.putString(
+ prefix + ".Policy.impl.CertificateRenewalWindowExt.class",
+ "com.netscape.cmscore.policy.CertificateRenewalWindowExt");
+ c.putString(
+ prefix + ".Policy.impl.CertificateScopeOfUseExt.class",
+ "com.netscape.cmscore.policy.CertificateScopeOfUseExt");
+ if (isCA) {
+ c.putString(
+ prefix + ".Policy.impl.AuthorityKeyIdentifierExt.class",
+ "com.netscape.cmscore.policy.AuthorityKeyIdentifierExt");
+ c.putString(
+ prefix + ".Policy.impl.BasicConstraintsExt.class",
+ "com.netscape.cmscore.policy.BasicConstraintsExt");
+ c.putString(
+ prefix + ".Policy.impl.SubCANameConstraints.class",
+ "com.netscape.cmscore.policy.SubCANameConstraints");
+ }
+ c.putString(
+ prefix + ".Policy.impl.CRLDistributionPointsExt.class",
+ "com.netscape.cmscore.policy.CRLDistributionPointsExt");
+ c.putString(
+ prefix + ".Policy.impl.AuthInfoAccessExt.class",
+ "com.netscape.cmscore.policy.AuthInfoAccessExt");
+ c.putString(
+ prefix + ".Policy.impl.OCSPNoCheckExt.class",
+ "com.netscape.cmscore.policy.OCSPNoCheckExt");
+ c.putString(
+ prefix + ".Policy.impl.ExtendedKeyUsageExt.class",
+ "com.netscape.cmscore.policy.ExtendedKeyUsageExt");
+ if (isCA) {
+ c.putString(
+ prefix + ".Policy.impl.UniqueSubjectNameConstraints.class",
+ "com.netscape.cmscore.policy.UniqueSubjectNameConstraints");
+ }
+ c.putString(
+ prefix + ".Policy.impl.GenericASN1Ext.class",
+ "com.netscape.cmscore.policy.GenericASN1Ext");
+ c.putString(
+ prefix + ".Policy.impl.RemoveBasicConstraintsExt.class",
+ "com.netscape.cmscore.policy.RemoveBasicConstraintsExt");
+ }
+
+ /**
+ * This function is used for installation and upgrade.
+ */
+ public static void installCACRLExtensions(IConfigStore c)
+ throws EBaseException {
+ // ca crl extensions
+
+ // AuthorityKeyIdentifier
+ c.putString("ca.crl.MasterCRL.extension.AuthorityKeyIdentifier.enable",
+ "false");
+ c.putString("ca.crl.MasterCRL.extension.AuthorityKeyIdentifier.critical",
+ "false");
+ c.putString("ca.crl.MasterCRL.extension.AuthorityKeyIdentifier.type",
+ "CRLExtension");
+ c.putString("ca.crl.MasterCRL.extension.AuthorityKeyIdentifier.class",
+ "com.netscape.cms.crl.CMSAuthorityKeyIdentifierExtension");
+
+ // IssuerAlternativeName
+ c.putString("ca.crl.MasterCRL.extension.IssuerAlternativeName.enable",
+ "false");
+ c.putString("ca.crl.MasterCRL.extension.IssuerAlternativeName.critical",
+ "false");
+ c.putString("ca.crl.MasterCRL.extension.IssuerAlternativeName.type",
+ "CRLExtension");
+ c.putString("ca.crl.MasterCRL.extension.IssuerAlternativeName.class",
+ "com.netscape.cms.crl.CMSIssuerAlternativeNameExtension");
+ c.putString("ca.crl.MasterCRL.extension.IssuerAlternativeName.numNames", "0");
+ c.putString("ca.crl.MasterCRL.extension.IssuerAlternativeName.nameType0", "");
+ c.putString("ca.crl.MasterCRL.extension.IssuerAlternativeName.name0", "");
+
+ // CRLNumber
+ c.putString("ca.crl.MasterCRL.extension.CRLNumber.enable", "true");
+ c.putString("ca.crl.MasterCRL.extension.CRLNumber.critical", "false");
+ c.putString("ca.crl.MasterCRL.extension.CRLNumber.type", "CRLExtension");
+ c.putString("ca.crl.MasterCRL.extension.CRLNumber.class",
+ "com.netscape.cms.crl.CMSCRLNumberExtension");
+
+ // DeltaCRLIndicator
+ c.putString("ca.crl.MasterCRL.extension.DeltaCRLIndicator.enable", "false");
+ c.putString("ca.crl.MasterCRL.extension.DeltaCRLIndicator.critical", "true");
+ c.putString("ca.crl.MasterCRL.extension.DeltaCRLIndicator.type", "CRLExtension");
+ c.putString("ca.crl.MasterCRL.extension.DeltaCRLIndicator.class",
+ "com.netscape.cms.crl.CMSDeltaCRLIndicatorExtension");
+
+ // IssuingDistributionPoint
+ c.putString("ca.crl.MasterCRL.extension.IssuingDistributionPoint.enable",
+ "false");
+ c.putString("ca.crl.MasterCRL.extension.IssuingDistributionPoint.critical",
+ "true");
+ c.putString("ca.crl.MasterCRL.extension.IssuingDistributionPoint.type",
+ "CRLExtension");
+ c.putString("ca.crl.MasterCRL.extension.IssuingDistributionPoint.class",
+ "com.netscape.cms.crl.CMSIssuingDistributionPointExtension");
+ c.putString("ca.crl.MasterCRL.extension.IssuingDistributionPoint.pointType", "");
+ c.putString("ca.crl.MasterCRL.extension.IssuingDistributionPoint.pointName", "");
+ c.putString("ca.crl.MasterCRL.extension.IssuingDistributionPoint.onlyContainsUserCerts",
+ "false");
+ c.putString("ca.crl.MasterCRL.extension.IssuingDistributionPoint.onlyContainsCACerts",
+ "false");
+ c.putString("ca.crl.MasterCRL.extension.IssuingDistributionPoint.onlySomeReasons", "");
+ //"keyCompromise,cACompromise,affiliationChanged,superseded,cessationOfOperation,certificateHold");
+ c.putString("ca.crl.MasterCRL.extension.IssuingDistributionPoint.indirectCRL",
+ "false");
+
+ // CRLReason
+ c.putString("ca.crl.MasterCRL.extension.CRLReason.enable", "true");
+ c.putString("ca.crl.MasterCRL.extension.CRLReason.critical", "false");
+ c.putString("ca.crl.MasterCRL.extension.CRLReason.type", "CRLEntryExtension");
+ c.putString("ca.crl.MasterCRL.extension.CRLReason.class",
+ "com.netscape.cms.crl.CMSCRLReasonExtension");
+
+ // HoldInstruction
+ c.putString("ca.crl.MasterCRL.extension.HoldInstruction.enable", "false");
+ c.putString("ca.crl.MasterCRL.extension.HoldInstruction.critical", "false");
+ c.putString("ca.crl.MasterCRL.extension.HoldInstruction.type", "CRLEntryExtension");
+ c.putString("ca.crl.MasterCRL.extension.HoldInstruction.class",
+ "com.netscape.cms.crl.CMSHoldInstructionExtension");
+ c.putString("ca.crl.MasterCRL.extension.HoldInstruction.instruction", "none");
+
+ // InvalidityDate
+ c.putString("ca.crl.MasterCRL.extension.InvalidityDate.enable", "true");
+ c.putString("ca.crl.MasterCRL.extension.InvalidityDate.critical", "false");
+ c.putString("ca.crl.MasterCRL.extension.InvalidityDate.type", "CRLEntryExtension");
+ c.putString("ca.crl.MasterCRL.extension.InvalidityDate.class",
+ "com.netscape.cms.crl.CMSInvalidityDateExtension");
+
+ // CertificateIssuer
+ /*
+ c.putString("ca.crl.MasterCRL.extension.CertificateIssuer.enable", "false");
+ c.putString("ca.crl.MasterCRL.extension.CertificateIssuer.critical", "true");
+ c.putString("ca.crl.MasterCRL.extension.CertificateIssuer.type", "CRLEntryExtension");
+ c.putString("ca.crl.MasterCRL.extension.CertificateIssuer.class",
+ "com.netscape.cms.crl.CMSCertificateIssuerExtension");
+ c.putString("ca.crl.MasterCRL.extension.CertificateIssuer.numNames", "0");
+ c.putString("ca.crl.MasterCRL.extension.CertificateIssuer.nameType0", "");
+ c.putString("ca.crl.MasterCRL.extension.CertificateIssuer.name0", "");
+ */
+
+ // FreshestCRL
+ c.putString("ca.crl.MasterCRL.extension.FreshestCRL.enable", "false");
+ c.putString("ca.crl.MasterCRL.extension.FreshestCRL.critical", "false");
+ c.putString("ca.crl.MasterCRL.extension.FreshestCRL.type", "CRLExtension");
+ c.putString("ca.crl.MasterCRL.extension.FreshestCRL.class",
+ "com.netscape.cms.crl.CMSFreshestCRLExtension");
+ c.putString("ca.crl.MasterCRL.extension.FreshestCRL.numPoints", "0");
+ c.putString("ca.crl.MasterCRL.extension.FreshestCRL.pointType0", "");
+ c.putString("ca.crl.MasterCRL.extension.FreshestCRL.pointName0", "");
+ }
+
+ public static void installCAPublishingImpls(IConfigStore c)
+ throws EBaseException {
+ for (int i = 0; i < caLdappublishImplsEntries.length; i++) {
+ c.putString(
+ caLdappublishImplsEntries[i][0], caLdappublishImplsEntries[i][1]);
+ }
+ }
+
+ private static final String[][] caLdappublishImplsEntries = new String[][] {
+ { "ca.publish.mapper.impl.LdapCaSimpleMap.class", "com.netscape.cms.publish.LdapCaSimpleMap" },
+ { "ca.publish.mapper.impl.LdapSimpleMap.class", "com.netscape.cms.publish.LdapSimpleMap" },
+ { "ca.publish.mapper.impl.LdapEnhancedMap.class", "com.netscape.cms.publish.LdapEnhancedMap" },
+ { "ca.publish.mapper.impl.LdapDNCompsMap.class", "com.netscape.cms.publish.LdapCertCompsMap" },
+ { "ca.publish.mapper.impl.LdapSubjAttrMap.class", "com.netscape.cms.publish.LdapCertSubjMap" },
+ { "ca.publish.mapper.impl.LdapDNExactMap.class", "com.netscape.cms.publish.LdapCertExactMap" },
+ //{"ca.publish.mapper.impl.LdapCrlIssuerCompsMap.class","com.netscape.cms.publish.LdapCrlIssuerCompsMap"},
+ {
+ "ca.publish.publisher.impl.LdapUserCertPublisher.class",
+ "com.netscape.cms.publish.LdapUserCertPublisher" },
+ {
+ "ca.publish.publisher.impl.LdapCaCertPublisher.class",
+ "com.netscape.cms.publish.LdapCaCertPublisher" },
+ { "ca.publish.publisher.impl.LdapCrlPublisher.class", "com.netscape.cms.publish.LdapCrlPublisher" },
+ {
+ "ca.publish.publisher.impl.FileBasedPublisher.class",
+ "com.netscape.cms.publish.FileBasedPublisher" },
+ { "ca.publish.publisher.impl.OCSPPublisher.class", "com.netscape.cms.publish.OCSPPublisher" },
+ { "ca.publish.rule.impl.Rule.class", "com.netscape.cmscore.ldap.LdapRule" },
+ };
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/apps/Upgrade.java b/base/server/cmscore/src/com/netscape/cmscore/apps/Upgrade.java
new file mode 100644
index 000000000..cd5b2991f
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/apps/Upgrade.java
@@ -0,0 +1,329 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.apps;
+
+import java.io.File;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.cmsutil.util.Utils;
+
+public final class Upgrade {
+ public static void perform422to45(IConfigStore c)
+ throws EBaseException {
+ jss3(c);
+ c.putInteger("agentGateway.https.timeout", 120);
+ IConfigStore cs = c.getSubStore("ca");
+
+ if (cs != null && cs.size() > 0) {
+ c.putString("ca.publish.mapper.impl.LdapEnhancedMap.class",
+ "com.netscape.certsrv.ldap.LdapEnhancedMap");
+ }
+ c.putString("cms.version", "4.5");
+ c.commit(false);
+ }
+
+ public static void perform42to422(IConfigStore c)
+ throws EBaseException {
+ // upgrade CMS's configuration parameters
+ c.putString(
+ "eeGateway.dynamicVariables",
+ "serverdate=serverdate(),subsystemname=subsystemname(),http=http(),authmgrs=authmgrs(),clacrlurl=clacrlurl()");
+
+ // new OCSP Publisher implemention
+ c.putString("ra.publish.publisher.impl.OCSPPublisher.class",
+ "com.netscape.certsrv.ldap.OCSPPublisher");
+ c.putString("ca.publish.publisher.impl.OCSPPublisher.class",
+ "com.netscape.certsrv.ldap.OCSPPublisher");
+
+ // new logging framework
+ c.putString("log.impl.file.class",
+ "com.netscape.certsrv.logging.RollingLogFile");
+
+ c.putString("log.instance.Audit.bufferSize",
+ c.getString("logAudit.bufferSize"));
+ c.putString("log.instance.Audit.enable",
+ c.getString("logAudit.on"));
+ // This feature doesnot work in the previous release
+ // But it works now. I don't want people to have their
+ // logs auto deleted without notice.It's dangerous.
+ c.putString("log.instance.Audit.expirationTime",
+ "0"); //Specifically turn it off.
+ // c.getString("logAudit.expirationTime"));
+ c.putString("log.instance.Audit.fileName",
+ c.getString("logAudit.fileName"));
+ c.putString("log.instance.Audit.flushInterval",
+ c.getString("logAudit.flushInterval"));
+ c.putString("log.instance.Audit.level",
+ c.getString("logAudit.level"));
+ c.putString("log.instance.Audit.maxFileSize",
+ c.getString("logAudit.maxFileSize"));
+ c.putString("log.instance.Audit.pluginName",
+ "file");
+ c.putString("log.instance.Audit.rolloverInterval",
+ c.getString("logAudit.rolloverInterval"));
+ c.putString("log.instance.Audit.type",
+ "audit");
+
+ c.putString("log.instance.Error.bufferSize",
+ c.getString("logError.bufferSize"));
+ c.putString("log.instance.Error.enable",
+ c.getString("logError.on"));
+ c.putString("log.instance.Error.expirationTime",
+ "0"); //Specifically turn it off.
+ // c.getString("logError.expirationTime"));
+ c.putString("log.instance.Error.fileName",
+ c.getString("logError.fileName"));
+ c.putString("log.instance.Error.flushInterval",
+ c.getString("logError.flushInterval"));
+ c.putString("log.instance.Error.level",
+ c.getString("logError.level"));
+ c.putString("log.instance.Error.maxFileSize",
+ c.getString("logError.maxFileSize"));
+ c.putString("log.instance.Error.pluginName",
+ "file");
+ c.putString("log.instance.Error.rolloverInterval",
+ c.getString("logError.rolloverInterval"));
+ c.putString("log.instance.Error.type",
+ "system");
+
+ c.putString("log.instance.System.bufferSize",
+ c.getString("logSystem.bufferSize"));
+ c.putString("log.instance.System.enable",
+ c.getString("logSystem.on"));
+ c.putString("log.instance.System.expirationTime",
+ "0"); //Specifically turn it off.
+ // c.getString("logSystem.expirationTime"));
+ c.putString("log.instance.System.fileName",
+ c.getString("logSystem.fileName"));
+ c.putString("log.instance.System.flushInterval",
+ c.getString("logSystem.flushInterval"));
+ c.putString("log.instance.System.level",
+ c.getString("logSystem.level"));
+ c.putString("log.instance.System.maxFileSize",
+ c.getString("logSystem.maxFileSize"));
+ c.putString("log.instance.System.pluginName",
+ "file");
+ c.putString("log.instance.System.rolloverInterval",
+ c.getString("logSystem.rolloverInterval"));
+ c.putString("log.instance.System.type",
+ "system");
+
+ if (Utils.isNT()) {
+ c.putString("log.impl.NTEventLog.class",
+ "com.netscape.certsrv.logging.NTEventLog");
+
+ c.putString("log.instance.NTAudit.NTEventSourceName",
+ c.getString("logNTAudit.NTEventSourceName"));
+ c.putString("log.instance.NTAudit.enable",
+ c.getString("logNTAudit.on"));
+ c.putString("log.instance.NTAudit.level",
+ c.getString("logNTAudit.level"));
+ c.putString("log.instance.NTAudit.pluginName",
+ "NTEventLog");
+ c.putString("log.instance.NTAudit.type",
+ "system");
+
+ c.putString("log.instance.NTSystem.NTEventSourceName",
+ c.getString("logNTSystem.NTEventSourceName"));
+ c.putString("log.instance.NTSystem.enable",
+ c.getString("logNTSystem.on"));
+ c.putString("log.instance.NTSystem.level",
+ c.getString("logNTSystem.level"));
+ c.putString("log.instance.NTSystem.pluginName",
+ "NTEventLog");
+ c.putString("log.instance.NTSystem.type",
+ "system");
+ }
+ c.putString("cms.version", "4.22");
+ c.commit(false);
+ }
+
+ /**
+ * This method handles pre4.2 -> 4.2 configuration
+ * upgrade.
+ */
+ public static void perform(IConfigStore c)
+ throws EBaseException {
+ boolean isCA = false;
+ boolean isRA = false;
+
+ // determine what subsystems do we have?
+ IConfigStore cs = c.getSubStore("ca");
+
+ if (cs != null && cs.size() > 0) {
+ isCA = true;
+ }
+ cs = c.getSubStore("ra");
+ if (cs != null && cs.size() > 0) {
+ isRA = true;
+ }
+
+ Setup.installAuthImpls(c);
+ Setup.installOIDMap(c);
+
+ // start upgrade processing
+ if (isCA) {
+ Setup.installPolicyImpls("ca", c);
+ Setup.installCACRLExtensions(c);
+ Setup.installCAPublishingImpls(c);
+ caPublishing(c);
+ }
+
+ if (isRA) {
+ Setup.installPolicyImpls("ra", c);
+ }
+
+ c.putString("eeGateway.dynamicVariables",
+ "serverdate=serverdate(),subsystemname=subsystemname(),http=http(),authmgrs=authmgrs()");
+
+ c.putString("cms.version", "4.2");
+ // Assumed user backups (including CMS.cfg) the system before
+ // upgrading
+ c.commit(false);
+ }
+
+ /**
+ * Upgrade publishing. This function upgrades both enabled
+ * or disabled publishing configuration.
+ */
+ public static void caPublishing(IConfigStore c)
+ throws EBaseException {
+ c.putString("ca.publish.enable",
+ c.getString("ca.enableLdapPublish", "false"));
+ c.putString("ca.publish.ldappublish.enable",
+ c.getString("ca.enableLdapPublish", "false"));
+ c.putString("ca.publish.ldappublish.ldap.ldapauth.authtype",
+ c.getString("ca.ldappublish.ldap.ldapauth.authtype", "BasicAuth"));
+ c.putString("ca.publish.ldappublish.ldap.ldapauth.bindDN",
+ c.getString("ca.ldappublish.ldap.ldapauth.bindDN", ""));
+ c.putString("ca.publish.ldappublish.ldap.ldapauth.bindPWPrompt",
+ c.getString("ca.ldappublish.ldap.ldapauth.bindPWPrompt", "LDAP Publishing"));
+ c.putString("ca.publish.ldappublish.ldap.ldapconn.host",
+ c.getString("ca.ldappublish.ldap.ldapconn.host", ""));
+ c.putString("ca.publish.ldappublish.ldap.ldapconn.port",
+ c.getString("ca.ldappublish.ldap.ldapconn.port", ""));
+ c.putString("ca.publish.ldappublish.ldap.ldapconn.secureConn",
+ c.getString("ca.ldappublish.ldap.ldapconn.secureConn", "false"));
+ c.putString("ca.publish.ldappublish.ldap.ldapconn.version",
+ c.getString("ca.ldappublish.ldap.ldapconn.version", "2"));
+
+ // mappers
+ c.putString("ca.publish.mapper.instance.LdapCaCertMap.pluginName",
+ "LdapDNCompsMap");
+ c.putString("ca.publish.mapper.instance.LdapCaCertMap.dnComps",
+ c.getString("ca.ldappublish.type.ca.mapper.dnComps"));
+ c.putString("ca.publish.mapper.instance.LdapCaCertMap.filterComps",
+ c.getString("ca.ldappublish.type.ca.mapper.filterComps"));
+ c.putString("ca.publish.mapper.instance.LdapCaCertMap.baseDN",
+ c.getString("ca.ldappublish.type.ca.mapper.baseDN"));
+
+ c.putString("ca.publish.mapper.instance.LdapCrlMap.pluginName",
+ "LdapDNCompsMap");
+ c.putString("ca.publish.mapper.instance.LdapCrlMap.dnComps",
+ c.getString("ca.ldappublish.type.crl.mapper.dnComps"));
+ c.putString("ca.publish.mapper.instance.LdapCrlMap.filterComps",
+ c.getString("ca.ldappublish.type.crl.mapper.filterComps"));
+ c.putString("ca.publish.mapper.instance.LdapCrlMap.baseDN",
+ c.getString("ca.ldappublish.type.crl.mapper.baseDN"));
+ c.putString("ca.publish.mapper.instance.LdapUserCertMap.pluginName",
+ "LdapDNCompsMap");
+ c.putString("ca.publish.mapper.instance.LdapUserCertMap.dnComps",
+ c.getString("ca.ldappublish.type.client.mapper.dnComps"));
+ c.putString("ca.publish.mapper.instance.LdapUserCertMap.filterComps",
+ c.getString("ca.ldappublish.type.client.mapper.filterComps"));
+ c.putString("ca.publish.mapper.instance.LdapUserCertMap.baseDN",
+ c.getString("ca.ldappublish.type.client.mapper.baseDN"));
+
+ // publishers
+ c.putString("ca.publish.publisher.instance.LdapCaCertPublisher.caCertAttr", "caCertificate;binary");
+ c.putString("ca.publish.publisher.instance.LdapCaCertPublisher.caObjectClass", "certificationAuthority");
+ c.putString("ca.publish.publisher.instance.LdapCaCertPublisher.pluginName", "LdapCaCertPublisher");
+ c.putString("ca.publish.publisher.instance.LdapCrlPublisher.crlAttr", "certificateRevocationList;binary");
+ c.putString("ca.publish.publisher.instance.LdapCrlPublisher.pluginName", "LdapCrlPublisher");
+ c.putString("ca.publish.publisher.instance.LdapUserCertPublisher.certAttr", "userCertificate;binary");
+ c.putString("ca.publish.publisher.instance.LdapUserCertPublisher.pluginName", "LdapUserCertPublisher");
+
+ // rules
+ c.putString("ca.publish.rule.instance.LdapCaCertRule.pluginName ",
+ "Rule");
+ c.putString("ca.publish.rule.instance.LdapCaCertRule.predicate",
+ "");
+ c.putString("ca.publish.rule.instance.LdapCaCertRule.publisher",
+ "LdapCaCertPublisher");
+ c.putString("ca.publish.rule.instance.LdapCaCertRule.type",
+ "cacert");
+ c.putString("ca.publish.rule.instance.LdapCaCertRule.enable",
+ "true");
+ c.putString("ca.publish.rule.instance.LdapCaCertRule.mapper",
+ "LdapCaCertMap");
+
+ c.putString("ca.publish.rule.instance.LdapCrlRule.pluginName",
+ "Rule");
+ c.putString("ca.publish.rule.instance.LdapCrlRule.predicate", "");
+ c.putString("ca.publish.rule.instance.LdapCrlRule.publisher",
+ "LdapCrlPublisher");
+ c.putString("ca.publish.rule.instance.LdapCrlRule.type", "crl");
+ c.putString("ca.publish.rule.instance.LdapCrlRule.enable", "true");
+ c.putString("ca.publish.rule.instance.LdapCrlRule.mapper",
+ "LdapCrlMap");
+
+ c.putString("ca.publish.rule.instance.LdapUserCertRule.pluginName",
+ "Rule");
+ c.putString("ca.publish.rule.instance.LdapUserCertRule.predicate", "");
+ c.putString("ca.publish.rule.instance.LdapUserCertRule.publisher",
+ "LdapUserCertPublisher");
+ c.putString("ca.publish.rule.instance.LdapUserCertRule.type", "certs");
+ c.putString("ca.publish.rule.instance.LdapUserCertRule.enable", "true");
+ c.putString("ca.publish.rule.instance.LdapUserCertRule.mapper",
+ "LdapUserCertMap");
+
+ c.removeSubStore("ca.ldappublish");
+ }
+
+ /**
+ * Upgrade publishing. This function upgrades both enabled
+ * or disabled publishing configuration.
+ */
+ public static void jss3(IConfigStore c)
+ throws EBaseException {
+ String moddb = c.getString("jss.moddb");
+
+ if (moddb == null)
+ return;
+
+ int i = moddb.lastIndexOf("/");
+ String dir = moddb.substring(0, i);
+ String secmodName = moddb.substring(i + 1);
+ String certdb = c.getString("jss.certdb");
+
+ i = certdb.indexOf("/config/cert7.db");
+ certdb = certdb.substring(0, i);
+ i = certdb.lastIndexOf("/");
+ String instID = certdb.substring(i + 1);
+ String certPrefix = ".." + File.separator + ".." + File.separator + instID +
+ File.separator + "config" + File.separator;
+ String keyPrefix = certPrefix;
+
+ c.putString("jss.certPrefix", certPrefix.replace('\\', '/'));
+ c.putString("jss.keyPrefix", keyPrefix.replace('\\', '/'));
+ c.putString("jss.configDir", dir.replace('\\', '/'));
+ c.putString("jss.secmodName", secmodName);
+
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/authentication/AuthSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/authentication/AuthSubsystem.java
new file mode 100644
index 000000000..549ce01f9
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/authentication/AuthSubsystem.java
@@ -0,0 +1,511 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.authentication;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthManagerProxy;
+import com.netscape.certsrv.authentication.AuthMgrPlugin;
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.authentication.EAuthMgrNotFound;
+import com.netscape.certsrv.authentication.EAuthMgrPluginNotFound;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * Default authentication subsystem
+ * <P>
+ *
+ * @author cfu
+ * @author lhsiao
+ * @version $Revision$, $Date$
+ */
+public class AuthSubsystem implements IAuthSubsystem {
+ public static final String ID = "auths";
+
+ public Hashtable<String, AuthMgrPlugin> mAuthMgrPlugins = new Hashtable<String, AuthMgrPlugin>();
+ public Hashtable<String, AuthManagerProxy> mAuthMgrInsts = new Hashtable<String, AuthManagerProxy>();
+ private String mId = "auths";
+ private IConfigStore mConfig = null;
+
+ private ILogger mLogger = null;
+
+ // singleton enforcement
+
+ private static AuthSubsystem mInstance = new AuthSubsystem();
+
+ public static synchronized AuthSubsystem getInstance() {
+ return mInstance;
+ }
+
+ // end singleton enforcement.
+
+ private AuthSubsystem() {
+ }
+
+ /**
+ * Initializes the authentication subsystem from the config store.
+ * Load Authentication manager plugins, create and initialize
+ * initialize authentication manager instances.
+ *
+ * @param owner The owner of this module.
+ * @param config The configuration store.
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ try {
+ mLogger = CMS.getLogger();
+ mConfig = config;
+
+ // hardcode admin and agent plugins required for the server to be
+ // functional.
+
+ AuthMgrPlugin newPlugin = null;
+
+ newPlugin = new AuthMgrPlugin(PASSWDUSERDB_PLUGIN_ID,
+ PasswdUserDBAuthentication.class.getName());
+ newPlugin.setVisible(false);
+ mAuthMgrPlugins.put(PASSWDUSERDB_PLUGIN_ID, newPlugin);
+
+ newPlugin = new AuthMgrPlugin(CERTUSERDB_PLUGIN_ID,
+ CertUserDBAuthentication.class.getName());
+ newPlugin.setVisible(false);
+ mAuthMgrPlugins.put(CERTUSERDB_PLUGIN_ID, newPlugin);
+
+ newPlugin = new AuthMgrPlugin(CHALLENGE_PLUGIN_ID,
+ ChallengePhraseAuthentication.class.getName());
+ newPlugin.setVisible(false);
+ mAuthMgrPlugins.put(CHALLENGE_PLUGIN_ID, newPlugin);
+
+ // Bugscape #56659
+ // Removed NullAuthMgr to harden CMS. Otherwise,
+ // any request submitted for nullAuthMgr will
+ // be approved automatically
+ //
+ // newPlugin = new AuthMgrPlugin(NULL_PLUGIN_ID,
+ // NullAuthentication.class.getName());
+ // newPlugin.setVisible(false);
+ // mAuthMgrPlugins.put(NULL_PLUGIN_ID, newPlugin);
+
+ newPlugin = new AuthMgrPlugin(SSLCLIENTCERT_PLUGIN_ID,
+ SSLClientCertAuthentication.class.getName());
+ newPlugin.setVisible(false);
+ mAuthMgrPlugins.put(SSLCLIENTCERT_PLUGIN_ID, newPlugin);
+
+ // get auth manager plugins.
+
+ IConfigStore c = config.getSubStore(PROP_IMPL);
+ Enumeration<String> mImpls = c.getSubStoreNames();
+
+ while (mImpls.hasMoreElements()) {
+ String id = mImpls.nextElement();
+ String pluginPath = c.getString(id + "." + PROP_CLASS);
+
+ AuthMgrPlugin plugin = new AuthMgrPlugin(id, pluginPath);
+
+ mAuthMgrPlugins.put(id, plugin);
+ }
+ if (Debug.ON) {
+ Debug.trace("loaded auth plugins");
+ }
+
+ // hardcode admin and agent auth manager instances for the server
+ // to be functional
+
+ IAuthManager passwdUserDBAuth = new PasswdUserDBAuthentication();
+
+ passwdUserDBAuth.init(PASSWDUSERDB_AUTHMGR_ID, PASSWDUSERDB_PLUGIN_ID, null);
+ mAuthMgrInsts.put(PASSWDUSERDB_AUTHMGR_ID, new
+ AuthManagerProxy(true, passwdUserDBAuth));
+ if (Debug.ON) {
+ Debug.trace("loaded password based auth manager");
+ }
+
+ IAuthManager certUserDBAuth = new CertUserDBAuthentication();
+
+ certUserDBAuth.init(CERTUSERDB_AUTHMGR_ID, CERTUSERDB_PLUGIN_ID, config);
+ mAuthMgrInsts.put(CERTUSERDB_AUTHMGR_ID, new AuthManagerProxy(true, certUserDBAuth));
+ if (Debug.ON) {
+ Debug.trace("loaded certificate based auth manager");
+ }
+
+ IAuthManager challengeAuth = new ChallengePhraseAuthentication();
+
+ challengeAuth.init(CHALLENGE_AUTHMGR_ID, CHALLENGE_PLUGIN_ID, config);
+ mAuthMgrInsts.put(CHALLENGE_AUTHMGR_ID, new AuthManagerProxy(true, challengeAuth));
+ if (Debug.ON) {
+ Debug.trace("loaded challenge phrase auth manager");
+ }
+
+ IAuthManager cmcAuth = new com.netscape.cms.authentication.CMCAuth();
+
+ cmcAuth.init(CMCAUTH_AUTHMGR_ID, CMCAUTH_PLUGIN_ID, config);
+ mAuthMgrInsts.put(CMCAUTH_AUTHMGR_ID, new AuthManagerProxy(true, cmcAuth));
+ if (Debug.ON) {
+ Debug.trace("loaded cmc auth manager");
+ }
+
+ // #56659
+ // IAuthManager nullAuth = new NullAuthentication();
+
+ // nullAuth.init(NULL_AUTHMGR_ID, NULL_PLUGIN_ID, config);
+ // mAuthMgrInsts.put(NULL_AUTHMGR_ID, new AuthManagerProxy(true, nullAuth));
+ // if (Debug.ON) {
+ // Debug.trace("loaded null auth manager");
+ // }
+
+ IAuthManager sslClientCertAuth = new SSLClientCertAuthentication();
+
+ sslClientCertAuth.init(SSLCLIENTCERT_AUTHMGR_ID, SSLCLIENTCERT_PLUGIN_ID, config);
+ mAuthMgrInsts.put(SSLCLIENTCERT_AUTHMGR_ID, new AuthManagerProxy(true, sslClientCertAuth));
+ if (Debug.ON) {
+ Debug.trace("loaded sslClientCert auth manager");
+ }
+
+ // get auth manager instances.
+ c = config.getSubStore(PROP_INSTANCE);
+ Enumeration<String> instances = c.getSubStoreNames();
+
+ while (instances.hasMoreElements()) {
+ String insName = instances.nextElement();
+ String implName = c.getString(insName + "." + PROP_PLUGIN);
+ AuthMgrPlugin plugin =
+ mAuthMgrPlugins.get(implName);
+
+ if (plugin == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_CANT_FIND_PLUGIN", implName));
+ throw new EAuthMgrPluginNotFound(CMS.getUserMessage("CMS_AUTHENTICATION_AUTHMGR_NOT_FOUND",
+ implName));
+ }
+ String className = plugin.getClassPath();
+
+ boolean isEnable = false;
+ // Instantiate and init the authentication manager.
+ IAuthManager authMgrInst = null;
+
+ try {
+ authMgrInst = (IAuthManager)
+ Class.forName(className).newInstance();
+ IConfigStore authMgrConfig = c.getSubStore(insName);
+
+ authMgrInst.init(insName, implName, authMgrConfig);
+ isEnable = true;
+
+ log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_AUTH_ADD_AUTH_INSTANCE", insName));
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_AUTHSUB_ERROR", e.toString()));
+ throw new EAuthException(CMS.getUserMessage("CMS_ACL_CLASS_LOAD_FAIL", className));
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_AUTHSUB_ERROR", e.toString()));
+ throw new EAuthException(CMS.getUserMessage("CMS_ACL_CLASS_LOAD_FAIL", className));
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_AUTHSUB_ERROR", e.toString()));
+ throw new EAuthException(CMS.getUserMessage("CMS_ACL_CLASS_LOAD_FAIL", className));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_AUTH_INIT_ERROR", insName, e.toString()));
+ // Skip the authenticaiton instance if
+ // it is mis-configurated. This give
+ // administrator another chance to
+ // fix the problem via console
+ } catch (Throwable e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_AUTH_INIT_ERROR", insName, e.toString()));
+ // Skip the authenticaiton instance if
+ // it is mis-configurated. This give
+ // administrator another chance to
+ // fix the problem via console
+ }
+ // add manager instance to list.
+ mAuthMgrInsts.put(insName, new
+ AuthManagerProxy(isEnable, authMgrInst));
+ if (Debug.ON) {
+ Debug.trace("loaded auth instance " + insName + " impl " + implName);
+ }
+ }
+ log(ILogger.LL_INFO, CMS.getLogMessage("INIT_DONE", getId()));
+ } catch (EBaseException ee) {
+ if (CMS.isPreOpMode())
+ return;
+ throw ee;
+ }
+ }
+
+ /**
+ * Authenticate to the named authentication manager instance
+ * <p>
+ *
+ * @param authCred authentication credentials subject to the
+ * requirements of each authentication manager
+ * @param authMgrName name of the authentication manager instance
+ * @return authentication token with individualized authenticated
+ * information.
+ * @exception EMissingCredential If a required credential for the
+ * authentication manager is missing.
+ * @exception EInvalidCredentials If the credentials cannot be authenticated
+ * @exception EAuthMgrNotFound The auth manager is not found.
+ * @exception EBaseException If an internal error occurred.
+ */
+ public IAuthToken authenticate(
+ IAuthCredentials authCred, String authMgrInstName)
+ throws EMissingCredential, EInvalidCredentials,
+ EAuthMgrNotFound, EBaseException {
+ AuthManagerProxy proxy = mAuthMgrInsts.get(authMgrInstName);
+
+ if (proxy == null) {
+ throw new EAuthMgrNotFound(CMS.getUserMessage("CMS_AUTHENTICATION_AUTHMGR_NOT_FOUND", authMgrInstName));
+ }
+ if (!proxy.isEnable()) {
+ throw new EAuthMgrNotFound(CMS.getUserMessage("CMS_AUTHENTICATION_AUTHMGR_NOT_FOUND", authMgrInstName));
+ }
+ IAuthManager authMgrInst = proxy.getAuthManager();
+
+ if (authMgrInst == null) {
+ throw new EAuthMgrNotFound(CMS.getUserMessage("CMS_AUTHENTICATION_AUTHMGR_NOT_FOUND", authMgrInstName));
+ }
+ return (authMgrInst.authenticate(authCred));
+ }
+
+ /**
+ * Gets a list of required authentication credential names
+ * of the specified authentication manager.
+ */
+ public String[] getRequiredCreds(String authMgrInstName)
+ throws EAuthMgrNotFound {
+ IAuthManager authMgrInst = get(authMgrInstName);
+
+ if (authMgrInst == null) {
+ throw new EAuthMgrNotFound(CMS.getUserMessage("CMS_AUTHENTICATION_AUTHMGR_NOT_FOUND", authMgrInstName));
+ }
+ return authMgrInst.getRequiredCreds();
+ }
+
+ /**
+ * Gets configuration parameters for the given
+ * authentication manager plugin.
+ *
+ * @param implName Name of the authentication plugin.
+ * @return Hashtable of required parameters.
+ */
+ public String[] getConfigParams(String implName)
+ throws EAuthMgrPluginNotFound, EBaseException {
+ // is this a registered implname?
+ AuthMgrPlugin plugin = mAuthMgrPlugins.get(implName);
+
+ if (plugin == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_PLUGIN_NOT_FOUND", implName));
+ throw new EAuthMgrPluginNotFound(CMS.getUserMessage("CMS_AUTHENTICATION_AUTHMGR_NOT_FOUND", implName));
+ }
+
+ // a temporary instance
+ IAuthManager authMgrInst = null;
+ String className = plugin.getClassPath();
+
+ try {
+ authMgrInst = (IAuthManager)
+ Class.forName(className).newInstance();
+ return (authMgrInst.getConfigParams());
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_INSTANCE_NOT_CREATED", e.toString()));
+ throw new EAuthException(CMS.getUserMessage("CMS_ACL_CLASS_LOAD_FAIL", className));
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_INSTANCE_NOT_CREATED", e.toString()));
+ throw new EAuthException(CMS.getUserMessage("CMS_ACL_CLASS_LOAD_FAIL", className));
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_INSTANCE_NOT_CREATED", e.toString()));
+ throw new EAuthException(CMS.getUserMessage("CMS_ACL_CLASS_LOAD_FAIL", className));
+ }
+ }
+
+ /**
+ * Add an authentication manager instance.
+ *
+ * @param name name of the authentication manager instance
+ * @param authMgr the authentication manager instance to be added
+ */
+ public void add(String name, IAuthManager authMgrInst) {
+ mAuthMgrInsts.put(name, new AuthManagerProxy(true, authMgrInst));
+ }
+
+ /*
+ * Removes a authentication manager instance.
+ * @param name name of the authentication manager
+ */
+ public void delete(String name) {
+ mAuthMgrInsts.remove(name);
+ }
+
+ /**
+ * Gets the authentication manager instance of the specified name.
+ *
+ * @param name name of the authentication manager instance
+ * @return the named authentication manager instance
+ */
+ public IAuthManager get(String name) {
+ AuthManagerProxy proxy = mAuthMgrInsts.get(name);
+
+ if (proxy == null)
+ return null;
+ return proxy.getAuthManager();
+ }
+
+ /**
+ * Enumerate all authentication manager instances.
+ */
+ public Enumeration<IAuthManager> getAuthManagers() {
+ Vector<IAuthManager> inst = new Vector<IAuthManager>();
+ Enumeration<String> e = mAuthMgrInsts.keys();
+
+ while (e.hasMoreElements()) {
+ IAuthManager p = get(e.nextElement());
+
+ if (p != null) {
+ inst.addElement(p);
+ }
+ }
+ return (inst.elements());
+ }
+
+ /**
+ * Enumerate all registered authentication manager plugins.
+ */
+ public Enumeration<AuthMgrPlugin> getAuthManagerPlugins() {
+ return (mAuthMgrPlugins.elements());
+ }
+
+ /**
+ * retrieve a single auth manager plugin by name
+ */
+ public AuthMgrPlugin getAuthManagerPluginImpl(String name) {
+ return mAuthMgrPlugins.get(name);
+ }
+
+ /**
+ * Retrieve a single auth manager instance
+ */
+
+ /* getconfigparams above should be recoded to use this func */
+ public IAuthManager getAuthManagerPlugin(String name) {
+ AuthMgrPlugin plugin = mAuthMgrPlugins.get(name);
+ String classpath = plugin.getClassPath();
+ IAuthManager authMgrInst = null;
+
+ try {
+ authMgrInst = (IAuthManager) Class.forName(classpath).newInstance();
+ return (authMgrInst);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_INSTANCE_NOT_CREATED", e.toString()));
+ return null;
+ }
+ }
+
+ /**
+ * Retrieves id (name) of this subsystem.
+ *
+ * @return name of the authentication subsystem
+ */
+ public String getId() {
+ return (mId);
+ }
+
+ /**
+ * Sets id string to this subsystem.
+ * <p>
+ * Use with caution. Should not do it when sharing with others
+ *
+ * @param id name to be applied to an authentication sybsystem
+ */
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ /**
+ * registers the administration servlet with the administration subsystem.
+ */
+ public void startup() throws EBaseException {
+ //remove the log since it's already logged from S_ADMIN
+ //String infoMsg = "Auth subsystem administration Servlet registered";
+ //log(ILogger.LL_INFO, infoMsg);
+ }
+
+ /**
+ * shuts down authentication managers one by one.
+ * <P>
+ */
+ public void shutdown() {
+ for (AuthManagerProxy proxy : mAuthMgrInsts.values()) {
+
+ IAuthManager mgr = proxy.getAuthManager();
+
+ log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_AUTH_INSTANCE_SHUTDOWN", mgr.getName()));
+
+ mgr.shutdown();
+ }
+ mAuthMgrPlugins.clear();
+ mAuthMgrInsts.clear();
+ }
+
+ public Hashtable<String, AuthMgrPlugin> getPlugins() {
+ return mAuthMgrPlugins;
+ }
+
+ public Hashtable<String, AuthManagerProxy> getInstances() {
+ return mAuthMgrInsts;
+ }
+
+ /**
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * gets the named authentication manager
+ *
+ * @param name of the authentication manager
+ * @return the named authentication manager
+ */
+ public IAuthManager getAuthManager(String name) {
+ return get(name);
+ }
+
+ /**
+ * logs an entry in the log file.
+ */
+ public void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHENTICATION,
+ level, msg);
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/authentication/CertUserDBAuthentication.java b/base/server/cmscore/src/com/netscape/cmscore/authentication/CertUserDBAuthentication.java
new file mode 100644
index 000000000..573b736d4
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/authentication/CertUserDBAuthentication.java
@@ -0,0 +1,253 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.authentication;
+
+import java.security.cert.X509Certificate;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authentication.ICertUserDBAuthentication;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.usrgrp.Certificates;
+import com.netscape.certsrv.usrgrp.EUsrGrpException;
+import com.netscape.certsrv.usrgrp.ICertUserLocator;
+import com.netscape.cmscore.usrgrp.ExactMatchCertUserLocator;
+import com.netscape.cmscore.usrgrp.User;
+
+/**
+ * Certificate server agent authentication.
+ * Maps a SSL client authenticate certificate to a user (agent) entry in the
+ * internal database.
+ * <P>
+ *
+ * @author lhsiao
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class CertUserDBAuthentication implements IAuthManager, ICertUserDBAuthentication {
+
+ /* required credentials */
+ protected String[] mRequiredCreds = { CRED_CERT };
+
+ /* config parameters to pass to console (none) */
+ protected static String[] mConfigParams = null;
+
+ private String mName = null;
+ private String mImplName = null;
+ private IConfigStore mConfig = null;
+
+ private ICertUserLocator mCULocator = null;
+ private ILogger mLogger = CMS.getLogger();
+
+ private boolean mRevocationCheckingEnabled = false;
+ private IConfigStore mRevocationChecking = null;
+
+ public CertUserDBAuthentication() {
+ }
+
+ /**
+ * initializes the CertUserDBAuthentication auth manager
+ * <p>
+ * called by AuthSubsystem init() method, when initializing all available authentication managers.
+ *
+ * @param owner - The authentication subsystem that hosts this
+ * auth manager
+ * @param config - The configuration store used by the
+ * authentication subsystem
+ */
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ mName = name;
+ mImplName = implName;
+ mConfig = config;
+
+ if (mConfig != null) {
+ mRevocationChecking = mConfig.getSubStore("revocationChecking");
+ }
+ if (mRevocationChecking != null) {
+ mRevocationCheckingEnabled = mRevocationChecking.getBoolean("enabled", false);
+ if (mRevocationCheckingEnabled) {
+ int size = mRevocationChecking.getInteger("bufferSize", 0);
+ long interval = mRevocationChecking.getInteger("validityInterval", 28800);
+ long unknownStateInterval = mRevocationChecking.getInteger("unknownStateInterval", 1800);
+
+ if (size > 0)
+ CMS.setListOfVerifiedCerts(size, interval, unknownStateInterval);
+ }
+ }
+
+ mCULocator = new ExactMatchCertUserLocator();
+ log(ILogger.LL_INFO, CMS.getLogMessage("INIT_DONE", name));
+ }
+
+ /**
+ * Gets the name of this authentication manager.
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Gets the plugin name of authentication manager.
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ /**
+ * authenticates user(agent) by certificate
+ * <p>
+ * called by other subsystems or their servlets to authenticate users (agents)
+ *
+ * @param authCred - authentication credential that contains
+ * an usrgrp.Certificates of the user (agent)
+ * @return the authentication token that contains the following
+ *
+ * @exception com.netscape.certsrv.base.EAuthsException any
+ * authentication failure or insufficient credentials
+ * @see com.netscape.certsrv.authentication.AuthToken
+ * @see com.netscape.certsrv.usrgrp.Certificates
+ */
+ public IAuthToken authenticate(IAuthCredentials authCred)
+ throws EMissingCredential, EInvalidCredentials, EBaseException {
+ CMS.debug("CertUserDBAuth: started");
+ AuthToken authToken = new AuthToken(this);
+ CMS.debug("CertUserDBAuth: Retrieving client certificate");
+ X509Certificate[] x509Certs =
+ (X509Certificate[]) authCred.get(CRED_CERT);
+
+ if (x509Certs == null) {
+ CMS.debug("CertUserDBAuth: no client certificate found");
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_MISSING_CERT"));
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_CERT));
+ }
+ CMS.debug("CertUserDBAuth: Got client certificate");
+
+ if (mRevocationCheckingEnabled) {
+ X509CertImpl cert0 = (X509CertImpl) x509Certs[0];
+ if (cert0 == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_NO_CERT"));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_NO_CERT"));
+ }
+ if (CMS.isRevoked(x509Certs)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_REVOKED_CERT"));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ }
+
+ CMS.debug("Authentication: client certificate found");
+
+ // map cert to user
+ User user = null;
+ Certificates certs = new Certificates(x509Certs);
+
+ try {
+ user = (User) mCULocator.locateUser(certs);
+ } catch (EUsrGrpException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_AGENT_AUTH_FAILED", x509Certs[0].getSerialNumber()
+ .toString(16), x509Certs[0].getSubjectDN().toString(), e.toString()));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ } catch (netscape.ldap.LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_CANNOT_AGENT_AUTH", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+
+ // any unexpected error occurs like internal db down,
+ // UGSubsystem only returns null for user.
+ if (user == null) {
+ CMS.debug("Authentication: cannot map certificate to user");
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_AGENT_USER_NOT_FOUND"));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ CMS.debug("Authentication: mapped certificate to user");
+
+ authToken.set(TOKEN_USERDN, user.getUserDN());
+ authToken.set(TOKEN_USER_DN, user.getUserDN());
+ authToken.set(TOKEN_USERID, user.getUserID());
+ authToken.set(TOKEN_UID, user.getUserID());
+ authToken.set(CRED_CERT, certs);
+
+ log(ILogger.LL_INFO, CMS.getLogMessage("CMS_AUTH_AUTHENTICATED", user.getUserID()));
+ CMS.debug("authenticated " + user.getUserDN());
+
+ return authToken;
+ }
+
+ /**
+ * get the list of authentication credential attribute names
+ * required by this authentication manager. Generally used by
+ * the servlets that handle agent operations to authenticate its
+ * users. It calls this method to know which are the
+ * required credentials from the user (e.g. Javascript form data)
+ *
+ * @return attribute names in Vector
+ */
+ public String[] getRequiredCreds() {
+ return (mRequiredCreds);
+ }
+
+ /**
+ * get the list of configuration parameter names
+ * required by this authentication manager. Generally used by
+ * the Certificate Server Console to display the table for
+ * configuration purposes. CertUserDBAuthentication is currently not
+ * exposed in this case, so this method is not to be used.
+ *
+ * @return configuration parameter names in Hashtable of Vectors
+ * where each hashtable entry's key is the substore name, value is a
+ * Vector of parameter names. If no substore, the parameter name
+ * is the Hashtable key itself, with value same as key.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+
+ /**
+ * prepare this authentication manager for shutdown.
+ */
+ public void shutdown() {
+ }
+
+ /**
+ * gets the configuretion substore used by this authentication
+ * manager
+ *
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHENTICATION,
+ level, msg);
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/authentication/ChallengePhraseAuthentication.java b/base/server/cmscore/src/com/netscape/cmscore/authentication/ChallengePhraseAuthentication.java
new file mode 100644
index 000000000..f5bde0b54
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/authentication/ChallengePhraseAuthentication.java
@@ -0,0 +1,406 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.authentication;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EAuthException;
+import com.netscape.certsrv.authentication.EAuthUserError;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+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.IConfigStore;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cmscore.base.SubsystemRegistry;
+import com.netscape.cmscore.dbs.CertRecord;
+import com.netscape.cmscore.util.Debug;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Challenge phrase based authentication.
+ * Maps a certificate to the request in the
+ * internal database and further compares the challenge phrase with
+ * that from the EE input.
+ * <P>
+ *
+ * @author cfu chrisho
+ * @version $Revision$, $Date$
+ */
+public class ChallengePhraseAuthentication implements IAuthManager {
+
+ /* result auth token attributes */
+ public static final String TOKEN_CERT_SERIAL = "certSerialToRevoke";
+
+ /* required credentials */
+ public static final String CRED_CERT_SERIAL = IAuthManager.CRED_CERT_SERIAL_TO_REVOKE;
+ public static final String CRED_CHALLENGE = "challengePhrase";
+ protected String[] mRequiredCreds = { CRED_CERT_SERIAL, CRED_CHALLENGE };
+
+ /* config parameters to pass to console (none) */
+ protected static String[] mConfigParams = null;
+ protected ICertificateAuthority mCA = null;
+ protected ICertificateRepository mCertDB = null;
+
+ private String mName = null;
+ private String mImplName = null;
+ private IConfigStore mConfig = null;
+
+ private ILogger mLogger = CMS.getLogger();
+ private MessageDigest mSHADigest = null;
+
+ // request attributes hacks
+ public static final String CHALLENGE_PHRASE = CRED_CHALLENGE;
+ public static final String SUBJECTNAME = "subjectName";
+ public static final String SERIALNUMBER = "serialNumber";
+ public static final String SERIALNOARRAY = "serialNoArray";
+
+ public ChallengePhraseAuthentication() {
+ }
+
+ /**
+ * initializes the ChallengePhraseAuthentication auth manager
+ * <p>
+ * called by AuthSubsystem init() method, when initializing all available authentication managers.
+ *
+ * @param name The name of this authentication manager instance.
+ * @param implName The name of the authentication manager plugin.
+ * @param config The configuration store for this authentication manager.
+ */
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ mName = name;
+ mImplName = implName;
+ mConfig = config;
+
+ try {
+ mSHADigest = MessageDigest.getInstance("SHA1");
+ } catch (NoSuchAlgorithmException e) {
+ throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR", e.getMessage()));
+ }
+
+ log(ILogger.LL_INFO, CMS.getLogMessage("INIT_DONE", name));
+ }
+
+ /**
+ * Gets the name of this authentication manager.
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Gets the plugin name of authentication manager.
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ /**
+ * authenticates revocation of a certification by a challenge phrase
+ * <p>
+ * called by other subsystems or their servlets to authenticate a revocation request
+ *
+ * @param authCred - authentication credential that contains
+ * a Certificate to revoke
+ * @return the authentication token that contains the request id
+ *
+ * @exception EMissingCredential If a required credential for this
+ * authentication manager is missing.
+ * @exception EInvalidCredentials If credentials cannot be authenticated.
+ * @exception EBaseException If an internal error occurred.
+ * @see com.netscape.certsrv.authentication.AuthToken
+ */
+ public IAuthToken authenticate(IAuthCredentials authCred)
+ throws EMissingCredential, EInvalidCredentials, EBaseException {
+ mCA = (ICertificateAuthority)
+ SubsystemRegistry.getInstance().get("ca");
+
+ if (mCA != null) {
+ mCertDB = mCA.getCertificateRepository();
+ }
+
+ AuthToken authToken = new AuthToken(this);
+
+ /*
+ X509Certificate[] x509Certs =
+ (X509Certificate[]) authCred.get(CRED_CERT);
+ if (x509Certs == null) {
+ log(ILogger.LL_FAILURE,
+ " missing cert credential.");
+ throw new EMissingCredential(CRED_CERT_SERIAL);
+ }
+ */
+
+ String serialNumString = (String) authCred.get(CRED_CERT_SERIAL);
+
+ BigInteger serialNum = null;
+
+ if (serialNumString == null || serialNumString.equals(""))
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_CERT_SERIAL));
+ else {
+ //serialNumString = getDecimalStr(serialNumString);
+ try {
+ serialNumString = serialNumString.trim();
+ if (serialNumString.startsWith("0x") || serialNumString.startsWith("0X")) {
+ serialNum = new
+ BigInteger(serialNumString.substring(2), 16);
+ } else {
+ serialNum = new
+ BigInteger(serialNumString);
+ }
+
+ } catch (NumberFormatException e) {
+ throw new EAuthUserError(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_ATTRIBUTE_VALUE",
+ "Invalid serial number."));
+ }
+ }
+
+ String challenge = (String) authCred.get(CRED_CHALLENGE);
+
+ if (challenge == null) {
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_CHALLENGE));
+ }
+ if (challenge.equals("")) {
+ // empty challenge not allowed
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_REVO_ATTEMPT", serialNum.toString()));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ /* maybe later
+ if (mCertDB.isCertificateRevoked(cert) != null) {
+ log(ILogger.LL_FAILURE,
+ "Certificate has already been revoked.");
+ // throw something else...cfu
+ throw new EInvalidCredentials();
+ }
+ */
+
+ BigInteger[] bigIntArray = null;
+
+ // check challenge phrase against request
+ /*
+ * map cert to a request: a cert serial number maps to a
+ * cert record in the internal db, from the cert record,
+ * where we'll find the challenge phrase
+ */
+ if (mCertDB != null) { /* is CA */
+ CertRecord record = null;
+
+ try {
+ record = (CertRecord) mCertDB.readCertificateRecord(serialNum);
+ } catch (EBaseException ee) {
+ if (Debug.ON) {
+ Debug.trace(ee.toString());
+ }
+ }
+ if (record != null) {
+ String status = record.getStatus();
+
+ if (!status.equals("REVOKED")) {
+ boolean samepwd = compareChallengePassword(record, challenge);
+
+ if (samepwd) {
+ bigIntArray = new BigInteger[1];
+ bigIntArray[0] = record.getSerialNumber();
+ } else
+ throw new EAuthUserError(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_ATTRIBUTE_VALUE",
+ "Invalid password."));
+
+ } else {
+ bigIntArray = new BigInteger[0];
+ }
+ } else {
+ bigIntArray = new BigInteger[0];
+ }
+ } else {
+
+ /*
+ * ra, build a request and send through the connection for
+ * authentication
+ */
+ IRequestQueue queue = getReqQueue();
+
+ if (queue != null) {
+ IRequest checkChallengeReq = null;
+
+ checkChallengeReq =
+ queue.newRequest(IRequest.REVOCATION_CHECK_CHALLENGE_REQUEST);
+ checkChallengeReq.setExtData(CHALLENGE_PHRASE, challenge);
+ // pass just serial number instead of whole cert
+ if (serialNum != null)
+ checkChallengeReq.setExtData(SERIALNUMBER, serialNum);
+ queue.processRequest(checkChallengeReq);
+ // check request status...
+ RequestStatus status = checkChallengeReq.getRequestStatus();
+
+ if (status == RequestStatus.COMPLETE) {
+ bigIntArray = checkChallengeReq.getExtDataInBigIntegerArray("serialNoArray");
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_INCOMPLETE_REQUEST"));
+ }
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_FAILED_GET_QUEUE"));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_REVOCATION_CHALLENGE_QUEUE_FAILED"));
+ }
+ } // else, ra
+ if (bigIntArray != null && bigIntArray.length > 0) {
+ if (Debug.ON) {
+ Debug.trace("challenge authentication serialno array not null");
+ for (int i = 0; i < bigIntArray.length; i++)
+ Debug.trace("challenge auth serialno " + bigIntArray[i]);
+ }
+ }
+ if (Debug.ON) {
+ Debug.trace("challenge authentication set " + TOKEN_CERT_SERIAL);
+ }
+ authToken.set(TOKEN_CERT_SERIAL, bigIntArray);
+
+ return authToken;
+ }
+
+ private boolean compareChallengePassword(CertRecord record, String pwd)
+ throws EBaseException {
+ MetaInfo metaInfo = (MetaInfo) record.get(CertRecord.ATTR_META_INFO);
+
+ if (metaInfo == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", "metaInfo"));
+ }
+
+ if (pwd == null) {
+ if (Debug.ON) {
+ Debug.trace("challenge pwd is null");
+ }
+ return false;
+ }
+ String hashpwd = hashPassword(pwd);
+
+ // got metaInfo
+ String challengeString =
+ (String) metaInfo.get(CertRecord.META_CHALLENGE_PHRASE);
+
+ if (challengeString == null) {
+ if (Debug.ON) {
+ Debug.trace("challengeString null");
+ }
+ return false;
+ }
+
+ if (!challengeString.equals(hashpwd)) {
+ return false;
+
+ /*
+ log(ILogger.LL_FAILURE,
+ "Incorrect challenge phrase password used for revocation");
+ throw new EInvalidCredentials();
+ */
+ } else
+ return true;
+ }
+
+ /**
+ * get the list of authentication credential attribute names
+ * required by this authentication manager. Generally used by
+ * the servlets that handle agent operations to authenticate its
+ * users. It calls this method to know which are the
+ * required credentials from the user (e.g. Javascript form data)
+ *
+ * @return attribute names in Vector
+ */
+ public String[] getRequiredCreds() {
+ return (mRequiredCreds);
+ }
+
+ /**
+ * get the list of configuration parameter names
+ * required by this authentication manager. Generally used by
+ * the Certificate Server Console to display the table for
+ * configuration purposes. ChallengePhraseAuthentication is currently not
+ * exposed in this case, so this method is not to be used.
+ *
+ * @return configuration parameter names in Hashtable of Vectors
+ * where each hashtable entry's key is the substore name, value is a
+ * Vector of parameter names. If no substore, the parameter name
+ * is the Hashtable key itself, with value same as key.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+
+ /**
+ * prepare this authentication manager for shutdown.
+ */
+ public void shutdown() {
+ }
+
+ /**
+ * gets the configuretion substore used by this authentication
+ * manager
+ *
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHENTICATION,
+ level, msg);
+ }
+
+ private IRequestQueue getReqQueue() {
+ IRequestQueue queue = null;
+
+ try {
+ IRegistrationAuthority ra = (IRegistrationAuthority)
+ SubsystemRegistry.getInstance().get("ra");
+
+ if (ra != null) {
+ queue = ra.getRequestQueue();
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ " cannot get access to the request queue.");
+ }
+
+ return queue;
+ }
+
+ private String hashPassword(String pwd) {
+ String salt = "lala123";
+ byte[] pwdDigest = mSHADigest.digest((salt + pwd).getBytes());
+ String b64E = Utils.base64encode(pwdDigest);
+
+ return "{SHA}" + b64E;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/authentication/NullAuthentication.java b/base/server/cmscore/src/com/netscape/cmscore/authentication/NullAuthentication.java
new file mode 100644
index 000000000..a7a1461cf
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/authentication/NullAuthentication.java
@@ -0,0 +1,161 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.authentication;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+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.IConfigStore;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * This authentication does nothing but just returns an empty authToken.
+ * <P>
+ *
+ * @author chrisho
+ * @version $Revision$, $Date$
+ */
+public class NullAuthentication implements IAuthManager {
+
+ /* configuration params to pass to console (none) */
+ protected static String[] mConfigParams = null;
+
+ protected static String[] mRequiredCred = {};
+ private String mName = null;
+ private String mImplName = null;
+ private IConfigStore mConfig = null;
+ private ILogger mLogger = CMS.getLogger();
+
+ public NullAuthentication() {
+ }
+
+ /**
+ * initializes the NullAuthentication auth manager
+ * <p>
+ * called by AuthSubsystem init() method, when initializing all available authentication managers.
+ *
+ * @param name - Name assigned to this authentication manager instance.
+ * @param implName - Name of the authentication plugin.
+ * @param config - The configuration store used by the
+ * authentication subsystem.
+ */
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ mName = name;
+ mImplName = implName;
+ mConfig = config;
+
+ log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_AUTH_INIT_AUTH", mName));
+ }
+
+ /**
+ * authenticates nothing
+ * <p>
+ * called by other subsystems or their servlets to authenticate administrators
+ *
+ * @param authCred Authentication credentials.
+ * "uid" and "pwd" are required.
+ * @return the authentication token (authToken) that contains the following
+ * userdn = [userdn, in case of success]<br>
+ * authMgrName = [authMgrName]<br>
+ * @exception com.netscape.certsrv.base.MissingCredential If either
+ * "uid" or "pwd" is missing from the given credentials.
+ * @exception com.netscape.certsrv.base.InvalidCredentials If the
+ * the credentials failed to authenticate.
+ * @exception com.netscape.certsrv.base.EBaseException If an internal
+ * error occurred.
+ */
+ public IAuthToken authenticate(IAuthCredentials authCred)
+ throws EMissingCredential, EInvalidCredentials, EBaseException {
+ AuthToken authToken = new AuthToken(this);
+
+ authToken.set("authType", "NOAUTH");
+
+ return authToken;
+ }
+
+ /**
+ * gets the name of this authentication manager instance
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * gets the name of the authentication manager plugin
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ /**
+ * get the list of authentication credential attribute names
+ * required by this authentication manager. Generally used by
+ * servlets that use this authentication manager, to retrieve
+ * required credentials from the user (e.g. Javascript form data)
+ *
+ * @return attribute names in Vector
+ */
+ public String[] getRequiredCreds() {
+ return (mRequiredCred);
+ }
+
+ /**
+ * Get the list of configuration parameter names
+ * required by this authentication manager. In this case, an empty list.
+ *
+ * @return String array of configuration parameters.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+
+ /**
+ * disconnects the member connection
+ */
+ public void shutdown() {
+ }
+
+ /**
+ * gets the configuration substore used by this authentication
+ * manager
+ *
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Log a message.
+ *
+ * @param level The logging level.
+ * @param msg The message to log.
+ */
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHENTICATION,
+ level, msg);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/authentication/PasswdUserDBAuthentication.java b/base/server/cmscore/src/com/netscape/cmscore/authentication/PasswdUserDBAuthentication.java
new file mode 100644
index 000000000..2905f3c75
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/authentication/PasswdUserDBAuthentication.java
@@ -0,0 +1,272 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.authentication;
+
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authentication.IPasswdUserDBAuthentication;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.cmscore.dbs.DBSubsystem;
+import com.netscape.cmscore.ldapconn.LdapAnonConnFactory;
+import com.netscape.cmscore.ldapconn.LdapBoundConnFactory;
+import com.netscape.cmscore.ldapconn.LdapConnInfo;
+import com.netscape.cmscore.usrgrp.UGSubsystem;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * Certificate Server admin authentication.
+ * Used to authenticate administrators in the Certificate Server Console.
+ * Authentications by checking the uid and password against the
+ * database.
+ * <P>
+ *
+ * @author lhsiao, cfu
+ * @version $Revision$, $Date$
+ */
+public class PasswdUserDBAuthentication implements IAuthManager, IPasswdUserDBAuthentication {
+
+ /* required credentials. uid, pwd are strings */
+ protected static String[] mRequiredCred = { CRED_UID, CRED_PWD };
+
+ /* configuration params to pass to console (none) */
+ protected static String[] mConfigParams = null;
+
+ private String mName = null;
+ private String mImplName = null;
+ private IConfigStore mConfig;
+ private String mBaseDN = null;
+ private LdapBoundConnFactory mConnFactory = null;
+ private LdapAnonConnFactory mAnonConnFactory = null;
+ private ILogger mLogger = CMS.getLogger();
+
+ public PasswdUserDBAuthentication() {
+ }
+
+ /**
+ * initializes the PasswdUserDBAuthentication auth manager
+ * <p>
+ * called by AuthSubsystem init() method, when initializing all available authentication managers.
+ *
+ * @param name - Name assigned to this authentication manager instance.
+ * @param implName - Name of the authentication plugin.
+ * @param config - The configuration store used by the
+ * authentication subsystem.
+ */
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ mName = name;
+ mImplName = implName;
+ mConfig = config;
+
+ /* internal database directory used */
+ DBSubsystem dbs = (DBSubsystem) DBSubsystem.getInstance();
+ LdapConnInfo ldapinfo = dbs.getLdapConnInfo();
+ if (ldapinfo == null && CMS.isPreOpMode())
+ return;
+
+ mBaseDN = dbs.getBaseDN();
+ mConnFactory = new LdapBoundConnFactory(3, 20, ldapinfo, dbs.getLdapAuthInfo());
+ mAnonConnFactory = new LdapAnonConnFactory(3, 20, ldapinfo);
+
+ log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_AUTH_INIT_AUTH", mName));
+ }
+
+ /**
+ * authenticates administratrators by LDAP uid/pwd
+ * <p>
+ * called by other subsystems or their servlets to authenticate administrators
+ *
+ * @param authCred Authentication credentials.
+ * "uid" and "pwd" are required.
+ * @return the authentication token (authToken) that contains the following
+ * userdn = [userdn, in case of success]<br>
+ * authMgrName = [authMgrName]<br>
+ * @exception com.netscape.certsrv.base.MissingCredential If either
+ * "uid" or "pwd" is missing from the given credentials.
+ * @exception com.netscape.certsrv.base.InvalidCredentials If the
+ * the credentials failed to authenticate.
+ * @exception com.netscape.certsrv.base.EBaseException If an internal
+ * error occurred.
+ */
+ public IAuthToken authenticate(IAuthCredentials authCred)
+ throws EMissingCredential, EInvalidCredentials, EBaseException {
+ AuthToken authToken = new AuthToken(this);
+
+ // make sure the required credentials are provided
+ String uid = (String) authCred.get(CRED_UID);
+ CMS.debug("Authentication: UID=" + uid);
+ if (uid == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_MISSING_UID"));
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_UID));
+ }
+ String pwd = (String) authCred.get(CRED_PWD);
+
+ if (pwd == null) {
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMSCORE_AUTH_ADMIN_NULL_PW", uid));
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_PWD));
+ }
+ // don't allow anonymous binding
+ if (pwd == "") {
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMSCORE_AUTH_ADMIN_EMPTY_PW", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ String userdn = null;
+ LDAPConnection conn = null;
+ LDAPConnection anonConn = null;
+
+ try {
+ conn = mConnFactory.getConn();
+ // do anonymous search for the user's dn.
+ LDAPSearchResults res = conn.search(mBaseDN,
+ LDAPv2.SCOPE_SUB, "(uid=" + uid + ")", null, false);
+
+ if (res.hasMoreElements()) {
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+
+ userdn = entry.getDN();
+ }
+ if (userdn == null) {
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMSCORE_AUTH_ADMIN_NOT_FOUND", uid));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ anonConn = mAnonConnFactory.getConn();
+ anonConn.authenticate(userdn, pwd);
+ } catch (LDAPException e) {
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMSCORE_AUTH_AUTH_FAILED", uid, e.toString()));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ } finally {
+ if (conn != null)
+ mConnFactory.returnConn(conn);
+ if (anonConn != null)
+ mAnonConnFactory.returnConn(anonConn);
+ }
+
+ UGSubsystem ug = UGSubsystem.getInstance();
+
+ authToken.set(TOKEN_USERDN, userdn);
+ authToken.set(CRED_UID, uid); // return original uid for info
+
+ IUser user = null;
+
+ try {
+ user = ug.getUser(uid);
+ } catch (EBaseException e) {
+ if (Debug.ON)
+ e.printStackTrace();
+ // not a user in our user/group database.
+ log(ILogger.LL_SECURITY, CMS.getLogMessage("CMSCORE_AUTH_UID_NOT_FOUND", uid, e.toString()));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL") + " " + e.getMessage());
+ }
+ if (user == null) {
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR",
+ "Failure in User Group subsystem."));
+ }
+ authToken.set(TOKEN_USERDN, user.getUserDN());
+ authToken.set(TOKEN_USERID, user.getUserID());
+ log(ILogger.LL_INFO, CMS.getLogMessage("CMS_AUTH_AUTHENTICATED", uid));
+
+ return authToken;
+ }
+
+ /**
+ * gets the name of this authentication manager instance
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * gets the name of the authentication manager plugin
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+
+ /**
+ * get the list of authentication credential attribute names
+ * required by this authentication manager. Generally used by
+ * servlets that use this authentication manager, to retrieve
+ * required credentials from the user (e.g. Javascript form data)
+ *
+ * @return attribute names in Vector
+ */
+ public String[] getRequiredCreds() {
+ return (mRequiredCred);
+ }
+
+ /**
+ * Get the list of configuration parameter names
+ * required by this authentication manager. In this case, an empty list.
+ *
+ * @return String array of configuration parameters.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+
+ /**
+ * disconnects the member connection
+ */
+ public void shutdown() {
+ try {
+ // disconnect all outstanding connections in the factory
+ if (mConnFactory != null) mConnFactory.reset();
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ }
+ }
+
+ /**
+ * gets the configuretion substore used by this authentication
+ * manager
+ *
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Log a message.
+ *
+ * @param level The logging level.
+ * @param msg The message to log.
+ */
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHENTICATION,
+ level, msg);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/authentication/SSLClientCertAuthentication.java b/base/server/cmscore/src/com/netscape/cmscore/authentication/SSLClientCertAuthentication.java
new file mode 100644
index 000000000..235362395
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/authentication/SSLClientCertAuthentication.java
@@ -0,0 +1,289 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.authentication;
+
+// ldap java sdk
+
+// cert server imports.
+import java.math.BigInteger;
+import java.security.Principal;
+import java.security.cert.X509Certificate;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EAuthUserError;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+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.IConfigStore;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ra.IRegistrationAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * SSL client based authentication.
+ * <P>
+ *
+ * @author chrisho
+ * @version $Revision$, $Date$
+ */
+public class SSLClientCertAuthentication implements IAuthManager {
+
+ /* required credential to authenticate, client certificate */
+ public static final String CRED_CERT = IAuthManager.CRED_SSL_CLIENT_CERT;
+ public static final String SERIALNUMBER = "serialNumber";
+ public static final String ISSUERDN = "issuerDN";
+ protected static String[] mRequiredCreds = { CRED_CERT };
+
+ private ICertificateAuthority mCA = null;
+ private ICertificateRepository mCertDB = null;
+ private ILogger mLogger = CMS.getLogger();
+ private String mName = null;
+ private String mImplName = null;
+ private IConfigStore mConfig = null;
+
+ /* Holds configuration parameters accepted by this implementation.
+ * This list is passed to the configuration console so configuration
+ * for instances of this implementation can be configured through the
+ * console.
+ */
+ protected static String[] mConfigParams =
+ new String[] {};
+
+ /**
+ * Default constructor, initialization must follow.
+ */
+ public SSLClientCertAuthentication() {
+ super();
+ }
+
+ public void init(String name, String implName, IConfigStore config)
+ throws EBaseException {
+ mName = name;
+ mImplName = implName;
+ mConfig = config;
+
+ log(ILogger.LL_INFO, CMS.getLogMessage("INIT_DONE", name));
+ }
+
+ public IAuthToken authenticate(IAuthCredentials authCred)
+ throws EMissingCredential, EInvalidCredentials, EBaseException {
+
+ AuthToken authToken = new AuthToken(this);
+
+ CMS.debug("SSLCertAuth: Retrieving client certificates");
+ X509Certificate[] x509Certs =
+ (X509Certificate[]) authCred.get(CRED_CERT);
+
+ if (x509Certs == null) {
+ CMS.debug("SSLCertAuth: No client certificate found");
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_AUTH_MISSING_CERT"));
+ throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_CERT));
+ }
+ CMS.debug("SSLCertAuth: Got client certificate");
+
+ mCA = (ICertificateAuthority) CMS.getSubsystem("ca");
+
+ if (mCA != null) {
+ mCertDB = mCA.getCertificateRepository();
+ }
+
+ X509CertImpl clientCert = (X509CertImpl) x509Certs[0];
+
+ BigInteger serialNum = null;
+
+ try {
+ serialNum = clientCert.getSerialNumber();
+ //serialNum = new BigInteger(s.substring(2), 16);
+ } catch (NumberFormatException e) {
+ throw new EAuthUserError(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_ATTRIBUTE_VALUE",
+ "Invalid serial number."));
+ }
+
+ String clientCertIssuerDN = clientCert.getIssuerDN().toString();
+
+ if (mCertDB != null) { /* is CA */
+ ICertRecord record = null;
+
+ try {
+ record = mCertDB.readCertificateRecord(serialNum);
+ } catch (EBaseException ee) {
+ if (Debug.ON) {
+ Debug.trace(ee.toString());
+ }
+ }
+ if (record != null) {
+ String status = record.getStatus();
+
+ if (status.equals("VALID")) {
+
+ X509CertImpl cacert = mCA.getCACert();
+ Principal p = cacert.getSubjectDN();
+
+ if (!p.toString().equals(clientCertIssuerDN)) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ISSUER_NAME"));
+ }
+ } else {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_CERT_STATUS", status));
+ }
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+ }
+ } else {
+
+ /*
+ * ra, build a request and send through the connection for
+ * authentication
+ */
+ IRequestQueue queue = getReqQueue();
+
+ if (queue != null) {
+ IRequest getCertStatusReq = null;
+
+ getCertStatusReq =
+ queue.newRequest(IRequest.GETCERT_STATUS_REQUEST);
+ // pass just serial number instead of whole cert
+ if (serialNum != null) {
+ getCertStatusReq.setExtData(SERIALNUMBER, serialNum);
+ getCertStatusReq.setExtData(ISSUERDN, clientCertIssuerDN);
+ }
+ queue.processRequest(getCertStatusReq);
+ // check request status...
+ RequestStatus status = getCertStatusReq.getRequestStatus();
+
+ if (status == RequestStatus.COMPLETE) {
+ String certStatus =
+ getCertStatusReq.getExtDataInString(IRequest.CERT_STATUS);
+
+ if (certStatus == null) {
+ String[] params = { "null status" };
+
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_CERT_STATUS", params));
+ } else if (certStatus.equals("INVALIDCERTROOT")) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ISSUER_NAME"));
+ } else if (!certStatus.equals("VALID")) {
+ String[] params = { status.toString() };
+
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_CERT_STATUS", params));
+ }
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_AUTH_INCOMPLETE_REQUEST"));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_REQUEST_IN_BAD_STATE"));
+ }
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_AUTH_FAILED_GET_QUEUE"));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_GET_QUEUE_FAILED"));
+ }
+ } // else, ra
+
+ authToken.set(AuthToken.TOKEN_CERT, clientCert);
+
+ return authToken;
+ }
+
+ /**
+ * prepare this authentication manager for shutdown.
+ */
+ public void shutdown() {
+ }
+
+ /**
+ * Returns a list of configuration parameter names.
+ * The list is passed to the configuration console so instances of
+ * this implementation can be configured through the console.
+ *
+ * @return String array of configuration parameter names.
+ */
+ public String[] getConfigParams() {
+ return (mConfigParams);
+ }
+
+ /**
+ * Returns array of required credentials for this authentication manager.
+ *
+ * @return Array of required credentials.
+ */
+ public String[] getRequiredCreds() {
+ return mRequiredCreds;
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHENTICATION,
+ level, msg);
+ }
+
+ private IRequestQueue getReqQueue() {
+ IRequestQueue queue = null;
+
+ try {
+ IRegistrationAuthority ra =
+ (IRegistrationAuthority) CMS.getSubsystem("ra");
+
+ if (ra != null) {
+ queue = ra.getRequestQueue();
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE,
+ " cannot get access to the request queue.");
+ }
+
+ return queue;
+ }
+
+ /**
+ * Gets the configuration substore used by this authentication manager
+ *
+ * @return configuration store
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * gets the name of this authentication manager instance
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * gets the plugin name of this authentication manager.
+ */
+ public String getImplName() {
+ return mImplName;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/authentication/VerifiedCert.java b/base/server/cmscore/src/com/netscape/cmscore/authentication/VerifiedCert.java
new file mode 100644
index 000000000..0ada86e75
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/authentication/VerifiedCert.java
@@ -0,0 +1,90 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.authentication;
+
+import java.math.BigInteger;
+import java.util.Date;
+
+import com.netscape.certsrv.apps.CMS;
+
+/**
+ * class storing verified certificate.
+ *
+ * @version $Revision$, $Date$
+ */
+
+public class VerifiedCert {
+ public static final int CHECKED = 4;
+ public static final int EXPIRED = 3;
+ public static final int NOT_REVOKED = 2;
+ public static final int REVOKED = 1;
+ public static final int UNKNOWN = 0;
+
+ private int mStatus = UNKNOWN;
+ private Date mCreated = null;
+ private BigInteger mSerialNumber = null;
+ private byte[] mCertEncoded = null;
+
+ /**
+ * Constructs verified certiificate record
+ */
+
+ public VerifiedCert(BigInteger serialNumber, byte[] certEncoded,
+ int status) {
+ mStatus = status;
+ mSerialNumber = serialNumber;
+ mCertEncoded = certEncoded;
+ mCreated = CMS.getCurrentDate();
+ }
+
+ public int check(BigInteger serialNumber, byte[] certEncoded,
+ long interval, long unknownStateInterval) {
+ int status = UNKNOWN;
+
+ if (mSerialNumber.equals(serialNumber)) {
+ if (mCertEncoded != null) {
+ if (certEncoded != null &&
+ mCertEncoded.length == certEncoded.length) {
+ int i;
+
+ for (i = 0; i < mCertEncoded.length; i++) {
+ if (mCertEncoded[i] != certEncoded[i])
+ break;
+ }
+ if (i >= mCertEncoded.length) {
+ Date expires = new Date(mCreated.getTime() + (interval * 1000));
+ Date now = CMS.getCurrentDate();
+
+ if (now.after(expires))
+ mStatus = EXPIRED;
+ status = mStatus;
+ }
+ }
+ } else if (unknownStateInterval > 0) {
+ Date expires = new Date(mCreated.getTime() + (unknownStateInterval * 1000));
+ Date now = CMS.getCurrentDate();
+
+ if (now.after(expires))
+ mStatus = EXPIRED;
+ status = mStatus; // CHECKED
+ }
+ }
+
+ return status;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/authentication/VerifiedCerts.java b/base/server/cmscore/src/com/netscape/cmscore/authentication/VerifiedCerts.java
new file mode 100644
index 000000000..ccefe5b21
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/authentication/VerifiedCerts.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.authentication;
+
+import java.math.BigInteger;
+
+import netscape.security.x509.X509CertImpl;
+
+/**
+ * class storing verified certificates.
+ *
+ * @version $Revision$, $Date$
+ */
+
+public class VerifiedCerts {
+
+ /* the value type of the dn component */
+ private int mFirst = 0;
+ private int mLast = 0;
+ private int mNext = 0;
+ private VerifiedCert[] mVCerts = null;
+ private long mInterval = 0;
+ private long mUnknownStateInterval = 0;
+
+ /**
+ * Constructs verified certiificates list
+ */
+
+ public VerifiedCerts(int size, long interval) {
+ mVCerts = new VerifiedCert[size];
+ mInterval = interval;
+ mUnknownStateInterval = interval;
+ }
+
+ public VerifiedCerts(int size, long interval, long unknownStateInterval) {
+ mVCerts = new VerifiedCert[size];
+ mInterval = interval;
+ mUnknownStateInterval = unknownStateInterval;
+ }
+
+ public synchronized void update(X509CertImpl cert, int status) {
+ if (cert != null) {
+ byte[] certEncoded = null;
+
+ try {
+ certEncoded = cert.getEncoded();
+ } catch (Exception e) {
+ }
+ if ((certEncoded != null ||
+ (status == VerifiedCert.CHECKED && mUnknownStateInterval > 0))
+ && mInterval > 0) {
+ update(cert.getSerialNumber(), certEncoded, status);
+ }
+ }
+ }
+
+ public synchronized void update(BigInteger serialNumber, byte[] certEncoded, int status) {
+ if ((status == VerifiedCert.NOT_REVOKED ||
+ status == VerifiedCert.REVOKED ||
+ (status == VerifiedCert.CHECKED && mUnknownStateInterval > 0))
+ && mInterval > 0) {
+ if (mLast == mNext && mFirst == mNext) { // empty
+ mVCerts[mNext] = new VerifiedCert(serialNumber, certEncoded, status);
+ mNext = next(mNext);
+ } else if (mFirst == mNext) { // full
+ mFirst = next(mFirst);
+ mVCerts[mNext] = new VerifiedCert(serialNumber, certEncoded, status);
+ mLast = mNext;
+ mNext = next(mNext);
+ } else {
+ mVCerts[mNext] = new VerifiedCert(serialNumber, certEncoded, status);
+ mLast = mNext;
+ mNext = next(mNext);
+ }
+ }
+ }
+
+ public synchronized int check(X509CertImpl cert) {
+ int status = VerifiedCert.UNKNOWN;
+
+ if (mLast != mNext && mInterval > 0) { // if not empty and
+ if (cert != null) {
+ byte[] certEncoded = null;
+
+ try {
+ certEncoded = cert.getEncoded();
+ } catch (Exception e) {
+ }
+ if (certEncoded != null) {
+ status = check(cert.getSerialNumber(), certEncoded);
+ }
+ }
+ }
+
+ return status;
+ }
+
+ public synchronized int check(BigInteger serialNumber, byte[] certEncoded) {
+ int status = VerifiedCert.UNKNOWN;
+ int i = mLast;
+
+ if (mVCerts != null && mLast != mNext && mInterval > 0) { // if not empty and
+ while (status == VerifiedCert.UNKNOWN) {
+ if (mVCerts[i] == null)
+ return status;
+ status = mVCerts[i].check(serialNumber, certEncoded,
+ mInterval, mUnknownStateInterval);
+ if (status == VerifiedCert.EXPIRED) {
+ if (mFirst == mLast)
+ mNext = mLast;
+ else
+ mFirst = next(i);
+ break;
+ } else if (mFirst == i) {
+ break;
+ } else {
+ i = previous(i);
+ }
+ }
+ if (status == VerifiedCert.UNKNOWN)
+ status = mVCerts[i].check(serialNumber, certEncoded,
+ mInterval, mUnknownStateInterval);
+ }
+
+ return status;
+ }
+
+ private int next(int i) {
+ i++;
+ if (i >= mVCerts.length)
+ i = 0;
+
+ return i;
+ }
+
+ private int previous(int i) {
+ if (i <= 0)
+ i = mVCerts.length;
+ i--;
+
+ return i;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/authorization/AuthzSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/authorization/AuthzSubsystem.java
new file mode 100644
index 000000000..a6019730a
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/authorization/AuthzSubsystem.java
@@ -0,0 +1,468 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.authorization;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authorization.AuthzManagerProxy;
+import com.netscape.certsrv.authorization.AuthzMgrPlugin;
+import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzException;
+import com.netscape.certsrv.authorization.EAuthzMgrNotFound;
+import com.netscape.certsrv.authorization.EAuthzMgrPluginNotFound;
+import com.netscape.certsrv.authorization.IAuthzManager;
+import com.netscape.certsrv.authorization.IAuthzSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * Default authorization subsystem
+ * <P>
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class AuthzSubsystem implements IAuthzSubsystem {
+ public static final String ID = "authz";
+
+ public Hashtable<String, AuthzMgrPlugin> mAuthzMgrPlugins = new Hashtable<String, AuthzMgrPlugin>();
+ public Hashtable<String, AuthzManagerProxy> mAuthzMgrInsts = new Hashtable<String, AuthzManagerProxy>();
+ private String mId = "authz";
+ private IConfigStore mConfig = null;
+
+ private ILogger mLogger = null;
+
+ // singleton enforcement
+
+ private static AuthzSubsystem mInstance = new AuthzSubsystem();
+
+ public static synchronized AuthzSubsystem getInstance() {
+ return mInstance;
+ }
+
+ // end singleton enforcement.
+
+ private AuthzSubsystem() {
+ }
+
+ /**
+ * Initializes the authorization subsystem from the config store.
+ * Load Authorization manager plugins, create and initialize
+ * initialize authorization manager instances.
+ *
+ * @param owner The owner of this module.
+ * @param config The configuration store.
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ try {
+ mLogger = CMS.getLogger();
+ mConfig = config;
+
+ // get authz manager plugins.
+
+ IConfigStore c = config.getSubStore(PROP_IMPL);
+ Enumeration<String> mImpls = c.getSubStoreNames();
+
+ while (mImpls.hasMoreElements()) {
+ String id = mImpls.nextElement();
+ String pluginPath = c.getString(id + "." + PROP_CLASS);
+
+ AuthzMgrPlugin plugin = new AuthzMgrPlugin(id, pluginPath);
+
+ mAuthzMgrPlugins.put(id, plugin);
+ }
+ if (Debug.ON) {
+ Debug.trace("loaded authz plugins");
+ }
+
+ // get authz manager instances.
+
+ c = config.getSubStore(PROP_INSTANCE);
+ Enumeration<String> instances = c.getSubStoreNames();
+
+ while (instances.hasMoreElements()) {
+ String insName = instances.nextElement();
+ String implName = c.getString(insName + "." + PROP_PLUGIN);
+ AuthzMgrPlugin plugin =
+ mAuthzMgrPlugins.get(implName);
+
+ if (plugin == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_NOT_FOUND", implName));
+ throw new EAuthzMgrPluginNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_PLUGIN_NOT_FOUND",
+ implName));
+ } else {
+ CMS.debug(
+ CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_FOUND", implName));
+ }
+
+ String className = plugin.getClassPath();
+
+ boolean isEnable = false;
+ // Instantiate and init the authorization manager.
+ IAuthzManager authzMgrInst = null;
+
+ try {
+ authzMgrInst = (IAuthzManager)
+ Class.forName(className).newInstance();
+ IConfigStore authzMgrConfig = c.getSubStore(insName);
+
+ authzMgrInst.init(insName, implName, authzMgrConfig);
+ isEnable = true;
+
+ log(ILogger.LL_INFO,
+ CMS.getLogMessage("CMSCORE_AUTHZ_INSTANCE_ADDED", insName));
+ } catch (ClassNotFoundException e) {
+ String errMsg = "AuthzSubsystem:: init()-" + e.toString();
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", errMsg));
+ throw new EAuthzException(CMS.getUserMessage("CMS_AUTHORIZATION_LOAD_CLASS_FAIL", className));
+ } catch (IllegalAccessException e) {
+ String errMsg = "AuthzSubsystem:: init()-" + e.toString();
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", errMsg));
+ throw new EAuthzException(CMS.getUserMessage("CMS_AUTHORIZATION_LOAD_CLASS_FAIL", className));
+ } catch (InstantiationException e) {
+ String errMsg = "AuthzSubsystem: init()-" + e.toString();
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", errMsg));
+ throw new EAuthzException(CMS.getUserMessage("CMS_AUTHORIZATION_LOAD_CLASS_FAIL", className));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_INIT_FAILED", insName, e.toString()));
+ // it is mis-configurated. This give
+ // administrator another chance to
+ // fix the problem via console
+ } catch (Throwable e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_INIT_FAILED", insName, e.toString()));
+ // Skip the authorization instance if
+ // it is mis-configurated. This give
+ // administrator another chance to
+ // fix the problem via console
+ }
+ // add manager instance to list.
+ mAuthzMgrInsts.put(insName, new
+ AuthzManagerProxy(isEnable, authzMgrInst));
+ if (Debug.ON) {
+ Debug.trace("loaded authz instance " + insName + " impl " + implName);
+ }
+ }
+ } catch (EBaseException ee) {
+ if (CMS.isPreOpMode())
+ return;
+ throw ee;
+ }
+
+ log(ILogger.LL_INFO, CMS.getLogMessage("INIT_DONE", getId()));
+ }
+
+ /**
+ * authMgrzAccessInit is for servlets who want to initialize their
+ * own authorization information before full operation. It is supposed
+ * to be called during the init() method of a servlet.
+ *
+ * @param authzMgrName The authorization manager name
+ * @param accessInfo the access information to be initialized. currently it's acl string in the format specified in
+ * the authorization manager
+ */
+ public void authzMgrAccessInit(String authzMgrInstName, String accessInfo)
+ throws EAuthzMgrNotFound, EBaseException {
+ AuthzManagerProxy proxy = mAuthzMgrInsts.get(authzMgrInstName);
+
+ if (proxy == null) {
+ throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName));
+ }
+ if (!proxy.isEnable()) {
+ throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName));
+ }
+ IAuthzManager authzMgrInst = proxy.getAuthzManager();
+
+ if (authzMgrInst == null) {
+ throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName));
+ }
+
+ authzMgrInst.accessInit(accessInfo);
+ }
+
+ /**
+ * Authorization to the named authorization manager instance
+ *
+ * @param authzMgrName The authorization manager name
+ * @param authToken the authenticaton token associated with a user
+ * @param resource the resource protected by the authorization system
+ * @param operation the operation for resource protected by the authoriz
+ * n system
+ * @exception EBaseException If an error occurs during authorization.
+ * @return a authorization token.
+ */
+ public AuthzToken authorize(
+ String authzMgrInstName, IAuthToken authToken,
+ String resource, String operation)
+ throws EAuthzMgrNotFound, EBaseException {
+
+ AuthzManagerProxy proxy = mAuthzMgrInsts.get(authzMgrInstName);
+
+ if (proxy == null) {
+ throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName));
+ }
+ if (!proxy.isEnable()) {
+ throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName));
+ }
+ IAuthzManager authzMgrInst = proxy.getAuthzManager();
+
+ if (authzMgrInst == null) {
+ throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName));
+ }
+ return (authzMgrInst.authorize(authToken, resource, operation));
+ }
+
+ public AuthzToken authorize(
+ String authzMgrInstName, IAuthToken authToken, String exp)
+ throws EAuthzMgrNotFound, EBaseException {
+
+ AuthzManagerProxy proxy = mAuthzMgrInsts.get(authzMgrInstName);
+
+ if (proxy == null) {
+ throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName));
+ }
+ if (!proxy.isEnable()) {
+ throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName));
+ }
+ IAuthzManager authzMgrInst = proxy.getAuthzManager();
+
+ if (authzMgrInst == null) {
+ throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName));
+ }
+ return (authzMgrInst.authorize(authToken, exp));
+ }
+
+ /**
+ * Gets configuration parameters for the given
+ * authorization manager plugin.
+ *
+ * @param implName Name of the authorization plugin.
+ * @return Hashtable of required parameters.
+ */
+ public String[] getConfigParams(String implName)
+ throws EAuthzMgrPluginNotFound, EBaseException {
+ // is this a registered implname?
+ AuthzMgrPlugin plugin = mAuthzMgrPlugins.get(implName);
+
+ if (plugin == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_NOT_FOUND", implName));
+ throw new EAuthzMgrPluginNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_PLUGIN_NOT_FOUND",
+ implName));
+ }
+
+ // a temporary instance
+ IAuthzManager authzMgrInst = null;
+ String className = plugin.getClassPath();
+
+ try {
+ authzMgrInst = (IAuthzManager)
+ Class.forName(className).newInstance();
+ return (authzMgrInst.getConfigParams());
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_NOT_CREATED", e.toString()));
+ throw new EAuthzException(CMS.getUserMessage("CMS_AUTHORIZATION_LOAD_CLASS_FAIL", className));
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_NOT_CREATED", e.toString()));
+ throw new EAuthzException(CMS.getUserMessage("CMS_AUTHORIZATION_LOAD_CLASS_FAIL", className));
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_NOT_CREATED", e.toString()));
+ throw new EAuthzException(CMS.getUserMessage("CMS_AUTHORIZATION_LOAD_CLASS_FAIL", className));
+ }
+ }
+
+ /**
+ * Add an authorization manager instance.
+ *
+ * @param name name of the authorization manager instance
+ * @param authzMgr the authorization manager instance to be added
+ */
+ public void add(String name, IAuthzManager authzMgrInst) {
+ mAuthzMgrInsts.put(name, new AuthzManagerProxy(true, authzMgrInst));
+ }
+
+ /*
+ * Removes a authorization manager instance.
+ * @param name name of the authorization manager
+ */
+ public void delete(String name) {
+ mAuthzMgrInsts.remove(name);
+ }
+
+ /**
+ * Gets the authorization manager instance of the specified name.
+ *
+ * @param name name of the authorization manager instance
+ * @return the named authorization manager instance
+ */
+ public IAuthzManager get(String name) {
+ AuthzManagerProxy proxy = mAuthzMgrInsts.get(name);
+
+ if (proxy == null)
+ return null;
+ return proxy.getAuthzManager();
+ }
+
+ /**
+ * Enumerate all authorization manager instances.
+ */
+ public Enumeration<IAuthzManager> getAuthzManagers() {
+ Vector<IAuthzManager> inst = new Vector<IAuthzManager>();
+ Enumeration<String> e = mAuthzMgrInsts.keys();
+
+ while (e.hasMoreElements()) {
+ IAuthzManager p = get(e.nextElement());
+
+ if (p != null) {
+ inst.addElement(p);
+ }
+ }
+ return (inst.elements());
+ }
+
+ /**
+ * Enumerate all registered authorization manager plugins.
+ */
+ public Enumeration<AuthzMgrPlugin> getAuthzManagerPlugins() {
+ return (mAuthzMgrPlugins.elements());
+ }
+
+ /**
+ * retrieve a single authz manager plugin by name
+ */
+ public AuthzMgrPlugin getAuthzManagerPluginImpl(String name) {
+ return mAuthzMgrPlugins.get(name);
+ }
+
+ /**
+ * Retrieve a single authz manager instance
+ */
+
+ /* getconfigparams above should be recoded to use this func */
+ public IAuthzManager getAuthzManagerPlugin(String name) {
+ AuthzMgrPlugin plugin = mAuthzMgrPlugins.get(name);
+ String classpath = plugin.getClassPath();
+ IAuthzManager authzMgrInst = null;
+
+ try {
+ authzMgrInst = (IAuthzManager) Class.forName(classpath).newInstance();
+ return (authzMgrInst);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_NOT_CREATED", e.toString()));
+ return null;
+ }
+ }
+
+ /**
+ * Retrieves id (name) of this subsystem.
+ *
+ * @return name of the authorization subsystem
+ */
+ public String getId() {
+ return (mId);
+ }
+
+ /**
+ * Sets id string to this subsystem.
+ * <p>
+ * Use with caution. Should not do it when sharing with others
+ *
+ * @param id name to be applied to an authorization sybsystem
+ */
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ /**
+ * registers the administration servlet with the administration subsystem.
+ */
+ public void startup() throws EBaseException {
+ //remove the log since it's already logged from S_ADMIN
+ //String infoMsg = "Authz subsystem administration Servlet registered";
+ //log(ILogger.LL_INFO, infoMsg);
+ }
+
+ /**
+ * shuts down authorization managers one by one.
+ * <P>
+ */
+ public void shutdown() {
+ for (AuthzManagerProxy proxy : mAuthzMgrInsts.values()) {
+ IAuthzManager mgr = proxy.getAuthzManager();
+
+ //String infoMsg =
+ // "Shutting down authz manager instance " + mgr.getName();
+ //log(ILogger.LL_INFO, infoMsg);
+ if (mgr != null)
+ mgr.shutdown();
+ }
+ mAuthzMgrPlugins.clear();
+ mAuthzMgrInsts.clear();
+ }
+
+ public Hashtable<String, AuthzMgrPlugin> getPlugins() {
+ return mAuthzMgrPlugins;
+ }
+
+ public Hashtable<String, AuthzManagerProxy> getInstances() {
+ return mAuthzMgrInsts;
+ }
+
+ /**
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * gets the named authorization manager
+ *
+ * @param name of the authorization manager
+ * @return the named authorization manager
+ */
+ public IAuthzManager getAuthzManager(String name) {
+ return get(name);
+ }
+
+ /**
+ * logs an entry in the log file.
+ */
+ public void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHORIZATION,
+ level, msg);
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/base/ArgBlock.java b/base/server/cmscore/src/com/netscape/cmscore/base/ArgBlock.java
new file mode 100644
index 000000000..7b7e42a0f
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/base/ArgBlock.java
@@ -0,0 +1,713 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.base;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SignatureException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+import netscape.security.pkcs.PKCS10;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.KeyGenInfo;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * This class represents a set of indexed arguments.
+ * Each argument is indexed by a key, which can be
+ * used during the argument retrieval.
+ *
+ * @version $Revision$, $Date$
+ */
+public class ArgBlock implements IArgBlock {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6054531129316353282L;
+ /*==========================================================
+ * variables
+ *==========================================================*/
+ public static final String CERT_NEW_REQUEST_HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----";
+ public static final String CERT_NEW_REQUEST_TRAILER = "-----END NEW CERTIFICATE REQUEST-----";
+ public static final String CERT_REQUEST_HEADER = "-----BEGIN CERTIFICATE REQUEST-----";
+ public static final String CERT_REQUEST_TRAILER = "-----END CERTIFICATE REQUEST-----";
+ public static final String CERT_RENEWAL_HEADER = "-----BEGIN RENEWAL CERTIFICATE REQUEST-----";
+ public static final String CERT_RENEWAL_TRAILER = "-----END RENEWAL CERTIFICATE REQUEST-----";
+
+ private Hashtable<String, Object> mArgs = new Hashtable<String, Object>();
+
+ private String mType = "unspecified-argblock";
+
+ /*==========================================================
+ * constructors
+ *==========================================================*/
+ /**
+ * Constructs an argument block with the given hashtable values.
+ *
+ * @param realm the type of argblock - used for debugging the values
+ */
+ public ArgBlock(String realm, Hashtable<String, String> httpReq) {
+ mType = realm;
+ populate(httpReq);
+ }
+
+ /**
+ * Constructs an argument block with the given hashtable values.
+ *
+ * @param httpReq hashtable keys and values
+ */
+ public ArgBlock(Hashtable<String, String> httpReq) {
+ populate(httpReq);
+ }
+
+ private void populate(Hashtable<String, String> httpReq) {
+ // Add all parameters from the request
+ Enumeration<String> e = httpReq.keys();
+
+ if (e != null) {
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+ String value = httpReq.get(name);
+
+ addStringValue(name, value);
+ }
+ }
+ }
+
+ /**
+ * Constructs an empty argument block.
+ */
+ public ArgBlock() {
+ }
+
+ /*==========================================================
+ * public methods
+ *==========================================================*/
+
+ /**
+ * Checks if this argument block contains the given key.
+ *
+ * @param n key
+ * @return true if key is present
+ */
+ public boolean isValuePresent(String n) {
+ CMS.traceHashKey(mType, n);
+ if (mArgs.get(n) != null) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Adds string-based value into this argument block.
+ *
+ * @param n key
+ * @param v value
+ * @return value
+ */
+ public Object addStringValue(String n, String v) {
+ if (v == null) {
+ return mArgs.put(n, Character.valueOf((char) 0));
+ } else {
+ return mArgs.put(n, v);
+ }
+ }
+
+ /**
+ * Retrieves argument value as string.
+ *
+ * @param n key
+ * @return argument value as string
+ * @exception EBaseException failed to retrieve value
+ */
+ public String getValueAsString(String n) throws EBaseException {
+ String t = (String) mArgs.get(n);
+ CMS.traceHashKey(mType, n, t);
+
+ if (t != null) {
+ return t;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND", n));
+ }
+ }
+
+ /**
+ * Retrieves argument value as string.
+ *
+ * @param n key
+ * @param def default value to be returned if key is not present
+ * @return argument value as string
+ */
+ public String getValueAsString(String n, String def) {
+ String val = (String) mArgs.get(n);
+ CMS.traceHashKey(mType, n, val, def);
+
+ if (val != null) {
+ return val;
+ } else {
+ return def;
+ }
+ }
+
+ /**
+ * Retrieves argument value as integer.
+ *
+ * @param n key
+ * @return argument value as int
+ * @exception EBaseException failed to retrieve value
+ */
+ public int getValueAsInt(String n) throws EBaseException {
+ if (mArgs.get(n) != null) {
+ CMS.traceHashKey(mType, n, (String) mArgs.get(n));
+ try {
+ return new Integer((String) mArgs.get(n)).intValue();
+ } catch (NumberFormatException e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_TYPE", n, e.toString()));
+ }
+ } else {
+ CMS.traceHashKey(mType, n, "<notpresent>");
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND", n));
+ }
+ }
+
+ /**
+ * Retrieves argument value as integer.
+ *
+ * @param n key
+ * @param def default value to be returned if key is not present
+ * @return argument value as int
+ */
+ public int getValueAsInt(String n, int def) {
+ CMS.traceHashKey(mType, n, (String) mArgs.get(n), "" + def);
+ if (mArgs.get(n) != null) {
+ try {
+ return new Integer((String) mArgs.get(n)).intValue();
+ } catch (NumberFormatException e) {
+ return def;
+ }
+ } else {
+ return def;
+ }
+ }
+
+ /**
+ * Retrieves argument value as big integer.
+ *
+ * @param n key
+ * @return argument value as big integer
+ * @exception EBaseException failed to retrieve value
+ */
+ public BigInteger getValueAsBigInteger(String n)
+ throws EBaseException {
+ String v = (String) mArgs.get(n);
+
+ if (v != null) {
+ try {
+ return new BigInteger(v, 10);
+ } catch (NumberFormatException e) {
+ try {
+ return new BigInteger(v, 16);
+ } catch (NumberFormatException ex) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_TYPE", n, ex.toString()));
+ }
+ }
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND", n));
+ }
+ }
+
+ /**
+ * Retrieves argument value as big integer.
+ *
+ * @param n key
+ * @param def default value to be returned if key is not present
+ * @return argument value as big integer
+ */
+ public BigInteger getValueAsBigInteger(String n, BigInteger def) {
+ try {
+ return getValueAsBigInteger(n);
+ } catch (EBaseException e) {
+ return def;
+ }
+ }
+
+ /**
+ * Retrieves argument value as object
+ *
+ * @param n key
+ * @return argument value as object
+ * @exception EBaseException failed to retrieve value
+ */
+ public Object getValue(Object n) throws EBaseException {
+ if (mArgs.get(n) != null) {
+ return mArgs.get(n);
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND", (String) n));
+ }
+ }
+
+ /**
+ * Retrieves argument value as object
+ *
+ * @param n key
+ * @param def default value to be returned if key is not present
+ * @return argument value as object
+ */
+ public Object getValue(Object n, Object def) {
+ if (mArgs.get(n) != null) {
+ return mArgs.get(n);
+ } else {
+ return def;
+ }
+ }
+
+ /**
+ * Gets boolean value. They should be "true" or "false".
+ *
+ * @param name name of the input type
+ * @return boolean type: <code>true</code> or <code>false</code>
+ * @exception EBaseException failed to retrieve value
+ */
+ public boolean getValueAsBoolean(String name) throws EBaseException {
+ String val = (String) mArgs.get(name);
+ CMS.traceHashKey(mType, name, val);
+
+ if (val != null) {
+ if (val.equalsIgnoreCase("true") ||
+ val.equalsIgnoreCase("on"))
+ return true;
+ else
+ return false;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND", name));
+ }
+ }
+
+ /**
+ * Gets boolean value. They should be "true" or "false".
+ *
+ * @param name name of the input type
+ * @return boolean type: <code>true</code> or <code>false</code>
+ */
+ public boolean getValueAsBoolean(String name, boolean def) {
+ boolean val;
+
+ try {
+ val = getValueAsBoolean(name);
+ return val;
+ } catch (EBaseException e) {
+ return def;
+ }
+ }
+
+ /**
+ * Gets KeyGenInfo
+ *
+ * @param name name of the input type
+ * @param verify true if signature validation is required
+ * @exception EBaseException
+ * @return KeyGenInfo object
+ */
+ public KeyGenInfo getValueAsKeyGenInfo(String name, KeyGenInfo def)
+ throws EBaseException {
+ KeyGenInfo keyGenInfo;
+
+ CMS.traceHashKey(mType, name);
+ if (mArgs.get(name) != null) {
+ try {
+ keyGenInfo = new KeyGenInfo((String) mArgs.get(name));
+ } catch (IOException e) {
+ return def;
+ }
+
+ } else {
+ return def;
+ }
+ return keyGenInfo;
+ }
+
+ /**
+ * Gets PKCS10 request. This pkcs10 attribute does not
+ * contain header information.
+ *
+ * @param name name of the input type
+ * @return pkcs10 request
+ * @exception EBaseException failed to retrieve value
+ */
+ public PKCS10 getValueAsRawPKCS10(String name) throws EBaseException {
+ PKCS10 request;
+
+ if (mArgs.get(name) != null) {
+ CMS.traceHashKey(mType, name, (String) mArgs.get(name));
+
+ String tempStr = unwrap((String) mArgs.get(name), false);
+
+ if (tempStr == null) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", name, "Empty Content"));
+ }
+ try {
+ request = decodePKCS10(tempStr);
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", name, e.toString()));
+ }
+ } else {
+ CMS.traceHashKey(mType, name, "<notpresent>");
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND", name));
+ }
+
+ return request;
+ }
+
+ /**
+ * Gets PKCS10 request. This pkcs10 attribute does not
+ * contain header information.
+ *
+ * @param name name of the input type
+ * @param def default PKCS10
+ * @return pkcs10 request
+ * @exception EBaseException failed to retrieve value
+ */
+ public PKCS10 getValueAsRawPKCS10(String name, PKCS10 def)
+ throws EBaseException {
+ PKCS10 request;
+
+ CMS.traceHashKey(mType, name);
+ if (mArgs.get(name) != null) {
+
+ String tempStr = unwrap((String) mArgs.get(name), false);
+
+ if (tempStr == null) {
+ return def;
+ }
+ try {
+ request = decodePKCS10(tempStr);
+ } catch (Exception e) {
+ return def;
+ }
+ } else {
+ return def;
+ }
+ return request;
+ }
+
+ /**
+ * Retrieves PKCS10
+ *
+ * @param name name of the input type
+ * @param checkheader true if header must be present
+ * @return PKCS10 object
+ * @exception EBaseException failed to retrieve value
+ */
+ public PKCS10 getValueAsPKCS10(String name, boolean checkheader)
+ throws EBaseException {
+ PKCS10 request;
+
+ CMS.traceHashKey(mType, name);
+ if (mArgs.get(name) != null) {
+
+ String tempStr = unwrap((String) mArgs.get(name), checkheader);
+
+ if (tempStr == null) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", name, "Empty Content"));
+ }
+ try {
+ request = decodePKCS10(tempStr);
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", name, e.toString()));
+ }
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND", name));
+ }
+
+ return request;
+ }
+
+ /**
+ * Retrieves PKCS10
+ *
+ * @param name name of the input type
+ * @param checkheader true if header must be present
+ * @param def default PKCS10
+ * @return PKCS10 object
+ * @exception EBaseException
+ */
+ public PKCS10 getValueAsPKCS10(
+ String name, boolean checkheader, PKCS10 def)
+ throws EBaseException {
+ PKCS10 request;
+
+ CMS.traceHashKey(mType, name);
+
+ if (mArgs.get(name) != null) {
+
+ String tempStr = unwrap((String) mArgs.get(name), checkheader);
+
+ if (tempStr == null) {
+ return def;
+ }
+ try {
+ request = decodePKCS10(tempStr);
+ } catch (Exception e) {
+ return def;
+ }
+ } else {
+ return def;
+ }
+
+ return request;
+ }
+
+ /**
+ * Retrieves PKCS10
+ *
+ * @param name name of the input type
+ * @param def default PKCS10
+ * @return PKCS10 object
+ * @exception EBaseException
+ */
+ public PKCS10 getValuePKCS10(String name, PKCS10 def)
+ throws EBaseException {
+ PKCS10 request;
+ String p10b64 = (String) mArgs.get(name);
+ CMS.traceHashKey(mType, name);
+
+ if (p10b64 != null) {
+
+ try {
+ request = decodePKCS10(p10b64);
+ return request;
+ } catch (Exception e) {
+ return def;
+ }
+ } else {
+ return def;
+ }
+ }
+
+ /**
+ * Sets argument into this block.
+ *
+ * @param name key
+ * @param ob value
+ */
+ public void set(String name, Object ob) {
+ mArgs.put(name, ob);
+ }
+
+ /**
+ * Retrieves argument.
+ *
+ * @param name key
+ * @return object value
+ */
+ public Object get(String name) {
+ CMS.traceHashKey(mType, name);
+ return mArgs.get(name);
+ }
+
+ /**
+ * Deletes argument by the given key.
+ *
+ * @param name key
+ */
+ public void delete(String name) {
+ mArgs.remove(name);
+ }
+
+ /**
+ * Retrieves a list of argument keys.
+ *
+ * @return a list of string-based keys
+ */
+ public Enumeration<String> getElements() {
+ return mArgs.keys();
+ }
+
+ /**
+ * Retrieves a list of argument keys.
+ *
+ * @return a list of string-based keys
+ */
+ public Enumeration<String> elements() {
+ return mArgs.keys();
+ }
+
+ /**
+ * Adds long-type arguments to this block.
+ *
+ * @param n key
+ * @param v value
+ * @return value
+ */
+ public Object addLongValue(String n, long v) {
+ return mArgs.put(n, Long.valueOf(v));
+ }
+
+ /**
+ * Adds integer-type arguments to this block.
+ *
+ * @param n key
+ * @param v value
+ * @return value
+ */
+ public Object addIntegerValue(String n, int v) {
+ return mArgs.put(n, Integer.valueOf(v));
+ }
+
+ /**
+ * Adds boolean-type arguments to this block.
+ *
+ * @param n key
+ * @param v value
+ * @return value
+ */
+ public Object addBooleanValue(String n, boolean v) {
+ return mArgs.put(n, Boolean.valueOf(v));
+ }
+
+ /**
+ * Adds integer-type arguments to this block.
+ *
+ * @param n key
+ * @param v value
+ * @param radix radix
+ * @return value
+ */
+ public Object addBigIntegerValue(String n, BigInteger v, int radix) {
+ return mArgs.put(n, v.toString(radix));
+ }
+
+ /*==========================================================
+ * private methods
+ *==========================================================*/
+
+ /**
+ * Unwrap PKCS10 Package
+ *
+ * @param request string formated PKCS10 request
+ * @exception EBaseException
+ * @return Base64Encoded PKCS10 request
+ */
+ private String unwrap(String request, boolean checkHeader)
+ throws EBaseException {
+ String unwrapped;
+ String header = null;
+ int head = -1;
+ int trail = -1;
+
+ // check for "-----BEGIN NEW CERTIFICATE REQUEST-----";
+ if (header == null) {
+ head = request.indexOf(CERT_NEW_REQUEST_HEADER);
+ trail = request.indexOf(CERT_NEW_REQUEST_TRAILER);
+
+ if (!(head == -1 && trail == -1)) {
+ header = CERT_NEW_REQUEST_HEADER;
+ }
+ }
+
+ // check for "-----BEGIN CERTIFICATE REQUEST-----";
+ if (header == null) {
+ head = request.indexOf(CERT_REQUEST_HEADER);
+ trail = request.indexOf(CERT_REQUEST_TRAILER);
+
+ // If this is not a request header, check if this is a renewal
+ // header.
+ if (!(head == -1 && trail == -1)) {
+ header = CERT_REQUEST_HEADER;
+
+ }
+ }
+
+ // check for "-----BEGIN RENEWAL CERTIFICATE REQUEST-----";
+ if (header == null) {
+ head = request.indexOf(CERT_RENEWAL_HEADER);
+ trail = request.indexOf(CERT_RENEWAL_TRAILER);
+ if (!(head == -1 && trail == -1)) {
+ header = CERT_RENEWAL_HEADER;
+ }
+ }
+
+ // Now validate if any headers or trailers are in place
+ if (head == -1 && checkHeader) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_MISSING_PKCS10_HEADER"));
+ }
+ if (trail == -1 && checkHeader) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_MISSING_PKCS10_TRAILER"));
+ }
+
+ if (header != null) {
+ unwrapped = request.substring(head + header.length(), trail);
+ } else {
+ unwrapped = request;
+ }
+
+ // strip all the crtl-characters (i.e. \r\n)
+ StringTokenizer st = new StringTokenizer(unwrapped, "\t\r\n ");
+ StringBuffer stripped = new StringBuffer();
+
+ while (st.hasMoreTokens()) {
+ stripped.append(st.nextToken());
+ }
+
+ return stripped.toString();
+ }
+
+ /**
+ * Decode Der encoded PKCS10 certifictae Request
+ *
+ * @param base64Request Base64 Encoded Certificate Request
+ * @exception Exception
+ * @return PKCS10
+ */
+ private PKCS10 decodePKCS10(String base64Request)
+ throws EBaseException {
+ PKCS10 pkcs10 = null;
+
+ try {
+ byte[] decodedBytes = Utils.base64decode(base64Request);
+
+ pkcs10 = new PKCS10(decodedBytes);
+ } catch (NoSuchProviderException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ } catch (IOException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ } catch (SignatureException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ } catch (NoSuchAlgorithmException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+
+ return pkcs10;
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/base/FileConfigStore.java b/base/server/cmscore/src/com/netscape/cmscore/base/FileConfigStore.java
new file mode 100644
index 000000000..b77f86d78
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/base/FileConfigStore.java
@@ -0,0 +1,175 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.base;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.Map;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * FileConfigStore:
+ * Extends HashConfigStore with methods to load/save from/to file for
+ * persistent storage. This is a configuration store agent who
+ * reads data from a file.
+ * <P>
+ * Note that a LdapConfigStore can be implemented so that it reads the configuration stores from the Ldap directory.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ * @see PropConfigStore
+ */
+public class FileConfigStore extends PropConfigStore implements
+ IConfigStore {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2642124526598175633L;
+ private File mFile = null;
+
+ /**
+ * Constructs a file configuration store.
+ * <P>
+ *
+ * @param fileName file name
+ * @exception EBaseException failed to create file configuration
+ */
+ public FileConfigStore(String fileName) throws EBaseException {
+ super(null); // top-level store without a name
+ mFile = new File(fileName);
+ if (!mFile.exists()) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_NO_CONFIG_FILE",
+ mFile.getPath()));
+ }
+ load(fileName);
+ }
+
+ /**
+ * Loads property file into memory.
+ * <P>
+ *
+ * @param fileName file name
+ * @exception EBaseException failed to load configuration
+ */
+ public void load(String fileName) throws EBaseException {
+ try {
+ FileInputStream fi = new FileInputStream(fileName);
+ BufferedInputStream bis = new BufferedInputStream(fi);
+
+ super.load(bis);
+ } catch (IOException e) {
+ throw new EBaseException("input stream error " + fileName, e);
+ }
+ }
+
+ /**
+ * The original config file is copied to
+ * <filename>.<current_time_in_milliseconds>.
+ * Commits the current properties to the configuration file.
+ * <P>
+ *
+ * @param backup
+ */
+ public void commit(boolean createBackup) throws EBaseException {
+ if (createBackup) {
+ File newName = new File(mFile.getPath() + "." +
+ Long.toString(System.currentTimeMillis()));
+
+ try {
+ if (Utils.isNT()) {
+ // NT is very picky on the path
+ Utils.exec("copy " +
+ mFile.getAbsolutePath().replace('/', '\\') +
+ " " +
+ newName.getAbsolutePath().replace('/',
+ '\\'));
+ } else {
+ // Create a copy of the original file which
+ // preserves the original file permissions.
+ Utils.exec("cp -p " + mFile.getAbsolutePath() + " " +
+ newName.getAbsolutePath());
+ }
+
+ // Proceed only if the backup copy was successful.
+ if (!newName.exists()) {
+ throw new EBaseException("backup copy failed");
+ } else {
+ // Make certain that the backup file has
+ // the correct permissions.
+ if (!Utils.isNT()) {
+ Utils.exec("chmod 00660 " + newName.getAbsolutePath());
+ }
+ }
+ } catch (EBaseException e) {
+ throw new EBaseException("backup copy failed");
+ }
+ }
+
+ // Overwrite the contents of the original file
+ // to preserve the original file permissions.
+ save(mFile.getPath());
+
+ try {
+ // Make certain that the original file retains
+ // the correct permissions.
+ if (!Utils.isNT()) {
+ Utils.exec("chmod 00660 " + mFile.getCanonicalPath());
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ /**
+ * Saves in-memory properties to a specified file.
+ * <P>
+ * Note that the superclass's save is synchronized. It means no properties can be altered (inserted) at the saving
+ * time.
+ * <P>
+ *
+ * @param fileName filename
+ * @exception EBaseException failed to save configuration
+ */
+ public void save(String fileName) throws EBaseException {
+ try {
+ Map<String, String> map = getProperties();
+
+ FileOutputStream fo = new FileOutputStream(fileName);
+ PrintWriter writer = new PrintWriter(new OutputStreamWriter(fo));
+
+ for (String name : map.keySet()) {
+ String value = map.get(name);
+ writer.println(name + "=" + value);
+ }
+
+ writer.close();
+ fo.close();
+ } catch (IOException e) {
+ throw new EBaseException("output stream error " + fileName, e);
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/base/JDialogPasswordCallback.java b/base/server/cmscore/src/com/netscape/cmscore/base/JDialogPasswordCallback.java
new file mode 100644
index 000000000..4bcf9b44f
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/base/JDialogPasswordCallback.java
@@ -0,0 +1,267 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.base;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.util.PasswordCallback;
+import org.mozilla.jss.util.PasswordCallbackInfo;
+
+/**
+ * A class to retrieve passwords through a modal Java dialog box
+ */
+public class JDialogPasswordCallback implements PasswordCallback {
+
+ public Password getPasswordFirstAttempt(PasswordCallbackInfo info)
+ throws PasswordCallback.GiveUpException {
+ return getPW(info, false);
+ }
+
+ public Password getPasswordAgain(PasswordCallbackInfo info)
+ throws PasswordCallback.GiveUpException {
+ return getPW(info, true);
+ }
+
+ // This structure holds information local to a getPW() call, for use
+ // by action listeners
+ private static class PWHolder {
+ public Password password = null;
+ public boolean cancelled = true;
+ }
+
+ private void resetGBC(GridBagConstraints gbc) {
+ gbc.gridx = GridBagConstraints.RELATIVE;
+ gbc.gridy = GridBagConstraints.RELATIVE;
+ gbc.gridwidth = 1;
+ gbc.gridheight = 1;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.anchor = GridBagConstraints.CENTER;
+ gbc.ipadx = 0;
+ gbc.ipady = 0;
+ gbc.weightx = 0.0;
+ gbc.weighty = 0.0;
+ }
+
+ /**
+ * This function can be overriden if different heading is required.
+ */
+ public String getPrompt(PasswordCallbackInfo info) {
+ return "Enter the password for \"" + info.getName() + "\": ";
+ }
+
+ /**
+ * This method does the work of displaying the dialog box,
+ * extracting the information, and returning it.
+ */
+ private Password getPW(PasswordCallbackInfo info, boolean retry)
+ throws PasswordCallback.GiveUpException {
+ // These need to final so they can be accessed from action listeners
+ final PWHolder pwHolder = new PWHolder();
+ final JFrame f = new JFrame("Password Dialog");
+ final JPasswordField pwField = new JPasswordField(15);
+
+ ///////////////////////////////////////////////////
+ // Panel
+ ///////////////////////////////////////////////////
+ JPanel contentPane = new JPanel(new GridBagLayout());
+
+ contentPane.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
+ GridBagConstraints c = new GridBagConstraints();
+
+ ////////////////////////////////////////////////////
+ // Labels
+ ////////////////////////////////////////////////////
+
+ if (retry) {
+ JLabel warning = new JLabel("Password incorrect.");
+
+ warning.setForeground(Color.red);
+ resetGBC(c);
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ // Setting this to NULL causes nasty Exception stack traces
+ // to be printed, although the program still seems to work
+ //warning.setHighlighter(null);
+ contentPane.add(warning, c);
+ }
+
+ String prompt = getPrompt(info);
+ JLabel label = new JLabel(prompt);
+
+ label.setForeground(Color.black);
+ // Setting this to NULL causes nasty Exception stack traces
+ // to be printed, although the program still seems to work
+ //label.setHighlighter(null);
+ resetGBC(c);
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ contentPane.add(label, c);
+
+ ///////////////////////////////////////////////////
+ // Password text field
+ ///////////////////////////////////////////////////
+
+ // Listener for the text field
+ ActionListener getPasswordListener = new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ //input = (JPasswordField)e.getSource();
+
+ pwHolder.password = new Password(pwField.getPassword());
+ pwHolder.cancelled = false;
+ f.dispose();
+ }
+ };
+
+ // There is a bug in JPasswordField. The cursor is advanced by the
+ // width of the character you type, but a '*' is echoed, so the
+ // cursor does not stay lined up with the end of the text.
+ // We use a monospaced font to workaround this.
+
+ pwField.setFont(new Font("Monospaced", Font.PLAIN,
+ pwField.getFont().getSize()));
+ pwField.setEchoChar('*');
+ pwField.addActionListener(getPasswordListener);
+ resetGBC(c);
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.NONE;
+ c.insets = new Insets(16, 0, 0, 0);
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ //c.gridy++;
+ contentPane.add(pwField, c);
+
+ ///////////////////////////////////////////////////
+ // Cancel button
+ ///////////////////////////////////////////////////
+
+ JPanel buttonPanel = new JPanel(new GridBagLayout());
+
+ JButton ok = new JButton(" OK ");
+
+ ok.addActionListener(getPasswordListener);
+ resetGBC(c);
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.CENTER;
+ c.gridheight = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(10, 0, 0, 4);
+ buttonPanel.add(ok, c);
+
+ JButton cancel = new JButton("Cancel");
+ ActionListener buttonListener = new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ pwHolder.cancelled = true;
+ f.dispose();
+ }
+ };
+
+ cancel.addActionListener(buttonListener);
+ resetGBC(c);
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(10, 4, 0, 0);
+ c.gridheight = GridBagConstraints.REMAINDER;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ buttonPanel.add(cancel, c);
+
+ resetGBC(c);
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.CENTER;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.gridheight = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(0, 0, 0, 0);
+ contentPane.add(buttonPanel, c);
+
+ ///////////////////////////////////////////////////
+ // Create modal dialog
+ ///////////////////////////////////////////////////
+ JDialog d = new JDialog(f, "Fedora Certificate System", true);
+
+ WindowListener windowListener = new WindowAdapter() {
+ public void windowOpened(WindowEvent e) {
+ pwField.requestFocus();
+ }
+ };
+
+ d.addWindowListener(windowListener);
+
+ d.setContentPane(contentPane);
+ d.pack();
+ Dimension screenSize = d.getToolkit().getScreenSize();
+ Dimension paneSize = d.getSize();
+
+ d.setLocation((screenSize.width - paneSize.width) / 2,
+ (screenSize.height - paneSize.height) / 2);
+ d.getRootPane().setDefaultButton(ok);
+
+ // toFront seems to cause the dialog to go blank on unix!
+ //d.toFront();
+
+ d.setVisible(true);
+
+ ///////////////////////////////////////////////////
+ // Return results
+ ///////////////////////////////////////////////////
+ if (pwHolder.cancelled) {
+ throw new PasswordCallback.GiveUpException();
+ }
+
+ return pwHolder.password;
+ }
+
+ // Test program
+ public static void main(String args[]) {
+ try {
+ CryptoManager manager;
+
+ CryptoManager.InitializationValues iv = new
+ CryptoManager.InitializationValues(args[0]);
+
+ CryptoManager.initialize(iv);
+ manager = CryptoManager.getInstance();
+
+ CryptoToken tok = manager.getInternalKeyStorageToken();
+
+ tok.login(new JDialogPasswordCallback());
+ System.out.println("Logged in!!!");
+ System.exit(0);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/base/PropConfigStore.java b/base/server/cmscore/src/com/netscape/cmscore/base/PropConfigStore.java
new file mode 100644
index 000000000..eb3f6c312
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/base/PropConfigStore.java
@@ -0,0 +1,777 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.base;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Vector;
+
+import org.mozilla.jss.util.Base64OutputStream;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotDefined;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISourceConfigStore;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * A class represents a in-memory configuration store.
+ * Note this class takes advantage of the recursive nature of
+ * property names. The current property prefix is kept in
+ * mStoreName and the mSource usually points back to another
+ * occurance of the same PropConfigStore, with longer mStoreName. IE
+ *
+ * <PRE>
+ * cms.ca0.http.service0 -> mSource=PropConfigStore ->
+ * cms.ca0.http -> mSource=PropConfigStore ->
+ * cms.ca0 -> mSource=PropConfigStore ->
+ * cms -> mSource=SourceConfigStore -> Properties
+ * </PRE>
+ *
+ * The chain ends when the store name is reduced down to it's original
+ * value.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class PropConfigStore implements IConfigStore, Cloneable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 4714108964096659077L;
+
+ protected static final String PROP_SUBSTORES = "substores";
+
+ /**
+ * The name of this substore
+ */
+ protected String mStoreName = null;
+
+ /**
+ * The source data for this substore
+ */
+ protected ISourceConfigStore mSource = null;
+
+ private static String mDebugType = "CS.cfg";
+
+ /**
+ * Constructs a property configuration store. This must
+ * be a brand new store without properties. The subclass
+ * must be a ISourceConfigStore.
+ * <P>
+ *
+ * @param storeName property store name
+ * @exception EBaseException failed to create configuration
+ */
+ public PropConfigStore(String storeName) {
+ mSource = new SourceConfigStore();
+ mStoreName = storeName;
+ }
+
+ /**
+ * Constructs a configuration store. The constructor is
+ * a helper class for substores. Source is the one
+ * that stores all the parameters. Each substore only
+ * store a substore name, and a reference to the source.
+ * <P>
+ *
+ * @param storeName store name
+ * @param prop list of properties
+ * @exception EBaseException failed to create configuration
+ */
+ protected PropConfigStore(String name, ISourceConfigStore source) {
+ mStoreName = name;
+ mSource = source;
+ }
+
+ /**
+ * Returns the name of this store.
+ * <P>
+ *
+ * @return store name
+ */
+ public String getName() {
+ return mStoreName;
+ }
+
+ /**
+ * Retrieves a property from the configuration file.
+ * <P>
+ *
+ * @param name property name
+ * @return property value
+ */
+ public String get(String name) {
+ return mSource.get(getFullName(name));
+ }
+
+ /**
+ * Retrieves a property from the configuration file. Does not prepend
+ * the config store name to the property.
+ * <P>
+ *
+ * @param name property name
+ * @return property value
+ */
+ private String nakedGet(String name) {
+ return mSource.get(name);
+ }
+
+ /**
+ * Puts a property into the configuration file. The
+ * values wont be updated to the file until save
+ * method is invoked.
+ * <P>
+ *
+ * @param name property name
+ * @param value property value
+ */
+ public String put(String name, String value) {
+ return mSource.put(getFullName(name), value);
+ }
+
+ /**
+ * Removes a property from the configuration file.
+ *
+ * @param name property name
+ */
+ public void remove(String name) {
+ ((SourceConfigStore) mSource).remove(getFullName(name));
+ }
+
+ /**
+ * Returns an enumeration of the config store's keys, hidding the store
+ * name.
+ *
+ * @see java.util.Hashtable#elements
+ * @see java.util.Enumeration
+ */
+ public Enumeration<String> keys() {
+ Hashtable<String, String> h = new Hashtable<String, String>();
+ enumerate(h);
+ return h.keys();
+ }
+
+ /**
+ * Retrieves lexicographically sorted properties as a map.
+ *
+ * @return map
+ */
+ public Map<String, String> getProperties() {
+ Map<String, String> map = new TreeMap<String, String>();
+ enumerate(map);
+ return map;
+ }
+
+ /**
+ * Return the number of items in this substore
+ */
+ public int size() {
+ Hashtable<String, String> h = new Hashtable<String, String>();
+ enumerate(h);
+ return h.size();
+ }
+
+ /**
+ * Fills the given map with all key/value pairs in the current
+ * config store, removing the config store name prefix
+ * <P>
+ *
+ * @param map the map
+ */
+ private synchronized void enumerate(Map<String, String> map) {
+ Enumeration<String> e = mSource.keys();
+ // We only want the keys which match the current substore name
+ // without the current substore prefix. This code works even
+ // if mStoreName is null.
+ String fullName = getFullName("");
+ int kIndex = fullName.length();
+
+ while (e.hasMoreElements()) {
+ String key = e.nextElement();
+
+ if (key.startsWith(fullName)) {
+ map.put(key.substring(kIndex), nakedGet(key));
+ }
+ }
+ }
+
+ /**
+ * Reads a config store from an input stream.
+ *
+ * @param in input stream where properties are located
+ * @exception IOException failed to load
+ */
+ public synchronized void load(InputStream in) throws IOException {
+ mSource.load(in);
+ }
+
+ /**
+ * Stores this config store to the specified output stream.
+ *
+ * @param out outputstream where the properties are saved
+ * @param header optional header information to be saved
+ */
+ public synchronized void save(OutputStream out, String header) {
+ mSource.save(out, header);
+ }
+
+ /**
+ * Retrieves a property value.
+ *
+ * @param name property key
+ * @return property value
+ * @exception EBaseException failed to retrieve value
+ */
+ public String getString(String name) throws EBaseException {
+ String str = get(name);
+
+ if (str == null) {
+ CMS.traceHashKey(mDebugType, getFullName(name), "<notpresent>");
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", getName() + "." + name));
+ }
+ // should we check for empty string ?
+ // if (str.length() == 0) {
+ // throw new EPropertyNotDefined(getName() + "." + name);
+ // }
+ String ret = null;
+
+ try {
+ ret = new String(str.getBytes(), "UTF8").trim();
+ } catch (java.io.UnsupportedEncodingException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_UTF8_NOT_SUPPORTED"));
+ }
+ CMS.traceHashKey(mDebugType, getFullName(name), ret);
+ return ret;
+ }
+
+ /**
+ * Retrieves a String from the configuration file.
+ * <P>
+ *
+ * @param name property name
+ * @param defval the default object to return if name does not exist
+ * @return property value
+ */
+ public String getString(String name, String defval) throws EBaseException {
+ String val;
+
+ try {
+ val = getString(name);
+ } catch (EPropertyNotFound e) {
+ val = defval;
+ }
+ CMS.traceHashKey(mDebugType, getFullName(name), val, defval);
+ return val;
+ }
+
+ /**
+ * Puts property value into this configuration store.
+ *
+ * @param name property key
+ * @param value property value
+ */
+ public void putString(String name, String value) {
+ put(name, value);
+ }
+
+ /**
+ * Retrieves a byte array from the configuration file.
+ * <P>
+ *
+ * @param name property name
+ * @exception IllegalArgumentException if name is not set or is null.
+ *
+ * @return property value
+ */
+ public byte[] getByteArray(String name) throws EBaseException {
+ byte[] arr = getByteArray(name, new byte[0]);
+
+ if (arr.length == 0) {
+ CMS.traceHashKey(mDebugType, getFullName(name), "<notpresent>");
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", getName() + "." + name));
+ }
+ return arr;
+ }
+
+ /**
+ * Retrieves a byte array from the configuration file.
+ * <P>
+ *
+ * @param name property name
+ * @param defval the default byte array to return if name does
+ * not exist
+ *
+ * @return property value
+ */
+ public byte[] getByteArray(String name, byte defval[])
+ throws EBaseException {
+ String str = get(name);
+
+ if (str == null || str.length() == 0) {
+ CMS.traceHashKey(mDebugType, getFullName(name),
+ "<notpresent>", "<bytearray>");
+ return defval;
+ } else {
+ CMS.traceHashKey(mDebugType, getFullName(name),
+ "<bytearray>", "<bytearray>");
+ return Utils.base64decode(str);
+ }
+ }
+
+ /**
+ * Puts byte array into this configuration store.
+ *
+ * @param name property key
+ * @param value byte array
+ */
+ public void putByteArray(String name, byte value[]) {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ try (Base64OutputStream b64 = new Base64OutputStream(new
+ PrintStream(new FilterOutputStream(output)))) {
+ b64.write(value);
+ b64.flush();
+
+ // 8859 contains all the base-64 chars, so there are no
+ // internationalization problems here
+ put(name, output.toString("8859_1"));
+ } catch (IOException e) {
+ System.out.println("Warning: base-64 encoding of configuration " +
+ "information failed");
+ }
+ }
+
+ /**
+ * Retrieves boolean-based property value.
+ *
+ * @param name property key
+ * @return boolean value
+ * @exception EBaseException failed to retrieve
+ */
+ public boolean getBoolean(String name) throws EBaseException {
+ String value = get(name);
+
+ if (value == null) {
+ CMS.traceHashKey(mDebugType, getFullName(name), "<notpresent>");
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", getName() + "." + name));
+ }
+ if (value.length() == 0) {
+ throw new EPropertyNotDefined(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_NOVALUE", getName() + "." + name));
+ }
+
+ if (value.equalsIgnoreCase("true")) {
+ return true;
+ } else if (value.equalsIgnoreCase("false")) {
+ return false;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_PROPERTY_1", getName() + "." + name,
+ "boolean", "\"true\" or \"false\""));
+ }
+ }
+
+ /**
+ * Retrieves boolean-based property value.
+ *
+ * @param name property key
+ * @param defval default value
+ * @return boolean value
+ * @exception EBaseException failed to retrieve
+ */
+ public boolean getBoolean(String name, boolean defval)
+ throws EBaseException {
+ boolean val;
+
+ try {
+ val = getBoolean(name);
+ } catch (EPropertyNotFound e) {
+ val = defval;
+ } catch (EPropertyNotDefined e) {
+ val = defval;
+ }
+ CMS.traceHashKey(mDebugType, getFullName(name),
+ val ? "true" : "false", defval ? "true" : "false");
+ return val;
+ }
+
+ /**
+ * Puts boolean value into the configuration store.
+ *
+ * @param name property key
+ * @param value property value
+ */
+ public void putBoolean(String name, boolean value) {
+ if (value) {
+ put(name, "true");
+ } else {
+ put(name, "false");
+ }
+ }
+
+ /**
+ * Retrieves integer value.
+ *
+ * @param name property key
+ * @return property value
+ * @exception EBaseException failed to retrieve value
+ */
+ public int getInteger(String name) throws EBaseException {
+ String value = get(name);
+
+ if (value == null) {
+ CMS.traceHashKey(mDebugType, getFullName(name), "<notpresent>");
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", getName() + "." + name));
+ }
+ if (value.length() == 0) {
+ throw new EPropertyNotDefined(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_NOVALUE", getName() + "." + name));
+ }
+ try {
+ CMS.traceHashKey(mDebugType, getFullName(name), value);
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_PROPERTY_1", getName() + "." + name, "int",
+ "number"));
+ }
+ }
+
+ /**
+ * Retrieves integer value.
+ *
+ * @param name property key
+ * @param defval default value
+ * @return property value
+ * @exception EBaseException failed to retrieve value
+ */
+ public int getInteger(String name, int defval) throws EBaseException {
+ int val;
+
+ try {
+ val = getInteger(name);
+ } catch (EPropertyNotFound e) {
+ val = defval;
+ } catch (EPropertyNotDefined e) {
+ val = defval;
+ }
+ CMS.traceHashKey(mDebugType, getFullName(name),
+ "" + val, "" + defval);
+ return val;
+ }
+
+ /**
+ * Puts an integer value.
+ *
+ * @param name property key
+ * @param val property value
+ * @exception EBaseException failed to retrieve value
+ */
+ public void putInteger(String name, int val) {
+ put(name, Integer.toString(val));
+ }
+
+ /**
+ * Retrieves big integer value.
+ *
+ * @param name property key
+ * @return property value
+ * @exception EBaseException failed to retrieve value
+ */
+ public BigInteger getBigInteger(String name) throws EBaseException {
+ String value = get(name);
+
+ if (value == null) {
+ CMS.traceHashKey(mDebugType, getFullName(name), "<notpresent>");
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", getName() + "." + name));
+ }
+ if (value.length() == 0) {
+ throw new EPropertyNotDefined(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_NOVALUE", getName() + "." + name));
+ }
+ try {
+ if (value.startsWith("0x") || value.startsWith("0X")) {
+ String val = value.substring(2);
+
+ return new BigInteger(val, 16);
+ }
+ return new BigInteger(value);
+ } catch (NumberFormatException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_PROPERTY_1", getName() + "." + name,
+ "BigInteger", "number"));
+ }
+ }
+
+ /**
+ * Retrieves integer value.
+ *
+ * @param name property key
+ * @param defval default value
+ * @return property value
+ * @exception EBaseException failed to retrieve value
+ */
+ public BigInteger getBigInteger(String name, BigInteger defval)
+ throws EBaseException {
+ BigInteger val;
+
+ try {
+ val = getBigInteger(name);
+ } catch (EPropertyNotFound e) {
+ val = defval;
+ } catch (EPropertyNotDefined e) {
+ val = defval;
+ }
+ return val;
+ }
+
+ /**
+ * Puts a big integer value.
+ *
+ * @param name property key
+ * @param val default value
+ */
+ public void putBigInteger(String name, BigInteger val) {
+ put(name, val.toString());
+ }
+
+ /**
+ * Creates a new sub store.
+ * <P>
+ *
+ * @param name substore name
+ * @return substore
+ */
+ public IConfigStore makeSubStore(String name) {
+
+ /*
+ String names=(String)mSource.get(getFullName(PROP_SUBSTORES));
+
+ if (names==null) {
+ names=name;
+ }
+ else {
+ names=names+","+name;
+ }
+ mSource.put(getFullName(PROP_SUBSTORES), name);
+ */
+ return new PropConfigStore(getFullName(name), mSource);
+ }
+
+ /**
+ * Removes a sub store.
+ * <p>
+ *
+ * @param name substore name
+ */
+ @SuppressWarnings("unchecked")
+ public void removeSubStore(String name) {
+ // this operation is expensive!!!
+
+ Enumeration<String> e = mSource.keys();
+ // We only want the keys which match the current substore name
+ // without the current substore prefix. This code works even
+ // if mStoreName is null.
+ String fullName = getFullName(name);
+
+ while (e.hasMoreElements()) {
+ String key = e.nextElement();
+
+ if (key.startsWith(fullName + ".")) {
+ ((Hashtable<String, String>) mSource).remove(key);
+ }
+ }
+ }
+
+ /**
+ * Retrieves a sub store. A substore contains a list
+ * of properties and substores. For example,
+ *
+ * <PRE>
+ * cms.ldap.host=ds.netscape.com
+ * cms.ldap.port=389
+ * </PRE>
+ *
+ * "ldap" is a substore in above example. If the
+ * substore property itself is set, this method
+ * will treat the value as a reference. For example,
+ *
+ * <PRE>
+ * cms.ldap = kms.ldap
+ * </PRE>
+ * <P>
+ *
+ * @param name substore name
+ * @return substore
+ */
+ public IConfigStore getSubStore(String name) {
+ String fullname = getFullName(name);
+ String reference = mSource.get(fullname);
+
+ if (reference == null) {
+ PropConfigStore ps = new PropConfigStore(fullname, mSource);
+
+ return ps;
+ } else {
+ PropConfigStore ps = new PropConfigStore(reference, mSource);
+
+ return ps;
+ }
+ }
+
+ /**
+ * Retrieves a list of property names.
+ *
+ * @return a list of string-based property names
+ */
+ public Enumeration<String> getPropertyNames() {
+ // XXX - this operation is expensive!!!
+ Map<String, String> map = getProperties();
+
+ Vector<String> v = new Vector<String>();
+ for (String name : map.keySet()) {
+ int i = name.indexOf('.'); // substores have "."
+ if (i >= 0) continue;
+ if (v.contains(name)) continue;
+
+ v.addElement(name);
+ }
+
+ return v.elements();
+ }
+
+ /**
+ * Returns a list of sub store names.
+ * <P>
+ *
+ * @return list of substore names
+ */
+ public Enumeration<String> getSubStoreNames() {
+ // XXX - this operation is expensive!!!
+ Map<String, String> map = getProperties();
+
+ Vector<String> v = new Vector<String>();
+ for (String name : map.keySet()) {
+ int i = name.indexOf('.'); // substores have "."
+ if (i < 0) continue;
+
+ name = name.substring(0, i);
+ if (v.contains(name)) continue;
+
+ v.addElement(name);
+ }
+
+ return v.elements();
+ }
+
+ /**
+ * Retrieves the source configuration store where
+ * the properties are stored.
+ * <P>
+ *
+ * @return source configuration store
+ */
+ public ISourceConfigStore getSourceConfigStore() {
+ return mSource;
+ }
+
+ /**
+ * For debugging purposes. Prints properties of this
+ * substore.
+ */
+ public void printProperties() {
+ Enumeration<String> keys = mSource.keys();
+
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement();
+
+ if (mStoreName == null) {
+ System.out.println(key);
+ } else {
+ if (key.startsWith(mStoreName))
+ System.out.println(key);
+ }
+ }
+ }
+
+ /**
+ * Converts the substore parameters.
+ *
+ * @param name property name
+ * @return fill property name
+ */
+ private String getFullName(String name) {
+ if (mStoreName == null)
+ return name;
+ else
+ return mStoreName + "." + name;
+ }
+
+ /**
+ * Cloning of property configuration store.
+ *
+ * @return a new configuration store
+ */
+ public Object clone() {
+ try {
+ PropConfigStore that = (PropConfigStore) super.clone();
+
+ mStoreName = getName();
+ mSource = new SourceConfigStore();
+ Enumeration<String> subs = getSubStoreNames();
+
+ while (subs.hasMoreElements()) {
+ String name = subs.nextElement();
+
+ IConfigStore sub = getSubStore(name);
+ IConfigStore newSub = that.makeSubStore(sub.getName());
+
+ Enumeration<String> props = sub.getPropertyNames();
+
+ while (props.hasMoreElements()) {
+ String n = props.nextElement();
+
+ try {
+ newSub.putString(n,
+ sub.getString(n));
+ } catch (EBaseException ex) {
+ }
+ }
+ }
+ return that;
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+
+ }
+
+ /**
+ * Commits properties into the file.
+ *
+ * @param createBackup true if create backup
+ * @exception EBaseException failed to commit properties
+ */
+ public void commit(boolean createBackup) throws EBaseException {
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/base/SimpleProperties.java b/base/server/cmscore/src/com/netscape/cmscore/base/SimpleProperties.java
new file mode 100644
index 000000000..38c17d861
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/base/SimpleProperties.java
@@ -0,0 +1,482 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.base;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * The <code>Properties</code> class represents a persistent set of
+ * properties. The <code>Properties</code> can be saved to a stream
+ * or loaded from a stream. Each key and its corresponding value in
+ * the property list is a string.
+ * <p>
+ * A property list can contain another property list as its "defaults"; this second property list is searched if the
+ * property key is not found in the original property list.
+ *
+ * Because <code>Properties</code> inherits from <code>Hashtable</code>, the <code>put</code> and <code>putAll</code>
+ * methods can be applied to a <code>Properties</code> object. Their use is strongly discouraged as they allow the
+ * caller to insert entries whose keys or values are not <code>Strings</code>. The <code>setProperty</code> method
+ * should be used instead. If the <code>store</code> or <code>save</code> method is called on a "compromised"
+ * <code>Properties</code> object that contains a non- <code>String</code> key or value, the call will fail.
+ *
+ */
+public class SimpleProperties extends Hashtable<String, String> {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6129810287662322712L;
+
+ /**
+ * A property list that contains default values for any keys not
+ * found in this property list.
+ *
+ * @serial
+ */
+ protected SimpleProperties defaults;
+
+ /**
+ * Creates an empty property list with no default values.
+ */
+ public SimpleProperties() {
+ this(null);
+ }
+
+ /**
+ * Creates an empty property list with the specified defaults.
+ *
+ * @param defaults the defaults.
+ */
+ public SimpleProperties(SimpleProperties defaults) {
+ this.defaults = defaults;
+ }
+
+ /**
+ * Calls the hashtable method <code>put</code>. Provided for
+ * parallelism with the getProperties method. Enforces use of
+ * strings for property keys and values.
+ *
+ * @since JDK1.2
+ */
+ public synchronized Object setProperty(String key, String value) {
+ return put(key, value);
+ }
+
+ private static final String keyValueSeparators = "=: \t\r\n\f";
+
+ private static final String strictKeyValueSeparators = "=:";
+
+ private static final String whiteSpaceChars = " \t\r\n\f";
+
+ /**
+ * Reads a property list (key and element pairs) from the input stream.
+ * <p>
+ * Every property occupies one line of the input stream. Each line is terminated by a line terminator (
+ * <code>\n</code> or <code>\r</code> or <code>\r\n</code>). Lines from the input stream are processed until end of
+ * file is reached on the input stream.
+ * <p>
+ * A line that contains only whitespace or whose first non-whitespace character is an ASCII <code>#</code> or
+ * <code>!</code> is ignored (thus, <code>#</code> or <code>!</code> indicate comment lines).
+ * <p>
+ * Every line other than a blank line or a comment line describes one property to be added to the table (except that
+ * if a line ends with \, then the following line, if it exists, is treated as a continuation line, as described
+ * below). The key consists of all the characters in the line starting with the first non-whitespace character and
+ * up to, but not including, the first ASCII <code>=</code>, <code>:</code>, or whitespace character. All of the key
+ * termination characters may be included in the key by preceding them with a \. Any whitespace after the key is
+ * skipped; if the first non-whitespace character after the key is <code>=</code> or <code>:</code>, then it is
+ * ignored and any whitespace characters after it are also skipped. All remaining characters on the line become part
+ * of the associated element string. Within the element string, the ASCII escape sequences <code>\t</code>,
+ * <code>\n</code>, <code>\r</code>, <code>\\</code>, <code>\"</code>, <code>\'</code>, <code>\ &#32;</code> &#32;(a
+ * backslash and a space), and <code>\\u</code><i>xxxx</i> are recognized and converted to single characters.
+ * Moreover, if the last character on the line is <code>\</code>, then the next line is treated as a continuation of
+ * the current line; the <code>\</code> and line terminator are simply discarded, and any leading whitespace
+ * characters on the continuation line are also discarded and are not part of the element string.
+ * <p>
+ * As an example, each of the following four lines specifies the key <code>"Truth"</code> and the associated element
+ * value <code>"Beauty"</code>:
+ * <p>
+ *
+ * <pre>
+ * Truth = Beauty
+ * Truth:Beauty
+ * Truth :Beauty
+ * </pre>
+ *
+ * As another example, the following three lines specify a single property:
+ * <p>
+ *
+ * <pre>
+ * fruits apple, banana, pear, \
+ * cantaloupe, watermelon, \
+ * kiwi, mango
+ * </pre>
+ *
+ * The key is <code>"fruits"</code> and the associated element is:
+ * <p>
+ *
+ * <pre>
+ * &quot;apple, banana, pear, cantaloupe, watermelon,kiwi, mango&quot;
+ * </pre>
+ *
+ * Note that a space appears before each <code>\</code> so that a space will appear after each comma in the final
+ * result; the <code>\</code>, line terminator, and leading whitespace on the continuation line are merely discarded
+ * and are <i>not</i> replaced by one or more other characters.
+ * <p>
+ * As a third example, the line:
+ * <p>
+ *
+ * <pre>
+ * cheeses
+ * </pre>
+ *
+ * specifies that the key is <code>"cheeses"</code> and the associated element is the empty string.
+ * <p>
+ *
+ * @param in the input stream.
+ * @exception IOException if an error occurred when reading from the
+ * input stream.
+ */
+ public synchronized void load(InputStream inStream) throws IOException {
+
+ BufferedReader in = new BufferedReader(new InputStreamReader(inStream, "8859_1"));
+
+ while (true) {
+ // Get next line
+ String line = in.readLine();
+
+ if (line == null)
+ return;
+
+ if (line.length() > 0) {
+ // Continue lines that end in slashes if they are not comments
+ char firstChar = line.charAt(0);
+
+ if ((firstChar != '#') && (firstChar != '!')) {
+ while (continueLine(line)) {
+ String nextLine = in.readLine();
+
+ if (nextLine == null)
+ nextLine = "";
+ String loppedLine = line.substring(0, line.length() - 1);
+ // Advance beyond whitespace on new line
+ int startIndex = 0;
+
+ for (startIndex = 0; startIndex < nextLine.length(); startIndex++)
+ if (whiteSpaceChars.indexOf(nextLine.charAt(startIndex)) == -1)
+ break;
+ nextLine = nextLine.substring(startIndex, nextLine.length());
+
+ line = loppedLine + nextLine;
+ }
+ // Find start of key
+ int len = line.length();
+ int keyStart;
+
+ for (keyStart = 0; keyStart < len; keyStart++) {
+ if (whiteSpaceChars.indexOf(line.charAt(keyStart)) == -1)
+ break;
+ }
+ // Find separation between key and value
+ int separatorIndex;
+
+ for (separatorIndex = keyStart; separatorIndex < len; separatorIndex++) {
+ char currentChar = line.charAt(separatorIndex);
+
+ if (currentChar == '\\')
+ separatorIndex++;
+ else if (keyValueSeparators.indexOf(currentChar) != -1)
+ break;
+ }
+
+ // Skip over whitespace after key if any
+ int valueIndex;
+
+ for (valueIndex = separatorIndex; valueIndex < len; valueIndex++)
+ if (whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1)
+ break;
+
+ // Skip over one non whitespace key value separators if any
+ if (valueIndex < len)
+ if (strictKeyValueSeparators.indexOf(line.charAt(valueIndex)) != -1)
+ valueIndex++;
+
+ // Skip over white space after other separators if any
+ while (valueIndex < len) {
+ if (whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1)
+ break;
+ valueIndex++;
+ }
+ String key = line.substring(keyStart, separatorIndex);
+ String value = (separatorIndex < len) ? line.substring(valueIndex, len) : "";
+
+ // Convert then store key and value
+ // NETSCAPE: no need to convert escape characters
+ // key = loadConvert(key);
+ // value = loadConvert(value);
+ put(key, value);
+ }
+ }
+ }
+ }
+
+ /*
+ * Returns true if the given line is a line that must
+ * be appended to the next line
+ */
+ private boolean continueLine(String line) {
+ int slashCount = 0;
+ int index = line.length() - 1;
+
+ while ((index >= 0) && (line.charAt(index--) == '\\'))
+ slashCount++;
+ return (slashCount % 2 == 1);
+ }
+
+ /**
+ * Calls the <code>store(OutputStream out, String header)</code> method
+ * and suppresses IOExceptions that were thrown.
+ *
+ * @deprecated This method does not throw an IOException if an I/O error
+ * occurs while saving the property list. As of JDK 1.2, the preferred
+ * way to save a properties list is via the <code>store(OutputStream out,
+ * String header)</code> method.
+ *
+ * @param out an output stream.
+ * @param header a description of the property list.
+ * @exception ClassCastException if this <code>Properties</code> object
+ * contains any keys or values that are not <code>Strings</code>.
+ */
+ public synchronized void save(OutputStream out, String header) {
+ try {
+ store(out, header);
+ } catch (IOException e) {
+ }
+ }
+
+ /**
+ * Writes this property list (key and element pairs) in this <code>Properties</code> table to the output stream in a
+ * format suitable
+ * for loading into a <code>Properties</code> table using the <code>load</code> method.
+ * <p>
+ * Properties from the defaults table of this <code>Properties</code> table (if any) are <i>not</i> written out by
+ * this method.
+ * <p>
+ * If the header argument is not null, then an ASCII <code>#</code> character, the header string, and a line
+ * separator are first written to the output stream. Thus, the <code>header</code> can serve as an identifying
+ * comment.
+ * <p>
+ * Next, a comment line is always written, consisting of an ASCII <code>#</code> character, the current date and
+ * time (as if produced by the <code>toString</code> method of <code>Date</code> for the current time), and a line
+ * separator as generated by the Writer.
+ * <p>
+ * Then every entry in this <code>Properties</code> table is written out, one per line. For each entry the key
+ * string is written, then an ASCII <code>=</code>, then the associated element string. Each character of the
+ * element string is examined to see whether it should be rendered as an escape sequence. The ASCII characters
+ * <code>\</code>, tab, newline, and carriage return are written as <code>\\</code>, <code>\t</code>,
+ * <code>\n</code>, and <code>\r</code>, respectively. Characters less than <code>\u0020</code> and characters
+ * greater than <code>\u007E</code> are written as <code>\\u</code><i>xxxx</i> for the appropriate hexadecimal value
+ * <i>xxxx</i>. Space characters, but not embedded or trailing space characters, are written with a preceding
+ * <code>\</code>. The key and value characters <code>#</code>, <code>!</code>, <code>=</code>, and <code>:</code>
+ * are written with a preceding slash to ensure that they are properly loaded.
+ * <p>
+ * After the entries have been written, the output stream is flushed. The output stream remains open after this
+ * method returns.
+ *
+ * @param out an output stream.
+ * @param header a description of the property list.
+ * @exception ClassCastException if this <code>Properties</code> object
+ * contains any keys or values that are not <code>Strings</code>.
+ */
+ public synchronized void store(OutputStream out, String header)
+ throws IOException {
+ BufferedWriter awriter;
+
+ awriter = new BufferedWriter(new OutputStreamWriter(out, "8859_1"));
+ if (header != null)
+ writeln(awriter, "#" + header);
+ writeln(awriter, "#" + new Date().toString());
+ for (Enumeration<String> e = keys(); e.hasMoreElements();) {
+ String key = e.nextElement();
+ String val = get(key);
+
+ // key = saveConvert(key);
+ // val = saveConvert(val);
+ writeln(awriter, key + "=" + val);
+ }
+ awriter.flush();
+ }
+
+ private static void writeln(BufferedWriter bw, String s) throws IOException {
+ bw.write(s);
+ bw.newLine();
+ }
+
+ /**
+ * Searches for the property with the specified key in this property list.
+ * If the key is not found in this property list, the default property list,
+ * and its defaults, recursively, are then checked. The method returns <code>null</code> if the property is not
+ * found.
+ *
+ * @param key the property key.
+ * @return the value in this property list with the specified key value.
+ * @see java.util.Properties#defaults
+ */
+ public synchronized String getProperty(String key) {
+ String oval = super.get(key);
+
+ return ((oval == null) && (defaults != null)) ? defaults.getProperty(key) : oval;
+ }
+
+ /**
+ * Searches for the property with the specified key in this property list.
+ * If the key is not found in this property list, the default property list,
+ * and its defaults, recursively, are then checked. The method returns the
+ * default value argument if the property is not found.
+ *
+ * @param key the hashtable key.
+ * @param defaultValue a default value.
+ *
+ * @return the value in this property list with the specified key value.
+ * @see java.util.Properties#defaults
+ */
+ public synchronized String getProperty(String key, String defaultValue) {
+ String val = getProperty(key);
+
+ return (val == null) ? defaultValue : val;
+ }
+
+ /**
+ * Returns an enumeration of all the keys in this property list, including
+ * the keys in the default property list.
+ *
+ * @return an enumeration of all the keys in this property list, including
+ * the keys in the default property list.
+ * @see java.util.Enumeration
+ * @see java.util.Properties#defaults
+ */
+ public Enumeration<String> propertyNames() {
+ Hashtable<String, String> h = new Hashtable<String, String>();
+
+ enumerate(h);
+ return h.keys();
+ }
+
+ /**
+ * Prints this property list out to the specified output stream.
+ * This method is useful for debugging.
+ *
+ * @param out an output stream.
+ */
+ public void list(PrintStream out) {
+ out.println("-- listing properties --");
+ Hashtable<String, String> h = new Hashtable<String, String>();
+
+ enumerate(h);
+ for (Enumeration<String> e = h.keys(); e.hasMoreElements();) {
+ String key = e.nextElement();
+ String val = h.get(key);
+
+ if (val.length() > 40) {
+ val = val.substring(0, 37) + "...";
+ }
+ out.println(key + "=" + val);
+ }
+ }
+
+ /**
+ * Prints this property list out to the specified output stream.
+ * This method is useful for debugging.
+ *
+ * @param out an output stream.
+ * @since JDK1.1
+ */
+
+ /*
+ * Rather than use an anonymous inner class to share common code, this
+ * method is duplicated in order to ensure that a non-1.1 compiler can
+ * compile this file.
+ */
+ public void list(PrintWriter out) {
+ out.println("-- listing properties --");
+ Hashtable<String, String> h = new Hashtable<String, String>();
+
+ enumerate(h);
+ for (Enumeration<String> e = h.keys(); e.hasMoreElements();) {
+ String key = e.nextElement();
+ String val = h.get(key);
+
+ if (val.length() > 40) {
+ val = val.substring(0, 37) + "...";
+ }
+ out.println(key + "=" + val);
+ }
+ }
+
+ /**
+ * Enumerates all key/value pairs in the specified hastable.
+ *
+ * @param h the hashtable
+ */
+ private synchronized void enumerate(Hashtable<String, String> h) {
+ if (defaults != null) {
+ defaults.enumerate(h);
+ }
+ for (Enumeration<String> e = keys(); e.hasMoreElements();) {
+ String key = e.nextElement();
+
+ h.put(key, get(key));
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((defaults == null) ? 0 : defaults.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ SimpleProperties other = (SimpleProperties) obj;
+ if (defaults == null) {
+ if (other.defaults != null)
+ return false;
+ } else if (!defaults.equals(other.defaults))
+ return false;
+ return true;
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/base/SourceConfigStore.java b/base/server/cmscore/src/com/netscape/cmscore/base/SourceConfigStore.java
new file mode 100644
index 000000000..546b97591
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/base/SourceConfigStore.java
@@ -0,0 +1,59 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.base;
+
+import com.netscape.certsrv.base.ISourceConfigStore;
+
+/**
+ * This class is is a wrapper to hide the Properties methods from
+ * the PropConfigStore. Lucky for us, Properties already implements
+ * almost every thing ISourceConfigStore requires.
+ *
+ * @version $Revision$, $Date$
+ * @see java.util.Properties
+ */
+public class SourceConfigStore extends SimpleProperties implements ISourceConfigStore {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1703553593020810628L;
+
+ /**
+ * Retrieves a property from the config store
+ * <P>
+ *
+ * @param name property name
+ * @return property value
+ */
+ public String get(String name) {
+ return super.get(name); // from Properties->Hashtable
+ }
+
+ /**
+ * Puts a property into the config store.
+ * <P>
+ *
+ * @param name property name
+ * @param value property value
+ * @return
+ */
+ public String put(String name, String value) {
+ return super.put(name, value); // from Properties->Hashtable
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/base/SubsystemLoader.java b/base/server/cmscore/src/com/netscape/cmscore/base/SubsystemLoader.java
new file mode 100644
index 000000000..8cd2990a1
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/base/SubsystemLoader.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.base;
+
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+
+/**
+ * A class represents a subsystem loader.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class SubsystemLoader {
+
+ private static final String PROP_SUBSYSTEM = "subsystem";
+ private static final String PROP_CLASSNAME = "class";
+ private static final String PROP_ID = "id";
+
+ public static Vector<ISubsystem> load(IConfigStore config) throws EBaseException {
+ Vector<ISubsystem> v = new Vector<ISubsystem>();
+
+ // load a list of installable subsystems (services)
+ for (int i = 0;; i++) {
+ IConfigStore c = config.getSubStore(PROP_SUBSYSTEM + i);
+
+ if (c == null)
+ break;
+ String id = null;
+
+ try {
+ id = c.getString(PROP_ID, null);
+ if (id == null)
+ break;
+ } catch (EBaseException e) {
+ break;
+ }
+ String className = c.getString(PROP_CLASSNAME, null);
+
+ if (className == null)
+ break;
+ try {
+ ISubsystem sub = (ISubsystem) Class.forName(
+ className).newInstance();
+
+ sub.setId(id);
+ v.addElement(sub);
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_LOAD_FAILED", className));
+ }
+ }
+ return v;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/base/SubsystemRegistry.java b/base/server/cmscore/src/com/netscape/cmscore/base/SubsystemRegistry.java
new file mode 100644
index 000000000..adae60496
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/base/SubsystemRegistry.java
@@ -0,0 +1,43 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.base;
+
+import java.util.Hashtable;
+
+import com.netscape.certsrv.base.ISubsystem;
+
+public class SubsystemRegistry extends Hashtable<String, ISubsystem> {
+ private static final long serialVersionUID = 7801949114531559118L;
+ private static SubsystemRegistry mInstance = null;
+
+ public static SubsystemRegistry getInstance() {
+ if (mInstance == null) {
+ mInstance = new SubsystemRegistry();
+ }
+ return mInstance;
+ }
+
+ private SubsystemRegistry() {
+ super();
+ }
+
+ public ISubsystem get(String key) {
+ return super.get(key);
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/cert/CertDateCompare.java b/base/server/cmscore/src/com/netscape/cmscore/cert/CertDateCompare.java
new file mode 100644
index 000000000..c39db40d0
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/cert/CertDateCompare.java
@@ -0,0 +1,55 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.cert;
+
+import java.util.Comparator;
+import java.util.Date;
+
+import netscape.security.x509.X509CertImpl;
+
+/**
+ * Compares validity dates for use in sorting.
+ *
+ * @author kanda
+ * @version $Revision$, $Date$
+ */
+public class CertDateCompare implements Comparator<X509CertImpl>, java.io.Serializable {
+
+ private static final long serialVersionUID = -1784015027375808580L;
+
+ public CertDateCompare() {
+ }
+
+ public int compare(X509CertImpl cert1, X509CertImpl cert2) {
+ Date d1 = null;
+ Date d2 = null;
+
+ try {
+ d1 = cert1.getNotAfter();
+ d2 = cert2.getNotAfter();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if (d1 == d2)
+ return 0;
+ if (d1.after(d2))
+ return 1;
+ else
+ return -1;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/cert/CertPrettyPrint.java b/base/server/cmscore/src/com/netscape/cmscore/cert/CertPrettyPrint.java
new file mode 100644
index 000000000..ecd1a4a60
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/cert/CertPrettyPrint.java
@@ -0,0 +1,36 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.cert;
+
+import java.security.cert.Certificate;
+
+import com.netscape.certsrv.base.ICertPrettyPrint;
+
+/**
+ * This class will display the certificate content in predefined
+ * format.
+ *
+ * @author Jack Pan-Chen
+ * @version $Revision$, $Date$
+ */
+public class CertPrettyPrint extends netscape.security.util.CertPrettyPrint implements ICertPrettyPrint {
+
+ public CertPrettyPrint(Certificate cert) {
+ super(cert);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/cert/CertUtils.java b/base/server/cmscore/src/com/netscape/cmscore/cert/CertUtils.java
new file mode 100644
index 000000000..9dc33e541
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/cert/CertUtils.java
@@ -0,0 +1,1121 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.cert;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.StringTokenizer;
+
+import netscape.security.extensions.NSCertTypeExtension;
+import netscape.security.pkcs.PKCS10;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.util.DerInputStream;
+import netscape.security.util.DerOutputStream;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateIssuerName;
+import netscape.security.x509.CertificateSerialNumber;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CRLImpl;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.CertificateUsage;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Utility class with assorted methods to check for
+ * smime pairs, determining the type of cert - signature
+ * or encryption ..etc.
+ *
+ * @author kanda
+ * @version $Revision$, $Date$
+ */
+public class CertUtils {
+ public static final String CERT_NEW_REQUEST_HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----";
+ public static final String CERT_NEW_REQUEST_TRAILER = "-----END NEW CERTIFICATE REQUEST-----";
+ public static final String CERT_REQUEST_HEADER = "-----BEGIN CERTIFICATE REQUEST-----";
+ public static final String CERT_REQUEST_TRAILER = "-----END CERTIFICATE REQUEST-----";
+ public static final String CERT_RENEWAL_HEADER = "-----BEGIN RENEWAL CERTIFICATE REQUEST-----";
+ public static final String CERT_RENEWAL_TRAILER = "-----END RENEWAL CERTIFICATE REQUEST-----";
+ public static final String BEGIN_CRL_HEADER =
+ "-----BEGIN CERTIFICATE REVOCATION LIST-----";
+ public static final String END_CRL_HEADER =
+ "-----END CERTIFICATE REVOCATION LIST-----";
+
+ protected static ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+ private final static String LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION =
+ "LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION_3";
+
+ /**
+ * Remove the header and footer in the PKCS10 request.
+ */
+ public static String unwrapPKCS10(String request, boolean checkHeader)
+ throws EBaseException {
+ String unwrapped;
+ String header = null;
+ int head = -1;
+ int trail = -1;
+
+ // check for "-----BEGIN NEW CERTIFICATE REQUEST-----";
+ if (header == null) {
+ head = request.indexOf(CERT_NEW_REQUEST_HEADER);
+ trail = request.indexOf(CERT_NEW_REQUEST_TRAILER);
+
+ if (!(head == -1 && trail == -1)) {
+ header = CERT_NEW_REQUEST_HEADER;
+ }
+ }
+
+ // check for "-----BEGIN CERTIFICATE REQUEST-----";
+ if (header == null) {
+ head = request.indexOf(CERT_REQUEST_HEADER);
+ trail = request.indexOf(CERT_REQUEST_TRAILER);
+
+ // If this is not a request header, check if this is a renewal header.
+ if (!(head == -1 && trail == -1)) {
+ header = CERT_REQUEST_HEADER;
+
+ }
+ }
+
+ // check for "-----BEGIN RENEWAL CERTIFICATE REQUEST-----";
+ if (header == null) {
+ head = request.indexOf(CERT_RENEWAL_HEADER);
+ trail = request.indexOf(CERT_RENEWAL_TRAILER);
+ if (!(head == -1 && trail == -1)) {
+ header = CERT_RENEWAL_HEADER;
+ }
+ }
+
+ // Now validate if any headers or trailers are in place
+ if (head == -1 && checkHeader) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_MISSING_PKCS10_HEADER"));
+ }
+ if (trail == -1 && checkHeader) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_MISSING_PKCS10_TRAILER"));
+ }
+
+ if (header != null) {
+ unwrapped = request.substring(head + header.length(), trail);
+ } else {
+ unwrapped = request;
+ }
+
+ // strip all the crtl-characters (i.e. \r\n)
+ StringTokenizer st = new StringTokenizer(unwrapped, "\t\r\n ");
+ StringBuffer stripped = new StringBuffer();
+
+ while (st.hasMoreTokens()) {
+ stripped.append(st.nextToken());
+ }
+
+ return stripped.toString();
+ }
+
+ public static PKCS10 decodePKCS10(String req) throws EBaseException {
+ String normalized = unwrapPKCS10(req, true);
+ PKCS10 pkcs10 = null;
+
+ try {
+ byte[] decodedBytes = Utils.base64decode(normalized);
+
+ pkcs10 = new PKCS10(decodedBytes);
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ }
+ return pkcs10;
+ }
+
+ public static void setRSAKeyToCertInfo(X509CertInfo info,
+ byte encoded[]) throws EBaseException {
+ try {
+ if (info == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION"));
+ }
+ X509Key key = new X509Key(AlgorithmId.get("RSAEncryption"), encoded);
+
+ info.set(X509CertInfo.KEY, key);
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION"));
+ }
+ }
+
+ public static X509CertInfo createCertInfo(int ver,
+ BigInteger serialno, String alg, String issuerName,
+ Date notBefore, Date notAfter) throws EBaseException {
+ try {
+ X509CertInfo info = new X509CertInfo();
+
+ info.set(X509CertInfo.VERSION, new CertificateVersion(ver));
+ info.set(X509CertInfo.SERIAL_NUMBER, new
+ CertificateSerialNumber(serialno));
+ info.set(X509CertInfo.ALGORITHM_ID, new
+ CertificateAlgorithmId(AlgorithmId.get(alg)));
+ info.set(X509CertInfo.ISSUER, new
+ CertificateIssuerName(new X500Name(issuerName)));
+ info.set(X509CertInfo.VALIDITY, new
+ CertificateValidity(notBefore, notAfter));
+ return info;
+ } catch (Exception e) {
+ System.out.println(e.toString());
+ return null;
+ }
+ }
+
+ public static void sortCerts(X509CertImpl[] arr) {
+ Arrays.sort(arr, new CertDateCompare());
+ }
+
+ public static boolean isSigningCert(X509CertImpl cert) {
+ boolean[] keyUsage = null;
+
+ try {
+ keyUsage = cert.getKeyUsage();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return (keyUsage == null) ? false : keyUsage[0];
+ }
+
+ public static boolean isEncryptionCert(X509CertImpl cert) {
+ boolean[] keyUsage = null;
+
+ try {
+ keyUsage = cert.getKeyUsage();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if (keyUsage == null)
+ return false;
+ if (keyUsage.length < 3)
+ return false;
+ else if (keyUsage.length == 3)
+ return keyUsage[2];
+ else
+ return keyUsage[2] || keyUsage[3];
+ }
+
+ public static boolean haveSameValidityPeriod(X509CertImpl cert1,
+ X509CertImpl cert2) {
+ long notBefDiff = 0;
+ long notAfterDiff = 0;
+
+ try {
+ notBefDiff = Math.abs(cert1.getNotBefore().getTime() -
+ cert2.getNotBefore().getTime());
+ notAfterDiff = Math.abs(cert1.getNotAfter().getTime() -
+ cert2.getNotAfter().getTime());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if (notBefDiff > 1000 || notAfterDiff > 1000)
+ return false;
+ else
+ return true;
+ }
+
+ public static boolean isSmimePair(X509CertImpl cert1, X509CertImpl cert2, boolean matchSubjectDN) {
+ // Check for subjectDN equality.
+ if (matchSubjectDN) {
+ String dn1 = cert1.getSubjectDN().toString();
+ String dn2 = cert2.getSubjectDN().toString();
+
+ if (!sameSubjectDN(dn1, dn2))
+ return false;
+ }
+
+ // Check for the presence of signing and encryption certs.
+ boolean hasSigningCert = isSigningCert(cert1) || isSigningCert(cert2);
+
+ if (!hasSigningCert)
+ return false;
+
+ boolean hasEncryptionCert = isEncryptionCert(cert1) || isEncryptionCert(cert2);
+
+ if (!hasEncryptionCert)
+ return false;
+
+ // If both certs have signing & encryption usage set, they are
+ // not really pairs.
+ if ((isSigningCert(cert1) && isEncryptionCert(cert1)) ||
+ (isSigningCert(cert2) && isEncryptionCert(cert2)))
+ return false;
+
+ // See if the certs have the same validity.
+ boolean haveSameValidity =
+ haveSameValidityPeriod(cert1, cert2);
+
+ return haveSameValidity;
+ }
+
+ public static boolean isNotYetValidCert(X509CertImpl cert) {
+ boolean ret = false;
+
+ try {
+ cert.checkValidity();
+ } catch (CertificateExpiredException e) {
+ } catch (CertificateNotYetValidException e) {
+ ret = true;
+ } catch (Exception e) {
+ }
+ return ret;
+ }
+
+ public static boolean isValidCert(X509CertImpl cert) {
+ boolean ret = true;
+
+ try {
+ cert.checkValidity();
+ } catch (Exception e) {
+ ret = false;
+ }
+ return ret;
+ }
+
+ public static boolean isExpiredCert(X509CertImpl cert) {
+ boolean ret = false;
+
+ try {
+ cert.checkValidity();
+ } catch (CertificateExpiredException e) {
+ ret = true;
+ } catch (Exception e) {
+ }
+ return ret;
+ }
+
+ public static boolean sameSubjectDN(String dn1, String dn2) {
+ boolean ret = false;
+
+ // The dn cannot be null.
+ if (dn1 == null || dn2 == null)
+ return false;
+ try {
+ X500Name n1 = new X500Name(dn1);
+ X500Name n2 = new X500Name(dn2);
+
+ ret = n1.equals(n2);
+ } catch (Exception e) {
+ }
+ return ret;
+ }
+
+ public static String getValidCertsDisplayInfo(String cn, X509CertImpl[] validCerts) {
+ StringBuffer sb = new StringBuffer(1024);
+
+ sb.append(cn + "'s Currently Valid Certificates\n\n");
+ sb.append(getCertsDisplayInfo(validCerts));
+ return new String(sb);
+ }
+
+ public static String getExpiredCertsDisplayInfo(String cn, X509CertImpl[] expiredCerts) {
+ StringBuffer sb = new StringBuffer(1024);
+
+ sb.append(cn + "'s Expired Certificates\n\n");
+ sb.append(getCertsDisplayInfo(expiredCerts));
+ return new String(sb);
+ }
+
+ public static String getRenewedCertsDisplayInfo(String cn,
+ X509CertImpl[] validCerts, X509CertImpl[] renewedCerts) {
+ StringBuffer sb = new StringBuffer(1024);
+
+ if (validCerts != null) {
+ sb.append(cn + "'s Currently Valid Certificates\n\n");
+ sb.append(getCertsDisplayInfo(validCerts));
+ sb.append("\n\nRenewed Certificates\n\n\n");
+ } else
+ sb.append(cn + "'s Renewed Certificates\n\n");
+ sb.append(getCertsDisplayInfo(renewedCerts));
+ return new String(sb);
+ }
+
+ public static String getCertsDisplayInfo(X509CertImpl[] validCerts) {
+ // We assume that the given pair is a valid S/MIME pair.
+ StringBuffer sb = new StringBuffer(1024);
+
+ sb.append("Subject DN: " + validCerts[0].getSubjectDN().toString());
+ sb.append("\n");
+ X509CertImpl signingCert, encryptionCert;
+
+ if (isSigningCert(validCerts[0])) {
+ signingCert = validCerts[0];
+ encryptionCert = validCerts[1];
+ } else {
+ signingCert = validCerts[1];
+ encryptionCert = validCerts[0];
+ }
+ sb.append("Signing Certificate Serial No: " + signingCert.getSerialNumber().toString(16).toUpperCase());
+ sb.append("\n");
+ sb.append("Encryption Certificate Serial No: " + encryptionCert.getSerialNumber().toString(16).toUpperCase());
+ sb.append("\n");
+ sb.append("Validity: From: "
+ + signingCert.getNotBefore().toString() + " To: " + signingCert.getNotAfter().toString());
+ sb.append("\n");
+ return new String(sb);
+ }
+
+ /**
+ * Returns the index of the given cert in an array of certs.
+ *
+ * Assumptions: The certs are issued by the same CA
+ *
+ * @param certArray The array of certs.
+ * @param givenCert The certificate we are lokking for in the array.
+ * @return -1 if not found or the index of the given cert in the array.
+ */
+ public static int getCertIndex(X509CertImpl[] certArray, X509CertImpl givenCert) {
+ int i = 0;
+
+ for (; i < certArray.length; i++) {
+ if (certArray[i].getSerialNumber().equals(
+ givenCert.getSerialNumber())) {
+ break;
+ }
+ }
+
+ return ((i == certArray.length) ? -1 : i);
+ }
+
+ /**
+ * Returns the most recently issued signing certificate from an
+ * an array of certs.
+ *
+ * Assumptions: The certs are issued by the same CA
+ *
+ * @param certArray The array of certs.
+ * @param givenCert The certificate we are lokking for in the array.
+ * @return null if there is no recent cert or the most recent cert.
+ */
+ public static X509CertImpl getRecentSigningCert(X509CertImpl[] certArray,
+ X509CertImpl currentCert) {
+ if (certArray == null || currentCert == null)
+ return null;
+
+ // Sort the certificate array.
+ Arrays.sort(certArray, new CertDateCompare());
+
+ // Get the index of the current cert in the array.
+ int i = getCertIndex(certArray, currentCert);
+
+ if (i < 0)
+ return null;
+
+ X509CertImpl recentCert = currentCert;
+
+ for (; i < certArray.length; i++) {
+ // Check if it is a signing cert and has its
+ // NotAfter later than the current cert.
+ if (isSigningCert(certArray[i]) &&
+ certArray[i].getNotAfter().after(recentCert.getNotAfter()))
+ recentCert = certArray[i];
+ }
+ return ((recentCert == currentCert) ? null : recentCert);
+ }
+
+ public static String getCertType(X509CertImpl cert) throws CertificateParsingException, IOException {
+ StringBuffer sb = new StringBuffer();
+
+ if (isSigningCert(cert))
+ sb.append("signing");
+ if (isEncryptionCert(cert)) {
+ if (sb.length() > 0)
+ sb.append(" ");
+ sb.append("encryption");
+ }
+
+ // Is is object signing cert?
+ CertificateExtensions extns = (CertificateExtensions)
+ cert.get(X509CertImpl.NAME + "." +
+ X509CertImpl.INFO + "." +
+ X509CertInfo.EXTENSIONS);
+
+ if (extns != null) {
+ NSCertTypeExtension nsExtn = (NSCertTypeExtension)
+ extns.get(NSCertTypeExtension.NAME);
+
+ if (nsExtn != null) {
+ String nsType = getNSExtensionInfo(nsExtn);
+
+ if (nsType != null) {
+ if (sb.length() > 0)
+ sb.append(" ");
+ sb.append(nsType);
+ }
+ }
+ }
+ return (sb.length() > 0) ? sb.toString() : null;
+ }
+
+ public static String getNSExtensionInfo(NSCertTypeExtension nsExtn) {
+ StringBuffer sb = new StringBuffer();
+
+ try {
+ Boolean res;
+
+ res = (Boolean) nsExtn.get(NSCertTypeExtension.SSL_CLIENT);
+ if (res.equals(Boolean.TRUE))
+ sb.append(" ssl_client");
+ res = (Boolean) nsExtn.get(NSCertTypeExtension.SSL_SERVER);
+ if (res.equals(Boolean.TRUE))
+ sb.append(" ssl_server");
+ res = (Boolean) nsExtn.get(NSCertTypeExtension.EMAIL);
+ if (res.equals(Boolean.TRUE))
+ sb.append(" email");
+ res = (Boolean) nsExtn.get(NSCertTypeExtension.OBJECT_SIGNING);
+ if (res.equals(Boolean.TRUE))
+ sb.append(" object_signing");
+ res = (Boolean) nsExtn.get(NSCertTypeExtension.SSL_CA);
+ if (res.equals(Boolean.TRUE))
+ sb.append(" ssl_CA");
+ res = (Boolean) nsExtn.get(NSCertTypeExtension.EMAIL_CA);
+ if (res.equals(Boolean.TRUE))
+ sb.append(" email_CA");
+ res = (Boolean) nsExtn.get(NSCertTypeExtension.OBJECT_SIGNING_CA);
+ if (res.equals(Boolean.TRUE))
+ sb.append(" object_signing_CA");
+ } catch (Exception e) {
+ }
+
+ return (sb.length() > 0) ? sb.toString() : null;
+ }
+
+ public static byte[] readFromFile(String fileName)
+ throws IOException {
+ FileInputStream fin = null;
+ try {
+ fin = new FileInputStream(fileName);
+ int available = fin.available();
+ byte[] ba = new byte[available];
+ int nRead = fin.read(ba);
+
+ if (nRead != available)
+ throw new IOException("Error reading data from file: " + fileName);
+
+ return ba;
+ } finally {
+ if (fin != null)
+ fin.close();
+ }
+ }
+
+ public static void storeInFile(String fileName, byte[] ba)
+ throws IOException {
+ FileOutputStream fout = null;
+ try {
+ fout = new FileOutputStream(fileName);
+
+ fout.write(ba);
+ } finally {
+ if (fout != null)
+ fout.close();
+ }
+ }
+
+ public static String toMIME64(X509CertImpl cert) {
+ try {
+ return "-----BEGIN CERTIFICATE-----\n" +
+ Utils.base64encode(cert.getEncoded()) +
+ "-----END CERTIFICATE-----\n";
+ } catch (CertificateException e) {
+ }
+ return null;
+ }
+
+ public static X509Certificate mapCert(String mime64)
+ throws IOException {
+ mime64 = stripCertBrackets(mime64.trim());
+ String newval = normalizeCertStr(mime64);
+ byte rawPub[] = Utils.base64decode(newval);
+ X509Certificate cert = null;
+
+ try {
+ cert = new X509CertImpl(rawPub);
+ } catch (CertificateException e) {
+ }
+ return cert;
+ }
+
+ public static X509Certificate[] mapCertFromPKCS7(String mime64)
+ throws IOException {
+ mime64 = stripCertBrackets(mime64.trim());
+ String newval = normalizeCertStr(mime64);
+ byte rawPub[] = Utils.base64decode(newval);
+ PKCS7 p7 = null;
+
+ try {
+ p7 = new PKCS7(rawPub);
+ return p7.getCertificates();
+ } catch (Exception e) {
+ throw new IOException(e.toString());
+ }
+ }
+
+ public static X509CRL mapCRL(String mime64)
+ throws IOException {
+ mime64 = stripCRLBrackets(mime64.trim());
+ String newval = normalizeCertStr(mime64);
+ byte rawPub[] = Utils.base64decode(newval);
+ X509CRL crl = null;
+
+ try {
+ crl = new X509CRLImpl(rawPub);
+ } catch (Exception e) {
+ }
+ return crl;
+ }
+
+ public static X509CRL mapCRL1(String mime64)
+ throws IOException {
+ mime64 = stripCRLBrackets(mime64.trim());
+ byte rawPub[] = Utils.base64decode(mime64);
+ X509CRL crl = null;
+
+ try {
+ crl = new X509CRLImpl(rawPub);
+ } catch (Exception e) {
+ throw new IOException(e.toString());
+ }
+ return crl;
+ }
+
+ public static String normalizeCertStr(String s) {
+ StringBuffer val = new StringBuffer();
+
+ for (int i = 0; i < s.length(); i++) {
+ if (s.charAt(i) == '\n') {
+ continue;
+ } else if (s.charAt(i) == '\r') {
+ continue;
+ } else if (s.charAt(i) == '"') {
+ continue;
+ } else if (s.charAt(i) == ' ') {
+ continue;
+ }
+ val.append(s.charAt(i));
+ }
+ return val.toString();
+ }
+
+ public static String stripCRLBrackets(String s) {
+ if (s == null) {
+ return s;
+ }
+ if ((s.startsWith("-----BEGIN CERTIFICATE REVOCATION LIST-----")) &&
+ (s.endsWith("-----END CERTIFICATE REVOCATION LIST-----"))) {
+ return (s.substring(43, (s.length() - 41)));
+ }
+ return s;
+ }
+
+ /**
+ * strips out the begin and end certificate brackets
+ *
+ * @param s the string potentially bracketed with
+ * "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----"
+ * @return string without the brackets
+ */
+ public static String stripCertBrackets(String s) {
+ if (s == null) {
+ return s;
+ }
+
+ if ((s.startsWith("-----BEGIN CERTIFICATE-----")) &&
+ (s.endsWith("-----END CERTIFICATE-----"))) {
+ return (s.substring(27, (s.length() - 25)));
+ }
+
+ // To support Thawte's header and footer
+ if ((s.startsWith("-----BEGIN PKCS #7 SIGNED DATA-----")) &&
+ (s.endsWith("-----END PKCS #7 SIGNED DATA-----"))) {
+ return (s.substring(35, (s.length() - 33)));
+ }
+
+ return s;
+ }
+
+ /**
+ * Returns a string that represents a cert's fingerprint.
+ * The fingerprint is a MD5 digest of the DER encoded certificate.
+ *
+ * @param cert Certificate to get the fingerprint of.
+ * @return a String that represents the cert's fingerprint.
+ */
+ public static String getFingerPrint(Certificate cert)
+ throws CertificateEncodingException, NoSuchAlgorithmException {
+ byte certDer[] = cert.getEncoded();
+ MessageDigest md = MessageDigest.getInstance("MD5");
+
+ md.update(certDer);
+ byte digestedCert[] = md.digest();
+ PrettyPrintFormat pp = new PrettyPrintFormat(":");
+ StringBuffer sb = new StringBuffer();
+
+ sb.append(pp.toHexString(digestedCert, 4, 20));
+ return sb.toString();
+ }
+
+ /**
+ * Returns a string that has the certificate's fingerprint using
+ * MD5, MD2 and SHA1 hashes.
+ * A certificate's fingerprint is a hash digest of the DER encoded
+ * certificate.
+ *
+ * @param cert Certificate to get the fingerprints of.
+ * @return a String with fingerprints using the MD5, MD2 and SHA1 hashes.
+ * For example,
+ *
+ * <pre>
+ * MD2: 78:7E:D1:F9:3E:AF:50:18:68:A7:29:50:C3:21:1F:71
+ *
+ * MD5: 0E:89:91:AC:40:50:F7:BE:6E:7B:39:4F:56:73:75:75
+ *
+ * SHA1: DC:D9:F7:AF:E2:83:10:B2:F7:0A:77:E8:50:E2:F7:D1:15:9A:9D:00
+ * </pre>
+ */
+ public static String getFingerPrints(Certificate cert)
+ throws NoSuchAlgorithmException, CertificateEncodingException {
+ byte certDer[] = cert.getEncoded();
+ /*
+ String[] hashes = new String[] {"MD2", "MD5", "SHA1"};
+ String certFingerprints = "";
+ PrettyPrintFormat pp = new PrettyPrintFormat(":");
+
+ for (int i = 0; i < hashes.length; i++) {
+ MessageDigest md = MessageDigest.getInstance(hashes[i]);
+
+ md.update(certDer);
+ certFingerprints += " " + hashes[i] + ":" +
+ pp.toHexString(md.digest(), 6 - hashes[i].length());
+ }
+ return certFingerprints;
+ */
+ return getFingerPrints(certDer);
+ }
+
+ /**
+ * Returns a string that has the certificate's fingerprint using
+ * MD5, MD2 and SHA1 hashes.
+ * A certificate's fingerprint is a hash digest of the DER encoded
+ * certificate.
+ *
+ * @param cert Certificate to get the fingerprints of.
+ * @return a String with fingerprints using the MD5, MD2 and SHA1 hashes.
+ * For example,
+ *
+ * <pre>
+ * MD2: 78:7E:D1:F9:3E:AF:50:18:68:A7:29:50:C3:21:1F:71
+ *
+ * MD5: 0E:89:91:AC:40:50:F7:BE:6E:7B:39:4F:56:73:75:75
+ *
+ * SHA1: DC:D9:F7:AF:E2:83:10:B2:F7:0A:77:E8:50:E2:F7:D1:15:9A:9D:00
+ * </pre>
+ */
+ public static String getFingerPrints(byte[] certDer)
+ throws NoSuchAlgorithmException/*, CertificateEncodingException*/{
+ // byte certDer[] = cert.getEncoded();
+ String[] hashes = new String[] { "MD2", "MD5", "SHA1", "SHA256", "SHA512" };
+ StringBuffer certFingerprints = new StringBuffer();
+ PrettyPrintFormat pp = new PrettyPrintFormat(":");
+
+ for (int i = 0; i < hashes.length; i++) {
+ MessageDigest md = MessageDigest.getInstance(hashes[i]);
+
+ md.update(certDer);
+ certFingerprints.append(hashes[i] + ":\n" +
+ pp.toHexString(md.digest(), 8, 16));
+ }
+ return certFingerprints.toString();
+ }
+
+ /**
+ * Check if a object identifier in string form is valid,
+ * that is a string in the form n.n.n.n and der encode and decode-able.
+ *
+ * @param attrName attribute name (from the configuration file)
+ * @param value object identifier string.
+ */
+ public static ObjectIdentifier checkOID(String attrName, String value)
+ throws EBaseException {
+ String msg = "value must be a object identifier in the form n.n.n.n";
+ String msg1 = "not a valid object identifier.";
+ ObjectIdentifier oid;
+
+ try {
+ oid = ObjectIdentifier.getObjectIdentifier(value);
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ attrName, msg));
+ }
+
+ // if the OID isn't valid (ex. n.n) the error isn't caught til
+ // encoding time leaving a bad request in the request queue.
+ DerOutputStream derOut = null;
+ try {
+ derOut = new DerOutputStream();
+
+ derOut.putOID(oid);
+ new ObjectIdentifier(new DerInputStream(derOut.toByteArray()));
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ attrName, msg1));
+ } finally {
+ try {
+ derOut.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return oid;
+ }
+
+ public static String trimB64E(String b64e) {
+ StringBuffer tmp = new StringBuffer("");
+ String line = null;
+ StringTokenizer tokens = new StringTokenizer(b64e, "\n");
+
+ while (tokens.hasMoreTokens()) {
+ line = tokens.nextToken();
+ line = line.trim();
+ tmp.append(line.trim());
+ if (tokens.hasMoreTokens())
+ tmp.append("\n");
+ }
+
+ return tmp.toString();
+ }
+
+ /*
+ * verify a certificate by its nickname
+ * returns true if it verifies; false if any not
+ */
+ public static boolean verifySystemCertByNickname(String nickname, String certusage) {
+ boolean r = true;
+ CertificateUsage cu = null;
+ cu = getCertificateUsage(certusage);
+ int ccu = 0;
+
+ if (cu == null) {
+ CMS.debug("CertUtils: verifySystemCertByNickname() failed: " +
+ nickname + " with unsupported certusage =" + certusage);
+ return false;
+ }
+
+ if (certusage == null || certusage.equals(""))
+ CMS.debug("CertUtils: verifySystemCertByNickname(): required certusage not defined, getting current certusage");
+ CMS.debug("CertUtils: verifySystemCertByNickname(): calling isCertValid()");
+ try {
+ CryptoManager cm = CryptoManager.getInstance();
+ if (cu.getUsage() != CryptoManager.CertificateUsage.CheckAllUsages.getUsage()) {
+ if (cm.isCertValid(nickname, true, cu)) {
+ r = true;
+ CMS.debug("CertUtils: verifySystemCertByNickname() passed:" + nickname);
+ } else {
+ CMS.debug("CertUtils: verifySystemCertByNickname() failed:" + nickname);
+ r = false;
+ }
+ } else {
+ // find out about current cert usage
+ ccu = cm.isCertValid(nickname, true);
+ if (ccu == CertificateUsage.basicCertificateUsages) {
+ /* cert is good for nothing */
+ r = false;
+ CMS.debug("CertUtils: verifySystemCertByNickname() failed: cert is good for nothing:" + nickname);
+ } else {
+ r = true;
+ CMS.debug("CertUtils: verifySystemCertByNickname() passed:" + nickname);
+
+ if ((ccu & CryptoManager.CertificateUsage.SSLServer.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is SSLServer");
+ if ((ccu & CryptoManager.CertificateUsage.SSLClient.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is SSLClient");
+ if ((ccu & CryptoManager.CertificateUsage.SSLServerWithStepUp.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is SSLServerWithStepUp");
+ if ((ccu & CryptoManager.CertificateUsage.SSLCA.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is SSLCA");
+ if ((ccu & CryptoManager.CertificateUsage.EmailSigner.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is EmailSigner");
+ if ((ccu & CryptoManager.CertificateUsage.EmailRecipient.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is EmailRecipient");
+ if ((ccu & CryptoManager.CertificateUsage.ObjectSigner.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is ObjectSigner");
+ if ((ccu & CryptoManager.CertificateUsage.UserCertImport.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is UserCertImport");
+ if ((ccu & CryptoManager.CertificateUsage.VerifyCA.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is VerifyCA");
+ if ((ccu & CryptoManager.CertificateUsage.ProtectedObjectSigner.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is ProtectedObjectSigner");
+ if ((ccu & CryptoManager.CertificateUsage.StatusResponder.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is StatusResponder");
+ if ((ccu & CryptoManager.CertificateUsage.AnyCA.getUsage()) != 0)
+ CMS.debug("CertUtils: verifySystemCertByNickname(): cert is AnyCA");
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("CertUtils: verifySystemCertByNickname() failed: " +
+ e.toString());
+ r = false;
+ }
+ return r;
+ }
+
+ /*
+ * verify a certificate by its tag name
+ * returns true if it verifies; false if any not
+ */
+ public static boolean verifySystemCertByTag(String tag) {
+ String auditMessage = null;
+ IConfigStore config = CMS.getConfigStore();
+ boolean r = true;
+ try {
+ String subsysType = config.getString("cs.type", "");
+ if (subsysType.equals("")) {
+ CMS.debug("CertUtils: verifySystemCertByTag() cs.type not defined in CS.cfg. System certificates verification not done");
+ r = false;
+ }
+ subsysType = toLowerCaseSubsystemType(subsysType);
+ if (subsysType == null) {
+ CMS.debug("CertUtils: verifySystemCerts() invalid cs.type in CS.cfg. System certificates verification not done");
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ "");
+
+ audit(auditMessage);
+ r = false;
+ return r;
+ }
+ String nickname = config.getString(subsysType + ".cert." + tag + ".nickname", "");
+ if (nickname.equals("")) {
+ CMS.debug("CertUtils: verifySystemCertByTag() nickname for cert tag " + tag + " undefined in CS.cfg");
+ r = false;
+ }
+ String certusage = config.getString(subsysType + ".cert." + tag + ".certusage", "");
+ if (certusage.equals("")) {
+ CMS.debug("CertUtils: verifySystemCertByTag() certusage for cert tag "
+ + tag + " undefined in CS.cfg, getting current certificate usage");
+ }
+ r = verifySystemCertByNickname(nickname, certusage);
+ if (r == true) {
+ // audit here
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.SUCCESS,
+ nickname);
+
+ audit(auditMessage);
+ } else {
+ // audit here
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ nickname);
+
+ audit(auditMessage);
+ }
+ } catch (Exception e) {
+ CMS.debug("CertUtils: verifySystemCertsByTag() failed: " +
+ e.toString());
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ "");
+
+ audit(auditMessage);
+ r = false;
+ }
+
+ return r;
+ }
+
+ /*
+ * returns CertificateUsage mapping to JSS
+ */
+ public static CertificateUsage getCertificateUsage(String certusage) {
+ CertificateUsage cu = null;
+ if ((certusage == null) || certusage.equals(""))
+ cu = CryptoManager.CertificateUsage.CheckAllUsages;
+ else if (certusage.equalsIgnoreCase("CheckAllUsages"))
+ cu = CryptoManager.CertificateUsage.CheckAllUsages;
+ else if (certusage.equalsIgnoreCase("SSLServer"))
+ cu = CryptoManager.CertificateUsage.SSLServer;
+ else if (certusage.equalsIgnoreCase("SSLServerWithStepUp"))
+ cu = CryptoManager.CertificateUsage.SSLServerWithStepUp;
+ else if (certusage.equalsIgnoreCase("SSLClient"))
+ cu = CryptoManager.CertificateUsage.SSLClient;
+ else if (certusage.equalsIgnoreCase("SSLCA"))
+ cu = CryptoManager.CertificateUsage.SSLCA;
+ else if (certusage.equalsIgnoreCase("AnyCA"))
+ cu = CryptoManager.CertificateUsage.AnyCA;
+ else if (certusage.equalsIgnoreCase("StatusResponder"))
+ cu = CryptoManager.CertificateUsage.StatusResponder;
+ else if (certusage.equalsIgnoreCase("ObjectSigner"))
+ cu = CryptoManager.CertificateUsage.ObjectSigner;
+ else if (certusage.equalsIgnoreCase("UserCertImport"))
+ cu = CryptoManager.CertificateUsage.UserCertImport;
+ else if (certusage.equalsIgnoreCase("ProtectedObjectSigner"))
+ cu = CryptoManager.CertificateUsage.ProtectedObjectSigner;
+ else if (certusage.equalsIgnoreCase("VerifyCA"))
+ cu = CryptoManager.CertificateUsage.VerifyCA;
+ else if (certusage.equalsIgnoreCase("EmailSigner"))
+ cu = CryptoManager.CertificateUsage.EmailSigner;
+
+ return cu;
+ }
+
+ /*
+ * goes through all system certs and check to see if they are good
+ * and audit the result
+ * returns true if all verifies; false if any not
+ */
+ public static boolean verifySystemCerts() {
+ String auditMessage = null;
+ IConfigStore config = CMS.getConfigStore();
+ boolean verifyResult = true;
+ boolean r = true; /* the final return value */
+ try {
+ String subsysType = config.getString("cs.type", "");
+ if (subsysType.equals("")) {
+ CMS.debug("CertUtils: verifySystemCerts() cs.type not defined in CS.cfg. System certificates verification not done");
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ "");
+
+ audit(auditMessage);
+ return false;
+ }
+ subsysType = toLowerCaseSubsystemType(subsysType);
+ if (subsysType == null) {
+ CMS.debug("CertUtils: verifySystemCerts() invalid cs.type in CS.cfg. System certificates verification not done");
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ "");
+
+ audit(auditMessage);
+ return false;
+ }
+ String certlist = config.getString(subsysType + ".cert.list", "");
+ if (certlist.equals("")) {
+ CMS.debug("CertUtils: verifySystemCerts() "
+ + subsysType + ".cert.list not defined in CS.cfg. System certificates verification not done");
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ "");
+
+ audit(auditMessage);
+ return false;
+ }
+ StringTokenizer tokenizer = new StringTokenizer(certlist, ",");
+ while (tokenizer.hasMoreTokens()) {
+ String tag = tokenizer.nextToken();
+ tag = tag.trim();
+ CMS.debug("CertUtils: verifySystemCerts() cert tag=" + tag);
+ verifyResult = verifySystemCertByTag(tag);
+ if (verifyResult == false)
+ r = false; //r captures the value for final return
+ }
+ } catch (Exception e) {
+ // audit here
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE,
+ "");
+
+ audit(auditMessage);
+ r = false;
+ CMS.debug("CertUtils: verifySystemCerts():" + e.toString());
+ }
+ return r;
+ }
+
+ public static String toLowerCaseSubsystemType(String s) {
+ if (s == null) {
+ return null;
+ }
+ if (s.equalsIgnoreCase("CA")) {
+ return "ca";
+ } else if (s.equalsIgnoreCase("KRA")) {
+ return "kra";
+ } else if (s.equalsIgnoreCase("OCSP")) {
+ return "ocsp";
+ } else if (s.equalsIgnoreCase("TKS")) {
+ return "tks";
+ } else if (s.equalsIgnoreCase("TPS")) {
+ return "tps";
+ }
+ return null;
+ }
+
+ /**
+ * Signed Audit Log
+ * This method is called to store messages to the signed audit log.
+ *
+ * @param msg signed audit log message
+ */
+ private static void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (mSignedAuditLogger == null) {
+ return;
+ }
+
+ mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/cert/CertificatePair.java b/base/server/cmscore/src/com/netscape/cmscore/cert/CertificatePair.java
new file mode 100644
index 000000000..779e0dafc
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/cert/CertificatePair.java
@@ -0,0 +1,288 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.cert;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import org.mozilla.jss.asn1.ANY;
+import org.mozilla.jss.asn1.ASN1Value;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.asn1.Tag;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.cert.ICrossCertPairSubsystem;
+
+/**
+ * This class implements CertificatePair used for Cross Certification
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class CertificatePair implements ASN1Value {
+ private byte[] mForward; // cert cross-siged by another CA
+ private byte[] mReverse; // subordinate cert signed by this CA
+ private static final Tag TAG = SEQUENCE.TAG;
+
+ /**
+ * construct a CertificatePair. It doesn't matter which is
+ * forward and which is reverse in the parameters. It will figure
+ * it out
+ *
+ * @param cert1 one X509Certificate
+ * @param cert2 one X509Certificate
+ */
+ public CertificatePair(X509Certificate cert1, X509Certificate cert2)
+ throws EBaseException {
+ if ((cert1 == null) || (cert2 == null))
+ throw new EBaseException("CertificatePair: both certs can not be null");
+ debug("in CertificatePair()");
+ boolean rightOrder = certOrders(cert1, cert2);
+
+ try {
+ if (rightOrder == false) {
+ mForward = cert2.getEncoded();
+ mReverse = cert1.getEncoded();
+ } else {
+ mForward = cert1.getEncoded();
+ mReverse = cert2.getEncoded();
+ }
+ } catch (CertificateException e) {
+ throw new EBaseException("CertificatePair: constructor failed:" + e.toString());
+ }
+ }
+
+ /**
+ * construct a CertificatePair. It doesn't matter which is
+ * forward and which is reverse in the parameters. It will figure
+ * it out
+ *
+ * @param cert1 one certificate byte array
+ * @param cert2 one certificate byte array
+ */
+ public CertificatePair(byte[] cert1, byte[] cert2)
+ throws EBaseException {
+ if ((cert1 == null) || (cert2 == null))
+ throw new EBaseException("CertificatePair: both certs can not be null");
+ boolean rightOrder = certOrders(cert1, cert2);
+
+ if (rightOrder == false) {
+ mForward = cert2;
+ mReverse = cert1;
+ } else {
+ mForward = cert1;
+ mReverse = cert2;
+ }
+ }
+
+ /*
+ * returns true if c1 is forward and cert2 is reverse
+ * returns false if c2 is forward and cert1 is reverse
+ */
+ private boolean certOrders(X509Certificate c1, X509Certificate c2)
+ throws EBaseException {
+ debug("in certOrders() with X509Cert");
+
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca");
+ X509Certificate caCert = ca.getCACert();
+
+ debug("got this caCert");
+ // reverse cert is the one signed by this ca
+ // more check really should be done here regarding the
+ // validity of the two certs...later
+
+ /* It looks the DN's returned are not normalized and fail
+ * comparison
+
+ if ((c1.getIssuerDN().equals((Object) caCert.getSubjectDN())))
+ debug("myCA signed c1");
+ else {
+ debug("c1 issuerDN="+c1.getIssuerDN().toString());
+ debug("myCA subjectDN="+caCert.getSubjectDN().toString());
+ }
+
+ if(caCert.getSubjectDN().equals((Object) c2.getSubjectDN()))
+ debug("myCA subject == c2 subject");
+ else {
+ debug("caCert subjectDN="+caCert.getSubjectDN().toString());
+ debug("c2 subjectDN="+c2.getSubjectDN().toString());
+ }
+
+ if ((c2.getIssuerDN().equals((Object) caCert.getSubjectDN())))
+ debug("myCA signed c2");
+ else {
+ debug("c2 issuerDN="+c1.getIssuerDN().toString());
+ debug("myCA subjectDN="+caCert.getSubjectDN().toString());
+ }
+
+ if(caCert.getSubjectDN().equals((Object) c1.getSubjectDN()))
+ debug("myCA subject == c1 subject");
+ else {
+ debug("caCert subjectDN="+caCert.getSubjectDN().toString());
+ debug("c1 subjectDN="+c1.getSubjectDN().toString());
+ }
+
+ if ((c1.getIssuerDN().equals((Object) caCert.getSubjectDN()))
+ && (caCert.getSubjectDN().equals((Object) c2.getSubjectDN())))
+
+ {
+ return false;
+ } else if ((c2.getIssuerDN().equals((Object) caCert.getSubjectDN()))
+ && (caCert.getSubjectDN().equals((Object) c1.getSubjectDN())))
+ {
+ return true;
+ } else {
+ throw new EBaseException("CertificatePair: need correct forward and reverse relationship to construct CertificatePair");
+ }
+ */
+
+ /*
+ * my other attempt:
+ * one of the certs has to share the same public key as this
+ * CA, and that will be the "forward" cert; the other one is
+ * assumed to be the "reverse" cert
+ */
+ byte[] caCertBytes = caCert.getPublicKey().getEncoded();
+
+ if (caCertBytes != null)
+ debug("got cacert public key bytes length=" + caCertBytes.length);
+ else {
+ debug("cacert public key bytes null");
+ throw new EBaseException(
+ "CertificatePair: certOrders() fails to get this CA's signing certificate public key encoded");
+ }
+
+ byte[] c1Bytes = c1.getPublicKey().getEncoded();
+
+ if (c1Bytes != null)
+ debug("got c1 public key bytes length=" + c1Bytes.length);
+ else {
+ debug("c1 cert public key bytes length null");
+ throw new EBaseException("CertificatePair::certOrders() public key bytes are of length null");
+ }
+
+ byte[] c2Bytes = c2.getPublicKey().getEncoded();
+
+ if (c2Bytes != null)
+ debug("got c2 public key bytes length=" + c2Bytes.length);
+ else
+ debug("c2 cert public key bytes length null");
+
+ if (byteArraysAreEqual(c1Bytes, caCertBytes)) {
+ debug("c1 has same public key as this ca");
+ return true;
+ } else if (byteArraysAreEqual(c2Bytes, caCertBytes)) {
+ debug("c2 has same public key as this ca");
+
+ return false;
+ } else {
+ debug("neither c1 nor c2 public key matches with this ca");
+ throw new EBaseException(
+ "CertificatePair: need correct forward and reverse relationship to construct CertificatePair");
+ }
+ }
+
+ /**
+ * compares contents two byte arrays returning true if exactly same.
+ */
+ public boolean byteArraysAreEqual(byte[] a, byte[] b) {
+ debug("in byteArraysAreEqual()");
+
+ if (a == null && b == null) {
+ return true;
+ }
+ if (a == null || b == null) {
+ return false;
+ }
+ if (a.length != b.length) {
+ debug("exiting byteArraysAreEqual(): false");
+ return false;
+ }
+ for (int i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ debug("exiting byteArraysAreEqual(): false");
+ return false;
+ }
+ }
+ debug("exiting byteArraysAreEqual(): true");
+ return true;
+ }
+
+ /*
+ * returns true if cert1 is forward and cert2 is reverse
+ * returns false if cert2 is forward and cert1 is reverse
+ */
+ private boolean certOrders(byte[] cert1, byte[] cert2)
+ throws EBaseException {
+ debug("in certOrders() with byte[]");
+ ICrossCertPairSubsystem ccps =
+ (ICrossCertPairSubsystem) CMS.getSubsystem("CrossCertPair");
+ X509Certificate c1 = null;
+ X509Certificate c2 = null;
+
+ try {
+ c1 = ccps.byteArray2X509Cert(cert1);
+ c2 = ccps.byteArray2X509Cert(cert2);
+ } catch (CertificateException e) {
+ throw new EBaseException("CertificatePair: certOrders() failed:" + e.toString());
+ }
+ return certOrders(c1, c2);
+ }
+
+ public void encode(OutputStream os) throws IOException {
+ encode(TAG, os);
+ }
+
+ public void encode(Tag implicitTag, OutputStream os) throws IOException {
+ SEQUENCE seq = new SEQUENCE();
+
+ if (mForward != null) {
+ try {
+ ANY any = new ANY(mForward);
+
+ seq.addElement(any);
+ } catch (InvalidBERException e) {
+ debug("encode error:" + e.toString());
+ }
+ }
+ if (mReverse != null) {
+ try {
+ ANY any = new ANY(mReverse);
+
+ seq.addElement(any);
+ } catch (InvalidBERException e) {
+ debug("encode error:" + e.toString());
+ }
+ }
+
+ seq.encode(implicitTag, os);
+ }
+
+ public Tag getTag() {
+ return TAG;
+ }
+
+ private void debug(String msg) {
+ CMS.debug("CertifiatePair: " + msg);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/cert/CrlCachePrettyPrint.java b/base/server/cmscore/src/com/netscape/cmscore/cert/CrlCachePrettyPrint.java
new file mode 100644
index 000000000..86746619b
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/cert/CrlCachePrettyPrint.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.cert;
+
+import java.text.DateFormat;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.TimeZone;
+
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.Extension;
+import netscape.security.x509.RevokedCertificate;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.ICRLPrettyPrint;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+
+/**
+ * This class will display the certificate content in predefined
+ * format.
+ *
+ * @author Andrew Wnuk
+ * @version $Revision$, $Date$
+ */
+public class CrlCachePrettyPrint implements ICRLPrettyPrint {
+
+ /*==========================================================
+ * constants
+ *==========================================================*/
+ private final static String CUSTOM_LOCALE = "Custom";
+
+ /*==========================================================
+ * variables
+ *==========================================================*/
+ private ICRLIssuingPoint mIP = null;
+ private PrettyPrintFormat pp = null;
+
+ /*==========================================================
+ * constructors
+ *==========================================================*/
+
+ public CrlCachePrettyPrint(ICRLIssuingPoint ip) {
+ mIP = ip;
+ pp = new PrettyPrintFormat(":");
+ }
+
+ /*==========================================================
+ * public methods
+ *==========================================================*/
+
+ /**
+ * This method return string representation of the certificate
+ * revocation list in predefined format using specified client
+ * local. I18N Support.
+ *
+ * @param clientLocale Locale to be used for localization
+ * @return string representation of the certificate
+ */
+ public String toString(Locale clientLocale) {
+ return toString(clientLocale, 0, 0, 0);
+ }
+
+ public String toString(Locale clientLocale, long crlSize, long pageStart, long pageSize) {
+
+ //get I18N resources
+ ResourceBundle resource = ResourceBundle.getBundle(
+ PrettyPrintResources.class.getName());
+ DateFormat dateFormater = DateFormat.getDateTimeInstance(
+ DateFormat.FULL, DateFormat.FULL, clientLocale);
+ //get timezone and timezone ID
+ String tz = " ";
+ String tzid = " ";
+
+ StringBuffer sb = new StringBuffer();
+
+ try {
+ sb.append(pp.indent(4) + resource.getString(
+ PrettyPrintResources.TOKEN_CRL) + "\n");
+ sb.append(pp.indent(8) + resource.getString(
+ PrettyPrintResources.TOKEN_DATA) + "\n");
+
+ String signingAlgorithm = mIP.getLastSigningAlgorithm();
+ if (signingAlgorithm != null) {
+ sb.append(pp.indent(12) + resource.getString(
+ PrettyPrintResources.TOKEN_SIGALG) +
+ signingAlgorithm + "\n");
+ }
+ sb.append(pp.indent(12) + resource.getString(
+ PrettyPrintResources.TOKEN_ISSUER) +
+ ((ICertificateAuthority) (mIP.getCertificateAuthority()))
+ .getCRLX500Name().toString() + "\n");
+ // Format thisUpdate
+ String thisUpdate = dateFormater.format(mIP.getLastUpdate());
+
+ // get timezone and timezone ID
+ if (TimeZone.getDefault() != null) {
+ tz = TimeZone.getDefault().getDisplayName(
+ TimeZone.getDefault().inDaylightTime(mIP.getLastUpdate()),
+ TimeZone.SHORT,
+ clientLocale);
+ tzid = TimeZone.getDefault().getID();
+ }
+ // Specify ThisUpdate
+ if (tz.equals(tzid) || tzid.equals(CUSTOM_LOCALE)) {
+ // Do NOT append timezone ID
+ sb.append(pp.indent(12)
+ + resource.getString(
+ PrettyPrintResources.TOKEN_THIS_UPDATE)
+ + thisUpdate
+ + "\n");
+ } else {
+ // Append timezone ID
+ sb.append(pp.indent(12)
+ + resource.getString(
+ PrettyPrintResources.TOKEN_THIS_UPDATE)
+ + thisUpdate
+ + " " + tzid + "\n");
+ }
+ // Check for presence of NextUpdate
+ if (mIP.getNextUpdate() != null) {
+ // Format nextUpdate
+ String nextUpdate = dateFormater.format(mIP.getNextUpdate());
+
+ // re-get timezone (just in case it is different . . .)
+ if (TimeZone.getDefault() != null) {
+ tz = TimeZone.getDefault().getDisplayName(
+ TimeZone.getDefault().inDaylightTime(mIP.getNextUpdate()),
+ TimeZone.SHORT,
+ clientLocale);
+ }
+ // Specify NextUpdate
+ if (tz.equals(tzid) || tzid.equals(CUSTOM_LOCALE)) {
+ // Do NOT append timezone ID
+ sb.append(pp.indent(12)
+ + resource.getString(
+ PrettyPrintResources.TOKEN_NEXT_UPDATE)
+ + nextUpdate
+ + "\n");
+ } else {
+ // Append timezone ID
+ sb.append(pp.indent(12)
+ + resource.getString(
+ PrettyPrintResources.TOKEN_NEXT_UPDATE)
+ + nextUpdate
+ + " " + tzid + "\n");
+ }
+ }
+
+ if (crlSize > 0 && pageStart == 0 && pageSize == 0) {
+ sb.append(pp.indent(12) + resource.getString(
+ PrettyPrintResources.TOKEN_REVOKED_CERTIFICATES) + crlSize + "\n");
+ } else if ((crlSize == 0 && pageStart == 0 && pageSize == 0) ||
+ (crlSize > 0 && pageStart > 0 && pageSize > 0)) {
+ sb.append(pp.indent(12) + resource.getString(
+ PrettyPrintResources.TOKEN_REVOKED_CERTIFICATES));
+ long upperLimit = crlSize;
+ if (crlSize > 0 && pageStart > 0 && pageSize > 0) {
+ upperLimit = (pageStart + pageSize - 1 > crlSize) ? crlSize : pageStart + pageSize - 1;
+ sb.append("" + pageStart + "-" + upperLimit + " of " + crlSize);
+ } else {
+ pageStart = 1;
+ sb.append("" + crlSize);
+ }
+ sb.append("\n");
+
+ Set<RevokedCertificate> revokedCerts =
+ mIP.getRevokedCertificates((int) (pageStart - 1), (int) upperLimit);
+
+ if (revokedCerts != null) {
+ Iterator<RevokedCertificate> i = revokedCerts.iterator();
+ long l = 1;
+
+ while ((i.hasNext()) && ((crlSize == 0) || (upperLimit - pageStart + 1 >= l))) {
+ RevokedCertificate revokedCert = i.next();
+
+ if ((crlSize == 0) || (upperLimit - pageStart + 1 >= l)) {
+ sb.append(pp.indent(16) + resource.getString(
+ PrettyPrintResources.TOKEN_SERIAL) + "0x" +
+ revokedCert.getSerialNumber().toString(16).toUpperCase() + "\n");
+ String revocationDate =
+ dateFormater.format(revokedCert.getRevocationDate());
+
+ // re-get timezone
+ // (just in case it is different . . .)
+ if (TimeZone.getDefault() != null) {
+ tz = TimeZone.getDefault().getDisplayName(
+ TimeZone.getDefault().inDaylightTime(
+ revokedCert.getRevocationDate()),
+ TimeZone.SHORT,
+ clientLocale);
+ }
+ // Specify revocationDate
+ if (tz.equals(tzid) ||
+ tzid.equals(CUSTOM_LOCALE)) {
+ // Do NOT append timezone ID
+ sb.append(pp.indent(16)
+ + resource.getString(
+ PrettyPrintResources.TOKEN_REVOCATION_DATE)
+ + revocationDate
+ + "\n");
+ } else {
+ // Append timezone ID
+ sb.append(pp.indent(16)
+ + resource.getString(
+ PrettyPrintResources.TOKEN_REVOCATION_DATE)
+ + revocationDate
+ + " " + tzid + "\n");
+ }
+ if (revokedCert.hasExtensions()) {
+ sb.append(pp.indent(16) + resource.getString(
+ PrettyPrintResources.TOKEN_EXTENSIONS) + "\n");
+ CRLExtensions crlExtensions = revokedCert.getExtensions();
+
+ if (crlExtensions != null) {
+ for (int k = 0; k < crlExtensions.size(); k++) {
+ Extension ext = crlExtensions.elementAt(k);
+ ExtPrettyPrint extpp = new ExtPrettyPrint(ext, 20);
+
+ sb.append(extpp.toString());
+ }
+ }
+ }
+ }
+ l++;
+ }
+ } else if (mIP.isCRLCacheEnabled() && mIP.isCRLCacheEmpty()) {
+ sb.append("\n" + pp.indent(16) + resource.getString(
+ PrettyPrintResources.TOKEN_CACHE_IS_EMPTY) + "\n\n");
+ } else {
+ sb.append("\n" + pp.indent(16) + resource.getString(
+ PrettyPrintResources.TOKEN_CACHE_NOT_AVAILABLE) + "\n\n");
+ }
+ }
+
+ } catch (Exception e) {
+ sb.append("\n\n" + pp.indent(4) + resource.getString(
+ PrettyPrintResources.TOKEN_DECODING_ERROR) + "\n\n");
+ CMS.debug("Exception=" + e.toString());
+ CMS.debugStackTrace();
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/cert/CrlPrettyPrint.java b/base/server/cmscore/src/com/netscape/cmscore/cert/CrlPrettyPrint.java
new file mode 100644
index 000000000..2dc947641
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/cert/CrlPrettyPrint.java
@@ -0,0 +1,36 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.cert;
+
+import netscape.security.x509.X509CRLImpl;
+
+import com.netscape.certsrv.base.ICRLPrettyPrint;
+
+/**
+ * This class will display the certificate content in predefined
+ * format.
+ *
+ * @author Andrew Wnuk
+ * @version $Revision$, $Date$
+ */
+public class CrlPrettyPrint extends netscape.security.util.CrlPrettyPrint implements ICRLPrettyPrint {
+
+ public CrlPrettyPrint(X509CRLImpl crl) {
+ super(crl);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/cert/CrossCertPairSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/cert/CrossCertPairSubsystem.java
new file mode 100644
index 000000000..b0feca8c2
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/cert/CrossCertPairSubsystem.java
@@ -0,0 +1,510 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.cert;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPModificationSet;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.cert.ICrossCertPairSubsystem;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.publish.IXcertPublisherProcessor;
+import com.netscape.cmscore.ldapconn.LdapBoundConnFactory;
+
+/**
+ * Subsystem for handling cross certificate pairing and publishing
+ * Intended use:
+ * <ul>
+ * <li>when signing a subordinate CA cert which is intended to be part of the crossCertificatePair
+ * <li>when this ca submits a request (with existing CA signing key material to another ca for cross-signing
+ * </ul>
+ * In both cases, administrator needs to "import" the crossSigned
+ * certificates via the admin console. When importCert() is called,
+ * the imported cert will be stored in the internal db
+ * first until it's pairing cert shows up.
+ * If it happens that the above two cases finds its pairing
+ * cert already there, then a CertifiatePair is created and put
+ * in the internal db "crosscertificatepair;binary" attribute
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class CrossCertPairSubsystem implements ICrossCertPairSubsystem {
+
+ public static final String ID = "CrossCertPair";
+ public static final String DN_XCERTS = "cn=crossCerts";
+ public static final String LDAP_ATTR_CA_CERT = "caCertificate;binary";
+ public static final String LDAP_ATTR_XCERT_PAIR = "crossCertificatePair;binary";
+ protected static final String PROP_LDAP = "ldap";
+ protected static final String PROP_BASEDN = "basedn";
+
+ protected IConfigStore mConfig = null;
+ protected LdapBoundConnFactory mLdapConnFactory = null;
+ protected String mBaseDN = null;
+ protected ICertificateAuthority mCa = null;
+ protected IPublisherProcessor mPublisherProcessor = null;
+
+ private String mId = ID;
+ private ILogger mLogger = null;
+
+ public CrossCertPairSubsystem() {
+ }
+
+ /**
+ * Retrieves subsystem identifier.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ try {
+ mConfig = config;
+ mLogger = CMS.getLogger();
+ synchronized (this) {
+ mCa = (ICertificateAuthority) CMS.getSubsystem("ca");
+ mPublisherProcessor = mCa.getPublisherProcessor();
+ }
+
+ // initialize LDAP connection factory
+ IConfigStore ldapConfig = mConfig.getSubStore(PROP_LDAP);
+
+ if (ldapConfig == null) {
+ log(ILogger.LL_MISCONF,
+ CMS.getLogMessage("CMSCORE_DBS_CONF_ERROR",
+ PROP_LDAP));
+ return;
+ }
+
+ mBaseDN = ldapConfig.getString(PROP_BASEDN, null);
+
+ mLdapConnFactory = new LdapBoundConnFactory();
+
+ if (mLdapConnFactory != null)
+ mLdapConnFactory.init(ldapConfig);
+ else {
+ log(ILogger.LL_MISCONF,
+ CMS.getLogMessage("CMSCORE_DBS_CONF_ERROR",
+ PROP_LDAP));
+ return;
+ }
+ } catch (EBaseException e) {
+ if (CMS.isPreOpMode())
+ return;
+ throw e;
+ }
+ }
+
+ /**
+ * "import" the CA cert cross-signed by another CA (potentially a
+ * bridge CA) into internal ldap db.
+ * the imported cert will be stored in the internal db
+ * first until it's pairing cert shows up.
+ * If it happens that it finds its pairing
+ * cert already there, then a CertifiatePair is created and put
+ * in the internal db "crosscertificatepair;binary" attribute
+ *
+ * @param certBytes cert in byte array to be imported
+ */
+ public void importCert(byte[] certBytes) throws EBaseException {
+ debug("importCert(byte[])");
+ X509Certificate cert = null;
+
+ try {
+ cert = byteArray2X509Cert(certBytes);
+ } catch (CertificateException e) {
+ throw new EBaseException("CrossCertPairSubsystem: importCert() failed:" + e.toString());
+
+ }
+
+ importCert(cert);
+ }
+
+ /**
+ * "import" the CA cert cross-signed by another CA (potentially a
+ * bridge CA) into internal ldap db.
+ * the imported cert will be stored in the internal db
+ * first until it's pairing cert shows up.
+ * If it happens that it finds its pairing
+ * cert already there, then a CertifiatePair is created and put
+ * in the internal db "crosscertificatepair;binary" attribute
+ *
+ * @param certBytes cert in byte array to be imported
+ */
+ public synchronized void importCert(Object certObj) throws EBaseException {
+ if (!(certObj instanceof X509Certificate))
+ throw new IllegalArgumentException("Illegal arg to publish");
+
+ debug("in importCert(Object)");
+ X509Certificate cert = (X509Certificate) certObj;
+ // check to see if this is a valid cross-signed ca cert:
+ // 1. does cert2 share the same key pair as this CA's signing
+ // cert
+ // 2. does cert2's subject match this CA's subject?
+ // 3. other valididity checks: is this a ca cert? Is this
+ // cert still valid? If the issuer is not yet trusted, let it
+ // be.
+
+ // get certs from internal db to see if we find a pair
+ LDAPConnection conn = null;
+
+ try {
+ conn = getConn();
+ LDAPSearchResults res = conn.search(mBaseDN, LDAPv2.SCOPE_SUB,
+ DN_XCERTS, null, false);
+
+ if (res.hasMoreElements()) {
+ log(ILogger.LL_INFO, "ldap search found " + DN_XCERTS);
+
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+ LDAPAttribute caCerts = entry.getAttribute(LDAP_ATTR_CA_CERT);
+ LDAPAttribute certPairs = entry.getAttribute(LDAP_ATTR_XCERT_PAIR);
+
+ if (caCerts == null) {
+ debug("no existing ca certs, just import");
+ addCAcert(conn, cert.getEncoded());
+ return;
+ }
+
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> en = caCerts.getByteValues();
+
+ if ((en == null) || (en.hasMoreElements() == false)) {
+ debug("1st potential xcert");
+ addCAcert(conn, cert.getEncoded());
+ debug("potential cross ca cert added to crossCerts entry successfully");
+ return;
+ }
+ byte[] val = null;
+ boolean match = false;
+
+ while (en.hasMoreElements()) {
+ val = en.nextElement();
+ debug("val =" + val.length);
+ if (val.length == 0) {
+ continue;
+ } else {
+ X509Certificate inCert = byteArray2X509Cert(val);
+
+ if (arePair(inCert, cert)) {
+ // found a pair,form xcert, write to
+ // crossCertificatePair attr, remove from
+ // caCertificate attr, and publish if so configured
+ debug("found a pair!");
+ CertificatePair cp = new
+ // CertificatePair(inCert.getEncoded(), cert.getEncoded());
+ CertificatePair(inCert, cert);
+
+ addXCertPair(conn, certPairs, cp);
+ deleteCAcert(conn, inCert.getEncoded());
+ // found a match, get out
+ match = true;
+ break;
+ }
+ }
+ } //while
+ if (match == false) {
+ // don't find a pair, add it into
+ // caCertificate attr for later pairing
+ // opportunities
+ debug("didn't find a pair!");
+ addCAcert(conn, cert.getEncoded());
+ debug("potential cross ca cert added to crossCerts entry successfully");
+ }
+
+ } else {
+ log(ILogger.LL_INFO, "ldap search found no " + DN_XCERTS);
+ }
+ } catch (IOException e) {
+ throw new EBaseException("CrossCertPairSubsystem: importCert() failed:" + e.toString());
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, "exception: " + e.toString());
+ throw new EBaseException("CrossCertPairSubsystem: importCert() failed:" + e.toString());
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, "exception: " + e.toString());
+ throw new EBaseException("CrossCertPairSubsystem: importCert() failed:" + e.toString());
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, "exception: " + e.toString());
+ throw new EBaseException("CrossCertPairSubsystem: importCert() failed:" + e.toString());
+ } finally {
+ try {
+ returnConn(conn);
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, "exception: " + e.toString());
+ throw new EBaseException("CrossCertPairSubsystem: importCert() failed:" + e.toString());
+ }
+ }
+ debug("importCert(Object) completed");
+ }
+
+ /**
+ * are cert1 and cert2 cross-signed certs?
+ *
+ * @param cert1 the cert for comparison in our internal db
+ * @param cert2 the cert that's being considered
+ */
+ protected boolean arePair(X509Certificate cert1, X509Certificate cert2) {
+ // 1. does cert1's issuer match cert2's subject?
+ // 2. does cert2's issuer match cert1's subject?
+ if (cert1.getIssuerDN().equals(cert2.getSubjectDN())
+ && cert2.getIssuerDN().equals(cert1.getSubjectDN()))
+ return true;
+ else
+ return false;
+ }
+
+ public X509Certificate byteArray2X509Cert(byte[] certBytes)
+ throws CertificateException {
+ debug("in bytearray2X509Cert()");
+ ByteArrayInputStream inStream = new
+ ByteArrayInputStream(certBytes);
+
+ CertificateFactory cf =
+ CertificateFactory.getInstance("X.509");
+
+ X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
+
+ debug("done bytearray2X509Cert()");
+ return cert;
+ }
+
+ public synchronized void addXCertPair(LDAPConnection conn,
+ LDAPAttribute certPairs, CertificatePair pair)
+ throws LDAPException, IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ pair.encode(bos);
+
+ if (ByteValueExists(certPairs, bos.toByteArray()) == true) {
+ debug("cross cert pair exists in internal db, don't add again");
+ return;
+ }
+
+ // add certificatePair
+ LDAPModificationSet modSet = new LDAPModificationSet();
+
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(LDAP_ATTR_XCERT_PAIR, bos.toByteArray()));
+ conn.modify(DN_XCERTS + "," + mBaseDN, modSet);
+ }
+
+ /**
+ * checks if a byte attribute has a certain value.
+ */
+ public static boolean ByteValueExists(LDAPAttribute attr, byte[] bval) {
+ if (attr == null) {
+ return false;
+ }
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> vals = attr.getByteValues();
+ byte[] val = null;
+
+ while (vals.hasMoreElements()) {
+ val = vals.nextElement();
+ if (val.length == 0)
+ continue;
+ if (byteArraysAreEqual(val, bval)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * compares contents two byte arrays returning true if exactly same.
+ */
+ static public boolean byteArraysAreEqual(byte[] a, byte[] b) {
+ debug("in byteArraysAreEqual()");
+ if (a.length != b.length) {
+ debug("exiting byteArraysAreEqual(): false");
+ return false;
+ }
+ for (int i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ debug("exiting byteArraysAreEqual(): false");
+ return false;
+ }
+ }
+ debug("exiting byteArraysAreEqual(): true");
+ return true;
+ }
+
+ public synchronized void addCAcert(LDAPConnection conn, byte[] certEnc)
+ throws LDAPException {
+ LDAPModificationSet modSet = new
+ LDAPModificationSet();
+
+ modSet.add(LDAPModification.ADD,
+ new LDAPAttribute(LDAP_ATTR_CA_CERT, certEnc));
+ conn.modify(DN_XCERTS + "," + mBaseDN, modSet);
+ }
+
+ public synchronized void deleteCAcert(LDAPConnection conn, byte[] certEnc)
+ throws LDAPException {
+ LDAPModificationSet modSet = new
+ LDAPModificationSet();
+
+ modSet.add(LDAPModification.DELETE,
+ new LDAPAttribute(LDAP_ATTR_CA_CERT, certEnc));
+ conn.modify(DN_XCERTS + "," + mBaseDN, modSet);
+ }
+
+ /**
+ * publish all cert pairs, if publisher is on
+ */
+ public synchronized void publishCertPairs() throws EBaseException {
+ LDAPConnection conn = null;
+
+ if ((mPublisherProcessor == null) ||
+ !mPublisherProcessor.enabled())
+ return;
+
+ try {
+ conn = getConn();
+ // search in internal db for xcerts
+ LDAPSearchResults res = conn.search(mBaseDN, LDAPv2.SCOPE_SUB,
+ DN_XCERTS, null, false);
+
+ debug("trying to publish cert pairs, if any");
+ if ((res == null) || (res.hasMoreElements() == false)) {
+ debug("no cross cert pairs to publish");
+ return;
+ }
+
+ if (res.hasMoreElements()) {
+ log(ILogger.LL_INFO, "ldap search found " + DN_XCERTS);
+
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+ LDAPAttribute xcerts = entry.getAttribute(LDAP_ATTR_XCERT_PAIR);
+
+ if (xcerts == null) {
+ debug("no cross cert pairs to publish");
+ return;
+ }
+
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> en = xcerts.getByteValues();
+
+ if ((en == null) || (en.hasMoreElements() == false)) {
+ debug("publishCertPair found no pairs in internal db");
+ return;
+ }
+ byte[] val = null;
+
+ while (en.hasMoreElements()) {
+ val = en.nextElement();
+ debug("val =" + val.length);
+ if (val.length == 0) {
+ continue;
+ } else {
+ try {
+ //found a cross cert pair, publish if we could
+ IXcertPublisherProcessor xp = null;
+
+ xp = (IXcertPublisherProcessor) mPublisherProcessor;
+ xp.publishXCertPair(val);
+ } catch (Exception e) {
+ throw new EBaseException("CrossCertPairSubsystem: publishCertPairs() failed:"
+ + e.toString());
+ }
+ }
+ }// while
+ }//if
+ } catch (Exception e) {
+ throw new EBaseException("CrossCertPairSubsystem: publishCertPairs() failed:" + e.toString());
+ }
+ }
+
+ protected LDAPConnection getConn() throws ELdapException {
+ if (mLdapConnFactory != null) {
+ LDAPConnection conn = mLdapConnFactory.getConn();
+ if (conn == null) {
+ throw new ELdapException("No Ldap Connection Available");
+ } else {
+ return conn;
+ }
+ }
+
+ throw new ELdapException("Ldap Connection Factory is null");
+ }
+
+ protected void returnConn(LDAPConnection conn) throws ELdapException {
+ if (mLdapConnFactory != null)
+ mLdapConnFactory.returnConn(conn);
+ }
+
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Stops this system.
+ */
+ public synchronized void shutdown() {
+ if (mLdapConnFactory != null) {
+ try {
+ mLdapConnFactory.reset();
+ } catch (ELdapException e) {
+ CMS.debug("CrossCertPairSubsystem shutdown exception: " + e.toString());
+ }
+ }
+ }
+
+ /*
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ protected void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM,
+ ILogger.S_XCERT, level, msg);
+ }
+
+ private static void debug(String msg) {
+ CMS.debug("CrossCertPairSubsystem: " + msg);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/cert/ExtPrettyPrint.java b/base/server/cmscore/src/com/netscape/cmscore/cert/ExtPrettyPrint.java
new file mode 100644
index 000000000..10ac3fbb1
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/cert/ExtPrettyPrint.java
@@ -0,0 +1,36 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.cert;
+
+import netscape.security.x509.Extension;
+
+import com.netscape.certsrv.base.IExtPrettyPrint;
+
+/**
+ * This class will display the certificate content in predefined
+ * format.
+ *
+ * @author Andrew Wnuk
+ * @version $Revision$, $Date$
+ */
+public class ExtPrettyPrint extends netscape.security.util.ExtPrettyPrint implements IExtPrettyPrint {
+
+ public ExtPrettyPrint(Extension ext, int indentSize) {
+ super(ext, indentSize);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/cert/OidLoaderSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/cert/OidLoaderSubsystem.java
new file mode 100644
index 000000000..95bbd98e7
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/cert/OidLoaderSubsystem.java
@@ -0,0 +1,189 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.cert;
+
+import java.security.cert.CertificateException;
+import java.util.Enumeration;
+
+import netscape.security.extensions.CertificateRenewalWindowExtension;
+import netscape.security.extensions.CertificateScopeOfUseExtension;
+import netscape.security.extensions.NSCertTypeExtension;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.DeltaCRLIndicatorExtension;
+import netscape.security.x509.FreshestCRLExtension;
+import netscape.security.x509.HoldInstructionExtension;
+import netscape.security.x509.InvalidityDateExtension;
+import netscape.security.x509.IssuingDistributionPointExtension;
+import netscape.security.x509.OIDMap;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ *
+ * @author stevep
+ * @version $Revision
+ */
+public class OidLoaderSubsystem implements ISubsystem {
+
+ private IConfigStore mConfig = null;
+ public static final String ID = "oidmap";
+ private String mId = ID;
+
+ private static final String PROP_OID = "oid";
+ private static final String PROP_CLASS = "class";
+
+ /**
+ *
+ */
+ private OidLoaderSubsystem() {
+ }
+
+ /**
+ * Retrieves subsystem identifier.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ // singleton enforcement
+
+ private static OidLoaderSubsystem mInstance = new OidLoaderSubsystem();
+
+ public static OidLoaderSubsystem getInstance() {
+ return mInstance;
+ }
+
+ private static final int CertType_data[] = { 2, 16, 840, 1, 113730, 1, 1 };
+
+ /**
+ * Identifies the particular public key used to sign the certificate.
+ */
+ public static final ObjectIdentifier CertType_Id = new
+ ObjectIdentifier(CertType_data);
+
+ private static final String[][] oidMapEntries = new String[][] {
+ { NSCertTypeExtension.class.getName(),
+ CertType_Id.toString(),
+ NSCertTypeExtension.NAME },
+ { CertificateRenewalWindowExtension.class.getName(),
+ CertificateRenewalWindowExtension.ID.toString(),
+ CertificateRenewalWindowExtension.NAME },
+ { CertificateScopeOfUseExtension.class.getName(),
+ CertificateScopeOfUseExtension.ID.toString(),
+ CertificateScopeOfUseExtension.NAME },
+ { DeltaCRLIndicatorExtension.class.getName(),
+ DeltaCRLIndicatorExtension.OID,
+ DeltaCRLIndicatorExtension.NAME },
+ { HoldInstructionExtension.class.getName(),
+ HoldInstructionExtension.OID,
+ HoldInstructionExtension.NAME },
+ { InvalidityDateExtension.class.getName(),
+ InvalidityDateExtension.OID,
+ InvalidityDateExtension.NAME },
+ { IssuingDistributionPointExtension.class.getName(),
+ IssuingDistributionPointExtension.OID,
+ IssuingDistributionPointExtension.NAME },
+ { FreshestCRLExtension.class.getName(),
+ FreshestCRLExtension.OID,
+ FreshestCRLExtension.NAME },
+ };
+
+ /**
+ * Initializes this subsystem with the given
+ * configuration store.
+ * It first initializes resident subsystems,
+ * and it loads and initializes loadable
+ * subsystem specified in the configuration
+ * store.
+ * <P>
+ * Note that individual subsystem should be initialized in a separated thread if it has dependency on the
+ * initialization of other subsystems.
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration store
+ */
+ public synchronized void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ if (Debug.ON) {
+ Debug.trace("OIDLoaderSubsystem started");
+ }
+ mConfig = config;
+
+ Enumeration<String> names = mConfig.getSubStoreNames();
+
+ // load static (build-in) extensions
+
+ for (int i = 0; i < oidMapEntries.length; i++) {
+ try {
+ OIDMap.addAttribute(oidMapEntries[i][0],
+ oidMapEntries[i][1],
+ oidMapEntries[i][2]);
+ } catch (Exception e) {
+ }
+ }
+
+ // load dynamic extensions
+
+ while (names.hasMoreElements()) {
+ String substorename = names.nextElement();
+ IConfigStore substore = mConfig.getSubStore(substorename);
+
+ try {
+ String oidname = substore.getString(PROP_OID);
+ String classname = substore.getString(PROP_CLASS);
+
+ OIDMap.addAttribute(classname,
+ oidname,
+ substorename);
+ } catch (EPropertyNotFound e) {
+ // Log error
+ } catch (CertificateException e) {
+ // log error
+ }
+ }
+ }
+
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Stops this system.
+ */
+ public synchronized void shutdown() {
+ }
+
+ /*
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public synchronized IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/cert/PrettyPrintFormat.java b/base/server/cmscore/src/com/netscape/cmscore/cert/PrettyPrintFormat.java
new file mode 100644
index 000000000..60bc8c8f6
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/cert/PrettyPrintFormat.java
@@ -0,0 +1,164 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.cert;
+
+import com.netscape.certsrv.base.IPrettyPrintFormat;
+
+/**
+ * This class will display the certificate content in predefined
+ * format.
+ *
+ * @author Andrew Wnuk
+ * @version $Revision$, $Date$
+ */
+public class PrettyPrintFormat implements IPrettyPrintFormat {
+
+ /*==========================================================
+ * variables
+ *==========================================================*/
+ private String mSeparator = "";
+ private int mIndentSize = 0;
+ private int mLineLen = 0;
+
+ /*==========================================================
+ * constants
+ *
+ *==========================================================*/
+ private final static String spaces =
+ " " +
+ " " +
+ " " +
+ " " +
+ " ";
+
+ /*==========================================================
+ * constructors
+ *==========================================================*/
+
+ public PrettyPrintFormat(String separator) {
+ mSeparator = separator;
+ }
+
+ public PrettyPrintFormat(String separator, int lineLen) {
+ mSeparator = separator;
+ mLineLen = lineLen;
+ }
+
+ public PrettyPrintFormat(String separator, int lineLen, int indentSize) {
+ mSeparator = separator;
+ mLineLen = lineLen;
+ mIndentSize = indentSize;
+ }
+
+ /*==========================================================
+ * Private methods
+ *==========================================================*/
+
+ /*==========================================================
+ * public methods
+ *==========================================================*/
+
+ /**
+ * Provide white space indention
+ * stevep - speed improvements. Factor of 10 improvement
+ *
+ * @param numSpace number of white space to be returned
+ * @return white spaces
+ */
+ public String indent(int size) {
+ return spaces.substring(0, size);
+ }
+
+ private static final char[] hexdigits = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
+ /**
+ * Convert Byte Array to Hex String Format
+ * stevep - speedup by factor of 8
+ *
+ * @param byte array of data to hexify
+ * @param indentSize number of spaces to prepend before each line
+ * @param lineLen number of bytes to output on each line (0
+ * means: put everything on one line
+ * @param separator the first character of this string will be used as
+ * the separator between bytes.
+ * @return string representation
+ */
+
+ public String toHexString(byte[] in, int indentSize,
+ int lineLen, String separator) {
+
+ if (in == null) return "";
+
+ StringBuffer sb = new StringBuffer(indent(indentSize));
+ int hexCount = 0;
+ char c[];
+ int j = 0;
+
+ if (lineLen == 0) {
+ c = new char[in.length * 3 + 1];
+ } else {
+ c = new char[lineLen * 3 + 1];
+ }
+
+ char sep = separator.charAt(0);
+
+ for (int i = 0; i < in.length; i++) {
+ if (lineLen > 0 && hexCount == lineLen) {
+ c[j++] = '\n';
+ sb.append(c, 0, j);
+ sb.append(indent(indentSize));
+ hexCount = 0;
+ j = 0;
+ }
+ byte x = in[i];
+
+ // output hex digits to buffer
+ c[j++] = hexdigits[(char) ((x >> 4) & 0xf)];
+ c[j++] = hexdigits[(char) (x & 0xf)];
+
+ // if not last char, output separator
+ if (i != in.length - 1) {
+ c[j++] = sep;
+ }
+
+ hexCount++;
+ }
+ if (j > 0) {
+ c[j++] = '\n';
+ sb.append(c, 0, j);
+ }
+ // sb.append("\n");
+
+ return sb.toString();
+ }
+
+ public String toHexString(byte[] in, int indentSize, int lineLen) {
+ return toHexString(in, indentSize, lineLen, mSeparator);
+ }
+
+ public String toHexString(byte[] in, int indentSize) {
+ return toHexString(in, indentSize, mLineLen);
+ }
+
+ public String toHexString(byte[] in) {
+ return toHexString(in, mIndentSize);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/cert/PrettyPrintResources.java b/base/server/cmscore/src/com/netscape/cmscore/cert/PrettyPrintResources.java
new file mode 100644
index 000000000..0756664d9
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/cert/PrettyPrintResources.java
@@ -0,0 +1,293 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.cert;
+
+import java.util.ListResourceBundle;
+
+import netscape.security.extensions.NSCertTypeExtension;
+import netscape.security.x509.KeyUsageExtension;
+
+/**
+ * Resource Boundle for the Pretty Print
+ *
+ * @author Jack Pan-Chen
+ * @version $Revision$, $Date$
+ */
+
+public class PrettyPrintResources extends ListResourceBundle {
+
+ /**
+ * Returns content
+ */
+ public Object[][] getContents() {
+ return contents;
+ }
+
+ /**
+ * Constants. The suffix represents the number of
+ * possible parameters.
+ */
+
+ //certificate pretty print
+ public final static String TOKEN_CERTIFICATE = "tokenCertificate";
+ public final static String TOKEN_DATA = "tokenData";
+ public final static String TOKEN_VERSION = "tokenVersion";
+ public final static String TOKEN_SERIAL = "tokenSerial";
+ public final static String TOKEN_SIGALG = "tokenSignatureAlgorithm";
+ public final static String TOKEN_ISSUER = "tokenIssuer";
+ public final static String TOKEN_VALIDITY = "tokenValidity";
+ public final static String TOKEN_NOT_BEFORE = "tokenNotBefore";
+ public final static String TOKEN_NOT_AFTER = "tokenNotAfter";
+ public final static String TOKEN_SUBJECT = "tokenSubject";
+ public final static String TOKEN_SPKI = "tokenSPKI";
+ public final static String TOKEN_ALGORITHM = "tokenAlgorithm";
+ public final static String TOKEN_PUBLIC_KEY = "tokenPublicKey";
+ public final static String TOKEN_PUBLIC_KEY_MODULUS = "tokenPublicKeyModulus";
+ public final static String TOKEN_PUBLIC_KEY_EXPONENT = "tokenPublicKeyExponent";
+ public final static String TOKEN_EXTENSIONS = "tokenExtensions";
+ public final static String TOKEN_SIGNATURE = "tokenSignature";
+
+ //extension pretty print
+ public final static String TOKEN_YES = "tokenYes";
+ public final static String TOKEN_NO = "tokenNo";
+ public final static String TOKEN_IDENTIFIER = "tokenIdentifier";
+ public final static String TOKEN_CRITICAL = "tokenCritical";
+ public final static String TOKEN_VALUE = "tokenValue";
+
+ //specific extension token
+ public final static String TOKEN_KEY_TYPE = "tokenKeyType";
+ public final static String TOKEN_CERT_TYPE = "tokenCertType";
+ public final static String TOKEN_SKI = "tokenSKI";
+ public final static String TOKEN_AKI = "tokenAKI";
+ public final static String TOKEN_ACCESS_DESC = "tokenAccessDesc";
+ public final static String TOKEN_OCSP_NOCHECK = "tokenOcspNoCheck";
+ public final static String TOKEN_EXTENDED_KEY_USAGE = "tokenExtendedKeyUsage";
+ public final static String TOKEN_PRIVATE_KEY_USAGE = "tokenPrivateKeyUsage";
+ public final static String TOKEN_PRESENCE_SERVER = "tokenPresenceServer";
+ public final static String TOKEN_AIA = "tokenAIA";
+ public final static String TOKEN_KEY_USAGE = "tokenKeyUsage";
+ public final static String TOKEN_CERT_USAGE = "tokenCertUsage";
+ public final static String TOKEN_KEY_ID = "tokenKeyId";
+ public final static String TOKEN_AUTH_NAME = "tokenAuthName";
+
+ public final static String TOKEN_CRL = "tokenCRL";
+ public final static String TOKEN_THIS_UPDATE = "tokenThisUpdate";
+ public final static String TOKEN_NEXT_UPDATE = "tokenNextUpdate";
+ public final static String TOKEN_REVOKED_CERTIFICATES = "revokedCerts";
+ public final static String TOKEN_REVOCATION_DATE = "revocationDate";
+
+ public final static String TOKEN_REVOCATION_REASON = "revocationReason";
+ public final static String TOKEN_REASON = "reason";
+
+ public final static String TOKEN_BASIC_CONSTRAINTS = "basicConstraints";
+ public final static String TOKEN_NAME_CONSTRAINTS = "tokenNameConstraints";
+ public final static String TOKEN_NSC_COMMENT = "tokenNSCComment";
+ public final static String TOKEN_IS_CA = "isCA";
+ public final static String TOKEN_PATH_LEN = "pathLen";
+ public final static String TOKEN_PATH_LEN_UNLIMITED = "pathLenUnlimited";
+ public final static String TOKEN_PATH_LEN_UNDEFINED = "pathLenUndefined";
+ public final static String TOKEN_PATH_LEN_INVALID = "pathLenInvalid";
+
+ public final static String TOKEN_CRL_NUMBER = "CRLNumber";
+ public final static String TOKEN_NUMBER = "Number";
+
+ public final static String TOKEN_DELTA_CRL_INDICATOR = "DeltaCRLIndicator";
+ public final static String TOKEN_BASE_CRL_NUMBER = "BaseCRLNumber";
+
+ public final static String TOKEN_CERT_SCOPE_OF_USE = "CertificateScopeOfUse";
+ public final static String TOKEN_SCOPE_OF_USE = "ScopeOfUse";
+ public final static String TOKEN_PORT = "Port";
+
+ public final static String TOKEN_ISSUER_ALT_NAME = "IssuerAlternativeName";
+ public final static String TOKEN_ISSUER_NAMES = "IssuerNames";
+
+ public final static String TOKEN_SUBJECT_ALT_NAME = "SubjectAlternativeName";
+ public final static String TOKEN_SUBJECT_NAME = "SubjectName";
+
+ public final static String TOKEN_DECODING_ERROR = "decodingError";
+
+ public final static String TOKEN_FRESHEST_CRL_EXT = "FreshestCRL";
+
+ public final static String TOKEN_CRL_DP_EXT = "CRLDistributionPoints";
+ public final static String TOKEN_CRLDP_NUMPOINTS = "CRLDP_NUMPOINTS";
+ public final static String TOKEN_CRLDP_POINTN = "CRLDP_POINTN";
+ public final static String TOKEN_CRLDP_DISTPOINT = "CRLDP_DISTPOINT";
+ public final static String TOKEN_CRLDP_REASONS = "CRLDP_REASONS";
+ public final static String TOKEN_CRLDP_CRLISSUER = "CRLDP_CRLISSUER";
+
+ public final static String TOKEN_ISSUING_DIST_POINT = "IssuingDistributionPoint";
+ public final static String TOKEN_DIST_POINT_NAME = "DistributionPointName";
+ public final static String TOKEN_FULL_NAME = "FullName";
+ public final static String TOKEN_RELATIVE_NAME = "NameRelativeToCRLIssuer";
+ public final static String TOKEN_ONLY_USER_CERTS = "OnlyContainsUserCerts";
+ public final static String TOKEN_ONLY_CA_CERTS = "OnlyContainsCACerts";
+ public final static String TOKEN_ONLY_SOME_REASONS = "OnlySomeReasons";
+ public final static String TOKEN_INDIRECT_CRL = "IndirectCRL";
+
+ public final static String TOKEN_INVALIDITY_DATE = "invalidityDate";
+ public final static String TOKEN_DATE_OF_INVALIDITY = "dateOfInvalidity";
+
+ public final static String TOKEN_CERTIFICATE_ISSUER = "CertificateIssuer";
+
+ public final static String TOKEN_HOLD_INSTRUCTION = "HoldInstruction";
+ public final static String TOKEN_HOLD_INSTRUCTION_CODE = "HoldInstructionCode";
+ public final static String TOKEN_POLICY_CONSTRAINTS = "PolicyConstraints";
+ public final static String TOKEN_POLICY_MAPPINGS = "PolicyMappings";
+ public final static String TOKEN_SUBJECT_DIR_ATTR = "SubjectDirectoryAttributes";
+
+ // policy constriants extension fields
+ public final static String TOKEN_INHIBIT_POLICY_MAPPING = "inhibitPolicyMapping";
+ public final static String TOKEN_REQUIRE_EXPLICIT_POLICY = "requireExplicitPolicy";
+
+ // policy mappings extension fields
+ public final static String TOKEN_MAPPINGS = "mappings";
+ public final static String TOKEN_MAP = "map";
+ public final static String TOKEN_ISSUER_DOMAIN_POLICY = "issuerDomainPolicy";
+ public final static String TOKEN_SUBJECT_DOMAIN_POLICY = "subjectDomainPolicy";
+
+ // subject directory attribute fields
+ public final static String TOKEN_ATTRIBUTES = "Attributes";
+ public final static String TOKEN_ATTRIBUTE = "Attribute";
+ public final static String TOKEN_VALUES = "Values";
+
+ // field values
+ public final static String TOKEN_NOT_SET = "notSet";
+ public final static String TOKEN_NONE = "none";
+
+ public final static String TOKEN_CACHE_NOT_AVAILABLE = "cacheNotAvailable";
+ public final static String TOKEN_CACHE_IS_EMPTY = "cacheIsEmpty";
+
+ //Tokens should have blank_space as trailer
+ static final Object[][] contents = {
+ { TOKEN_CERTIFICATE, "Certificate: " },
+ { TOKEN_DATA, "Data: " },
+ { TOKEN_VERSION, "Version: " },
+ { TOKEN_SERIAL, "Serial Number: " },
+ { TOKEN_SIGALG, "Signature Algorithm: " },
+ { TOKEN_ISSUER, "Issuer: " },
+ { TOKEN_VALIDITY, "Validity: " },
+ { TOKEN_NOT_BEFORE, "Not Before: " },
+ { TOKEN_NOT_AFTER, "Not After: " },
+ { TOKEN_SUBJECT, "Subject: " },
+ { TOKEN_SPKI, "Subject Public Key Info: " },
+ { TOKEN_ALGORITHM, "Algorithm: " },
+ { TOKEN_PUBLIC_KEY, "Public Key: " },
+ { TOKEN_PUBLIC_KEY_MODULUS, "Public Key Modulus: " },
+ { TOKEN_PUBLIC_KEY_EXPONENT, "Exponent: " },
+ { TOKEN_EXTENSIONS, "Extensions: " },
+ { TOKEN_SIGNATURE, "Signature: " },
+ { TOKEN_YES, "yes " },
+ { TOKEN_NO, "no " },
+ { TOKEN_IDENTIFIER, "Identifier: " },
+ { TOKEN_CRITICAL, "Critical: " },
+ { TOKEN_VALUE, "Value: " },
+ { TOKEN_KEY_TYPE, "Key Type " },
+ { TOKEN_CERT_TYPE, "Netscape Certificate Type " },
+ { TOKEN_SKI, "Subject Key Identifier " },
+ { TOKEN_AKI, "Authority Key Identifier " },
+ { TOKEN_ACCESS_DESC, "Access Description: " },
+ { TOKEN_OCSP_NOCHECK, "OCSP NoCheck: " },
+ { TOKEN_EXTENDED_KEY_USAGE, "Extended Key Usage: " },
+ { TOKEN_PRIVATE_KEY_USAGE, "Private Key Usage: " },
+ { TOKEN_PRESENCE_SERVER, "Presence Server: " },
+ { TOKEN_AIA, "Authority Info Access: " },
+ { TOKEN_KEY_USAGE, "Key Usage: " },
+ { KeyUsageExtension.DIGITAL_SIGNATURE, "Digital Signature " },
+ { KeyUsageExtension.NON_REPUDIATION, "Non Repudiation " },
+ { KeyUsageExtension.KEY_ENCIPHERMENT, "Key Encipherment " },
+ { KeyUsageExtension.DATA_ENCIPHERMENT, "Data Encipherment " },
+ { KeyUsageExtension.KEY_AGREEMENT, "Key Agreement " },
+ { KeyUsageExtension.KEY_CERTSIGN, "Key CertSign " },
+ { KeyUsageExtension.CRL_SIGN, "Crl Sign " },
+ { KeyUsageExtension.ENCIPHER_ONLY, "Encipher Only " },
+ { KeyUsageExtension.DECIPHER_ONLY, "Decipher Only " },
+ { TOKEN_CERT_USAGE, "Certificate Usage: " },
+ { NSCertTypeExtension.SSL_CLIENT, "SSL Client " },
+ { NSCertTypeExtension.SSL_SERVER, "SSL Server " },
+ { NSCertTypeExtension.EMAIL, "Secure Email " },
+ { NSCertTypeExtension.OBJECT_SIGNING, "Object Signing " },
+ { NSCertTypeExtension.SSL_CA, "SSL CA " },
+ { NSCertTypeExtension.EMAIL_CA, "Secure Email CA " },
+ { NSCertTypeExtension.OBJECT_SIGNING_CA, "ObjectSigning CA " },
+ { TOKEN_KEY_ID, "Key Identifier: " },
+ { TOKEN_AUTH_NAME, "Authority Name: " },
+ { TOKEN_CRL, "Certificate Revocation List: " },
+ { TOKEN_THIS_UPDATE, "This Update: " },
+ { TOKEN_NEXT_UPDATE, "Next Update: " },
+ { TOKEN_REVOKED_CERTIFICATES, "Revoked Certificates: " },
+ { TOKEN_REVOCATION_DATE, "Revocation Date: " },
+ { TOKEN_REVOCATION_REASON, "Revocation Reason " },
+ { TOKEN_REASON, "Reason: " },
+ { TOKEN_BASIC_CONSTRAINTS, "Basic Constraints " },
+ { TOKEN_NAME_CONSTRAINTS, "Name Constraints " },
+ { TOKEN_NSC_COMMENT, "Netscape Comment " },
+ { TOKEN_IS_CA, "Is CA: " },
+ { TOKEN_PATH_LEN, "Path Length Constraint: " },
+ { TOKEN_PATH_LEN_UNLIMITED, "UNLIMITED" },
+ { TOKEN_PATH_LEN_UNDEFINED, "UNDEFINED" },
+ { TOKEN_PATH_LEN_INVALID, "INVALID" },
+ { TOKEN_CRL_NUMBER, "CRL Number " },
+ { TOKEN_NUMBER, "Number: " },
+ { TOKEN_DELTA_CRL_INDICATOR, "Delta CRL Indicator " },
+ { TOKEN_BASE_CRL_NUMBER, "Base CRL Number: " },
+ { TOKEN_CERT_SCOPE_OF_USE, "Certificate Scope of Use " },
+ { TOKEN_SCOPE_OF_USE, "Scope of Use: " },
+ { TOKEN_PORT, "Port: " },
+ { TOKEN_ISSUER_ALT_NAME, "Issuer Alternative Name " },
+ { TOKEN_ISSUER_NAMES, "Issuer Names: " },
+ { TOKEN_SUBJECT_ALT_NAME, "Subject Alternative Name " },
+ { TOKEN_DECODING_ERROR, "Decoding Error" },
+ { TOKEN_FRESHEST_CRL_EXT, "Freshest CRL " },
+ { TOKEN_CRL_DP_EXT, "CRL Distribution Points " },
+ { TOKEN_CRLDP_NUMPOINTS, "Number of Points: " },
+ { TOKEN_CRLDP_POINTN, "Point " },
+ { TOKEN_CRLDP_DISTPOINT, "Distribution Point: " },
+ { TOKEN_CRLDP_REASONS, "Reason Flags: " },
+ { TOKEN_CRLDP_CRLISSUER, "CRL Issuer: " },
+ { TOKEN_ISSUING_DIST_POINT, "Issuing Distribution Point " },
+ { TOKEN_DIST_POINT_NAME, "Distribution Point: " },
+ { TOKEN_FULL_NAME, "Full Name: " },
+ { TOKEN_RELATIVE_NAME, "Name Relative To CRL Issuer: " },
+ { TOKEN_ONLY_USER_CERTS, "Only Contains User Certificates: " },
+ { TOKEN_ONLY_CA_CERTS, "Only Contains CA Certificates: " },
+ { TOKEN_ONLY_SOME_REASONS, "Only Some Reasons: " },
+ { TOKEN_INDIRECT_CRL, "Indirect CRL: " },
+ { TOKEN_INVALIDITY_DATE, "Invalidity Date " },
+ { TOKEN_DATE_OF_INVALIDITY, "Invalidity Date: " },
+ { TOKEN_CERTIFICATE_ISSUER, "Certificate Issuer " },
+ { TOKEN_HOLD_INSTRUCTION, "Hold Instruction Code " },
+ { TOKEN_HOLD_INSTRUCTION_CODE, "Hold Instruction Code: " },
+ { TOKEN_POLICY_CONSTRAINTS, "Policy Constraints " },
+ { TOKEN_INHIBIT_POLICY_MAPPING, "Inhibit Policy Mapping: " },
+ { TOKEN_REQUIRE_EXPLICIT_POLICY, "Require Explicit Policy: " },
+ { TOKEN_POLICY_MAPPINGS, "Policy Mappings " },
+ { TOKEN_MAPPINGS, "Mappings: " },
+ { TOKEN_MAP, "Map " },
+ { TOKEN_ISSUER_DOMAIN_POLICY, "Issuer Domain Policy: " },
+ { TOKEN_SUBJECT_DOMAIN_POLICY, "Subject Domain Policy: " },
+ { TOKEN_SUBJECT_DIR_ATTR, "Subject Directory Attributes " },
+ { TOKEN_ATTRIBUTES, "Attributes:" },
+ { TOKEN_ATTRIBUTE, "Attribute " },
+ { TOKEN_VALUES, "Values: " },
+ { TOKEN_NOT_SET, "not set" },
+ { TOKEN_NONE, "none" },
+ { TOKEN_CACHE_NOT_AVAILABLE, "CRL cache is not available. " },
+ { TOKEN_CACHE_IS_EMPTY, "CRL cache is empty. " },
+ };
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/cert/PubKeyPrettyPrint.java b/base/server/cmscore/src/com/netscape/cmscore/cert/PubKeyPrettyPrint.java
new file mode 100644
index 000000000..5c5b13084
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/cert/PubKeyPrettyPrint.java
@@ -0,0 +1,35 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.cert;
+
+import java.security.PublicKey;
+
+/**
+ * This class will display the certificate content in predefined
+ * format.
+ *
+ * @author Jack Pan-Chen
+ * @author Andrew Wnuk
+ * @version $Revision$, $Date$
+ */
+public class PubKeyPrettyPrint extends netscape.security.util.PubKeyPrettyPrint {
+
+ public PubKeyPrettyPrint(PublicKey key) {
+ super(key);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/cert/X500NameSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/cert/X500NameSubsystem.java
new file mode 100644
index 000000000..7accf2b4f
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/cert/X500NameSubsystem.java
@@ -0,0 +1,285 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.cert;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+import netscape.security.util.DerValue;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AVAValueConverter;
+import netscape.security.x509.DirStrConverter;
+import netscape.security.x509.X500NameAttrMap;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * Subsystem for configuring X500Name related things.
+ * It is used for the following.
+ * <ul>
+ * <li>Add X500Name (string to oid) maps for attributes that are not supported by default.
+ * <li>Specify an order for encoding Directory Strings other than the default.
+ * </ul>
+ *
+ * @author lhsiao
+ * @version $Revision$
+ */
+public class X500NameSubsystem implements ISubsystem {
+
+ private IConfigStore mConfig = null;
+ public static final String ID = "X500Name";
+ private String mId = ID;
+
+ private static final String PROP_DIR_STR_ENCODING_ORDER = "directoryStringEncodingOrder";
+
+ private static final String PROP_ATTR = "attr";
+ private static final String PROP_OID = "oid";
+ private static final String PROP_CLASS = "class";
+
+ private X500NameSubsystem() {
+ }
+
+ /**
+ * Retrieves subsystem identifier.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ // singleton enforcement
+
+ private static X500NameSubsystem mInstance = new X500NameSubsystem();
+
+ public static X500NameSubsystem getInstance() {
+ return mInstance;
+ }
+
+ /**
+ * Initializes this subsystem with the given configuration store.
+ * All paramters are optional.
+ * <ul>
+ * <li>Change encoding order of Directory Strings:
+ *
+ * <pre>
+ * X500Name.directoryStringEncodingOrder=order seperated by commas
+ * For example: Printable,BMPString,UniversalString.
+ * </pre>
+ *
+ * Possible values are:
+ * <ul>
+ * <li>Printable
+ * <li>IA5String
+ * <li>UniversalString
+ * <li>BMPString
+ * <li>UTF8String
+ * </ul>
+ * <p>
+ * <li>Add X500Name attributes:
+ *
+ * <pre>
+ * X500Name.attr.attribute-name.oid=n.n.n.n
+ * X500Name.attr.attribute-name.class=value converter class
+ * </pre>
+ *
+ * The value converter class converts a string to a ASN.1 value. It must implement
+ * netscape.security.x509.AVAValueConverter interface. Converter classes provided in CMS are:
+ *
+ * <pre>
+ * netscape.security.x509.PrintableConverter -
+ * Converts to a Printable String value. String must have only
+ * printable characters.
+ * netscape.security.x509.IA5StringConverter -
+ * Converts to a IA5String value. String must have only IA5String
+ * characters.
+ * netscape.security.x509.DirStrConverter -
+ * Converts to a Directory (v3) String. String is expected to
+ * be in Directory String format according to rfc2253.
+ * netscape.security.x509.GenericValueConverter -
+ * Converts string character by character in the following order
+ * from smaller character sets to broadest character set.
+ * Printable, IA5String, BMPString, Universal String.
+ * </pre>
+ *
+ * </ul>
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration store
+ */
+ public synchronized void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mLogger = CMS.getLogger();
+ if (Debug.ON) {
+ Debug.trace(ID + " started");
+ }
+ mConfig = config;
+
+ // get order for encoding directory strings if any.
+ setDirStrEncodingOrder();
+
+ // load x500 name maps
+ loadX500NameAttrMaps();
+ }
+
+ /**
+ * Loads X500Name String to attribute maps.
+ * Called from init.
+ */
+ private void loadX500NameAttrMaps()
+ throws EBaseException {
+ X500NameAttrMap globalMap = X500NameAttrMap.getDefault();
+ IConfigStore attrSubStore = mConfig.getSubStore(PROP_ATTR);
+ Enumeration<String> attrNames = attrSubStore.getSubStoreNames();
+
+ while (attrNames.hasMoreElements()) {
+ String name = attrNames.nextElement();
+ IConfigStore substore = attrSubStore.getSubStore(name);
+ String oidString = substore.getString(PROP_OID);
+ ObjectIdentifier oid = CertUtils.checkOID(name, oidString);
+ String className = substore.getString(PROP_CLASS);
+
+ AVAValueConverter convClass = null;
+
+ try {
+ convClass = (AVAValueConverter)
+ Class.forName(className).newInstance();
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_LOAD_CLASS_FAILED", className, e.toString()));
+ }
+ globalMap.addNameOID(name, oid, convClass);
+ if (Debug.ON) {
+ Debug.trace(ID + ": Loaded " + name + " " + oid + " " + className);
+ }
+ }
+ }
+
+ /**
+ * Set directory string encoding order.
+ * Called from init().
+ */
+ private void setDirStrEncodingOrder()
+ throws EBaseException {
+ String order = mConfig.getString(PROP_DIR_STR_ENCODING_ORDER, null);
+
+ if (order == null || order.length() == 0) // nothing.
+ return;
+ StringTokenizer toker = new StringTokenizer(order, ", \t");
+ int numTokens = toker.countTokens();
+
+ if (numTokens == 0) {
+ String msg = "must be a list of DER tag names seperated by commas.";
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CERT_DIR_STRING", PROP_DIR_STR_ENCODING_ORDER));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ PROP_DIR_STR_ENCODING_ORDER, msg));
+ }
+
+ byte[] tags = new byte[numTokens];
+
+ for (int i = 0; toker.hasMoreTokens(); i++) {
+ String nextTag = toker.nextToken();
+
+ try {
+ tags[i] = derStr2Tag(nextTag);
+ } catch (IllegalArgumentException e) {
+ String msg = "unknown DER tag '" + nextTag + "'.";
+
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_CERT_UNKNOWN_TAG", PROP_DIR_STR_ENCODING_ORDER, nextTag));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ PROP_DIR_STR_ENCODING_ORDER, msg));
+ }
+ }
+
+ DirStrConverter.setDefEncodingOrder(tags);
+ }
+
+ private static String PRINTABLESTRING = "PrintableString";
+ private static String IA5STRING = "IA5String";
+ private static String VISIBLESTRING = "VisibleString";
+ private static String T61STRING = "T61String";
+ private static String BMPSTRING = "BMPString";
+ private static String UNIVERSALSTRING = "UniversalString";
+ private static String UFT8STRING = "UTF8String";
+ private static Hashtable<String, Byte> mDerStr2TagHash = new Hashtable<String, Byte>();
+
+ static {
+ mDerStr2TagHash.put(
+ PRINTABLESTRING, Byte.valueOf(DerValue.tag_PrintableString));
+ mDerStr2TagHash.put(
+ IA5STRING, Byte.valueOf(DerValue.tag_IA5String));
+ mDerStr2TagHash.put(
+ VISIBLESTRING, Byte.valueOf(DerValue.tag_VisibleString));
+ mDerStr2TagHash.put(
+ T61STRING, Byte.valueOf(DerValue.tag_T61String));
+ mDerStr2TagHash.put(
+ BMPSTRING, Byte.valueOf(DerValue.tag_BMPString));
+ mDerStr2TagHash.put(
+ UNIVERSALSTRING, Byte.valueOf(DerValue.tag_UniversalString));
+ mDerStr2TagHash.put(
+ UFT8STRING, Byte.valueOf(DerValue.tag_UTF8String));
+ }
+
+ private byte derStr2Tag(String s) {
+ if (s == null || s.length() == 0)
+ throw new IllegalArgumentException();
+ Byte tag = mDerStr2TagHash.get(s);
+
+ if (tag == null)
+ throw new IllegalArgumentException();
+ return tag.byteValue();
+ }
+
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Stops this system.
+ */
+ public synchronized void shutdown() {
+ }
+
+ /*
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ protected ILogger mLogger = null;
+
+ protected synchronized void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM,
+ ILogger.S_ADMIN, level, msg);
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnFactory.java b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnFactory.java
new file mode 100644
index 000000000..a55a186e3
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnFactory.java
@@ -0,0 +1,299 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.connector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.connector.IHttpConnection;
+import com.netscape.certsrv.connector.IRemoteAuthority;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmsutil.http.JssSSLSocketFactory;
+import com.netscape.cmsutil.net.ISocketFactory;
+
+/**
+ * Factory for getting HTTP Connections to a HTTPO server
+ */
+public class HttpConnFactory {
+ protected int mMinConns = 1;
+ protected int mMaxConns = 30;
+
+ private ILogger mLogger = CMS.getLogger();
+
+ private int mNumConns = 0; // number of available conns in array
+ private int mTotal = 0; // total num conns
+ private IHttpConnection mConns[];
+ @SuppressWarnings("unused")
+ private IAuthority mSource;
+ private IRemoteAuthority mDest = null;
+ private String mNickname = "";
+ private int mTimeout = 0;
+
+ /**
+ * Constructor for initializing from the config store.
+ * must be followed by init(IConfigStore)
+ */
+ public HttpConnFactory() {
+ }
+
+ /**
+ * Constructor for HttpConnFactory
+ *
+ * @param minConns minimum number of connections to have available
+ * @param maxConns max number of connections to have available. This is
+ * @param serverInfo server connection info - host, port, etc.
+ */
+ public HttpConnFactory(int minConns, int maxConns, IAuthority source, IRemoteAuthority dest, String nickname,
+ int timeout) throws EBaseException {
+
+ CMS.debug("In HttpConnFactory constructor mTimeout " + timeout);
+ mSource = source;
+ mDest = dest;
+ mNickname = nickname;
+ mTimeout = timeout;
+
+ init(minConns, maxConns);
+ }
+
+ /**
+ * initialize parameters obtained from either constructor or
+ * config store
+ *
+ * @param minConns minimum number of connection handls to have available.
+ * @param maxConns maximum total number of connections to ever have.
+ * @param connInfo ldap connection info.
+ * @param authInfo ldap authentication info.
+ * @exception ELdapException if any error occurs.
+ */
+ private void init(int minConns, int maxConns
+ )
+ throws EBaseException {
+
+ CMS.debug("min conns " + minConns + " maxConns " + maxConns);
+ if (minConns <= 0 || maxConns <= 0 || minConns > maxConns) {
+ CMS.debug("bad values from CMS.cfg");
+
+ } else {
+
+ mMinConns = minConns;
+ mMaxConns = maxConns;
+ }
+
+ CMS.debug("before creating httpconn array");
+
+ mConns = new IHttpConnection[mMaxConns];
+
+ // Create connection handle and make initial connection
+
+ CMS.debug("before makeConnection");
+
+ CMS.debug(
+ "initializing HttpConnFactory with mininum " + mMinConns + " and maximum " + mMaxConns +
+ " connections to ");
+
+ // initalize minimum number of connection handles available.
+ //makeMinimum();
+
+ CMS.debug("leaving HttpConnFactory init.");
+ }
+
+ private IHttpConnection createConnection() throws EBaseException {
+
+ IHttpConnection retConn = null;
+
+ CMS.debug("In HttpConnFactory.createConnection.");
+
+ try {
+ ISocketFactory tFactory = new JssSSLSocketFactory(mNickname);
+
+ if (mTimeout == 0) {
+ retConn = CMS.getHttpConnection(mDest, tFactory);
+ } else {
+ retConn = CMS.getHttpConnection(mDest, tFactory, mTimeout);
+ }
+
+ } catch (Exception e) {
+
+ CMS.debug("can't make new Htpp Connection");
+
+ throw new EBaseException(
+ "Can't create new Http Connection");
+ }
+
+ return retConn;
+ }
+
+ /**
+ * makes the minumum number of connections
+ */
+ private void makeMinimum() throws EBaseException {
+
+ CMS.debug("In HttpConnFactory.makeMinimum.");
+ int increment;
+
+ if (mNumConns < mMinConns && mTotal <= mMaxConns) {
+
+ increment = Math.min(mMinConns - mNumConns, mMaxConns - mTotal);
+
+ if (increment == 0)
+ return;
+
+ CMS.debug(
+ "increasing minimum connections by " + increment);
+ for (int i = increment - 1; i >= 0; i--) {
+ mConns[i] = createConnection();
+ }
+ mTotal += increment;
+ mNumConns += increment;
+ CMS.debug("new total available http connections " + mTotal);
+ CMS.debug("new number of http connections " + mNumConns);
+ }
+ }
+
+ /**
+ * gets a conenction from this factory.
+ * All connections obtained from the factory must be returned by
+ * returnConn() method.
+ * The best thing to do is to put returnConn in a finally clause so it
+ * always gets called. For example,
+ *
+ * <pre>
+ * IHttpConnection c = null;
+ * try {
+ * c = factory.getConn();
+ * myclass.do_something_with_c(c);
+ * } catch (EBaseException e) {
+ * handle_error_here();
+ * } finally {
+ * factory.returnConn(c);
+ * }
+ * </pre>
+ */
+ public IHttpConnection getConn()
+ throws EBaseException {
+ return getConn(true);
+ }
+
+ /**
+ * Returns a Http connection - a clone of the master connection.
+ * All connections should be returned to the factory using returnConn()
+ * to recycle connection objects.
+ * If not returned the limited max number is affected but if that
+ * number is large not much harm is done.
+ * Returns null if maximum number of connections reached.
+ * The best thing to do is to put returnConn in a finally clause so it
+ * always gets called. For example,
+ *
+ * <pre>
+ * IHttpConnnection c = null;
+ * try {
+ * c = factory.getConn();
+ * myclass.do_something_with_c(c);
+ * } catch (EBaseException e) {
+ * handle_error_here();
+ * } finally {
+ * factory.returnConn(c);
+ * }
+ * </pre>
+ */
+ public synchronized IHttpConnection getConn(boolean waitForConn)
+ throws EBaseException {
+ boolean waited = false;
+
+ CMS.debug("In HttpConnFactory.getConn");
+ if (mNumConns == 0)
+ makeMinimum();
+ if (mNumConns == 0) {
+ if (!waitForConn)
+ return null;
+ try {
+ CMS.debug("getConn: out of http connections");
+ log(ILogger.LL_WARN,
+ "Ran out of http connections available ");
+ waited = true;
+ CMS.debug("HttpConn:about to wait for a new http connection");
+ while (mNumConns == 0)
+ wait();
+
+ CMS.debug("HttpConn:done waiting for new http connection");
+ } catch (InterruptedException e) {
+ }
+ }
+ mNumConns--;
+ IHttpConnection conn = mConns[mNumConns];
+
+ mConns[mNumConns] = null;
+
+ if (waited) {
+ CMS.debug("HttpConn:had to wait for an available connection from pool");
+ log(ILogger.LL_WARN,
+ "Http connections are available again in http connection pool ");
+ }
+ CMS.debug("HttpgetConn: mNumConns now " + mNumConns);
+
+ return conn;
+ }
+
+ /**
+ * Teturn connection to the factory.
+ * This is mandatory after a getConn().
+ * The best thing to do is to put returnConn in a finally clause so it
+ * always gets called. For example,
+ *
+ * <pre>
+ * IHttpConnection c = null;
+ * try {
+ * c = factory.getConn();
+ * myclass.do_something_with_c(c);
+ * } catch (EBaseException e) {
+ * handle_error_here();
+ * } finally {
+ * factory.returnConn(c);
+ * }
+ * </pre>
+ */
+ public synchronized void returnConn(IHttpConnection conn) {
+
+ CMS.debug("In HttpConnFactory.returnConn");
+ if (conn == null) {
+ return;
+ }
+ IHttpConnection boundconn = conn;
+
+ for (int i = 0; i < mNumConns; i++) {
+ if (mConns[i] == conn) {
+ CMS.debug(
+ "returnConn: previously returned connection. " + conn);
+
+ }
+ }
+ mConns[mNumConns++] = boundconn;
+ CMS.debug("HttpreturnConn: mNumConns now " + mNumConns);
+ notify();
+ }
+
+ /**
+ * handy routine for logging in this class.
+ */
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "In Http (bound) connection pool to" +
+ msg);
+ }
+} \ No newline at end of file
diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java
new file mode 100644
index 000000000..7a65c1760
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java
@@ -0,0 +1,244 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.connector;
+
+import java.io.IOException;
+import java.util.StringTokenizer;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.connector.IHttpConnection;
+import com.netscape.certsrv.connector.IPKIMessage;
+import com.netscape.certsrv.connector.IRemoteAuthority;
+import com.netscape.certsrv.connector.IRequestEncoder;
+import com.netscape.cmscore.util.Debug;
+import com.netscape.cmsutil.http.HttpClient;
+import com.netscape.cmsutil.http.HttpRequest;
+import com.netscape.cmsutil.http.HttpResponse;
+import com.netscape.cmsutil.net.ISocketFactory;
+
+public class HttpConnection implements IHttpConnection {
+ protected IRemoteAuthority mDest = null;
+ protected HttpRequest mHttpreq = new HttpRequest();
+ protected IRequestEncoder mReqEncoder = null;
+ protected HttpClient mHttpClient = null;
+
+ protected boolean Connect(String host, HttpClient client) {
+ StringTokenizer st = new StringTokenizer(host, " ");
+ while (st.hasMoreTokens()) {
+ String hp = st.nextToken(); // host:port
+ StringTokenizer st1 = new StringTokenizer(hp, ":");
+ try {
+ String h = st1.nextToken();
+ int p = Integer.parseInt(st1.nextToken());
+ client.connect(h, p);
+ return true;
+ } catch (Exception e) {
+ // may want to log the failure
+ }
+ try {
+ Thread.sleep(5000); // 5 seconds
+ } catch (Exception e) {
+ }
+
+ }
+ return false;
+ }
+
+ public HttpConnection(IRemoteAuthority dest, ISocketFactory factory) {
+ mDest = dest;
+ mReqEncoder = new HttpRequestEncoder();
+ mHttpClient = new HttpClient(factory);
+ if (Debug.ON)
+ Debug.trace("Created HttpClient");
+ try {
+ mHttpreq.setMethod("POST");
+ mHttpreq.setURI(mDest.getURI());
+ mHttpreq.setHeader("Connection", "Keep-Alive");
+ CMS.debug("HttpConnection: connecting to " + dest.getHost() + ":" + dest.getPort());
+ String host = dest.getHost();
+ // we could have a list of host names in the host parameters
+ // the format is, for example,
+ // "directory.knowledge.com:1050 people.catalog.com 199.254.1.2"
+ if (host != null && host.indexOf(' ') != -1) {
+ // try to do client-side failover
+ boolean connected = false;
+ do {
+ connected = Connect(host, mHttpClient);
+ } while (!connected);
+ } else {
+ mHttpClient.connect(host, dest.getPort());
+ }
+ CMS.debug("HttpConnection: connected to " + dest.getHost() + ":" + dest.getPort());
+ } catch (IOException e) {
+ // server's probably down. that's fine. try later.
+ //System.out.println(
+ //"Can't connect to server in connection creation");
+ }
+ }
+
+ // Inserted by beomsuk
+ public HttpConnection(IRemoteAuthority dest, ISocketFactory factory, int timeout) {
+ mDest = dest;
+ mReqEncoder = new HttpRequestEncoder();
+ mHttpClient = new HttpClient(factory);
+ CMS.debug("HttpConn:Created HttpConnection: factory " + factory + "client " + mHttpClient);
+ try {
+ mHttpreq.setMethod("POST");
+ mHttpreq.setURI(mDest.getURI());
+ mHttpreq.setHeader("Connection", "Keep-Alive");
+ CMS.debug("HttpConnection: connecting to " + dest.getHost() + ":" + dest.getPort() + " timeout:" + timeout);
+ mHttpClient.connect(dest.getHost(), dest.getPort(), timeout);
+ CMS.debug("HttpConnection: connected to " + dest.getHost() + ":" + dest.getPort() + " timeout:" + timeout);
+ } catch (IOException e) {
+ // server's probably down. that's fine. try later.
+ //System.out.println(
+ //"Can't connect to server in connection creation");
+ CMS.debug("CMSConn:IOException in creating HttpConnection " + e.toString());
+ }
+ }
+
+ // Insert end
+ /**
+ * sends a request to remote RA/CA, returning the result.
+ *
+ * @throws EBaseException if request could not be encoded
+ */
+ public IPKIMessage send(IPKIMessage tomsg)
+ throws EBaseException {
+ IPKIMessage replymsg = null;
+
+ CMS.debug("in HttpConnection.send " + this);
+ if (Debug.ON)
+ Debug.trace("encoding request ");
+ String content = null;
+
+ try {
+ content = mReqEncoder.encode(tomsg);
+ } catch (IOException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", "Could not encode request"));
+ }
+ if (Debug.ON) {
+ Debug.trace("encoded request");
+ Debug.trace("------ " + content.length() + "-----");
+ Debug.trace(content);
+ Debug.trace("--------------------------");
+ }
+ boolean reconnect = false;
+
+ mHttpreq.setHeader("Content-Length",
+ Integer.toString(content.length()));
+ if (Debug.ON)
+ Debug.trace("request encoded length " + content.length());
+ mHttpreq.setContent(content);
+
+ HttpResponse p = null;
+
+ try {
+ if (!mHttpClient.connected()) {
+ mHttpClient.connect(mDest.getHost(), mDest.getPort());
+ CMS.debug("HttpConn:reconnected to " + mDest.getHost() + ":" + mDest.getPort());
+ reconnect = true;
+ }
+ } catch (IOException e) {
+ if (e.getMessage().indexOf("Peer's certificate issuer has been marked as not trusted") != -1) {
+ throw new EBaseException(
+ CMS.getUserMessage(
+ "CMS_BASE_CONN_FAILED",
+ "(This local authority cannot connect to the remote authority. The local authority's signing certificate must chain to a CA certificate trusted for client authentication in the certificate database. Use the certificate manager, or command line tool such as certutil to verify that the trust permissions of the local authority's issuer cert have 'CT' setting in the SSL client auth field.)"));
+ }
+ CMS.debug("HttpConn:Couldn't reconnect " + e);
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", "Couldn't reconnect " + e));
+ }
+
+ // if remote closed connection want to reconnect and resend.
+ while (p == null) {
+ try {
+ if (Debug.ON)
+ Debug.trace("sending request");
+ p = mHttpClient.send(mHttpreq);
+ } catch (IOException e) {
+ CMS.debug("HttpConn: mHttpClient.send failed " + e.toString());
+ if (reconnect) {
+ CMS.debug("HttpConn:resend failed again. " + e);
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", "resend failed again. " + e));
+ }
+ try {
+ CMS.debug("HttpConn: trying a reconnect ");
+ mHttpClient.connect(mDest.getHost(), mDest.getPort());
+ } catch (IOException ex) {
+ CMS.debug("reconnect for resend failed. " + ex);
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", "reconnect for resend failed."
+ + ex));
+ }
+ reconnect = true;
+ }
+ }
+
+ // got reply; check status
+ String statusStr = p.getStatusCode();
+
+ CMS.debug("HttpConn:server returned status " + statusStr);
+ int statuscode = -1;
+
+ try {
+ statuscode = Integer.parseInt(statusStr);
+ } catch (NumberFormatException e) {
+ statuscode = -1;
+ }
+
+ /* HttpServletResponse.SC_OK = 200 */
+ if (statuscode != 200) {
+
+ /* HttpServletResponse.SC_UNAUTHORIZED = 401 */
+ if (statuscode == 401) {
+ // XXX what to do here.
+ String msg = "request no good " + statuscode + " " + p.getReasonPhrase();
+
+ if (Debug.ON)
+ Debug.trace(msg);
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_AUTHENTICATE_FAILED", msg));
+ } else {
+ // XXX what to do here.
+ String msg = "HttpConn:request no good " + statuscode + " " + p.getReasonPhrase();
+
+ CMS.debug(msg);
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", msg));
+ }
+ }
+
+ // decode reply.
+ // if reply is bad, error is thrown and request will be resent
+ String pcontent = p.getContent();
+
+ if (Debug.ON) {
+ Debug.trace("Server returned\n");
+ Debug.trace("-------");
+ Debug.trace(pcontent);
+ Debug.trace("-------");
+ }
+
+ try {
+ replymsg = (IPKIMessage) mReqEncoder.decode(pcontent);
+ } catch (IOException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", "Could not decode content"));
+ }
+ CMS.debug("HttpConn:decoded reply");
+ return replymsg;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnector.java b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnector.java
new file mode 100644
index 000000000..33b0d62b7
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnector.java
@@ -0,0 +1,211 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.connector;
+
+import java.util.Vector;
+
+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.connector.IConnector;
+import com.netscape.certsrv.connector.IHttpConnection;
+import com.netscape.certsrv.connector.IHttpPKIMessage;
+import com.netscape.certsrv.connector.IRemoteAuthority;
+import com.netscape.certsrv.connector.IResender;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cmsutil.http.JssSSLSocketFactory;
+import com.netscape.cmsutil.net.ISocketFactory;
+
+public class HttpConnector implements IConnector {
+ protected IAuthority mSource = null;
+ protected IRemoteAuthority mDest = null;
+ protected ISocketFactory mFactory = null;
+
+ // XXX todo make this a pool.
+ // XXX use CMMF in the future.
+ protected IHttpConnection mConn = null;
+ private IResender mResender = null;
+ @SuppressWarnings("unused")
+ private int mTimeout;
+
+ private HttpConnFactory mConnFactory = null;
+
+ public HttpConnector(IAuthority source, String nickName,
+ IRemoteAuthority dest, int resendInterval, IConfigStore config) throws EBaseException {
+
+ mTimeout = 0;
+ mSource = source;
+ mDest = dest;
+ mFactory = new JssSSLSocketFactory(nickName);
+
+ int minConns = config.getInteger("minHttpConns", 1);
+ int maxConns = config.getInteger("maxHttpConns", 15);
+
+ CMS.debug("HttpConn: min " + minConns);
+ CMS.debug("HttpConn: max " + maxConns);
+
+ try {
+ mConnFactory = new HttpConnFactory(minConns, maxConns, source, dest, nickName, 0);
+ } catch (EBaseException e) {
+ CMS.debug("can't create new HttpConnFactory " + e.toString());
+ }
+
+ // mConn = CMS.getHttpConnection(dest, mFactory);
+ // this will start resending past requests in parallel.
+ mResender = CMS.getResender(mSource, nickName, dest, resendInterval);
+ }
+
+ // Inserted by beomsuk
+ public HttpConnector(IAuthority source, String nickName,
+ IRemoteAuthority dest, int resendInterval, IConfigStore config, int timeout) throws EBaseException {
+ mSource = source;
+ mDest = dest;
+ mTimeout = timeout;
+ mFactory = new JssSSLSocketFactory(nickName);
+
+ int minConns = config.getInteger("minHttpConns", 1);
+ int maxConns = config.getInteger("maxHttpConns", 15);
+
+ CMS.debug("HttpConn: min " + minConns);
+ CMS.debug("HttpConn: max " + maxConns);
+
+ try {
+ mConnFactory = new HttpConnFactory(minConns, maxConns, source, dest, nickName, timeout);
+ } catch (EBaseException e) {
+ CMS.debug("can't create new HttpConnFactory");
+ }
+
+ // this will start resending past requests in parallel.
+ mResender = CMS.getResender(mSource, nickName, dest, resendInterval);
+ }
+
+ // Insert end
+
+ public boolean send(IRequest r)
+ throws EBaseException {
+ IHttpConnection curConn = null;
+
+ try {
+ IHttpPKIMessage tomsg = (IHttpPKIMessage) CMS.getHttpPKIMessage();
+ HttpPKIMessage replymsg = null;
+
+ tomsg.fromRequest(r);
+ CMS.debug("Before synch");
+
+ curConn = mConnFactory.getConn();
+
+ CMS.debug("HttpConnector.send " + curConn);
+
+ replymsg = (HttpPKIMessage) curConn.send(tomsg);
+
+ if (replymsg == null) {
+ CMS.debug("HttpConncter. replymsg is null");
+ return false;
+ }
+
+ CMS.debug("HttpConncter.send has been called");
+
+ RequestStatus replyStatus;
+ RequestId replyRequestId;
+
+ replyStatus = RequestStatus.fromString(replymsg.reqStatus);
+ int index = replymsg.reqId.lastIndexOf(':');
+
+ replyRequestId = new RequestId(replymsg.reqId.substring(index + 1));
+ CMS.debug("reply request id " + replyRequestId);
+ r.setExtData(IRequest.REMOTE_REQID, replyRequestId.toString());
+
+ CMS.debug("reply request type " + r.getRequestType());
+ CMS.debug("reply status " + replyStatus);
+
+ // non terminal states.
+ // XXX hack: don't resend get revocation info requests since
+ // resent results are ignored.
+ if ((!r.getRequestType().equals(
+ IRequest.GETREVOCATIONINFO_REQUEST)) &&
+ (replyStatus == RequestStatus.BEGIN ||
+ replyStatus == RequestStatus.PENDING ||
+ replyStatus == RequestStatus.SVC_PENDING ||
+ replyStatus == RequestStatus.APPROVED)) {
+ CMS.debug("HttpConn: remote request id still pending " +
+ r.getRequestId() + " state " + replyStatus);
+ mSource.log(ILogger.LL_INFO,
+ CMS.getLogMessage("CMSCORE_CONNECTOR_REQUEST_NOT_COMPLETED", r.getRequestId().toString()));
+ mResender.addRequest(r);
+ return false;
+ }
+
+ // request was completed.
+ replymsg.toRequest(r); // this only copies contents.
+
+ // terminal states other than completed
+ if (replyStatus == RequestStatus.REJECTED ||
+ replyStatus == RequestStatus.CANCELED) {
+ CMS.debug(
+ "remote request id " + r.getRequestId() +
+ " was rejected or cancelled.");
+ r.setExtData(IRequest.REMOTE_STATUS, replyStatus.toString());
+ r.setExtData(IRequest.RESULT, IRequest.RES_ERROR);
+ r.setExtData(IRequest.ERROR,
+ new EBaseException(CMS.getUserMessage("CMS_BASE_REMOTE_AUTHORITY_ERROR")));
+ // XXX overload svcerrors for now.
+ Vector<String> policyErrors = r.getExtDataInStringVector(IRequest.ERRORS);
+
+ if (policyErrors != null && policyErrors.size() > 0) {
+ r.setExtData(IRequest.SVCERRORS, policyErrors);
+ }
+ }
+
+ CMS.debug(
+ "remote request id " + r.getRequestId() + " was completed");
+ return true;
+ } catch (EBaseException e) {
+ CMS.debug("HttpConn: inside EBaseException " + e.toString());
+
+ if (!r.getRequestType().equals(IRequest.GETREVOCATIONINFO_REQUEST))
+ mResender.addRequest(r);
+
+ CMS.debug("HttpConn: error sending request to cert " + e.toString());
+ mSource.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CONNECTOR_SEND_REQUEST", r.getRequestId()
+ .toString(), mDest.getHost(), Integer.toString(mDest.getPort())));
+ // mSource.log(ILogger.LL_INFO,
+ // "Queing " + r.getRequestId() + " for resend.");
+ return false;
+ } finally {
+
+ if (curConn != null) {
+ mConnFactory.returnConn(curConn);
+ }
+ }
+ }
+
+ public void start() {
+ CMS.debug("Starting HttpConnector resender thread");
+ mResender.start("HttpConnector");
+ }
+
+ public void stop() {
+ CMS.debug("Stopping HttpConnector resender thread");
+ mResender.stop();
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpPKIMessage.java b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpPKIMessage.java
new file mode 100644
index 000000000..4b35662fa
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpPKIMessage.java
@@ -0,0 +1,230 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.connector;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.OptionalDataException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.NoSuchElementException;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.connector.IHttpPKIMessage;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * simple name/value pair message.
+ */
+public class HttpPKIMessage implements IHttpPKIMessage {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3378261119472034953L;
+ // initialized to "" because nulls don't serialize well.
+ public String reqType = "";
+ public String reqId = "";
+ protected String reqStatus = "";
+ protected Vector<Object> mNameVals = new Vector<Object>(); // sequence of name/vals.
+
+ public HttpPKIMessage() {
+ }
+
+ public String getReqStatus() {
+ return reqStatus;
+ }
+
+ public String getReqType() {
+ return reqType;
+ }
+
+ public String getReqId() {
+ return reqId;
+ }
+
+ /**
+ * copy contents of request to make a simple name/value message.
+ */
+ public void fromRequest(IRequest r) {
+ // actually don't need to copy source id since
+ reqType = r.getRequestType();
+ reqId = r.getRequestId().toString();
+ reqStatus = r.getRequestStatus().toString();
+
+ CMS.debug("HttpPKIMessage.fromRequest: requestId="
+ + r.getRequestId().toString() + " requestStatus=" + reqStatus + " instance=" + r);
+
+ String attrs[] = RequestTransfer.getTransferAttributes(r);
+ String[] names = attrs;
+ Object value = null;
+
+ for (int i = 0; i < attrs.length; i++) {
+ String key = names[i];
+ if (r.isSimpleExtDataValue(key)) {
+ value = r.getExtDataInString(key);
+ } else {
+ value = r.getExtDataInHashtable(key);
+ }
+ if (value != null) {
+ mNameVals.addElement(key);
+ mNameVals.addElement(value);
+ }
+ }
+ }
+
+ /**
+ * copy contents to request.
+ */
+ @SuppressWarnings("unchecked")
+ public void toRequest(IRequest r) {
+ // id, type and status
+ // type had to have been set in instantiation.
+ // id is checked but not reset.
+ // request status cannot be set, but can be looked at.
+ reqStatus = r.getRequestStatus().toString();
+ CMS.debug("HttpPKMessage.toRequest: requestStatus=" + reqStatus);
+
+ String key;
+ Object value;
+ Enumeration<Object> enum1 = mNameVals.elements();
+
+ while (enum1.hasMoreElements()) {
+ key = (String) enum1.nextElement();
+ try {
+ value = enum1.nextElement();
+ if (value instanceof String) {
+ r.setExtData(key, (String) value);
+ } else if (value instanceof Hashtable) {
+ r.setExtData(key, (Hashtable<String, String>) value);
+ } else {
+ CMS.debug("HttpPKIMessage.toRequest(): key: " + key +
+ " has unexpected type " + value.getClass().toString());
+ }
+ } catch (NoSuchElementException e) {
+ CMS.debug("Incorrect pairing of name/value for " + key);
+ }
+ }
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out)
+ throws IOException {
+ CMS.debug("writeObject");
+ out.writeObject(reqType);
+ if (Debug.ON)
+ Debug.trace("read object req type " + reqType);
+ out.writeObject(reqId);
+ if (Debug.ON)
+ Debug.trace("read object req id " + reqId);
+ out.writeObject(reqStatus);
+ if (Debug.ON)
+ Debug.trace("read object req source status " + reqStatus);
+ Enumeration<Object> enum1 = mNameVals.elements();
+
+ while (enum1.hasMoreElements()) {
+ Object key = null;
+ Object val = null;
+ key = enum1.nextElement();
+ try {
+ val = enum1.nextElement();
+ // test if key and value are serializable
+ ObjectOutputStream os =
+ new ObjectOutputStream(new ByteArrayOutputStream());
+ os.writeObject(key);
+ os.writeObject(val);
+
+ // ok, if we dont have problem serializing the objects,
+ // then write the objects into the real object stream
+ out.writeObject(key);
+ out.writeObject(val);
+ } catch (Exception e) {
+ // skip not serialiable attribute in DRM
+ // DRM does not need to store the enrollment request anymore
+ CMS.debug("HttpPKIMessage:skipped key=" +
+ key.getClass().getName());
+ if (val == null) {
+ CMS.debug("HttpPKIMessage:skipped val= null");
+ } else {
+ CMS.debug("HttpPKIMessage:skipped val=" +
+ val.getClass().getName());
+ }
+ }
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in)
+ throws IOException, ClassNotFoundException, OptionalDataException {
+ reqType = (String) in.readObject();
+ reqId = (String) in.readObject();
+ reqStatus = (String) in.readObject();
+ mNameVals = new Vector<Object>();
+ Object keyorval = null;
+
+ try {
+ boolean iskey = true;
+
+ while (true) {
+ boolean skipped = false;
+ try {
+ keyorval = in.readObject();
+ } catch (OptionalDataException e) {
+ throw e;
+ } catch (IOException e) {
+ // just skipped parameter
+ CMS.debug("skipped attribute in request e=" + e);
+ if (!iskey) {
+ int s = mNameVals.size();
+ if (s > 0) {
+ // remove previous key if this is value
+ mNameVals.removeElementAt(s - 1);
+ skipped = true;
+ keyorval = "";
+ }
+ }
+ }
+ if (iskey) {
+ if (Debug.ON)
+ Debug.trace("read key " + keyorval);
+ iskey = false;
+ } else {
+ if (Debug.ON)
+ Debug.trace("read val " + keyorval);
+ iskey = true;
+ }
+ if (Debug.ON)
+ Debug.trace("read " + keyorval);
+ if (!skipped) {
+ if (keyorval == null)
+ break;
+ mNameVals.addElement(keyorval);
+ }
+ }
+ } catch (OptionalDataException e) {
+ if (e.eof == true) {
+ if (Debug.ON)
+ Debug.trace("end of stream");
+ } else {
+ if (Debug.ON)
+ Debug.trace(" " + e.length);
+ throw e;
+ }
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpRequestEncoder.java b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpRequestEncoder.java
new file mode 100644
index 000000000..bb18030dc
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpRequestEncoder.java
@@ -0,0 +1,76 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.connector;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OptionalDataException;
+
+import com.netscape.certsrv.connector.IRequestEncoder;
+import com.netscape.cmscore.util.Debug;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * encodes a request by serializing it.
+ */
+public class HttpRequestEncoder implements IRequestEncoder {
+ public String encode(Object r)
+ throws IOException {
+ String s = null;
+ byte[] serial;
+ ByteArrayOutputStream ba = new ByteArrayOutputStream();
+ ObjectOutputStream os = new ObjectOutputStream(ba);
+
+ os.writeObject(r);
+ serial = ba.toByteArray();
+ s = Utils.base64encode(serial);
+ return s;
+ }
+
+ public Object decode(String s)
+ throws IOException {
+ Object result = null;
+ byte[] serial = null;
+
+ try {
+
+ serial = Utils.base64decode(s);
+ ByteArrayInputStream ba = new ByteArrayInputStream(serial);
+ ObjectInputStream is = new ObjectInputStream(ba);
+
+ result = is.readObject();
+ } catch (ClassNotFoundException e) {
+ // XXX hack: change this
+ if (Debug.ON)
+ Debug.trace("class not found ex " + e + e.getMessage());
+ throw new IOException("Class Not Found " + e.getMessage());
+ } catch (OptionalDataException e) {
+ if (e.eof == true) {
+ if (Debug.ON)
+ Debug.trace("done reading input stream " + result);
+ } else {
+ if (Debug.ON)
+ Debug.trace(e.length + " more bytes of primitive data");
+ }
+ }
+ return result;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/LocalConnector.java b/base/server/cmscore/src/com/netscape/cmscore/connector/LocalConnector.java
new file mode 100644
index 000000000..ba2db83a1
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/connector/LocalConnector.java
@@ -0,0 +1,213 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.connector;
+
+import java.util.Hashtable;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.connector.IConnector;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestListener;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cmscore.util.Debug;
+
+public class LocalConnector implements IConnector {
+ ICertAuthority mSource = null;
+ IAuthority mDest = null;
+ Hashtable<String, IRequest> mSourceReqs = new Hashtable<String, IRequest>();
+
+ public LocalConnector(ICertAuthority source, IAuthority dest) {
+ mSource = source;
+ // mSource.log(ILogger.LL_DEBUG, "Local connector setup for source " +
+ // mSource.getId());
+ mDest = dest;
+ CMS.debug("Local connector setup for dest " +
+ mDest.getId());
+ // register for events.
+ mDest.registerRequestListener(new LocalConnListener());
+ CMS.debug("Connector inited");
+ }
+
+ /**
+ * send request to local authority.
+ * returns resulting request
+ */
+ public boolean send(IRequest r) throws EBaseException {
+ if (Debug.ON) {
+ Debug.print("send request type "
+ + r.getRequestType() + " status=" + r.getRequestStatus() + " to " + mDest.getId() + " id="
+ + r.getRequestId() + "\n");
+ }
+ CMS.debug("send request type " + r.getRequestType() +
+ " to " + mDest.getId());
+
+ IRequestQueue destQ = mDest.getRequestQueue();
+ IRequest destreq = destQ.newRequest(r.getRequestType());
+
+ CMS.debug("local connector dest req " +
+ destreq.getRequestId() + " created for source rId " + r.getRequestId());
+ // mSource.log(ILogger.LL_DEBUG,
+ // "setting connector dest " + mDest.getId() +
+ // " source id to " + r.getRequestId());
+
+ // XXX set context to the real identity later.
+ destreq.setSourceId(
+ mSource.getX500Name().toString() + ":" + r.getRequestId().toString());
+ //destreq.copyContents(r); // copy meta attributes in request.
+ transferRequest(r, destreq);
+ // XXX requestor type is not transferred on return.
+ destreq.setExtData(IRequest.REQUESTOR_TYPE,
+ IRequest.REQUESTOR_RA);
+ CMS.debug("connector dest " + mDest.getId() +
+ " processing " + destreq.getRequestId());
+
+ // set context before calling process request so
+ // that request subsystem can record the creator
+ // of the request
+ SessionContext s = SessionContext.getContext();
+
+ if (s.get(SessionContext.USER_ID) == null) {
+ // use $local$ to represent it is not a user who
+ // submit the request, but it is a local subsystem
+ s.put(SessionContext.USER_ID, "$local$" + mSource.getId());
+ }
+
+ // Locally cache the source request so that we
+ // can update it when the dest request is
+ // processed (when LocalConnListener is being called).
+ mSourceReqs.put(r.getRequestId().toString(), r);
+ try {
+ destQ.processRequest(destreq);
+ } catch (EBaseException ex) {
+ throw ex;
+ } finally {
+ // release the source id either success or failure
+ mSourceReqs.remove(r.getRequestId().toString());
+ }
+
+ CMS.debug("connector dest " + mDest.getId() +
+ " processed " + destreq.getRequestId() +
+ " status " + destreq.getRequestStatus());
+
+ if (destreq.getRequestStatus() == RequestStatus.COMPLETE) {
+ // no need to transfer contents if request wasn't complete.
+ transferRequest(destreq, r);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public class LocalConnListener implements IRequestListener {
+
+ public void init(ISubsystem sys, IConfigStore config)
+ throws EBaseException {
+ }
+
+ public void set(String name, String val) {
+ }
+
+ public void accept(IRequest destreq) {
+ if (Debug.ON) {
+ Debug.print("dest " + mDest.getId() + " done with " + destreq.getRequestId());
+ }
+ CMS.debug(
+ "dest " + mDest.getId() + " done with " + destreq.getRequestId());
+
+ IRequestQueue sourceQ = mSource.getRequestQueue();
+ // accept requests that only belong to us.
+ // XXX review death scenarios here. - If system dies anywhere
+ // here need to check all requests at next server startup.
+ String sourceNameAndId = destreq.getSourceId();
+ String sourceName = mSource.getX500Name().toString();
+
+ if (sourceNameAndId == null ||
+ !sourceNameAndId.toString().regionMatches(0,
+ sourceName, 0, sourceName.length())) {
+ CMS.debug("request " + destreq.getRequestId() +
+ " from " + sourceNameAndId + " not ours.");
+ return;
+ }
+ int index = sourceNameAndId.lastIndexOf(':');
+
+ if (index == -1) {
+ mSource.log(ILogger.LL_FAILURE,
+ "request " + destreq.getRequestId() +
+ " for " + sourceNameAndId + " malformed.");
+ return;
+ }
+ String sourceId = sourceNameAndId.substring(index + 1);
+ RequestId rId = new RequestId(sourceId);
+
+ // mSource.log(ILogger.LL_DEBUG, mDest.getId() + " " +
+ // destreq.getRequestId() + " mapped to " + mSource.getId() + " " + rId);
+
+ IRequest r = null;
+
+ // 391439: Previously, we try to access the request
+ // via request queue here. Due to the recent
+ // performance enhancement, approved request will
+ // not be immediately available in the database. So
+ // retrieving the request from the queue within
+ // the serviceRequest() function will have
+ // diffculities.
+ // You may wonder what happen if the system crashes
+ // during the request servicing. Yes, the request
+ // will be lost. This is ok because the users will
+ // resubmit their requests again.
+ // Note that the pending requests, on the other hand,
+ // are persistent before the servicing.
+ // Please see stateEngine() function in
+ // ARequestQueue.java for details.
+ r = mSourceReqs.get(rId.toString());
+ if (r != null) {
+ if (r.getRequestStatus() != RequestStatus.SVC_PENDING) {
+ mSource.log(ILogger.LL_FAILURE,
+ "request state of " + rId + "not pending " +
+ " from dest authority " + mDest.getId());
+ sourceQ.releaseRequest(r);
+ return;
+ }
+ transferRequest(destreq, r);
+ sourceQ.markAsServiced(r);
+ sourceQ.releaseRequest(r);
+
+ CMS.debug("released request " + r.getRequestId());
+ }
+ }
+ }
+
+ public void start() {
+ }
+
+ public void stop() {
+ }
+
+ protected void transferRequest(IRequest src, IRequest dest) {
+ RequestTransfer.transfer(src, dest);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/RemoteAuthority.java b/base/server/cmscore/src/com/netscape/cmscore/connector/RemoteAuthority.java
new file mode 100644
index 000000000..71d01579f
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/connector/RemoteAuthority.java
@@ -0,0 +1,69 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.connector;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.connector.IRemoteAuthority;
+
+public class RemoteAuthority implements IRemoteAuthority {
+ String mHost = null;
+ int mPort = -1;
+ String mURI = null;
+ int mTimeout = 0;
+
+ /**
+ * host parameter can be:
+ * "directory.knowledge.com"
+ * "199.254.1.2"
+ * "directory.knowledge.com:1050 people.catalog.com 199.254.1.2"
+ */
+ public RemoteAuthority(String host, int port, String uri, int timeout) {
+ mHost = host;
+ mPort = port;
+ mURI = uri;
+ mTimeout = timeout;
+ }
+
+ public RemoteAuthority() {
+ }
+
+ public void init(IConfigStore c)
+ throws EBaseException {
+ mHost = c.getString("host");
+ mPort = c.getInteger("port");
+ mURI = c.getString("uri");
+ mTimeout = c.getInteger("timeout");
+ }
+
+ public String getHost() {
+ return mHost;
+ }
+
+ public int getPort() {
+ return mPort;
+ }
+
+ public String getURI() {
+ return mURI;
+ }
+
+ public int getTimeout() {
+ return mTimeout;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/RequestTransfer.java b/base/server/cmscore/src/com/netscape/cmscore/connector/RequestTransfer.java
new file mode 100644
index 000000000..b3479aea0
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/connector/RequestTransfer.java
@@ -0,0 +1,115 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.connector;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cmscore.authentication.ChallengePhraseAuthentication;
+
+public class RequestTransfer {
+
+ private static String[] transferAttributes = {
+ IRequest.HTTP_PARAMS,
+ IRequest.AGENT_PARAMS,
+ IRequest.CERT_INFO,
+ IRequest.ISSUED_CERTS,
+ IRequest.OLD_CERTS,
+ IRequest.OLD_SERIALS,
+ IRequest.REVOKED_CERTS,
+ IRequest.CACERTCHAIN,
+ IRequest.CRL,
+ IRequest.ERRORS,
+ IRequest.RESULT,
+ IRequest.ERROR,
+ IRequest.SVCERRORS,
+ IRequest.REMOTE_STATUS,
+ IRequest.REMOTE_REQID,
+ IRequest.REVOKED_CERT_RECORDS,
+ IRequest.CERT_STATUS,
+ ChallengePhraseAuthentication.CHALLENGE_PHRASE,
+ ChallengePhraseAuthentication.SUBJECTNAME,
+ ChallengePhraseAuthentication.SERIALNUMBER,
+ ChallengePhraseAuthentication.SERIALNOARRAY,
+ IRequest.ISSUERDN,
+ IRequest.CERT_FILTER,
+ "keyRecord",
+ "uid", // UidPwdDirAuthentication.CRED_UID,
+ "udn", // UdnPwdDirAuthentication.CRED_UDN,
+ };
+
+ public static boolean isProfileRequest(IRequest request) {
+ String profileId = request.getExtDataInString("profileId");
+
+ if (profileId == null || profileId.equals(""))
+ return false;
+ else
+ return true;
+ }
+
+ public static String[] getTransferAttributes(IRequest r) {
+ if (isProfileRequest(r)) {
+ // copy everything in the request
+ CMS.debug("RequestTransfer: profile request " +
+ r.getRequestId().toString());
+ Enumeration<String> e = r.getExtDataKeys();
+ Vector<String> v = new Vector<String>();
+
+ while (e.hasMoreElements()) {
+ String k = e.nextElement();
+
+ if (k.equals("requestType"))
+ continue;
+ if (k.equals("requestId"))
+ continue;
+ if (k.equals("requestVersion"))
+ continue;
+ if (k.equals("AUTH_TOKEN"))
+ continue;
+ CMS.debug("RequestTransfer: attribute=" + k);
+ if (k.equals("requestStatus")) {
+ CMS.debug("RequestTransfer : requestStatus=" +
+ r.getExtDataInString("requestStatus"));
+ }
+ v.addElement(k);
+ }
+ CMS.debug("RequestTransfer: attribute size=" + v.size());
+ return v.toArray(new String[v.size()]);
+ } else {
+ return transferAttributes;
+ }
+ }
+
+ public static void transfer(IRequest src, IRequest dest) {
+ CMS.debug("Transfer srcId=" +
+ src.getRequestId().toString() +
+ " destId=" + dest.getRequestId().toString());
+ String attrs[] = getTransferAttributes(src);
+
+ for (int i = 0; i < attrs.length; i++) {
+ String key = attrs[i];
+ if (src.isSimpleExtDataValue(key)) {
+ dest.setExtData(key, src.getExtDataInString(key));
+ } else {
+ dest.setExtData(key, src.getExtDataInHashtable(key));
+ }
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/Resender.java b/base/server/cmscore/src/com/netscape/cmscore/connector/Resender.java
new file mode 100644
index 000000000..a949b993e
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/connector/Resender.java
@@ -0,0 +1,260 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.connector;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.connector.IRemoteAuthority;
+import com.netscape.certsrv.connector.IResender;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestList;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cmscore.util.Debug;
+import com.netscape.cmsutil.http.JssSSLSocketFactory;
+
+/**
+ * Resend requests at intervals to the server to check if it's been completed.
+ * Default interval is 5 minutes.
+ */
+public class Resender implements IResender {
+ public static final int MINUTE = 60;
+
+ protected IAuthority mAuthority = null;
+ IRequestQueue mQueue = null;
+ protected IRemoteAuthority mDest = null;
+ ScheduledExecutorService executorService;
+
+ /* Vector of Request Id *Strings* */
+ protected Vector<String> mRequestIds = new Vector<String>();
+
+ protected HttpConnection mConn = null;
+
+ protected String mNickName = null;
+ protected boolean connected = false;
+
+ // default interval.
+ // XXX todo add another interval for requests unsent because server
+ // was down (versus being serviced in request queue)
+ protected int mInterval = 1 * MINUTE;
+
+ public Resender(IAuthority authority, String nickName, IRemoteAuthority dest) {
+ mAuthority = authority;
+ mQueue = mAuthority.getRequestQueue();
+ mDest = dest;
+ mNickName = nickName;
+ }
+
+ public Resender(
+ IAuthority authority, String nickName,
+ IRemoteAuthority dest, int interval) {
+ mAuthority = authority;
+ mQueue = mAuthority.getRequestQueue();
+ mDest = dest;
+ mNickName = nickName;
+ if (interval > 0)
+ mInterval = interval; // interval specified in seconds.
+ }
+
+ // must be done after a subsystem 'start' so queue is initialized.
+ private void initRequests() {
+ mQueue = mAuthority.getRequestQueue();
+ // get all requests in mAuthority that are still pending.
+ IRequestList list =
+ mQueue.listRequestsByStatus(RequestStatus.SVC_PENDING);
+
+ while (list != null && list.hasMoreElements()) {
+ RequestId rid = list.nextRequestId();
+ CMS.debug("added request Id " + rid + " in init to resend queue.");
+ // note these are added as strings
+ mRequestIds.addElement(rid.toString());
+ }
+ }
+
+ public void addRequest(IRequest r) {
+ synchronized (mRequestIds) {
+ // note the request ids are added as strings.
+ mRequestIds.addElement(r.getRequestId().toString());
+ }
+ CMS.debug("added " + r.getRequestId() + " to resend queue");
+ }
+
+ public void start(final String name) {
+ CMS.debug("Starting resender thread with interval " + mInterval);
+
+ // schedule task to run immediately and repeat after specified interval
+ executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
+ public Thread newThread(Runnable r) {
+ return new Thread(r, name);
+ }
+ });
+ executorService.scheduleWithFixedDelay(this, 0, mInterval, TimeUnit.SECONDS);
+
+ }
+
+ public void run() {
+ if (! CMS.isInRunningState())
+ return;
+
+ if (! connected) {
+ CMS.debug("Connecting ...");
+ mConn = new HttpConnection(mDest, new JssSSLSocketFactory(mNickName));
+ initRequests();
+ connected = true;
+ }
+ resend();
+ }
+
+ public void stop() {
+ // shutdown executorService without interrupting running task
+ if (executorService != null) executorService.shutdown();
+ }
+
+ private void resend() {
+ // clone a seperate list so mRequestIds can be modified
+ @SuppressWarnings("unchecked")
+ Vector<String> rids = (Vector<String>) mRequestIds.clone();
+ Vector<RequestId> completedRids = new Vector<RequestId>();
+
+ // resend each request to CA to ping for status.
+ Enumeration<String> enum1 = rids.elements();
+
+ while (enum1.hasMoreElements()) {
+ // request ids are added as strings.
+ String ridString = enum1.nextElement();
+ RequestId rid = new RequestId(ridString);
+ IRequest r = null;
+
+ CMS.debug(
+ "resend processing request id " + rid);
+
+ try {
+ r = mQueue.findRequest(rid);
+ } catch (EBaseException e) {
+ // XXX bad case. should we remove the rid now ?
+ mAuthority.log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSCORE_CONNECTOR_REQUEST_NOT_FOUND", rid.toString()));
+ continue;
+ }
+ try {
+ if (r.getRequestStatus() != RequestStatus.SVC_PENDING) {
+ // request not pending anymore - aborted or cancelled.
+ completedRids.addElement(rid);
+ CMS.debug(
+ "request id " + rid + " no longer service pending");
+ } else {
+ boolean completed = send(r);
+
+ if (completed) {
+ completedRids.addElement(rid);
+ mAuthority.log(ILogger.LL_INFO,
+ CMS.getLogMessage("CMSCORE_CONNECTOR_REQUEST_COMPLETED", rid.toString()));
+ }
+ }
+ } catch (IOException e) {
+ mAuthority.log(ILogger.LL_WARN,
+ CMS.getLogMessage("CMSCORE_CONNECTOR_REQUEST_ERROR", rid.toString(), e.toString()));
+ } catch (EBaseException e) {
+ // if connection is down, don't send the remaining request
+ // as it will sure fail.
+ mAuthority.log(ILogger.LL_WARN, CMS.getLogMessage("CMSCORE_CONNECTOR_DOWN"));
+ if (e.toString().indexOf("connection not available") >= 0)
+ break;
+ }
+ }
+
+ // remove completed ones from list so they won't be resent.
+ Enumeration<RequestId> en = completedRids.elements();
+
+ synchronized (mRequestIds) {
+ while (en.hasMoreElements()) {
+ RequestId id = en.nextElement();
+
+ CMS.debug(
+ "Connector: Removed request " + id + " from re-send queue");
+ mRequestIds.removeElement(id.toString());
+ CMS.debug(
+ "Connector: mRequestIds now has " +
+ mRequestIds.size() + " elements.");
+ }
+ }
+ }
+
+ // this is almost the same as connector's send.
+ private boolean send(IRequest r)
+ throws IOException, EBaseException {
+
+ try {
+ HttpPKIMessage tomsg = new HttpPKIMessage();
+ HttpPKIMessage replymsg = null;
+
+ tomsg.fromRequest(r);
+ replymsg = (HttpPKIMessage) mConn.send(tomsg);
+ if (replymsg == null)
+ return false;
+ CMS.debug(
+ r.getRequestId() + " resent to CA");
+
+ RequestStatus replyStatus =
+ RequestStatus.fromString(replymsg.reqStatus);
+ int index = replymsg.reqId.lastIndexOf(':');
+ RequestId replyRequestId =
+ new RequestId(replymsg.reqId.substring(index + 1));
+
+ if (Debug.ON)
+ Debug.trace("reply request id " + replyRequestId +
+ " for request " + r.getRequestId());
+
+ if (replyStatus != RequestStatus.COMPLETE) {
+ CMS.debug("resend " +
+ r.getRequestId() + " still not completed.");
+ return false;
+ }
+
+ // request was completed. copy relevant contents.
+ replymsg.toRequest(r);
+ if (Debug.ON)
+ Debug.trace("resend request id was completed " + r.getRequestId());
+ mQueue.markAsServiced(r);
+ mQueue.releaseRequest(r);
+ CMS.debug(
+ "resend released request " + r.getRequestId());
+ return true;
+ } catch (EBaseException e) {
+ // same as not having sent it, so still want to resend.
+ mAuthority.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_CONNECTOR_RESEND_ERROR", r.getRequestId().toString(), e.toString()));
+ if (e.toString().indexOf("Connection refused by peer") > 0)
+ throw new EBaseException("connection not available");
+ }
+ return false;
+
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/crmf/CRMFParser.java b/base/server/cmscore/src/com/netscape/cmscore/crmf/CRMFParser.java
new file mode 100644
index 000000000..34b378bf1
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/crmf/CRMFParser.java
@@ -0,0 +1,122 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.crmf;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Vector;
+
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.ASN1Value;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.pkix.crmf.CertReqMsg;
+import org.mozilla.jss.pkix.crmf.CertRequest;
+import org.mozilla.jss.pkix.crmf.PKIArchiveOptions;
+import org.mozilla.jss.pkix.primitive.AVA;
+
+import com.netscape.certsrv.apps.CMS;
+
+public class CRMFParser {
+
+ private static final OBJECT_IDENTIFIER PKIARCHIVEOPTIONS_OID =
+ new OBJECT_IDENTIFIER(new long[] { 1, 3, 6, 1, 5, 5, 7, 5, 1, 4 }
+ );
+
+ /**
+ * Retrieves PKIArchiveOptions from CRMF request.
+ *
+ * @param request CRMF request
+ * @return PKIArchiveOptions
+ * @exception failed to extrace option
+ */
+ public static PKIArchiveOptionsContainer[]
+ getPKIArchiveOptions(String crmfBlob) throws IOException {
+ Vector<PKIArchiveOptionsContainer> options = new Vector<PKIArchiveOptionsContainer>();
+
+ byte[] crmfBerBlob = null;
+
+ crmfBerBlob = CMS.AtoB(crmfBlob);
+ if (crmfBerBlob == null)
+ throw new IOException("no CRMF data found");
+
+ ByteArrayInputStream crmfBerBlobIn = new
+ ByteArrayInputStream(crmfBerBlob);
+ SEQUENCE crmfmsgs = null;
+
+ try {
+ crmfmsgs = (SEQUENCE) new
+ SEQUENCE.OF_Template(new
+ CertReqMsg.Template()).decode(
+ crmfBerBlobIn);
+ } catch (IOException e) {
+ throw new IOException("[crmf msgs]" + e.toString());
+ } catch (InvalidBERException e) {
+ throw new IOException("[crmf msgs]" + e.toString());
+ }
+
+ for (int z = 0; z < crmfmsgs.size(); z++) {
+ CertReqMsg certReqMsg = (CertReqMsg)
+ crmfmsgs.elementAt(z);
+ CertRequest certReq = certReqMsg.getCertReq();
+
+ // try to locate PKIArchiveOption control
+ AVA archAva = null;
+
+ try {
+ for (int i = 0; i < certReq.numControls(); i++) {
+ AVA ava = certReq.controlAt(i);
+ OBJECT_IDENTIFIER oid = ava.getOID();
+
+ if (oid.equals(PKIARCHIVEOPTIONS_OID)) {
+ archAva = ava;
+ break;
+ }
+ }
+ } catch (Exception e) {
+ throw new IOException("no PKIArchiveOptions found " + e.toString());
+ }
+ if (archAva != null) {
+
+ ASN1Value archVal = archAva.getValue();
+ ByteArrayInputStream bis = new ByteArrayInputStream(ASN1Util.encode(archVal));
+ PKIArchiveOptions archOpts = null;
+
+ try {
+ archOpts = (PKIArchiveOptions)
+ (new PKIArchiveOptions.Template()).decode(bis);
+ } catch (IOException e) {
+ throw new IOException("[PKIArchiveOptions]" + e.toString());
+ } catch (InvalidBERException e) {
+ throw new IOException("[PKIArchiveOptions]" + e.toString());
+ }
+ options.addElement(new PKIArchiveOptionsContainer(archOpts, z));
+ }
+ }
+ if (options.size() == 0) {
+ throw new IOException("no PKIArchiveOptions found");
+ } else {
+ PKIArchiveOptionsContainer p[] = new PKIArchiveOptionsContainer[options.size()];
+
+ options.copyInto(p);
+ // options.clear();
+ return p;
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/crmf/PKIArchiveOptionsContainer.java b/base/server/cmscore/src/com/netscape/cmscore/crmf/PKIArchiveOptionsContainer.java
new file mode 100644
index 000000000..4c5478daf
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/crmf/PKIArchiveOptionsContainer.java
@@ -0,0 +1,31 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.crmf;
+
+import org.mozilla.jss.pkix.crmf.PKIArchiveOptions;
+
+public class PKIArchiveOptionsContainer {
+
+ public PKIArchiveOptions mAO = null;
+ public int mReqPos;
+
+ public PKIArchiveOptionsContainer(PKIArchiveOptions ao, int reqpos) {
+ mAO = ao;
+ mReqPos = reqpos;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/BigIntegerMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/BigIntegerMapper.java
new file mode 100644
index 000000000..7d92c79cd
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/BigIntegerMapper.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+
+/**
+ * A class represents ann attribute mapper that maps
+ * a Java BigInteger object into LDAP attribute,
+ * and vice versa.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class BigIntegerMapper implements IDBAttrMapper {
+
+ private String mLdapName = null;
+ private Vector<String> v = new Vector<String>();
+
+ /**
+ * Constructs BigInteger mapper.
+ */
+ public BigIntegerMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Returns a list of supported ldap attribute names.
+ */
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps object into ldap attribute set.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ attrs.add(new LDAPAttribute(mLdapName,
+ BigIntegerToDB((BigInteger) obj)));
+ }
+
+ /**
+ * Maps LDAP attributes into object, and put the object
+ * into 'parent'.
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(mLdapName);
+
+ if (attr == null)
+ return;
+ parent.set(name, BigIntegerFromDB(
+ (String) attr.getStringValues().nextElement()));
+ }
+
+ /**
+ * Maps search filters into LDAP search filter.
+ */
+ public String mapSearchFilter(String name, String op,
+ String value) throws EBaseException {
+ String v = null;
+
+ try {
+ if (value.startsWith("0x") || value.startsWith("0X")) {
+ v = BigIntegerToDB(new
+ BigInteger(value.substring(2), 16));
+ } else {
+ v = BigIntegerToDB(new BigInteger(value));
+ }
+ } catch (NumberFormatException e) {
+ v = value;
+ }
+ return mLdapName + op + v;
+ }
+
+ public static String BigIntegerToDB(BigInteger i) {
+ int len = i.toString().length();
+ String ret = null;
+
+ if (len < 10) {
+ ret = "0" + Integer.toString(len) + i.toString();
+ } else {
+ ret = Integer.toString(len) + i.toString();
+ }
+ return ret;
+ }
+
+ public static BigInteger BigIntegerFromDB(String i) {
+ String s = i.substring(2);
+
+ // possibly check length
+ return new BigInteger(s);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/ByteArrayMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/ByteArrayMapper.java
new file mode 100644
index 000000000..88d205b20
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/ByteArrayMapper.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+
+/**
+ * A class represents ann attribute mapper that maps
+ * a Java byte array object into LDAP attribute,
+ * and vice versa.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class ByteArrayMapper implements IDBAttrMapper {
+
+ private String mLdapName = null;
+ private Vector<String> v = new Vector<String>();
+
+ /**
+ * Constructs a byte array mapper.
+ */
+ public ByteArrayMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Lists a list of supported ldap attribute names.
+ */
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps object to ldap attribute set.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ byte data[] = (byte[]) obj;
+ if (data == null) {
+ CMS.debug("ByteArrayMapper:mapObjectToLDAPAttributeSet " + name +
+ " size=0");
+ } else {
+ CMS.debug("ByteArrayMapper:mapObjectToLDAPAttributeSet " + name +
+ " size=" + data.length);
+ }
+ attrs.add(new LDAPAttribute(mLdapName, data));
+ }
+
+ /**
+ * Maps LDAP attributes into object, and put the object
+ * into 'parent'.
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(mLdapName);
+
+ if (attr == null)
+ return;
+ parent.set(name, attr.getByteValues().nextElement());
+ }
+
+ /**
+ * Maps search filters into LDAP search filter.
+ */
+ public String mapSearchFilter(String name, String op,
+ String value) throws EBaseException {
+ return mLdapName + op + value;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/CRLDBSchema.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/CRLDBSchema.java
new file mode 100644
index 000000000..60f6b69a1
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/CRLDBSchema.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+/**
+ * A class represents a collection of schema information
+ * for CRL.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class CRLDBSchema {
+
+ public static final String LDAP_OC_TOP = "top";
+ public static final String LDAP_OC_CRL_RECORD = "crlIssuingPointRecord";
+ public static final String LDAP_ATTR_CRL_ID = "cn";
+ public static final String LDAP_ATTR_CRL_NUMBER = "crlNumber";
+ public static final String LDAP_ATTR_DELTA_NUMBER = "deltaNumber";
+ public static final String LDAP_ATTR_CRL_SIZE = "crlSize";
+ public static final String LDAP_ATTR_DELTA_SIZE = "deltaSize";
+ public static final String LDAP_ATTR_THIS_UPDATE = "thisUpdate";
+ public static final String LDAP_ATTR_NEXT_UPDATE = "nextUpdate";
+ public static final String LDAP_ATTR_FIRST_UNSAVED = "firstUnsaved";
+ public static final String LDAP_ATTR_CRL = "certificateRevocationList";
+ public static final String LDAP_ATTR_CA_CERT = "cACertificate";
+ public static final String LDAP_ATTR_CRL_CACHE = "crlCache";
+ public static final String LDAP_ATTR_REVOKED_CERTS = "revokedCerts";
+ public static final String LDAP_ATTR_UNREVOKED_CERTS = "unrevokedCerts";
+ public static final String LDAP_ATTR_EXPIRED_CERTS = "expiredCerts";
+ public static final String LDAP_ATTR_DELTA_CRL = "deltaRevocationList";
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/CRLIssuingPointRecord.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/CRLIssuingPointRecord.java
new file mode 100644
index 000000000..c6d041b34
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/CRLIssuingPointRecord.java
@@ -0,0 +1,334 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import netscape.security.x509.RevokedCertificate;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+
+/**
+ * A class represents a CRL issuing point record.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class CRLIssuingPointRecord implements ICRLIssuingPointRecord, IDBObj {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 400565044343905267L;
+ protected String mId = null; // internal unique id
+ protected BigInteger mCRLNumber = null; // CRL number
+ protected Long mCRLSize = null;
+ protected Date mThisUpdate = null;
+ protected Date mNextUpdate = null;
+ protected BigInteger mDeltaCRLNumber = null; // delta CRL number
+ protected Long mDeltaCRLSize = null;
+ protected String mFirstUnsaved = null;
+ protected byte mCRL[] = null;
+ protected byte mCACert[] = null;
+ protected Hashtable<BigInteger, RevokedCertificate> mCRLCache = null;
+ protected Hashtable<BigInteger, RevokedCertificate> mRevokedCerts = null;
+ protected Hashtable<BigInteger, RevokedCertificate> mUnrevokedCerts = null;
+ protected Hashtable<BigInteger, RevokedCertificate> mExpiredCerts = null;
+ protected byte mDeltaCRL[] = null;
+ protected static Vector<String> mNames = new Vector<String>();
+ static {
+ mNames.addElement(ATTR_ID);
+ mNames.addElement(ATTR_CRL_NUMBER);
+ mNames.addElement(ATTR_DELTA_NUMBER);
+ mNames.addElement(ATTR_CRL_SIZE);
+ mNames.addElement(ATTR_DELTA_SIZE);
+ mNames.addElement(ATTR_THIS_UPDATE);
+ mNames.addElement(ATTR_NEXT_UPDATE);
+ mNames.addElement(ATTR_FIRST_UNSAVED);
+ mNames.addElement(ATTR_CRL);
+ mNames.addElement(ATTR_CA_CERT);
+ mNames.addElement(ATTR_CRL_CACHE);
+ mNames.addElement(ATTR_REVOKED_CERTS);
+ mNames.addElement(ATTR_UNREVOKED_CERTS);
+ mNames.addElement(ATTR_EXPIRED_CERTS);
+ mNames.addElement(ATTR_DELTA_CRL);
+ }
+
+ /**
+ * Constructs empty CRLIssuingPointRecord. This is
+ * required in database framework.
+ */
+ public CRLIssuingPointRecord() {
+ }
+
+ /**
+ * Constructs a CRLIssuingPointRecord
+ */
+ public CRLIssuingPointRecord(String id, BigInteger crlNumber, Long crlSize,
+ Date thisUpdate, Date nextUpdate) {
+ mId = id;
+ mCRLNumber = crlNumber;
+ mCRLSize = crlSize;
+ mThisUpdate = thisUpdate;
+ mNextUpdate = nextUpdate;
+ mDeltaCRLNumber = BigInteger.ZERO;
+ mFirstUnsaved = NEW_CACHE;
+ mDeltaCRLSize = Long.valueOf(-1L);
+ mCRLCache = null;
+ mRevokedCerts = null;
+ mUnrevokedCerts = null;
+ mExpiredCerts = null;
+ }
+
+ /**
+ * Constructs a CRLIssuingPointRecord
+ */
+ public CRLIssuingPointRecord(String id, BigInteger crlNumber, Long crlSize,
+ Date thisUpdate, Date nextUpdate, BigInteger deltaCRLNumber, Long deltaCRLSize,
+ Hashtable<BigInteger, RevokedCertificate> revokedCerts,
+ Hashtable<BigInteger, RevokedCertificate> unrevokedCerts,
+ Hashtable<BigInteger, RevokedCertificate> expiredCerts) {
+ mId = id;
+ mCRLNumber = crlNumber;
+ mCRLSize = crlSize;
+ mThisUpdate = thisUpdate;
+ mNextUpdate = nextUpdate;
+ mDeltaCRLNumber = deltaCRLNumber;
+ mDeltaCRLSize = deltaCRLSize;
+ mFirstUnsaved = NEW_CACHE;
+ mCRLCache = null;
+ mRevokedCerts = revokedCerts;
+ mUnrevokedCerts = unrevokedCerts;
+ mExpiredCerts = expiredCerts;
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ public void set(String name, Object obj) throws EBaseException {
+ if (name.equalsIgnoreCase(ATTR_ID)) {
+ mId = (String) obj;
+ } else if (name.equalsIgnoreCase(ATTR_CRL_NUMBER)) {
+ mCRLNumber = (BigInteger) obj;
+ } else if (name.equalsIgnoreCase(ATTR_CRL_SIZE)) {
+ mCRLSize = (Long) obj;
+ } else if (name.equalsIgnoreCase(ATTR_THIS_UPDATE)) {
+ mThisUpdate = (Date) obj;
+ } else if (name.equalsIgnoreCase(ATTR_NEXT_UPDATE)) {
+ mNextUpdate = (Date) obj;
+ } else if (name.equalsIgnoreCase(ATTR_DELTA_NUMBER)) {
+ mDeltaCRLNumber = (BigInteger) obj;
+ } else if (name.equalsIgnoreCase(ATTR_DELTA_SIZE)) {
+ mDeltaCRLSize = (Long) obj;
+ } else if (name.equalsIgnoreCase(ATTR_FIRST_UNSAVED)) {
+ mFirstUnsaved = (String) obj;
+ } else if (name.equalsIgnoreCase(ATTR_CRL)) {
+ mCRL = (byte[]) obj;
+ } else if (name.equalsIgnoreCase(ATTR_CA_CERT)) {
+ mCACert = (byte[]) obj;
+ } else if (name.equalsIgnoreCase(ATTR_CRL_CACHE)) {
+ mCRLCache = (Hashtable<BigInteger, RevokedCertificate>) obj;
+ } else if (name.equalsIgnoreCase(ATTR_REVOKED_CERTS)) {
+ mRevokedCerts = (Hashtable<BigInteger, RevokedCertificate>) obj;
+ } else if (name.equalsIgnoreCase(ATTR_UNREVOKED_CERTS)) {
+ mUnrevokedCerts = (Hashtable<BigInteger, RevokedCertificate>) obj;
+ } else if (name.equalsIgnoreCase(ATTR_EXPIRED_CERTS)) {
+ mExpiredCerts = (Hashtable<BigInteger, RevokedCertificate>) obj;
+ } else if (name.equalsIgnoreCase(ATTR_DELTA_CRL)) {
+ mDeltaCRL = (byte[]) obj;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+ }
+
+ public Object get(String name) throws EBaseException {
+ if (name.equalsIgnoreCase(ATTR_ID)) {
+ return mId;
+ } else if (name.equalsIgnoreCase(ATTR_CRL_NUMBER)) {
+ return mCRLNumber;
+ } else if (name.equalsIgnoreCase(ATTR_CRL_SIZE)) {
+ return mCRLSize;
+ } else if (name.equalsIgnoreCase(ATTR_THIS_UPDATE)) {
+ return mThisUpdate;
+ } else if (name.equalsIgnoreCase(ATTR_NEXT_UPDATE)) {
+ return mNextUpdate;
+ } else if (name.equalsIgnoreCase(ATTR_DELTA_NUMBER)) {
+ return mDeltaCRLNumber;
+ } else if (name.equalsIgnoreCase(ATTR_DELTA_SIZE)) {
+ return mDeltaCRLSize;
+ } else if (name.equalsIgnoreCase(ATTR_FIRST_UNSAVED)) {
+ return mFirstUnsaved;
+ } else if (name.equalsIgnoreCase(ATTR_CRL)) {
+ return mCRL;
+ } else if (name.equalsIgnoreCase(ATTR_CA_CERT)) {
+ return mCACert;
+ } else if (name.equalsIgnoreCase(ATTR_CRL_CACHE)) {
+ return mCRLCache;
+ } else if (name.equalsIgnoreCase(ATTR_REVOKED_CERTS)) {
+ return mRevokedCerts;
+ } else if (name.equalsIgnoreCase(ATTR_UNREVOKED_CERTS)) {
+ return mUnrevokedCerts;
+ } else if (name.equalsIgnoreCase(ATTR_EXPIRED_CERTS)) {
+ return mExpiredCerts;
+ } else if (name.equalsIgnoreCase(ATTR_DELTA_CRL)) {
+ return mDeltaCRL;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+ }
+
+ public void delete(String name) throws EBaseException {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+
+ public Enumeration<String> getElements() {
+ return mNames.elements();
+ }
+
+ public Enumeration<String> getSerializableAttrNames() {
+ return mNames.elements();
+ }
+
+ /**
+ * Retrieve unique CRL identifier.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * Retrieves CRL number.
+ */
+ public BigInteger getCRLNumber() {
+ return mCRLNumber;
+ }
+
+ /**
+ * Retrieves CRL size.
+ */
+ public Long getCRLSize() {
+ return mCRLSize;
+ }
+
+ /**
+ * Retrieves this update time.
+ */
+ public Date getThisUpdate() {
+ return mThisUpdate;
+ }
+
+ /**
+ * Retrieves next update time.
+ */
+ public Date getNextUpdate() {
+ return mNextUpdate;
+ }
+
+ /**
+ * Retrieves delta CRL number.
+ */
+ public BigInteger getDeltaCRLNumber() {
+ return mDeltaCRLNumber;
+ }
+
+ /**
+ * Retrieves CRL size.
+ */
+ public Long getDeltaCRLSize() {
+ return mDeltaCRLSize;
+ }
+
+ /**
+ * Retrieve unique CRL identifier.
+ */
+ public String getFirstUnsaved() {
+ return mFirstUnsaved;
+ }
+
+ /**
+ * Retrieves CRL encodings.
+ */
+ public byte[] getCRL() {
+ return mCRL;
+ }
+
+ /**
+ * Retrieves CRL encodings.
+ */
+ public byte[] getDeltaCRL() {
+ return mDeltaCRL;
+ }
+
+ public byte[] getCACert() {
+ return mCACert;
+ }
+
+ public Hashtable<BigInteger, RevokedCertificate> getCRLCacheNoClone() {
+ if (mCRLCache == null)
+ return null;
+ else
+ return mCRLCache;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Hashtable<BigInteger, RevokedCertificate> getCRLCache() {
+ if (mCRLCache == null)
+ return null;
+ else
+ return (Hashtable<BigInteger, RevokedCertificate>) mCRLCache.clone();
+ }
+
+ /**
+ * Retrieves cache info of revoked certificates.
+ */
+ @SuppressWarnings("unchecked")
+ public Hashtable<BigInteger, RevokedCertificate> getRevokedCerts() {
+ if (mRevokedCerts == null)
+ return null;
+ else
+ return (Hashtable<BigInteger, RevokedCertificate>) mRevokedCerts.clone();
+ }
+
+ /**
+ * Retrieves cache info of unrevoked certificates.
+ */
+ @SuppressWarnings("unchecked")
+ public Hashtable<BigInteger, RevokedCertificate> getUnrevokedCerts() {
+ if (mUnrevokedCerts == null)
+ return null;
+ else
+ return (Hashtable<BigInteger, RevokedCertificate>) mUnrevokedCerts.clone();
+ }
+
+ /**
+ * Retrieves cache info of expired certificates.
+ */
+ @SuppressWarnings("unchecked")
+ public Hashtable<BigInteger, RevokedCertificate> getExpiredCerts() {
+ if (mExpiredCerts == null)
+ return null;
+ else
+ return (Hashtable<BigInteger, RevokedCertificate>) mExpiredCerts.clone();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/CRLRepository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/CRLRepository.java
new file mode 100644
index 000000000..c83494984
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/CRLRepository.java
@@ -0,0 +1,370 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import netscape.security.x509.RevokedCertificate;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSearchResults;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+import com.netscape.certsrv.dbs.crldb.ICRLRepository;
+
+/**
+ * A class represents a CRL repository. It stores all the
+ * CRL issuing points.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class CRLRepository extends Repository implements ICRLRepository {
+
+ private final String mLdapCRLIssuingPointName = "cn";
+ private IDBSubsystem mDBService;
+ private String mBaseDN;
+
+ /**
+ * Constructs a CRL repository.
+ */
+ public CRLRepository(IDBSubsystem dbService, int increment, String baseDN)
+ throws EDBException {
+ super(dbService, increment, baseDN);
+ mBaseDN = baseDN;
+ mDBService = dbService;
+
+ /*
+ DBRegistry reg = dbService.getRegistry();
+ String crlRecordOC[] = new String[1];
+ crlRecordOC[0] = Schema.LDAP_OC_CRL_RECORD;
+ reg.registerObjectClass(CRLIssuingPointRecord.class.getName(), crlRecordOC);
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_ID,
+ new StringMapper(Schema.LDAP_ATTR_CRL_ID));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CRL_NUMBER,
+ new BigIntegerMapper(Schema.LDAP_ATTR_CRL_NUMBER));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CRL_SIZE,
+ new LongMapper(Schema.LDAP_ATTR_CRL_SIZE));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_THIS_UPDATE,
+ new DateMapper(Schema.LDAP_ATTR_THIS_UPDATE));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_NEXT_UPDATE,
+ new DateMapper(Schema.LDAP_ATTR_NEXT_UPDATE));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CRL,
+ new ByteArrayMapper(Schema.LDAP_ATTR_CRL));
+ */
+ }
+
+ /**
+ * Retrieves backend database handle.
+ */
+ public IDBSubsystem getDBSubsystem() {
+ return mDBService;
+ }
+
+ /**
+ * Retrieves DN of this repository.
+ */
+ public String getDN() {
+ return mBaseDN;
+ }
+
+ /**
+ * Removes all objects with this repository.
+ */
+ public void removeAllObjects() throws EBaseException {
+ }
+
+ /**
+ * Adds CRL issuing points.
+ */
+ public void addCRLIssuingPointRecord(ICRLIssuingPointRecord rec)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String name = mLdapCRLIssuingPointName + "=" +
+ ((CRLIssuingPointRecord) rec).getId().toString() + "," + getDN();
+
+ s.add(name, rec);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ /**
+ * Retrieves all issuing points' names
+ */
+ public Vector<String> getIssuingPointsNames() throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ try {
+ String[] attrs = { ICRLIssuingPointRecord.ATTR_ID, "objectclass" };
+ String filter = "objectclass=" + CMS.getCRLIssuingPointRecordName();
+ IDBSearchResults res = s.search(getDN(), filter, attrs);
+ Vector<String> v = new Vector<String>();
+ while (res.hasMoreElements()) {
+ ICRLIssuingPointRecord nextelement =
+ (ICRLIssuingPointRecord) res.nextElement();
+ CMS.debug("CRLRepository getIssuingPointsNames(): name = "
+ + nextelement.getId());
+ v.addElement(nextelement.getId());
+ }
+
+ return v;
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ /**
+ * Reads issuing point record.
+ */
+ public ICRLIssuingPointRecord readCRLIssuingPointRecord(String id)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ CRLIssuingPointRecord rec = null;
+
+ try {
+ String name = mLdapCRLIssuingPointName + "=" + id +
+ "," + getDN();
+
+ if (s != null) {
+ rec = (CRLIssuingPointRecord) s.read(name);
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return rec;
+ }
+
+ /**
+ * deletes issuing point record.
+ */
+ public void deleteCRLIssuingPointRecord(String id)
+ throws EBaseException {
+ IDBSSession s = null;
+
+ try {
+ s = mDBService.createSession();
+ String name = mLdapCRLIssuingPointName + "=" + id +
+ "," + getDN();
+
+ if (s != null)
+ s.delete(name);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ public void modifyCRLIssuingPointRecord(String id,
+ ModificationSet mods) throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String name = mLdapCRLIssuingPointName + "=" + id +
+ "," + getDN();
+
+ if (s != null)
+ s.modify(name, mods);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ /**
+ * Updates CRL issuing point record.
+ */
+ public void updateCRLIssuingPointRecord(String id, byte[] newCRL,
+ Date thisUpdate, Date nextUpdate, BigInteger crlNumber, Long crlSize)
+ throws EBaseException {
+ ModificationSet mods = new ModificationSet();
+
+ if (newCRL != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_CRL,
+ Modification.MOD_REPLACE, newCRL);
+ }
+ if (nextUpdate != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_NEXT_UPDATE,
+ Modification.MOD_REPLACE, nextUpdate);
+ }
+ mods.add(ICRLIssuingPointRecord.ATTR_THIS_UPDATE,
+ Modification.MOD_REPLACE, thisUpdate);
+ mods.add(ICRLIssuingPointRecord.ATTR_CRL_NUMBER,
+ Modification.MOD_REPLACE, crlNumber);
+ mods.add(ICRLIssuingPointRecord.ATTR_CRL_SIZE,
+ Modification.MOD_REPLACE, crlSize);
+ modifyCRLIssuingPointRecord(id, mods);
+ }
+
+ /**
+ * Updates CRL issuing point record.
+ */
+ public void updateCRLIssuingPointRecord(String id, byte[] newCRL,
+ Date thisUpdate, Date nextUpdate, BigInteger crlNumber, Long crlSize,
+ Hashtable<BigInteger, RevokedCertificate> revokedCerts,
+ Hashtable<BigInteger, RevokedCertificate> unrevokedCerts,
+ Hashtable<BigInteger, RevokedCertificate> expiredCerts)
+ throws EBaseException {
+ ModificationSet mods = new ModificationSet();
+
+ if (newCRL != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_CRL,
+ Modification.MOD_REPLACE, newCRL);
+ }
+ if (nextUpdate != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_NEXT_UPDATE,
+ Modification.MOD_REPLACE, nextUpdate);
+ }
+ mods.add(ICRLIssuingPointRecord.ATTR_THIS_UPDATE,
+ Modification.MOD_REPLACE, thisUpdate);
+ mods.add(ICRLIssuingPointRecord.ATTR_CRL_NUMBER,
+ Modification.MOD_REPLACE, crlNumber);
+ mods.add(ICRLIssuingPointRecord.ATTR_CRL_SIZE,
+ Modification.MOD_REPLACE, crlSize);
+ if (revokedCerts != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_REVOKED_CERTS,
+ Modification.MOD_REPLACE, revokedCerts);
+ }
+ if (unrevokedCerts != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_UNREVOKED_CERTS,
+ Modification.MOD_REPLACE, unrevokedCerts);
+ }
+ if (expiredCerts != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_EXPIRED_CERTS,
+ Modification.MOD_REPLACE, expiredCerts);
+ }
+ if (revokedCerts != null || unrevokedCerts != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_FIRST_UNSAVED,
+ Modification.MOD_REPLACE, ICRLIssuingPointRecord.CLEAN_CACHE);
+ }
+ modifyCRLIssuingPointRecord(id, mods);
+ }
+
+ /**
+ * Updates CRL issuing point record with recently revoked certificates info.
+ */
+ public void updateRevokedCerts(String id,
+ Hashtable<BigInteger, RevokedCertificate> revokedCerts,
+ Hashtable<BigInteger, RevokedCertificate> unrevokedCerts)
+ throws EBaseException {
+ ModificationSet mods = new ModificationSet();
+
+ mods.add(ICRLIssuingPointRecord.ATTR_REVOKED_CERTS,
+ Modification.MOD_REPLACE, revokedCerts);
+ mods.add(ICRLIssuingPointRecord.ATTR_UNREVOKED_CERTS,
+ Modification.MOD_REPLACE, unrevokedCerts);
+ mods.add(ICRLIssuingPointRecord.ATTR_FIRST_UNSAVED,
+ Modification.MOD_REPLACE, ICRLIssuingPointRecord.CLEAN_CACHE);
+ modifyCRLIssuingPointRecord(id, mods);
+ }
+
+ /**
+ * Updates CRL issuing point record with recently expired certificates info.
+ */
+ public void updateExpiredCerts(String id, Hashtable<BigInteger, RevokedCertificate> expiredCerts)
+ throws EBaseException {
+ ModificationSet mods = new ModificationSet();
+
+ mods.add(ICRLIssuingPointRecord.ATTR_EXPIRED_CERTS,
+ Modification.MOD_REPLACE, expiredCerts);
+ modifyCRLIssuingPointRecord(id, mods);
+ }
+
+ /**
+ * Updates CRL issuing point record with CRL cache info.
+ */
+ public void updateCRLCache(String id, Long crlSize,
+ Hashtable<BigInteger, RevokedCertificate> revokedCerts,
+ Hashtable<BigInteger, RevokedCertificate> unrevokedCerts,
+ Hashtable<BigInteger, RevokedCertificate> expiredCerts)
+ throws EBaseException {
+ ModificationSet mods = new ModificationSet();
+
+ if (crlSize != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_CRL_SIZE,
+ Modification.MOD_REPLACE, crlSize);
+ }
+ mods.add(ICRLIssuingPointRecord.ATTR_REVOKED_CERTS,
+ Modification.MOD_REPLACE, revokedCerts);
+ mods.add(ICRLIssuingPointRecord.ATTR_UNREVOKED_CERTS,
+ Modification.MOD_REPLACE, unrevokedCerts);
+ mods.add(ICRLIssuingPointRecord.ATTR_EXPIRED_CERTS,
+ Modification.MOD_REPLACE, expiredCerts);
+ mods.add(ICRLIssuingPointRecord.ATTR_FIRST_UNSAVED,
+ Modification.MOD_REPLACE, ICRLIssuingPointRecord.CLEAN_CACHE);
+ modifyCRLIssuingPointRecord(id, mods);
+ }
+
+ /**
+ * Updates CRL issuing point record with delta-CRL.
+ */
+ public void updateDeltaCRL(String id, BigInteger deltaCRLNumber,
+ Long deltaCRLSize, Date nextUpdate,
+ byte[] deltaCRL)
+ throws EBaseException {
+ ModificationSet mods = new ModificationSet();
+
+ if (deltaCRLNumber != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_DELTA_NUMBER,
+ Modification.MOD_REPLACE, deltaCRLNumber);
+ }
+ if (deltaCRLSize != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_DELTA_SIZE,
+ Modification.MOD_REPLACE, deltaCRLSize);
+ }
+ if (nextUpdate != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_NEXT_UPDATE,
+ Modification.MOD_REPLACE, nextUpdate);
+ }
+ if (deltaCRL != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_DELTA_CRL,
+ Modification.MOD_REPLACE, deltaCRL);
+ }
+ modifyCRLIssuingPointRecord(id, mods);
+ }
+
+ public void updateFirstUnsaved(String id, String firstUnsaved)
+ throws EBaseException {
+ ModificationSet mods = new ModificationSet();
+
+ if (firstUnsaved != null) {
+ mods.add(ICRLIssuingPointRecord.ATTR_FIRST_UNSAVED,
+ Modification.MOD_REPLACE, firstUnsaved);
+ }
+ modifyCRLIssuingPointRecord(id, mods);
+ }
+
+ public BigInteger getLastSerialNumberInRange(BigInteger serial_low_bound, BigInteger serial_upper_bound)
+ throws EBaseException {
+
+ return null;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/CertDBSchema.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertDBSchema.java
new file mode 100644
index 000000000..916e83a8a
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertDBSchema.java
@@ -0,0 +1,54 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+/**
+ * A class represents a collection of certificate record
+ * specific schema information.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class CertDBSchema {
+
+ public static final String LDAP_OC_TOP = "top";
+ public static final String LDAP_ATTR_META_INFO = "metaInfo";
+ public static final String LDAP_ATTR_SERIALNO = "serialno";
+ public static final String LDAP_ATTR_CREATE_TIME = "dateOfCreate";
+ public static final String LDAP_ATTR_MODIFY_TIME = "dateOfModify";
+ public static final String LDAP_ATTR_PUBLIC_KEY_DATA = "publicKeyData";
+
+ public static final String LDAP_OC_CERT_RECORD = "certificateRecord";
+ public static final String LDAP_ATTR_CERT_RECORD_ID = "certRecordId";
+ public static final String LDAP_ATTR_NOT_BEFORE = "notBefore";
+ public static final String LDAP_ATTR_NOT_AFTER = "notAfter";
+ public static final String LDAP_ATTR_SIGNED_CERT = "userCertificate";
+ public static final String LDAP_ATTR_VERSION = "version";
+ public static final String LDAP_ATTR_DURATION = "duration";
+ public static final String LDAP_ATTR_SUBJECT = "subjectName";
+ public static final String LDAP_ATTR_ALGORITHM = "algorithmId";
+ public static final String LDAP_ATTR_SIGNING_ALGORITHM = "signingAlgorithmId";
+ public static final String LDAP_ATTR_REVO_INFO = "revInfo";
+ public static final String LDAP_ATTR_CERT_STATUS = "certStatus";
+ public static final String LDAP_ATTR_AUTO_RENEW = "autoRenew";
+ public static final String LDAP_ATTR_ISSUED_BY = "issuedBy";
+ public static final String LDAP_ATTR_REVOKED_BY = "revokedBy";
+ public static final String LDAP_ATTR_REVOKED_ON = "revokedOn";
+ public static final String LDAP_ATTR_EXTENSION = "extension";
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/CertRecord.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertRecord.java
new file mode 100644
index 000000000..422d506d5
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertRecord.java
@@ -0,0 +1,283 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.math.BigInteger;
+import java.security.cert.Certificate;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.IRevocationInfo;
+
+/**
+ * A class represents a serializable certificate record.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class CertRecord implements IDBObj, ICertRecord {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6231895305929417777L;
+ private BigInteger mId = null;
+ private X509CertImpl mX509Certificate = null;
+ private String mStatus = null;
+ private String mAutoRenew = null;
+ private MetaInfo mMetaInfo = null;
+ // XXX revocationInfo not serializable
+ private transient RevocationInfo mRevocationInfo = null;
+ private Date mCreateTime = null;
+ private Date mModifyTime = null;
+ private String mIssuedBy = null;
+ private String mRevokedBy = null;
+ private Date mRevokedOn = null;
+
+ protected static Vector<String> mNames = new Vector<String>();
+ static {
+ mNames.addElement(ATTR_ID);
+ mNames.addElement(ATTR_META_INFO);
+ mNames.addElement(ATTR_REVO_INFO);
+ mNames.addElement(ATTR_X509CERT);
+ mNames.addElement(ATTR_CREATE_TIME);
+ mNames.addElement(ATTR_MODIFY_TIME);
+ mNames.addElement(ATTR_CERT_STATUS);
+ mNames.addElement(ATTR_AUTO_RENEW);
+ mNames.addElement(ATTR_ISSUED_BY);
+ mNames.addElement(ATTR_REVOKED_BY);
+ mNames.addElement(ATTR_REVOKED_ON);
+ }
+
+ /**
+ * Constructs empty certificate record.
+ */
+ public CertRecord() {
+ }
+
+ /**
+ * Constructs certiificate record with certificate
+ * and meta info.
+ */
+ public CertRecord(BigInteger id, Certificate cert, MetaInfo meta) {
+ mId = id;
+ if (cert instanceof X509CertImpl)
+ mX509Certificate = (X509CertImpl) cert;
+ mMetaInfo = meta;
+ mStatus = STATUS_VALID;
+ mAutoRenew = AUTO_RENEWAL_ENABLED;
+ mCreateTime = CMS.getCurrentDate();
+ mModifyTime = CMS.getCurrentDate();
+ }
+
+ /**
+ * Sets attribute to this record.
+ */
+ public void set(String name, Object obj) throws EBaseException {
+ if (name.equalsIgnoreCase(ATTR_REVO_INFO)) {
+ mRevocationInfo = (RevocationInfo) obj;
+ } else if (name.equalsIgnoreCase(ATTR_ID)) {
+ mId = (BigInteger) obj;
+ } else if (name.equalsIgnoreCase(ATTR_META_INFO)) {
+ mMetaInfo = (MetaInfo) obj;
+ } else if (name.equalsIgnoreCase(ATTR_X509CERT)) {
+ mX509Certificate = (X509CertImpl) obj;
+ } else if (name.equalsIgnoreCase(ATTR_CERT_STATUS)) {
+ mStatus = (String) obj;
+ } else if (name.equalsIgnoreCase(ATTR_AUTO_RENEW)) {
+ mAutoRenew = (String) obj;
+ } else if (name.equalsIgnoreCase(ATTR_CREATE_TIME)) {
+ mCreateTime = (Date) obj;
+ } else if (name.equalsIgnoreCase(ATTR_MODIFY_TIME)) {
+ mModifyTime = (Date) obj;
+ } else if (name.equalsIgnoreCase(ATTR_ISSUED_BY)) {
+ mIssuedBy = (String) obj;
+ } else if (name.equalsIgnoreCase(ATTR_REVOKED_BY)) {
+ mRevokedBy = (String) obj;
+ } else if (name.equalsIgnoreCase(ATTR_REVOKED_ON)) {
+ mRevokedOn = (Date) obj;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+ }
+
+ /**
+ * Retrieves attributes from this record.
+ */
+ public Object get(String name) throws EBaseException {
+ if (name.equalsIgnoreCase(ATTR_REVO_INFO)) {
+ return mRevocationInfo;
+ } else if (name.equalsIgnoreCase(ATTR_ID)) {
+ return mId;
+ } else if (name.equalsIgnoreCase(ATTR_META_INFO)) {
+ return mMetaInfo;
+ } else if (name.equalsIgnoreCase(ATTR_X509CERT)) {
+ return mX509Certificate;
+ } else if (name.equalsIgnoreCase(ATTR_CERT_STATUS)) {
+ return mStatus;
+ } else if (name.equalsIgnoreCase(ATTR_AUTO_RENEW)) {
+ return mAutoRenew;
+ } else if (name.equalsIgnoreCase(ATTR_CREATE_TIME)) {
+ return mCreateTime;
+ } else if (name.equalsIgnoreCase(ATTR_MODIFY_TIME)) {
+ return mModifyTime;
+ } else if (name.equalsIgnoreCase(ATTR_ISSUED_BY)) {
+ return mIssuedBy;
+ } else if (name.equalsIgnoreCase(ATTR_REVOKED_BY)) {
+ return mRevokedBy;
+ } else if (name.equalsIgnoreCase(ATTR_REVOKED_ON)) {
+ return mRevokedOn;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+ }
+
+ /**
+ * Deletes attribute from this record.
+ */
+ public void delete(String name) throws EBaseException {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+
+ public Enumeration<String> getElements() {
+ return mNames.elements();
+ }
+
+ public Enumeration<String> getSerializableAttrNames() {
+ return mNames.elements();
+ }
+
+ /**
+ * Retrieves X509 certificate.
+ */
+ public X509CertImpl getCertificate() {
+ return mX509Certificate;
+ }
+
+ /**
+ * Retrieves meta information.
+ */
+ public MetaInfo getMetaInfo() {
+ return mMetaInfo;
+ }
+
+ /**
+ * Retrieves certificate status.
+ */
+ public String getStatus() {
+ return mStatus;
+ }
+
+ /**
+ * Retrieves the auto renew mode.
+ */
+ public String getAutoRenew() {
+ return mAutoRenew;
+ }
+
+ /**
+ * Retrieves revocation information.
+ */
+ public IRevocationInfo getRevocationInfo() {
+ return mRevocationInfo;
+ }
+
+ /**
+ * Retrieves serial number of this record. Usually,
+ * it is the same of the serial number of the
+ * associated certificate.
+ */
+ public BigInteger getSerialNumber() {
+ return mId;
+ }
+
+ /**
+ * Retrieves the person who issues this certificate.
+ */
+ public String getIssuedBy() {
+ return mIssuedBy;
+ }
+
+ /**
+ * Retrieves the person who revokes this certificate.
+ */
+ public String getRevokedBy() {
+ return mRevokedBy;
+ }
+
+ /**
+ * Retrieves the date which this record is revoked.
+ */
+ public Date getRevokedOn() {
+ return mRevokedOn;
+ }
+
+ /**
+ * Retrieves certificate serial number.
+ */
+ public BigInteger getCertificateSerialNumber() {
+ return mX509Certificate.getSerialNumber();
+ }
+
+ /**
+ * Retrieves not after.
+ */
+ public Date getNotAfter() {
+ return mX509Certificate.getNotAfter();
+ }
+
+ public Date getNotBefore() {
+ return mX509Certificate.getNotBefore();
+ }
+
+ /**
+ * Return revocation date.
+ */
+ public Date getRevocationDate() throws EDBException {
+ return mRevocationInfo.getRevocationDate();
+ }
+
+ public Date getCreateTime() {
+ return mCreateTime;
+ }
+
+ public Date getModifyTime() {
+ return mModifyTime;
+ }
+
+ /**
+ * String representation
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer("CertRecord: ");
+
+ if (getSerialNumber() != null)
+ buf.append(" " + getSerialNumber().toString());
+ return buf.toString();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/CertRecordList.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertRecordList.java
new file mode 100644
index 000000000..c4f10a61f
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertRecordList.java
@@ -0,0 +1,113 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBVirtualList;
+import com.netscape.certsrv.dbs.IElementProcessor;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertRecordList;
+
+/**
+ * A class represents a list of certificate records.
+ * <P>
+ *
+ * @author thomask mzhao
+ * @version $Revision$, $Date$
+ */
+public class CertRecordList implements ICertRecordList {
+
+ private IDBVirtualList<ICertRecord> mVlist = null;
+
+ /**
+ * Constructs a request list.
+ */
+ public CertRecordList(IDBVirtualList<ICertRecord> vlist) {
+ mVlist = vlist;
+ }
+
+ public int getCurrentIndex() {
+ return mVlist.getCurrentIndex();
+ }
+
+ /**
+ * Retrieves the size of request list.
+ */
+ public int getSize() {
+ // get the size of the virtual list
+ return mVlist.getSize();
+ }
+
+ public int getSizeBeforeJumpTo() {
+ return mVlist.getSizeBeforeJumpTo();
+
+ }
+
+ public int getSizeAfterJumpTo() {
+ return mVlist.getSizeAfterJumpTo();
+
+ }
+
+ /**
+ * Process certificate record as soon as it is returned.
+ * kmccarth: changed to ignore startidx and endidx because VLVs don't
+ * provide a stable list.
+ */
+ public void processCertRecords(int startidx, int endidx,
+ IElementProcessor ep) throws EBaseException {
+ int i = 0;
+ while (i < mVlist.getSize()) {
+ Object element = mVlist.getElementAt(i);
+ if (element != null && (!(element instanceof String))) {
+ ep.process(element);
+ }
+ i++;
+ }
+ }
+
+ /**
+ * Retrieves requests.
+ * It's no good to call this if you didnt check
+ * if the startidx, endidx are valid.
+ */
+ public Enumeration<ICertRecord> getCertRecords(int startidx, int endidx)
+ throws EBaseException {
+ Vector<ICertRecord> entries = new Vector<ICertRecord>();
+
+ for (int i = startidx; i <= endidx; i++) {
+ ICertRecord element = mVlist.getElementAt(i);
+
+ // CMS.debug("gerCertRecords[" + i + "] element: " + element);
+ if (element != null) {
+ entries.addElement(element);
+ }
+ }
+ return entries.elements();
+ }
+
+ public ICertRecord getCertRecord(int index)
+ throws EBaseException {
+
+ return mVlist.getElementAt(index);
+
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/CertRecordMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertRecordMapper.java
new file mode 100644
index 000000000..a074b41e6
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertRecordMapper.java
@@ -0,0 +1,95 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * A class represents a mapper to serialize
+ * certificate record into database.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class CertRecordMapper implements IDBAttrMapper {
+
+ private ICertificateRepository mDB = null;
+
+ public CertRecordMapper(ICertificateRepository db) {
+ mDB = db;
+ }
+
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(CertDBSchema.LDAP_ATTR_CERT_RECORD_ID);
+ return v.elements();
+ }
+
+ public void mapObjectToLDAPAttributeSet(IDBObj parent, String name,
+ Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ CertRecord rec = (CertRecord) obj;
+ attrs.add(new LDAPAttribute(
+ CertDBSchema.LDAP_ATTR_CERT_RECORD_ID,
+ rec.getSerialNumber().toString()));
+ }
+
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ try {
+ LDAPAttribute attr = attrs.getAttribute(
+ CertDBSchema.LDAP_ATTR_CERT_RECORD_ID);
+
+ if (attr == null)
+ return;
+ String serialno = (String) attr.getStringValues().nextElement();
+ ICertRecord rec = mDB.readCertificateRecord(
+ new BigInteger(serialno));
+
+ parent.set(name, rec);
+ } catch (Exception e) {
+ Debug.trace(e.toString());
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_DESERIALIZE_FAILED", name));
+ }
+ }
+
+ public String mapSearchFilter(String name, String op, String value)
+ throws EBaseException {
+ return name + op + value;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java
new file mode 100644
index 000000000..7d626b93d
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java
@@ -0,0 +1,2419 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+import java.security.cert.Certificate;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Random;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPSearchResults;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.ICRLIssuingPoint;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.EDBRecordNotFoundException;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSearchResults;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.IDBVirtualList;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertRecordList;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.dbs.certdb.IRevocationInfo;
+import com.netscape.certsrv.dbs.certdb.RenewableCertificateCollection;
+import com.netscape.certsrv.dbs.repository.IRepository;
+import com.netscape.certsrv.dbs.repository.IRepositoryRecord;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A class represents a certificate repository. It
+ * stores all the issued certificate.
+ * <P>
+ *
+ * @author thomask
+ * @author kanda
+ * @version $Revision$, $Date$
+ */
+public class CertificateRepository extends Repository
+ implements ICertificateRepository {
+
+ public final String CERT_X509ATTRIBUTE = "x509signedcert";
+ private static final String PROP_ENABLE_RANDOM_SERIAL_NUMBERS = "enableRandomSerialNumbers";
+ private static final String PROP_RANDOM_SERIAL_NUMBER_COUNTER = "randomSerialNumberCounter";
+ private static final String PROP_FORCE_MODE_CHANGE = "forceModeChange";
+ private static final String PROP_RANDOM_MODE = "random";
+ private static final String PROP_SEQUENTIAL_MODE = "sequential";
+ private static final String PROP_COLLISION_RECOVERY_STEPS = "collisionRecoverySteps";
+ private static final String PROP_COLLISION_RECOVERY_REGENERATIONS = "collisionRecoveryRegenerations";
+ private static final String PROP_MINIMUM_RANDOM_BITS = "minimumRandomBits";
+ private static final BigInteger BI_MINUS_ONE = (BigInteger.ZERO).subtract(BigInteger.ONE);
+
+ private IDBSubsystem mDBService;
+ private String mBaseDN;
+ private String mRequestBaseDN;
+ private boolean mConsistencyCheck = false;
+
+ @SuppressWarnings("unused")
+ private boolean mSkipIfInconsistent;
+
+ private Hashtable<String, ICRLIssuingPoint> mCRLIssuingPoints = new Hashtable<String, ICRLIssuingPoint>();
+
+ private int mTransitMaxRecords = 1000000;
+ private int mTransitRecordPageSize = 200;
+
+ private Random mRandom = null;
+ private int mBitLength = 0;
+ private BigInteger mRangeSize = null;
+ private int mMinRandomBitLength = 4;
+ private int mMaxCollisionRecoverySteps = 10;
+ private int mMaxCollisionRecoveryRegenerations = 3;
+ private IConfigStore mDBConfig = null;
+ private boolean mForceModeChange = false;
+
+ public CertStatusUpdateTask certStatusUpdateTask;
+ public RetrieveModificationsTask retrieveModificationsTask;
+
+ /**
+ * Constructs a certificate repository.
+ */
+ public CertificateRepository(IDBSubsystem dbService, String certRepoBaseDN, int increment, String baseDN)
+ throws EDBException {
+ super(dbService, increment, baseDN);
+ mBaseDN = certRepoBaseDN;
+ mDBService = dbService;
+ mDBConfig = mDBService.getDBConfigStore();
+ }
+
+ public ICertRecord createCertRecord(BigInteger id, Certificate cert, MetaInfo meta) {
+ return new CertRecord(id, cert, meta);
+ }
+
+ public boolean getEnableRandomSerialNumbers() {
+ return mEnableRandomSerialNumbers;
+ }
+
+ public void setEnableRandomSerialNumbers(boolean random, boolean updateMode, boolean forceModeChange) {
+ CMS.debug("CertificateRepository: setEnableRandomSerialNumbers random="+random+" updateMode="+updateMode);
+ if (mEnableRandomSerialNumbers ^ random || forceModeChange) {
+ mEnableRandomSerialNumbers = random;
+ CMS.debug("CertificateRepository: setEnableRandomSerialNumbers switching to " +
+ ((random)?PROP_RANDOM_MODE:PROP_SEQUENTIAL_MODE) + " mode");
+ if (updateMode) {
+ setCertificateRepositoryMode((mEnableRandomSerialNumbers)? PROP_RANDOM_MODE: PROP_SEQUENTIAL_MODE);
+ }
+ mDBConfig.putBoolean(PROP_ENABLE_RANDOM_SERIAL_NUMBERS, mEnableRandomSerialNumbers);
+
+ BigInteger lastSerialNumber = null;
+ try {
+ lastSerialNumber = getLastSerialNumberInRange(mMinSerialNo,mMaxSerialNo);
+ } catch (Exception e) {
+ }
+ if (lastSerialNumber != null) {
+ super.setLastSerialNo(lastSerialNumber);
+ if (mEnableRandomSerialNumbers) {
+ mCounter = lastSerialNumber.subtract(mMinSerialNo).add(BigInteger.ONE);
+ CMS.debug("CertificateRepository: setEnableRandomSerialNumbers mCounter="+
+ mCounter+"="+lastSerialNumber+"-"+mMinSerialNo+"+1");
+ long t = System.currentTimeMillis();
+ mDBConfig.putString(PROP_RANDOM_SERIAL_NUMBER_COUNTER, mCounter.toString()+","+t);
+ } else {
+ mCounter = BI_MINUS_ONE;
+ mDBConfig.putString(PROP_RANDOM_SERIAL_NUMBER_COUNTER, mCounter.toString());
+ }
+ }
+
+ try {
+ CMS.getConfigStore().commit(false);
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ private BigInteger getRandomNumber() throws EBaseException {
+ BigInteger randomNumber = null;
+
+ if (mRandom == null) {
+ mRandom = new Random();
+ }
+ super.initCacheIfNeeded();
+
+ if (mRangeSize == null) {
+ mRangeSize = (mMaxSerialNo.subtract(mMinSerialNo)).add(BigInteger.ONE);
+ CMS.debug("CertificateRepository: getRandomNumber mRangeSize="+mRangeSize);
+ mBitLength = mRangeSize.bitLength();
+ CMS.debug("CertificateRepository: getRandomNumber mBitLength="+mBitLength+
+ " >mMinRandomBitLength="+mMinRandomBitLength);
+ }
+ if (mBitLength < mMinRandomBitLength) {
+ CMS.debug("CertificateRepository: getRandomNumber mBitLength="+mBitLength+
+ " <mMinRandomBitLength="+mMinRandomBitLength);
+ CMS.debug("CertificateRepository: getRandomNumber: Range size is too small to support random certificate serial numbers.");
+ throw new EBaseException ("Range size is too small to support random certificate serial numbers.");
+ }
+ randomNumber = new BigInteger((mBitLength), mRandom);
+ randomNumber = (randomNumber.multiply(mRangeSize)).shiftRight(mBitLength);
+ CMS.debug("CertificateRepository: getRandomNumber randomNumber="+randomNumber);
+
+ return randomNumber;
+ }
+
+ private BigInteger getRandomSerialNumber(BigInteger randomNumber) throws EBaseException {
+ BigInteger nextSerialNumber = null;
+
+ nextSerialNumber = randomNumber.add(mMinSerialNo);
+ CMS.debug("CertificateRepository: getRandomSerialNumber nextSerialNumber="+nextSerialNumber);
+
+ return nextSerialNumber;
+ }
+
+ private BigInteger checkSerialNumbers(BigInteger randomNumber, BigInteger serialNumber) throws EBaseException {
+ BigInteger nextSerialNumber = null;
+ BigInteger initialRandomNumber = randomNumber;
+ BigInteger delta = BigInteger.ZERO;
+ int i = 0;
+ int n = mMaxCollisionRecoverySteps;
+
+ do {
+ CMS.debug("CertificateRepository: checkSerialNumbers checking("+(i+1)+")="+serialNumber);
+ try {
+ if (readCertificateRecord(serialNumber) != null) {
+ CMS.debug("CertificateRepository: checkSerialNumbers collision detected for serialNumber="+serialNumber);
+ }
+ } catch (EDBRecordNotFoundException nfe) {
+ CMS.debug("CertificateRepository: checkSerialNumbers serial number "+serialNumber+" is available");
+ nextSerialNumber = serialNumber;
+ } catch (Exception e) {
+ CMS.debug("CertificateRepository: checkSerialNumbers Exception="+e.getMessage());
+ }
+
+ if (nextSerialNumber == null) {
+ if (i%2 == 0) {
+ delta = delta.add(BigInteger.ONE);
+ serialNumber = getRandomSerialNumber(initialRandomNumber.add(delta));
+
+ if (mMaxSerialNo != null && serialNumber.compareTo(mMaxSerialNo) > 0) {
+ serialNumber = getRandomSerialNumber(initialRandomNumber.subtract(delta));
+ i++;
+ n++;
+ }
+ } else {
+ serialNumber = getRandomSerialNumber(initialRandomNumber.subtract(delta));
+ if (mMinSerialNo != null && serialNumber.compareTo(mMinSerialNo) < 0) {
+ delta = delta.add(BigInteger.ONE);
+ serialNumber = getRandomSerialNumber(initialRandomNumber.add(delta));
+ i++;
+ n++;
+ }
+ }
+ i++;
+ }
+ } while (nextSerialNumber == null && i < n);
+
+ return nextSerialNumber;
+ }
+
+ private Object nextSerialNumberMonitor = new Object();
+
+ public BigInteger getNextSerialNumber() throws
+ EBaseException {
+
+ BigInteger nextSerialNumber = null;
+ BigInteger randomNumber = null;
+
+ synchronized (nextSerialNumberMonitor) {
+ super.initCacheIfNeeded();
+ CMS.debug("CertificateRepository: getNextSerialNumber mEnableRandomSerialNumbers="+mEnableRandomSerialNumbers);
+
+ if (mEnableRandomSerialNumbers) {
+ int i = 0;
+ do {
+ if (i > 0) {
+ CMS.debug("CertificateRepository: getNextSerialNumber regenerating serial number");
+ }
+ randomNumber = getRandomNumber();
+ nextSerialNumber = getRandomSerialNumber(randomNumber);
+ nextSerialNumber = checkSerialNumbers(randomNumber, nextSerialNumber);
+ i++;
+ } while (nextSerialNumber == null && i < mMaxCollisionRecoveryRegenerations);
+
+ if (nextSerialNumber == null) {
+ CMS.debug("CertificateRepository: in getNextSerialNumber nextSerialNumber is null");
+ throw new EBaseException( "nextSerialNumber is null" );
+ }
+
+ if (mCounter.compareTo(BigInteger.ZERO) >= 0 &&
+ mMinSerialNo != null && mMaxSerialNo != null &&
+ nextSerialNumber != null &&
+ nextSerialNumber.compareTo(mMinSerialNo) >= 0 &&
+ nextSerialNumber.compareTo(mMaxSerialNo) <= 0) {
+ mCounter = mCounter.add(BigInteger.ONE);
+ }
+ CMS.debug("CertificateRepository: getNextSerialNumber nextSerialNumber="+
+ nextSerialNumber+" mCounter="+mCounter);
+
+ super.checkRange();
+ } else {
+ nextSerialNumber = super.getNextSerialNumber();
+ }
+ }
+
+ return nextSerialNumber;
+ }
+
+ private void updateCounter() {
+ CMS.debug("CertificateRepository: updateCounter mEnableRandomSerialNumbers="+
+ mEnableRandomSerialNumbers+" mCounter="+mCounter);
+ try {
+ super.initCacheIfNeeded();
+ } catch (Exception e) {
+ CMS.debug("CertificateRepository: updateCounter Exception from initCacheIfNeeded: "+e.getMessage());
+ }
+
+ String crMode = mDBService.getEntryAttribute(mBaseDN, IRepositoryRecord.ATTR_DESCRIPTION, "", null);
+
+ boolean modeChange = (mEnableRandomSerialNumbers && crMode != null && crMode.equals(PROP_SEQUENTIAL_MODE)) ||
+ ((!mEnableRandomSerialNumbers) && crMode != null && crMode.equals(PROP_RANDOM_MODE));
+ CMS.debug("CertificateRepository: updateCounter mEnableRandomSerialNumbers="+mEnableRandomSerialNumbers);
+ CMS.debug("CertificateRepository: updateCounter CertificateRepositoryMode ="+crMode);
+ CMS.debug("CertificateRepository: updateCounter modeChange="+modeChange);
+ if (modeChange) {
+ if (mForceModeChange) {
+ setEnableRandomSerialNumbers(mEnableRandomSerialNumbers, true, mForceModeChange);
+ } else {
+ setEnableRandomSerialNumbers(!mEnableRandomSerialNumbers, false, mForceModeChange);
+ }
+ } else if (mEnableRandomSerialNumbers && mCounter != null &&
+ mCounter.compareTo(BigInteger.ZERO) >= 0) {
+ long t = System.currentTimeMillis();
+ mDBConfig.putString(PROP_RANDOM_SERIAL_NUMBER_COUNTER, mCounter.toString()+","+t);
+ try {
+ CMS.getConfigStore().commit(false);
+ } catch (Exception e) {
+ CMS.debug("CertificateRepository: updateCounter Exception committing ConfigStore="+e.getMessage());
+ }
+ }
+ CMS.debug("CertificateRepository: UpdateCounter mEnableRandomSerialNumbers="+
+ mEnableRandomSerialNumbers+" mCounter="+mCounter);
+ }
+
+ private BigInteger getInRangeCount(String fromTime, BigInteger minSerialNo, BigInteger maxSerialNo)
+ throws EBaseException {
+ BigInteger count = BigInteger.ZERO;
+ String filter = null;
+
+ if (fromTime != null && fromTime.length() > 0) {
+ filter = "(certCreateTime >= "+fromTime+")";
+ } else {
+ filter = "(&("+ICertRecord.ATTR_ID+">="+minSerialNo+")("+
+ ICertRecord.ATTR_ID+"<="+maxSerialNo+"))";
+ }
+ CMS.debug("CertificateRepository: getInRangeCount filter="+filter+
+ " minSerialNo="+minSerialNo+" maxSerialNo="+maxSerialNo);
+
+ Enumeration<Object> e = findCertRecs(filter, new String[] {ICertRecord.ATTR_ID, "objectclass"});
+ while (e != null && e.hasMoreElements()) {
+ ICertRecord rec = (ICertRecord) e.nextElement();
+ if (rec != null) {
+ BigInteger sn = rec.getSerialNumber();
+ if (fromTime == null || fromTime.length() == 0 ||
+ (minSerialNo != null && maxSerialNo != null &&
+ sn != null && sn.compareTo(minSerialNo) >= 0 &&
+ sn.compareTo(maxSerialNo) <= 0)) {
+ count = count.add(BigInteger.ONE);
+ }
+ }
+ }
+ CMS.debug("CertificateRepository: getInRangeCount count=" + count);
+
+ return count;
+ }
+
+ private BigInteger getInRangeCounter(BigInteger minSerialNo, BigInteger maxSerialNo)
+ throws EBaseException {
+ String c = null;
+ String t = null;
+ String s = (mDBConfig.getString(PROP_RANDOM_SERIAL_NUMBER_COUNTER, "-1")).trim();
+ CMS.debug("CertificateRepository: getInRangeCounter: saved counter string="+s);
+ int i = s.indexOf(',');
+ int n = s.length();
+ if (i > -1) {
+ if (i > 0) {
+ c = s.substring(0, i);
+ if (i < n) {
+ t = s.substring(i+1);
+ }
+ } else {
+ c = "-1";
+ }
+ } else {
+ c = s;
+ }
+ CMS.debug("CertificateRepository: getInRangeCounter: c="+c+" t="+((t != null)?t:"null"));
+
+ BigInteger counter = new BigInteger(c);
+ BigInteger count = BigInteger.ZERO;
+ if (CMS.isPreOpMode()) {
+ CMS.debug("CertificateRepository: getInRangeCounter: CMS.isPreOpMode");
+ counter = new BigInteger("-2");
+ mDBConfig.putString(PROP_RANDOM_SERIAL_NUMBER_COUNTER, "-2");
+ try {
+ CMS.getConfigStore().commit(false);
+ } catch (Exception e) {
+ CMS.debug("CertificateRepository: updateCounter Exception committing ConfigStore="+e.getMessage());
+ }
+ } else if (t != null) {
+ count = getInRangeCount(t, minSerialNo, maxSerialNo);
+ if (count.compareTo(BigInteger.ZERO) > 0) {
+ counter = counter.add(count);
+ }
+ } else if (s.equals("-2")) {
+ count = getInRangeCount(t, minSerialNo, maxSerialNo);
+ if (count.compareTo(BigInteger.ZERO) >= 0) {
+ counter = count;
+ }
+ }
+ CMS.debug("CertificateRepository: getInRangeCounter: counter=" + counter);
+
+ return counter;
+ }
+
+ public BigInteger getLastSerialNumberInRange(BigInteger serial_low_bound, BigInteger serial_upper_bound)
+ throws EBaseException {
+
+ CMS.debug("CertificateRepository: in getLastSerialNumberInRange: low "
+ + serial_low_bound + " high " + serial_upper_bound);
+
+ if (serial_low_bound == null
+ || serial_upper_bound == null || serial_low_bound.compareTo(serial_upper_bound) >= 0) {
+ return null;
+
+ }
+
+ mEnableRandomSerialNumbers = mDBConfig.getBoolean(PROP_ENABLE_RANDOM_SERIAL_NUMBERS, false);
+ mForceModeChange = mDBConfig.getBoolean(PROP_FORCE_MODE_CHANGE, false);
+ String crMode = mDBService.getEntryAttribute(mBaseDN, IRepositoryRecord.ATTR_DESCRIPTION, "", null);
+ mMinRandomBitLength = mDBConfig.getInteger(PROP_MINIMUM_RANDOM_BITS, 4);
+ mMaxCollisionRecoverySteps = mDBConfig.getInteger(PROP_COLLISION_RECOVERY_STEPS, 10);
+ mMaxCollisionRecoveryRegenerations = mDBConfig.getInteger(PROP_COLLISION_RECOVERY_REGENERATIONS, 3);
+ boolean modeChange = (mEnableRandomSerialNumbers && crMode != null && crMode.equals(PROP_SEQUENTIAL_MODE)) ||
+ ((!mEnableRandomSerialNumbers) && crMode != null && crMode.equals(PROP_RANDOM_MODE));
+ boolean enableRsnAtConfig = mEnableRandomSerialNumbers && CMS.isPreOpMode() &&
+ (crMode == null || crMode.length() == 0);
+ CMS.debug("CertificateRepository: getLastSerialNumberInRange"+
+ " mEnableRandomSerialNumbers="+mEnableRandomSerialNumbers+
+ " mMinRandomBitLength="+mMinRandomBitLength+
+ " CollisionRecovery="+mMaxCollisionRecoveryRegenerations+","+mMaxCollisionRecoverySteps);
+ CMS.debug("CertificateRepository: getLastSerialNumberInRange modeChange="+modeChange+
+ " enableRsnAtConfig="+enableRsnAtConfig+" mForceModeChange="+mForceModeChange+
+ ((crMode != null)?" mode="+crMode:""));
+ if (modeChange || enableRsnAtConfig) {
+ if (mForceModeChange || enableRsnAtConfig) {
+ setCertificateRepositoryMode((mEnableRandomSerialNumbers)? PROP_RANDOM_MODE: PROP_SEQUENTIAL_MODE);
+ if (mForceModeChange) {
+ mForceModeChange = false;
+ mDBConfig.remove(PROP_FORCE_MODE_CHANGE);
+ }
+ } else {
+ mEnableRandomSerialNumbers = !mEnableRandomSerialNumbers;
+ mDBConfig.putBoolean(PROP_ENABLE_RANDOM_SERIAL_NUMBERS, mEnableRandomSerialNumbers);
+ }
+ }
+ if (mEnableRandomSerialNumbers && mCounter == null) {
+ mCounter = getInRangeCounter(serial_low_bound, serial_upper_bound);
+ } else {
+ mCounter = BI_MINUS_ONE;
+ }
+ mDBConfig.putString(PROP_RANDOM_SERIAL_NUMBER_COUNTER, mCounter.toString());
+ try {
+ CMS.getConfigStore().commit(false);
+ } catch (Exception e) {
+ }
+ CMS.debug("CertificateRepository: getLastSerialNumberInRange mEnableRandomSerialNumbers="+mEnableRandomSerialNumbers);
+
+ String ldapfilter = "("+ICertRecord.ATTR_CERT_STATUS+"=*"+")";
+
+ String[] attrs = null;
+
+ ICertRecordList recList =
+ findCertRecordsInList(ldapfilter, attrs, serial_upper_bound.toString(10), "serialno", 5 * -1);
+
+ int size = recList.getSize();
+
+ CMS.debug("CertificateRepository:getLastSerialNumberInRange: recList size " + size);
+
+ if (size <= 0) {
+ CMS.debug("CertificateRepository:getLastSerialNumberInRange: index may be empty");
+
+ BigInteger ret = new BigInteger(serial_low_bound.toString(10));
+
+ ret = ret.subtract(BigInteger.ONE);
+ CMS.debug("CertificateRepository:getLastCertRecordSerialNo: returning " + ret);
+ return ret;
+ }
+ int ltSize = recList.getSizeBeforeJumpTo();
+
+ CMS.debug("CertificateRepository:getLastSerialNumberInRange: ltSize " + ltSize);
+
+ CertRecord curRec = null;
+
+ int i;
+ Object obj = null;
+
+ for (i = 0; i < 5; i++) {
+ obj = recList.getCertRecord(i);
+
+ if (obj != null) {
+ curRec = (CertRecord) obj;
+
+ BigInteger serial = curRec.getSerialNumber();
+
+ CMS.debug("CertificateRepository:getLastCertRecordSerialNo: serialno " + serial);
+
+ if (((serial.compareTo(serial_low_bound) == 0) || (serial.compareTo(serial_low_bound) == 1)) &&
+ ((serial.compareTo(serial_upper_bound) == 0) || (serial.compareTo(serial_upper_bound) == -1))) {
+ CMS.debug("getLastSerialNumberInRange returning: " + serial);
+ if (modeChange && mEnableRandomSerialNumbers) {
+ mCounter = serial.subtract(serial_low_bound).add(BigInteger.ONE);
+ CMS.debug("getLastSerialNumberInRange mCounter: " + mCounter);
+ }
+ return serial;
+ }
+ } else {
+ CMS.debug("getLastSerialNumberInRange:found null from getCertRecord");
+ }
+ }
+
+ BigInteger ret = new BigInteger(serial_low_bound.toString(10));
+
+ ret = ret.subtract(BigInteger.ONE);
+
+ CMS.debug("CertificateRepository:getLastCertRecordSerialNo: returning " + ret);
+ if (modeChange && mEnableRandomSerialNumbers) {
+ mCounter = BigInteger.ZERO;
+ CMS.debug("getLastSerialNumberInRange mCounter: " + mCounter);
+ }
+ return ret;
+
+ }
+
+ /**
+ * Removes all objects with this repository.
+ */
+ public void removeCertRecords(BigInteger beginS, BigInteger endS) throws EBaseException {
+ String filter = "(" + CertRecord.ATTR_CERT_STATUS + "=*" + ")";
+ ICertRecordList list = findCertRecordsInList(filter,
+ null, "serialno", 10);
+ int size = list.getSize();
+ Enumeration<ICertRecord> e = list.getCertRecords(0, size - 1);
+ while (e.hasMoreElements()) {
+ CertRecord rec = (CertRecord) e.nextElement();
+ BigInteger cur = rec.getSerialNumber();
+ BigInteger max = cur.max(beginS);
+ BigInteger min = cur;
+ if (endS != null)
+ min = cur.min(endS);
+ if (cur.equals(beginS) || cur.equals(endS) ||
+ (cur.equals(max) && cur.equals(min)))
+ deleteCertificateRecord(cur);
+ }
+ }
+
+ public void setConsistencyCheck(boolean ConsistencyCheck) {
+ mConsistencyCheck = ConsistencyCheck;
+ }
+
+ public void setSkipIfInConsistent(boolean SkipIfInconsistent) {
+ mSkipIfInconsistent = SkipIfInconsistent;
+ }
+
+ public void setTransitMaxRecords(int max) {
+ mTransitMaxRecords = max;
+ }
+
+ public void setTransitRecordPageSize(int size) {
+ mTransitRecordPageSize = size;
+
+ }
+
+ /**
+ * register CRL Issuing Point
+ */
+ public void addCRLIssuingPoint(String id, ICRLIssuingPoint crlIssuingPoint) {
+ mCRLIssuingPoints.put(id, crlIssuingPoint);
+ }
+
+ /**
+ * interval value: (in seconds)
+ * 0 - disable
+ * >0 - enable
+ */
+ public void setCertStatusUpdateInterval(IRepository requestRepository, int interval,
+ boolean listenToCloneModifications) {
+
+ CMS.debug("In setCertStatusUpdateInterval " + interval);
+
+ // stop running tasks
+ if (certStatusUpdateTask != null) {
+ certStatusUpdateTask.stop();
+ }
+ if (retrieveModificationsTask != null) {
+ retrieveModificationsTask.stop();
+ }
+
+ if (interval == 0) {
+ CMS.debug("In setCertStatusUpdateInterval interval = 0");
+ return;
+ }
+
+ CMS.debug("In setCertStatusUpdateInterval listenToCloneModifications=" + listenToCloneModifications);
+
+ if (listenToCloneModifications) {
+ CMS.debug("In setCertStatusUpdateInterval listening to modifications");
+ retrieveModificationsTask = new RetrieveModificationsTask(this);
+ retrieveModificationsTask.start();
+ }
+
+ CMS.debug("In setCertStatusUpdateInterval scheduling cert status update every " + interval + " seconds.");
+ certStatusUpdateTask = new CertStatusUpdateTask(this, requestRepository, interval);
+ certStatusUpdateTask.start();
+ }
+
+ public void updateCertStatus() throws EBaseException {
+
+ CMS.debug("In updateCertStatus()");
+
+ CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ CMS.getLogMessage("CMSCORE_DBS_START_VALID_SEARCH"));
+ transitInvalidCertificates();
+ CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ CMS.getLogMessage("CMSCORE_DBS_FINISH_VALID_SEARCH"));
+
+ CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ CMS.getLogMessage("CMSCORE_DBS_START_EXPIRED_SEARCH"));
+ transitValidCertificates();
+ CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ CMS.getLogMessage("CMSCORE_DBS_FINISH_EXPIRED_SEARCH"));
+
+ CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ CMS.getLogMessage("CMSCORE_DBS_START_REVOKED_EXPIRED_SEARCH"));
+ transitRevokedExpiredCertificates();
+ CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ CMS.getLogMessage("CMSCORE_DBS_FINISH_REVOKED_EXPIRED_SEARCH"));
+ updateCounter();
+ }
+
+ /**
+ * Retrieves DN of this repository.
+ */
+ public String getDN() {
+ return mBaseDN;
+ }
+
+ public void setRequestDN(String requestDN) {
+ mRequestBaseDN = requestDN;
+ }
+
+ public String getRequestDN() {
+ return mRequestBaseDN;
+ }
+
+ /**
+ * Retrieves backend database handle.
+ */
+ public IDBSubsystem getDBSubsystem() {
+ return mDBService;
+ }
+
+ /**
+ * Adds a certificate record to the repository. Each certificate
+ * record contains four parts: certificate, meta-attributes,
+ * issue information and reovcation information.
+ * <P>
+ *
+ * @param cert X.509 certificate
+ * @exception EBaseException failed to add new certificate to
+ * the repository
+ */
+ public void addCertificateRecord(ICertRecord record)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String name = "cn" + "=" +
+ ((CertRecord) record).getSerialNumber().toString() + "," + getDN();
+ SessionContext ctx = SessionContext.getContext();
+ String uid = (String) ctx.get(SessionContext.USER_ID);
+
+ if (uid == null) {
+ // XXX is this right?
+ record.set(CertRecord.ATTR_ISSUED_BY, "system");
+
+ /**
+ * System.out.println("XXX servlet should set USER_ID");
+ * throw new EBaseException(BaseResources.UNKNOWN_PRINCIPAL_1,
+ * "null");
+ **/
+ } else {
+ record.set(CertRecord.ATTR_ISSUED_BY, uid);
+ }
+
+ // Check validity of this certificate. If it is not invalid,
+ // mark it so. We will have a thread to transit the status
+ // from INVALID to VALID.
+ X509CertImpl x509cert = (X509CertImpl) record.get(
+ CertRecord.ATTR_X509CERT);
+
+ if (x509cert != null) {
+ Date now = CMS.getCurrentDate();
+
+ if (x509cert.getNotBefore().after(now)) {
+ // not yet valid
+ record.set(ICertRecord.ATTR_CERT_STATUS,
+ ICertRecord.STATUS_INVALID);
+ }
+ }
+
+ s.add(name, record);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ /**
+ * Used by the Clone Master (CLA) to add a revoked certificate
+ * record to the repository.
+ * <p>
+ *
+ * @param record a CertRecord
+ * @exception EBaseException failed to add new certificate to
+ * the repository
+ */
+ public void addRevokedCertRecord(CertRecord record)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String name = "cn" + "=" +
+ record.getSerialNumber().toString() + "," + getDN();
+
+ s.add(name, record);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ /**
+ * This transits a certificate status from VALID to EXPIRED
+ * if a certificate becomes expired.
+ */
+ public void transitValidCertificates() throws EBaseException {
+
+ Date now = CMS.getCurrentDate();
+ ICertRecordList recList = getValidCertsByNotAfterDate(now, -1 * mTransitRecordPageSize);
+
+ int size = recList.getSize();
+
+ if (size <= 0) {
+ CMS.debug("index may be empty");
+ return;
+ }
+ int ltSize = recList.getSizeBeforeJumpTo();
+
+ ltSize = Math.min(ltSize, mTransitMaxRecords);
+
+ Vector<Serializable> cList = new Vector<Serializable>(ltSize);
+
+ CMS.debug("transidValidCertificates: list size: " + size);
+ CMS.debug("transitValidCertificates: ltSize " + ltSize);
+
+ CertRecord curRec = null;
+
+ int i;
+ ICertRecord obj = null;
+
+ for (i = 0; i < ltSize; i++) {
+ obj = recList.getCertRecord(i);
+
+ if (obj != null) {
+ curRec = (CertRecord) obj;
+
+ Date notAfter = curRec.getNotAfter();
+
+ //CMS.debug("notAfter " + notAfter.toString() + " now " + now.toString());
+ if (notAfter.after(now)) {
+ CMS.debug("Record does not qualify,notAfter " + notAfter.toString() + " date " + now.toString());
+ continue;
+ }
+
+ CMS.debug("transitValid: curRec: " + i + " " + curRec.toString());
+
+ if (mConsistencyCheck) {
+ cList.add(curRec);
+ } else {
+ cList.add(curRec.getSerialNumber());
+ }
+ } else {
+ CMS.debug("found null from getCertRecord");
+ }
+ }
+
+ transitCertList(cList, CertRecord.STATUS_EXPIRED);
+ }
+
+ /**
+ * This transits a certificate status from REVOKED to REVOKED_EXPIRED
+ * if an revoked certificate becomes expired.
+ */
+ public void transitRevokedExpiredCertificates() throws EBaseException {
+ Date now = CMS.getCurrentDate();
+ ICertRecordList recList = getRevokedCertsByNotAfterDate(now, -1 * mTransitRecordPageSize);
+
+ int size = recList.getSize();
+
+ if (size <= 0) {
+ CMS.debug("index may be empty");
+ return;
+ }
+
+ int ltSize = recList.getSizeBeforeJumpTo();
+ Vector<Serializable> cList = new Vector<Serializable>(ltSize);
+
+ ltSize = Math.min(ltSize, mTransitMaxRecords);
+
+ CMS.debug("transitRevokedExpiredCertificates: list size: " + size);
+ CMS.debug("transitRevokedExpiredCertificates: ltSize " + ltSize);
+
+ CertRecord curRec = null;
+ int i;
+ Object obj = null;
+
+ for (i = 0; i < ltSize; i++) {
+ obj = recList.getCertRecord(i);
+ if (obj != null) {
+ curRec = (CertRecord) obj;
+ CMS.debug("transitRevokedExpired: curRec: " + i + " " + curRec.toString());
+
+ Date notAfter = curRec.getNotAfter();
+
+ // CMS.debug("notAfter " + notAfter.toString() + " now " + now.toString());
+ if (notAfter.after(now)) {
+ CMS.debug("Record does not qualify,notAfter " + notAfter.toString() + " date " + now.toString());
+ continue;
+ }
+
+ if (mConsistencyCheck) {
+ cList.add(curRec);
+ } else {
+ cList.add(curRec.getSerialNumber());
+ }
+ } else {
+ CMS.debug("found null record in getCertRecord");
+ }
+ }
+
+ transitCertList(cList, CertRecord.STATUS_REVOKED_EXPIRED);
+
+ }
+
+ /**
+ * This transits a certificate status from INVALID to VALID
+ * if a certificate becomes valid.
+ */
+ public void transitInvalidCertificates() throws EBaseException {
+
+ Date now = CMS.getCurrentDate();
+
+ ICertRecordList recList = getInvalidCertsByNotBeforeDate(now, -1 * mTransitRecordPageSize);
+
+ int size = recList.getSize();
+
+ if (size <= 0) {
+ CMS.debug("index may be empty");
+ return;
+ }
+ int ltSize = recList.getSizeBeforeJumpTo();
+
+ ltSize = Math.min(ltSize, mTransitMaxRecords);
+
+ Vector<Serializable> cList = new Vector<Serializable>(ltSize);
+
+ CMS.debug("transidInValidCertificates: list size: " + size);
+ CMS.debug("transitInValidCertificates: ltSize " + ltSize);
+
+ CertRecord curRec = null;
+
+ int i;
+
+ Object obj = null;
+
+ for (i = 0; i < ltSize; i++) {
+ obj = recList.getCertRecord(i);
+
+ if (obj != null) {
+ curRec = (CertRecord) obj;
+
+ Date notBefore = curRec.getNotBefore();
+
+ //CMS.debug("notBefore " + notBefore.toString() + " now " + now.toString());
+ if (notBefore.after(now)) {
+ CMS.debug("Record does not qualify,notBefore " + notBefore.toString() + " date " + now.toString());
+ continue;
+
+ }
+ CMS.debug("transitInValid: curRec: " + i + " " + curRec.toString());
+
+ if (mConsistencyCheck) {
+ cList.add(curRec);
+ } else {
+ cList.add(curRec.getSerialNumber());
+ }
+
+ } else {
+ CMS.debug("found null from getCertRecord");
+ }
+ }
+
+ transitCertList(cList, CertRecord.STATUS_VALID);
+
+ }
+
+ private void transitCertList(Vector<Serializable> cList, String newCertStatus) throws EBaseException {
+ CertRecord cRec = null;
+ BigInteger serial = null;
+
+ int i;
+
+ CMS.debug("transitCertList " + newCertStatus);
+
+ for (i = 0; i < cList.size(); i++) {
+ if (mConsistencyCheck) {
+ cRec = (CertRecord) cList.elementAt(i);
+
+ if (cRec == null)
+ continue;
+
+ serial = cRec.getSerialNumber();
+ } else {
+ serial = (BigInteger) cList.elementAt(i);
+ }
+
+ updateStatus(serial, newCertStatus);
+
+ if (newCertStatus.equals(CertRecord.STATUS_REVOKED_EXPIRED)) {
+
+ // inform all CRLIssuingPoints about revoked and expired certificate
+
+ Enumeration<ICRLIssuingPoint> eIPs = mCRLIssuingPoints.elements();
+
+ while (eIPs.hasMoreElements()) {
+ ICRLIssuingPoint ip = eIPs.nextElement();
+
+ if (ip != null) {
+ ip.addExpiredCert(serial);
+ }
+ }
+
+ }
+
+ CMS.debug("transitCertList number at: " + i + " = " + serial);
+ }
+
+ cList.removeAllElements();
+ }
+
+ /**
+ * Reads the certificate identified by the given serial no.
+ */
+ public X509CertImpl getX509Certificate(BigInteger serialNo)
+ throws EBaseException {
+ ICertRecord cr = readCertificateRecord(serialNo);
+
+ return (cr.getCertificate());
+ }
+
+ /**
+ * Deletes certificate record.
+ */
+ public void deleteCertificateRecord(BigInteger serialNo)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String name = "cn" + "=" +
+ serialNo.toString() + "," + getDN();
+
+ s.delete(name);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ /**
+ * Reads certificate from repository.
+ */
+ public ICertRecord readCertificateRecord(BigInteger serialNo)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ CertRecord rec = null;
+
+ try {
+ String name = "cn" + "=" +
+ serialNo.toString() + "," + getDN();
+
+ rec = (CertRecord) s.read(name);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return rec;
+ }
+
+ public boolean checkCertificateRecord(BigInteger serialNo)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ CertRecord rec = null;
+ boolean exists = true;
+
+ try {
+ String name = "cn" + "=" +
+ serialNo.toString() + "," + getDN();
+ String attrs[] = { "DN" };
+
+ rec = (CertRecord) s.read(name, attrs);
+ if (rec == null) exists = false;
+ } catch (EDBRecordNotFoundException e) {
+ exists = false;
+ } catch (Exception e) {
+ throw new EBaseException(e.getMessage());
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return exists;
+ }
+
+ private void setCertificateRepositoryMode(String mode) {
+ IDBSSession s = null;
+
+ CMS.debug("CertificateRepository: setCertificateRepositoryMode setting mode: "+mode);
+ try {
+ s = mDBService.createSession();
+ ModificationSet mods = new ModificationSet();
+ String name = getDN();
+ mods.add(IRepositoryRecord.ATTR_DESCRIPTION, Modification.MOD_REPLACE, mode);
+ s.modify(name, mods);
+ } catch (Exception e) {
+ CMS.debug("CertificateRepository: setCertificateRepositoryMode Exception: "+e.getMessage());
+ }
+ try {
+ if (s != null) s.close();
+ } catch (Exception e) {
+ CMS.debug("CertificateRepository: setCertificateRepositoryMode Exception: "+e.getMessage());
+ }
+ }
+
+ public synchronized void modifyCertificateRecord(BigInteger serialNo,
+ ModificationSet mods) throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String name = "cn" + "=" +
+ serialNo.toString() + "," + getDN();
+
+ mods.add(CertRecord.ATTR_MODIFY_TIME, Modification.MOD_REPLACE,
+ CMS.getCurrentDate());
+ s.modify(name, mods);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ /**
+ * Checks if the specified certificate is in the repository.
+ */
+ public boolean containsCertificate(BigInteger serialNo)
+ throws EBaseException {
+ try {
+ ICertRecord cr = readCertificateRecord(serialNo);
+
+ if (cr != null)
+ return true;
+ } catch (EBaseException e) {
+ }
+ return false;
+ }
+
+ /**
+ * Marks certificate as revoked.
+ */
+ public void markAsRevoked(BigInteger id, IRevocationInfo info)
+ throws EBaseException {
+ ModificationSet mods = new ModificationSet();
+
+ mods.add(CertRecord.ATTR_REVO_INFO, Modification.MOD_ADD, info);
+ SessionContext ctx = SessionContext.getContext();
+ String uid = (String) ctx.get(SessionContext.USER_ID);
+
+ if (uid == null) {
+ mods.add(CertRecord.ATTR_REVOKED_BY, Modification.MOD_ADD,
+ "system");
+ } else {
+ mods.add(CertRecord.ATTR_REVOKED_BY, Modification.MOD_ADD,
+ uid);
+ }
+ mods.add(CertRecord.ATTR_REVOKED_ON, Modification.MOD_ADD,
+ CMS.getCurrentDate());
+ mods.add(CertRecord.ATTR_CERT_STATUS, Modification.MOD_REPLACE,
+ CertRecord.STATUS_REVOKED);
+ modifyCertificateRecord(id, mods);
+ }
+
+ /**
+ * Unmarks revoked certificate.
+ */
+ public void unmarkRevoked(BigInteger id, IRevocationInfo info,
+ Date revokedOn, String revokedBy)
+ throws EBaseException {
+ ModificationSet mods = new ModificationSet();
+
+ mods.add(CertRecord.ATTR_REVO_INFO, Modification.MOD_DELETE, info);
+ mods.add(CertRecord.ATTR_REVOKED_BY, Modification.MOD_DELETE, revokedBy);
+ mods.add(CertRecord.ATTR_REVOKED_ON, Modification.MOD_DELETE, revokedOn);
+ mods.add(CertRecord.ATTR_CERT_STATUS, Modification.MOD_REPLACE,
+ CertRecord.STATUS_VALID);
+ modifyCertificateRecord(id, mods);
+ }
+
+ /**
+ * Updates the certificiate record status to the specified.
+ */
+ public void updateStatus(BigInteger id, String status)
+ throws EBaseException {
+ CMS.debug("updateStatus: " + id + " status " + status);
+ ModificationSet mods = new ModificationSet();
+
+ mods.add(CertRecord.ATTR_CERT_STATUS, Modification.MOD_REPLACE,
+ status);
+ modifyCertificateRecord(id, mods);
+ }
+
+ public Enumeration<Object> searchCertificates(String filter, int maxSize)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<Object> e = null;
+
+ CMS.debug("searchCertificates filter " + filter + " maxSize " + maxSize);
+ try {
+ e = s.search(getDN(), filter, maxSize);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ public Enumeration<ICertRecord> searchCertificates(String filter, int maxSize, int timeLimit)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Vector<ICertRecord> v = new Vector<ICertRecord>();
+
+ CMS.debug("searchCertificateswith time limit filter " + filter);
+ try {
+ IDBSearchResults sr = s.search(getDN(), filter, maxSize, timeLimit);
+ while (sr.hasMoreElements()) {
+ v.add((ICertRecord) sr.nextElement());
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return v.elements();
+ }
+
+ /**
+ * Returns a list of X509CertImp that satisfies the filter.
+ *
+ * @deprecated replaced by <code>findCertificatesInList</code>
+ */
+ public Enumeration<Object> findCertRecs(String filter)
+ throws EBaseException {
+ CMS.debug("findCertRecs " + filter);
+ IDBSSession s = mDBService.createSession();
+ Enumeration<Object> e = null;
+ try {
+ e = s.search(getDN(), filter);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ public Enumeration<Object> findCertRecs(String filter, String[] attrs)
+ throws EBaseException {
+
+ CMS.debug("findCertRecs " + filter
+ + "attrs " + Arrays.toString(attrs));
+ IDBSSession s = mDBService.createSession();
+ Enumeration<Object> e = null;
+ try {
+ e = s.search(getDN(), filter, attrs);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return e;
+
+ }
+
+ public Enumeration<X509CertImpl> findCertificates(String filter)
+ throws EBaseException {
+ Enumeration<ICertRecord> e = findCertRecords(filter);
+ Vector<X509CertImpl> v = new Vector<X509CertImpl>();
+
+ while (e.hasMoreElements()) {
+ ICertRecord rec = e.nextElement();
+
+ v.addElement(rec.getCertificate());
+ }
+ return v.elements();
+ }
+
+ /**
+ * Finds a list of certificate records that satisifies
+ * the filter.
+ * If you are going to process everything in the list,
+ * use this.
+ */
+ public Enumeration<ICertRecord> findCertRecords(String filter)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<ICertRecord> e = null;
+
+ try {
+ //e = s.search(getDN(), filter);
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(filter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ /**
+ * Finds certificate records. Here is a list of filter
+ * attribute can be used:
+ *
+ * <pre>
+ * certRecordId
+ * certMetaInfo
+ * certStatus
+ * certCreateTime
+ * certModifyTime
+ * x509Cert.notBefore
+ * x509Cert.notAfter
+ * x509Cert.subject
+ * </pre>
+ *
+ * The filter should follow RFC1558 LDAP filter syntax.
+ * For example,
+ *
+ * <pre>
+ * (&(certRecordId=5)(x509Cert.notBefore=934398398))
+ * </pre>
+ */
+ public ICertRecordList findCertRecordsInList(String filter,
+ String attrs[], int pageSize) throws EBaseException {
+ return findCertRecordsInList(filter, attrs, CertRecord.ATTR_ID,
+ pageSize);
+ }
+
+ public ICertRecordList findCertRecordsInList(String filter,
+ String attrs[], String sortKey, int pageSize)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ CMS.debug("In findCertRecordsInList");
+ CertRecordList list = null;
+
+ try {
+ IDBVirtualList<ICertRecord> vlist = s.<ICertRecord>createVirtualList(getDN(), filter, attrs,
+ sortKey, pageSize);
+
+ list = new CertRecordList(vlist);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return list;
+ }
+
+ public ICertRecordList findCertRecordsInList(String filter,
+ String attrs[], String jumpTo, String sortKey, int pageSize)
+ throws EBaseException {
+ return findCertRecordsInList(filter, attrs, jumpTo, false, sortKey, pageSize);
+
+ }
+
+ public ICertRecordList findCertRecordsInList(String filter,
+ String attrs[], String jumpTo, boolean hardJumpTo,
+ String sortKey, int pageSize)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ CertRecordList list = null;
+
+ CMS.debug("In findCertRecordsInList with Jumpto " + jumpTo);
+ try {
+ String jumpToVal = null;
+
+ if (hardJumpTo) {
+ CMS.debug("In findCertRecordsInList with hardJumpto ");
+ jumpToVal = "99";
+ } else {
+ int len = jumpTo.length();
+
+ if (len > 9) {
+ jumpToVal = Integer.toString(len) + jumpTo;
+ } else {
+ jumpToVal = "0" + Integer.toString(len) + jumpTo;
+ }
+ }
+
+ IDBVirtualList<ICertRecord> vlist = s.createVirtualList(getDN(), filter,
+ attrs, jumpToVal, sortKey, pageSize);
+
+ list = new CertRecordList(vlist);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return list;
+ }
+
+ public ICertRecordList findCertRecordsInListRawJumpto(String filter,
+ String attrs[], String jumpTo, String sortKey, int pageSize)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ CertRecordList list = null;
+
+ CMS.debug("In findCertRecordsInListRawJumpto with Jumpto " + jumpTo);
+
+ try {
+
+ IDBVirtualList<ICertRecord> vlist = s.createVirtualList(getDN(), filter,
+ attrs, jumpTo, sortKey, pageSize);
+
+ list = new CertRecordList(vlist);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return list;
+ }
+
+ /**
+ * Marks certificate as renewable.
+ */
+ public void markCertificateAsRenewable(ICertRecord record)
+ throws EBaseException {
+ changeRenewalAttribute(((CertRecord) record).getSerialNumber().toString(),
+ CertRecord.AUTO_RENEWAL_ENABLED);
+ }
+
+ /**
+ * Marks certificate as renewable.
+ */
+ public void markCertificateAsNotRenewable(ICertRecord record)
+ throws EBaseException {
+ changeRenewalAttribute(((CertRecord) record).getSerialNumber().toString(),
+ CertRecord.AUTO_RENEWAL_DISABLED);
+ }
+
+ public void markCertificateAsRenewed(String serialNo)
+ throws EBaseException {
+ changeRenewalAttribute(serialNo, CertRecord.AUTO_RENEWAL_DONE);
+ }
+
+ public void markCertificateAsRenewalNotified(String serialNo)
+ throws EBaseException {
+ changeRenewalAttribute(serialNo, CertRecord.AUTO_RENEWAL_NOTIFIED);
+ }
+
+ private void changeRenewalAttribute(String serialno, String value)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String name = "cn" + "=" + serialno +
+ "," + getDN();
+ ModificationSet mods = new ModificationSet();
+
+ mods.add(CertRecord.ATTR_AUTO_RENEW, Modification.MOD_REPLACE,
+ value);
+ s.modify(name, mods);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ public Hashtable<String, RenewableCertificateCollection> getRenewableCertificates(String renewalTime)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ Hashtable<String, RenewableCertificateCollection> tab = null;
+
+ try {
+ String filter = "(&(" + CertRecord.ATTR_CERT_STATUS + "=" +
+ CertRecord.STATUS_VALID + ")("
+ + CertRecord.ATTR_X509CERT +
+ "." + CertificateValidity.NOT_AFTER + "<=" + renewalTime +
+ ")(!(" + CertRecord.ATTR_AUTO_RENEW + "=" +
+ CertRecord.AUTO_RENEWAL_DONE +
+ "))(!(" + CertRecord.ATTR_AUTO_RENEW + "=" +
+ CertRecord.AUTO_RENEWAL_NOTIFIED + ")))";
+ //Enumeration e = s.search(getDN(), filter);
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(filter, null, "serialno", 10);
+ int size = list.getSize();
+ Enumeration<ICertRecord> e = list.getCertRecords(0, size - 1);
+
+ tab = new Hashtable<String, RenewableCertificateCollection>();
+ while (e.hasMoreElements()) {
+ CertRecord rec = (CertRecord) e.nextElement();
+ X509CertImpl cert = rec.getCertificate();
+ String subjectDN = cert.getSubjectDN().toString();
+ String renewalFlag = rec.getAutoRenew();
+
+ // See if the subjectDN is in the table
+ Object val = null;
+
+ if ((val = tab.get(subjectDN)) == null) {
+ RenewableCertificateCollection collection =
+ new RenewableCertificateCollection();
+
+ collection.addCertificate(renewalFlag, cert);
+ tab.put(subjectDN, collection);
+ } else {
+ ((RenewableCertificateCollection) val).addCertificate(renewalFlag, cert);
+ }
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return tab;
+ }
+
+ /**
+ * Gets all valid and unexpired certificates pertaining
+ * to a subject DN.
+ *
+ * @param subjectDN The distinguished name of the subject.
+ * @param validityType The type of certificates to get.
+ * @return An array of certificates.
+ */
+
+ public X509CertImpl[] getX509Certificates(String subjectDN,
+ int validityType) throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ X509CertImpl certs[] = null;
+
+ try {
+ // XXX - not checking validityType...
+ String filter = "(&(" + CertRecord.ATTR_X509CERT +
+ "." + X509CertInfo.SUBJECT + "=" + subjectDN;
+
+ if (validityType == ALL_VALID_CERTS) {
+ filter += ")(" +
+ CertRecord.ATTR_CERT_STATUS + "=" +
+ CertRecord.STATUS_VALID;
+ }
+ if (validityType == ALL_UNREVOKED_CERTS) {
+ filter += ")(|(" +
+ CertRecord.ATTR_CERT_STATUS + "=" +
+ CertRecord.STATUS_VALID + ")(" +
+ CertRecord.ATTR_CERT_STATUS + "=" +
+ CertRecord.STATUS_EXPIRED + ")";
+ }
+ filter += "))";
+
+ //Enumeration e = s.search(getDN(), filter);
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(filter, null, "serialno", 10);
+ int size = list.getSize();
+ Enumeration<ICertRecord> e = list.getCertRecords(0, size - 1);
+
+ Vector<X509CertImpl> v = new Vector<X509CertImpl>();
+
+ while (e.hasMoreElements()) {
+ CertRecord rec = (CertRecord) e.nextElement();
+
+ v.addElement(rec.getCertificate());
+ }
+ if (v.size() == 0)
+ return null;
+ certs = new X509CertImpl[v.size()];
+ v.copyInto(certs);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return certs;
+ }
+
+ public X509CertImpl[] getX509Certificates(String filter)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ X509CertImpl certs[] = null;
+
+ try {
+ Enumeration<ICertRecord> e = null;
+
+ if (filter != null && filter.length() > 0) {
+ //e = s.search(getDN(), filter);
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(filter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+ }
+
+ Vector<X509CertImpl> v = new Vector<X509CertImpl>();
+
+ while (e != null && e.hasMoreElements()) {
+ CertRecord rec = (CertRecord) e.nextElement();
+
+ v.addElement(rec.getCertificate());
+ }
+ if (v.size() > 0) {
+ certs = new X509CertImpl[v.size()];
+ v.copyInto(certs);
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return certs;
+ }
+
+ /**
+ * Retrives all valid certificates excluding ones already revoked.
+ *
+ * @param from The starting point of the serial number range.
+ * @param to The ending point of the serial number range.
+ */
+ public Enumeration<ICertRecord> getValidCertificates(String from, String to)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Vector<ICertRecord> v = new Vector<ICertRecord>();
+
+ try {
+
+ // 'from' determines 'jumpto' value
+ // 'to' determines where to stop looking
+
+ String ldapfilter = "(certstatus=VALID)";
+
+ String fromVal = "0";
+ try {
+ if (from != null) {
+ new BigInteger(from);
+ fromVal = from;
+ }
+ } catch (Exception e1) {
+ // from is not integer
+ }
+
+ ICertRecordList list =
+ findCertRecordsInList(ldapfilter, null, fromVal, "serialno", 40);
+
+ BigInteger toInt = null;
+ if (to != null && !to.trim().equals("")) {
+ toInt = new BigInteger(to);
+ }
+
+ for (int i = 0;; i++) {
+ CertRecord rec = (CertRecord) list.getCertRecord(i);
+ CMS.debug("processing record: " + i);
+ if (rec == null) {
+ break; // no element returned
+ } else {
+
+ CMS.debug("processing record: " + i + " " + rec.getSerialNumber());
+ // Check if we are past the 'to' marker
+ if (toInt != null) {
+ if (rec.getSerialNumber().compareTo(toInt) > 0) {
+ break;
+ }
+ }
+ v.addElement(rec);
+ }
+ }
+
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ CMS.debug("returning " + v.size() + " elements");
+ return v.elements();
+ }
+
+ /**
+ * Retrives all valid certificates excluding ones already revoked.
+ */
+ public Enumeration<ICertRecord> getAllValidCertificates()
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<ICertRecord> e = null;
+
+ try {
+ Date now = CMS.getCurrentDate();
+ String ldapfilter = "(&(!(" + CertRecord.ATTR_REVO_INFO + "=*))(" +
+ CertRecord.ATTR_X509CERT + "." +
+ CertificateValidity.NOT_BEFORE + "<=" +
+ DateMapper.dateToDB(now) + ")(" +
+ CertRecord.ATTR_X509CERT + "." +
+ CertificateValidity.NOT_AFTER + ">=" +
+ DateMapper.dateToDB(now) + "))";
+ //e = s.search(getDN(), ldapfilter);
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(ldapfilter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+
+ } finally {
+ // XXX - transaction is not done at this moment
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ /**
+ * Retrives all valid not published certificates
+ * excluding ones already revoked.
+ *
+ * @param from The starting point of the serial number range.
+ * @param to The ending point of the serial number range.
+ */
+ public Enumeration<ICertRecord> getValidNotPublishedCertificates(String from, String to)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<ICertRecord> e = null;
+
+ try {
+ Date now = CMS.getCurrentDate();
+ String ldapfilter = "(&(";
+
+ if (from != null && from.length() > 0)
+ ldapfilter += CertRecord.ATTR_ID + ">=" + from + ")(";
+ if (to != null && to.length() > 0)
+ ldapfilter += CertRecord.ATTR_ID + "<=" + to + ")(";
+ ldapfilter += "!(" + CertRecord.ATTR_REVO_INFO + "=*))(" +
+ CertRecord.ATTR_X509CERT + "." +
+ CertificateValidity.NOT_BEFORE + "<=" +
+ DateMapper.dateToDB(now) + ")(" +
+ CertRecord.ATTR_X509CERT + "." +
+ CertificateValidity.NOT_AFTER + ">=" +
+ DateMapper.dateToDB(now) + ")(!(" +
+ "certMetainfo=" +
+ CertRecord.META_LDAPPUBLISH +
+ ":true)))";
+ //e = s.search(getDN(), ldapfilter);
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(ldapfilter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ /**
+ * Retrives all valid not published certificates
+ * excluding ones already revoked.
+ */
+ public Enumeration<ICertRecord> getAllValidNotPublishedCertificates()
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<ICertRecord> e = null;
+
+ try {
+ Date now = CMS.getCurrentDate();
+ String ldapfilter = "(&(!(" + CertRecord.ATTR_REVO_INFO + "=*))(" +
+ CertRecord.ATTR_X509CERT + "." +
+ CertificateValidity.NOT_BEFORE + "<=" +
+ DateMapper.dateToDB(now) + ")(" +
+ CertRecord.ATTR_X509CERT + "." +
+ CertificateValidity.NOT_AFTER + ">=" +
+ DateMapper.dateToDB(now) + ")(!(" +
+ "certMetainfo=" +
+ CertRecord.META_LDAPPUBLISH +
+ ":true)))";
+ //e = s.search(getDN(), ldapfilter);
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(ldapfilter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+
+ } finally {
+ // XXX - transaction is not done at this moment
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ /**
+ * Retrives all expired certificates.
+ *
+ * @param from The starting point of the serial number range.
+ * @param to The ending point of the serial number range.
+ */
+ public Enumeration<ICertRecord> getExpiredCertificates(String from, String to)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<ICertRecord> e = null;
+
+ try {
+ Date now = CMS.getCurrentDate();
+ String ldapfilter = "(&(";
+
+ if (from != null && from.length() > 0)
+ ldapfilter += CertRecord.ATTR_ID + ">=" + from + ")(";
+ if (to != null && to.length() > 0)
+ ldapfilter += CertRecord.ATTR_ID + "<=" + to + ")(";
+ ldapfilter += "!(" + CertRecord.ATTR_X509CERT + "." +
+ CertificateValidity.NOT_AFTER + ">=" +
+ DateMapper.dateToDB(now) + ")))";
+ //e = s.search(getDN(), ldapfilter);
+
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(ldapfilter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+ } finally {
+ // XXX - transaction is not done at this moment
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ /**
+ * Retrives all expired certificates.
+ */
+ public Enumeration<ICertRecord> getAllExpiredCertificates()
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<ICertRecord> e = null;
+
+ try {
+ Date now = CMS.getCurrentDate();
+ String ldapfilter = "(!(" + CertRecord.ATTR_X509CERT + "." +
+ CertificateValidity.NOT_AFTER + ">=" +
+ DateMapper.dateToDB(now) + "))";
+ //e = s.search(getDN(), ldapfilter);
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(ldapfilter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+
+ } finally {
+ // XXX - transaction is not done at this moment
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ /**
+ * Retrives all expired published certificates.
+ *
+ * @param from The starting point of the serial number range.
+ * @param to The ending point of the serial number range.
+ */
+ public Enumeration<ICertRecord> getExpiredPublishedCertificates(String from, String to)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<ICertRecord> e = null;
+
+ try {
+ Date now = CMS.getCurrentDate();
+ String ldapfilter = "(&(";
+
+ if (from != null && from.length() > 0)
+ ldapfilter += CertRecord.ATTR_ID + ">=" + from + ")(";
+ if (to != null && to.length() > 0)
+ ldapfilter += CertRecord.ATTR_ID + "<=" + to + ")(";
+ ldapfilter += "!(" + CertRecord.ATTR_X509CERT + "." +
+ CertificateValidity.NOT_AFTER + ">=" +
+ //DateMapper.dateToDB(now) + ")))";
+ DateMapper.dateToDB(now) + "))(" +
+ "certMetainfo=" +
+ CertRecord.META_LDAPPUBLISH +
+ ":true))";
+ //e = s.search(getDN(), ldapfilter);
+
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(ldapfilter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+ } finally {
+ // XXX - transaction is not done at this moment
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ /**
+ * Retrives all expired publishedcertificates.
+ */
+ public Enumeration<ICertRecord> getAllExpiredPublishedCertificates()
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<ICertRecord> e = null;
+
+ try {
+ Date now = CMS.getCurrentDate();
+ String ldapfilter = "(&";
+
+ ldapfilter += "(!(" + CertRecord.ATTR_X509CERT + "." +
+ CertificateValidity.NOT_AFTER + ">=" +
+ DateMapper.dateToDB(now) + "))";
+ ldapfilter += "(certMetainfo=" +
+ CertRecord.META_LDAPPUBLISH +
+ ":true))";
+
+ //e = s.search(getDN(), ldapfilter);
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(ldapfilter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+
+ } finally {
+ // XXX - transaction is not done at this moment
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ public ICertRecordList getInvalidCertsByNotBeforeDate(Date date, int pageSize)
+ throws EBaseException {
+
+ ICertRecordList list = null;
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String ldapfilter = "(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_INVALID + ")";
+
+ String[] attrs = null;
+
+ if (mConsistencyCheck == false) {
+ attrs = new String[] { "objectclass", CertRecord.ATTR_ID, CertRecord.ATTR_X509CERT };
+ }
+
+ CMS.debug("getInvalidCertificatesByNotBeforeDate filter " + ldapfilter);
+ //e = s.search(getDN(), ldapfilter);
+ CMS.debug("getInvalidCertificatesByNotBeforeDate: about to call findCertRecordsInList");
+
+ list = findCertRecordsInListRawJumpto(ldapfilter, attrs,
+ DateMapper.dateToDB(date), "notBefore", pageSize);
+
+ //e = list.getCertRecords(0, size - 1);
+
+ } finally {
+ // XXX - transaction is not done at this moment
+
+ CMS.debug("In getInvalidCertsByNotBeforeDate finally.");
+
+ if (s != null)
+ s.close();
+ }
+ return list;
+
+ }
+
+ public ICertRecordList getValidCertsByNotAfterDate(Date date, int pageSize)
+ throws EBaseException {
+
+ ICertRecordList list = null;
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String ldapfilter = "(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_VALID + ")";
+
+ String[] attrs = null;
+
+ if (mConsistencyCheck == false) {
+ attrs = new String[] { "objectclass", CertRecord.ATTR_ID, CertRecord.ATTR_X509CERT };
+ }
+
+ CMS.debug("getValidCertsByNotAfterDate filter " + ldapfilter);
+ //e = s.search(getDN(), ldapfilter);
+ list = findCertRecordsInListRawJumpto(ldapfilter, attrs, DateMapper.dateToDB(date), "notAfter", pageSize);
+
+ } finally {
+ // XXX - transaction is not done at this moment
+
+ if (s != null)
+ s.close();
+ }
+ return list;
+ }
+
+ public ICertRecordList getRevokedCertsByNotAfterDate(Date date, int pageSize)
+ throws EBaseException {
+
+ ICertRecordList list = null;
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String ldapfilter = "(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED + ")";
+
+ String[] attrs = null;
+
+ if (mConsistencyCheck == false) {
+ attrs = new String[] { "objectclass", CertRecord.ATTR_REVOKED_ON, CertRecord.ATTR_ID,
+ CertRecord.ATTR_REVO_INFO, CertificateValidity.NOT_AFTER, CertRecord.ATTR_X509CERT };
+ }
+
+ CMS.debug("getRevokedCertificatesByNotAfterDate filter " + ldapfilter);
+ //e = s.search(getDN(), ldapfilter);
+ CMS.debug("getRevokedCertificatesByNotAfterDate: about to call findCertRecordsInList");
+
+ list = findCertRecordsInListRawJumpto(ldapfilter, attrs,
+ DateMapper.dateToDB(date), "notafter", pageSize);
+
+ } finally {
+ // XXX - transaction is not done at this moment
+
+ if (s != null)
+ s.close();
+ }
+ return list;
+
+ }
+
+ /**
+ * Retrieves all revoked certificates in the serial number range.
+ *
+ * @param from The starting point of the serial number range.
+ * @param to The ending point of the serial number range.
+ */
+ public Enumeration<ICertRecord> getRevokedCertificates(String from, String to)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<ICertRecord> e = null;
+
+ try {
+ String ldapfilter = "(&(" + CertRecord.ATTR_REVO_INFO + "=*)";
+
+ if (from != null && from.length() > 0)
+ ldapfilter += "(" + CertRecord.ATTR_ID + ">=" + from + ")";
+ if (to != null && to.length() > 0)
+ ldapfilter += "(" + CertRecord.ATTR_ID + "<=" + to + ")";
+ ldapfilter += ")";
+ //e = s.search(getDN(), ldapfilter);
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(ldapfilter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+ } finally {
+ // XXX - transaction is not done at this moment
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ /**
+ * Retrives all revoked certificates including ones already expired or
+ * not yet valid.
+ */
+ public Enumeration<ICertRecord> getAllRevokedCertificates()
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<ICertRecord> e = null;
+ // index is setup for this filter
+ String ldapfilter = "(|(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED + ")("
+ + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED_EXPIRED + "))";
+
+ try {
+ //e = s.search(getDN(), ldapfilter);
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(ldapfilter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ /**
+ * Retrieves all revoked publishedcertificates in the serial number range.
+ *
+ * @param from The starting point of the serial number range.
+ * @param to The ending point of the serial number range.
+ */
+ public Enumeration<ICertRecord> getRevokedPublishedCertificates(String from, String to)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<ICertRecord> e = null;
+
+ try {
+ String ldapfilter = "(&(" + CertRecord.ATTR_REVO_INFO + "=*)";
+
+ if (from != null && from.length() > 0)
+ ldapfilter += "(" + CertRecord.ATTR_ID + ">=" + from + ")";
+ if (to != null && to.length() > 0)
+ ldapfilter += "(" + CertRecord.ATTR_ID + "<=" + to + ")";
+ //ldapfilter += ")";
+ ldapfilter += "(certMetainfo=" +
+ CertRecord.META_LDAPPUBLISH +
+ ":true))";
+ //e = s.search(getDN(), ldapfilter);
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(ldapfilter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+ } finally {
+ // XXX - transaction is not done at this moment
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ /**
+ * Retrives all revoked published certificates including ones
+ * already expired or not yet valid.
+ */
+ public Enumeration<ICertRecord> getAllRevokedPublishedCertificates()
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<ICertRecord> e = null;
+ // index is setup for this filter
+ String ldapfilter = "(&(|(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED + ")("
+ + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED_EXPIRED + "))";
+
+ ldapfilter += "(certMetainfo=" +
+ CertRecord.META_LDAPPUBLISH +
+ ":true))";
+ try {
+ //e = s.search(getDN(), ldapfilter);
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(ldapfilter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ /**
+ * Retrieves all revoked certificates that have not expired.
+ */
+ public Enumeration<ICertRecord> getRevokedCertificates(Date asOfDate)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<ICertRecord> e = null;
+
+ try {
+
+ /*e = s.search(getDN(), "(&(" +
+ CertRecord.ATTR_REVO_INFO + "=*)(" + CertRecord.ATTR_X509CERT +
+ "." + CertificateValidity.NOT_AFTER + " >= " +
+ DateMapper.dateToDB(asOfDate) + "))");*/
+ String ldapfilter = "(&(" +
+ CertRecord.ATTR_REVO_INFO + "=*)(" + CertRecord.ATTR_X509CERT +
+ "." + CertificateValidity.NOT_AFTER + " >= " +
+ DateMapper.dateToDB(asOfDate) + "))";
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(ldapfilter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+ } finally {
+ // XXX - transaction is not done at this moment
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ /**
+ * Retrives all revoked certificates excluing ones already expired.
+ */
+ public Enumeration<ICertRecord> getAllRevokedNonExpiredCertificates()
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration<ICertRecord> e = null;
+ String ldapfilter = "(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED + ")"; // index is setup for this filter
+
+ try {
+ //e = s.search(getDN(), ldapfilter);
+ ICertRecordList list = null;
+
+ list = findCertRecordsInList(ldapfilter, null, "serialno", 10);
+ int size = list.getSize();
+
+ e = list.getCertRecords(0, size - 1);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ LDAPSearchResults searchForModifiedCertificateRecords(IDBSSession session) throws EBaseException {
+ CMS.debug("Starting persistent search.");
+ String filter = "(" + CertRecord.ATTR_CERT_STATUS + "=*)";
+ return session.persistentSearch(getDN(), filter, null);
+ }
+
+ public void getModifications(LDAPEntry entry) {
+ if (entry != null) {
+ CMS.debug("getModifications entry DN=" + entry.getDN());
+
+ LDAPAttributeSet entryAttrs = entry.getAttributeSet();
+ ICertRecord certRec = null;
+ try {
+ certRec = (ICertRecord) mDBService.getRegistry().createObject(entryAttrs);
+ } catch (Exception e) {
+ }
+ if (certRec != null) {
+ String status = certRec.getStatus();
+ CMS.debug("getModifications serialNumber=" + certRec.getSerialNumber() +
+ " status=" + status);
+ if (status != null && (status.equals(ICertRecord.STATUS_VALID) ||
+ status.equals(ICertRecord.STATUS_REVOKED))) {
+
+ Enumeration<ICRLIssuingPoint> eIPs = mCRLIssuingPoints.elements();
+
+ while (eIPs.hasMoreElements()) {
+ ICRLIssuingPoint ip = eIPs.nextElement();
+
+ if (ip != null) {
+ if (status.equals(ICertRecord.STATUS_REVOKED)) {
+ IRevocationInfo rInfo = certRec.getRevocationInfo();
+ if (rInfo != null) {
+ ip.addRevokedCert(certRec.getSerialNumber(),
+ new RevokedCertImpl(certRec.getSerialNumber(),
+ rInfo.getRevocationDate(),
+ rInfo.getCRLEntryExtensions()));
+ }
+ } else {
+ ip.addUnrevokedCert(certRec.getSerialNumber());
+ }
+ }
+ }
+
+ }
+ }
+ } else {
+ CMS.debug("getModifications entry == null");
+ }
+ }
+
+ /**
+ * Checks if the presented certificate belongs to the repository
+ * and is revoked.
+ *
+ * @param cert certificate to verify.
+ * @return RevocationInfo if the presented certificate is revoked otherwise null.
+ */
+ public RevocationInfo isCertificateRevoked(X509CertImpl cert)
+ throws EBaseException {
+ RevocationInfo info = null;
+
+ // 615932
+ if (cert == null)
+ return null;
+
+ ICertRecord rec = readCertificateRecord(cert.getSerialNumber());
+
+ if (rec != null) {
+ if (rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) {
+ X500Name name = (X500Name) cert.getSubjectDN();
+ X500Name repCertName = (X500Name) rec.getCertificate().getSubjectDN();
+
+ if (name.equals(repCertName)) {
+ byte[] certEncoded = null;
+ byte[] repCertEncoded = null;
+
+ try {
+ certEncoded = cert.getEncoded();
+ repCertEncoded = rec.getCertificate().getEncoded();
+ } catch (Exception e) {
+ }
+
+ if (certEncoded != null &&
+ repCertEncoded != null &&
+ certEncoded.length == repCertEncoded.length) {
+ int i;
+
+ for (i = 0; i < certEncoded.length; i++) {
+ if (certEncoded[i] != repCertEncoded[i])
+ break;
+ }
+ if (i >= certEncoded.length) {
+ info = (RevocationInfo) ((CertRecord) rec).getRevocationInfo();
+ }
+ }
+ }
+ }
+ }
+
+ return info;
+ }
+
+ public void shutdown() {
+ if (certStatusUpdateTask != null) {
+ certStatusUpdateTask.stop();
+ }
+
+ if (retrieveModificationsTask != null) {
+ retrieveModificationsTask.stop();
+ }
+ }
+}
+
+class CertStatusUpdateTask implements Runnable {
+
+ CertificateRepository repository;
+ IRepository requestRepository;
+
+ int interval;
+
+ ScheduledExecutorService executorService;
+
+ public CertStatusUpdateTask(CertificateRepository repository, IRepository requestRepository, int interval) {
+ this.repository = repository;
+ this.requestRepository = requestRepository;
+ this.interval = interval;
+ }
+
+ public void start() {
+ // schedule task to run immediately and repeat after specified interval
+ executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
+ public Thread newThread(Runnable r) {
+ return new Thread(r, "CertStatusUpdateTask");
+ }
+ });
+ executorService.scheduleWithFixedDelay(this, 0, interval, TimeUnit.SECONDS);
+ }
+
+ public void run() {
+ try {
+ CMS.debug("About to start updateCertStatus");
+ updateCertStatus();
+
+ } catch (EBaseException e) {
+ CMS.debug("updateCertStatus done: " + e.toString());
+ }
+ }
+
+ public synchronized void updateCertStatus() throws EBaseException {
+ CMS.debug("Starting updateCertStatus (entered lock)");
+ repository.updateCertStatus();
+ CMS.debug("updateCertStatus done");
+
+ CMS.debug("Starting cert checkRanges");
+ repository.checkRanges();
+ CMS.debug("cert checkRanges done");
+
+ CMS.debug("Starting request checkRanges");
+ requestRepository.checkRanges();
+ CMS.debug("request checkRanges done");
+ }
+
+ public void stop() {
+ // shutdown executorService without interrupting running task
+ if (executorService != null) executorService.shutdown();
+ }
+}
+
+class RetrieveModificationsTask implements Runnable {
+
+ CertificateRepository repository;
+
+ IDBSSession session;
+ LDAPSearchResults results;
+
+ ScheduledExecutorService executorService;
+
+ public RetrieveModificationsTask(CertificateRepository repository) {
+ this.repository = repository;
+
+ executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
+ public Thread newThread(Runnable r) {
+ return new Thread(r, "RetrieveModificationsTask");
+ }
+ });
+ }
+
+ public void start() {
+
+ // schedule task to run immediately
+ executorService.schedule(this, 0, TimeUnit.MINUTES);
+ }
+
+ public void connect() throws EBaseException {
+
+ if (session != null) return;
+
+ try {
+ session = repository.getDBSubsystem().createSession();
+ results = repository.searchForModifiedCertificateRecords(session);
+
+ } catch (EBaseException e) {
+ close(); // avoid leaks
+ throw e;
+ }
+ }
+
+ public void close() {
+
+ if (session == null) return;
+
+ // make sure the search is abandoned
+ if (results != null) try { session.abandon(results); } catch (Exception e) { e.printStackTrace(); }
+
+ // close session
+ try { session.close(); } catch (Exception e) { e.printStackTrace(); }
+
+ session = null;
+ }
+
+ public void run() {
+ try {
+ // make sure it's connected
+ connect();
+
+ // results.hasMoreElements() will block until next result becomes available
+ // or return false if the search is abandoned or the connection is closed
+
+ CMS.debug("Waiting for next result.");
+ if (results.hasMoreElements()) {
+ LDAPEntry entry = results.next();
+
+ CMS.debug("Processing "+entry.getDN()+".");
+ repository.getModifications(entry);
+ CMS.debug("Done processing "+entry.getDN()+".");
+
+ // wait for next result immediately
+ executorService.schedule(this, 0, TimeUnit.MINUTES);
+
+ } else {
+ if (executorService.isShutdown()) {
+ CMS.debug("Task has been shutdown.");
+
+ } else {
+ CMS.debug("Persistence search ended.");
+ close();
+
+ CMS.debug("Retrying in 1 minute.");
+ executorService.schedule(this, 1, TimeUnit.MINUTES);
+ }
+ }
+
+ } catch (Exception e) {
+ CMS.debug(e);
+ close();
+
+ CMS.debug("Retrying in 1 minute.");
+ executorService.schedule(this, 1, TimeUnit.MINUTES);
+ }
+ }
+
+ public void stop() {
+ executorService.shutdown();
+ close();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/DBAttribute.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBAttribute.java
new file mode 100644
index 000000000..d89c56e7c
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBAttribute.java
@@ -0,0 +1,30 @@
+// --- 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 com.netscape.cmscore.dbs;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * @author Endi S. Dewata
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DBAttribute {
+ public String value();
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/DBObjectClasses.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBObjectClasses.java
new file mode 100644
index 000000000..8920a4f97
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBObjectClasses.java
@@ -0,0 +1,30 @@
+// --- 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 com.netscape.cmscore.dbs;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * @author Endi S. Dewata
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DBObjectClasses {
+ public String[] value();
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/DBRecord.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBRecord.java
new file mode 100644
index 000000000..8d62b00d2
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBRecord.java
@@ -0,0 +1,98 @@
+package com.netscape.cmscore.dbs;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBObj;
+
+public class DBRecord implements IDBObj {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void set(String name, Object value) throws EBaseException {
+ try {
+ // find setter
+ String setter = "set" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
+ for (Method method : getClass().getMethods()) {
+ if (!method.getName().equals(setter)) continue;
+
+ // invoke setter
+ method.invoke(this, value);
+ return;
+ }
+
+ // if setter not available, set field directly
+ Field field = getClass().getField(name);
+ field.set(this, value);
+
+ } catch (InvocationTargetException|NoSuchFieldException|IllegalAccessException e) {
+ throw new EBaseException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public Object get(String name) throws EBaseException {
+ try {
+ // find getter
+ String getter = "get" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
+ for (Method method : getClass().getMethods()) {
+ if (!method.getName().equals(getter)) continue;
+
+ // invoke getter
+ return method.invoke(this);
+ }
+
+ // if getter not available, get field directly
+ Field field = getClass().getField(name);
+ return field.get(this);
+
+ } catch (InvocationTargetException|NoSuchFieldException|IllegalAccessException e) {
+ throw new EBaseException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public void delete(String name) throws EBaseException {
+ set(name, null);
+ }
+
+ @Override
+ public Enumeration<String> getElements() {
+ return getSerializableAttrNames();
+ }
+
+ @Override
+ public Enumeration<String> getSerializableAttrNames() {
+ Vector<String> list = new Vector<String>();
+
+ // get attributes defined in setters/getters
+ for (Method method : getClass().getMethods()) {
+ DBAttribute dbAttribute = method.getAnnotation(DBAttribute.class);
+ if (dbAttribute == null) continue;
+
+ String name = method.getName();
+ if (!name.matches("^set.+") && !name.matches("^get.+")) continue;
+
+ // get attribute name from method name
+ name = Character.toLowerCase(name.charAt(3)) + name.substring(4);
+ list.add(name);
+ }
+
+ // get attributes defined in fields
+ for (Field field : getClass().getFields()) {
+ DBAttribute dbAttribute = field.getAnnotation(DBAttribute.class);
+ if (dbAttribute == null) continue;
+
+ String name = field.getName();
+ list.add(name);
+ }
+
+ return list.elements();
+ }
+
+} \ No newline at end of file
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/DBRegistry.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBRegistry.java
new file mode 100644
index 000000000..653850e02
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBRegistry.java
@@ -0,0 +1,553 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBDynAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.dbs.IDBRegistry;
+import com.netscape.certsrv.dbs.IFilterConverter;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A class represents a registry where all the
+ * schema (object classes and attribute) information
+ * is stored.
+ *
+ * Attribute mappers can be registered with this
+ * registry.
+ *
+ * Given the schema information stored, this registry
+ * has knowledge to convert a Java object into a
+ * LDAPAttributeSet or vice versa.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class DBRegistry implements IDBRegistry, ISubsystem {
+
+ private IConfigStore mConfig = null;
+ private Hashtable<String, String[]> mOCclassNames = new Hashtable<String, String[]>();
+ private Hashtable<String, NameAndObject> mOCldapNames = new Hashtable<String, NameAndObject>();
+ private Hashtable<String, IDBAttrMapper> mAttrufNames = new Hashtable<String, IDBAttrMapper>();
+ private IFilterConverter mConverter = null;
+ private Vector<IDBDynAttrMapper> mDynAttrMappers = new Vector<IDBDynAttrMapper>();
+
+ private ILogger mLogger = CMS.getLogger();
+
+ /**
+ * Constructs registry.
+ */
+ public DBRegistry() {
+ }
+
+ /**
+ * Retrieves subsystem identifier.
+ */
+ public String getId() {
+ return "dbsregistry";
+ }
+
+ /**
+ * Sets subsystem identifier. This is an internal
+ * subsystem, and is not loadable.
+ */
+ public void setId(String id) throws EBaseException {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION"));
+ }
+
+ /**
+ * Initializes the internal registery. Connects to the
+ * data source, and create a pool of connection of which
+ * applications can use. Optionally, check the integrity
+ * of the database.
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+ mConverter = new LdapFilterConverter(mAttrufNames);
+ }
+
+ /**
+ * Retrieves configuration store.
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Starts up this subsystem.
+ */
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Shutdowns this subsystem gracefully.
+ */
+ public void shutdown() {
+ mOCclassNames.clear();
+ mOCldapNames.clear();
+ mAttrufNames.clear();
+ }
+
+ /**
+ * Registers object class.
+ */
+ public void registerObjectClass(String className, String ldapNames[])
+ throws EDBException {
+ try {
+ Class<?> c = Class.forName(className);
+
+ mOCclassNames.put(className, ldapNames);
+ mOCldapNames.put(sortAndConcate(
+ ldapNames).toLowerCase(),
+ new NameAndObject(className, c));
+ } catch (ClassNotFoundException e) {
+
+ /*LogDoc
+ *
+ * @phase db startup
+ * @reason failed to register object class
+ * @message DBRegistry: <exception thrown>
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB,
+ ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_INVALID_CLASS_NAME", className));
+ }
+ }
+
+ /**
+ * See if an object class is registered.
+ */
+ public boolean isObjectClassRegistered(String className) {
+ return mOCclassNames.containsKey(className);
+ }
+
+ /**
+ * Registers attribute mapper.
+ */
+ public void registerAttribute(String ufName, IDBAttrMapper mapper)
+ throws EDBException {
+ // should not allows 'objectclass' as attribute; it has
+ // special meaning
+ mAttrufNames.put(ufName.toLowerCase(), mapper);
+ }
+
+ /**
+ * See if an attribute is registered.
+ */
+ public boolean isAttributeRegistered(String ufName) {
+ return mAttrufNames.containsKey(ufName.toLowerCase());
+ }
+
+ public void registerDynamicMapper(IDBDynAttrMapper mapper) {
+ mDynAttrMappers.add(mapper);
+ }
+
+ /**
+ * Creates LDAP-based search filters with help of
+ * registered mappers.
+ * Parses filter from filter string specified in RFC1558.
+ *
+ * <pre>
+ * <filter> ::= '(' <filtercomp> ')'
+ * <filtercomp> ::= <and> | <or> | <not> | <item>
+ * <and> ::= '&' <filterlist>
+ * <or> ::= '|' <filterlist>
+ * <not> ::= '!' <filter>
+ * <filterlist> ::= <filter> | <filter> <filterlist>
+ * <item> ::= <simple> | <present> | <substring>
+ * <simple> ::= <attr> <filtertype> <value>
+ * <filtertype> ::= <equal> | <approx> | <greater> | <less>
+ * <equal> ::= '='
+ * <approx> ::= '~='
+ * <greater> ::= '>='
+ * <less> ::= '<='
+ * <present> ::= <attr> '=*'
+ * <substring> ::= <attr> '=' <initial> <any> <final>
+ * <initial> ::= NULL | <value>
+ * <any> ::= '*' <starval>
+ * <starval> ::= NULL | <value> '*' <starval>
+ * <final> ::= NULL | <value>
+ * </pre>
+ */
+ public String getFilter(String filter) throws EBaseException {
+ return getFilter(filter, mConverter);
+ }
+
+ public String getFilter(String filter, IFilterConverter c)
+ throws EBaseException {
+ String f = filter;
+
+ f = f.trim();
+ if (f.startsWith("(") && f.endsWith(")")) {
+ return "(" + getFilterComp(f.substring(1,
+ f.length() - 1), c) + ")";
+ } else {
+ return getFilterComp(filter, c);
+ }
+ }
+
+ private String getFilterComp(String f, IFilterConverter c)
+ throws EBaseException {
+ f = f.trim();
+ if (f.startsWith("&")) { // AND operation
+ return "&" + getFilterList(f.substring(1,
+ f.length()), c);
+ } else if (f.startsWith("|")) { // OR operation
+ return "|" + getFilterList(f.substring(1,
+ f.length()), c);
+ } else if (f.startsWith("!")) { // NOT operation
+ return "!" + getFilter(f.substring(1, f.length()), c);
+ } else { // item
+ return getFilterItem(f, c);
+ }
+ }
+
+ private String getFilterList(String f, IFilterConverter c)
+ throws EBaseException {
+ f = f.trim();
+ int level = 0;
+ int start = 0;
+ int end = 0;
+ Vector<String> v = new Vector<String>();
+
+ for (int i = 0; i < f.length(); i++) {
+ if (f.charAt(i) == '(') {
+ if (level == 0) {
+ start = i;
+ }
+ level++;
+ }
+ if (f.charAt(i) == ')') {
+ level--;
+ if (level == 0) {
+ end = i;
+ String filter = getFilter(f.substring(start, end + 1), c);
+
+ v.addElement(filter);
+ }
+ }
+ }
+ return inStringFormat(v);
+ }
+
+ /**
+ * Convert a Vector<String> to Concatenated String
+ * @param v
+ * @return
+ */
+ private String inStringFormat(Vector<String> v){
+ StringBuffer result = new StringBuffer();
+
+ for (int i = 0; i < v.size(); i++) {
+ result.append(v.elementAt(i));
+ }
+ return result.toString();
+ }
+
+ /**
+ * So, here we need to separate item into name, op, value.
+ */
+ private String getFilterItem(String f, IFilterConverter c)
+ throws EBaseException {
+ f = f.trim();
+ int idx = f.indexOf('=');
+
+ if (idx == -1) {
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_INVALID_FILTER_ITEM", "="));
+ }
+
+ String type = f.substring(0, idx).trim();
+ String value = f.substring(idx + 1).trim(); // skip '='
+
+ // make decision by looking at the type
+ type = type.trim();
+ if (type.endsWith("~")) {
+ // approximate match
+ String name = type.substring(0, type.length() - 1).trim();
+
+ return c.convert(name, "~=", value);
+ } else if (type.endsWith("!")) {
+ String name = type.substring(0, type.length() - 1).trim();
+
+ return c.convert(name, "!=", value);
+ } else if (type.endsWith(">")) {
+ // greater than
+ String name = type.substring(0, type.length() - 1).trim();
+
+ return c.convert(name, ">=", value);
+ } else if (type.endsWith("<")) {
+ String name = type.substring(0, type.length() - 1).trim();
+
+ return c.convert(name, "<=", value);
+ }
+
+ // for those that are not simple
+ if (value.startsWith("*") && value.length() == 1) {
+ return c.convert(type, "=", "*");
+ }
+
+ // if value contains no '*', then it is equality
+ if (value.indexOf('*') == -1) {
+ if (type.equals("objectclass")) {
+ String ldapNames[] = mOCclassNames.get(value);
+
+ if (ldapNames == null)
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_INVALID_FILTER_ITEM", f));
+ StringBuffer filter = new StringBuffer();
+
+ for (int g = 0; g < ldapNames.length; g++) {
+ filter.append("(objectclass=" +
+ ldapNames[g] + ")");
+ }
+ return "&" + filter.toString();
+ } else {
+ return c.convert(type, "=", value);
+ }
+ }
+ // XXX - does not support substring!!
+ return c.convert(type, "=", value);
+ }
+
+ /**
+ * Maps object into LDAP attribute set.
+ */
+ public void mapObject(IDBObj parent, String name, Object obj,
+ LDAPAttributeSet attrs) throws EBaseException {
+ IDBAttrMapper mapper = mAttrufNames.get(name.toLowerCase());
+
+ if (mapper == null) {
+ return; // no mapper found, just skip this attribute
+ }
+ mapper.mapObjectToLDAPAttributeSet(parent, name, obj, attrs);
+ }
+
+ /**
+ * Retrieves a list of LDAP attributes that are associated
+ * with the given attributes.
+ * This method is used for searches, to map the database attributes
+ * to LDAP attributes.
+ */
+ public String[] getLDAPAttributes(String attrs[])
+ throws EBaseException {
+ IDBAttrMapper mapper;
+
+ if (attrs == null)
+ return null;
+ Vector<String> v = new Vector<String>();
+
+ for (int i = 0; i < attrs.length; i++) {
+
+ if (attrs[i].equals("objectclass")) {
+ v.addElement("objectclass");
+ continue;
+ }
+
+ if (isAttributeRegistered(attrs[i])) {
+ mapper = mAttrufNames.get(attrs[i].toLowerCase());
+ if (mapper == null) {
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_INVALID_ATTRS"));
+ }
+ Enumeration<String> e = mapper.getSupportedLDAPAttributeNames();
+
+ while (e.hasMoreElements()) {
+ String s = e.nextElement();
+
+ if (!v.contains(s)) {
+ v.addElement(s);
+ }
+ }
+ } else {
+ IDBDynAttrMapper matchingDynAttrMapper = null;
+ // check if a dynamic mapper can handle the attribute
+ for (Iterator<IDBDynAttrMapper> dynMapperIter = mDynAttrMappers.iterator(); dynMapperIter.hasNext();) {
+ IDBDynAttrMapper dynAttrMapper =
+ dynMapperIter.next();
+ if (dynAttrMapper.supportsLDAPAttributeName(attrs[i])) {
+ matchingDynAttrMapper = dynAttrMapper;
+ break;
+ }
+ }
+ if (matchingDynAttrMapper != null) {
+ v.addElement(attrs[i]);
+ } else {
+ /*LogDoc
+ *
+ * @phase retrieve ldap attr
+ * @reason failed to get registered object class
+ * @message DBRegistry: <attr> is not registered
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB,
+ ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_DBS_ATTR_NOT_REGISTER", attrs[i]));
+ throw new EDBException(CMS.getLogMessage("CMSCORE_DBS_ATTR_NOT_REGISTER", attrs[i]));
+ }
+ }
+
+ }
+ if (v.size() == 0)
+ return null;
+ String ldapAttrs[] = new String[v.size()];
+
+ v.copyInto(ldapAttrs);
+ return ldapAttrs;
+ }
+
+ /**
+ * Creates attribute set from object.
+ */
+ public LDAPAttributeSet createLDAPAttributeSet(IDBObj obj)
+ throws EBaseException {
+ Enumeration<String> e = obj.getSerializableAttrNames();
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+
+ // add object class to attribute set
+ String className = ((Object) obj).getClass().getName();
+ String vals[] = mOCclassNames.get(className);
+
+ attrs.add(new LDAPAttribute("objectclass", vals));
+
+ // give every attribute a chance to put stuff in attr set
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (obj.get(name) != null) {
+ mapObject(obj, name, obj.get(name), attrs);
+ }
+ }
+ return attrs;
+ }
+
+ /**
+ * Creates object from attribute set.
+ */
+ public IDBObj createObject(LDAPAttributeSet attrs)
+ throws EDBException {
+ // map object class attribute to object
+ LDAPAttribute attr = attrs.getAttribute("objectclass");
+ if (attr == null) {
+ throw new EDBException(CMS.getLogMessage("CMS_DBS_MISSING_OBJECT_CLASS"));
+ }
+
+ //CMS.debug("createObject: attrs " + attrs.toString());
+
+ attrs.remove("objectclass");
+
+ // sort the object class values
+
+ String[] s = attr.getStringValueArray();
+ String sorted = sortAndConcate(s).toLowerCase();
+ NameAndObject no = mOCldapNames.get(sorted);
+
+ if (no == null) {
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_INVALID_CLASS_NAME", sorted));
+ }
+ Class<?> c = (Class<?>) no.getObject();
+
+ try {
+ IDBObj obj = (IDBObj) c.newInstance();
+ Enumeration<String> ee = obj.getSerializableAttrNames();
+
+ while (ee.hasMoreElements()) {
+ String oname = ee.nextElement();
+ IDBAttrMapper mapper = mAttrufNames.get(oname.toLowerCase());
+
+ if (mapper == null) {
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_NO_MAPPER_FOUND", oname));
+ }
+ mapper.mapLDAPAttributeSetToObject(attrs,
+ oname, obj);
+ }
+ return obj;
+ } catch (Exception e) {
+
+ /*LogDoc
+ *
+ * @phase create ldap attr
+ * @reason failed to create object class
+ * @message DBRegistry: <attr> is not registered
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB,
+ ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_INVALID_ATTRS"));
+ }
+ }
+
+ /**
+ * Sorts and concate given strings.
+ */
+ private String sortAndConcate(String s[]) {
+ Vector<String> v = new Vector<String>();
+
+ // sort it first
+ for (int i = 0; i < s.length; i++) {
+ for (int j = 0; j < v.size(); j++) {
+ String t = v.elementAt(j);
+
+ if (s[i].compareTo(t) < 0) {
+ v.insertElementAt(s[i], j);
+ break;
+ }
+ }
+ if (i != (v.size() - 1))
+ v.addElement(s[i]);
+ }
+
+ return inStringFormat(v);
+ }
+}
+
+/**
+ * Just a convenient container class.
+ */
+class NameAndObject {
+
+ private String mN = null;
+ private Object mO = null;
+
+ public NameAndObject(String name, Object o) {
+ mN = name;
+ mO = o;
+ }
+
+ public String getName() {
+ return mN;
+ }
+
+ public Object getObject() {
+ return mO;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSSession.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSSession.java
new file mode 100644
index 000000000..fd59e8d8f
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSSession.java
@@ -0,0 +1,485 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Enumeration;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPModificationSet;
+import netscape.ldap.LDAPSearchConstraints;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+import netscape.ldap.controls.LDAPPersistSearchControl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.EDBNotAvailException;
+import com.netscape.certsrv.dbs.EDBRecordNotFoundException;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSearchResults;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.IDBVirtualList;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A class represents the database session. Operations
+ * can be performed with a session.
+ *
+ * Transaction and Caching support can be integrated
+ * into session.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class DBSSession implements IDBSSession {
+
+ private IDBSubsystem mDBSystem = null;
+ private LDAPConnection mConn = null;
+ private ILogger mLogger = CMS.getLogger();
+
+ /**
+ * Constructs a database session.
+ *
+ * @param system the database subsytem
+ * @param c the ldap connection
+ */
+ public DBSSession(IDBSubsystem system, LDAPConnection c) {
+ mDBSystem = system;
+ mConn = c;
+ try {
+ // no limit
+ mConn.setOption(LDAPv2.SIZELIMIT, Integer.valueOf(0));
+ } catch (LDAPException e) {
+ }
+ }
+
+ /**
+ * Returns database subsystem.
+ */
+ public ISubsystem getDBSubsystem() {
+ return mDBSystem;
+ }
+
+ /**
+ * Closes this session.
+ */
+ public void close() throws EDBException {
+ // return ldap connection.
+ mDBSystem.returnConn(mConn);
+ }
+
+ /**
+ * Adds object to backend database. For example,
+ *
+ * <PRE>
+ * session.add(&quot;cn=123459,o=certificate repository,o=airius.com&quot;,
+ * certRec);
+ * </PRE>
+ *
+ * @param name the name of the ldap entry
+ * @param obj the DBobj that can be mapped to ldap attrubute set
+ */
+ public void add(String name, IDBObj obj) throws EBaseException {
+ try {
+ LDAPAttributeSet attrs = mDBSystem.getRegistry(
+ ).createLDAPAttributeSet(obj);
+ LDAPEntry e = new LDAPEntry(name, attrs);
+
+ /*LogDoc
+ *
+ * @phase local ldap add
+ * @message DBSSession: begin LDAP add <entry>
+ */
+ mConn.add(e);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
+ throw new EDBNotAvailException(
+ CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
+ name + " " + e.toString()));
+ }
+ }
+
+ /**
+ * Reads an object from the database.
+ * all attributes will be returned
+ *
+ * @param name the name of the ldap entry
+ */
+ public IDBObj read(String name) throws EBaseException {
+ return read(name, null);
+ }
+
+ /**
+ * Reads an object from the database, and only populates
+ * the selected attributes.
+ *
+ * @param name the name of the ldap entry
+ * @param attrs the attributes to be selected
+ */
+ public IDBObj read(String name, String attrs[])
+ throws EBaseException {
+ try {
+ String ldapattrs[] = null;
+
+ if (attrs != null) {
+ ldapattrs = mDBSystem.getRegistry(
+ ).getLDAPAttributes(attrs);
+ }
+
+ /*LogDoc
+ *
+ * @phase local ldap read
+ * @message DBSSession: begin LDAP read <entry>
+ */
+ LDAPSearchResults res = mConn.search(name,
+ LDAPv2.SCOPE_BASE, "(objectclass=*)",
+ ldapattrs, false);
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+
+ return mDBSystem.getRegistry().createObject(
+ entry.getAttributeSet());
+ } catch (LDAPException e) {
+
+ /*LogDoc
+ *
+ * @phase local ldap read
+ * @message DBSSession: <exception thrown>
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_INFO, "DBSSession: " + e.toString());
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
+ throw new EDBNotAvailException(
+ CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
+ if (e.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT)
+ throw new EDBRecordNotFoundException(
+ CMS.getUserMessage("CMS_DBS_RECORD_NOT_FOUND"));
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
+ name + " " + e.toString()));
+ }
+ }
+
+ /**
+ * Deletes object from database.
+ */
+ public void delete(String name) throws EBaseException {
+ try {
+ mConn.delete(name);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
+ throw new EDBNotAvailException(
+ CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
+ name + " " + e.toString()));
+ }
+ }
+
+ /**
+ * Modify an object in the database.
+ */
+ public void modify(String name, ModificationSet mods)
+ throws EBaseException {
+ try {
+ LDAPModificationSet ldapMods = new
+ LDAPModificationSet();
+ Enumeration<?> e = mods.getModifications();
+
+ while (e.hasMoreElements()) {
+ Modification mod = (Modification)
+ e.nextElement();
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+
+ mDBSystem.getRegistry().mapObject(null,
+ mod.getName(), mod.getValue(), attrs);
+ Enumeration<?> e0 = attrs.getAttributes();
+
+ while (e0.hasMoreElements()) {
+ ldapMods.add(toLdapModOp(mod.getOp()),
+ (LDAPAttribute)
+ e0.nextElement());
+ }
+ }
+
+ /*LogDoc
+ *
+ * @phase local ldap add
+ * @message DBSSession: begin LDAP modify <entry>
+ */
+ mConn.modify(name, ldapMods);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
+ throw new EDBNotAvailException(
+ CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
+ name + " " + e.toString()));
+ }
+ }
+
+ private int toLdapModOp(int modOp) throws EBaseException {
+ switch (modOp) {
+ case Modification.MOD_ADD:
+ return LDAPModification.ADD;
+
+ case Modification.MOD_DELETE:
+ return LDAPModification.DELETE;
+
+ case Modification.MOD_REPLACE:
+ return LDAPModification.REPLACE;
+ }
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
+ Integer.toString(modOp)));
+ }
+
+ /**
+ * Searchs for a list of objects that match the
+ * filter.
+ */
+ public IDBSearchResults search(String base, String filter)
+ throws EBaseException {
+ return search(base, filter, null);
+ }
+
+ @SuppressWarnings("unchecked")
+ public IDBSearchResults search(String base, String filter, int maxSize)
+ throws EBaseException {
+ try {
+ String ldapattrs[] = null;
+ String ldapfilter =
+ mDBSystem.getRegistry().getFilter(filter);
+
+ LDAPSearchConstraints cons = new LDAPSearchConstraints();
+
+ cons.setMaxResults(maxSize);
+
+ LDAPSearchResults res = mConn.search(base,
+ LDAPv2.SCOPE_ONE, ldapfilter, ldapattrs, false, cons);
+
+ return new DBSearchResults(mDBSystem.getRegistry(),
+ res);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
+ throw new EDBNotAvailException(
+ CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
+ // XXX error handling, should not raise exception if
+ // entry not found
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
+ e.toString()));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public IDBSearchResults search(String base, String filter, int maxSize, int timeLimit)
+ throws EBaseException {
+ try {
+ String ldapattrs[] = null;
+ String ldapfilter =
+ mDBSystem.getRegistry().getFilter(filter);
+
+ LDAPSearchConstraints cons = new LDAPSearchConstraints();
+
+ cons.setMaxResults(maxSize);
+ cons.setServerTimeLimit(timeLimit);
+
+ LDAPSearchResults res = mConn.search(base,
+ LDAPv2.SCOPE_ONE, ldapfilter, ldapattrs, false, cons);
+
+ return new DBSearchResults(mDBSystem.getRegistry(),
+ res);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
+ throw new EDBNotAvailException(
+ CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
+ // XXX error handling, should not raise exception if
+ // entry not found
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
+ e.toString()));
+ }
+ }
+
+ /**
+ * Retrieves a list of object that satifies the given
+ * filter.
+ */
+ @SuppressWarnings("unchecked")
+ public IDBSearchResults search(String base, String filter,
+ String attrs[]) throws EBaseException {
+ try {
+ String ldapattrs[] = null;
+
+ if (attrs != null) {
+ ldapattrs = mDBSystem.getRegistry(
+ ).getLDAPAttributes(attrs);
+ }
+ String ldapfilter =
+ mDBSystem.getRegistry().getFilter(filter);
+
+ /*LogDoc
+ *
+ * @phase local ldap add
+ * @message DBSSession: begin LDAP search <filter>
+ */
+ LDAPSearchConstraints cons = new LDAPSearchConstraints();
+
+ cons.setMaxResults(0);
+
+ LDAPSearchResults res = mConn.search(base,
+ LDAPv2.SCOPE_ONE, ldapfilter, ldapattrs, false, cons);
+
+ return new DBSearchResults(mDBSystem.getRegistry(),
+ res);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
+ throw new EDBNotAvailException(
+ CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
+ // XXX error handling, should not raise exception if
+ // entry not found
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
+ e.toString()));
+ }
+ }
+
+ public LDAPSearchResults persistentSearch(String base, String filter, String attrs[])
+ throws EBaseException {
+ try {
+ String ldapattrs[] = null;
+ if (attrs != null) {
+ ldapattrs = mDBSystem.getRegistry(
+ ).getLDAPAttributes(attrs);
+ }
+ String ldapfilter =
+ mDBSystem.getRegistry().getFilter(filter);
+
+ Integer version = (Integer) (mConn.getOption(LDAPv2.PROTOCOL_VERSION));
+
+ // Only version 3 protocol supports persistent search.
+ if (version.intValue() == 2) {
+ mConn.setOption(LDAPv2.PROTOCOL_VERSION, Integer.valueOf(3));
+ }
+
+ int op = LDAPPersistSearchControl.MODIFY;
+
+ boolean changesOnly = true;
+ boolean returnControls = true;
+ boolean isCritical = true;
+ LDAPPersistSearchControl persistCtrl = new
+ LDAPPersistSearchControl(op, changesOnly,
+ returnControls, isCritical);
+
+ LDAPSearchConstraints cons = new LDAPSearchConstraints();
+ cons.setBatchSize(0);
+ cons.setServerControls(persistCtrl);
+
+ LDAPSearchResults res = mConn.search(base,
+ LDAPv2.SCOPE_ONE, ldapfilter, ldapattrs, false, cons);
+ return res;
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
+ throw new EDBNotAvailException(
+ CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
+ // XXX error handling, should not raise exception if
+ // entry not found
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
+ e.toString()));
+ }
+ }
+
+ public void abandon(LDAPSearchResults results) throws EBaseException {
+ try {
+ mConn.abandon(results);
+
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE)
+ throw new EDBNotAvailException(
+ CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
+ // XXX error handling, should not raise exception if
+ // entry not found
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE",
+ e.toString()));
+ }
+ }
+
+ /**
+ * Retrieves a list of objects.
+ */
+ public <T> IDBVirtualList<T> createVirtualList(String base, String filter,
+ String attrs[]) throws EBaseException {
+ return new DBVirtualList<T>(mDBSystem.getRegistry(), mConn, base,
+ filter, attrs);
+ }
+
+ /**
+ * Retrieves a list of objects.
+ */
+ public <T> IDBVirtualList<T> createVirtualList(String base, String filter,
+ String attrs[], String sortKey[]) throws EBaseException {
+ return new DBVirtualList<T>(mDBSystem.getRegistry(), mConn, base,
+ filter, attrs, sortKey);
+ }
+
+ /**
+ * Retrieves a list of objects.
+ */
+ public IDBVirtualList<?> createVirtualList(String base, String filter,
+ String attrs[], String sortKey) throws EBaseException {
+ return new DBVirtualList<Object>(mDBSystem.getRegistry(), mConn, base,
+ filter, attrs, sortKey);
+ }
+
+ /**
+ * Retrieves a list of objects.
+ */
+ public IDBVirtualList<?> createVirtualList(String base, String filter,
+ String attrs[], String sortKey[], int pageSize) throws EBaseException {
+ return new DBVirtualList<Object>(mDBSystem.getRegistry(), mConn, base,
+ filter, attrs, sortKey, pageSize);
+ }
+
+ /**
+ * Retrieves a list of objects.
+ */
+ public IDBVirtualList<Object> createVirtualList(String base, String filter,
+ String attrs[], String sortKey, int pageSize) throws EBaseException {
+ return new DBVirtualList<Object>(mDBSystem.getRegistry(), mConn, base,
+ filter, attrs, sortKey, pageSize);
+ }
+
+ public IDBVirtualList<Object> createVirtualList(String base, String filter,
+ String attrs[], String startFrom, String sortKey, int pageSize) throws EBaseException {
+ return new DBVirtualList<Object>(mDBSystem.getRegistry(), mConn, base,
+ filter, attrs, startFrom, sortKey, pageSize);
+
+ }
+
+ /**
+ * Releases object to this interface. This allows us to
+ * use memory more efficiently.
+ */
+ public void release(Object obj) {
+ // not implemented
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSUtil.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSUtil.java
new file mode 100644
index 000000000..1460db969
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSUtil.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+/**
+ * A class represents ann attribute mapper that maps
+ * a Java BigInteger object into LDAP attribute,
+ * and vice versa.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class DBSUtil {
+
+ public static String longToDB(long val) {
+ String s = Long.toString(val);
+ // prefix with 2 digits that represents
+ // the length of the value
+ int l = s.length();
+ String dbVal = "";
+
+ if (s.length() < 10) {
+ dbVal = "0";
+ }
+ return dbVal + Integer.toString(l) + s;
+ }
+
+ public static long longFromDB(String dbLong) {
+ // remove the first 2 digits
+ String s = dbLong.substring(2);
+
+ return Long.parseLong(s);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSearchResults.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSearchResults.java
new file mode 100644
index 000000000..a97998916
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSearchResults.java
@@ -0,0 +1,93 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Enumeration;
+
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.dbs.IDBRegistry;
+import com.netscape.certsrv.dbs.IDBSearchResults;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A class represents the search results. A search
+ * results object contain a enumeration of
+ * Java objects that are just read from the database.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class DBSearchResults implements IDBSearchResults {
+
+ private IDBRegistry mRegistry = null;
+ private Enumeration<Object> mRes = null;
+ private ILogger mLogger = CMS.getLogger();
+
+ /**
+ * Constructs search results.
+ */
+ public DBSearchResults(IDBRegistry registry, Enumeration<Object> res) {
+ mRegistry = registry;
+ mRes = res;
+ }
+
+ /**
+ * Checks if any element is available.
+ */
+ public boolean hasMoreElements() {
+ return mRes.hasMoreElements();
+ }
+
+ /**
+ * Retrieves next element.
+ */
+ public Object nextElement() {
+ LDAPEntry entry = null;
+
+ try {
+ Object o = mRes.nextElement();
+
+ if (o instanceof LDAPEntry) {
+ entry = (LDAPEntry) o;
+ return mRegistry.createObject(entry.getAttributeSet());
+ } else {
+ if (o instanceof LDAPException)
+ ;
+ // doing nothing because the last object in the search
+ // results is always LDAPException
+ else
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB,
+ ILogger.LL_FAILURE, "DBSearchResults: result format error class=" + o.getClass().getName());
+ }
+ } catch (Exception e) {
+
+ /*LogDoc
+ *
+ * @phase local ldap search
+ * @reason failed to get next element
+ * @message DBSearchResults: <exception thrown>
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB,
+ ILogger.LL_FAILURE, "DBSearchResults: " + e.toString());
+ }
+ return null;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSubsystem.java
new file mode 100644
index 000000000..be674bfd5
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBSubsystem.java
@@ -0,0 +1,986 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.math.BigInteger;
+import java.util.Hashtable;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSchema;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPObjectClassSchema;
+import netscape.ldap.LDAPSchema;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv3;
+import netscape.security.x509.CertificateValidity;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.EDBNotAvailException;
+import com.netscape.certsrv.dbs.IDBRegistry;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord;
+import com.netscape.certsrv.dbs.repository.IRepositoryRecord;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmscore.base.PropConfigStore;
+import com.netscape.cmscore.ldapconn.LdapAuthInfo;
+import com.netscape.cmscore.ldapconn.LdapBoundConnFactory;
+import com.netscape.cmscore.ldapconn.LdapConnInfo;
+
+/**
+ * A class represents the database subsystem that manages
+ * the backend data storage.
+ *
+ * This subsystem maintains multiple sessions that allows
+ * operations to be performed, and provide a registry
+ * where all the schema information is stored.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class DBSubsystem implements IDBSubsystem {
+
+ public static String ID = IDBSubsystem.SUB_ID;
+
+ private IConfigStore mConfig = null;
+ private IConfigStore mDBConfig = null;
+ private LdapBoundConnFactory mLdapConnFactory = null;
+ private DBRegistry mRegistry = null;
+ private String mBaseDN = null;
+ private ISubsystem mOwner = null;
+
+ private Hashtable<String, String>[] mRepos = null;
+
+ private BigInteger mNextSerialConfig = null;
+ private boolean mEnableSerialMgmt = false;
+
+ private static final String PROP_ENABLE_SERIAL_NUMBER_RECOVERY =
+ "enableSerialNumberRecovery";
+ // This value is only equal to the next Serial number that the CA's
+ // going to issue when cms just start up or it's just set from console.
+ // It doesn't record the next serial number at other time when cms's
+ // runing not to increase overhead when issuing certs.
+ private static final String PROP_NEXT_SERIAL_NUMBER =
+ "nextSerialNumber";
+ private static final String PROP_MIN_SERIAL_NUMBER = "beginSerialNumber";
+ private static final String PROP_MAX_SERIAL_NUMBER = "endSerialNumber";
+ private static final String PROP_NEXT_MIN_SERIAL_NUMBER = "nextBeginSerialNumber";
+ private static final String PROP_NEXT_MAX_SERIAL_NUMBER = "nextEndSerialNumber";
+ private static final String PROP_SERIAL_LOW_WATER_MARK = "serialLowWaterMark";
+ private static final String PROP_SERIAL_INCREMENT = "serialIncrement";
+ private static final String PROP_SERIAL_BASEDN = "serialDN";
+ private static final String PROP_SERIAL_RANGE_DN = "serialRangeDN";
+
+ private static final String PROP_MIN_REQUEST_NUMBER = "beginRequestNumber";
+ private static final String PROP_MAX_REQUEST_NUMBER = "endRequestNumber";
+ private static final String PROP_NEXT_MIN_REQUEST_NUMBER = "nextBeginRequestNumber";
+ private static final String PROP_NEXT_MAX_REQUEST_NUMBER = "nextEndRequestNumber";
+ private static final String PROP_REQUEST_LOW_WATER_MARK = "requestLowWaterMark";
+ private static final String PROP_REQUEST_INCREMENT = "requestIncrement";
+ private static final String PROP_REQUEST_BASEDN = "requestDN";
+ private static final String PROP_REQUEST_RANGE_DN = "requestRangeDN";
+
+ private static final String PROP_MIN_REPLICA_NUMBER = "beginReplicaNumber";
+ private static final String PROP_MAX_REPLICA_NUMBER = "endReplicaNumber";
+ private static final String PROP_NEXT_MIN_REPLICA_NUMBER = "nextBeginReplicaNumber";
+ private static final String PROP_NEXT_MAX_REPLICA_NUMBER = "nextEndReplicaNumber";
+ private static final String PROP_REPLICA_LOW_WATER_MARK = "replicaLowWaterMark";
+ private static final String PROP_REPLICA_INCREMENT = "replicaIncrement";
+ private static final String PROP_REPLICA_BASEDN = "replicaDN";
+ private static final String PROP_REPLICA_RANGE_DN = "replicaRangeDN";
+
+ private static final String PROP_INFINITE_SERIAL_NUMBER = "1000000000";
+ private static final String PROP_INFINITE_REQUEST_NUMBER = "1000000000";
+ private static final String PROP_INFINITE_REPLICA_NUMBER = "1000";
+ private static final String PROP_BASEDN = "basedn";
+ private static final String PROP_LDAP = "ldap";
+ private static final String PROP_NEXT_RANGE = "nextRange";
+ private static final String PROP_ENABLE_SERIAL_MGMT = "enableSerialManagement";
+
+ // hash keys
+ private static final String NAME = "name";
+ private static final String PROP_MIN = "min";
+ private static final String PROP_MIN_NAME = "min_name";
+ private static final String PROP_MAX = "max";
+ private static final String PROP_MAX_NAME = "max_name";
+ private static final String PROP_NEXT_MIN = "next_min";
+ private static final String PROP_NEXT_MIN_NAME = "next_min_name";
+ private static final String PROP_NEXT_MAX = "next_max";
+ private static final String PROP_NEXT_MAX_NAME = "next_max_name";
+ private static final String PROP_LOW_WATER_MARK = "lowWaterMark";
+ private static final String PROP_LOW_WATER_MARK_NAME = "lowWaterMark_name";
+ private static final String PROP_INCREMENT = "increment";
+ private static final String PROP_INCREMENT_NAME = "increment_name";
+ private static final String PROP_RANGE_DN = "rangeDN";
+
+ private ILogger mLogger = null;
+
+ // singleton enforcement
+
+ private static IDBSubsystem mInstance = new DBSubsystem();
+
+ public static IDBSubsystem getInstance() {
+ return mInstance;
+ }
+
+ /**
+ * This method is used for unit tests. It allows the underlying instance
+ * to be stubbed out.
+ *
+ * @param dbSubsystem The stubbed out subsystem to override with.
+ */
+ public static void setInstance(IDBSubsystem dbSubsystem) {
+ mInstance = dbSubsystem;
+ }
+
+ // end singleton enforcement.
+
+ /**
+ * Constructs database subsystem.
+ */
+ private DBSubsystem() {
+ }
+
+ /**
+ * Retrieves subsystem identifier.
+ */
+ public String getId() {
+ return IDBSubsystem.SUB_ID;
+ }
+
+ /**
+ * Sets subsystem identifier.
+ */
+ public void setId(String id) throws EBaseException {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION"));
+ }
+
+ public boolean enableSerialNumberRecovery() {
+ try {
+ return mDBConfig.getBoolean(
+ PROP_ENABLE_SERIAL_NUMBER_RECOVERY, true);
+ } catch (EBaseException e) {
+ // by default
+ return true;
+ }
+ }
+
+ public boolean getEnableSerialMgmt() {
+ return mEnableSerialMgmt;
+ }
+
+ public void setEnableSerialMgmt(boolean v)
+ throws EBaseException {
+ if (v) {
+ CMS.debug("DBSubsystem: Enabling Serial Number Management");
+ } else {
+ CMS.debug("DBSubsystem: Disabling Serial Number Management");
+ }
+
+ mDBConfig.putBoolean(PROP_ENABLE_SERIAL_MGMT, v);
+ IConfigStore rootStore = getOwner().getConfigStore();
+ rootStore.commit(false);
+ mEnableSerialMgmt = v;
+ }
+
+ public BigInteger getNextSerialConfig() {
+ return mNextSerialConfig;
+ }
+
+ public void setNextSerialConfig(BigInteger serial)
+ throws EBaseException {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB,
+ ILogger.LL_INFO, "DBSubsystem: " +
+ "Setting next serial number: 0x" + serial.toString(16));
+ mDBConfig.putString(PROP_NEXT_SERIAL_NUMBER,
+ serial.toString(16));
+ }
+
+ /**
+ * Gets minimum serial number limit in config file
+ *
+ * @param repo repo identifier
+ * @return min serial number
+ */
+ public String getMinSerialConfig(int repo) {
+ return mRepos[repo].get(PROP_MIN);
+ }
+
+ /**
+ * Gets maximum serial number limit in config file
+ *
+ * @param repo repo identifier
+ * @return max serial number
+ */
+ public String getMaxSerialConfig(int repo) {
+ return mRepos[repo].get(PROP_MAX);
+ }
+
+ /**
+ * Gets minimum serial number limit in next range in config file
+ *
+ * @param repo repo identifier
+ * @return min serial number in next range
+ */
+ public String getNextMinSerialConfig(int repo) {
+ String ret = mRepos[repo].get(PROP_NEXT_MIN);
+ if (ret.equals("-1")) {
+ return null;
+ } else {
+ return ret;
+ }
+ }
+
+ /**
+ * Gets maximum serial number limit in next range in config file
+ *
+ * @param repo repo identifier
+ * @return max serial number in next range
+ */
+ public String getNextMaxSerialConfig(int repo) {
+ String ret = mRepos[repo].get(PROP_NEXT_MAX);
+ if (ret.equals("-1")) {
+ return null;
+ } else {
+ return ret;
+ }
+ }
+
+ /**
+ * Gets low water mark limit in config file
+ *
+ * @param repo repo identifier
+ * @return low water mark
+ */
+ public String getLowWaterMarkConfig(int repo) {
+ return mRepos[repo].get(PROP_LOW_WATER_MARK);
+ }
+
+ /**
+ * Gets range increment for next range in config file
+ *
+ * @param repo repo identifier
+ * @return range increment
+ */
+ public String getIncrementConfig(int repo) {
+ return mRepos[repo].get(PROP_INCREMENT);
+ }
+
+ /**
+ * Sets maximum serial number limit in config file
+ *
+ * @param repo repo identifier
+ * @param serial max serial number
+ * @exception EBaseException failed to set
+ */
+ public void setMaxSerialConfig(int repo, String serial)
+ throws EBaseException {
+ Hashtable<String, String> h = mRepos[repo];
+ CMS.debug("DBSubsystem: Setting max serial number for " + h.get(NAME) + ": " + serial);
+
+ //persist to file
+ mDBConfig.putString(h.get(PROP_MAX_NAME), serial);
+ IConfigStore rootStore = getOwner().getConfigStore();
+ rootStore.commit(false);
+
+ h.put(PROP_MAX, serial);
+ mRepos[repo] = h;
+ }
+
+ /**
+ * Sets minimum serial number limit in config file
+ *
+ * @param repo repo identifier
+ * @param serial min serial number
+ * @exception EBaseException failed to set
+ */
+ public void setMinSerialConfig(int repo, String serial)
+ throws EBaseException {
+ Hashtable<String, String> h = mRepos[repo];
+ CMS.debug("DBSubsystem: Setting min serial number for " + h.get(NAME) + ": " + serial);
+
+ //persist to file
+ mDBConfig.putString(h.get(PROP_MIN_NAME), serial);
+ IConfigStore rootStore = getOwner().getConfigStore();
+ rootStore.commit(false);
+
+ h.put(PROP_MIN, serial);
+ mRepos[repo] = h;
+ }
+
+ /**
+ * Sets maximum serial number limit for next range in config file
+ *
+ * @param repo repo identifier
+ * @param serial max serial number for next range
+ * @exception EBaseException failed to set
+ */
+ public void setNextMaxSerialConfig(int repo, String serial)
+ throws EBaseException {
+ Hashtable<String, String> h = mRepos[repo];
+ if (serial == null) {
+ CMS.debug("DBSubsystem: Removing next max " + h.get(NAME) + " number");
+ mDBConfig.remove(h.get(PROP_NEXT_MAX_NAME));
+ } else {
+ CMS.debug("DBSubsystem: Setting next max " + h.get(NAME) + " number: " + serial);
+ mDBConfig.putString(h.get(PROP_NEXT_MAX_NAME), serial);
+ }
+ IConfigStore rootStore = getOwner().getConfigStore();
+ rootStore.commit(false);
+ if (serial == null) {
+ h.remove(PROP_NEXT_MAX);
+ } else {
+ h.put(PROP_NEXT_MAX, serial);
+ }
+ mRepos[repo] = h;
+ }
+
+ /**
+ * Sets minimum serial number limit for next range in config file
+ *
+ * @param repo repo identifier
+ * @param serial min serial number for next range
+ * @exception EBaseException failed to set
+ */
+ public void setNextMinSerialConfig(int repo, String serial)
+ throws EBaseException {
+ Hashtable<String, String> h = mRepos[repo];
+ if (serial == null) {
+ CMS.debug("DBSubsystem: Removing next min " + h.get(NAME) + " number");
+ mDBConfig.remove(h.get(PROP_NEXT_MIN_NAME));
+ } else {
+ CMS.debug("DBSubsystem: Setting next min " + h.get(NAME) + " number: " + serial);
+ mDBConfig.putString(h.get(PROP_NEXT_MIN_NAME), serial);
+ }
+ IConfigStore rootStore = getOwner().getConfigStore();
+ rootStore.commit(false);
+ if (serial == null) {
+ h.remove(PROP_NEXT_MIN);
+ } else {
+ h.put(PROP_NEXT_MIN, serial);
+ }
+ mRepos[repo] = h;
+ }
+
+ /**
+ * Gets start of next range from database.
+ * Increments the nextRange attribute and allocates
+ * this range to the current instance by creating a pkiRange object.
+ *
+ * @param repo repo identifier
+ * @return start of next range
+ */
+ public String getNextRange(int repo) {
+ LDAPConnection conn = null;
+ String nextRange = null;
+ try {
+ Hashtable<String, String> h = mRepos[repo];
+ conn = mLdapConnFactory.getConn();
+ String dn = h.get(PROP_BASEDN) + "," + mBaseDN;
+ String rangeDN = h.get(PROP_RANGE_DN) + "," + mBaseDN;
+
+ LDAPEntry entry = conn.read(dn);
+ LDAPAttribute attr = entry.getAttribute(PROP_NEXT_RANGE);
+ if (attr == null) {
+ throw new Exception("Missing Attribute" + PROP_NEXT_RANGE + "in Entry " + dn);
+ }
+ nextRange = (String) attr.getStringValues().nextElement();
+
+ BigInteger nextRangeNo = new BigInteger(nextRange);
+ BigInteger incrementNo = new BigInteger(h.get(PROP_INCREMENT));
+ // To make sure attrNextRange always increments, first delete the current value and then
+ // increment. Two operations in the same transaction
+ LDAPAttribute attrNextRange = new LDAPAttribute(PROP_NEXT_RANGE, nextRangeNo.add(incrementNo).toString());
+ LDAPModification[] mods = {
+ new LDAPModification(LDAPModification.DELETE, attr),
+ new LDAPModification(LDAPModification.ADD, attrNextRange) };
+ conn.modify(dn, mods);
+
+ // Add new range object
+ String endRange = nextRangeNo.add(incrementNo).subtract(BigInteger.ONE).toString();
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectClass", "top"));
+ attrs.add(new LDAPAttribute("objectClass", "pkiRange"));
+ attrs.add(new LDAPAttribute("beginRange", nextRange));
+ attrs.add(new LDAPAttribute("endRange", endRange));
+ attrs.add(new LDAPAttribute("cn", nextRange));
+ attrs.add(new LDAPAttribute("host", CMS.getEESSLHost()));
+ attrs.add(new LDAPAttribute("securePort", CMS.getEESSLPort()));
+ String dn2 = "cn=" + nextRange + "," + rangeDN;
+ LDAPEntry rangeEntry = new LDAPEntry(dn2, attrs);
+ conn.add(rangeEntry);
+ CMS.debug("DBSubsystem: getNextRange Next range has been added: " +
+ nextRange + " - " + endRange);
+ } catch (Exception e) {
+ CMS.debug("DBSubsystem: getNextRange. Unable to provide next range :" + e);
+ e.printStackTrace();
+ nextRange = null;
+ } finally {
+ try {
+ if ((conn != null) && (mLdapConnFactory != null)) {
+ CMS.debug("Releasing ldap connection");
+ mLdapConnFactory.returnConn(conn);
+ }
+ } catch (Exception e) {
+ CMS.debug("Error releasing the ldap connection" + e.toString());
+ }
+ }
+ return nextRange;
+ }
+
+ /**
+ * Determines if a range conflict has been observed in database.
+ * If so, delete the conflict entry and remove the next range.
+ * When the next number is requested, if the number of certs is still
+ * below the low water mark, then a new range will be requested.
+ *
+ * @param repo repo identifier
+ * @return true if range conflict, false otherwise
+ */
+ public boolean hasRangeConflict(int repo) {
+ LDAPConnection conn = null;
+ boolean conflict = false;
+ try {
+ String nextRangeStart = getNextMinSerialConfig(repo);
+ if (nextRangeStart == null) {
+ return false;
+ }
+ Hashtable<String, String> h = mRepos[repo];
+ conn = mLdapConnFactory.getConn();
+ String rangedn = h.get(PROP_RANGE_DN) + "," + mBaseDN;
+ String filter = "(&(nsds5ReplConflict=*)(objectClass=pkiRange)(host= " +
+ CMS.getEESSLHost() + ")(SecurePort=" + CMS.getEESSLPort() +
+ ")(beginRange=" + nextRangeStart + "))";
+ LDAPSearchResults results = conn.search(rangedn, LDAPv3.SCOPE_SUB,
+ filter, null, false);
+
+ while (results.hasMoreElements()) {
+ conflict = true;
+ LDAPEntry entry = results.next();
+ String dn = entry.getDN();
+ CMS.debug("Deleting conflict entry:" + dn);
+ conn.delete(dn);
+ }
+ } catch (Exception e) {
+ CMS.debug("DBSubsystem: hasRangeConflict. Error while checking next range." + e);
+ e.printStackTrace();
+ } finally {
+ try {
+ if ((conn != null) && (mLdapConnFactory != null)) {
+ CMS.debug("Releasing ldap connection");
+ mLdapConnFactory.returnConn(conn);
+ }
+ } catch (Exception e) {
+ CMS.debug("Error releasing the ldap connection" + e.toString());
+ }
+ }
+ return conflict;
+ }
+
+ public ISubsystem getOwner() {
+ return mOwner;
+ }
+
+ /**
+ * Initializes the internal registery. Connects to the
+ * data source, and create a pool of connection of which
+ * applications can use. Optionally, check the integrity
+ * of the database.
+ */
+ @SuppressWarnings("unchecked")
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+
+ mLogger = CMS.getLogger();
+ mDBConfig = config;
+ mRepos = new Hashtable[IDBSubsystem.NUM_REPOS];
+
+ mConfig = config.getSubStore(PROP_LDAP);
+ IConfigStore tmpConfig = null;
+ try {
+ mBaseDN = mConfig.getString(PROP_BASEDN, "o=NetscapeCertificateServer");
+
+ mOwner = owner;
+
+ mNextSerialConfig = new BigInteger(mDBConfig.getString(
+ PROP_NEXT_SERIAL_NUMBER, "0"), 16);
+
+ mEnableSerialMgmt = mDBConfig.getBoolean(PROP_ENABLE_SERIAL_MGMT, false);
+ CMS.debug("DBSubsystem: init() mEnableSerialMgmt="+mEnableSerialMgmt);
+
+ // populate the certs hash entry
+ Hashtable<String, String> certs = new Hashtable<String, String>();
+ certs.put(NAME, "certs");
+ certs.put(PROP_BASEDN, mDBConfig.getString(PROP_SERIAL_BASEDN, ""));
+ certs.put(PROP_RANGE_DN, mDBConfig.getString(PROP_SERIAL_RANGE_DN, ""));
+
+ certs.put(PROP_MIN_NAME, PROP_MIN_SERIAL_NUMBER);
+ certs.put(PROP_MIN, mDBConfig.getString(
+ PROP_MIN_SERIAL_NUMBER, "0"));
+
+ certs.put(PROP_MAX_NAME, PROP_MAX_SERIAL_NUMBER);
+ certs.put(PROP_MAX, mDBConfig.getString(
+ PROP_MAX_SERIAL_NUMBER, PROP_INFINITE_SERIAL_NUMBER));
+
+ certs.put(PROP_NEXT_MIN_NAME, PROP_NEXT_MIN_SERIAL_NUMBER);
+ certs.put(PROP_NEXT_MIN, mDBConfig.getString(
+ PROP_NEXT_MIN_SERIAL_NUMBER, "-1"));
+
+ certs.put(PROP_NEXT_MAX_NAME, PROP_NEXT_MAX_SERIAL_NUMBER);
+ certs.put(PROP_NEXT_MAX, mDBConfig.getString(
+ PROP_NEXT_MAX_SERIAL_NUMBER, "-1"));
+
+ certs.put(PROP_LOW_WATER_MARK_NAME, PROP_SERIAL_LOW_WATER_MARK);
+ certs.put(PROP_LOW_WATER_MARK, mDBConfig.getString(
+ PROP_SERIAL_LOW_WATER_MARK, "5000"));
+
+ certs.put(PROP_INCREMENT_NAME, PROP_SERIAL_INCREMENT);
+ certs.put(PROP_INCREMENT, mDBConfig.getString(
+ PROP_SERIAL_INCREMENT, PROP_INFINITE_SERIAL_NUMBER));
+
+ mRepos[CERTS] = certs;
+
+ // populate the requests hash entry
+ Hashtable<String, String> requests = new Hashtable<String, String>();
+ requests.put(NAME, "requests");
+ requests.put(PROP_BASEDN, mDBConfig.getString(PROP_REQUEST_BASEDN, ""));
+ requests.put(PROP_RANGE_DN, mDBConfig.getString(PROP_REQUEST_RANGE_DN, ""));
+
+ requests.put(PROP_MIN_NAME, PROP_MIN_REQUEST_NUMBER);
+ requests.put(PROP_MIN, mDBConfig.getString(
+ PROP_MIN_REQUEST_NUMBER, "0"));
+
+ requests.put(PROP_MAX_NAME, PROP_MAX_REQUEST_NUMBER);
+ requests.put(PROP_MAX, mDBConfig.getString(
+ PROP_MAX_REQUEST_NUMBER, PROP_INFINITE_REQUEST_NUMBER));
+
+ requests.put(PROP_NEXT_MIN_NAME, PROP_NEXT_MIN_REQUEST_NUMBER);
+ requests.put(PROP_NEXT_MIN, mDBConfig.getString(
+ PROP_NEXT_MIN_REQUEST_NUMBER, "-1"));
+
+ requests.put(PROP_NEXT_MAX_NAME, PROP_NEXT_MAX_REQUEST_NUMBER);
+ requests.put(PROP_NEXT_MAX, mDBConfig.getString(
+ PROP_NEXT_MAX_REQUEST_NUMBER, "-1"));
+
+ requests.put(PROP_LOW_WATER_MARK_NAME, PROP_REQUEST_LOW_WATER_MARK);
+ requests.put(PROP_LOW_WATER_MARK, mDBConfig.getString(
+ PROP_REQUEST_LOW_WATER_MARK, "5000"));
+
+ requests.put(PROP_INCREMENT_NAME, PROP_REQUEST_INCREMENT);
+ requests.put(PROP_INCREMENT, mDBConfig.getString(
+ PROP_REQUEST_INCREMENT, PROP_INFINITE_REQUEST_NUMBER));
+
+ mRepos[REQUESTS] = requests;
+
+ // populate replica ID hash entry
+ Hashtable<String, String> replicaID = new Hashtable<String, String>();
+ replicaID.put(NAME, "requests");
+ replicaID.put(PROP_BASEDN, mDBConfig.getString(PROP_REPLICA_BASEDN, ""));
+ replicaID.put(PROP_RANGE_DN, mDBConfig.getString(PROP_REPLICA_RANGE_DN, ""));
+
+ replicaID.put(PROP_MIN_NAME, PROP_MIN_REPLICA_NUMBER);
+ replicaID.put(PROP_MIN, mDBConfig.getString(
+ PROP_MIN_REPLICA_NUMBER, "1"));
+
+ replicaID.put(PROP_MAX_NAME, PROP_MAX_REPLICA_NUMBER);
+ replicaID.put(PROP_MAX, mDBConfig.getString(
+ PROP_MAX_REPLICA_NUMBER, PROP_INFINITE_REPLICA_NUMBER));
+
+ replicaID.put(PROP_NEXT_MIN_NAME, PROP_NEXT_MIN_REPLICA_NUMBER);
+ replicaID.put(PROP_NEXT_MIN, mDBConfig.getString(
+ PROP_NEXT_MIN_REPLICA_NUMBER, "-1"));
+
+ replicaID.put(PROP_NEXT_MAX_NAME, PROP_NEXT_MAX_REPLICA_NUMBER);
+ replicaID.put(PROP_NEXT_MAX, mDBConfig.getString(
+ PROP_NEXT_MAX_REPLICA_NUMBER, "-1"));
+
+ replicaID.put(PROP_LOW_WATER_MARK_NAME, PROP_REPLICA_LOW_WATER_MARK);
+ replicaID.put(PROP_LOW_WATER_MARK, mDBConfig.getString(
+ PROP_REPLICA_LOW_WATER_MARK, "10"));
+
+ replicaID.put(PROP_INCREMENT_NAME, PROP_REPLICA_INCREMENT);
+ replicaID.put(PROP_INCREMENT, mDBConfig.getString(
+ PROP_REPLICA_INCREMENT, PROP_INFINITE_REPLICA_NUMBER));
+
+ mRepos[REPLICA_ID] = replicaID;
+
+ // initialize registry
+ mRegistry = new DBRegistry();
+ mRegistry.init(this, null);
+
+ // initialize LDAP connection factory
+ // by default return error if server is down at startup time.
+ mLdapConnFactory = new LdapBoundConnFactory(true);
+ tmpConfig = (IConfigStore) (((PropConfigStore) mConfig).clone());
+
+ tmpConfig.putString(PROP_BASEDN, mBaseDN);
+ } catch (EBaseException e) {
+ if (CMS.isPreOpMode())
+ return;
+ throw e;
+ }
+
+ try {
+ mLdapConnFactory.init(tmpConfig);
+ } catch (ELdapServerDownException e) {
+ if (CMS.isPreOpMode())
+ return;
+ throw new EDBNotAvailException(
+ CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
+ } catch (ELdapException ex) {
+ if (CMS.isPreOpMode())
+ return;
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_ERROR", ex.toString()));
+ } catch (EBaseException e) {
+ if (CMS.isPreOpMode())
+ return;
+ throw e;
+ }
+
+ try {
+ // registers CMS database attributes
+ IDBRegistry reg = getRegistry();
+
+ String certRecordOC[] = new String[2];
+
+ certRecordOC[0] = CertDBSchema.LDAP_OC_TOP;
+ certRecordOC[1] = CertDBSchema.LDAP_OC_CERT_RECORD;
+
+ if (!reg.isObjectClassRegistered(CertRecord.class.getName())) {
+ reg.registerObjectClass(CertRecord.class.getName(),
+ certRecordOC);
+ }
+ if (!reg.isAttributeRegistered(CertRecord.ATTR_ID)) {
+ reg.registerAttribute(CertRecord.ATTR_ID, new
+ BigIntegerMapper(CertDBSchema.LDAP_ATTR_SERIALNO));
+ }
+ if (!reg.isAttributeRegistered(CertRecord.ATTR_META_INFO)) {
+ reg.registerAttribute(CertRecord.ATTR_META_INFO, new
+ MetaInfoMapper(CertDBSchema.LDAP_ATTR_META_INFO));
+ }
+ if (!reg.isAttributeRegistered(CertRecord.ATTR_REVO_INFO)) {
+ reg.registerAttribute(CertRecord.ATTR_REVO_INFO, new
+ RevocationInfoMapper());
+ }
+ if (!reg.isAttributeRegistered(CertRecord.ATTR_X509CERT)) {
+ reg.registerAttribute(CertRecord.ATTR_X509CERT, new
+ X509CertImplMapper());
+ }
+ if (!reg.isAttributeRegistered(CertRecord.ATTR_CERT_STATUS)) {
+ reg.registerAttribute(CertRecord.ATTR_CERT_STATUS, new
+ StringMapper(CertDBSchema.LDAP_ATTR_CERT_STATUS));
+ }
+ if (!reg.isAttributeRegistered(CertRecord.ATTR_AUTO_RENEW)) {
+ reg.registerAttribute(CertRecord.ATTR_AUTO_RENEW, new
+ StringMapper(CertDBSchema.LDAP_ATTR_AUTO_RENEW));
+ }
+ if (!reg.isAttributeRegistered(CertRecord.ATTR_CREATE_TIME)) {
+ reg.registerAttribute(CertRecord.ATTR_CREATE_TIME, new
+ DateMapper(CertDBSchema.LDAP_ATTR_CREATE_TIME));
+ }
+ if (!reg.isAttributeRegistered(CertRecord.ATTR_MODIFY_TIME)) {
+ reg.registerAttribute(CertRecord.ATTR_MODIFY_TIME, new
+ DateMapper(CertDBSchema.LDAP_ATTR_MODIFY_TIME));
+ }
+ if (!reg.isAttributeRegistered(CertRecord.ATTR_ISSUED_BY)) {
+ reg.registerAttribute(CertRecord.ATTR_ISSUED_BY, new
+ StringMapper(CertDBSchema.LDAP_ATTR_ISSUED_BY));
+ }
+ if (!reg.isAttributeRegistered(CertRecord.ATTR_REVOKED_BY)) {
+ reg.registerAttribute(CertRecord.ATTR_REVOKED_BY, new
+ StringMapper(CertDBSchema.LDAP_ATTR_REVOKED_BY));
+ }
+ if (!reg.isAttributeRegistered(CertRecord.ATTR_REVOKED_ON)) {
+ reg.registerAttribute(CertRecord.ATTR_REVOKED_ON, new
+ DateMapper(CertDBSchema.LDAP_ATTR_REVOKED_ON));
+ }
+
+ if (!reg.isAttributeRegistered(CertificateValidity.NOT_AFTER)) {
+ reg.registerAttribute(CertificateValidity.NOT_AFTER, new
+ DateMapper(CertDBSchema.LDAP_ATTR_NOT_AFTER));
+ }
+
+ if (!reg.isAttributeRegistered(CertificateValidity.NOT_BEFORE)) {
+ reg.registerAttribute(CertificateValidity.NOT_BEFORE, new
+ DateMapper(CertDBSchema.LDAP_ATTR_NOT_BEFORE));
+ }
+
+ String crlRecordOC[] = new String[2];
+
+ crlRecordOC[0] = CRLDBSchema.LDAP_OC_TOP;
+ crlRecordOC[1] = CRLDBSchema.LDAP_OC_CRL_RECORD;
+ reg.registerObjectClass(CRLIssuingPointRecord.class.getName(),
+ crlRecordOC);
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_ID, new
+ StringMapper(CRLDBSchema.LDAP_ATTR_CRL_ID));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CRL_NUMBER, new
+ BigIntegerMapper(CRLDBSchema.LDAP_ATTR_CRL_NUMBER));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_DELTA_NUMBER, new
+ BigIntegerMapper(CRLDBSchema.LDAP_ATTR_DELTA_NUMBER));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CRL_SIZE, new
+ LongMapper(CRLDBSchema.LDAP_ATTR_CRL_SIZE));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_DELTA_SIZE, new
+ LongMapper(CRLDBSchema.LDAP_ATTR_DELTA_SIZE));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_THIS_UPDATE, new
+ DateMapper(CRLDBSchema.LDAP_ATTR_THIS_UPDATE));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_NEXT_UPDATE, new
+ DateMapper(CRLDBSchema.LDAP_ATTR_NEXT_UPDATE));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_FIRST_UNSAVED, new
+ StringMapper(CRLDBSchema.LDAP_ATTR_FIRST_UNSAVED));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CRL, new
+ ByteArrayMapper(CRLDBSchema.LDAP_ATTR_CRL));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_DELTA_CRL, new
+ ByteArrayMapper(CRLDBSchema.LDAP_ATTR_DELTA_CRL));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CA_CERT, new
+ ByteArrayMapper(CRLDBSchema.LDAP_ATTR_CA_CERT));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CRL_CACHE, new
+ ObjectStreamMapper(CRLDBSchema.LDAP_ATTR_CRL_CACHE));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_REVOKED_CERTS, new
+ ObjectStreamMapper(CRLDBSchema.LDAP_ATTR_REVOKED_CERTS));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_UNREVOKED_CERTS, new
+ ObjectStreamMapper(CRLDBSchema.LDAP_ATTR_UNREVOKED_CERTS));
+ reg.registerAttribute(ICRLIssuingPointRecord.ATTR_EXPIRED_CERTS, new
+ ObjectStreamMapper(CRLDBSchema.LDAP_ATTR_EXPIRED_CERTS));
+
+ if (!reg.isObjectClassRegistered(
+ RepositoryRecord.class.getName())) {
+ String repRecordOC[] = new String[2];
+
+ repRecordOC[0] = RepositorySchema.LDAP_OC_TOP;
+ repRecordOC[1] = RepositorySchema.LDAP_OC_REPOSITORY;
+ reg.registerObjectClass(
+ RepositoryRecord.class.getName(), repRecordOC);
+ }
+ if (!reg.isAttributeRegistered(IRepositoryRecord.ATTR_SERIALNO)) {
+ reg.registerAttribute(IRepositoryRecord.ATTR_SERIALNO,
+ new BigIntegerMapper(RepositorySchema.LDAP_ATTR_SERIALNO));
+ }
+ if (!reg.isAttributeRegistered(IRepositoryRecord.ATTR_PUB_STATUS)) {
+ reg.registerAttribute(IRepositoryRecord.ATTR_PUB_STATUS,
+ new StringMapper(RepositorySchema.LDAP_ATTR_PUB_STATUS));
+ }
+ if (!reg.isAttributeRegistered(IRepositoryRecord.ATTR_DESCRIPTION)) {
+ reg.registerAttribute(IRepositoryRecord.ATTR_DESCRIPTION,
+ new StringMapper(RepositorySchema.LDAP_ATTR_DESCRIPTION));
+ }
+
+ } catch (EBaseException e) {
+ if (CMS.isPreOpMode())
+ return;
+ throw e;
+ }
+ }
+
+ public String getEntryAttribute(String dn, String attrName,
+ String defaultValue, String errorValue) {
+ LDAPConnection conn = null;
+ String attrValue = null;
+ try {
+ conn = mLdapConnFactory.getConn();
+ String[] attrs = { attrName };
+ LDAPEntry entry = conn.read(dn, attrs);
+ if (entry != null) {
+ LDAPAttribute attr = entry.getAttribute(attrName);
+ if (attr != null) {
+ attrValue = (String) attr.getStringValues().nextElement();
+ } else {
+ attrValue = defaultValue;
+ }
+ } else {
+ attrValue = errorValue;
+ }
+ } catch (LDAPException e) {
+ CMS.debug("DBSubsystem: getEntryAttribute LDAPException code="+e.getLDAPResultCode());
+ if (e.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT) {
+ attrValue = defaultValue;
+ }
+ } catch (Exception e) {
+ CMS.debug("DBSubsystem: getEntryAttribute. Unable to retrieve '"+attrName+"': "+ e);
+ attrValue = errorValue;
+ } finally {
+ try {
+ if ((conn != null) && (mLdapConnFactory != null)) {
+ CMS.debug("Releasing ldap connection");
+ mLdapConnFactory.returnConn(conn);
+ }
+ } catch (Exception e) {
+ CMS.debug("Error releasing the ldap connection" + e.toString());
+ }
+ }
+ CMS.debug("DBSubsystem: getEntryAttribute: dn="+dn+" attr="+attrName+":"+attrValue+";");
+
+ return attrValue;
+ }
+
+ /**
+ * Starts up this service.
+ */
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Retrieves internal DB configuration store.
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Retrieves DB subsystem configuration store.
+ */
+ public IConfigStore getDBConfigStore() {
+ return mDBConfig;
+ }
+
+ /**
+ * Retrieves base DN of backend database.
+ */
+ public String getBaseDN() {
+ return mBaseDN;
+ }
+
+ /**
+ * Retrieves LDAP connection info (host, port, secure)
+ */
+ public LdapConnInfo getLdapConnInfo() {
+ if (mLdapConnFactory != null)
+ return mLdapConnFactory.getConnInfo();
+ return null;
+ }
+
+ public LdapAuthInfo getLdapAuthInfo() {
+ if (mLdapConnFactory != null)
+ return mLdapConnFactory.getAuthInfo();
+ return null;
+ }
+
+ /**
+ * Shutdowns this subsystem gracefully.
+ */
+ public void shutdown() {
+ try {
+ if (mLdapConnFactory != null) {
+ mLdapConnFactory.reset();
+ }
+ } catch (ELdapException e) {
+
+ /*LogDoc
+ *
+ * @phase shutdown server
+ * @reason shutdown db subsystem
+ * @message DBSubsystem: <exception thrown>
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB,
+ ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+ if (mRegistry != null)
+ mRegistry.shutdown();
+ }
+
+ /**
+ * Retrieves the registry.
+ */
+ public IDBRegistry getRegistry() {
+ return mRegistry;
+ }
+
+ /**
+ * Creates a database session.
+ */
+ public IDBSSession createSession() throws EDBException {
+ LDAPConnection conn = null;
+
+ try {
+ conn = mLdapConnFactory.getConn();
+
+ String schemaAdded = mDBConfig.getString("newSchemaEntryAdded", "");
+
+ if (schemaAdded.equals("")) {
+ LDAPSchema dirSchema = new LDAPSchema();
+
+ // create new attribute: userType
+ dirSchema.fetchSchema(conn);
+ LDAPAttributeSchema userType = dirSchema.getAttribute("usertype");
+
+ if (userType == null) {
+ userType = new LDAPAttributeSchema("usertype", "usertype-oid",
+ "Distinguish whether the user is administrator, agent or subsystem.",
+ LDAPAttributeSchema.cis, false);
+ userType.add(conn);
+ }
+
+ // create new objectclass: cmsuser
+ dirSchema.fetchSchema(conn);
+ LDAPObjectClassSchema newObjClass = dirSchema.getObjectClass("cmsuser");
+ String[] requiredAttrs = { "usertype" };
+ String[] optionalAttrs = new String[0];
+
+ if (newObjClass == null) {
+ newObjClass = new LDAPObjectClassSchema("cmsuser", "cmsuser-oid",
+ "top", "CMS User", requiredAttrs, optionalAttrs);
+ newObjClass.add(conn);
+ }
+ mDBConfig.putString("newSchemaEntryAdded", "true");
+ IConfigStore rootStore = getOwner().getConfigStore();
+
+ rootStore.commit(false);
+ }
+ } catch (ELdapException e) {
+ if (e instanceof ELdapServerDownException) {
+ throw new EDBNotAvailException(
+ CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE"));
+ }
+
+ /*LogDoc
+ *
+ * @phase create db session
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_DBS_CONN_ERROR", e.toString()));
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_CONNECT_LDAP_FAILED", e.toString()));
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() != 20) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_DBS_SCHEMA_ERROR", e.toString()));
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_ADD_ENTRY_FAILED", e.toString()));
+ }
+ } catch (EBaseException e) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_DBS_CONF_ERROR",
+ e.toString()));
+ }
+ return new DBSSession(this, conn);
+ }
+
+ public void returnConn(LDAPConnection conn) {
+ mLdapConnFactory.returnConn(conn);
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/DBVirtualList.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBVirtualList.java
new file mode 100644
index 000000000..51a9230ac
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/DBVirtualList.java
@@ -0,0 +1,800 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Arrays;
+import java.util.Vector;
+
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPControl;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPSearchConstraints;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPSortKey;
+import netscape.ldap.controls.LDAPSortControl;
+import netscape.ldap.controls.LDAPVirtualListControl;
+import netscape.ldap.controls.LDAPVirtualListResponse;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBRegistry;
+import com.netscape.certsrv.dbs.IDBVirtualList;
+import com.netscape.certsrv.dbs.IElementProcessor;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A class represents a virtual list of search results.
+ * Note that this class must be used with DS4.0.
+ *
+ * @author thomask
+ * @author mzhao
+ * @version $Revision$, $Date$
+ */
+public class DBVirtualList<E> implements IDBVirtualList<E> {
+
+ private IDBRegistry mRegistry = null;
+ private LDAPConnection mConn = null;
+ private String mBase = null;
+ private String mFilter = null;
+ private String mAttrs[] = null;
+ // virtual list size
+ private int mSize = -1;
+
+ private Vector<E> mEntries = new Vector<E>();
+ // mSize is get or not?
+ private boolean mInitialized = false;
+ private LDAPSortKey[] mKeys;
+ private LDAPControl[] mPageControls = null;
+ // page buffer size
+ private int mPageSize = 10;
+ // the top of the buffer
+ private int mTop = 0;
+ private int mBeforeCount;
+ private int mAfterCount;
+ // the index of the first entry returned
+ private int mSelectedIndex = 0;
+ private int mJumpToIndex = 0;
+ private int mJumpToInitialIndex = 0; // Initial index hit in jumpto operation
+ private int mJumpToDirection = 1; // Do we proceed forward or backwards
+ private String mJumpTo = null; // Determines if this is the jumpto case
+
+ private ILogger mLogger = CMS.getLogger();
+
+ /**
+ * Constructs a virtual list.
+ * Be sure to setPageSize() later if your pageSize is not the default 10
+ * Be sure to setSortKey() before fetchs
+ *
+ * param registry the registry of attribute mappers
+ * param c the ldap connection. It has to be version 3 and upper
+ * param base the base distinguished name to search from
+ * param filter search filter specifying the search criteria
+ * param attrs list of attributes that you want returned in the search results
+ */
+ public DBVirtualList(IDBRegistry registry, LDAPConnection c,
+ String base, String filter, String attrs[]) throws EBaseException {
+ mRegistry = registry;
+ mFilter = filter;
+ mBase = base;
+ mAttrs = attrs;
+ CMS.debug("In DBVirtualList filter attrs filter: " + filter
+ + " attrs: " + Arrays.toString(attrs));
+ mPageControls = new LDAPControl[2];
+ try {
+ mConn = (LDAPConnection) c.clone();
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED",
+ e.toString()));
+ }
+ }
+
+ /**
+ * Constructs a virtual list.
+ * Be sure to setPageSize() later if your pageSize is not the default 10
+ *
+ * param registry the registry of attribute mappers
+ * param c the ldap connection. It has to be version 3 and upper
+ * param base the base distinguished name to search from
+ * param filter search filter specifying the search criteria
+ * param attrs list of attributes that you want returned in the search results
+ * param sortKey the attributes to sort by
+ */
+ public DBVirtualList(IDBRegistry registry, LDAPConnection c,
+ String base, String filter, String attrs[], String sortKey[])
+ throws EBaseException {
+
+ CMS.debug("In DBVirtualList filter attrs sotrKey[] filter: " + filter
+ + " attrs: " + Arrays.toString(attrs));
+ mRegistry = registry;
+ mFilter = filter;
+ try {
+ mConn = (LDAPConnection) c.clone();
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED",
+ e.toString()));
+ }
+ mBase = base;
+ mAttrs = attrs;
+ mPageControls = new LDAPControl[2];
+ setSortKey(sortKey);
+ }
+
+ /**
+ * Constructs a virtual list.
+ * Be sure to setPageSize() later if your pageSize is not the default 10
+ *
+ * param registry the registry of attribute mappers
+ * param c the ldap connection. It has to be version 3 and upper
+ * param base the base distinguished name to search from
+ * param filter search filter specifying the search criteria
+ * param attrs list of attributes that you want returned in the search results
+ * param sortKey the attribute to sort by
+ */
+ public DBVirtualList(IDBRegistry registry, LDAPConnection c,
+ String base, String filter, String attrs[], String sortKey)
+ throws EBaseException {
+
+ CMS.debug("In DBVirtualList filter attrs sortKey filter: " + filter + " attrs: " + Arrays.toString(attrs));
+ mRegistry = registry;
+ mFilter = filter;
+ try {
+ mConn = (LDAPConnection) c.clone();
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED",
+ e.toString()));
+ }
+ mBase = base;
+ mAttrs = attrs;
+ mPageControls = new LDAPControl[2];
+ setSortKey(sortKey);
+ }
+
+ /**
+ * Constructs a virtual list.
+ *
+ * param registry the registry of attribute mappers
+ * param c the ldap connection. It has to be version 3 and upper
+ * param base the base distinguished name to search from
+ * param filter search filter specifying the search criteria
+ * param attrs list of attributes that you want returned in the search results
+ * param sortKey the attributes to sort by
+ * param pageSize the size of a page. There is a 3*pageSize buffer maintained so
+ * pageUp and pageDown won't invoke fetch from ldap server
+ */
+ public DBVirtualList(IDBRegistry registry, LDAPConnection c,
+ String base, String filter, String attrs[], String sortKey[],
+ int pageSize) throws EBaseException {
+
+ CMS.debug("In DBVirtualList filter attrs sortKey[] pageSize filter: "
+ + filter + " attrs: " + Arrays.toString(attrs)
+ + " pageSize " + pageSize);
+ mRegistry = registry;
+ mFilter = filter;
+ try {
+ mConn = (LDAPConnection) c.clone();
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED",
+ e.toString()));
+ }
+ mBase = base;
+ mAttrs = attrs;
+ mPageControls = new LDAPControl[2];
+ setSortKey(sortKey);
+ setPageSize(pageSize);
+ }
+
+ /**
+ * Constructs a virtual list.
+ *
+ * param registry the registry of attribute mappers
+ * param c the ldap connection. It has to be version 3 and upper
+ * param base the base distinguished name to search from
+ * param filter search filter specifying the search criteria
+ * param attrs list of attributes that you want returned in the search results
+ * param sortKey the attribute to sort by
+ * param pageSize the size of a page. There is a 3*pageSize buffer maintained so
+ * pageUp and pageDown won't invoke fetch from ldap server
+ */
+ public DBVirtualList(IDBRegistry registry, LDAPConnection c,
+ String base, String filter, String attrs[], String sortKey,
+ int pageSize) throws EBaseException {
+
+ CMS.debug("In DBVirtualList filter attrs sortKey pageSize filter: "
+ + filter + " attrs: " + Arrays.toString(attrs)
+ + " pageSize " + pageSize);
+ mRegistry = registry;
+ mFilter = filter;
+ try {
+ mConn = (LDAPConnection) c.clone();
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED",
+ e.toString()));
+ }
+ mBase = base;
+ mAttrs = attrs;
+ mPageControls = new LDAPControl[2];
+ setSortKey(sortKey);
+ setPageSize(pageSize);
+ }
+
+ public DBVirtualList(IDBRegistry registry, LDAPConnection c,
+ String base, String filter, String attrs[],
+ String startFrom, String sortKey,
+ int pageSize) throws EBaseException {
+
+ CMS.debug("In DBVirtualList filter attrs startFrom sortKey pageSize "
+ + "filter: " + filter
+ + " attrs: " + Arrays.toString(attrs)
+ + " pageSize " + pageSize + " startFrom " + startFrom);
+ mRegistry = registry;
+ mFilter = filter;
+ try {
+ mConn = (LDAPConnection) c.clone();
+ } catch (Exception e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED",
+ e.toString()));
+ }
+ mBase = base;
+ mAttrs = attrs;
+ mPageControls = new LDAPControl[2];
+ mJumpTo = startFrom;
+ setSortKey(sortKey);
+ // setPageSize(pageSize);
+
+ if (pageSize < 0) {
+ mJumpToDirection = -1;
+ }
+ mPageSize = pageSize;
+
+ mBeforeCount = 0;
+ mAfterCount = mPageSize;
+ }
+
+ /**
+ * Set the paging size of this virtual list.
+ * The page size here is just a buffer size. A buffer is kept around
+ * that is three times as large as the number of visible entries.
+ * That way, you can scroll up/down several items(up to a page-full)
+ * without refetching entries from the directory.
+ *
+ * @param size the page size
+ */
+ public void setPageSize(int size) {
+
+ if (mJumpTo != null) {
+ return;
+ }
+
+ mPageSize = size;
+ mBeforeCount = 0; //mPageSize;
+ mAfterCount = mPageSize; // mPageSize + mPageSize;
+
+ //CMS.debug("In setPageSize " + size + " mBeforeCount " + mBeforeCount + " mAfterCount " + mAfterCount);
+ }
+
+ /**
+ * set the sort key
+ *
+ * @param sortKey the attribute to sort by
+ */
+ public void setSortKey(String sortKey) throws EBaseException {
+ String keys[] = new String[1];
+
+ keys[0] = sortKey;
+ setSortKey(keys);
+ }
+
+ /**
+ * set the sort key
+ *
+ * @param sortKey the attributes to sort by
+ */
+ public void setSortKey(String[] sortKeys) throws EBaseException {
+ if (sortKeys == null)
+ throw new EBaseException("sort keys cannot be null");
+ try {
+ mKeys = new LDAPSortKey[sortKeys.length];
+ String la[] = null;
+ synchronized (this) {
+ la = mRegistry.getLDAPAttributes(sortKeys);
+ }
+
+ for (int j = 0; j < sortKeys.length; j++) {
+ mKeys[j] = new LDAPSortKey(la[j]);
+ }
+ } catch (Exception e) {
+
+ /*LogDoc
+ *
+ * @phase local ldap search
+ * @reason Failed at setSortKey.
+ * @message DBVirtualList: <exception thrown>
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE,
+ CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+ // Paged results also require a sort control
+ if (mKeys != null) {
+ mPageControls[0] =
+ new LDAPSortControl(mKeys, true);
+ } else {
+ throw new EBaseException("sort keys cannot be null");
+ }
+ }
+
+ /**
+ * Retrieves the size of this virtual list.
+ * Recommend to call getSize() before getElementAt() or getElements()
+ * since you'd better check if the index is out of bound first.
+ */
+ public int getSize() {
+ if (!mInitialized) {
+ mInitialized = true;
+ // Do an initial search to get the virtual list size
+ // Keep one page before and one page after the start
+ if (mJumpTo == null) {
+ mBeforeCount = 0; //mPageSize;
+ mAfterCount = mPageSize; // mPageSize + mPageSize;
+ }
+ // Create the initial paged results control
+ /* Since this one is only used to get the size of the virtual list;
+ we don't care about the starting index. If there is no partial
+ match, the first one before (or after, if none before) is returned
+ as the index entry. Instead of "A", you could use the other
+ constructor and specify 0 both for startIndex and for
+ contentCount. */
+ LDAPVirtualListControl cont = null;
+
+ if (mJumpTo == null) {
+ cont = new LDAPVirtualListControl("A",
+ mBeforeCount,
+ mAfterCount);
+ } else {
+
+ if (mPageSize < 0) {
+ mBeforeCount = mPageSize * -1;
+ mAfterCount = 0;
+ }
+ cont = new LDAPVirtualListControl(mJumpTo,
+ mBeforeCount,
+ mAfterCount);
+ }
+ mPageControls[1] = cont;
+ getJumpToPage();
+ }
+
+ CMS.debug("Getting Virtual List size: " + mSize);
+ return mSize;
+ }
+
+ public int getSizeBeforeJumpTo() {
+
+ if (!mInitialized || mJumpTo == null)
+ return 0;
+
+ int size = 0;
+
+ if (mJumpToDirection < 0) {
+ size = mTop + mEntries.size();
+ } else {
+ size = mTop;
+
+ }
+
+ return size;
+
+ }
+
+ public int getSizeAfterJumpTo() {
+
+ if (!mInitialized || mJumpTo == null)
+ return 0;
+
+ int size = mSize - mTop;
+
+ return size;
+
+ }
+
+ private synchronized boolean getEntries() {
+ // Specify necessary controls for vlist
+ // LDAPSearchConstraints cons = mConn.getSearchConstraints();
+ LDAPSearchConstraints cons = new LDAPSearchConstraints();
+
+ cons.setMaxResults(0);
+ if (mPageControls != null) {
+ cons.setServerControls(mPageControls);
+ //System.out.println( "setting vlist control" );
+ }
+ // Empty the buffer
+ mEntries.removeAllElements();
+ // Do a search
+ try {
+ //what happen if there is no matching?
+ String ldapFilter = mRegistry.getFilter(mFilter);
+ String ldapAttrs[] = null;
+ LDAPSearchResults result;
+
+ if (mAttrs != null) {
+ ldapAttrs = mRegistry.getLDAPAttributes(mAttrs);
+
+ /*
+ LDAPv2.SCOPE_BASE:
+ (search only the base DN)
+ LDAPv2.SCOPE_ONE:
+ (search only entries under the base DN)
+ LDAPv2.SCOPE_SUB:
+ (search the base DN and all entries within its subtree)
+ */
+ result = mConn.search(mBase,
+ LDAPConnection.SCOPE_ONE, ldapFilter, ldapAttrs,
+ false, cons);
+
+ } else {
+ result = mConn.search(mBase,
+ LDAPConnection.SCOPE_ONE, ldapFilter, null,
+ false, cons);
+ }
+ if (result == null) {
+ return false;
+ }
+ int damageCounter = 0;
+
+ while (result.hasMoreElements()) {
+ LDAPEntry entry = (LDAPEntry) result.nextElement();
+
+ try {
+ //maintain mEntries as vector of LDAPEntry
+ @SuppressWarnings("unchecked")
+ E o = (E) mRegistry.createObject(entry.getAttributeSet());
+
+ mEntries.addElement(o);
+ } catch (Exception e) {
+
+ CMS.debug("Exception " + e);
+
+ /*LogDoc
+ *
+ * @phase local ldap search
+ * @reason Failed to get enties.
+ * @message DBVirtualList: <exception thrown>
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_DBS_VL_ADD", e.toString()));
+ // #539044
+ damageCounter++;
+ if (damageCounter > 100) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_DBS_VL_CORRUPTED_ENTRIES", Integer.toString(damageCounter)));
+ return false;
+ }
+ }
+ }
+ } catch (Exception e) {
+
+ /*LogDoc
+ *
+ * @phase local ldap search
+ * @reason Failed to get enties.
+ * @message DBVirtualList: <exception thrown>
+ */
+ CMS.debug("getEntries: exception " + e);
+
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE,
+ CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+ //System.out.println( "Returning " + mEntries.size() +
+ // " entries" );
+
+ CMS.debug("getEntries returning " + mEntries.size());
+ return true;
+ }
+
+ public int getCurrentIndex() {
+ return mTop;
+ }
+
+ private synchronized boolean getJumpToPage() {
+ try {
+ // Get the actual entries
+ if (!getEntries())
+ return false;
+
+ // Check if we have a control returned
+ LDAPControl[] c = mConn.getResponseControls();
+ LDAPVirtualListResponse nextCont = null;
+
+ if (c != null) {
+ for (LDAPControl control : c) {
+ if (control instanceof LDAPVirtualListResponse) {
+ nextCont = (LDAPVirtualListResponse)control;
+ break;
+ }
+ }
+ }
+
+ if (nextCont != null) {
+ mSelectedIndex = nextCont.getFirstPosition() - 1;
+ mTop = Math.max(0, mSelectedIndex - mBeforeCount);
+
+ CMS.debug("mTop " + mTop);
+ if (mJumpTo != null) {
+ mJumpToInitialIndex = mTop;
+ }
+
+ // Now we know the total size of the virtual list box
+ mSize = nextCont.getContentCount();
+ ((LDAPVirtualListControl) mPageControls[1]).setListSize(mSize);
+ mInitialized = true;
+ //System.out.println( "Virtual window: " + mTop +
+ // ".." + (mTop+mEntries.size()-1) +
+ // " of " + mSize );
+ } else {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_DBS_VL_NULL_RESPONSE"));
+ }
+ return true;
+ } catch (Exception e) {
+ // happens when connection is not available
+ return false;
+ }
+ }
+
+ /**
+ * Get a page starting at "first" (although we may also fetch
+ * some preceding entries)
+ * Recommend to call getSize() before getElementAt() or getElements()
+ * since you'd better check if the index is out of bound first.
+ *
+ * @param first the index of the first entry of the page you want to fetch
+ */
+ public boolean getPage(int first) {
+ CMS.debug("getPage " + first);
+ if (!mInitialized) {
+ LDAPVirtualListControl cont = new LDAPVirtualListControl(0,
+ mBeforeCount,
+ mAfterCount, 0);
+
+ mPageControls[1] = cont;
+ }
+
+ //CMS.debug("about to set range first " + first + " mBeforeCount " + mBeforeCount + " mAfterCount " + mAfterCount);
+ ((LDAPVirtualListControl) mPageControls[1]).setRange(first, mBeforeCount, mAfterCount);
+ return getPage();
+ }
+
+ /**
+ * Fetch a buffer
+ */
+ private boolean getPage() {
+ // Get the actual entries
+ if (!getEntries())
+ return false;
+
+ // Check if we have a control returned
+ LDAPControl[] c = mConn.getResponseControls();
+ LDAPVirtualListResponse nextCont = null;
+
+ if (c != null) {
+ for (LDAPControl control : c) {
+ if (control instanceof LDAPVirtualListResponse) {
+ nextCont = (LDAPVirtualListResponse)control;
+ break;
+ }
+ }
+ }
+
+ if (nextCont != null) {
+ mSelectedIndex = nextCont.getFirstPosition() - 1;
+ mTop = Math.max(0, mSelectedIndex - mBeforeCount);
+ //CMS.debug("New mTop: " + mTop + " mSelectedIndex " + mSelectedIndex);
+ // Now we know the total size of the virtual list box
+ mSize = nextCont.getContentCount();
+ ((LDAPVirtualListControl) mPageControls[1]).setListSize(mSize);
+ mInitialized = true;
+ //System.out.println( "Virtual window: " + mTop +
+ // ".." + (mTop+mEntries.size()-1) +
+ // " of " + mSize );
+ } else {
+
+ /*LogDoc
+ *
+ * @phase local ldap search
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_DBS_VL_NULL_RESPONSE"));
+ }
+ return true;
+ }
+
+ /**
+ * Called by application to scroll the list with initial letters.
+ * Consider text to be an initial substring of the attribute of the
+ * primary sorting key(the first one specified in the sort key array)
+ * of an entry.
+ * If no entries match, the one just before(or after, if none before)
+ * will be returned as mSelectedIndex
+ *
+ * @param text the prefix of the first entry of the page you want to fetch
+ */
+ public boolean getPage(String text) {
+ mPageControls[1] =
+ new LDAPVirtualListControl(text,
+ mBeforeCount,
+ mAfterCount);
+ //System.out.println( "Setting requested start to " +
+ // text + ", -" + mBeforeCount + ", +" +
+ // mAfterCount );
+ return getPage();
+ }
+
+ /**
+ * fetch data of a single list item
+ * Recommend to call getSize() before getElementAt() or getElements()
+ * since you'd better check if the index is out of bound first.
+ * If the index is out of range of the virtual list, an exception will be thrown
+ * and return null
+ *
+ * @param index the index of the element to fetch
+ */
+ public E getElementAt(int index) {
+
+ /* mSize may not be init at this time! Bad !
+ * the caller should really check the index is within bound before this
+ * but I'll take care of this just in case they are too irresponsible
+ */
+ if (!mInitialized)
+ mSize = getSize();
+
+ CMS.debug("getElementAt: " + index + " mTop " + mTop);
+
+ //System.out.println( "need entry " + index );
+ if ((index < 0) || (index >= mSize)) {
+ CMS.debug("returning null");
+ return null;
+ }
+
+ if (mJumpTo != null) { //Handle the explicit jumpto case
+
+ if (index == 0)
+ mJumpToIndex = 0; // Keep a running jumpto index for this page of data
+ else
+ mJumpToIndex++;
+
+ //CMS.debug("getElementAtJT: " + index + " mTop " + mTop + " mEntries.size() " + mEntries.size());
+
+ if ((mJumpToDirection > 0) && (mJumpToInitialIndex + index >= mSize)) // out of data in forward paging jumpto case
+ {
+ CMS.debug("mJumpTo virtual list exhausted mTop " + mTop + " mSize " + mSize);
+ return null;
+ }
+
+ if (mJumpToIndex >= mEntries.size()) // In jumpto case, page of data has been exhausted
+ {
+ mJumpToIndex = 0; // new page will be needed reset running count
+
+ if (mJumpToDirection > 0) { //proceed in positive direction past hit point
+ getPage(index + mJumpToInitialIndex + 1);
+ } else { //proceed backwards from hit point
+ if (mTop == 0) {
+ getPage(0);
+ CMS.debug("asking for a page less than zero in reverse case, return null");
+ return null;
+ }
+
+ CMS.debug("getting page reverse mJumptoIndex " + mJumpToIndex + " mTop " + mTop);
+ getPage(mTop);
+
+ }
+
+ }
+
+ if (mJumpToDirection > 0) // handle getting entry in forward direction
+ {
+ return mEntries.elementAt(mJumpToIndex);
+ } else { // handle getting entry in reverse direction
+ int reverse_index = mEntries.size() - mJumpToIndex - 1;
+
+ CMS.debug("reverse direction getting index " + reverse_index);
+
+ if (reverse_index < 0 || reverse_index >= mEntries.size()) {
+ CMS.debug("reverse_index out of range " + reverse_index);
+ return null;
+ }
+ return mEntries.elementAt(reverse_index);
+ }
+ }
+
+ //CMS.debug("getElementAt noJumpto: " + index);
+
+ if ((index < mTop) || (index >= mTop + mEntries.size())) { // handle the non jumpto case
+ //fetch a new page
+ //System.out.println( "fetching a page starting at " +
+ // index );
+ // CMS.debug("getElementAt noJumpto: getting page index: " + index + " mEntries.size() " + mEntries.size() + " mTop: " + mTop);
+ getPage(index);
+ }
+
+ int offset = index - mTop;
+
+ if ((offset < 0) || (offset >= mEntries.size()))
+ //XXX
+ return null; //("No entry at " + index);
+ else
+ return mEntries.elementAt(offset);
+ }
+
+ public E getJumpToElementAt(int i) {
+ return mEntries.elementAt(i);
+ }
+
+ /**
+ * This function processes elements as soon as it arrives. It is
+ * more memory-efficient.
+ */
+ public void processElements(int startidx, int endidx, IElementProcessor ep)
+ throws EBaseException {
+
+ /* mSize may not be init at this time! Bad !
+ * the caller should really check the index is within bound before this
+ * but I'll take care of this just in case they are too irresponsible
+ */
+ if (!mInitialized)
+ mSize = getSize();
+
+ // short-cut the existing code ... :(
+ if (mJumpTo != null) {
+ for (int i = startidx; i <= endidx; i++) {
+ Object element = getJumpToElementAt(i);
+
+ if (element != null)
+ ep.process(element);
+ }
+ return;
+ }
+
+ //guess this is what you really mean to try to improve performance
+ if (startidx >= endidx) {
+ throw new EBaseException("startidx must be less than endidx");
+ } else {
+ setPageSize(endidx - startidx);
+ getPage(startidx);
+ }
+
+ for (int i = startidx; i <= endidx; i++) {
+ Object element = getElementAt(i);
+
+ if (element != null)
+ ep.process(element);
+ }
+ }
+
+ /**
+ * get the virutal selected index
+ */
+ public int getSelectedIndex() {
+ return mSelectedIndex;
+ }
+
+ /**
+ * get the top of the buffer
+ */
+ public int getFirstIndex() {
+ return mTop;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/Database.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/Database.java
new file mode 100644
index 000000000..3df2d5919
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/Database.java
@@ -0,0 +1,77 @@
+// --- 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 com.netscape.cmscore.dbs;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import com.netscape.certsrv.apps.CMS;
+
+/**
+ * This class implements in-memory database.
+ *
+ * @author Endi S. Dewata
+ */
+public class Database<E> {
+
+ public final static int DEFAULT_SIZE = 20;
+
+ public String name;
+
+ public Map<String, E> records = new LinkedHashMap<String, E>();
+
+ public Database(String name) {
+ this.name = name;
+
+ CMS.debug("Initializing " + name + " database");
+ }
+
+ public Collection<E> getRecords() throws Exception {
+ return records.values();
+ }
+
+ public E getRecord(String id) throws Exception {
+ if (!records.containsKey(id)) {
+ throw new Exception(name + " " + id + " does not exist.");
+ }
+ return records.get(id);
+ }
+
+ public void addRecord(String id, E record) throws Exception {
+ if (records.containsKey(id)) {
+ throw new Exception(name + " " + id + " already exists.");
+ }
+ records.put(id, record);
+ }
+
+ public void updateRecord(String id, E record) throws Exception {
+ if (!records.containsKey(id)) {
+ throw new Exception(name + " " + id + " does not exist.");
+ }
+ records.put(id, record);
+ }
+
+ public void removeRecord(String id) throws Exception {
+ if (!records.containsKey(id)) {
+ throw new Exception(name + " " + id + " does not exist.");
+ }
+ records.remove(id);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/DateArrayMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/DateArrayMapper.java
new file mode 100644
index 000000000..99d54be60
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/DateArrayMapper.java
@@ -0,0 +1,110 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+
+/**
+ * A class represents ann attribute mapper that maps
+ * a Java Date array object into LDAP attribute,
+ * and vice versa.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class DateArrayMapper implements IDBAttrMapper {
+
+ private String mLdapName = null;
+ private Vector<String> v = new Vector<String>();
+
+ /**
+ * Constructs a date array mapper.
+ */
+ public DateArrayMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Retrieves a list of support ldap attributes.
+ */
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps object to a set of attributes.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ if (obj == null)
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ Date dates[] = (Date[]) obj;
+
+ LDAPAttribute attr = new LDAPAttribute(mLdapName);
+
+ for (int i = 0; i < dates.length; i++) {
+ attr.addValue(DateMapper.dateToDB(dates[i]));
+ }
+ attrs.add(attr);
+ }
+
+ /**
+ * Maps LDAP attributes into object, and put the object
+ * into 'parent'.
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(mLdapName);
+
+ if (attr == null)
+ return;
+ @SuppressWarnings("unchecked")
+ Enumeration<String> e = attr.getStringValues();
+ Vector<Date> v = new Vector<Date>();
+
+ while (e.hasMoreElements()) {
+ v.addElement(DateMapper.dateFromDB(e.nextElement()));
+ }
+ if (v.size() == 0)
+ return;
+ Date dates[] = new Date[v.size()];
+
+ v.copyInto(dates);
+ parent.set(name, dates);
+ }
+
+ /**
+ * Maps search filters into LDAP search filter.
+ */
+ public String mapSearchFilter(String name, String op,
+ String value) throws EBaseException {
+ return mLdapName + op + value;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/DateMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/DateMapper.java
new file mode 100644
index 000000000..cb287f05e
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/DateMapper.java
@@ -0,0 +1,117 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+
+/**
+ * A class represents ann attribute mapper that maps
+ * a Java Date object into LDAP attribute,
+ * and vice versa.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class DateMapper implements IDBAttrMapper {
+
+ private String mLdapName = null;
+ private Vector<String> v = new Vector<String>();
+ private static SimpleDateFormat formatter = new
+ SimpleDateFormat("yyyyMMddHHmmss'Z'");
+
+ /**
+ * Constructs date mapper.
+ */
+ public DateMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Retrieves a list of ldap attribute names.
+ */
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps object to ldap attribute set.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ attrs.add(new LDAPAttribute(mLdapName,
+ dateToDB((Date) obj)));
+ }
+
+ /**
+ * Maps LDAP attributes into object, and put the object
+ * into 'parent'.
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(mLdapName);
+
+ if (attr == null)
+ return;
+ parent.set(name, dateFromDB((String)
+ attr.getStringValues().nextElement()));
+ }
+
+ /**
+ * Maps search filters into LDAP search filter.
+ */
+ public String mapSearchFilter(String name, String op,
+ String value) throws EBaseException {
+ String val = null;
+
+ try {
+ val = dateToDB(new Date(Long.parseLong(value)));
+ } catch (NumberFormatException e) {
+ val = value;
+ }
+ return mLdapName + op + val;
+ }
+
+ public synchronized static String dateToDB(Date date) {
+ return formatter.format(date);
+ }
+
+ public synchronized static Date dateFromDB(String dbDate) {
+ try {
+ return formatter.parse(dbDate);
+ } catch (ParseException e) {
+ }
+ return null;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/IntegerMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/IntegerMapper.java
new file mode 100644
index 000000000..a50ce99d7
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/IntegerMapper.java
@@ -0,0 +1,93 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+
+/**
+ * A class represents ann attribute mapper that maps
+ * a Java Integer object into LDAP attribute,
+ * and vice versa.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class IntegerMapper implements IDBAttrMapper {
+
+ private String mLdapName = null;
+ private Vector<String> v = new Vector<String>();
+
+ /**
+ * Constructs mapper to deal with Integer.
+ */
+ public IntegerMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Retrieves a list of supported ldap attributes.
+ */
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps object to ldap attribute set.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ attrs.add(new LDAPAttribute(mLdapName,
+ ((Integer) obj).toString()));
+ }
+
+ /**
+ * Maps LDAP attributes into object, and put the object
+ * into 'parent'.
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(mLdapName);
+
+ if (attr == null)
+ return;
+ parent.set(name, new Integer((String)
+ attr.getStringValues().nextElement()));
+ }
+
+ /**
+ * Maps search filters into LDAP search filter.
+ */
+ public String mapSearchFilter(String name, String op,
+ String value) throws EBaseException {
+ return mLdapName + op + value;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyDBSchema.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyDBSchema.java
new file mode 100644
index 000000000..743176318
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyDBSchema.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+/**
+ * A class represents a collection of key record
+ * specific schema information.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class KeyDBSchema {
+
+ public static final String LDAP_OC_TOP = "top";
+ public static final String LDAP_ATTR_SERIALNO = "serialno";
+ public static final String LDAP_ATTR_CREATE_TIME = "dateOfCreate";
+ public static final String LDAP_ATTR_MODIFY_TIME = "dateOfModify";
+ public static final String LDAP_ATTR_META_INFO = "metaInfo";
+ public static final String LDAP_OC_KEYRECORD = "keyRecord";
+ public static final String LDAP_ATTR_OWNER_NAME = "ownerName";
+ public static final String LDAP_ATTR_PRIVATE_KEY_DATA = "privateKeyData";
+ public static final String LDAP_ATTR_KEY_RECORD_ID = "keyRecordId";
+ public static final String LDAP_ATTR_PUBLIC_KEY_DATA = "publicKeyData";
+ public static final String LDAP_ATTR_KEY_SIZE = "keySize";
+ public static final String LDAP_ATTR_ALGORITHM = "algorithm";
+ public static final String LDAP_ATTR_STATE = "keyState";
+ public static final String LDAP_ATTR_DATE_OF_RECOVERY =
+ "dateOfRecovery";
+ public static final String LDAP_ATTR_PUBLIC_KEY_FORMAT =
+ "publicKeyFormat";
+ public static final String LDAP_ATTR_ARCHIVED_BY = "archivedBy";
+ public static final String LDAP_ATTR_CLIENT_ID = "clientId";
+ public static final String LDAP_ATTR_STATUS = "status";
+ public static final String LDAP_ATTR_DATA_TYPE = "dataType";
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecord.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecord.java
new file mode 100644
index 000000000..7ae546184
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecord.java
@@ -0,0 +1,392 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+import com.netscape.certsrv.dbs.keydb.KeyState;
+
+/**
+ * A class represents a Key record. It maintains the key
+ * life cycle as well as other information about an
+ * archived key. Namely, whether a key is inactive because
+ * of compromise.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class KeyRecord implements IDBObj, IKeyRecord {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3765000841161998984L;
+ private BigInteger mSerialNo = null;
+ private KeyState mState = null;
+ private MetaInfo mMetaInfo = null;
+ private String mAlgorithm = null;
+ private byte mPrivateKey[] = null;
+ private byte mPublicKey[] = null;
+ private Integer mSize = null;
+ private String mOwnerName = null;
+ private Date mDatesOfRecovery[] = null;
+ private Date mCreateTime = null;
+ private Date mModifyTime = null;
+ private String mArchivedBy = null;
+ private String mClientId = null;
+ private String mStatus = null;
+ private String mDataType = null;
+
+
+ protected static Vector<String> mNames = new Vector<String>();
+ static {
+ mNames.addElement(ATTR_STATE);
+ mNames.addElement(ATTR_ID);
+ mNames.addElement(ATTR_OWNER_NAME);
+ mNames.addElement(ATTR_KEY_SIZE);
+ mNames.addElement(ATTR_ALGORITHM);
+ mNames.addElement(ATTR_PRIVATE_KEY_DATA);
+ mNames.addElement(ATTR_PUBLIC_KEY_DATA);
+ mNames.addElement(ATTR_DATE_OF_RECOVERY);
+ mNames.addElement(ATTR_META_INFO);
+ mNames.addElement(ATTR_CREATE_TIME);
+ mNames.addElement(ATTR_MODIFY_TIME);
+ mNames.addElement(ATTR_ARCHIVED_BY);
+ mNames.addElement(ATTR_CLIENT_ID);
+ mNames.addElement(ATTR_STATUS);
+ mNames.addElement(ATTR_DATA_TYPE);
+ }
+
+ /**
+ * Constructs empty key record.
+ */
+ public KeyRecord() {
+ }
+
+ /*
+ * Constructs key record.
+ *
+ * @param key key to be archived
+ */
+ public KeyRecord(BigInteger serialNo, byte publicData[],
+ byte privateData[], String owner,
+ String algorithm, String agentId)
+ throws EBaseException {
+ mSerialNo = serialNo;
+ mPublicKey = publicData;
+ mPrivateKey = privateData;
+ mOwnerName = owner;
+ mAlgorithm = algorithm;
+ mState = KeyState.VALID;
+ mCreateTime = com.netscape.certsrv.apps.CMS.getCurrentDate();
+ mModifyTime = com.netscape.certsrv.apps.CMS.getCurrentDate();
+ mArchivedBy = agentId;
+ }
+
+ /**
+ * Sets an attribute.
+ * <P>
+ */
+ public void set(String name, Object object) throws EBaseException {
+ if (name.equalsIgnoreCase(ATTR_STATE)) {
+ mState = (KeyState) object;
+ } else if (name.equalsIgnoreCase(ATTR_ID)) {
+ mSerialNo = (BigInteger) object;
+ } else if (name.equalsIgnoreCase(ATTR_KEY_SIZE)) {
+ mSize = (Integer) object;
+ } else if (name.equalsIgnoreCase(ATTR_OWNER_NAME)) {
+ mOwnerName = (String) object;
+ } else if (name.equalsIgnoreCase(ATTR_ALGORITHM)) {
+ mAlgorithm = (String) object;
+ } else if (name.equalsIgnoreCase(ATTR_PRIVATE_KEY_DATA)) {
+ mPrivateKey = (byte[]) object;
+ } else if (name.equalsIgnoreCase(ATTR_PUBLIC_KEY_DATA)) {
+ mPublicKey = (byte[]) object;
+ } else if (name.equalsIgnoreCase(ATTR_DATE_OF_RECOVERY)) {
+ mDatesOfRecovery = (Date[]) object;
+ } else if (name.equalsIgnoreCase(ATTR_META_INFO)) {
+ mMetaInfo = (MetaInfo) object;
+ } else if (name.equalsIgnoreCase(ATTR_CREATE_TIME)) {
+ mCreateTime = (Date) object;
+ } else if (name.equalsIgnoreCase(ATTR_MODIFY_TIME)) {
+ mModifyTime = (Date) object;
+ } else if (name.equalsIgnoreCase(ATTR_ARCHIVED_BY)) {
+ mArchivedBy = (String) object;
+ } else if (name.equalsIgnoreCase(ATTR_CLIENT_ID)) {
+ mClientId = (String) object;
+ } else if (name.equalsIgnoreCase(ATTR_DATA_TYPE)) {
+ mDataType = (String) object;
+ } else if (name.equalsIgnoreCase(ATTR_STATUS)) {
+ mStatus = (String) object;
+ } else {
+ throw new EBaseException(com.netscape.certsrv.apps.CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+ }
+
+ /**
+ * Retrieves an attribute.
+ * <P>
+ */
+ public Object get(String name) throws EBaseException {
+ if (name.equalsIgnoreCase(ATTR_STATE)) {
+ return mState;
+ } else if (name.equalsIgnoreCase(ATTR_ID)) {
+ return mSerialNo;
+ } else if (name.equalsIgnoreCase(ATTR_KEY_SIZE)) {
+ return mSize;
+ } else if (name.equalsIgnoreCase(ATTR_OWNER_NAME)) {
+ return mOwnerName;
+ } else if (name.equalsIgnoreCase(ATTR_ALGORITHM)) {
+ return mAlgorithm;
+ } else if (name.equalsIgnoreCase(ATTR_PRIVATE_KEY_DATA)) {
+ return mPrivateKey;
+ } else if (name.equalsIgnoreCase(ATTR_PUBLIC_KEY_DATA)) {
+ return mPublicKey;
+ } else if (name.equalsIgnoreCase(ATTR_DATE_OF_RECOVERY)) {
+ return mDatesOfRecovery;
+ } else if (name.equalsIgnoreCase(ATTR_CREATE_TIME)) {
+ return mCreateTime;
+ } else if (name.equalsIgnoreCase(ATTR_MODIFY_TIME)) {
+ return mModifyTime;
+ } else if (name.equalsIgnoreCase(ATTR_META_INFO)) {
+ return mMetaInfo;
+ } else if (name.equalsIgnoreCase(ATTR_ARCHIVED_BY)) {
+ return mArchivedBy;
+ } else if (name.equalsIgnoreCase(ATTR_CLIENT_ID)) {
+ return mClientId;
+ } else if (name.equalsIgnoreCase(ATTR_DATA_TYPE)) {
+ return mDataType;
+ } else if (name.equalsIgnoreCase(ATTR_STATUS)) {
+ return mStatus;
+ } else {
+ throw new EBaseException(com.netscape.certsrv.apps.CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+ }
+
+ /**
+ * Deletes an attribute.
+ * <P>
+ */
+ public void delete(String name) throws EBaseException {
+ throw new EBaseException(com.netscape.certsrv.apps.CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+
+ /**
+ * Retrieves an enumeration of attributes.
+ * <P>
+ */
+ public Enumeration<String> getElements() {
+ return mNames.elements();
+ }
+
+ /**
+ * Retrieves serializable attribute names.
+ */
+ public Enumeration<String> getSerializableAttrNames() {
+ return mNames.elements();
+ }
+
+ /**
+ * Retrieves serial number of the key record. Each key record
+ * is uniquely identified by serial number.
+ * <P>
+ *
+ * @return serial number of this key record
+ */
+ public BigInteger getSerialNumber() throws EBaseException {
+ return mSerialNo;
+ }
+
+ /**
+ * Sets serial number.
+ */
+ public void setSerialNumber(BigInteger serialno) throws EBaseException {
+ mSerialNo = serialno;
+ }
+
+ /**
+ * Retrieves the key state. This gives key life cycle
+ * information.
+ * <P>
+ *
+ * @return key state
+ */
+ public KeyState getState() throws EBaseException {
+ return mState;
+ }
+
+ /**
+ * Sets key state.
+ * <P>
+ */
+ public void setState(KeyState state) throws EBaseException {
+ mState = state;
+ }
+
+ /**
+ * Retrieves the uid of person who archived this record.
+ */
+ public String getArchivedBy() {
+ return mArchivedBy;
+ }
+
+ /**
+ * Retrieves key.
+ * <P>
+ *
+ * @return archived key
+ */
+ public byte[] getPrivateKeyData() throws EBaseException {
+ return mPrivateKey;
+ }
+
+ /**
+ * Sets key data.
+ */
+ public void setPrivateKeyData(byte keydata[]) throws EBaseException {
+ mPrivateKey = keydata;
+ }
+
+ /**
+ * Retrieves the key size.
+ * <P>
+ *
+ * @return key size
+ */
+ public Integer getKeySize() throws EBaseException {
+ return mSize;
+ }
+
+ /**
+ * Retrieves the metaInfo.
+ * <P>
+ *
+ * @return metaInfo
+ */
+ public MetaInfo getMetaInfo() {
+ return mMetaInfo;
+ }
+
+ /**
+ * Sets key size.
+ * <P>
+ */
+ public void setKeySize(Integer keySize) throws EBaseException {
+ mSize = keySize;
+ }
+
+ /**
+ * Retrieves owner name.
+ * <P>
+ */
+ public String getOwnerName() throws EBaseException {
+ return mOwnerName;
+ }
+
+ /**
+ * Sets owner name.
+ * <P>
+ */
+ public void setOwnerName(String name) throws EBaseException {
+ mOwnerName = name;
+ }
+
+ /**
+ * Retrieves the public key.
+ * <P>
+ */
+ public byte[] getPublicKeyData() throws EBaseException {
+ return mPublicKey;
+ }
+
+ /**
+ * Sets the public key.
+ * <P>
+ */
+ public void setPublicKeyData(byte key[]) throws EBaseException {
+ mPublicKey = key;
+ }
+
+ /**
+ * Retrieves the date(s) of revocation.
+ * <P>
+ */
+ public Date[] getDateOfRevocation() throws EBaseException {
+ return mDatesOfRecovery;
+ }
+
+ /**
+ * Sets the dateso of revocation.
+ * <P>
+ */
+ public void setDateOfRevocation(Date dates[]) throws EBaseException {
+ mDatesOfRecovery = dates;
+ }
+
+ /**
+ * Retrieves algorithm of the key pair.
+ */
+ public String getAlgorithm() {
+ return mAlgorithm;
+ }
+
+ /**
+ * Retrieves the creation time of this record.
+ */
+ public Date getCreateTime() {
+ return mCreateTime;
+ }
+
+ /**
+ * Retrieves the last modification time of
+ * this record.
+ */
+ public Date getModifyTime() {
+ return mModifyTime;
+ }
+
+ /**
+ * Retrieves the client ID of this record.
+ */
+ public String getClientId() throws EBaseException {
+ return mClientId ;
+ }
+
+ /**
+ * Retrieves the key status of this record.
+ */
+ public String getKeyStatus() throws EBaseException {
+ return mStatus;
+
+ }
+
+ /**
+ * Retrieves the key data type of this record.
+ */
+ public String getDataType() throws EBaseException {
+ return mDataType;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecordList.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecordList.java
new file mode 100644
index 000000000..732957c25
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecordList.java
@@ -0,0 +1,89 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBVirtualList;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+import com.netscape.certsrv.dbs.keydb.IKeyRecordList;
+
+/**
+ * A class represents a list of key records.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class KeyRecordList implements IKeyRecordList {
+
+ private IDBVirtualList<IKeyRecord> mVlist = null;
+
+ /**
+ * Constructs a key list.
+ */
+ public KeyRecordList(IDBVirtualList<IKeyRecord> vlist) {
+ mVlist = vlist;
+ }
+
+ /**
+ * Retrieves the size of key list.
+ */
+ public int getSize() {
+ return mVlist.getSize();
+ }
+
+ public int getSizeBeforeJumpTo() {
+
+ return mVlist.getSizeBeforeJumpTo();
+
+ }
+
+ public int getSizeAfterJumpTo() {
+
+ return mVlist.getSizeAfterJumpTo();
+ }
+
+ public IKeyRecord getKeyRecord(int i) {
+ IKeyRecord record = mVlist.getElementAt(i);
+
+ if (record == null)
+ return null;
+
+ return record;
+ }
+
+ /**
+ * Retrieves requests.
+ */
+ public Enumeration<IKeyRecord> getKeyRecords(int startidx, int endidx)
+ throws EBaseException {
+ Vector<IKeyRecord> entries = new Vector<IKeyRecord>();
+
+ for (int i = startidx; i <= endidx; i++) {
+ IKeyRecord element = mVlist.getElementAt(i);
+
+ if (element != null) {
+ entries.addElement(element);
+ }
+ }
+ return entries.elements();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecordMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecordMapper.java
new file mode 100644
index 000000000..b124857ca
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecordMapper.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+import com.netscape.certsrv.dbs.keydb.IKeyRepository;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A class represents a mapper to serialize
+ * key record into database.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class KeyRecordMapper implements IDBAttrMapper {
+
+ private IKeyRepository mDB = null;
+ private ILogger mLogger = CMS.getLogger();
+
+ public KeyRecordMapper(IKeyRepository db) {
+ mDB = db;
+ }
+
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(KeyDBSchema.LDAP_ATTR_KEY_RECORD_ID);
+ return v.elements();
+ }
+
+ public void mapObjectToLDAPAttributeSet(IDBObj parent, String name,
+ Object obj, LDAPAttributeSet attrs) throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ try {
+ KeyRecord rec = (KeyRecord) obj;
+
+ attrs.add(new LDAPAttribute(KeyDBSchema.LDAP_ATTR_KEY_RECORD_ID,
+ rec.getSerialNumber().toString()));
+ } catch (Exception e) {
+ /*LogDoc
+ *
+ * @phase Maps object to ldap attribute set
+ * @message KeyRecordMapper: <exception thrown>
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_DBS_KEYRECORD_MAPPER_ERROR", e.toString()));
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ }
+
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ try {
+ LDAPAttribute attr = attrs.getAttribute(
+ KeyDBSchema.LDAP_ATTR_KEY_RECORD_ID);
+
+ if (attr == null)
+ return;
+ String serialno = (String) attr.getStringValues().nextElement();
+ IKeyRecord rec = mDB.readKeyRecord(new
+ BigInteger(serialno));
+
+ parent.set(name, rec);
+ } catch (Exception e) {
+
+ /*LogDoc
+ *
+ * @phase Maps ldap attribute set to object
+ * @message KeyRecordMapper: <exception thrown>
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_DBS_KEYRECORD_MAPPER_ERROR", e.toString()));
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_DESERIALIZE_FAILED", name));
+ }
+ }
+
+ public String mapSearchFilter(String name, String op, String value)
+ throws EBaseException {
+ return name + op + value;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRepository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRepository.java
new file mode 100644
index 000000000..556cab9f5
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRepository.java
@@ -0,0 +1,607 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+import netscape.security.x509.X500Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBRegistry;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSearchResults;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.dbs.keydb.IKeyRecord;
+import com.netscape.certsrv.dbs.keydb.IKeyRecordList;
+import com.netscape.certsrv.dbs.keydb.IKeyRepository;
+import com.netscape.certsrv.dbs.repository.IRepository;
+
+/**
+ * A class represents a Key repository. This is the container of
+ * archived keys.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class KeyRepository extends Repository implements IKeyRepository {
+
+ public KeyStatusUpdateTask mKeyStatusUpdateTask;
+ protected IDBSubsystem mDBService;
+
+ IRepository requestRepository;
+
+ /**
+ * Internal constants
+ */
+ private String mBaseDN = null;
+
+ /**
+ * Constructs a key repository. It checks if the key repository
+ * does exist. If not, it creates the repository.
+ * <P>
+ *
+ * @param service db service
+ * @exception EBaseException failed to setup key repository
+ */
+ public KeyRepository(IDBSubsystem service, int increment, String baseDN)
+ throws EDBException {
+ super(service, increment, baseDN);
+ mBaseDN = baseDN;
+ mDBService = service;
+
+ // register key record schema
+ IDBRegistry reg = service.getRegistry();
+ String keyRecordOC[] = new String[2];
+
+ keyRecordOC[0] = KeyDBSchema.LDAP_OC_TOP;
+ keyRecordOC[1] = KeyDBSchema.LDAP_OC_KEYRECORD;
+
+ if (!reg.isObjectClassRegistered(KeyRecord.class.getName())) {
+ reg.registerObjectClass(KeyRecord.class.getName(),
+ keyRecordOC);
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_ID)) {
+ reg.registerAttribute(KeyRecord.ATTR_ID, new
+ BigIntegerMapper(KeyDBSchema.LDAP_ATTR_SERIALNO));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_ALGORITHM)) {
+ reg.registerAttribute(KeyRecord.ATTR_ALGORITHM, new
+ StringMapper(KeyDBSchema.LDAP_ATTR_ALGORITHM));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_STATE)) {
+ reg.registerAttribute(KeyRecord.ATTR_STATE, new
+ KeyStateMapper(KeyDBSchema.LDAP_ATTR_STATE));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_KEY_SIZE)) {
+ reg.registerAttribute(KeyRecord.ATTR_KEY_SIZE, new
+ IntegerMapper(KeyDBSchema.LDAP_ATTR_KEY_SIZE));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_OWNER_NAME)) {
+ reg.registerAttribute(KeyRecord.ATTR_OWNER_NAME, new
+ StringMapper(KeyDBSchema.LDAP_ATTR_OWNER_NAME));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_PRIVATE_KEY_DATA)) {
+ reg.registerAttribute(KeyRecord.ATTR_PRIVATE_KEY_DATA, new
+ ByteArrayMapper(KeyDBSchema.LDAP_ATTR_PRIVATE_KEY_DATA));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_PUBLIC_KEY_DATA)) {
+ reg.registerAttribute(KeyRecord.ATTR_PUBLIC_KEY_DATA, new
+ PublicKeyMapper(KeyDBSchema.LDAP_ATTR_PUBLIC_KEY_DATA));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_DATE_OF_RECOVERY)) {
+ reg.registerAttribute(KeyRecord.ATTR_DATE_OF_RECOVERY, new
+ DateArrayMapper(KeyDBSchema.LDAP_ATTR_DATE_OF_RECOVERY));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_CREATE_TIME)) {
+ reg.registerAttribute(KeyRecord.ATTR_CREATE_TIME, new
+ DateMapper(KeyDBSchema.LDAP_ATTR_CREATE_TIME));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_MODIFY_TIME)) {
+ reg.registerAttribute(KeyRecord.ATTR_MODIFY_TIME, new
+ DateMapper(KeyDBSchema.LDAP_ATTR_MODIFY_TIME));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_META_INFO)) {
+ reg.registerAttribute(KeyRecord.ATTR_META_INFO, new
+ MetaInfoMapper(KeyDBSchema.LDAP_ATTR_META_INFO));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_ARCHIVED_BY)) {
+ reg.registerAttribute(KeyRecord.ATTR_ARCHIVED_BY, new
+ StringMapper(KeyDBSchema.LDAP_ATTR_ARCHIVED_BY));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_CLIENT_ID)) {
+ reg.registerAttribute(KeyRecord.ATTR_CLIENT_ID, new
+ StringMapper(KeyDBSchema.LDAP_ATTR_CLIENT_ID));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_STATUS)) {
+ reg.registerAttribute(KeyRecord.ATTR_STATUS, new
+ StringMapper(KeyDBSchema.LDAP_ATTR_STATUS));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_DATA_TYPE)) {
+ reg.registerAttribute(KeyRecord.ATTR_DATA_TYPE, new
+ StringMapper(KeyDBSchema.LDAP_ATTR_DATA_TYPE));
+ }
+
+ }
+
+ public void setKeyStatusUpdateInterval(IRepository requestRepo, int interval) {
+
+ CMS.debug("In setKeyStatusUpdateInterval " + interval);
+ synchronized (this) {
+ this.requestRepository = requestRepo;
+ }
+
+ // stop running task
+ if (mKeyStatusUpdateTask != null) {
+ mKeyStatusUpdateTask.stop();
+ }
+
+ // don't run the thread if serial management is disabled.
+ if (interval == 0 || !mDBService.getEnableSerialMgmt()) {
+ CMS.debug("In setKeyStatusUpdateInterval interval = 0");
+ return;
+ }
+
+ CMS.debug("In setKeyStatusUpdateInterval scheduling key status update every " + interval + " seconds.");
+ mKeyStatusUpdateTask = new KeyStatusUpdateTask(this, interval);
+ mKeyStatusUpdateTask.start();
+ }
+
+ /**
+ * This method blocks when another thread is running
+ */
+ public synchronized void updateKeyStatus() {
+ try {
+ CMS.debug("About to start checkRanges");
+
+ CMS.debug("Starting key checkRanges");
+ checkRanges();
+ CMS.debug("key checkRanges done");
+
+ CMS.debug("Starting request checkRanges");
+ requestRepository.checkRanges();
+ CMS.debug("request checkRanges done");
+
+ } catch (Exception e) {
+ CMS.debug("key checkRanges done: " + e.toString());
+ }
+ }
+
+ public IDBSubsystem getDBSubsystem() {
+ return mDBService;
+ }
+
+ /**
+ * Retrieves the DN of this repository.
+ */
+ public String getDN() {
+ return mBaseDN;
+ }
+
+ /**
+ * Removes all objects with this repository.
+ */
+ public void removeAllObjects() throws EBaseException {
+ String filter = "(" + KeyRecord.ATTR_OWNER_NAME + "=*" + ")";
+ IKeyRecordList list = findKeyRecordsInList(filter,
+ null, "serialno", 10);
+ int size = list.getSize();
+ Enumeration<IKeyRecord> e = list.getKeyRecords(0, size - 1);
+ while (e.hasMoreElements()) {
+ IKeyRecord rec = e.nextElement();
+ deleteKeyRecord(rec.getSerialNumber());
+ }
+ }
+
+ /**
+ * Archives a key to the repository.
+ * <P>
+ *
+ * @param record key record
+ * @exception EBaseException failed to archive key
+ */
+ public void addKeyRecord(IKeyRecord record) throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String name = "cn" + "=" +
+ ((KeyRecord) record).getSerialNumber().toString() + "," + getDN();
+
+ if (s != null)
+ s.add(name, (KeyRecord) record);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ /**
+ * Recovers an archived key by serial number.
+ * <P>
+ *
+ * @param serialNo serial number
+ * @return key record
+ * @exception EBaseException failed to recover key
+ */
+ public IKeyRecord readKeyRecord(BigInteger serialNo)
+ throws EBaseException {
+ if (serialNo == null) {
+ throw new EBaseException("Invalid Serial Number.");
+ }
+ IDBSSession s = mDBService.createSession();
+ KeyRecord rec = null;
+
+ try {
+ String name = "cn" + "=" +
+ serialNo.toString() + "," + getDN();
+
+ if (s != null)
+ rec = (KeyRecord) s.read(name);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ if (rec == null) {
+ throw new EBaseException("Failed to recover Key for Serial Number " + serialNo);
+ }
+ return rec;
+ }
+
+ /**
+ * Recovers an archived key by owner name.
+ * <P>
+ *
+ * @param ownerName owner name
+ * @return key record
+ * @exception EBaseException failed to recover key
+ */
+ public IKeyRecord readKeyRecord(X500Name ownerName)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ KeyRecord keyRec = null;
+
+ try {
+ if (ownerName != null) {
+ String filter = "(" + KeyRecord.ATTR_OWNER_NAME + "=" +
+ ownerName.toString() + ")";
+ IDBSearchResults res = s.search(getDN(), filter);
+
+ keyRec = (KeyRecord) res.nextElement();
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return keyRec;
+ }
+
+ /**
+ * Recovers archived key using public key.
+ */
+ public IKeyRecord readKeyRecord(PublicKey publicKey)
+ throws EBaseException {
+ // XXX - setup binary search attributes
+ byte data[] = publicKey.getEncoded();
+
+ if (data == null)
+ throw new EBaseException("null data");
+ IDBSSession s = mDBService.createSession();
+ KeyRecord rec = null;
+
+ try {
+ String filter = "(" + KeyRecord.ATTR_PUBLIC_KEY_DATA + "=" +
+ escapeBinaryData(data) + ")";
+ if (s != null) {
+ IDBSearchResults res = s.search(getDN(), filter);
+
+ rec = (KeyRecord) res.nextElement();
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return rec;
+ }
+
+ /**
+ * Recovers archived key using b64 encoded cert
+ */
+ public IKeyRecord readKeyRecord(String cert)
+ throws EBaseException {
+
+ IDBSSession s = mDBService.createSession();
+ KeyRecord rec = null;
+
+ try {
+ String filter = "(publicKey=x509cert#\"" + cert + "\")";
+ CMS.debug("filter= " + filter);
+
+ if (s != null) {
+ IDBSearchResults res = s.search(getDN(), filter);
+
+ rec = (KeyRecord) res.nextElement();
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return rec;
+ }
+
+ /**
+ * Modifies key record.
+ */
+ public void modifyKeyRecord(BigInteger serialNo, ModificationSet mods)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String name = "cn" + "=" +
+ serialNo.toString() + "," + getDN();
+
+ mods.add(KeyRecord.ATTR_MODIFY_TIME, Modification.MOD_REPLACE,
+ new Date());
+ if (s != null)
+ s.modify(name, mods);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ public void deleteKeyRecord(BigInteger serialNo)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ try {
+ String name = "cn" + "=" +
+ serialNo.toString() + "," + getDN();
+
+ if (s != null)
+ s.delete(name);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ /**
+ * Read RFC-2254
+ */
+ public static String escapeBinaryData(byte data[]) {
+ StringBuffer result = new StringBuffer();
+
+ for (int i = 0; i < data.length; i++) {
+ result.append("\\" + Integer.toHexString(data[i]));
+ }
+ return result.toString();
+ }
+
+ public Enumeration<IKeyRecord> searchKeys(String filter, int maxSize)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Vector<IKeyRecord> v = new Vector<IKeyRecord>();
+
+ try {
+ IDBSearchResults sr = s.search(getDN(), filter, maxSize);
+ while (sr.hasMoreElements()) {
+ v.add((IKeyRecord) sr.nextElement());
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return v.elements();
+ }
+
+ public Enumeration<IKeyRecord> searchKeys(String filter, int maxSize, int timeLimit)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Vector<IKeyRecord> v = new Vector<IKeyRecord>();
+
+ try {
+ IDBSearchResults sr = s.search(getDN(), filter, maxSize, timeLimit);
+ while (sr.hasMoreElements()) {
+ v.add((IKeyRecord) sr.nextElement());
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return v.elements();
+ }
+
+ /**
+ * Retrieves key record list.
+ */
+ public IKeyRecordList findKeyRecordsInList(String filter,
+ String attrs[], int pageSize) throws EBaseException {
+ return findKeyRecordsInList(filter, attrs, IKeyRecord.ATTR_ID,
+ pageSize);
+ }
+
+ public IKeyRecordList findKeyRecordsInList(String filter,
+ String attrs[], String sortKey, int pageSize)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ IKeyRecordList list = null;
+
+ try {
+ if (s != null) {
+ list = new KeyRecordList(
+ s.<IKeyRecord>createVirtualList(getDN(), "(&(objectclass=" +
+ KeyRecord.class.getName() + ")" + filter + ")",
+ attrs, sortKey, pageSize));
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return list;
+ }
+
+ public IKeyRecordList findKeyRecordsInList(String filter,
+ String attrs[], String jumpTo, String sortKey, int pageSize)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ IKeyRecordList list = null;
+
+ int len = jumpTo.length();
+
+ String jumpToVal = null;
+
+ if (len > 9) {
+ jumpToVal = Integer.toString(len) + jumpTo;
+ } else {
+ jumpToVal = "0" + Integer.toString(len) + jumpTo;
+ }
+
+ try {
+ if (s != null) {
+ list = new KeyRecordList(
+ s.<IKeyRecord>createVirtualList(getDN(), "(&(objectclass=" +
+ KeyRecord.class.getName() + ")" + filter + ")",
+ attrs, jumpToVal, sortKey, pageSize));
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return list;
+ }
+
+ public BigInteger getLastSerialNumberInRange(BigInteger serial_low_bound, BigInteger serial_upper_bound) throws
+ EBaseException {
+
+ CMS.debug("KeyRepository: in getLastSerialNumberInRange: low "
+ + serial_low_bound + " high " + serial_upper_bound);
+
+ if (serial_low_bound == null
+ || serial_upper_bound == null || serial_low_bound.compareTo(serial_upper_bound) >= 0) {
+ return null;
+ }
+
+ String ldapfilter = "(" + "serialno" + "=*" + ")";
+ String[] attrs = null;
+
+ KeyRecordList recList =
+ (KeyRecordList) findKeyRecordsInList(ldapfilter, attrs, serial_upper_bound.toString(10), "serialno",
+ 5 * -1);
+
+ int size = -1;
+ if (recList != null) {
+ size = recList.getSize();
+ }
+
+ CMS.debug("KeyRepository: getLastSerialNumberInRange: recList size " + size);
+
+ if (size <= 0) {
+ CMS.debug("KeyRepository: getLastSerialNumberInRange: index may be empty");
+
+ BigInteger ret = new BigInteger(serial_low_bound.toString(10));
+
+ ret = ret.add(new BigInteger("-1"));
+
+ CMS.debug("KeyRepository: getLastSerialNumberInRange returning: " + ret);
+ return ret;
+ }
+ int ltSize = recList.getSizeBeforeJumpTo();
+
+ CMS.debug("KeyRepository:getLastSerialNumberInRange: ltSize " + ltSize);
+
+ int i;
+ KeyRecord curRec = null;
+
+ for (i = 0; i < 5; i++) {
+ curRec = (KeyRecord) recList.getKeyRecord(i);
+
+ if (curRec != null) {
+
+ BigInteger serial = curRec.getSerialNumber();
+
+ CMS.debug("KeyRepository: getLastCertRecordSerialNo: serialno " + serial);
+
+ if (((serial.compareTo(serial_low_bound) == 0) || (serial.compareTo(serial_low_bound) == 1)) &&
+ ((serial.compareTo(serial_upper_bound) == 0) || (serial.compareTo(serial_upper_bound) == -1))) {
+ CMS.debug("KeyRepository: getLastSerialNumberInRange returning: " + serial);
+ return serial;
+ }
+ } else {
+ CMS.debug("KeyRepository: getLastSerialNumberInRange:found null from getCertRecord");
+ }
+ }
+
+ BigInteger ret = new BigInteger(serial_low_bound.toString(10));
+
+ ret = ret.add(new BigInteger("-1"));
+
+ CMS.debug("KeyRepository: getLastSerialNumberInRange returning: " + ret);
+ return ret;
+
+ }
+
+ public void shutdown() {
+ if (mKeyStatusUpdateTask != null) {
+ mKeyStatusUpdateTask.stop();
+ }
+ }
+
+}
+
+class KeyStatusUpdateTask implements Runnable {
+ KeyRepository repository;
+ int interval;
+
+ ScheduledExecutorService executorService;
+
+ public KeyStatusUpdateTask(KeyRepository repository, int interval) {
+ this.repository = repository;
+ this.interval = interval;
+ }
+
+ public void start() {
+ // schedule task to run immediately and repeat after specified interval
+ executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
+ public Thread newThread(Runnable r) {
+ return new Thread(r, "KeyStatusUpdateTask");
+ }
+ });
+ executorService.scheduleWithFixedDelay(this, 0, interval, TimeUnit.SECONDS);
+ }
+
+ public void run() {
+ repository.updateKeyStatus();
+ }
+
+ public void stop() {
+ // shutdown executorService without interrupting running task
+ if (executorService != null) executorService.shutdown();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyStateMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyStateMapper.java
new file mode 100644
index 000000000..02b49b1c8
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyStateMapper.java
@@ -0,0 +1,86 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.dbs.keydb.KeyState;
+
+/**
+ * A class represents a key state mapper.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class KeyStateMapper implements IDBAttrMapper {
+
+ private String mLdapName = null;
+
+ public KeyStateMapper(String ldapName) {
+ mLdapName = ldapName;
+ }
+
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(mLdapName);
+ return v.elements();
+ }
+
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ attrs.add(new LDAPAttribute(mLdapName,
+ ((KeyState) obj).toString()));
+ }
+
+ /**
+ * Maps LDAP attributes into object, and put the object
+ * into 'parent'.
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(mLdapName);
+
+ if (attr == null) {
+ return;
+ }
+ parent.set(name, KeyState.toKeyState(
+ ((String) attr.getStringValues().nextElement())));
+ }
+
+ /**
+ * Maps search filters into LDAP search filter.
+ */
+ public String mapSearchFilter(String name, String op,
+ String value) throws EBaseException {
+ return mLdapName + op + value;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/LDAPDatabase.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/LDAPDatabase.java
new file mode 100644
index 000000000..f6ded787b
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/LDAPDatabase.java
@@ -0,0 +1,171 @@
+package com.netscape.cmscore.dbs;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Enumeration;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.dbs.IDBRegistry;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSearchResults;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+
+/**
+ * This class implements LDAP database.
+ *
+ * @author Endi S. Dewata
+ */
+public abstract class LDAPDatabase<E extends IDBObj> extends Database<E> {
+
+ public IDBSubsystem dbSubsystem;
+ public String baseDN;
+ public Class<E> recordType;
+
+ public LDAPDatabase(String name, IDBSubsystem dbSubsystem, String baseDN, Class<E> recordType) throws EBaseException {
+ super(name);
+
+ this.dbSubsystem = dbSubsystem;
+ this.baseDN = baseDN;
+ this.recordType = recordType;
+
+ register(recordType);
+ }
+
+ public IDBAttrMapper createMapper(Class<?> attrType, DBAttribute dbAttribute) throws EBaseException {
+ String attrName = dbAttribute.value();
+
+ if (attrType == String.class) {
+ return new StringMapper(attrName);
+
+ } else if (attrType == Date.class) {
+ return new DateMapper(attrName);
+
+ } else {
+ // TODO: add other mappers
+ throw new EBaseException("Unsupported attribute type: " + attrType);
+ }
+ }
+
+ public void register(Class<E> recordType) throws EBaseException {
+ IDBRegistry dbRegistry = dbSubsystem.getRegistry();
+
+ // register object classes
+ DBObjectClasses dbObjectClasses = recordType.getAnnotation(DBObjectClasses.class);
+ if (dbObjectClasses == null) {
+ throw new EBaseException("Missing object class mapping in " + recordType.getName());
+ }
+ dbRegistry.registerObjectClass(recordType.getName(), dbObjectClasses.value());
+
+ // register attributes defined in setters/getters
+ for (Method method : recordType.getMethods()) {
+ DBAttribute dbAttribute = method.getAnnotation(DBAttribute.class);
+ if (dbAttribute == null) continue;
+
+ String name = method.getName();
+ if (!name.matches("^set.+") && !name.matches("^get.+")) continue;
+
+ // get attribute name from method name
+ name = Character.toLowerCase(name.charAt(3)) + name.substring(4);
+
+ Class<?> attrType = method.getReturnType();
+ IDBAttrMapper mapper = createMapper(attrType, dbAttribute);
+
+ dbRegistry.registerAttribute(name, mapper);
+ }
+
+ // register attributes defined in fields
+ for (Field field : recordType.getFields()) {
+ DBAttribute dbAttribute = field.getAnnotation(DBAttribute.class);
+ if (dbAttribute == null) continue;
+
+ String name = field.getName();
+ Class<?> attrType = field.getType();
+ IDBAttrMapper mapper = createMapper(attrType, dbAttribute);
+
+ dbRegistry.registerAttribute(name, mapper);
+ }
+ }
+
+ public abstract String createDN(String id);
+ public abstract String createFilter(String filter);
+
+ @Override
+ public Collection<E> getRecords() throws Exception {
+ CMS.debug("LDAPDatabase: getRecords()");
+
+ try (IDBSSession session = dbSubsystem.createSession()) {
+ Collection<E> list = new ArrayList<E>();
+
+ CMS.debug("LDAPDatabase: searching " + baseDN);
+ IDBSearchResults results = session.search(baseDN, createFilter(null));
+
+ while (results.hasMoreElements()) {
+ @SuppressWarnings("unchecked")
+ E result = (E)results.nextElement();
+ list.add(result);
+ }
+
+ return list;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public E getRecord(String id) throws Exception {
+ CMS.debug("LDAPDatabase: getRecord(\"" + id + "\")");
+ try (IDBSSession session = dbSubsystem.createSession()) {
+ String dn = createDN(id);
+ CMS.debug("LDAPDatabase: reading " + baseDN);
+ return (E)session.read(dn);
+ }
+ }
+
+ @Override
+ public void addRecord(String id, E record) throws Exception {
+ CMS.debug("LDAPDatabase: addRecord(\"" + id + "\")");
+ try (IDBSSession session = dbSubsystem.createSession()) {
+ String dn = createDN(id);
+
+ CMS.debug("LDAPDatabase: adding " + dn);
+ session.add(dn, record);
+ }
+ }
+
+ @Override
+ public void updateRecord(String id, E record) throws Exception {
+ CMS.debug("LDAPDatabase: updateRecord(\"" + id + "\")");
+ try (IDBSSession session = dbSubsystem.createSession()) {
+ String dn = createDN(id);
+
+ ModificationSet mods = new ModificationSet();
+ for (Enumeration<String> names = record.getSerializableAttrNames(); names.hasMoreElements(); ) {
+ String name = names.nextElement();
+ Object value = record.get(name);
+ mods.add(name, Modification.MOD_REPLACE, value);
+ }
+
+ CMS.debug("LDAPDatabase: modifying " + dn);
+ session.modify(dn, mods);
+ }
+ }
+
+ @Override
+ public void removeRecord(String id) throws Exception {
+ CMS.debug("LDAPDatabase: removeRecord(\"" + id + "\")");
+ try (IDBSSession session = dbSubsystem.createSession()) {
+ String dn = createDN(id);
+
+ CMS.debug("LDAPDatabase: removing " + dn);
+ session.delete(dn);
+ }
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/LdapFilterConverter.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/LdapFilterConverter.java
new file mode 100644
index 000000000..e31cf1019
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/LdapFilterConverter.java
@@ -0,0 +1,62 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Hashtable;
+
+import com.netscape.certsrv.base.AttributeNameHelper;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IFilterConverter;
+
+/**
+ * A class represents a filter converter
+ * that understands how to convert a attribute
+ * type from one defintion to another.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class LdapFilterConverter implements IFilterConverter {
+
+ private Hashtable<String, IDBAttrMapper> mReg = null;
+
+ /**
+ * Constructs filter convertor.
+ */
+ public LdapFilterConverter(Hashtable<String, IDBAttrMapper> reg) {
+ mReg = reg;
+ }
+
+ /**
+ * Converts database filter to ldap filter.
+ */
+ public String convert(String name, String op, String value) {
+ AttributeNameHelper h = new AttributeNameHelper(name);
+ IDBAttrMapper mapper = mReg.get(
+ h.getPrefix().toLowerCase());
+
+ if (mapper == null)
+ return null;
+ try {
+ return mapper.mapSearchFilter(name, op, value);
+ } catch (EBaseException e) {
+ }
+ return null;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/LongMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/LongMapper.java
new file mode 100644
index 000000000..3c066ca43
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/LongMapper.java
@@ -0,0 +1,123 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+
+/**
+ * A class represents ann attribute mapper that maps
+ * a Java Long object into LDAP attribute,
+ * and vice versa.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class LongMapper implements IDBAttrMapper {
+
+ private String mLdapName = null;
+ private Vector<String> v = new Vector<String>();
+
+ /**
+ * Constructs Long mapper.
+ */
+ public LongMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Returns a list of supported ldap attribute names.
+ */
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps object into ldap attribute set.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ attrs.add(new LDAPAttribute(mLdapName,
+ LongToDB((Long) obj)));
+ }
+
+ /**
+ * Maps LDAP attributes into object, and put the object
+ * into 'parent'.
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(mLdapName);
+
+ if (attr == null)
+ return;
+ parent.set(name, LongFromDB(
+ (String) attr.getStringValues().nextElement()));
+ }
+
+ /**
+ * Maps search filters into LDAP search filter.
+ */
+ public String mapSearchFilter(String name, String op,
+ String value) throws EBaseException {
+ String v = null;
+
+ try {
+ if (value.startsWith("0x") || value.startsWith("0X")) {
+ v = LongToDB(Long.valueOf(value.substring(2), 16));
+ } else {
+ v = LongToDB(Long.valueOf(value));
+ }
+ } catch (NumberFormatException e) {
+ v = value;
+ }
+ return mLdapName + op + v;
+ }
+
+ public static String LongToDB(Long i) {
+ int len = i.toString().length();
+ String ret = null;
+
+ if (len < 10) {
+ ret = "0" + Integer.toString(len) + i.toString();
+ } else {
+ ret = Integer.toString(len) + i.toString();
+ }
+ return ret;
+ }
+
+ public static Long LongFromDB(String i) {
+ String s = i.substring(2);
+
+ // possibly check length
+ return new Long(s);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/MetaInfoMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/MetaInfoMapper.java
new file mode 100644
index 000000000..f4913b936
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/MetaInfoMapper.java
@@ -0,0 +1,128 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+
+/**
+ * A class represent mapper for metainfo attribute. Metainfo
+ * is in format of the following:
+ *
+ * <PRE>
+ * metaInfoType:metaInfoValue
+ * metaInfoType:metaInfoValue
+ * metaInfoType:metaInfoValue
+ * metaInfoType:metaInfoValue
+ * </PRE>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class MetaInfoMapper implements IDBAttrMapper {
+
+ public static final String SEP = ":";
+
+ private String mLdapName = null;
+ private Vector<String> v = new Vector<String>();
+
+ /**
+ * Constructs a metainfo object.
+ */
+ public MetaInfoMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Returns a list of supported ldap attribute names.
+ */
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps object into ldap attribute set.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ MetaInfo info = (MetaInfo) obj;
+ Enumeration<String> e = info.getElements();
+
+ if (!e.hasMoreElements())
+ return; // dont add anything
+ LDAPAttribute attr = new LDAPAttribute(mLdapName);
+
+ while (e.hasMoreElements()) {
+ String s = null;
+ String attrName = e.nextElement();
+ String value = (String) info.get(attrName);
+
+ s = attrName + SEP + value;
+ attr.addValue(s);
+ }
+ attrs.add(attr);
+ }
+
+ /**
+ * Maps LDAP attributes into object, and put the object into
+ * 'parent'.
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(mLdapName);
+
+ if (attr == null)
+ return;
+ @SuppressWarnings("unchecked")
+ Enumeration<String> values = attr.getStringValues();
+ MetaInfo info = new MetaInfo();
+
+ while (values.hasMoreElements()) {
+ String s = values.nextElement();
+ StringTokenizer st = new StringTokenizer(s, SEP);
+
+ info.set(st.nextToken(), st.nextToken());
+ }
+ parent.set(name, info);
+ }
+
+ /**
+ * Map search filters into LDAP search filter.
+ * Possible search filter:
+ * (&(metaInfo=reserver0:value0)(metaInfo=reserved1:value1))
+ */
+ public String mapSearchFilter(String name, String op,
+ String value) throws EBaseException {
+ return mLdapName + op + value;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/ObjectStreamMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/ObjectStreamMapper.java
new file mode 100644
index 000000000..5c61d36af
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/ObjectStreamMapper.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A class represents ann attribute mapper that maps
+ * a Java object into LDAP attribute,
+ * and vice versa.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class ObjectStreamMapper implements IDBAttrMapper {
+
+ private String mLdapName = null;
+ private Vector<String> v = new Vector<String>();
+ private ILogger mLogger = CMS.getLogger();
+
+ /**
+ * Constructs object stream mapper.
+ */
+ public ObjectStreamMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Retrieves a list of supported ldap attributes.
+ */
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps object to ldap attribute set.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent, String name,
+ Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ try {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream os = new ObjectOutputStream(bos);
+
+ os.writeObject(obj);
+ byte data[] = bos.toByteArray();
+ if (data == null) {
+ CMS.debug("ObjectStreamMapper:mapObjectToLDAPAttributeSet " +
+ name + " size=0");
+ } else {
+ CMS.debug("ObjectStreamMapper:mapObjectToLDAPAttributeSet " +
+ name + " size=" + data.length);
+ }
+ attrs.add(new LDAPAttribute(mLdapName, data));
+ } catch (IOException e) {
+
+ /*LogDoc
+ *
+ * @phase Maps object to ldap attribute set
+ * @message ObjectStreamMapper: <exception thrown>
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_DBS_OBJECTSTREAM_MAPPER_ERROR",
+ e.toString()));
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ }
+
+ /**
+ * Maps LDAP attributes into object, and put the object
+ * into 'parent'.
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ try {
+ LDAPAttribute attr = attrs.getAttribute(mLdapName);
+
+ if (attr == null) {
+ return;
+ }
+ ByteArrayInputStream bis = new ByteArrayInputStream(
+ (byte[]) attr.getByteValues().nextElement());
+ ObjectInputStream is = new ObjectInputStream(bis);
+
+ parent.set(name, is.readObject());
+ } catch (IOException e) {
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_DESERIALIZE_FAILED", name));
+ } catch (ClassNotFoundException e) {
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_DESERIALIZE_FAILED", name));
+ }
+ }
+
+ /**
+ * Maps search filters into LDAP search filter.
+ */
+ public String mapSearchFilter(String name, String op,
+ String value) throws EBaseException {
+ return mLdapName + op + value;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/PublicKeyMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/PublicKeyMapper.java
new file mode 100644
index 000000000..8a4dbc77d
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/PublicKeyMapper.java
@@ -0,0 +1,136 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmscore.cert.CertUtils;
+
+/**
+ * A class represents an attribute mapper that maps
+ * a public key data into LDAP attribute and
+ * vice versa.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class PublicKeyMapper implements IDBAttrMapper {
+
+ private String mLdapName = null;
+ private Vector<String> v = new Vector<String>();
+
+ private ILogger mLogger = CMS.getLogger();
+
+ /**
+ * Constructs a byte array mapper.
+ */
+ public PublicKeyMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Lists a list of supported ldap attribute names.
+ */
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps object to ldap attribute set.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ attrs.add(new LDAPAttribute(mLdapName, (byte[]) obj));
+ }
+
+ /**
+ * Maps LDAP attributes into object, and put the object
+ * into 'parent'.
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(mLdapName);
+
+ if (attr == null) {
+ return;
+ }
+ parent.set(name, attr.getByteValues().nextElement());
+ }
+
+ /**
+ * Maps search filters into LDAP search filter. It knows
+ * how to extract public key from the certificate.
+ */
+ public String mapSearchFilter(String name, String op,
+ String value) throws EBaseException {
+ int i = value.indexOf("#");
+
+ if (i != -1) {
+ //String tag = value.substring(0, i);
+ String val = value.substring(i + 1);
+
+ try {
+ if (val.startsWith("\"")) {
+ val = val.substring(1, val.length() - 1);
+ }
+ X509Certificate cert = CertUtils.mapCert(val);
+ PublicKey key = cert.getPublicKey();
+ byte pub[] = key.getEncoded();
+
+ return mLdapName + op + escapeBinaryData(pub);
+ } catch (Exception e) {
+
+ /*LogDoc
+ *
+ * @phase Maps search filters into LDAP search filter
+ * @message PublicKeyMapper: <exception thrown>
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_DBS_PUBLICKEY_MAPPER_ERROR",
+ e.toString()));
+ }
+ }
+ return mLdapName + op + value;
+ }
+
+ public static String escapeBinaryData(byte data[]) {
+ StringBuffer result = new StringBuffer();
+
+ for (int i = 0; i < data.length; i++) {
+ int v = 0xff & data[i];
+
+ result.append("\\" + (v < 16 ? "0" : "") +
+ Integer.toHexString(v));
+ }
+ return result.toString();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/ReplicaIDRepository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/ReplicaIDRepository.java
new file mode 100644
index 000000000..5a6a61d20
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/ReplicaIDRepository.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.math.BigInteger;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.replicadb.IReplicaIDRepository;
+
+/**
+ * A class represents a replica repository. It
+ * creates unique managed replica IDs.
+ * <P>
+ *
+ * @author alee
+ * @version $Revision$, $Date$
+ */
+public class ReplicaIDRepository extends Repository
+ implements IReplicaIDRepository {
+
+ private IDBSubsystem mDBService;
+ private String mBaseDN;
+
+ /**
+ * Constructs a certificate repository.
+ */
+ public ReplicaIDRepository(IDBSubsystem dbService, int increment, String baseDN)
+ throws EDBException {
+ super(dbService, increment, baseDN);
+ mBaseDN = baseDN;
+ mDBService = dbService;
+ }
+
+ /**
+ * Returns last serial number in given range
+ */
+ public BigInteger getLastSerialNumberInRange(BigInteger serial_low_bound, BigInteger serial_upper_bound)
+ throws EBaseException {
+ CMS.debug("ReplicaIDReposoitory: in getLastSerialNumberInRange: low "
+ + serial_low_bound + " high " + serial_upper_bound);
+ if (serial_low_bound == null
+ || serial_upper_bound == null || serial_low_bound.compareTo(serial_upper_bound) >= 0) {
+ return null;
+ }
+ BigInteger ret = new BigInteger(getMinSerial());
+ if ((ret == null) || (ret.compareTo(serial_upper_bound) > 0) || (ret.compareTo(serial_low_bound) < 0)) {
+ return null;
+ }
+ return ret;
+ }
+
+ /**
+ * Retrieves DN of this repository.
+ */
+ public String getDN() {
+ return mBaseDN;
+ }
+
+ /**
+ * Retrieves backend database handle.
+ */
+ public IDBSubsystem getDBSubsystem() {
+ return mDBService;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
new file mode 100644
index 000000000..e6b6e831e
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
@@ -0,0 +1,539 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.math.BigInteger;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.dbs.keydb.IKeyRepository;
+import com.netscape.certsrv.dbs.replicadb.IReplicaIDRepository;
+import com.netscape.certsrv.dbs.repository.IRepository;
+import com.netscape.certsrv.dbs.repository.IRepositoryRecord;
+
+/**
+ * A class represents a generic repository. It maintains unique
+ * serial number within repository.
+ * <P>
+ * To build domain specific repository, subclass should be created.
+ * <P>
+ *
+ * @author galperin
+ * @author thomask
+ * @version $Revision: 1.4
+ *
+ * $, $Date$
+ */
+
+public abstract class Repository implements IRepository {
+
+ private BigInteger BI_INCREMENT = null;
+ // (the next serialNo to be issued) - 1
+ private BigInteger mSerialNo = null;
+ // the serialNo attribute stored in db
+ private BigInteger mNext = null;
+
+ private String mMaxSerial = null;
+ private String mMinSerial = null;
+ private String mNextMaxSerial = null;
+ private String mNextMinSerial = null;
+
+ protected boolean mEnableRandomSerialNumbers = false;
+ protected BigInteger mCounter = null;
+ protected BigInteger mMinSerialNo = null;
+ protected BigInteger mMaxSerialNo = null;
+ private BigInteger mNextMinSerialNo = null;
+ private BigInteger mNextMaxSerialNo = null;
+
+ private BigInteger mIncrementNo = null;
+ private BigInteger mLowWaterMarkNo = null;
+
+ private IDBSubsystem mDB = null;
+ private String mBaseDN = null;
+ private boolean mInit = false;
+ private int mRadix = 10;
+ private int mRepo = -1;
+
+ private BigInteger mLastSerialNo = null;
+
+ /**
+ * Constructs a repository.
+ * <P>
+ */
+ public Repository(IDBSubsystem db, int increment, String baseDN)
+ throws EDBException {
+ mDB = db;
+ mBaseDN = baseDN;
+
+ BI_INCREMENT = new BigInteger(Integer.toString(increment));
+
+ /*
+ // register schema
+ IDBRegistry reg = db.getRegistry();
+ if (!reg.isObjectClassRegistered(RepositoryRecord.class.getName())) {
+ String repRecordOC[] = new String[2];
+ repRecordOC[0] = RepositorySchema.LDAP_OC_TOP;
+ repRecordOC[1] = RepositorySchema.LDAP_OC_REPOSITORY;
+ reg.registerObjectClass(RepositoryRecord.class.getName(), repRecordOC);
+ }
+ if (!reg.isAttributeRegistered(RepositoryRecord.ATTR_SERIALNO)) {
+ reg.registerAttribute(RepositoryRecord.ATTR_SERIALNO,
+ new BigIntegerMapper(RepositorySchema.LDAP_ATTR_SERIALNO));
+ }
+ */
+ }
+
+ /**
+ * Resets serial number.
+ */
+ public void resetSerialNumber(BigInteger serial) throws EBaseException {
+ IDBSSession s = mDB.createSession();
+
+ try {
+ String name = mBaseDN;
+ ModificationSet mods = new ModificationSet();
+ mods.add(IRepositoryRecord.ATTR_SERIALNO,
+ Modification.MOD_REPLACE, serial);
+ s.modify(name, mods);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ /**
+ * Retrieves the next serial number attr in db.
+ * <P>
+ *
+ * @return next serial number
+ */
+ protected BigInteger getSerialNumber() throws EBaseException {
+ IDBSSession s = mDB.createSession();
+
+ CMS.debug("Repository: getSerialNumber.");
+ RepositoryRecord rec = null;
+
+ try {
+ if (s != null)
+ rec = (RepositoryRecord) s.read(mBaseDN);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+
+ if (rec == null) {
+ CMS.debug("Repository::getSerialNumber() - "
+ + "- rec is null!");
+ throw new EBaseException("rec is null");
+ }
+
+ BigInteger serial = rec.getSerialNumber();
+ CMS.debug("Repository: getSerialNumber serial="+serial);
+
+ if (!mInit) {
+ // cms may crash after issue a cert but before update
+ // the serial number record
+ try {
+ IDBObj obj = s.read("cn=" +
+ serial + "," + mBaseDN);
+
+ if (obj != null) {
+ serial = serial.add(BigInteger.ONE);
+ setSerialNumber(serial);
+ }
+ } catch (EBaseException e) {
+ // do nothing
+ }
+ mInit = true;
+ }
+ return serial;
+ }
+
+ /**
+ * Updates the serial number to the specified in db.
+ * <P>
+ *
+ * @param num serial number
+ */
+ protected void setSerialNumber(BigInteger num) throws EBaseException {
+
+ CMS.debug("Repository:setSerialNumber " + num.toString());
+
+ return;
+
+ }
+
+ /**
+ * Get the maximum serial number.
+ *
+ * @return maximum serial number
+ */
+ public String getMaxSerial() {
+ return mMaxSerial;
+ }
+
+ /**
+ * Set the maximum serial number.
+ *
+ * @param serial maximum number
+ * @exception EBaseException failed to set maximum serial number
+ */
+ public void setMaxSerial(String serial) throws EBaseException {
+ BigInteger maxSerial = null;
+ CMS.debug("Repository:setMaxSerial " + serial);
+
+ maxSerial = new BigInteger(serial, mRadix);
+ if (maxSerial != null) {
+ mMaxSerial = serial;
+ mMaxSerialNo = maxSerial;
+ }
+ }
+
+ /**
+ * Get the maximum serial number in next range.
+ *
+ * @return maximum serial number in next range
+ */
+ public String getNextMaxSerial() {
+ return mNextMaxSerial;
+ }
+
+ /**
+ * Set the maximum serial number in next range
+ *
+ * @param serial maximum number in next range
+ * @exception EBaseException failed to set maximum serial number in next range
+ */
+ public void setNextMaxSerial(String serial) throws EBaseException {
+ BigInteger maxSerial = null;
+ CMS.debug("Repository:setNextMaxSerial " + serial);
+
+ maxSerial = new BigInteger(serial, mRadix);
+ if (maxSerial != null) {
+ mNextMaxSerial = serial;
+ mNextMaxSerialNo = maxSerial;
+ }
+
+ return;
+ }
+
+ /**
+ * Get the minimum serial number.
+ *
+ * @return minimum serial number
+ */
+ public String getMinSerial() {
+ return mMinSerial;
+ }
+
+ protected void setLastSerialNo(BigInteger lastSN) {
+ mLastSerialNo = lastSN;
+ }
+
+ /**
+ * init serial number cache
+ */
+ private void initCache() throws EBaseException {
+ mNext = getSerialNumber();
+ mRadix = 10;
+
+ CMS.debug("Repository: in InitCache");
+
+ if (this instanceof ICertificateRepository) {
+ CMS.debug("Repository: Instance of Certificate Repository.");
+ mRadix = 16;
+ mRepo = IDBSubsystem.CERTS;
+ } else if (this instanceof IKeyRepository) {
+ // Key Repository uses the same configuration parameters as Certificate
+ // Repository. This is ok because they are on separate subsystems.
+ CMS.debug("Repository: Instance of Key Repository");
+ mRadix = 16;
+ mRepo = IDBSubsystem.CERTS;
+ } else if (this instanceof IReplicaIDRepository) {
+ CMS.debug("Repository: Instance of Replica ID repository");
+ mRepo = IDBSubsystem.REPLICA_ID;
+ } else {
+ // CRLRepository subclasses this too, but does not use serial number stuff
+ CMS.debug("Repository: Instance of Request Repository or CRLRepository.");
+ mRepo = IDBSubsystem.REQUESTS;
+ }
+
+ mMinSerial = mDB.getMinSerialConfig(mRepo);
+ mMaxSerial = mDB.getMaxSerialConfig(mRepo);
+ mNextMinSerial = mDB.getNextMinSerialConfig(mRepo);
+ mNextMaxSerial = mDB.getNextMaxSerialConfig(mRepo);
+ String increment = mDB.getIncrementConfig(mRepo);
+ String lowWaterMark = mDB.getLowWaterMarkConfig(mRepo);
+
+ CMS.debug("Repository: minSerial:" + mMinSerial + " maxSerial: " + mMaxSerial);
+ CMS.debug("Repository: nextMinSerial: " + ((mNextMinSerial == null)?"":mNextMinSerial) +
+ " nextMaxSerial: " + ((mNextMaxSerial == null)?"":mNextMaxSerial));
+ CMS.debug("Repository: increment:" + increment + " lowWaterMark: " + lowWaterMark);
+
+ if (mMinSerial != null)
+ mMinSerialNo = new BigInteger(mMinSerial, mRadix);
+
+ if (mMaxSerial != null)
+ mMaxSerialNo = new BigInteger(mMaxSerial, mRadix);
+
+ if (mNextMinSerial != null)
+ mNextMinSerialNo = new BigInteger(mNextMinSerial, mRadix);
+
+ if (mNextMaxSerial != null)
+ mNextMaxSerialNo = new BigInteger(mNextMaxSerial, mRadix);
+
+ if (lowWaterMark != null)
+ mLowWaterMarkNo = new BigInteger(lowWaterMark, mRadix);
+
+ if (increment != null)
+ mIncrementNo = new BigInteger(increment, mRadix);
+
+ BigInteger theSerialNo = null;
+ theSerialNo = getLastSerialNumberInRange(mMinSerialNo, mMaxSerialNo);
+
+ if (theSerialNo != null) {
+
+ mLastSerialNo = new BigInteger(theSerialNo.toString());
+ CMS.debug("Repository: mLastSerialNo: " + mLastSerialNo.toString());
+
+ } else {
+
+ throw new EBaseException("Error in obtaining the last serial number in the repository!");
+
+ }
+
+ }
+
+ protected void initCacheIfNeeded() throws EBaseException {
+ if (mLastSerialNo == null)
+ initCache();
+ }
+
+ /**
+ * get the next serial number in cache
+ */
+ public BigInteger getTheSerialNumber() throws EBaseException {
+
+ CMS.debug("Repository:In getTheSerialNumber ");
+ if (mLastSerialNo == null)
+ initCache();
+ BigInteger serial = mLastSerialNo.add(BigInteger.ONE);
+
+ if (mMaxSerialNo != null && serial.compareTo(mMaxSerialNo) > 0)
+ return null;
+ else
+ return serial;
+ }
+
+ /**
+ * Updates the serial number to the specified in db and cache.
+ * <P>
+ *
+ * @param num serial number
+ */
+ public void setTheSerialNumber(BigInteger num) throws EBaseException {
+ // mSerialNo is already set. But just in case
+
+ CMS.debug("Repository:In setTheSerialNumber " + num.toString());
+ if (mLastSerialNo == null)
+ initCache();
+
+ if (num.compareTo(mSerialNo) <= 0) {
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_SETBACK_SERIAL",
+ mSerialNo.toString(16)));
+ }
+ // write the config parameter. It's needed in case the serialNum gap
+ // < BI_INCREMENT and server restart right afterwards.
+ mDB.setNextSerialConfig(num);
+
+ mSerialNo = num.subtract(BigInteger.ONE);
+ mNext = num.add(BI_INCREMENT);
+ setSerialNumber(mNext);
+ }
+
+ /**
+ * Retrieves the next serial number, and also increase the
+ * serial number by one.
+ * <P>
+ *
+ * @return serial number
+ */
+ public synchronized BigInteger getNextSerialNumber() throws
+ EBaseException {
+
+ CMS.debug("Repository: in getNextSerialNumber. ");
+
+ if (mLastSerialNo == null) {
+ initCache();
+ }
+ if (mLastSerialNo == null) {
+ CMS.debug("Repository::getNextSerialNumber() " +
+ "- mLastSerialNo is null!");
+ throw new EBaseException("mLastSerialNo is null");
+ }
+
+ mLastSerialNo = mLastSerialNo.add(BigInteger.ONE);
+
+ checkRange();
+
+ BigInteger retSerial = new BigInteger(mLastSerialNo.toString());
+
+ CMS.debug("Repository: getNextSerialNumber: returning retSerial " + retSerial);
+ return retSerial;
+ }
+
+ /**
+ * Checks to see if range needs to be switched.
+ *
+ * @exception EBaseException thrown when next range is not allocated
+ */
+ protected void checkRange() throws EBaseException
+ {
+ // check if we have reached the end of the range
+ // if so, move to next range
+ BigInteger randomLimit = null;
+ BigInteger rangeLength = null;
+ if ((this instanceof ICertificateRepository) &&
+ mDB.getEnableSerialMgmt() && mEnableRandomSerialNumbers) {
+ rangeLength = mMaxSerialNo.subtract(mMinSerialNo).add(BigInteger.ONE);
+ randomLimit = rangeLength.subtract(mLowWaterMarkNo.shiftRight(1));
+ CMS.debug("Repository: checkRange rangeLength="+rangeLength);
+ CMS.debug("Repository: checkRange randomLimit="+randomLimit);
+ }
+ CMS.debug("Repository: checkRange mLastSerialNo="+mLastSerialNo);
+ if (mLastSerialNo.compareTo( mMaxSerialNo ) > 0 ||
+ ((!CMS.isPreOpMode()) && randomLimit != null && mCounter.compareTo(randomLimit) > 0)) {
+
+ if (mDB.getEnableSerialMgmt()) {
+ CMS.debug("Reached the end of the range. Attempting to move to next range");
+ if ((mNextMinSerialNo == null) || (mNextMaxSerialNo == null)) {
+ if (rangeLength != null && mCounter.compareTo(rangeLength) < 0) {
+ return;
+ } else {
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_LIMIT_REACHED",
+ mLastSerialNo.toString()));
+ }
+ }
+ mMinSerialNo = mNextMinSerialNo;
+ mMaxSerialNo = mNextMaxSerialNo;
+ mLastSerialNo = mMinSerialNo;
+ mNextMinSerialNo = null;
+ mNextMaxSerialNo = null;
+ mCounter = BigInteger.ZERO;
+
+ // persist the changes
+ mDB.setMinSerialConfig(mRepo, mMinSerialNo.toString(mRadix));
+ mDB.setMaxSerialConfig(mRepo, mMaxSerialNo.toString(mRadix));
+ mDB.setNextMinSerialConfig(mRepo, null);
+ mDB.setNextMaxSerialConfig(mRepo, null);
+ } else {
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_LIMIT_REACHED",
+ mLastSerialNo.toString()));
+ }
+ }
+ }
+
+ /**
+ * Checks to see if a new range is needed, or if we have reached the end of the
+ * current range, or if a range conflict has occurred.
+ *
+ * @exception EBaseException failed to check next range for conflicts
+ */
+ public void checkRanges() throws EBaseException {
+ if (!mDB.getEnableSerialMgmt()) {
+ CMS.debug("Serial Management not enabled. Returning .. ");
+ return;
+ }
+ if (CMS.getEESSLPort() == null) {
+ CMS.debug("Server not completely started. Returning ..");
+ return;
+ }
+
+ if (mLastSerialNo == null)
+ initCache();
+
+ BigInteger numsInRange = null;
+ if ((this instanceof ICertificateRepository) &&
+ mDB.getEnableSerialMgmt() && mEnableRandomSerialNumbers) {
+ numsInRange = (mMaxSerialNo.subtract(mMinSerialNo)).subtract(mCounter);
+ } else {
+ numsInRange = mMaxSerialNo.subtract(mLastSerialNo);
+ }
+ BigInteger numsInNextRange = null;
+ BigInteger numsAvail = null;
+ CMS.debug("Serial numbers left in range: " + numsInRange.toString());
+ CMS.debug("Last Serial Number: " + mLastSerialNo.toString());
+ if ((mNextMaxSerialNo != null) && (mNextMinSerialNo != null)) {
+ numsInNextRange = mNextMaxSerialNo.subtract(mNextMinSerialNo).add(BigInteger.ONE);
+ numsAvail = numsInRange.add(numsInNextRange);
+ CMS.debug("Serial Numbers in next range: " + numsInNextRange.toString());
+ CMS.debug("Serial Numbers available: " + numsAvail.toString());
+ } else {
+ numsAvail = numsInRange;
+ CMS.debug("Serial Numbers available: " + numsAvail.toString());
+ }
+
+ if ((numsAvail.compareTo(mLowWaterMarkNo) < 0) && (!CMS.isPreOpMode())) {
+ CMS.debug("Low water mark reached. Requesting next range");
+ mNextMinSerialNo = new BigInteger(mDB.getNextRange(mRepo), mRadix);
+ if (mNextMinSerialNo == null) {
+ CMS.debug("Next Range not available");
+ } else {
+ CMS.debug("nNextMinSerialNo has been set to " + mNextMinSerialNo.toString(mRadix));
+ mNextMaxSerialNo = mNextMinSerialNo.add(mIncrementNo).subtract(BigInteger.ONE);
+ numsAvail = numsAvail.add(mIncrementNo);
+ mDB.setNextMinSerialConfig(mRepo, mNextMinSerialNo.toString(mRadix));
+ mDB.setNextMaxSerialConfig(mRepo, mNextMaxSerialNo.toString(mRadix));
+ }
+ }
+
+ if (numsInRange.compareTo(mLowWaterMarkNo) < 0) {
+ // check for a replication error
+ CMS.debug("Checking for a range conflict");
+ if (mDB.hasRangeConflict(mRepo)) {
+ CMS.debug("Range Conflict found! Removing next range.");
+ mNextMaxSerialNo = null;
+ mNextMinSerialNo = null;
+ mDB.setNextMinSerialConfig(mRepo, null);
+ mDB.setNextMaxSerialConfig(mRepo, null);
+ }
+ }
+ }
+
+ /**
+ * Sets whether serial number management is enabled for certs
+ * and requests.
+ *
+ * @param value true/false
+ * @exception EBaseException failed to set
+ */
+ public void setEnableSerialMgmt(boolean value) throws EBaseException {
+ mDB.setEnableSerialMgmt(value);
+ }
+
+ public abstract BigInteger getLastSerialNumberInRange(BigInteger serial_low_bound, BigInteger serial_upper_bound)
+ throws
+ EBaseException;
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/RepositoryRecord.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/RepositoryRecord.java
new file mode 100644
index 000000000..a268f68a9
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/RepositoryRecord.java
@@ -0,0 +1,121 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.repository.IRepositoryRecord;
+
+/**
+ * A class represents a repository record.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class RepositoryRecord implements IRepositoryRecord {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1648450747848783853L;
+ private BigInteger mSerialNo = null;
+ private String mPublishingStatus = null;
+ private String mDescription = null;
+
+ protected static Vector<String> mNames = new Vector<String>();
+ static {
+ mNames.addElement(IRepositoryRecord.ATTR_SERIALNO);
+ mNames.addElement(IRepositoryRecord.ATTR_PUB_STATUS);
+ mNames.addElement(IRepositoryRecord.ATTR_DESCRIPTION);
+ }
+
+ /**
+ * Constructs a repository record.
+ * <P>
+ */
+ public RepositoryRecord() {
+ }
+
+ /**
+ * Sets attribute.
+ */
+ public void set(String name, Object obj) throws EBaseException {
+ if (name.equalsIgnoreCase(IRepositoryRecord.ATTR_SERIALNO)) {
+ mSerialNo = (BigInteger) obj;
+ } else if (name.equalsIgnoreCase(IRepositoryRecord.ATTR_PUB_STATUS)) {
+ mPublishingStatus = (String) obj;
+ } else if (name.equalsIgnoreCase(IRepositoryRecord.ATTR_DESCRIPTION)) {
+ mDescription = (String) obj;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+ }
+
+ /**
+ * Retrieves attribute from this record.
+ */
+ public Object get(String name) throws EBaseException {
+ if (name.equalsIgnoreCase(IRepositoryRecord.ATTR_SERIALNO)) {
+ return mSerialNo;
+ } else if (name.equalsIgnoreCase(IRepositoryRecord.ATTR_PUB_STATUS)) {
+ return mPublishingStatus;
+ } else if (name.equalsIgnoreCase(IRepositoryRecord.ATTR_DESCRIPTION)) {
+ return mDescription;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+ }
+
+ /**
+ * Deletes an attribute.
+ */
+ public void delete(String name) throws EBaseException {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+
+ /**
+ * Retrieves a list of attribute names.
+ */
+ public Enumeration<String> getElements() {
+ return mNames.elements();
+ }
+
+ public Enumeration<String> getSerializableAttrNames() {
+ return mNames.elements();
+ }
+
+ /**
+ * Retrieves serial number.
+ */
+ public BigInteger getSerialNumber() {
+ return mSerialNo;
+ }
+
+ public String getPublishingStatus() {
+ return mPublishingStatus;
+ }
+
+ public String getDescription() {
+ return mDescription;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/RepositorySchema.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/RepositorySchema.java
new file mode 100644
index 000000000..5dfc55590
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/RepositorySchema.java
@@ -0,0 +1,35 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+/**
+ * A class represents a collection of repository-specific
+ * schema information.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class RepositorySchema {
+
+ public static final String LDAP_OC_TOP = "top";
+ public static final String LDAP_OC_REPOSITORY = "repository";
+ public static final String LDAP_ATTR_SERIALNO = "serialno";
+ public static final String LDAP_ATTR_PUB_STATUS = "publishingStatus";
+ public final static String LDAP_ATTR_DESCRIPTION = "description";
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/RevocationInfo.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/RevocationInfo.java
new file mode 100644
index 000000000..36f470511
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/RevocationInfo.java
@@ -0,0 +1,78 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+
+import com.netscape.certsrv.dbs.certdb.IRevocationInfo;
+
+/**
+ * A class represents a certificate revocation info. This
+ * object is written as an attribute of certificate record
+ * which essentially signifies a revocation act.
+ * <P>
+ *
+ * @author galperin
+ * @version $Revision$, $Date$
+ */
+public class RevocationInfo implements IRevocationInfo, Serializable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -157323417902547417L;
+ private Date mRevocationDate = null;
+ private CRLExtensions mCRLEntryExtensions = null;
+
+ /**
+ * Constructs revocation info.
+ */
+ public RevocationInfo() {
+ }
+
+ /**
+ * Constructs revocation info used by revocation
+ * request implementation.
+ *
+ * @param reason if not null contains CRL entry extension
+ * that specifies revocation reason
+ * @see CRLReasonExtension
+ */
+ public RevocationInfo(Date revocationDate, CRLExtensions exts) {
+ mRevocationDate = revocationDate;
+ mCRLEntryExtensions = exts;
+ }
+
+ /**
+ * Retrieves revocation date.
+ */
+ public Date getRevocationDate() {
+ return mRevocationDate;
+ }
+
+ /**
+ * Retrieves CRL extensions.
+ */
+ public CRLExtensions getCRLEntryExtensions() {
+ return mCRLEntryExtensions;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/RevocationInfoMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/RevocationInfoMapper.java
new file mode 100644
index 000000000..e033f8154
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/RevocationInfoMapper.java
@@ -0,0 +1,175 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.Extension;
+import netscape.security.x509.InvalidityDateExtension;
+import netscape.security.x509.RevocationReason;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * A class represents a mapper to serialize
+ * revocation information into database.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class RevocationInfoMapper implements IDBAttrMapper {
+
+ protected static Vector<String> mNames = new Vector<String>();
+ static {
+ mNames.addElement(CertDBSchema.LDAP_ATTR_REVO_INFO);
+ }
+
+ /**
+ * Constructs revocation information mapper.
+ */
+ public RevocationInfoMapper() {
+ }
+
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return mNames.elements();
+ }
+
+ public void mapObjectToLDAPAttributeSet(IDBObj parent, String name,
+ Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ try {
+ // in format of <date>;<extensions>
+ StringBuffer value = new StringBuffer();
+
+ RevocationInfo info = (RevocationInfo) obj;
+ Date d = info.getRevocationDate();
+
+ value.append(DateMapper.dateToDB(d));
+ CRLExtensions exts = info.getCRLEntryExtensions();
+ // CRLExtension's DER encoding and decoding does not work!
+ // That is why we need to do our own serialization.
+ Enumeration<Extension> e = exts.getElements();
+
+ while (e.hasMoreElements()) {
+ Extension ext = e.nextElement();
+
+ if (ext instanceof CRLReasonExtension) {
+ RevocationReason reason =
+ ((CRLReasonExtension) ext).getReason();
+
+ value.append(";CRLReasonExtension=" +
+ Integer.toString(reason.toInt()));
+ } else if (ext instanceof InvalidityDateExtension) {
+ Date invalidityDate =
+ ((InvalidityDateExtension) ext).getInvalidityDate();
+
+ value.append(";InvalidityDateExtension=" +
+ DateMapper.dateToDB(invalidityDate));
+ } else {
+ Debug.trace("XXX skipped extension");
+ }
+ }
+ attrs.add(new LDAPAttribute(CertDBSchema.LDAP_ATTR_REVO_INFO,
+ value.toString()));
+ } catch (Exception e) {
+ Debug.trace(e.toString());
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ }
+
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ try {
+ LDAPAttribute attr = attrs.getAttribute(
+ CertDBSchema.LDAP_ATTR_REVO_INFO);
+
+ if (attr == null)
+ return;
+ String value = (String) attr.getStringValues().nextElement();
+ int i = value.indexOf(';'); // look for 1st ";"
+ String str = null;
+ CRLExtensions exts = new CRLExtensions();
+ Date d = null;
+
+ if (i == -1) {
+ // only date found; no extensions
+ d = DateMapper.dateFromDB(value);
+ } else {
+ String s = value;
+
+ str = s.substring(0, i);
+ d = DateMapper.dateFromDB(str);
+ s = s.substring(i + 1);
+ do {
+ i = s.indexOf(';');
+ if (i == -1) {
+ str = s;
+ } else {
+ str = s.substring(0, i);
+ s = s.substring(i + 1);
+ }
+ if (str.startsWith("CRLReasonExtension=")) {
+ String reasonStr = str.substring(19);
+ RevocationReason reason = RevocationReason.fromInt(
+ Integer.parseInt(reasonStr));
+ CRLReasonExtension ext = new CRLReasonExtension(reason);
+
+ exts.set(CRLReasonExtension.NAME, ext);
+ } else if (str.startsWith("InvalidityDateExtension=")) {
+ String invalidityDateStr = str.substring(24);
+ Date invalidityDate = DateMapper.dateFromDB(invalidityDateStr);
+ InvalidityDateExtension ext =
+ new InvalidityDateExtension(invalidityDate);
+
+ exts.set(InvalidityDateExtension.NAME, ext);
+ } else {
+ Debug.trace("XXX skipped extension");
+ }
+ } while (i != -1);
+ }
+ RevocationInfo info = new RevocationInfo(d, exts);
+
+ parent.set(name, info);
+ } catch (Exception e) {
+ Debug.trace(e.toString());
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_DESERIALIZE_FAILED", name));
+ }
+ }
+
+ public String mapSearchFilter(String name, String op, String value)
+ throws EBaseException {
+ return CertDBSchema.LDAP_ATTR_REVO_INFO + op + value;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/StringMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/StringMapper.java
new file mode 100644
index 000000000..3282e11b5
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/StringMapper.java
@@ -0,0 +1,94 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+
+/**
+ * A class represents ann attribute mapper that maps
+ * a Java String object into LDAP attribute,
+ * and vice versa.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class StringMapper implements IDBAttrMapper {
+
+ private String mLdapName = null;
+ private Vector<String> v = new Vector<String>();
+
+ /**
+ * Constructs string mapper.
+ */
+ public StringMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Retrieves a list of supported ldap attributes.
+ */
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps attribute value to ldap attributes.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ attrs.add(new LDAPAttribute(mLdapName, (String) obj));
+ }
+
+ /**
+ * Maps LDAP attributes into object, and put the object
+ * into 'parent'.
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent)
+ throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(mLdapName);
+
+ if (attr == null) {
+ return;
+ }
+ try {
+ parent.set(name, attr.getStringValues().nextElement());
+ } catch (NoSuchElementException e) {
+ // attribute present, but without value
+ }
+ }
+
+ /**
+ * Maps search filters into LDAP search filter.
+ */
+ public String mapSearchFilter(String name, String op,
+ String value) throws EBaseException {
+ return mLdapName + op + value;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/StringVectorMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/StringVectorMapper.java
new file mode 100644
index 000000000..db2c9ee58
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/StringVectorMapper.java
@@ -0,0 +1,115 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+
+/**
+ * A class represents ann attribute mapper that maps
+ * a Java String object into LDAP attribute,
+ * and vice versa.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class StringVectorMapper implements IDBAttrMapper {
+
+ private String mLdapName = null;
+ private Vector<String> v = new Vector<String>();
+
+ /**
+ * Constructs string vector mapper.
+ */
+ public StringVectorMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Retrieves a list of supported ldap attributes.
+ */
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps attribute value to ldap attributes.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ @SuppressWarnings("unchecked")
+ Vector<String> v = (Vector<String>) obj;
+ int s = v.size();
+
+ if (s == 0) {
+ return;
+ }
+ String m[] = new String[s];
+
+ for (int i = 0; i < s; i++) {
+ m[i] = v.elementAt(i);
+ }
+ attrs.add(new LDAPAttribute(mLdapName, m));
+ }
+
+ /**
+ * Maps LDAP attributes into object, and put the object
+ * into 'parent'.
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(mLdapName);
+
+ if (attr == null)
+ return;
+ @SuppressWarnings("unchecked")
+ Enumeration<String> e = attr.getStringValues();
+ Vector<String> v = new Vector<String>();
+
+ while (e.hasMoreElements()) {
+ v.addElement(e.nextElement());
+ }
+ if (v.size() == 0)
+ return;
+ String m[] = new String[v.size()];
+
+ v.copyInto(m);
+ parent.set(name, m);
+ }
+
+ /**
+ * Maps search filters into LDAP search filter.
+ */
+ public String mapSearchFilter(String name, String op,
+ String value) throws EBaseException {
+ return mLdapName + op + value;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/X500NameMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/X500NameMapper.java
new file mode 100644
index 000000000..50d938d81
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/X500NameMapper.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.security.x509.X500Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A class represents ann attribute mapper that maps
+ * a Java X500Name object into LDAP attribute,
+ * and vice versa.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class X500NameMapper implements IDBAttrMapper {
+
+ private String mLdapName = null;
+ private Vector<String> v = new Vector<String>();
+
+ private ILogger mLogger = CMS.getLogger();
+
+ /**
+ * Constructs X500Name mapper.
+ */
+ public X500NameMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Retrieves a list of ldap attributes.
+ */
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps attribute value to ldap attributes.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ attrs.add(new LDAPAttribute(mLdapName,
+ ((X500Name) obj).toString()));
+ }
+
+ /**
+ * Maps LDAP attributes into object, and put the object
+ * into 'parent'.
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(mLdapName);
+
+ if (attr == null) {
+ return;
+ }
+ try {
+ parent.set(name, new X500Name((String)
+ attr.getStringValues().nextElement()));
+ } catch (IOException e) {
+
+ /*LogDoc
+ *
+ * @phase Maps LDAP attributes into object
+ * @message X500NameMapper: <exception thrown>
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_DBS_X500NAME_MAPPER_ERROR",
+ e.toString()));
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_DESERIALIZE_FAILED", name));
+ }
+ }
+
+ /**
+ * Maps search filters into LDAP search filter.
+ */
+ public String mapSearchFilter(String name, String op,
+ String value) throws EBaseException {
+ return mLdapName + op + value;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/X509CertImplMapper.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/X509CertImplMapper.java
new file mode 100644
index 000000000..ef8577747
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/X509CertImplMapper.java
@@ -0,0 +1,372 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.security.extensions.NSCertTypeExtension;
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.Extension;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509Key;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.AttributeNameHelper;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+
+/**
+ * A class represents a mapper to serialize
+ * x509 certificate into database.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class X509CertImplMapper implements IDBAttrMapper {
+
+ public X509CertImplMapper() {
+ }
+
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(CertDBSchema.LDAP_ATTR_NOT_BEFORE);
+ v.addElement(CertDBSchema.LDAP_ATTR_NOT_AFTER);
+ v.addElement(CertDBSchema.LDAP_ATTR_DURATION);
+ v.addElement(CertDBSchema.LDAP_ATTR_EXTENSION);
+ v.addElement(CertDBSchema.LDAP_ATTR_SUBJECT);
+ v.addElement(CertDBSchema.LDAP_ATTR_SIGNED_CERT);
+ v.addElement(CertDBSchema.LDAP_ATTR_VERSION);
+ v.addElement(CertDBSchema.LDAP_ATTR_ALGORITHM);
+ v.addElement(CertDBSchema.LDAP_ATTR_SIGNING_ALGORITHM);
+ v.addElement(CertDBSchema.LDAP_ATTR_PUBLIC_KEY_DATA);
+ return v.elements();
+ }
+
+ public void mapObjectToLDAPAttributeSet(IDBObj parent, String name,
+ Object obj, LDAPAttributeSet attrs) throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ try {
+ X509CertImpl cert = (X509CertImpl) obj;
+ // make information searchable
+ Date notBefore = cert.getNotBefore();
+
+ attrs.add(new LDAPAttribute(
+ CertDBSchema.LDAP_ATTR_NOT_BEFORE,
+ DateMapper.dateToDB(notBefore)));
+ Date notAfter = cert.getNotAfter();
+
+ attrs.add(new LDAPAttribute(CertDBSchema.LDAP_ATTR_NOT_AFTER,
+ DateMapper.dateToDB(notAfter)));
+ attrs.add(new LDAPAttribute(CertDBSchema.LDAP_ATTR_DURATION,
+ DBSUtil.longToDB(notAfter.getTime() - notBefore.getTime())));
+ attrs.add(new LDAPAttribute(CertDBSchema.LDAP_ATTR_SUBJECT,
+ cert.getSubjectDN().getName()));
+ attrs.add(new LDAPAttribute(CertDBSchema.LDAP_ATTR_PUBLIC_KEY_DATA, cert.getPublicKey().getEncoded()));
+ // make extension searchable
+ Set<String> nonCritSet = cert.getNonCriticalExtensionOIDs();
+
+ if (nonCritSet != null) {
+ for (Iterator<String> i = nonCritSet.iterator(); i.hasNext();) {
+ String oid = i.next();
+
+ if (oid.equals("2.16.840.1.113730.1.1")) {
+ String extVal = getCertTypeExtensionInfo(cert);
+
+ if (extVal != null) {
+ oid = oid + ";" + extVal;
+ }
+ } else if (oid.equals("2.5.29.19")) {
+ String extVal = getBasicConstraintsExtensionInfo(cert);
+
+ if (extVal != null) {
+ oid = oid + ";" + extVal;
+ }
+ }
+ attrs.add(new LDAPAttribute(
+ CertDBSchema.LDAP_ATTR_EXTENSION, oid));
+ }
+ }
+ Set<String> critSet = cert.getCriticalExtensionOIDs();
+
+ if (critSet != null) {
+ for (Iterator<String> i = critSet.iterator(); i.hasNext();) {
+ String oid = i.next();
+
+ if (oid.equals("2.16.840.1.113730.1.1")) {
+ String extVal = getCertTypeExtensionInfo(cert);
+
+ if (extVal != null) {
+ oid = oid + ";" + extVal;
+ }
+ } else if (oid.equals("2.5.29.19")) {
+ String extVal = getBasicConstraintsExtensionInfo(cert);
+
+ if (extVal != null) {
+ oid = oid + ";" + extVal;
+ }
+ }
+ attrs.add(new LDAPAttribute(
+ CertDBSchema.LDAP_ATTR_EXTENSION, oid));
+ }
+ }
+
+ // something extra; so that we can rebuild the
+ // object quickly
+ // if we dont add ";binary", communicator does
+ // not know how to display the certificate in
+ // pretty print format.
+ attrs.add(new LDAPAttribute(
+ CertDBSchema.LDAP_ATTR_SIGNED_CERT + ";binary",
+ cert.getEncoded()));
+
+ attrs.add(new LDAPAttribute(
+ CertDBSchema.LDAP_ATTR_VERSION,
+ Integer.toString(cert.getVersion())));
+ X509Key pubKey = (X509Key) cert.getPublicKey();
+
+ attrs.add(new LDAPAttribute(
+ CertDBSchema.LDAP_ATTR_ALGORITHM,
+ pubKey.getAlgorithmId().getOID().toString()));
+ attrs.add(new LDAPAttribute(
+ CertDBSchema.LDAP_ATTR_SIGNING_ALGORITHM,
+ cert.getSigAlgOID()));
+ } catch (CertificateEncodingException e) {
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ }
+
+ private String getCertTypeExtensionInfo(X509CertImpl cert) {
+ try {
+ Extension ext = cert.getExtension("2.16.840.1.113730.1.1");
+
+ if (ext == null) {
+ // sometime time (during installation) it
+ // is named differently
+ ext = cert.getExtension(NSCertTypeExtension.NAME);
+ if (ext == null)
+ return null;
+ }
+ NSCertTypeExtension nsExt = (NSCertTypeExtension) ext;
+
+ String result = "";
+
+ Boolean sslServer = (Boolean) nsExt.get(
+ NSCertTypeExtension.SSL_SERVER);
+
+ result += "SSLServer=" + sslServer.toString() + ",";
+ Boolean sslClient = (Boolean) nsExt.get(
+ NSCertTypeExtension.SSL_CLIENT);
+
+ result += "SSLClient=" + sslClient.toString() + ",";
+ Boolean email = (Boolean) nsExt.get(
+ NSCertTypeExtension.EMAIL);
+
+ result += "Email=" + email.toString() + ",";
+ Boolean sslCA = (Boolean) nsExt.get(
+ NSCertTypeExtension.SSL_CA);
+
+ result += "SSLCA=" + sslCA.toString() + ",";
+ Boolean mailCA = (Boolean) nsExt.get(
+ NSCertTypeExtension.EMAIL_CA);
+
+ result += "EmailCA=" + mailCA.toString() + ",";
+ Boolean objectSigning = (Boolean) nsExt.get(
+ NSCertTypeExtension.OBJECT_SIGNING);
+
+ result += "objectSigning=" +
+ objectSigning.toString();
+ return result;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ private String getBasicConstraintsExtensionInfo(X509CertImpl cert) {
+ try {
+ Extension ext = cert.getExtension("2.5.29.19");
+
+ if (ext == null) {
+ // sometime time (during installation) it
+ // is named differently
+ ext = cert.getExtension(BasicConstraintsExtension.NAME);
+ if (ext == null)
+ return null;
+ }
+ BasicConstraintsExtension bcExt = (BasicConstraintsExtension) ext;
+
+ String result = "";
+
+ Boolean isCA = (Boolean) bcExt.get(
+ BasicConstraintsExtension.IS_CA);
+
+ result += "isCA=" + isCA.toString() + ",";
+ Integer pathLen = (Integer) bcExt.get(
+ BasicConstraintsExtension.PATH_LEN);
+
+ result += "pathLen=" + pathLen.toString();
+ return result;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent) throws EBaseException {
+ try {
+ // rebuild object quickly using binary image
+ // XXX bad! when we add this attribute,
+ // we add it as userCertificate, but when
+ // we retrieve it, DS returns it as
+ // userCertificate;binary. So I cannot do the
+ // following:
+ // LDAPAttribute attr = attrs.getAttribute(
+ // Schema.LDAP_ATTR_SIGNED_CERT);
+
+ LDAPAttribute attr = attrs.getAttribute(
+ CertDBSchema.LDAP_ATTR_SIGNED_CERT);
+
+ if (attr == null) {
+ // YUK!
+ attr = attrs.getAttribute(
+ CertDBSchema.LDAP_ATTR_SIGNED_CERT + ";binary");
+ }
+ if (attr != null) {
+ byte der[] = (byte[])
+ attr.getByteValues().nextElement();
+ X509CertImpl impl = new X509CertImpl(der);
+
+ parent.set(name, impl);
+ }
+ } catch (CertificateException e) {
+ //throw new EDBException(
+ // DBResources.FAILED_TO_DESERIALIZE_1, name);
+ parent.set(name, null);
+ } catch (Exception e) {
+ //throw new EDBException(
+ // DBResources.FAILED_TO_DESERIALIZE_1, name);
+ parent.set(name, null);
+
+ }
+ }
+
+ public String mapSearchFilter(String name, String op, String value)
+ throws EBaseException {
+ AttributeNameHelper h = new AttributeNameHelper(name);
+ String suffix = h.getSuffix();
+
+ if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_NOT_BEFORE)) {
+ name = CertDBSchema.LDAP_ATTR_NOT_BEFORE;
+ try {
+ value = DateMapper.dateToDB(new
+ Date(Long.parseLong(value)));
+ } catch (NumberFormatException e) {
+ }
+ } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_NOT_AFTER)) {
+ name = CertDBSchema.LDAP_ATTR_NOT_AFTER;
+ try {
+ value = DateMapper.dateToDB(new
+ Date(Long.parseLong(value)));
+ } catch (NumberFormatException e) {
+ }
+ } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_SUBJECT)) {
+ name = CertDBSchema.LDAP_ATTR_SUBJECT;
+ } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_PUBLIC_KEY_DATA)) {
+ name = CertDBSchema.LDAP_ATTR_PUBLIC_KEY_DATA;
+ } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_DURATION)) {
+ name = CertDBSchema.LDAP_ATTR_DURATION;
+ value = DBSUtil.longToDB(Long.parseLong(value));
+ } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_VERSION)) {
+ name = CertDBSchema.LDAP_ATTR_VERSION;
+ } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_ALGORITHM)) {
+ name = CertDBSchema.LDAP_ATTR_ALGORITHM;
+ } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_SIGNING_ALGORITHM)) {
+ name = CertDBSchema.LDAP_ATTR_SIGNING_ALGORITHM;
+ } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_SERIAL_NUMBER)) {
+ name = CertDBSchema.LDAP_ATTR_CERT_RECORD_ID;
+ } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_EXTENSION)) {
+ name = CertDBSchema.LDAP_ATTR_EXTENSION;
+ } else if (suffix.equalsIgnoreCase(ICertRecord.ATTR_REVO_INFO)) {
+ name = CertDBSchema.LDAP_ATTR_REVO_INFO;
+ value = "*;CRLReasonExtension=" + value;
+ } else if (suffix.equalsIgnoreCase("nsExtension.SSLClient")) {
+ // special case for NS cert type extension
+ name = CertDBSchema.LDAP_ATTR_EXTENSION;
+ if (value.equals("on")) {
+ value = "2.16.840.1.113730.1.1;*SSLClient=true*";
+ } else {
+ value = "2.16.840.1.113730.1.1;*SSLClient=false*";
+ }
+ } else if (suffix.equalsIgnoreCase("nsExtension.SSLServer")) {
+ // special case for NS cert type extension
+ name = CertDBSchema.LDAP_ATTR_EXTENSION;
+ if (value.equals("on")) {
+ value = "2.16.840.1.113730.1.1;*SSLServer=true*";
+ } else {
+ value = "2.16.840.1.113730.1.1;*SSLServer=false*";
+ }
+ } else if (suffix.equalsIgnoreCase("nsExtension.SecureEmail")) {
+ // special case for NS cert type extension
+ name = CertDBSchema.LDAP_ATTR_EXTENSION;
+ if (value.equals("on")) {
+ value = "2.16.840.1.113730.1.1;*Email=true*";
+ } else {
+ value = "2.16.840.1.113730.1.1;*Email=false*";
+ }
+ } else if (suffix.equalsIgnoreCase("nsExtension.SubordinateSSLCA")) {
+ // special case for NS cert type extension
+ name = CertDBSchema.LDAP_ATTR_EXTENSION;
+ if (value.equals("on")) {
+ value = "2.16.840.1.113730.1.1;*SSLCA=true*";
+ } else {
+ value = "2.16.840.1.113730.1.1;*SSLCA=false*";
+ }
+ } else if (suffix.equalsIgnoreCase("nsExtension.SubordinateEmailCA")) {
+ // special case for NS cert type extension
+ name = CertDBSchema.LDAP_ATTR_EXTENSION;
+ if (value.equals("on")) {
+ value = "2.16.840.1.113730.1.1;*EmailCA=true*";
+ } else {
+ value = "2.16.840.1.113730.1.1;*EmailCA=false*";
+ }
+ } else if (suffix.equalsIgnoreCase("BasicConstraints.isCA")) {
+ // special case for Basic Constraints extension
+ name = CertDBSchema.LDAP_ATTR_EXTENSION;
+ if (value.equals("on")) {
+ value = "2.5.29.19;*isCA=true*";
+ } else {
+ value = "2.5.29.19;*isCA=false*";
+ }
+ }
+ return name + op + value;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/extensions/CMSExtensionsMap.java b/base/server/cmscore/src/com/netscape/cmscore/extensions/CMSExtensionsMap.java
new file mode 100644
index 000000000..3322ca9b0
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/extensions/CMSExtensionsMap.java
@@ -0,0 +1,161 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.extensions;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import netscape.security.util.ObjectIdentifier;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.extensions.EExtensionsException;
+import com.netscape.certsrv.extensions.ICMSExtension;
+
+/**
+ * Loads extension classes from configuration file and return
+ * for a given extension name or OID.
+ */
+public class CMSExtensionsMap implements ISubsystem {
+ public static String ID = "extensions";
+
+ private static CMSExtensionsMap mInstance = new CMSExtensionsMap();
+
+ public static final CMSExtensionsMap getInstance() {
+ return mInstance;
+ }
+
+ private CMSExtensionsMap() {
+ }
+
+ private static final String PROP_CLASS = "class";
+
+ private Hashtable<String, ICMSExtension> mName2Ext = new Hashtable<String, ICMSExtension>();
+ private Hashtable<String, ICMSExtension> mOID2Ext = new Hashtable<String, ICMSExtension>();
+ @SuppressWarnings("unused")
+ private ISubsystem mOwner;
+ private IConfigStore mConfig = null;
+
+ /**
+ * Create extensions from configuration store.
+ *
+ * @param config the configuration store.
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mOwner = owner;
+ mConfig = config;
+
+ Enumeration<String> sstores = mConfig.getSubStoreNames();
+
+ while (sstores.hasMoreElements()) {
+ String name = sstores.nextElement();
+ IConfigStore c = mConfig.getSubStore(name);
+
+ String className = c.getString(PROP_CLASS);
+ ICMSExtension ext = null;
+
+ try {
+ ext = (ICMSExtension) Class.forName(className).newInstance();
+ ext.init(this, c);
+ addExt(ext);
+ } catch (ClassNotFoundException e) {
+ throw new EExtensionsException(
+ CMS.getUserMessage("CMS_EXTENSION_CLASS_NOT_FOUND", className));
+ } catch (IllegalAccessException e) {
+ throw new EExtensionsException(
+ CMS.getUserMessage("CMS_EXTENSION_INSTANTIATE_ERROR",
+ className, e.toString()));
+ } catch (InstantiationException e) {
+ throw new EExtensionsException(
+ CMS.getUserMessage("CMS_EXTENSION_INSTANTIATE_ERROR",
+ className, e.toString()));
+ } catch (ClassCastException e) {
+ throw new EExtensionsException(
+ CMS.getUserMessage("CMS_EXTENSION_INVALID_IMPL", className));
+ }
+ }
+ }
+
+ public void addExt(ICMSExtension ext) throws EBaseException {
+ String name = ext.getName();
+ ObjectIdentifier oid = ext.getOID();
+
+ if (name == null || oid == null) {
+ throw new EExtensionsException(
+ CMS.getUserMessage("CMS_EXTENSION_INCORRECT_IMPL",
+ ext.getClass().getName()));
+ }
+ mName2Ext.put(name, ext);
+ mOID2Ext.put(oid.toString(), ext);
+ }
+
+ /**
+ * startup - does nothing.
+ */
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * shutdown - does nothing.
+ */
+ public void shutdown() {
+ }
+
+ /**
+ * Get configuration store.
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Returns subsystem ID
+ */
+ public String getId() {
+ return ID;
+ }
+
+ /**
+ * sets subsystem ID
+ */
+ public void setId(String Id) {
+ }
+
+ /**
+ * Get the extension class by name.
+ *
+ * @param name name of the extension
+ * @return the extension class.
+ */
+ public ICMSExtension getByName(String name) {
+ return mName2Ext.get(name);
+ }
+
+ /**
+ * Get the extension class by its OID.
+ *
+ * @param oid - the OID of the extension.
+ * @return the extension class.
+ */
+ public ICMSExtension getByOID(ObjectIdentifier oid) {
+ return mOID2Ext.get(oid.toString());
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/extensions/KeyUsage.java b/base/server/cmscore/src/com/netscape/cmscore/extensions/KeyUsage.java
new file mode 100644
index 000000000..c5487de31
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/extensions/KeyUsage.java
@@ -0,0 +1,227 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.extensions;
+
+import java.io.IOException;
+
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.Extension;
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.PKIXExtensions;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.extensions.EExtensionsException;
+import com.netscape.certsrv.extensions.ICMSExtension;
+import com.netscape.cmscore.util.Debug;
+
+public class KeyUsage implements ICMSExtension {
+ private final static String NAME = "KeyUsageExtension";
+ private final static ObjectIdentifier OID = PKIXExtensions.KeyUsage_Id;
+
+ @SuppressWarnings("unused")
+ private IConfigStore mConfig;
+ private boolean mSetDefault = false;
+
+ public KeyUsage(boolean setDefault) {
+ mSetDefault = setDefault;
+ }
+
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ // nothing to do here.
+ mConfig = config;
+ }
+
+ public String getName() {
+ return NAME;
+ }
+
+ public ObjectIdentifier getOID() {
+ return OID;
+ }
+
+ protected static final boolean[] DEF_BITS =
+ new boolean[KeyUsageExtension.NBITS];
+
+ static {
+ // set default bits used when request missing key usage info.
+ DEF_BITS[KeyUsageExtension.DIGITAL_SIGNATURE_BIT] = true;
+ DEF_BITS[KeyUsageExtension.NON_REPUDIATION_BIT] = false;
+ DEF_BITS[KeyUsageExtension.KEY_ENCIPHERMENT_BIT] = true;
+ DEF_BITS[KeyUsageExtension.DATA_ENCIPHERMENT_BIT] = true;
+ DEF_BITS[KeyUsageExtension.KEY_AGREEMENT_BIT] = false;
+ DEF_BITS[KeyUsageExtension.KEY_CERTSIGN_BIT] = false;
+ DEF_BITS[KeyUsageExtension.CRL_SIGN_BIT] = false;
+ DEF_BITS[KeyUsageExtension.ENCIPHER_ONLY_BIT] = false;
+ DEF_BITS[KeyUsageExtension.DECIPHER_ONLY_BIT] = false;
+ }
+
+ private static boolean getBoolean(Object value) {
+ String val = (String) value;
+
+ if (val != null &&
+ (val.equalsIgnoreCase("true") || val.equalsIgnoreCase("on")))
+ return true;
+ else
+ return false;
+ }
+
+ public Extension getExtension(IArgBlock args) throws EBaseException {
+ boolean[] bits = new boolean[KeyUsageExtension.NBITS];
+ Object[] values = new Object[KeyUsageExtension.NBITS];
+ int bit;
+
+ // check if no bits are set. If not set default bits.
+ bit = KeyUsageExtension.DIGITAL_SIGNATURE_BIT;
+ values[bit] = args.get(KeyUsageExtension.names[bit]);
+ bit = KeyUsageExtension.NON_REPUDIATION_BIT;
+ values[bit] = args.get(KeyUsageExtension.names[bit]);
+ bit = KeyUsageExtension.KEY_ENCIPHERMENT_BIT;
+ values[bit] = args.get(KeyUsageExtension.names[bit]);
+ bit = KeyUsageExtension.DATA_ENCIPHERMENT_BIT;
+ values[bit] = args.get(KeyUsageExtension.names[bit]);
+ bit = KeyUsageExtension.KEY_AGREEMENT_BIT;
+ values[bit] = args.get(KeyUsageExtension.names[bit]);
+ bit = KeyUsageExtension.KEY_CERTSIGN_BIT;
+ values[bit] = args.get(KeyUsageExtension.names[bit]);
+ bit = KeyUsageExtension.CRL_SIGN_BIT;
+ values[bit] = args.get(KeyUsageExtension.names[bit]);
+ bit = KeyUsageExtension.ENCIPHER_ONLY_BIT;
+ values[bit] = args.get(KeyUsageExtension.names[bit]);
+ bit = KeyUsageExtension.DECIPHER_ONLY_BIT;
+ values[bit] = args.get(KeyUsageExtension.names[bit]);
+
+ // if nothing is set, make one with default set of bits.
+ int i;
+
+ for (i = 0; i < KeyUsageExtension.NBITS; i++) {
+ if (values[i] != null && (values[i] instanceof String))
+ break;
+ }
+ if (i == KeyUsageExtension.NBITS && mSetDefault) {
+ // no key usage extension parameters are requested. set default.
+ CMS.debug(
+ "No Key usage bits requested. Setting default.");
+ bits = DEF_BITS;
+ } else {
+ bit = KeyUsageExtension.DIGITAL_SIGNATURE_BIT;
+ bits[bit] = getBoolean(values[bit]);
+ if (Debug.ON)
+ Debug.trace("Requested key usage bit " + bit + " " + bits[bit]);
+ bit = KeyUsageExtension.NON_REPUDIATION_BIT;
+ bits[bit] = getBoolean(values[bit]);
+ if (Debug.ON)
+ Debug.trace("Requested key usage bit " + bit + " " + bits[bit]);
+ bit = KeyUsageExtension.KEY_ENCIPHERMENT_BIT;
+ bits[bit] = getBoolean(values[bit]);
+ if (Debug.ON)
+ Debug.trace("Requested key usage bit " + bit + " " + bits[bit]);
+ bit = KeyUsageExtension.DATA_ENCIPHERMENT_BIT;
+ bits[bit] = getBoolean(values[bit]);
+ if (Debug.ON)
+ Debug.trace("Requested key usage bit " + bit + " " + bits[bit]);
+ bit = KeyUsageExtension.KEY_AGREEMENT_BIT;
+ bits[bit] = getBoolean(values[bit]);
+ if (Debug.ON)
+ Debug.trace("Requested key usage bit " + bit + " " + bits[bit]);
+ bit = KeyUsageExtension.KEY_CERTSIGN_BIT;
+ bits[bit] = getBoolean(values[bit]);
+ if (Debug.ON)
+ Debug.trace("Requested key usage bit " + bit + " " + bits[bit]);
+ bit = KeyUsageExtension.CRL_SIGN_BIT;
+ bits[bit] = getBoolean(values[bit]);
+ if (Debug.ON)
+ Debug.trace("Requested key usage bit " + bit + " " + bits[bit]);
+ bit = KeyUsageExtension.ENCIPHER_ONLY_BIT;
+ bits[bit] = getBoolean(values[bit]);
+ if (Debug.ON)
+ Debug.trace("Requested key usage bit " + bit + " " + bits[bit]);
+ bit = KeyUsageExtension.DECIPHER_ONLY_BIT;
+ bits[bit] = getBoolean(values[bit]);
+ if (Debug.ON)
+ Debug.trace("Requested key usage bit " + bit + " " + bits[bit]);
+ }
+
+ try {
+ int j = 0;
+
+ for (j = 0; j < bits.length; j++) {
+ if (bits[j])
+ break;
+ }
+ if (j == bits.length) {
+ if (!mSetDefault)
+ return null;
+ else
+ bits = DEF_BITS;
+ }
+ return new KeyUsageExtension(bits);
+ } catch (IOException e) {
+ throw new EExtensionsException(
+ CMS.getUserMessage("CMS_EXTENSION_CREATING_EXT_ERROR", NAME));
+ }
+ }
+
+ public IArgBlock getFormParams(Extension extension)
+ throws EBaseException {
+ KeyUsageExtension ext = null;
+
+ if (!extension.getExtensionId().equals(PKIXExtensions.KeyUsage_Id)) {
+ return null;
+ }
+ if (extension instanceof KeyUsageExtension) {
+ ext = (KeyUsageExtension) extension;
+ } else {
+ try {
+ byte[] value = extension.getExtensionValue();
+
+ ext = new KeyUsageExtension(Boolean.valueOf(true), value);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ IArgBlock params = CMS.createArgBlock();
+ boolean[] bits = ext.getBits();
+
+ params.set(KeyUsageExtension.DIGITAL_SIGNATURE,
+ String.valueOf(bits[KeyUsageExtension.DIGITAL_SIGNATURE_BIT]));
+ params.set(KeyUsageExtension.NON_REPUDIATION,
+ String.valueOf(bits[KeyUsageExtension.NON_REPUDIATION_BIT]));
+ params.set(KeyUsageExtension.KEY_ENCIPHERMENT,
+ String.valueOf(bits[KeyUsageExtension.KEY_ENCIPHERMENT_BIT]));
+ params.set(KeyUsageExtension.DATA_ENCIPHERMENT,
+ String.valueOf(bits[KeyUsageExtension.DATA_ENCIPHERMENT_BIT]));
+ params.set(KeyUsageExtension.KEY_AGREEMENT,
+ String.valueOf(bits[KeyUsageExtension.KEY_AGREEMENT_BIT]));
+ params.set(KeyUsageExtension.KEY_CERTSIGN,
+ String.valueOf(bits[KeyUsageExtension.KEY_CERTSIGN_BIT]));
+ params.set(KeyUsageExtension.CRL_SIGN,
+ String.valueOf(bits[KeyUsageExtension.CRL_SIGN_BIT]));
+ params.set(KeyUsageExtension.ENCIPHER_ONLY,
+ String.valueOf(bits[KeyUsageExtension.ENCIPHER_ONLY_BIT]));
+ params.set(KeyUsageExtension.DECIPHER_ONLY,
+ String.valueOf(bits[KeyUsageExtension.DECIPHER_ONLY_BIT]));
+ return params;
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/jobs/CronItem.java b/base/server/cmscore/src/com/netscape/cmscore/jobs/CronItem.java
new file mode 100644
index 000000000..5e6a3296e
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/jobs/CronItem.java
@@ -0,0 +1,168 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.jobs;
+
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * class representing one Job cron item
+ * <p>
+ * here, an "item" refers to one of the 5 fields in a cron string; "element" refers to any comma-deliminated element in
+ * an "item"...which includes both numbers and '-' separated ranges.
+ * <p>
+ * for each of the 5 cron fields, it's represented as a CronItem
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class CronItem {
+ protected static final String ALL = "*";
+ protected static final String DELIM = ",";
+ protected static final String RANGE = "-";
+ private ILogger mLogger = CMS.getLogger();
+
+ int mMin; // minimum
+ int mMax; // maximum
+
+ // store all elements in a field.
+ // elements can either be numbers or ranges (CronRange)
+ protected Vector<CronRange> mElements = new Vector<CronRange>();
+
+ public CronItem(int min, int max) {
+ mMin = min;
+ mMax = max;
+ }
+
+ /**
+ * parses and sets a string cron item
+ *
+ * @param sItem the string representing an item of a cron string.
+ * item can be potentially comma separated with ranges specified
+ * with '-'s
+ */
+ public void set(String sItem) throws EBaseException {
+
+ if (sItem.equals(ALL)) {
+ // System.out.println("CronItem set(): item is ALL");
+ CronRange cr = new CronRange();
+
+ cr.setBegin(mMin);
+ cr.setEnd(mMax);
+ mElements.addElement(cr);
+ } else {
+ // break comma-separated elements
+ StringTokenizer st = new StringTokenizer(sItem, DELIM);
+
+ while (st.hasMoreTokens()) {
+ String tok = st.nextToken();
+ // elements could be ranges (separated by '-')
+ int r = tok.indexOf(RANGE);
+
+ if (r != -1) {
+ // potential range
+ String sBegin = tok.substring(0, r);
+ int begin = 0;
+ int end = 0;
+
+ try {
+ begin = Integer.parseInt(sBegin);
+ } catch (NumberFormatException e) {
+ // throw ...
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_JOBS_INVALID_TOKEN", tok, e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_JOB_CRON"));
+ }
+ String sEnd = tok.substring(r + 1, tok.length());
+
+ try {
+ end = Integer.parseInt(sEnd);
+ } catch (NumberFormatException e) {
+ // throw ...
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_JOBS_INVALID_TOKEN", tok, e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_JOB_CRON"));
+ }
+ // got both begin and end for range
+ CronRange cr = new CronRange();
+
+ cr.setBegin(begin);
+ cr.setEnd(end);
+ // check range
+ if (!cr.isValidRange(mMin, mMax)) {
+ // throw...
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_JOBS_INVALID_RANGE",
+ tok));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_JOB_CRON"));
+ }
+ // System.out.println("CronItem set(): adding a range");
+ mElements.addElement(cr);
+ } else {
+ // number element, begin and end are the same
+ try {
+ CronRange cr = new CronRange();
+ int num = Integer.parseInt(tok);
+
+ cr.setBegin(num);
+ cr.setEnd(num);
+ // check range
+ if (!cr.isValidRange(mMin, mMax)) {
+ // throw...
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_JOBS_INVALID_MIN_MAX_RANGE", Integer.toString(mMin),
+ Integer.toString(mMax)));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_JOB_CRON"));
+ }
+ // System.out.println("CronItem set(): adding a number");
+ mElements.addElement(cr);
+ } catch (NumberFormatException e) {
+ // throw...
+ log(ILogger.LL_FAILURE,
+ "invalid item in cron: " + tok);
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_JOB_CRON"));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * get the vector stuffed with elements where each element is
+ * represented as CronRange
+ *
+ * @return a vector of CronRanges
+ */
+ public Vector<CronRange> getElements() {
+ return mElements;
+ }
+
+ /**
+ * logs an entry in the log file.
+ */
+ protected void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ level, "jobs/CronItem: " + msg);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/jobs/CronRange.java b/base/server/cmscore/src/com/netscape/cmscore/jobs/CronRange.java
new file mode 100644
index 000000000..c49a5b1b4
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/jobs/CronRange.java
@@ -0,0 +1,84 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.jobs;
+
+/**
+ * class representing one Job cron element
+ * <p>
+ * here, an "item" refers to one of the 5 fields in a cron string; "element" refers to any comma-deliminated element in
+ * an "item"...which includes both numbers and '-' separated ranges.
+ * <p>
+ * an Element can contain either an integer number or a range specified as CronRange. In case of integer numbers, begin
+ * and end are of the same value
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class CronRange {
+ int mBegin = 0;
+ int mEnd = 0;
+
+ public CronRange() {
+ }
+
+ /**
+ * sets the lower boundary value of the range
+ */
+ public void setBegin(int i) {
+ mBegin = i;
+ }
+
+ /**
+ * gets the lower boundary value of the range
+ */
+ public int getBegin() {
+ return mBegin;
+ }
+
+ /**
+ * sets the higher boundary value of the range
+ */
+ public void setEnd(int i) {
+ mEnd = i;
+ }
+
+ /**
+ * gets the higher boundary value of the range
+ */
+ public int getEnd() {
+ return mEnd;
+ }
+
+ /**
+ * checks to see if the lower and higher boundary values are
+ * within the min/max.
+ *
+ * @param min the minimum value one can specify in this field
+ * @param max the maximum value one can specify in this field
+ * @return a boolean (true/false) on whether the begin/end values
+ * are within the min/max passed in the params
+ */
+ public boolean isValidRange(int min, int max) {
+ if ((mEnd < mBegin) ||
+ (mBegin < min) ||
+ (mEnd > max))
+ return false;
+ else
+ return true;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/jobs/JobCron.java b/base/server/cmscore/src/com/netscape/cmscore/jobs/JobCron.java
new file mode 100644
index 000000000..7befa611c
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/jobs/JobCron.java
@@ -0,0 +1,355 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.jobs;
+
+import java.util.Calendar;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.jobs.IJobCron;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * class representing one Job cron information
+ * <p>
+ * here, an "item" refers to one of the 5 fields in a cron string; "element" refers to any comma-deliminated element in
+ * an "item"...which includes both numbers and '-' separated ranges. A cron string in the configuration takes the
+ * following format: <i>minute (0-59), hour (0-23), day of the month (1-31), month of the year (1-12), day of the week
+ * (0-6 with 0=Sunday)</i>
+ * <p>
+ * e.g. jobsScheduler.job.rnJob1.cron=30 11,23 * * 1-5 In this example, the job "rnJob1" will be executed from Monday
+ * through Friday, at 11:30am and 11:30pm.
+ * <p>
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class JobCron implements IJobCron {
+
+ /**
+ * CRON_MINUTE, CRON_HOUR, CRON_DAY_OF_MONTH, CRON_MONTH_OF_YEAR,
+ * and CRON_DAY_OF_WEEK are to be used in <b>getItem()</b> to
+ * retrieve the corresponding <b>CronItem</b>
+ */
+ public static final String CRON_MINUTE = "minute";
+ public static final String CRON_HOUR = "hour";
+ public static final String CRON_DAY_OF_MONTH = "dom";
+ public static final String CRON_MONTH_OF_YEAR = "moy";
+ public static final String CRON_DAY_OF_WEEK = "dow";
+ private ILogger mLogger = CMS.getLogger();
+
+ String mCronString = null;
+
+ CronItem cMinute = null;
+ CronItem cHour = null;
+ CronItem cDOM = null;
+ CronItem cMOY = null;
+ CronItem cDOW = null;
+
+ public JobCron(String cronString)
+ throws EBaseException {
+ mCronString = cronString;
+
+ // create all 5 items in the cron
+ cMinute = new CronItem(0, 59);
+ cHour = new CronItem(0, 23);
+ cDOM = new CronItem(1, 31);
+ cMOY = new CronItem(1, 12);
+ cDOW = new CronItem(0, 6); // 0=Sunday
+
+ cronToVals(mCronString);
+ }
+
+ private void cronToVals(String cronString)
+ throws EBaseException {
+ StringTokenizer st = new StringTokenizer(cronString);
+
+ String sMinute = null;
+ String sHour = null;
+ String sDayOMonth = null;
+ String sMonthOYear = null;
+ String sDayOWeek = null;
+
+ try {
+ if (st.hasMoreTokens()) {
+ sMinute = st.nextToken();
+ cMinute.set(sMinute);
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_JOBS_INVALID_MIN", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_JOB_CRON"));
+ }
+
+ try {
+ if (st.hasMoreTokens()) {
+ sHour = st.nextToken();
+ cHour.set(sHour);
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_JOBS_INVALID_HOUR", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_JOB_CRON"));
+ }
+
+ if (st.hasMoreTokens()) {
+ sDayOMonth = st.nextToken();
+ // cDOM.set(sDayOMonth);
+ }
+
+ try {
+ if (st.hasMoreTokens()) {
+ sMonthOYear = st.nextToken();
+ cMOY.set(sMonthOYear);
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_JOBS_INVALID_MONTH", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_JOB_CRON"));
+ }
+
+ if (st.hasMoreTokens()) {
+ sDayOWeek = st.nextToken();
+ // cDOW.set(sDayOWeek);
+ }
+
+ /**
+ * day-of-month or day-of-week, or both?
+ * if only one of them is '*', the non '*' one prevails,
+ * the '*' one will remain empty (no elements)
+ */
+ // day-of-week
+ if ((sDayOMonth != null)
+ && sDayOMonth.equals(CronItem.ALL) && (sDayOWeek != null) && !sDayOWeek.equals(CronItem.ALL)) {
+ try {
+ cDOW.set(sDayOWeek);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_JOBS_INVALID_DAY_OF_WEEK", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_JOB_CRON"));
+ }
+ } else if ((sDayOMonth != null)
+ && !sDayOMonth.equals(CronItem.ALL) && (sDayOWeek != null) && sDayOWeek.equals(CronItem.ALL)) {
+ try {
+ cDOM.set(sDayOMonth);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_JOBS_INVALID_DAY_OF_MONTH", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_JOB_CRON"));
+ }
+ } else { // if both '*', every day, if neither is '*', do both
+ try {
+ if (sDayOWeek != null) {
+ cDOW.set(sDayOWeek);
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_JOBS_INVALID_DAY_OF_WEEK", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_JOB_CRON"));
+ }
+ try {
+ if (sDayOMonth != null) {
+ cDOM.set(sDayOMonth);
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_JOBS_INVALID_DAY_OF_MONTH", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_JOB_CRON"));
+ }
+ }
+ }
+
+ /**
+ * retrieves the cron item
+ *
+ * @param item name of the item. must be one of the <b>CRON_*</b>
+ * strings defined in this class
+ * @return an instance of the CronItem class which represents the
+ * requested cron item
+ */
+ public CronItem getItem(String item) {
+ if (item.equals(CRON_MINUTE)) {
+ return cMinute;
+ } else if (item.equals(CRON_HOUR)) {
+ return cHour;
+ } else if (item.equals(CRON_DAY_OF_MONTH)) {
+ return cDOM;
+ } else if (item.equals(CRON_MONTH_OF_YEAR)) {
+ return cMOY;
+ } else if (item.equals(CRON_DAY_OF_WEEK)) {
+ return cDOW;
+ } else {
+ // throw...
+ }
+
+ return null;
+ }
+
+ /**
+ * Does the element fit any element in the item
+ *
+ * @param element the element of "now" in cron format
+ * @param item the item consists of a vector of elements
+ * @return boolean (true/false) on whether the element is one of
+ * the elements in the item
+ */
+ boolean isElement(int element, Vector<CronRange> item) {
+ // loop through all of the elements of an item
+ for (Enumeration<CronRange> e = item.elements(); e.hasMoreElements();) {
+ CronRange cElement = e.nextElement();
+
+ // is a number
+ if (cElement.getBegin() == cElement.getEnd()) {
+ if (element == cElement.getBegin()) {
+ return true;
+ }
+ } else { // is a range
+ if ((element >= cElement.getBegin()) &&
+ (element <= cElement.getEnd())) {
+ return true;
+ }
+ }
+ }
+ // no fit
+ return false;
+ }
+
+ /**
+ * convert the day of the week representation from Calendar to
+ * cron
+ *
+ * @param time the Calendar value represents a moment of time
+ * @return an integer value that represents a cron Day-Of-Week
+ * element
+ */
+ public int DOW_cal2cron(Calendar time) {
+ int calDow = time.get(Calendar.DAY_OF_WEEK);
+ int cronDow = 0; // default should never be used
+
+ // convert the Calendar representation of dow to the cron one
+ switch (calDow) {
+ case Calendar.SUNDAY:
+ cronDow = 0;
+ break;
+
+ case Calendar.MONDAY:
+ cronDow = 1;
+ break;
+
+ case Calendar.TUESDAY:
+ cronDow = 2;
+ break;
+
+ case Calendar.WEDNESDAY:
+ cronDow = 3;
+ break;
+
+ case Calendar.THURSDAY:
+ cronDow = 4;
+ break;
+
+ case Calendar.FRIDAY:
+ cronDow = 5;
+ break;
+
+ case Calendar.SATURDAY:
+ cronDow = 6;
+ break;
+
+ default:
+ throw new IllegalArgumentException();
+ }
+
+ return cronDow;
+ }
+
+ /**
+ * convert the month of year representation from Calendar to cron
+ *
+ * @param time the Calendar value represents a moment of time
+ * @return an integer value that represents a cron Month-Of-Year
+ * element
+ */
+ public int MOY_cal2cron(Calendar time) {
+ int calMoy = time.get(Calendar.MONTH);
+ int cronMoy = 0;
+
+ // convert the Calendar representation of moy to the cron one
+ switch (calMoy) {
+ case Calendar.JANUARY:
+ cronMoy = 1;
+ break;
+
+ case Calendar.FEBRUARY:
+ cronMoy = 2;
+ break;
+
+ case Calendar.MARCH:
+ cronMoy = 3;
+ break;
+
+ case Calendar.APRIL:
+ cronMoy = 4;
+ break;
+
+ case Calendar.MAY:
+ cronMoy = 5;
+ break;
+
+ case Calendar.JUNE:
+ cronMoy = 6;
+ break;
+
+ case Calendar.JULY:
+ cronMoy = 7;
+ break;
+
+ case Calendar.AUGUST:
+ cronMoy = 8;
+ break;
+
+ case Calendar.SEPTEMBER:
+ cronMoy = 9;
+ break;
+
+ case Calendar.OCTOBER:
+ cronMoy = 10;
+ break;
+
+ case Calendar.NOVEMBER:
+ cronMoy = 11;
+ break;
+
+ case Calendar.DECEMBER:
+ cronMoy = 12;
+ break;
+
+ default:
+ throw new IllegalArgumentException();
+ }
+
+ return cronMoy;
+ }
+
+ /**
+ * logs an entry in the log file.
+ */
+ protected void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ level, msg);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/jobs/JobsScheduler.java b/base/server/cmscore/src/com/netscape/cmscore/jobs/JobsScheduler.java
new file mode 100644
index 000000000..feabb1f46
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/jobs/JobsScheduler.java
@@ -0,0 +1,509 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.jobs;
+
+import java.util.Calendar;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.jobs.EJobsException;
+import com.netscape.certsrv.jobs.IJob;
+import com.netscape.certsrv.jobs.IJobCron;
+import com.netscape.certsrv.jobs.IJobsScheduler;
+import com.netscape.certsrv.jobs.JobPlugin;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * This is a daemon thread that handles scheduled jobs like cron would
+ * do with different jobs. This daemon wakes up at a pre-configured
+ * interval to see
+ * if there is any job to be done, if so, a thread is created to execute
+ * the job(s).
+ * <p>
+ * The interval <b>jobsScheduler.interval</b> in the configuration is specified as number of minutes. If not set, the
+ * default is 1 minute. Note that the cron specification for each job CAN NOT be finer than the granularity of the
+ * Scheduler daemon interval. For example, if the daemon interval is set to 5 minute, a job cron for every minute at 7am
+ * on each Tuesday (e.g. * 7 * * 2) will result in the execution of the job thread only once every 5 minutes during that
+ * hour. <b>The inteval value is recommended at 1 minute, setting it otherwise has the potential of forever missing the
+ * beat</b>. Use with caution.
+ *
+ * @author cfu
+ * @see JobCron
+ * @version $Revision$, $Date$
+ */
+public class JobsScheduler implements Runnable, IJobsScheduler {
+
+ protected static final long MINUTE_MILLI = 60000;
+ protected static final String DELIM = ",";
+
+ /**
+ * Scheduler thread doing job scheduling
+ */
+ protected String mId = ID;
+ protected Thread mScheduleThread = null;
+
+ public Hashtable<String, JobPlugin> mJobPlugins = new Hashtable<String, JobPlugin>();
+ public Hashtable<String, IJob> mJobs = new Hashtable<String, IJob>();
+ private Hashtable<String, Thread> mJobThreads = new Hashtable<String, Thread>();
+
+ private IConfigStore mConfig = null;
+ private ILogger mLogger = null;
+
+ // in milliseconds. daemon wakeup interval, default 1 minute.
+ private long mInterval = 0;
+
+ // singleton enforcement
+
+ private static JobsScheduler mInstance = new JobsScheduler();
+
+ public static JobsScheduler getInstance() {
+ return mInstance;
+ }
+
+ // end singleton enforcement.
+
+ private JobsScheduler() {
+ }
+
+ /**
+ * read from the config file all implementations of Jobs,
+ * register and initialize them
+ * <p>
+ * the config params have the following formats: jobScheduler.impl.[implementation name].class=[package name]
+ * jobScheduler.job.[job name].pluginName=[implementation name] jobScheduler.job.[job name].cron=[crontab format]
+ * jobScheduler.job.[job name].[any job specific params]=[values]
+ *
+ * @param config jobsScheduler configStore
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException, EJobsException {
+ mLogger = CMS.getLogger();
+
+ // read in config parameters and set variables
+ mConfig = config;
+
+ // getting/setting interval
+ int i;
+
+ try {
+ i = mConfig.getInteger(PROP_INTERVAL);
+ } catch (Exception e) {
+ i = 1; // default 1 minute
+ }
+ setInterval(i);
+
+ IConfigStore c = mConfig.getSubStore(PROP_IMPL);
+ Enumeration<String> mImpls = c.getSubStoreNames();
+
+ // register all job plugins
+ while (mImpls.hasMoreElements()) {
+ String id = mImpls.nextElement();
+ String pluginPath = c.getString(id + "." + PROP_CLASS);
+
+ JobPlugin plugin = new JobPlugin(id, pluginPath);
+
+ mJobPlugins.put(id, plugin);
+ }
+
+ // register all jobs
+ c = config.getSubStore(PROP_JOB);
+ Enumeration<String> jobs = c.getSubStoreNames();
+
+ while (jobs.hasMoreElements()) {
+ String jobName = jobs.nextElement();
+ String implName = c.getString(jobName + "." + PROP_PLUGIN);
+ JobPlugin plugin = mJobPlugins.get(implName);
+
+ if (plugin == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_JOBS_CLASS_NOT_FOUND",
+ implName));
+ throw new EJobsException(CMS.getUserMessage("CMS_JOB_PLUGIN_NOT_FOUND", implName));
+ }
+ String classPath = plugin.getClassPath();
+
+ // instantiate and init the job
+ try {
+ IJob job = (IJob)
+ Class.forName(classPath).newInstance();
+ IConfigStore jconfig = c.getSubStore(jobName);
+
+ job.init(this, jobName, implName, jconfig);
+
+ // register the job
+ mJobs.put(jobName, job);
+
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_JOBS_INIT_ERROR", e.toString()));
+ throw new EJobsException(CMS.getUserMessage("CMS_JOB_LOAD_CLASS_FAILED", classPath));
+
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_JOBS_INIT_ERROR", e.toString()));
+ throw new EJobsException(CMS.getUserMessage("CMS_JOB_LOAD_CLASS_FAILED", classPath));
+
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_JOBS_INIT_ERROR", e.toString()));
+ throw new EJobsException(CMS.getUserMessage("CMS_JOB_LOAD_CLASS_FAILED", classPath));
+
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_JOBS_INIT_ERROR", e.toString()));
+ throw e;
+ }
+ }
+
+ // are we enabled?
+ if (mConfig.getBoolean(PROP_ENABLED, false) == true) {
+ // start the daemon thread
+ startDaemon();
+ }
+ }
+
+ public Hashtable<String, JobPlugin> getPlugins() {
+ return mJobPlugins;
+ }
+
+ public Hashtable<String, IJob> getInstances() {
+ return mJobs;
+ }
+
+ /**
+ * when wake up:
+ * . execute the scheduled job(s)
+ * * if job still running from previous interval, skip it
+ * . figure out when is the next wakeup time (every interval). If
+ * current wakup time runs over the interval, skip the missed interval(s)
+ * . sleep till the next wakeup time
+ */
+ public void run() {
+ long wokeupTime = 0;
+
+ while (true) {
+ // get time now
+ Calendar cal = Calendar.getInstance();
+ long rightNow = cal.getTime().getTime();
+ long duration;
+ long second = cal.get(Calendar.SECOND);
+
+ if (second != 1) { // scheduler needs adjustment
+ // adjust to wake up at 1st second
+ long milliSec = cal.get(Calendar.MILLISECOND);
+
+ // possible to be at exactly second 1, millisecond 0,
+ // just let it skip to next second, fine.
+ duration = (60 - second) * 1000 + 1000 - milliSec;
+ log(ILogger.LL_INFO,
+ "adjustment for cron behavior: sleep for " +
+ duration + " milliseconds");
+ } else {
+
+ // when is the next wakeup time for the JobsScheduler?
+ // reset next wakeup time - wake up every preset interval
+
+ duration = mInterval - rightNow + wokeupTime;
+
+ }
+
+ while (duration < 0) {
+ duration += mInterval;
+ }
+
+ if (duration != 0) {
+ try {
+ Thread.sleep(duration);
+ } catch (InterruptedException e) {
+ System.out.println(e);
+ }
+ }
+
+ // if (duration == 0), it's time
+
+ // woke up...
+ try {
+ if (mConfig.getBoolean(PROP_ENABLED, false) == false) {
+ return;
+ }
+ } catch (Exception e) {
+ return;
+ }
+
+ // check to see if new jobs are registered
+ // ... later
+
+ // get time now
+ cal = Calendar.getInstance();
+
+ /**
+ * Get the current time outside the jobs while loop
+ * to make sure that the rightful jobs are run
+ * -- milliseconds from the epoch
+ */
+ wokeupTime = cal.getTime().getTime();
+
+ for (Enumeration<IJob> e = mJobs.elements(); e.hasMoreElements(); ) {
+ IJob job = e.nextElement();
+
+ // is it enabled?
+ IConfigStore cs = job.getConfigStore();
+
+ try {
+ if (cs.getBoolean(PROP_ENABLED, false) == false)
+ continue;
+ } catch (Exception ex) {
+ continue; // ignore this job
+ }
+
+ // first, check to see if thread already running
+ // ...
+
+ // start the job thread if necessary
+ if (isShowTime(job, cal) == true) {
+ // log(ILogger.LL_INFO, "show time for: "+job.getId());
+
+ // if previous thread still alive, skip
+ Thread jthread = mJobThreads.get(job.getId());
+
+ if ((jthread == null) || (!jthread.isAlive())) {
+ Thread jobThread = new Thread((Runnable) job, job.getId());
+
+ jobThread.start();
+ // put into job thread control
+ mJobThreads.put(job.getId(), jobThread);
+ } else {
+ // previous thread still alive, log it
+ log(ILogger.LL_INFO, "Job " + job.getId() +
+ " still running...skipping this round");
+ }
+ }
+ } // for
+
+ }
+ }
+
+ public IJobCron createJobCron(String cs) throws EBaseException {
+ return new JobCron(cs);
+ }
+
+ /**
+ * Is it time for the job?
+ */
+ protected boolean isShowTime(IJob job, Calendar now) {
+ JobCron jcron = (JobCron) job.getJobCron();
+
+ if (jcron == null) {
+ // the impossible has happened
+ log(ILogger.LL_INFO, "isShowTime(): jobcron null");
+ return false;
+ }
+
+ /**
+ * is it the right month?
+ */
+ Vector<CronRange> moy =
+ jcron.getItem(JobCron.CRON_MONTH_OF_YEAR).getElements();
+
+ int cronMoy = jcron.MOY_cal2cron(now);
+
+ if (jcron.isElement(cronMoy, moy) == false) {
+ return false;
+ }
+ // is the right month!
+
+ /**
+ * is it the right date?
+ */
+ Vector<CronRange> dow = jcron.getItem(JobCron.CRON_DAY_OF_WEEK).getElements();
+ Vector<CronRange> dom = jcron.getItem(JobCron.CRON_DAY_OF_MONTH).getElements();
+
+ // can't be both empty
+ if ((dow.isEmpty()) && dom.isEmpty()) {
+ // throw... or return false?
+ }
+
+ int cronDow = jcron.DOW_cal2cron(now);
+
+ if ((jcron.isElement(cronDow, dow) == false) &&
+ (jcron.isElement(now.get(Calendar.DAY_OF_MONTH), dom) == false)) {
+ return false;
+ }
+ // is the right date!
+
+ /**
+ * is it the right hour?
+ */
+ Vector<CronRange> hour = jcron.getItem(JobCron.CRON_HOUR).getElements();
+
+ if (jcron.isElement(now.get(Calendar.HOUR_OF_DAY), hour) == false) {
+ return false;
+ }
+ // is the right hour!
+
+ /**
+ * is it the right minute?
+ */
+ Vector<CronRange> minute = jcron.getItem(JobCron.CRON_MINUTE).getElements();
+
+ if (jcron.isElement(now.get(Calendar.MINUTE), minute) == false) {
+ return false;
+ }
+ // is the right minute! We're on!
+
+ return true;
+ }
+
+ /**
+ * Retrieves id (name) of this subsystem.
+ *
+ * @return name of the Jobs Scheduler subsystem
+ */
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * Sets id string to this subsystem.
+ * <p>
+ * Use with caution. Should not do it when sharing with others
+ *
+ * @param id name to be applied to an Jobs Scheduler subsystem
+ */
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ /**
+ * creates and starts the daemon thread
+ */
+ public void startDaemon() {
+ mScheduleThread = new Thread(this, "JobScheduler");
+ log(ILogger.LL_INFO, "started Jobs Scheduler daemon thread");
+ mScheduleThread.setDaemon(true);
+ mScheduleThread.start();
+ }
+
+ /**
+ * registers the administration servlet with the administration subsystem.
+ */
+ public void startup() throws EBaseException {
+ //remove, already logged from S_ADMIN
+ //String infoMsg = "Jobs Scheduler subsystem administration Servlet registered";
+ //log(ILogger.LL_INFO, infoMsg);
+ }
+
+ /**
+ * shuts down Jobs one by one.
+ * <P>
+ */
+ public void shutdown() {
+ for (IJob job : mJobs.values()) {
+ job.stop();
+ }
+ }
+
+ /**
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Gets configuration parameters for the given
+ * job plugin.
+ *
+ * @param implName Name of the job plugin.
+ * @return Hashtable of required parameters.
+ */
+ public String[] getConfigParams(String implName)
+ throws EJobsException {
+ if (Debug.ON)
+ Debug.trace("in getCofigParams()");
+
+ // is this a registered implname?
+ JobPlugin plugin = mJobPlugins.get(implName);
+
+ if (plugin == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_JOBS_CLASS_NOT_FOUND", implName));
+ if (Debug.ON)
+ Debug.trace("Job plugin " + implName + " not found.");
+ throw new EJobsException(CMS.getUserMessage("CMS_JOB_PLUGIN_NOT_FOUND",
+ implName));
+ }
+
+ // XXX can find an instance of this plugin in existing
+ // auth manager instantces to avoid instantiation just for this.
+
+ // a temporary instance
+ String className = plugin.getClassPath();
+
+ if (Debug.ON)
+ Debug.trace("className = " + className);
+ try {
+ IJob jobInst = (IJob)
+ Class.forName(className).newInstance();
+ if (Debug.ON)
+ Debug.trace("class instantiated");
+ return (jobInst.getConfigParams());
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_JOBS_CREATE_NEW", e.toString()));
+ if (Debug.ON)
+ Debug.trace("class NOT instantiated: " + e);
+ throw new EJobsException(CMS.getUserMessage("CMS_JOB_LOAD_CLASS_FAILED", className));
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_JOBS_CREATE_NEW", e.toString()));
+ if (Debug.ON)
+ Debug.trace("class NOT instantiated: " + e);
+ throw new EJobsException(CMS.getUserMessage("CMS_JOB_LOAD_CLASS_FAILED", className));
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_JOBS_CREATE_NEW", e.toString()));
+ if (Debug.ON)
+ Debug.trace("class NOT instantiated: " + e);
+ throw new EJobsException(CMS.getUserMessage("CMS_JOB_LOAD_CLASS_FAILED", className));
+ }
+ }
+
+ public void setInterval(int minutes) {
+ mInterval = minutes * MINUTE_MILLI;
+ }
+
+ /**
+ * logs an entry in the log file.
+ */
+ public void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ level, msg);
+ }
+
+ public Hashtable<String, JobPlugin> getJobPlugins() {
+ return mJobPlugins;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapAndExpression.java b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapAndExpression.java
new file mode 100644
index 000000000..7c1fa979e
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapAndExpression.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldap;
+
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.publish.ILdapExpression;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class represents an expression of the form
+ * <var1 op val1 AND var2 op va2>.
+ *
+ * Expressions are used as predicates for publishing rule selection.
+ *
+ * @author mzhao
+ * @version $Revision$, $Date$
+ */
+public class LdapAndExpression implements ILdapExpression {
+ private ILdapExpression mExp1;
+ private ILdapExpression mExp2;
+
+ public LdapAndExpression(ILdapExpression exp1, ILdapExpression exp2) {
+ mExp1 = exp1;
+ mExp2 = exp2;
+ }
+
+ public boolean evaluate(SessionContext sc)
+ throws ELdapException {
+ // If an expression is missing we assume applicability.
+ if (mExp1 == null && mExp2 == null)
+ return true;
+ else if (mExp1 != null && mExp2 != null)
+ return mExp1.evaluate(sc) && mExp2.evaluate(sc);
+ else if (mExp1 == null)
+ return mExp2.evaluate(sc);
+ else
+ // (if mExp2 == null)
+ return mExp1.evaluate(sc);
+ }
+
+ public boolean evaluate(IRequest req)
+ throws ELdapException {
+ // If an expression is missing we assume applicability.
+ if (mExp1 == null && mExp2 == null)
+ return true;
+ else if (mExp1 != null && mExp2 != null)
+ return mExp1.evaluate(req) && mExp2.evaluate(req);
+ else if (mExp1 == null)
+ return mExp2.evaluate(req);
+ else
+ // (if mExp2 == null)
+ return mExp1.evaluate(req);
+ }
+
+ public String toString() {
+ return mExp1.toString() + " AND " + mExp2.toString();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapConnModule.java b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapConnModule.java
new file mode 100644
index 000000000..859e442fa
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapConnModule.java
@@ -0,0 +1,132 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldap;
+
+import netscape.ldap.LDAPConnection;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ILdapBoundConnFactory;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.ldap.ILdapConnInfo;
+import com.netscape.certsrv.ldap.ILdapConnModule;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmscore.ldapconn.LdapAuthInfo;
+import com.netscape.cmscore.ldapconn.LdapBoundConnFactory;
+import com.netscape.cmscore.ldapconn.LdapConnInfo;
+
+public class LdapConnModule implements ILdapConnModule {
+ protected IConfigStore mConfig = null;
+ protected LdapBoundConnFactory mLdapConnFactory = null;
+ protected ILogger mLogger = CMS.getLogger();
+ private boolean mInited = false;
+
+ /**
+ * instantiate connection factory.
+ */
+
+ public static final String PROP_LDAP = "ldap";
+
+ public LdapConnModule() {
+ }
+
+ public LdapConnModule(LdapBoundConnFactory factory) {
+ mLdapConnFactory = factory;
+ mInited = true;
+ }
+
+ protected ISubsystem mPubProcessor;
+
+ public void init(ISubsystem p,
+ IConfigStore config)
+ throws EBaseException {
+
+ CMS.debug("LdapConnModule: init called");
+ if (mInited) {
+ CMS.debug("LdapConnModule: already initialized. return.");
+ return;
+ }
+ CMS.debug("LdapConnModule: init begins");
+
+ mPubProcessor = p;
+ mConfig = config;
+ /*
+ mLdapConnFactory = new LdapBoundConnFactory();
+ mLdapConnFactory.init(mConfig.getSubStore("ldap"));
+ */
+
+ // support publishing dirsrv with different pwd than internaldb
+ IConfigStore ldap = mConfig.getSubStore("ldap");
+
+ IConfigStore ldapconn = ldap.getSubStore(
+ ILdapBoundConnFactory.PROP_LDAPCONNINFO);
+ IConfigStore authinfo = ldap.getSubStore(
+ ILdapBoundConnFactory.PROP_LDAPAUTHINFO);
+ ILdapConnInfo connInfo =
+ CMS.getLdapConnInfo(ldapconn);
+ LdapAuthInfo authInfo =
+ new LdapAuthInfo(authinfo, ldapconn.getString("host"),
+ ldapconn.getInteger("port"), connInfo.getSecure());
+
+ int minConns = mConfig.getInteger(ILdapBoundConnFactory.PROP_MINCONNS, 3);
+ int maxConns = mConfig.getInteger(ILdapBoundConnFactory.PROP_MAXCONNS, 15);
+ // must get authInfo from the config, don't default to internaldb!!!
+
+ CMS.debug("Creating LdapBoundConnFactory for LdapConnModule.");
+ mLdapConnFactory =
+ new LdapBoundConnFactory(minConns, maxConns, (LdapConnInfo) connInfo, authInfo);
+
+ mInited = true;
+
+ CMS.debug("LdapConnModule: init ends");
+ }
+
+ /**
+ * Returns the internal ldap connection factory.
+ * This can be useful to get a ldap connection to the
+ * ldap publishing directory without having to get it again from the
+ * config file. Note that this means sharing a ldap connection pool
+ * with the ldap publishing module so be sure to return connections to pool.
+ * Use ILdapConnFactory.getConn() to get a Ldap connection to the ldap
+ * publishing directory.
+ * Use ILdapConnFactory.returnConn() to return the connection.
+ *
+ * @see com.netscape.certsrv.ldap.ILdapBoundConnFactory
+ * @see com.netscape.certsrv.ldap.ILdapConnFactory
+ */
+ public ILdapConnFactory getLdapConnFactory() {
+ return mLdapConnFactory;
+ }
+
+ public LDAPConnection getConn() throws ELdapException {
+ return mLdapConnFactory.getConn();
+ }
+
+ public void returnConn(LDAPConnection conn) throws ELdapException {
+ mLdapConnFactory.returnConn(conn);
+ }
+
+ public void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_LDAP, level,
+ "LdapPublishModule: " + msg);
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapOrExpression.java b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapOrExpression.java
new file mode 100644
index 000000000..92a9b902e
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapOrExpression.java
@@ -0,0 +1,80 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldap;
+
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.publish.ILdapExpression;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class represents an Or expression of the form
+ * (var1 op val1 OR var2 op val2).
+ *
+ * Expressions are used as predicates for publishing rule selection.
+ *
+ * @author mzhao
+ * @version $Revision$, $Date$
+ */
+public class LdapOrExpression implements ILdapExpression {
+ private ILdapExpression mExp1;
+ private ILdapExpression mExp2;
+
+ public LdapOrExpression(ILdapExpression exp1, ILdapExpression exp2) {
+ mExp1 = exp1;
+ mExp2 = exp2;
+ }
+
+ public boolean evaluate(SessionContext sc)
+ throws ELdapException {
+ if (mExp1 == null && mExp2 == null)
+ return true;
+ else if (mExp1 != null && mExp2 != null)
+ return mExp1.evaluate(sc) || mExp2.evaluate(sc);
+ else if (mExp1 != null && mExp2 == null)
+ return mExp1.evaluate(sc);
+ else
+ // (mExp1 == null && mExp2 != null)
+ return mExp2.evaluate(sc);
+ }
+
+ public boolean evaluate(IRequest req)
+ throws ELdapException {
+ if (mExp1 == null && mExp2 == null)
+ return true;
+ else if (mExp1 != null && mExp2 != null)
+ return mExp1.evaluate(req) || mExp2.evaluate(req);
+ else if (mExp1 != null && mExp2 == null)
+ return mExp1.evaluate(req);
+ else
+ // (mExp1 == null && mExp2 != null)
+ return mExp2.evaluate(req);
+ }
+
+ public String toString() {
+ if (mExp1 == null && mExp2 == null)
+ return "";
+ else if (mExp1 != null && mExp2 != null)
+ return mExp1.toString() + " OR " + mExp2.toString();
+ else if (mExp1 != null && mExp2 == null)
+ return mExp1.toString();
+ else
+ // (mExp1 == null && mExp2 != null)
+ return mExp2.toString();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapPredicateParser.java b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapPredicateParser.java
new file mode 100644
index 000000000..8d98f21b7
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapPredicateParser.java
@@ -0,0 +1,336 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldap;
+
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.publish.ILdapExpression;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * Default implementation of predicate parser.
+ *
+ * Limitations:
+ *
+ * 1. Currently parentheses are not suported.
+ * 2. Only ==, != <, >, <= and >= operators are supported.
+ * 3. The only boolean operators supported are AND and OR. AND takes precedence
+ * over OR. Example: a AND b OR e OR c AND d
+ * is treated as (a AND b) OR e OR (c AND d)
+ * 4. If this is n't adequate, roll your own.
+ *
+ * @author mzhao
+ * @version $Revision$, $Date$
+ */
+public class LdapPredicateParser {
+ public static final int OP_AND = 1;
+ public static final int OP_OR = 2;
+ public static final int EXPRESSION = 0;
+
+ public static final String AND = "AND";
+ public static final String OR = "OR";
+
+ private static final char COMMA = ',';
+
+ /**
+ * Parse the predicate expression and return a vector of expressions.
+ *
+ * @param predicateExp The predicate expression as read from the config file.
+ * @return expVector The vector of expressions.
+ */
+ public static ILdapExpression parse(String predicateExpression)
+ throws ELdapException {
+ if (predicateExpression == null ||
+ predicateExpression.length() == 0)
+ return null;
+ PredicateTokenizer pt = new PredicateTokenizer(predicateExpression);
+
+ if (pt == null || !pt.hasMoreTokens())
+ return null;
+
+ // The first token cannot be an operator. We are not dealing with
+ // reverse-polish notation.
+ String token = pt.nextToken();
+
+ if (getOP(token) != EXPRESSION) {
+ if (Debug.ON)
+ Debug.trace("Malformed expression: " + predicateExpression);
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_BAD_LDAP_EXPRESSION", predicateExpression));
+ }
+ ILdapExpression current = parseExpression(token);
+ boolean malformed = false;
+ Vector<ILdapExpression> expSet = new Vector<ILdapExpression>();
+ int prevType = EXPRESSION;
+
+ while (pt.hasMoreTokens()) {
+ token = pt.nextToken();
+ int curType = getOP(token);
+
+ if ((prevType != EXPRESSION && curType != EXPRESSION) ||
+ (prevType == EXPRESSION && curType == EXPRESSION)) {
+ malformed = true;
+ break;
+ }
+
+ // If an operator seen skip to the next token
+ if (curType != EXPRESSION) {
+ prevType = curType;
+ continue;
+ }
+
+ // If the previous type was an OR token, add the current expression to
+ // the expression set;
+ if (prevType == OP_OR) {
+ expSet.addElement(current);
+ current = parseExpression(token);
+ prevType = curType;
+ continue;
+ }
+
+ // If the previous type was an AND token, make an AND expression
+ if (prevType == OP_AND) {
+ current = new LdapAndExpression(current, parseExpression(token));
+ prevType = curType;
+ }
+ }
+ if (malformed) {
+ if (Debug.ON)
+ Debug.trace("Malformed expression: " + predicateExpression);
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_BAD_LDAP_EXPRESSION",
+ predicateExpression));
+ }
+
+ // Form an LdapOrExpression
+ if (current != null)
+ expSet.addElement(current);
+
+ int size = expSet.size();
+
+ if (size == 0)
+ return null;
+ LdapOrExpression orExp = new
+ LdapOrExpression(expSet.elementAt(0), null);
+
+ for (int i = 1; i < size; i++)
+ orExp = new LdapOrExpression(orExp, expSet.elementAt(i));
+ return orExp;
+ }
+
+ private static int getOP(String token) {
+ if (token.equalsIgnoreCase(AND))
+ return OP_AND;
+ else if (token.equalsIgnoreCase(OR))
+ return OP_OR;
+ else
+ return EXPRESSION;
+ }
+
+ private static ILdapExpression parseExpression(String input)
+ throws ELdapException {
+ // If the expression has multiple parts separated by commas
+ // we need to construct an AND expression. Else we will return a
+ // simple expression.
+ int commaIndex = input.indexOf(COMMA);
+
+ if (commaIndex < 0)
+ return LdapSimpleExpression.parse(input);
+ int currentIndex = 0;
+ Vector<LdapSimpleExpression> expVector = new Vector<LdapSimpleExpression>();
+
+ while (commaIndex > 0) {
+ LdapSimpleExpression exp = (LdapSimpleExpression)
+ LdapSimpleExpression.parse(input.substring(currentIndex,
+ commaIndex));
+
+ expVector.addElement(exp);
+ currentIndex = commaIndex + 1;
+ commaIndex = input.indexOf(COMMA, currentIndex);
+ }
+ if (currentIndex < (input.length() - 1)) {
+ LdapSimpleExpression exp = (LdapSimpleExpression)
+ LdapSimpleExpression.parse(input.substring(currentIndex));
+
+ expVector.addElement(exp);
+ }
+
+ int size = expVector.size();
+ LdapSimpleExpression exp1 = expVector.elementAt(0);
+ LdapSimpleExpression exp2 = expVector.elementAt(1);
+ LdapAndExpression andExp = new LdapAndExpression(exp1, exp2);
+
+ for (int i = 2; i < size; i++) {
+ andExp = new LdapAndExpression(andExp, expVector.elementAt(i));
+ }
+ return andExp;
+ }
+
+ public static void main(String[] args) {
+
+ /**
+ * AttributeSet req = new AttributeSet();
+ * try
+ * {
+ * req.set("ou", "people");
+ * req.set("cn", "John Doe");
+ * req.set("uid", "jdoes");
+ * req.set("o", "airius.com");
+ * req.set("certtype", "client");
+ * req.set("request", "issuance");
+ * req.set("id", new Integer(10));
+ * req.set("dualcerts", new Boolean(true));
+ *
+ * Vector v = new Vector();
+ * v.addElement("one");
+ * v.addElement("two");
+ * v.addElement("three");
+ * req.set("count", v);
+ * }
+ * catch (Exception e){e.printStackTrace();}
+ * String[] array = { "ou == people AND certtype == client",
+ * "ou == servergroup AND certtype == server",
+ * "uid == jdoes, ou==people, o==airius.com OR ou == people AND certType == client OR certType == server AND cn == needles.mcom.com"
+ * ,
+ * };
+ * for (int i = 0; i < array.length; i++)
+ * {
+ * System.out.println();
+ * System.out.println("String: " + array[i]);
+ * ILdapExpression exp = null;
+ * try
+ * {
+ * exp = parse(array[i]);
+ * if (exp != null)
+ * {
+ * System.out.println("Parsed Expression: " + exp);
+ * boolean result = exp.evaluate(req);
+ * System.out.println("Result: " + result);
+ * }
+ * }
+ * catch (Exception e) {e.printStackTrace(); }
+ * }
+ *
+ *
+ * try
+ * {
+ * BufferedReader rdr = new BufferedReader(
+ * new FileReader(args[0]));
+ * String line;
+ * while((line=rdr.readLine()) != null)
+ * {
+ * System.out.println();
+ * System.out.println("Line Read: " + line);
+ * ILdapExpression exp = null;
+ * try
+ * {
+ * exp = parse(line);
+ * if (exp != null)
+ * {
+ * System.out.println(exp);
+ * boolean result = exp.evaluate(req);
+ * System.out.println("Result: " + result);
+ * }
+ *
+ * }catch (Exception e){e.printStackTrace();}
+ * }
+ * }
+ * catch (Exception e){e.printStackTrace(); }
+ **/
+ }
+
+}
+
+class PredicateTokenizer {
+ String input;
+ int currentIndex;
+ String nextToken;
+
+ public PredicateTokenizer(String predString) {
+ input = predString;
+ currentIndex = 0;
+ nextToken = null;
+ }
+
+ public boolean hasMoreTokens() {
+ return (currentIndex != -1);
+ }
+
+ public String nextToken() throws ELdapException {
+ if (nextToken != null) {
+ String toReturn = nextToken;
+
+ nextToken = null;
+ return toReturn;
+ }
+
+ int andIndex = input.indexOf(" AND", currentIndex);
+
+ if (andIndex < 0)
+ andIndex = input.indexOf(" and", currentIndex);
+ int orIndex = input.indexOf(" OR", currentIndex);
+
+ if (orIndex < 0)
+ orIndex = input.indexOf(" or", currentIndex);
+ String toReturn = null;
+
+ if (andIndex == -1 && orIndex == -1) {
+ if (currentIndex == 0) {
+ currentIndex = -1;
+ toReturn = input;
+ } else {
+ int temp = currentIndex;
+
+ currentIndex = -1;
+ toReturn = input.substring(temp);
+ }
+ } else if (andIndex >= 0 && (andIndex < orIndex || orIndex == -1)) {
+ if (currentIndex != andIndex) {
+ toReturn = input.substring(currentIndex, andIndex);
+ nextToken = input.substring(andIndex + 1, andIndex + 4);
+ currentIndex = andIndex + 4;
+ } else {
+ toReturn = "AND";
+ currentIndex += 4;
+ }
+ } else if (orIndex >= 0 && (orIndex < andIndex || andIndex == -1)) {
+ if (currentIndex != orIndex) {
+ toReturn = input.substring(currentIndex, orIndex);
+ nextToken = input.substring(orIndex + 1, orIndex + 3);
+ currentIndex = orIndex + 3;
+ } else {
+ toReturn = "OR";
+ currentIndex += 3;
+ }
+ } else {
+ // Cannot happen; Assert here.
+ if (Debug.ON)
+ Debug.trace("Malformed expression: Null Token");
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_BAD_LDAP_EXPRESSION"));
+ }
+
+ String trimmed = toReturn.trim();
+
+ if (trimmed.length() == 0)
+ return nextToken();
+ else
+ return trimmed;
+
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapPublishModule.java b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapPublishModule.java
new file mode 100644
index 000000000..c4ff20515
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapPublishModule.java
@@ -0,0 +1,782 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldap;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import netscape.ldap.LDAPConnection;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CRLImpl;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapMapper;
+import com.netscape.certsrv.publish.ILdapPlugin;
+import com.netscape.certsrv.publish.ILdapPublishModule;
+import com.netscape.certsrv.publish.ILdapPublisher;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestListener;
+import com.netscape.cmscore.dbs.CertRecord;
+import com.netscape.cmscore.ldapconn.LdapBoundConnFactory;
+import com.netscape.cmscore.util.Debug;
+
+public class LdapPublishModule implements ILdapPublishModule {
+ protected IConfigStore mConfig = null;
+ protected LdapBoundConnFactory mLdapConnFactory = null;
+ protected ILogger mLogger = CMS.getLogger();
+ private boolean mInited = false;
+ protected ICertAuthority mAuthority = null;
+
+ /**
+ * hashtable of cert types to cert mappers and publishers.
+ * cert types are client, server, ca, subca, ra, crl, etc.
+ * XXX the cert types need to be consistently used.
+ * for each, the mapper may be null, in which case the full subject
+ * name is used to map the cert.
+ * for crl, if the mapper is null the ca mapper is used. if that
+ * is null, the full issuer name is used.
+ * XXX if we support crl issuing points the issuing point should be used
+ * to publish the crl.
+ * When publishers are null, the certs are not published.
+ */
+ protected Hashtable<String, LdapMappers> mMappers = new Hashtable<String, LdapMappers>();
+
+ /**
+ * handlers for request types (events)
+ * values implement IRequestListener
+ */
+ protected Hashtable<String, IRequestListener> mEventHandlers = new Hashtable<String, IRequestListener>();
+
+ /**
+ * instantiate connection factory.
+ */
+ public static final String ATTR_LDAPPUBLISH_STATUS = "LdapPublishStatus";
+ public static final String PROP_LDAP = "ldap";
+ public static final String PROP_MAPPER = "mapper";
+ public static final String PROP_PUBLISHER = "publisher";
+ public static final String PROP_CLASS = "class";
+ public static final String PROP_TYPE = "type";
+ public static final String PROP_TYPE_CA = "ca";
+ public static final String PROP_TYPE_CLIENT = "client";
+ public static final String PROP_TYPE_CRL = "crl";
+
+ public LdapPublishModule() {
+ }
+
+ public void init(ISubsystem sub, IConfigStore config) throws EBaseException {
+ }
+
+ public void set(String name, String val) {
+ }
+
+ public LdapPublishModule(LdapBoundConnFactory factory) {
+ mLdapConnFactory = factory;
+ mInited = true;
+ }
+
+ protected IPublisherProcessor mPubProcessor;
+
+ public void init(ICertAuthority authority, IPublisherProcessor p,
+ IConfigStore config)
+ throws EBaseException {
+ if (mInited)
+ return;
+
+ mAuthority = authority;
+ mPubProcessor = p;
+ mConfig = config;
+ mLdapConnFactory = new LdapBoundConnFactory();
+ mLdapConnFactory.init(mConfig.getSubStore("ldap"));
+
+ // initMappers(config);
+ initHandlers();
+
+ mAuthority.registerRequestListener(this);
+ }
+
+ public void init(ICertAuthority authority, IConfigStore config)
+ throws EBaseException {
+ if (mInited)
+ return;
+
+ mAuthority = authority;
+ mConfig = config;
+ mLdapConnFactory = new LdapBoundConnFactory();
+ mLdapConnFactory.init(mConfig.getSubStore("ldap"));
+
+ initMappers(config);
+ initHandlers();
+
+ mAuthority.registerRequestListener(this);
+ }
+
+ /**
+ * Returns the internal ldap connection factory.
+ * This can be useful to get a ldap connection to the
+ * ldap publishing directory without having to get it again from the
+ * config file. Note that this means sharing a ldap connection pool
+ * with the ldap publishing module so be sure to return connections to pool.
+ * Use ILdapConnFactory.getConn() to get a Ldap connection to the ldap
+ * publishing directory.
+ * Use ILdapConnFactory.returnConn() to return the connection.
+ *
+ * @see com.netscape.certsrv.ldap.ILdapBoundConnFactory
+ * @see com.netscape.certsrv.ldap.ILdapConnFactory
+ */
+ public ILdapConnFactory getLdapConnFactory() {
+ return mLdapConnFactory;
+ }
+
+ /**
+ * Returns the connection factory to the publishing directory.
+ * Must return the connection once you return
+ */
+
+ protected LdapMappers getMappers(String certType) {
+ LdapMappers mappers = null;
+
+ if (certType == null) {
+ mappers = mMappers.get(PROP_TYPE_CLIENT);
+ } else {
+ mappers = mMappers.get(certType);
+ }
+ return mappers;
+ }
+
+ protected void initMappers(IConfigStore config)
+ throws EBaseException {
+ IConfigStore types = mConfig.getSubStore(PROP_TYPE);
+
+ if (types == null || types.size() <= 0) {
+ // nothing configured.
+ if (Debug.ON)
+ System.out.println("No ldap publishing configurations.");
+ return;
+ }
+ Enumeration<String> substores = types.getSubStoreNames();
+
+ while (substores.hasMoreElements()) {
+ String certType = substores.nextElement();
+ IConfigStore current = types.getSubStore(certType);
+
+ if (current == null || current.size() <= 0) {
+ CMS.debug(
+ "No ldap publish configuration for " + certType + " found.");
+ continue;
+ }
+ ILdapPlugin mapper = null, publisher = null;
+ IConfigStore mapperConf = null, publisherConf = null;
+ String mapperClassName = null, publisherClassName = null;
+
+ try {
+ mapperConf = current.getSubStore(PROP_MAPPER);
+ mapperClassName = mapperConf.getString(PROP_CLASS, null);
+ if (mapperClassName != null && mapperClassName.length() > 0) {
+ CMS.debug(
+ "mapper " + mapperClassName + " for " + certType);
+ mapper = (ILdapPlugin)
+ Class.forName(mapperClassName).newInstance();
+ mapper.init(mapperConf);
+ }
+ publisherConf = current.getSubStore(PROP_PUBLISHER);
+ publisherClassName = publisherConf.getString(PROP_CLASS, null);
+ if (publisherClassName != null &&
+ publisherClassName.length() > 0) {
+ CMS.debug(
+ "publisher " + publisherClassName + " for " + certType);
+ publisher = (ILdapPlugin)
+ Class.forName(publisherClassName).newInstance();
+ publisher.init(publisherConf);
+ }
+ mMappers.put(certType, new LdapMappers(mapper, publisher));
+ } catch (ClassNotFoundException e) {
+ String missingClass = mapperClassName +
+ ((publisherClassName == null) ? "" :
+ (" or " + publisherClassName));
+
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_FIND_CLASS", missingClass));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_CLASS_NOT_FOUND", missingClass));
+ } catch (InstantiationException e) {
+ String badInstance = mapperClassName +
+ ((publisherClassName == null) ? "" :
+ (" or " + publisherClassName));
+
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_INST_CLASS",
+ badInstance, certType));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INSTANTIATING_CLASS_FAILED", badInstance));
+ } catch (IllegalAccessException e) {
+ String badInstance = mapperClassName +
+ ((publisherClassName == null) ? "" :
+ (" or " + publisherClassName));
+
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_INSUFFICIENT_CREDENTIALS", badInstance, certType));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INSUFFICIENT_CREDENTIALS", certType));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_INIT_ERROR", certType, e.toString()));
+ throw e;
+ }
+ }
+ mInited = true;
+ }
+
+ protected void initHandlers() {
+ mEventHandlers.put(IRequest.ENROLLMENT_REQUEST,
+ new HandleEnrollment(this));
+ mEventHandlers.put(IRequest.RENEWAL_REQUEST,
+ new HandleRenewal(this));
+ mEventHandlers.put(IRequest.REVOCATION_REQUEST,
+ new HandleRevocation(this));
+ mEventHandlers.put(IRequest.UNREVOCATION_REQUEST,
+ new HandleUnrevocation(this));
+ }
+
+ public void accept(IRequest r) {
+ String type = r.getRequestType();
+
+ IRequestListener handler = mEventHandlers.get(type);
+
+ if (handler == null) {
+ CMS.debug(
+ "Nothing to publish for request type " + type);
+ return;
+ }
+ handler.accept(r);
+ }
+
+ public void publish(String certType, X509Certificate cert)
+ throws ELdapException {
+ // get mapper and publisher for cert type.
+ LdapMappers mappers = getMappers(certType);
+
+ if (mappers == null || mappers.publisher == null) {
+ CMS.debug("publisher for " + certType + " is null");
+ return;
+ }
+ publish((ILdapMapper) mappers.mapper,
+ (ILdapPublisher) mappers.publisher, cert);
+
+ // set the ldap published flag.
+ setPublishedFlag(cert.getSerialNumber(), true);
+ }
+
+ public void unpublish(String certType, X509Certificate cert)
+ throws ELdapException {
+ // get mapper and publisher for cert type.
+ LdapMappers mappers = getMappers(certType);
+
+ if (mappers == null || mappers.publisher == null) {
+ CMS.debug("publisher for " + certType + " is null");
+ return;
+ }
+ unpublish((ILdapMapper) mappers.mapper,
+ (ILdapPublisher) mappers.publisher, cert);
+
+ // set the ldap published flag.
+ setPublishedFlag(cert.getSerialNumber(), false);
+ }
+
+ /**
+ * set published flag - true when published, false when unpublished.
+ * not exist means not published.
+ */
+ public void setPublishedFlag(BigInteger serialNo, boolean published) {
+ if (!(mAuthority instanceof ICertificateAuthority))
+ return;
+ ICertificateAuthority ca = (ICertificateAuthority) mAuthority;
+
+ try {
+ ICertificateRepository certdb = ca.getCertificateRepository();
+ ICertRecord certRec = certdb.readCertificateRecord(serialNo);
+ MetaInfo metaInfo = certRec.getMetaInfo();
+
+ if (metaInfo == null) {
+ metaInfo = new MetaInfo();
+ }
+ metaInfo.set(
+ CertRecord.META_LDAPPUBLISH, String.valueOf(published));
+ ModificationSet modSet = new ModificationSet();
+
+ modSet.add(ICertRecord.ATTR_META_INFO,
+ Modification.MOD_REPLACE, metaInfo);
+ certdb.modifyCertificateRecord(serialNo, modSet);
+ } catch (EBaseException e) {
+ // not fatal. just log warning.
+ log(ILogger.LL_WARN,
+ "Cannot mark cert 0x" + serialNo.toString(16) + " published as " + published +
+ " in the ldap directory. Cert Record not found. Error: " +
+ e.getMessage());
+ }
+ }
+
+ public LDAPConnection getConn() throws ELdapException {
+ return mLdapConnFactory.getConn();
+ }
+
+ public void returnConn(LDAPConnection conn) throws ELdapException {
+ mLdapConnFactory.returnConn(conn);
+ }
+
+ public void publish(ILdapMapper mapper, ILdapPublisher publisher,
+ X509Certificate cert)
+ throws ELdapException {
+ LDAPConnection conn = null;
+
+ try {
+ String dirdn = null;
+ String result = null;
+
+ conn = mLdapConnFactory.getConn();
+ if (mapper == null) { // use the cert's subject name exactly
+ dirdn = cert.getSubjectDN().toString();
+ CMS.debug(
+ "no mapper found. Using subject name exactly." +
+ cert.getSubjectDN());
+ } else {
+ result = mapper.map(conn, cert);
+ dirdn = result;
+ if (dirdn == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_PUBLISH_NOT_MATCH",
+ cert.getSerialNumber().toString(16),
+ cert.getSubjectDN().toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH",
+ cert.getSubjectDN().toString()));
+ }
+ }
+ publisher.publish(conn, dirdn, cert);
+ } finally {
+ if (conn != null) {
+ mLdapConnFactory.returnConn(conn);
+ }
+ }
+ }
+
+ public void unpublish(ILdapMapper mapper, ILdapPublisher publisher,
+ X509Certificate cert)
+ throws ELdapException {
+ LDAPConnection conn = null;
+
+ try {
+ String dirdn = null;
+ String result = null;
+
+ conn = mLdapConnFactory.getConn();
+ if (mapper == null) { // use the cert's subject name exactly
+ dirdn = cert.getSubjectDN().toString();
+ } else {
+ result = mapper.map(conn, cert);
+ dirdn = result;
+ if (dirdn == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_PUBLISH_NOT_MATCH",
+ cert.getSerialNumber().toString(16),
+ cert.getSubjectDN().toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH",
+ cert.getSubjectDN().toString()));
+ }
+ }
+ publisher.unpublish(conn, dirdn, cert);
+ } finally {
+ if (conn != null) {
+ mLdapConnFactory.returnConn(conn);
+ }
+ }
+ }
+
+ /**
+ * publishes a crl by mapping the issuer name in the crl to an entry
+ * and publishing it there. entry must be a certificate authority.
+ */
+ public void publish(X509CRLImpl crl)
+ throws ELdapException {
+
+ LdapMappers mappers = getMappers(PROP_TYPE_CRL);
+
+ if (mappers == null || mappers.publisher == null) {
+ CMS.debug("publisher for crl is null");
+ return;
+ }
+
+ LDAPConnection conn = null;
+ String dn = null;
+
+ try {
+ String result = null;
+
+ conn = mLdapConnFactory.getConn();
+ if (mappers.mapper == null) {
+ dn = ((X500Name) crl.getIssuerDN()).toLdapDNString();
+ } else {
+ result = ((ILdapMapper) mappers.mapper).map(conn, crl);
+ dn = result;
+ if (dn == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_CRL_NOT_MATCH"));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH",
+ crl.getIssuerDN().toString()));
+ }
+ }
+ ((ILdapPublisher) mappers.publisher).publish(conn, dn, crl);
+ } catch (ELdapException e) {
+ //e.printStackTrace();
+ CMS.debug(
+ "Error publishing CRL to " + dn + ": " + e);
+ throw e;
+ } catch (IOException e) {
+ CMS.debug("Error publishing CRL to " + dn + ": " + e);
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_GET_ISSUER_FROM_CRL_FAILED", ""));
+ } finally {
+ if (conn != null) {
+ mLdapConnFactory.returnConn(conn);
+ }
+ }
+ }
+
+ /**
+ * publishes a crl by mapping the issuer name in the crl to an entry
+ * and publishing it there. entry must be a certificate authority.
+ */
+ public void publish(String dn, X509CRL crl)
+ throws ELdapException {
+ LdapMappers mappers = getMappers(PROP_TYPE_CRL);
+
+ if (mappers == null || mappers.publisher == null) {
+ CMS.debug("publisher for crl is null");
+ return;
+ }
+
+ LDAPConnection conn = null;
+
+ try {
+ conn = mLdapConnFactory.getConn();
+ ((ILdapPublisher) mappers.publisher).publish(conn, dn, crl);
+ } catch (ELdapException e) {
+ CMS.debug(
+ "Error publishing CRL to " + dn + ": " + e.toString());
+ throw e;
+ } finally {
+ if (conn != null) {
+ mLdapConnFactory.returnConn(conn);
+ }
+ }
+ }
+
+ public void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_LDAP, level,
+ "LdapPublishModule: " + msg);
+ }
+
+}
+
+class LdapMappers {
+ public LdapMappers(ILdapPlugin aMapper, ILdapPlugin aPublisher) {
+ mapper = aMapper;
+ publisher = aPublisher;
+ }
+
+ public ILdapPlugin mapper = null;
+ public ILdapPlugin publisher = null;
+}
+
+class HandleEnrollment implements IRequestListener {
+ LdapPublishModule mModule = null;
+
+ public HandleEnrollment(LdapPublishModule module) {
+ mModule = module;
+ }
+
+ public void set(String name, String val) {
+ }
+
+ public void init(ISubsystem sub, IConfigStore config) throws EBaseException {
+ }
+
+ public void accept(IRequest r) {
+ CMS.debug(
+ "handling publishing for enrollment request id " +
+ r.getRequestId());
+
+ // in case it's not meant for us
+ if (r.getExtDataInInteger(IRequest.RESULT) == null)
+ return;
+
+ // check if request failed.
+ if ((r.getExtDataInInteger(IRequest.RESULT)).equals(IRequest.RES_ERROR)) {
+ CMS.debug("Request errored. " +
+ "Nothing to publish for enrollment request id " +
+ r.getRequestId());
+ return;
+ }
+ CMS.debug("Checking publishing for request " +
+ r.getRequestId());
+ // check if issued certs is set.
+ X509CertImpl[] certs = r.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ if (certs == null || certs.length == 0 || certs[0] == null) {
+ CMS.debug(
+ "No certs to publish for request id " + r.getRequestId());
+ return;
+ }
+
+ // get mapper and publisher for client certs.
+ LdapMappers mappers =
+ mModule.getMappers(LdapPublishModule.PROP_TYPE_CLIENT);
+
+ if (mappers == null || mappers.publisher == null) {
+ CMS.debug(
+ "In publishing: No publisher for type " +
+ LdapPublishModule.PROP_TYPE_CLIENT);
+ return;
+ }
+
+ // publish
+ Integer results[] = new Integer[certs.length];
+
+ for (int i = 0; i < certs.length; i++) {
+ try {
+ if (certs[i] == null)
+ continue;
+ mModule.publish((ILdapMapper) mappers.mapper,
+ (ILdapPublisher) mappers.publisher, certs[i]);
+ results[i] = IRequest.RES_SUCCESS;
+ CMS.debug(
+ "Published cert serial no 0x" + certs[i].getSerialNumber().toString(16));
+ mModule.setPublishedFlag(certs[i].getSerialNumber(), true);
+ } catch (ELdapException e) {
+ mModule.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_PUBLISH",
+ certs[i].getSerialNumber().toString(16), e.toString()));
+ results[i] = IRequest.RES_ERROR;
+ }
+ r.setExtData("ldapPublishStatus", results);
+ }
+ }
+}
+
+class HandleRenewal implements IRequestListener {
+ private LdapPublishModule mModule = null;
+
+ public HandleRenewal(LdapPublishModule module) {
+ mModule = module;
+ }
+
+ public void init(ISubsystem sub, IConfigStore config) throws EBaseException {
+ }
+
+ public void set(String name, String val) {
+ }
+
+ public void accept(IRequest r) {
+ // Note we do not remove old certs from directory during renewal
+ X509CertImpl[] certs = r.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ if (certs == null || certs.length == 0) {
+ CMS.debug("no certs to publish for renewal " +
+ "request " + r.getRequestId());
+ return;
+ }
+ Integer results[] = new Integer[certs.length];
+ X509CertImpl cert = null;
+
+ // get mapper and publisher for cert type.
+ LdapMappers mappers =
+ mModule.getMappers(LdapPublishModule.PROP_TYPE_CLIENT);
+
+ if (mappers == null || mappers.publisher == null) {
+ CMS.debug(
+ "publisher for " + LdapPublishModule.PROP_TYPE_CLIENT + " is null");
+ return;
+ }
+
+ boolean error = false;
+
+ for (int i = 0; i < certs.length; i++) {
+ cert = certs[i];
+ if (cert == null)
+ continue; // there was an error issuing this cert.
+ try {
+ mModule.publish((ILdapMapper) mappers.mapper,
+ (ILdapPublisher) mappers.publisher, cert);
+ results[i] = IRequest.RES_SUCCESS;
+ mModule.log(ILogger.LL_INFO,
+ "Published cert serial no 0x" + cert.getSerialNumber().toString(16));
+ } catch (ELdapException e) {
+ error = true;
+ mModule.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_PUBLISH",
+ cert.getSerialNumber().toString(16), e.getMessage()));
+ results[i] = IRequest.RES_ERROR;
+ }
+ }
+ r.setExtData("ldapPublishStatus", results);
+ r.setExtData("ldapPublishOverAllStatus",
+ (error == true ? IRequest.RES_ERROR : IRequest.RES_SUCCESS));
+ }
+}
+
+class HandleRevocation implements IRequestListener {
+ private LdapPublishModule mModule = null;
+
+ public HandleRevocation(LdapPublishModule module) {
+ mModule = module;
+ }
+
+ public void init(ISubsystem sub, IConfigStore config) throws EBaseException {
+ }
+
+ public void set(String name, String val) {
+ }
+
+ public void accept(IRequest r) {
+ CMS.debug(
+ "Handle publishing for revoke request id " + r.getRequestId());
+
+ // get fields in request.
+ X509CertImpl[] revcerts = r.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ if (revcerts == null || revcerts.length == 0 || revcerts[0] == null) {
+ // no certs in revoke.
+ CMS.debug(
+ "Nothing to unpublish for revocation " +
+ "request " + r.getRequestId());
+ return;
+ }
+
+ // get mapper and publisher for cert type.
+ LdapMappers mappers =
+ mModule.getMappers(LdapPublishModule.PROP_TYPE_CLIENT);
+
+ if (mappers == null || mappers.publisher == null) {
+ CMS.debug(
+ "publisher for " + LdapPublishModule.PROP_TYPE_CLIENT + " is null");
+ return;
+ }
+
+ boolean error = false;
+ Integer results[] = new Integer[revcerts.length];
+
+ for (int i = 0; i < revcerts.length; i++) {
+ X509CertImpl cert = revcerts[i];
+
+ results[i] = IRequest.RES_ERROR;
+ try {
+ mModule.unpublish((ILdapMapper) mappers.mapper,
+ (ILdapPublisher) mappers.publisher, cert);
+ results[i] = IRequest.RES_SUCCESS;
+ CMS.debug(
+ "Unpublished cert serial no 0x" + cert.getSerialNumber().toString(16));
+ } catch (ELdapException e) {
+ error = true;
+ mModule.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_UNPUBLISH",
+ cert.getSerialNumber().toString(16), e.getMessage()));
+ }
+ }
+ r.setExtData("ldapPublishStatus", results);
+ r.setExtData("ldapPublishOverAllStatus",
+ (error == true ? IRequest.RES_ERROR : IRequest.RES_SUCCESS));
+ }
+}
+
+class HandleUnrevocation implements IRequestListener {
+ private LdapPublishModule mModule = null;
+
+ public HandleUnrevocation(LdapPublishModule module) {
+ mModule = module;
+ }
+
+ public void set(String name, String val) {
+ }
+
+ public void init(ISubsystem sub, IConfigStore config) throws EBaseException {
+ }
+
+ public void accept(IRequest r) {
+ CMS.debug(
+ "Handle publishing for unrevoke request id " + r.getRequestId());
+
+ // get fields in request.
+ X509CertImpl[] certs = r.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ if (certs == null || certs.length == 0 || certs[0] == null) {
+ // no certs in unrevoke.
+ CMS.debug(
+ "Nothing to publish for unrevocation " +
+ "request " + r.getRequestId());
+ return;
+ }
+
+ // get mapper and publisher for cert type.
+ LdapMappers mappers =
+ mModule.getMappers(LdapPublishModule.PROP_TYPE_CLIENT);
+
+ if (mappers == null || mappers.publisher == null) {
+ CMS.debug(
+ "publisher for " + LdapPublishModule.PROP_TYPE_CLIENT + " is null");
+ return;
+ }
+
+ boolean error = false;
+ Integer results[] = new Integer[certs.length];
+
+ for (int i = 0; i < certs.length; i++) {
+ results[i] = IRequest.RES_ERROR;
+ try {
+ mModule.publish((ILdapMapper) mappers.mapper,
+ (ILdapPublisher) mappers.publisher, certs[i]);
+ results[i] = IRequest.RES_SUCCESS;
+ CMS.debug(
+ "Unpublished cert serial no 0x" + certs[i].getSerialNumber().toString(16));
+ } catch (ELdapException e) {
+ error = true;
+ mModule.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_UNPUBLISH",
+ certs[i].getSerialNumber().toString(16), e.getMessage()));
+ }
+ }
+ r.setExtData("ldapPublishStatus", results);
+ r.setExtData("ldapPublishOverAllStatus",
+ (error == true ? IRequest.RES_ERROR : IRequest.RES_SUCCESS));
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapRequestListener.java b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapRequestListener.java
new file mode 100644
index 000000000..79131244a
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapRequestListener.java
@@ -0,0 +1,526 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldap;
+
+import java.math.BigInteger;
+import java.security.cert.Certificate;
+import java.util.Hashtable;
+
+import netscape.security.x509.X509CertImpl;
+
+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.base.MetaInfo;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestListener;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.cmscore.dbs.CertRecord;
+
+public class LdapRequestListener implements IRequestListener {
+ private boolean mInited = false;
+
+ /**
+ * handlers for request types (events)
+ * each handler implement IRequestListener
+ */
+ private Hashtable<String, IRequestListener> mRequestListeners = new Hashtable<String, IRequestListener>();
+
+ private IPublisherProcessor mPublisherProcessor = null;
+
+ public LdapRequestListener() {
+ }
+
+ public void set(String name, String val) {
+ }
+
+ public void init(ISubsystem sys, IConfigStore config) throws EBaseException {
+ if (mInited)
+ return;
+
+ mPublisherProcessor = (IPublisherProcessor) sys;
+
+ mRequestListeners.put(IRequest.ENROLLMENT_REQUEST,
+ new LdapEnrollmentListener(mPublisherProcessor));
+ mRequestListeners.put(IRequest.RENEWAL_REQUEST,
+ new LdapRenewalListener(mPublisherProcessor));
+ mRequestListeners.put(IRequest.REVOCATION_REQUEST,
+ new LdapRevocationListener(mPublisherProcessor));
+ mRequestListeners.put(IRequest.UNREVOCATION_REQUEST,
+ new LdapUnrevocationListener(mPublisherProcessor));
+ mInited = true;
+ }
+
+ public PublishObject getPublishObject(IRequest r) {
+ String type = r.getRequestType();
+ PublishObject obj = new PublishObject();
+
+ if (type.equals(IRequest.ENROLLMENT_REQUEST)) {
+ // in case it's not meant for us
+ if (r.getExtDataInInteger(IRequest.RESULT) == null)
+ return null;
+
+ // check if request failed.
+ if ((r.getExtDataInInteger(IRequest.RESULT)).equals(IRequest.RES_ERROR)) {
+ CMS.debug("Request errored. " +
+ "Nothing to publish for enrollment request id " +
+ r.getRequestId());
+ return null;
+ }
+ CMS.debug("Checking publishing for request " +
+ r.getRequestId());
+ // check if issued certs is set.
+ X509CertImpl[] certs = r.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ if (certs == null || certs.length == 0 || certs[0] == null) {
+ CMS.debug(
+ "No certs to publish for request id " +
+ r.getRequestId());
+ return null;
+ }
+ obj.setCerts(certs);
+ return obj;
+ } else if (type.equals(IRequest.RENEWAL_REQUEST)) {
+ // Note we do not remove old certs from directory during renewal
+ X509CertImpl[] certs = r.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ if (certs == null || certs.length == 0) {
+ CMS.debug("no certs to publish for renewal " +
+ "request " + r.getRequestId());
+ return null;
+ }
+ obj.setCerts(certs);
+ return obj;
+ } else if (type.equals(IRequest.REVOCATION_REQUEST)) {
+ X509CertImpl[] revcerts = r.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ if (revcerts == null || revcerts.length == 0 || revcerts[0] == null) {
+ // no certs in revoke.
+ CMS.debug(
+ "Nothing to unpublish for revocation " +
+ "request " + r.getRequestId());
+ return null;
+ }
+ obj.setCerts(revcerts);
+ return obj;
+ } else if (type.equals(IRequest.UNREVOCATION_REQUEST)) {
+ X509CertImpl[] certs = r.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ if (certs == null || certs.length == 0 || certs[0] == null) {
+ // no certs in unrevoke.
+ CMS.debug(
+ "Nothing to publish for unrevocation " +
+ "request " + r.getRequestId());
+ return null;
+ }
+ obj.setCerts(certs);
+ return obj;
+ } else {
+ CMS.debug("Request errored. " +
+ "Nothing to publish for request id " +
+ r.getRequestId());
+ return null;
+ }
+
+ }
+
+ public void accept(IRequest r) {
+ String type = r.getRequestType();
+
+ IRequestListener handler = mRequestListeners.get(type);
+
+ if (handler == null) {
+ CMS.debug(
+ "Nothing to publish for request type " + type);
+ return;
+ }
+ handler.accept(r);
+ }
+
+}
+
+class LdapEnrollmentListener implements IRequestListener {
+ IPublisherProcessor mProcessor = null;
+
+ public LdapEnrollmentListener(IPublisherProcessor processor) {
+ mProcessor = processor;
+ }
+
+ public void init(ISubsystem sys, IConfigStore config) throws EBaseException {
+ }
+
+ public void set(String name, String val) {
+ }
+
+ public void accept(IRequest r) {
+ CMS.debug(
+ "LdapRequestListener handling publishing for enrollment request id " +
+ r.getRequestId());
+
+ String profileId = r.getExtDataInString("profileId");
+
+ if (profileId == null) {
+ // in case it's not meant for us
+ if (r.getExtDataInInteger(IRequest.RESULT) == null)
+ return;
+
+ // check if request failed.
+ if ((r.getExtDataInInteger(IRequest.RESULT)).equals(IRequest.RES_ERROR)) {
+ CMS.debug("Request errored. " +
+ "Nothing to publish for enrollment request id " +
+ r.getRequestId());
+ return;
+ }
+ }
+ CMS.debug("Checking publishing for request " +
+ r.getRequestId());
+ // check if issued certs is set.
+ Certificate[] certs = null;
+ if (profileId == null) {
+ certs = r.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+ } else {
+ certs = new Certificate[1];
+ certs[0] = r.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
+ }
+
+ if (certs == null || certs.length == 0 || certs[0] == null) {
+ CMS.debug(
+ "No certs to publish for request id " + r.getRequestId());
+ return;
+ }
+
+ if (certs[0] instanceof X509CertImpl)
+ acceptX509(r, certs);
+ }
+
+ public void acceptX509(IRequest r, Certificate[] certs) {
+ Integer results[] = new Integer[certs.length];
+ boolean error = false;
+
+ for (int i = 0; i < certs.length; i++) {
+ X509CertImpl xcert = (X509CertImpl) certs[i];
+
+ if (xcert == null)
+ continue;
+ try {
+ mProcessor.publishCert(xcert, r);
+
+ results[i] = IRequest.RES_SUCCESS;
+ CMS.debug(
+ "acceptX509: Published cert serial no 0x" +
+ xcert.getSerialNumber().toString(16));
+ //mProcessor.setPublishedFlag(xcert.getSerialNumber(), true);
+ } catch (ELdapException e) {
+ mProcessor.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_PUBLISH",
+ xcert.getSerialNumber().toString(16), e.toString()));
+ results[i] = IRequest.RES_ERROR;
+ error = true;
+ }
+ }
+ r.setExtData("ldapPublishStatus", results);
+ r.setExtData("ldapPublishOverAllStatus",
+ (error == true ? IRequest.RES_ERROR : IRequest.RES_SUCCESS));
+ }
+}
+
+class LdapRenewalListener implements IRequestListener {
+ private IPublisherProcessor mProcessor = null;
+
+ public LdapRenewalListener(IPublisherProcessor processor) {
+ mProcessor = processor;
+ }
+
+ public void init(ISubsystem sys, IConfigStore config) throws EBaseException {
+ }
+
+ public void set(String name, String val) {
+ }
+
+ public void accept(IRequest r) {
+ // Note we do not remove old certs from directory during renewal
+ Certificate[] certs = r.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ if (certs == null || certs.length == 0) {
+ CMS.debug("no certs to publish for renewal " +
+ "request " + r.getRequestId());
+ return;
+ }
+
+ acceptX509(r, certs);
+ }
+
+ public void acceptX509(IRequest r, Certificate[] certs) {
+ X509CertImpl cert = null;
+
+ Integer results[] = new Integer[certs.length];
+ boolean error = false;
+
+ for (int i = 0; i < certs.length; i++) {
+ cert = (X509CertImpl) certs[i];
+ if (cert == null)
+ continue; // there was an error issuing this cert.
+ try {
+ mProcessor.publishCert(cert, r);
+ results[i] = IRequest.RES_SUCCESS;
+ mProcessor.log(ILogger.LL_INFO,
+ "Published cert serial no 0x" +
+ cert.getSerialNumber().toString(16));
+ } catch (ELdapException e) {
+ error = true;
+ mProcessor.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_PUBLISH",
+ cert.getSerialNumber().toString(16), e.toString()));
+ results[i] = IRequest.RES_ERROR;
+ }
+ }
+ r.setExtData("ldapPublishStatus", results);
+ r.setExtData("ldapPublishOverAllStatus",
+ (error == true ? IRequest.RES_ERROR : IRequest.RES_SUCCESS));
+ }
+}
+
+class LdapRevocationListener implements IRequestListener {
+ private IPublisherProcessor mProcessor = null;
+
+ public LdapRevocationListener(IPublisherProcessor processor) {
+ mProcessor = processor;
+ }
+
+ public void init(ISubsystem sys, IConfigStore config) throws EBaseException {
+ }
+
+ public void set(String name, String val) {
+ }
+
+ public void accept(IRequest r) {
+ CMS.debug(
+ "Handle publishing for revoke request id " + r.getRequestId());
+
+ // get fields in request.
+ Certificate[] certs = r.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ if (certs == null || certs.length == 0 || certs[0] == null) {
+ // no certs in revoke.
+ CMS.debug(
+ "Nothing to unpublish for revocation " +
+ "request " + r.getRequestId());
+ return;
+ }
+
+ acceptX509(r, certs);
+ }
+
+ public void acceptX509(IRequest r, Certificate[] revcerts) {
+ boolean error = false;
+ Integer results[] = new Integer[revcerts.length];
+
+ error = false;
+ for (int i = 0; i < revcerts.length; i++) {
+ X509CertImpl cert = (X509CertImpl) revcerts[i];
+
+ results[i] = IRequest.RES_ERROR;
+ try {
+ // We need the enrollment request to sort out predicate
+ BigInteger serial = cert.getSerialNumber();
+ ICertRecord certRecord = null;
+ IAuthority auth = (IAuthority) mProcessor.getAuthority();
+
+ if (auth == null ||
+ !(auth instanceof ICertificateAuthority)) {
+ mProcessor.log(ILogger.LL_WARN,
+ "Trying to get a certificate from non certificate authority.");
+ } else {
+ ICertificateRepository certdb =
+ ((ICertificateAuthority) auth).getCertificateRepository();
+
+ if (certdb == null) {
+ mProcessor.log(ILogger.LL_WARN, "Cert DB is null for " + auth);
+ } else {
+ try {
+ certRecord = certdb.readCertificateRecord(serial);
+ } catch (EBaseException e) {
+ mProcessor.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_GET_CERT_RECORD",
+ serial.toString(16), e.toString()));
+ }
+ }
+ }
+
+ MetaInfo metaInfo = null;
+ String ridString = null;
+
+ if (certRecord != null)
+ metaInfo =
+ (MetaInfo) certRecord.get(ICertRecord.ATTR_META_INFO);
+ if (metaInfo == null) {
+ mProcessor.log(ILogger.LL_FAILURE,
+ "failed getting CertRecord.ATTR_META_INFO for cert serial number 0x" +
+ serial.toString(16));
+ } else {
+ ridString = (String) metaInfo.get(ICertRecord.META_REQUEST_ID);
+ }
+
+ IRequest req = null;
+
+ if (ridString != null) {
+ RequestId rid = new RequestId(ridString);
+
+ req = auth.getRequestQueue().findRequest(rid);
+ }
+ mProcessor.unpublishCert(cert, req);
+ results[i] = IRequest.RES_SUCCESS;
+ CMS.debug(
+ "Unpublished cert serial no 0x" +
+ cert.getSerialNumber().toString(16));
+ } catch (ELdapException e) {
+ error = true;
+ mProcessor.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_UNPUBLISH",
+ cert.getSerialNumber().toString(16), e.toString()));
+ } catch (EBaseException e) {
+ error = true;
+ mProcessor.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_FIND",
+ cert.getSerialNumber().toString(16), e.toString()));
+ }
+ }
+ r.setExtData("ldapPublishStatus", results);
+ r.setExtData("ldapPublishOverAllStatus",
+ (error == true ? IRequest.RES_ERROR : IRequest.RES_SUCCESS));
+ }
+}
+
+class LdapUnrevocationListener implements IRequestListener {
+ private IPublisherProcessor mProcessor = null;
+
+ public LdapUnrevocationListener(IPublisherProcessor processor) {
+ mProcessor = processor;
+ }
+
+ public void init(ISubsystem sys, IConfigStore config) throws EBaseException {
+ }
+
+ public void set(String name, String val) {
+ }
+
+ public void accept(IRequest r) {
+ CMS.debug(
+ "Handle publishing for unrevoke request id " + r.getRequestId());
+
+ // get fields in request.
+ Certificate[] certs = r.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ if (certs == null || certs.length == 0 || certs[0] == null) {
+ // no certs in unrevoke.
+ CMS.debug(
+ "Nothing to publish for unrevocation " +
+ "request " + r.getRequestId());
+ return;
+ }
+
+ acceptX509(r, certs);
+ }
+
+ public void acceptX509(IRequest r, Certificate[] certs) {
+ boolean error = false;
+ Integer results[] = new Integer[certs.length];
+ X509CertImpl xcert = null;
+
+ for (int i = 0; i < certs.length; i++) {
+ results[i] = IRequest.RES_ERROR;
+ xcert = (X509CertImpl) certs[i];
+ try {
+ // We need the enrollment request to sort out predicate
+ BigInteger serial = xcert.getSerialNumber();
+ ICertRecord certRecord = null;
+ IAuthority auth = (IAuthority) mProcessor.getAuthority();
+
+ if (auth == null ||
+ !(auth instanceof ICertificateAuthority)) {
+ mProcessor.log(ILogger.LL_WARN,
+ "Trying to get a certificate from non certificate authority.");
+ } else {
+ ICertificateRepository certdb = ((ICertificateAuthority) auth).getCertificateRepository();
+
+ if (certdb == null) {
+ mProcessor.log(ILogger.LL_WARN, "Cert DB is null for " + auth);
+ } else {
+ try {
+ certRecord = certdb.readCertificateRecord(serial);
+ } catch (EBaseException e) {
+ mProcessor
+ .log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_GET_CERT_RECORD", serial.toString(16),
+ e.toString()));
+ }
+ }
+ }
+
+ MetaInfo metaInfo = null;
+ String ridString = null;
+
+ if (certRecord != null)
+ metaInfo =
+ (MetaInfo) certRecord.get(CertRecord.ATTR_META_INFO);
+ if (metaInfo == null) {
+ mProcessor.log(ILogger.LL_FAILURE,
+ "Failed getting CertRecord.ATTR_META_INFO for cert serial number 0x" +
+ serial.toString(16));
+ } else {
+ ridString = (String) metaInfo.get(CertRecord.META_REQUEST_ID);
+ }
+
+ IRequest req = null;
+
+ if (ridString != null) {
+ RequestId rid = new RequestId(ridString);
+
+ req = auth.getRequestQueue().findRequest(rid);
+ }
+ mProcessor.publishCert(xcert, req);
+ results[i] = IRequest.RES_SUCCESS;
+ CMS.debug(
+ "Published cert serial no 0x" +
+ xcert.getSerialNumber().toString(16));
+ } catch (ELdapException e) {
+ error = true;
+ mProcessor.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_PUBLISH",
+ xcert.getSerialNumber().toString(16), e.toString()));
+ } catch (EBaseException e) {
+ error = true;
+ mProcessor.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_FIND",
+ xcert.getSerialNumber().toString(16), e.toString()));
+ }
+ }
+ r.setExtData("ldapPublishStatus", results);
+ r.setExtData("ldapPublishOverAllStatus",
+ (error == true ? IRequest.RES_ERROR : IRequest.RES_SUCCESS));
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapRule.java b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapRule.java
new file mode 100644
index 000000000..2fb148492
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapRule.java
@@ -0,0 +1,305 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldap;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.publish.ILdapExpression;
+import com.netscape.certsrv.publish.ILdapRule;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * The publishing rule that links mapper and publisher together.
+ */
+public class LdapRule implements ILdapRule, IExtendedPluginInfo {
+ public final static String NOMAPPER = "<NONE>";
+
+ private IConfigStore mConfig = null;
+ protected ILdapExpression mFilterExp = null;
+ private String mInstanceName = null;
+
+ private IPublisherProcessor mProcessor = null;
+
+ private static String[] epi_params = null; // extendedpluginInfo
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public String[] getExtendedPluginInfo(Locale locale) {
+ //dont know why it's null here.
+ //if (mProcessor == null) System.out.println("p null");
+
+ if (Debug.ON) {
+ Debug.trace("LdapRule: getExtendedPluginInfo() - returning epi_params:");
+ for (int i = 0; i < epi_params.length; i++) {
+ Debug.trace("[" + i + "] " + epi_params[i]);
+ }
+ }
+ return epi_params;
+ }
+
+ public void init(IPublisherProcessor processor, IConfigStore config) throws EBaseException {
+ mConfig = config;
+
+ mProcessor = processor;
+ Enumeration<String> mappers = mProcessor.getMapperInsts().keys();
+ Enumeration<String> publishers = mProcessor.getPublisherInsts().keys();
+ StringBuffer map = new StringBuffer();
+ map.append(NOMAPPER);
+
+ for (; mappers.hasMoreElements();) {
+ String name = mappers.nextElement();
+
+ map.append("," + name);
+ }
+ StringBuffer publish = new StringBuffer();
+
+ for (; publishers.hasMoreElements();) {
+ String name = publishers.nextElement();
+
+ publish.append("," + name);
+ }
+
+ epi_params = new String[] {
+ "type;choice(cacert,crl, certs);The publishing object type",
+ "mapper;choice("
+ + map.toString() + ");Use the mapper to find the ldap dn \nto publish the certificate or crl",
+ "publisher;choice("
+ + publish.toString() + ");Use the publisher to publish the certificate or crl a directory etc",
+ "enable;boolean;Enable this publishing rule",
+ "predicate;string;Filter describing when this publishing rule shoule be used"
+ };
+
+ // Read the predicate expression if any associated
+ // with the rule
+ String exp = config.getString(IPublisherProcessor.PROP_PREDICATE, null);
+
+ if (exp != null)
+ exp = exp.trim();
+ if (exp != null && exp.length() > 0) {
+ ILdapExpression filterExp = LdapPredicateParser.parse(exp);
+
+ setPredicate(filterExp);
+ }
+ //if (mProcessor == null) System.out.println("null");
+
+ }
+
+ /**
+ * The init method in ILdapPlugin
+ * It can not set set mapper,publisher choice for console dynamicly
+ * Should not use this method to init.
+ */
+ public void init(IConfigStore config) throws EBaseException {
+ mConfig = config;
+
+ epi_params = new String[] {
+ "type;choice(cacert, crl, certs);The publishing object type",
+ "mapper;choice(null,LdapUserCertMap,LdapServerCertMap,LdapCrlMap,LdapCaCertMap);Use the mapper to find the ldap dn to publish the certificate or crl",
+ "publisher;choice(LdapUserCertPublisher,LdapServerCertPublisher,LdapCrlPublisher,LdapCaCertPublisher);Use the publisher to publish the certificate or crl a directory etc",
+ "enable;boolean;",
+ "predicate;string;"
+ };
+
+ // Read the predicate expression if any associated
+ // with the rule
+ String exp = config.getString(IPublisherProcessor.PROP_PREDICATE, null);
+
+ if (exp != null)
+ exp = exp.trim();
+ if (exp != null && exp.length() > 0) {
+ ILdapExpression filterExp = LdapPredicateParser.parse(exp);
+
+ setPredicate(filterExp);
+ }
+
+ }
+
+ /**
+ * Returns the implementation name.
+ */
+ public String getImplName() {
+ return "LdapRule";
+ }
+
+ /**
+ * Returns the description of the ldap publisher.
+ */
+ public String getDescription() {
+ return "LdapRule";
+ }
+
+ /**
+ * Set the instance name
+ */
+ public void setInstanceName(String insName) {
+ mInstanceName = insName;
+ }
+
+ /**
+ * Returns the instance name
+ */
+ public String getInstanceName() {
+ return mInstanceName;
+ }
+
+ /**
+ * Returns the current instance parameters.
+ */
+ public Vector<String> getInstanceParams() {
+ //if (mProcessor == null) System.out.println("xxxxnull");
+ //dont know why the processor was null in getExtendedPluginInfo()
+
+ /* Commented block contains variables which are used only in the below commented block.
+ *
+ * Enumeration<String> mappers = mProcessor.getMapperInsts().keys();
+ Enumeration<String> publishers = mProcessor.getPublisherInsts().keys();
+ StringBuffer map = new StringBuffer();
+ map.append(NOMAPPER);
+
+ for (; mappers.hasMoreElements();) {
+ String name = mappers.nextElement();
+
+ map.append("," + name);
+ }
+ StringBuffer publish = new StringBuffer();
+
+ for (; publishers.hasMoreElements();) {
+ String name = publishers.nextElement();
+
+ publish.append("," + name);
+ }*/
+
+ /*
+ mExtendedPluginInfo = new NameValuePairs();
+ mExtendedPluginInfo.add("type","choice(client,server,objSignClient,smime,ca,crl);The publishing object type");
+ mExtendedPluginInfo.add("mapper","choice("+map+");Use the mapper to find the ldap dn \nto publish the certificate or crl");
+ mExtendedPluginInfo.add("publisher","choice("+publish+");Use the publisher to publish the certificate or crl a directory etc");
+ mExtendedPluginInfo.add("enable","boolean;");
+ mExtendedPluginInfo.add("predicate","string;");
+ */
+
+ Vector<String> v = new Vector<String>();
+
+ try {
+ v.addElement(IPublisherProcessor.PROP_TYPE + "=" +
+ mConfig.getString(IPublisherProcessor.PROP_TYPE, ""));
+ v.addElement(IPublisherProcessor.PROP_PREDICATE + "=" +
+ mConfig.getString(IPublisherProcessor.PROP_PREDICATE,
+ ""));
+ v.addElement(IPublisherProcessor.PROP_ENABLE + "=" +
+ mConfig.getString(IPublisherProcessor.PROP_ENABLE,
+ ""));
+ v.addElement(IPublisherProcessor.PROP_MAPPER + "=" +
+ mConfig.getString(IPublisherProcessor.PROP_MAPPER,
+ ""));
+ v.addElement(IPublisherProcessor.PROP_PUBLISHER + "=" +
+ mConfig.getString(IPublisherProcessor.PROP_PUBLISHER,
+ ""));
+ } catch (EBaseException e) {
+ }
+ return v;
+ }
+
+ /**
+ * Sets a predicate expression for rule matching.
+ * <P>
+ *
+ * @param exp The predicate expression for the rule.
+ */
+ public void setPredicate(ILdapExpression exp) {
+ mFilterExp = exp;
+ }
+
+ /**
+ * Returns the predicate expression for the rule.
+ * <P>
+ *
+ * @return The predicate expression for the rule.
+ */
+ public ILdapExpression getPredicate() {
+ return mFilterExp;
+ }
+
+ public String getMapper() {
+ try {
+ String map =
+ mConfig.getString(IPublisherProcessor.PROP_MAPPER, "");
+
+ if (map != null)
+ map = map.trim();
+ if (map == null || map.equals(""))
+ return null;
+ else if (map.equals(NOMAPPER))
+ return null;
+ else
+ return map;
+ } catch (EBaseException e) {
+ }
+ return null;
+ }
+
+ public String getPublisher() {
+ try {
+ return mConfig.getString(IPublisherProcessor.PROP_PUBLISHER, "");
+ } catch (EBaseException e) {
+ }
+ return null;
+ }
+
+ public String getType() {
+ try {
+ return mConfig.getString(IPublisherProcessor.PROP_TYPE, "");
+ } catch (EBaseException e) {
+ }
+ return null;
+ }
+
+ public boolean enabled() {
+ try {
+ boolean enable =
+ mConfig.getBoolean(IPublisherProcessor.PROP_ENABLE, false);
+
+ //System.out.println(enable);
+ return enable;
+ } catch (EBaseException e) {
+ }
+ return false;
+ }
+
+ /**
+ * Returns the initial default parameters.
+ */
+ public Vector<String> getDefaultParams() {
+ Vector<String> v = new Vector<String>();
+
+ v.addElement(IPublisherProcessor.PROP_TYPE + "=");
+ v.addElement(IPublisherProcessor.PROP_PREDICATE + "=");
+ v.addElement(IPublisherProcessor.PROP_ENABLE + "=true");
+ v.addElement(IPublisherProcessor.PROP_MAPPER + "=");
+ v.addElement(IPublisherProcessor.PROP_PUBLISHER + "=");
+ return v;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapSimpleExpression.java b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapSimpleExpression.java
new file mode 100644
index 000000000..9a326b25e
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldap/LdapSimpleExpression.java
@@ -0,0 +1,473 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldap;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.publish.ILdapExpression;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cmscore.util.AssertionException;
+
+/**
+ * This class represents an expression of the form var = val,
+ * var != val, var < val, var > val, var <= val, var >= val.
+ *
+ * Expressions are used as predicates for publishing rule selection.
+ *
+ * @author mzhao
+ * @version $Revision$, $Date$
+ */
+public class LdapSimpleExpression implements ILdapExpression {
+ private String mPfx;
+ private String mVar;
+ private String mVal;
+ private String mPartialMatch;
+ private int mOp;
+ private boolean hasWildCard;
+ public static final char WILDCARD_CHAR = '*';
+
+ // This is just for indicating a null expression.
+ public static LdapSimpleExpression NULL_EXPRESSION = new LdapSimpleExpression("null", OP_EQUAL, "null");
+
+ public static ILdapExpression parse(String input)
+ throws ELdapException {
+ // Get the index of operator
+ // Debug.trace("LdapSimpleExpression::input: " + input);
+ String var = null;
+ int op = -1;
+ String val = null;
+
+ // XXX - Kanda - Need to change this parsing code eventually.
+ ExpressionComps comps = parseForEquality(input);
+
+ if (comps == null)
+ comps = parseForInEquality(input);
+ if (comps == null)
+ comps = parseForGE(input);
+ if (comps == null)
+ comps = parseForLE(input);
+ if (comps == null)
+ comps = parseForGT(input);
+ if (comps == null)
+ comps = parseForLT(input);
+ if (comps == null)
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_BAD_LDAP_EXPRESSION", input));
+
+ String pfx = null;
+ String rawVar = comps.getAttr();
+ int dotIdx = rawVar.indexOf('.');
+
+ if (dotIdx != -1) {
+ pfx = rawVar.substring(0, dotIdx).trim();
+ var = rawVar.substring(dotIdx + 1).trim();
+ } else {
+ var = rawVar;
+ }
+ op = comps.getOp();
+ val = comps.getVal();
+ return new LdapSimpleExpression(pfx, var, op, val);
+ }
+
+ public LdapSimpleExpression(String var, int op, String val) {
+ this(null, var, op, val);
+ }
+
+ public LdapSimpleExpression(String prefix, String var, int op, String val) {
+ // Assert that op has to be either ILdapExpression.OP_EQUAL or
+ // ILdapExpression.OP_NEQUAL.
+ // If val or var is null throw an exception!
+ mPfx = prefix;
+ mVar = var;
+ mOp = op;
+ mVal = val;
+ int firstIndex;
+
+ if ((firstIndex = mVal.indexOf(WILDCARD_CHAR)) >= 0) {
+ hasWildCard = true;
+ int nextIndex = mVal.indexOf(WILDCARD_CHAR, firstIndex + 1);
+
+ if (nextIndex == -1) {
+ if (firstIndex == 0)
+ mPartialMatch = mVal.substring(1);
+ else
+ mPartialMatch = mVal.substring(0, firstIndex);
+ } else
+ mPartialMatch = mVal.substring(firstIndex + 1, nextIndex);
+ } else
+ hasWildCard = false;
+ }
+
+ public boolean evaluate(SessionContext sc)
+ throws ELdapException {
+ Object givenVal;
+
+ try {
+ // Try exact case first.
+ givenVal = sc.get(mVar);
+ } catch (Exception e) {
+ givenVal = null;
+ }
+
+ // It is kind of a problem here if all letters are in
+ // lowercase or in upperCase - for example in the case
+ // of directory attributes.
+ if (givenVal == null) {
+ try {
+ givenVal = sc.get(mVar.toLowerCase());
+ } catch (Exception e) {
+ givenVal = null;
+ }
+ }
+
+ if (givenVal == null) {
+ try {
+ givenVal = sc.get(mVar.toUpperCase());
+ } catch (Exception e) {
+ givenVal = null;
+ }
+ }
+
+ // Debug.trace("mVar: " + mVar + ",Given Value: " + givenVal + ", Value to compare with: " + mVal);
+ boolean result = false;
+
+ result = matchValue(givenVal);
+
+ return result;
+
+ }
+
+ public boolean evaluate(IRequest req)
+ throws ELdapException {
+ boolean result = false;
+ // mPfx and mVar are looked up case-indendently
+ if (mPfx != null) {
+ result = matchValue(req.getExtDataInString(mPfx, mVar));
+ } else {
+ result = matchValue(req.getExtDataInString(mVar));
+ }
+ return result;
+ }
+
+ private boolean matchVector(Vector<Object> value)
+ throws ELdapException {
+ boolean result = false;
+ Enumeration<Object> e = value.elements();
+
+ for (; e.hasMoreElements();) {
+ result = matchValue(e.nextElement());
+ if (result)
+ break;
+ }
+ return result;
+ }
+
+ private boolean matchStringArray(String[] value)
+ throws ELdapException {
+ boolean result = false;
+
+ for (int i = 0; i < value.length; i++) {
+ result = matchValue(value[i]);
+ if (result)
+ break;
+ }
+ return result;
+ }
+
+ @SuppressWarnings("unchecked")
+ private boolean matchValue(Object value)
+ throws ELdapException {
+ boolean result;
+
+ // There is nothing to compare with!
+ if (value == null)
+ return false;
+
+ if (value instanceof String)
+ result = matchStringValue((String) value);
+ else if (value instanceof Integer)
+ result = matchIntegerValue((Integer) value);
+ else if (value instanceof Boolean)
+ result = matchBooleanValue((Boolean) value);
+ else if (value instanceof Vector)
+ result = matchVector((Vector<Object>) value);
+ else if (value instanceof String[])
+ result = matchStringArray((String[]) value);
+ else
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_INVALID_ATTR_VALUE",
+ value.getClass().getName()));
+ return result;
+ }
+
+ private boolean matchStringValue(String givenVal)
+ throws ELdapException {
+ boolean result;
+
+ switch (mOp) {
+ case OP_EQUAL:
+ if (hasWildCard)
+ result = (givenVal.indexOf(mPartialMatch) >= 0);
+ else
+ result = givenVal.equalsIgnoreCase(mVal);
+ break;
+
+ case OP_NEQUAL:
+ if (hasWildCard)
+ result = (givenVal.indexOf(mPartialMatch) < 0);
+ else
+ result = !givenVal.equalsIgnoreCase(mVal);
+ break;
+
+ case OP_LT:
+ result = (givenVal.compareTo(mVal) < 0);
+ break;
+
+ case OP_GT:
+ result = (givenVal.compareTo(mVal) > 0);
+ break;
+
+ case OP_GE:
+ result = (givenVal.compareTo(mVal) >= 0);
+ break;
+
+ case OP_LE:
+ result = (givenVal.compareTo(mVal) >= 0);
+ break;
+
+ default:
+ throw new AssertionException("Invalid operation code");
+ }
+ return result;
+ }
+
+ private boolean matchIntegerValue(Integer intVal)
+ throws ELdapException {
+ boolean result;
+ int storedVal;
+ int givenVal = intVal.intValue();
+
+ try {
+ storedVal = new Integer(mVal).intValue();
+ } catch (Exception e) {
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_INVALID_ATTR_VALUE", mVal));
+
+ }
+ switch (mOp) {
+ case OP_EQUAL:
+ result = (givenVal == storedVal);
+ break;
+
+ case OP_NEQUAL:
+ result = (givenVal != storedVal);
+ break;
+
+ case OP_LT:
+ result = (givenVal < storedVal);
+ break;
+
+ case OP_GT:
+ result = (givenVal > storedVal);
+ break;
+
+ case OP_GE:
+ result = (givenVal >= storedVal);
+ break;
+
+ case OP_LE:
+ result = (givenVal >= storedVal);
+ break;
+
+ default:
+ throw new AssertionException("Invalid operation code");
+ }
+ return result;
+ }
+
+ private boolean matchBooleanValue(Boolean givenVal)
+ throws ELdapException {
+ boolean result;
+ Boolean storedVal;
+
+ if (!(mVal.equalsIgnoreCase("true") || mVal.equalsIgnoreCase("false")))
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_INVALID_ATTR_VALUE",
+ mVal));
+ storedVal = Boolean.valueOf(mVal);
+ switch (mOp) {
+ case OP_EQUAL:
+ result = (givenVal.equals(storedVal));
+ break;
+
+ case OP_NEQUAL:
+ case OP_LT:
+ case OP_GT:
+ case OP_GE:
+ case OP_LE:
+ result = (!givenVal.equals(storedVal));
+ break;
+
+ default:
+ throw new AssertionException("Invalid operation code");
+ }
+ return result;
+ }
+
+ public String toString() {
+ String op = null;
+
+ switch (mOp) {
+ case ILdapExpression.OP_EQUAL:
+ op = ILdapExpression.EQUAL_STR;
+ break;
+
+ case ILdapExpression.OP_NEQUAL:
+ op = ILdapExpression.NEQUAL_STR;
+ break;
+
+ case ILdapExpression.OP_GT:
+ op = ILdapExpression.GT_STR;
+ break;
+
+ case ILdapExpression.OP_LT:
+ op = ILdapExpression.LT_STR;
+ break;
+
+ case ILdapExpression.OP_GE:
+ op = ILdapExpression.GE_STR;
+ break;
+
+ case ILdapExpression.OP_LE:
+ op = ILdapExpression.LE_STR;
+ break;
+ }
+ if (mPfx != null && mPfx.length() > 0)
+ return mPfx + "." + mVar + " " + op + " " + mVal;
+ else
+ return mVar + " " + op + " " + mVal;
+ }
+
+ private static ExpressionComps parseForEquality(String expression) {
+ int index = expression.indexOf(ILdapExpression.EQUAL_STR);
+
+ if (index < 0)
+ return null;
+ else {
+ String attr = expression.substring(0, index).trim();
+ int op = OP_EQUAL;
+ String val = expression.substring(index + 2).trim();
+
+ return new ExpressionComps(attr, op, val);
+ }
+ }
+
+ private static ExpressionComps parseForInEquality(String expression) {
+ int index = expression.indexOf(ILdapExpression.NEQUAL_STR);
+
+ if (index < 0)
+ return null;
+ else {
+ String attr = expression.substring(0, index).trim();
+ int op = OP_NEQUAL;
+ String val = expression.substring(index + 2).trim();
+
+ return new ExpressionComps(attr, op, val);
+ }
+ }
+
+ private static ExpressionComps parseForGT(String expression) {
+ int index = expression.indexOf(ILdapExpression.GT_STR);
+
+ if (index < 0)
+ return null;
+ else {
+ String attr = expression.substring(0, index).trim();
+ int op = OP_GT;
+ String val = expression.substring(index + 1).trim();
+
+ return new ExpressionComps(attr, op, val);
+ }
+ }
+
+ private static ExpressionComps parseForLT(String expression) {
+ int index = expression.indexOf(ILdapExpression.LT_STR);
+
+ if (index < 0)
+ return null;
+ else {
+ String attr = expression.substring(0, index).trim();
+ int op = OP_LT;
+ String val = expression.substring(index + 1).trim();
+
+ return new ExpressionComps(attr, op, val);
+ }
+ }
+
+ private static ExpressionComps parseForGE(String expression) {
+ int index = expression.indexOf(ILdapExpression.GE_STR);
+
+ if (index < 0)
+ return null;
+ else {
+ String attr = expression.substring(0, index).trim();
+ int op = OP_GE;
+ String val = expression.substring(index + 2).trim();
+
+ return new ExpressionComps(attr, op, val);
+ }
+ }
+
+ private static ExpressionComps parseForLE(String expression) {
+ int index = expression.indexOf(ILdapExpression.LE_STR);
+
+ if (index < 0)
+ return null;
+ else {
+ String attr = expression.substring(0, index).trim();
+ int op = OP_LE;
+ String val = expression.substring(index + 2).trim();
+
+ return new ExpressionComps(attr, op, val);
+ }
+ }
+}
+
+class ExpressionComps {
+ String attr;
+ int op;
+ String val;
+
+ public ExpressionComps(String a, int o, String v) {
+ attr = a;
+ op = o;
+ val = v;
+ }
+
+ public String getAttr() {
+ return attr;
+ }
+
+ public int getOp() {
+ return op;
+ }
+
+ public String getVal() {
+ return val;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldap/PublishObject.java b/base/server/cmscore/src/com/netscape/cmscore/ldap/PublishObject.java
new file mode 100644
index 000000000..940330d6d
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldap/PublishObject.java
@@ -0,0 +1,84 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldap;
+
+import netscape.security.x509.X509CRLImpl;
+import netscape.security.x509.X509CertImpl;
+
+/**
+ * The object to publish or unpublish: a certificate or a CRL
+ */
+public class PublishObject {
+ public static final String CERT = "cert";
+ public static final String CERTS = "certs";
+ public static final String CRL = "crl";
+ private String mObjectType = null;
+ private X509CertImpl mCert = null;
+ private X509CertImpl[] mCerts = null;
+ private X509CRLImpl mCRL = null;
+ private int mIndex = 0;
+
+ public PublishObject() {
+ }
+
+ public String getType() {
+ return mObjectType;
+ }
+
+ public void setCert(X509CertImpl cert) {
+ mObjectType = CERT;
+ mCert = cert;
+ mCerts = null;
+ mCRL = null;
+ }
+
+ public X509CertImpl getCert() {
+ return mCert;
+ }
+
+ public void setCerts(X509CertImpl[] certs) {
+ mObjectType = CERTS;
+ mCerts = certs;
+ mCert = null;
+ mCRL = null;
+ }
+
+ public X509CertImpl[] getCerts() {
+ return mCerts;
+ }
+
+ public void setIndex(int index) {
+ mIndex = index;
+ }
+
+ public int getIndex() {
+ return mIndex;
+ }
+
+ public void setCRL(X509CRLImpl crl) {
+ mObjectType = CRL;
+ mCert = null;
+ mCerts = null;
+ mCRL = crl;
+ }
+
+ public X509CRLImpl getCRL() {
+ return mCRL;
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldap/PublisherProcessor.java b/base/server/cmscore/src/com/netscape/cmscore/ldap/PublisherProcessor.java
new file mode 100644
index 000000000..5df29c10c
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldap/PublisherProcessor.java
@@ -0,0 +1,1487 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldap;
+
+import java.math.BigInteger;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import netscape.ldap.LDAPConnection;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CRLImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.ICertAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.dbs.certdb.ICertRecord;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ILdapConnModule;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.publish.ILdapExpression;
+import com.netscape.certsrv.publish.ILdapMapper;
+import com.netscape.certsrv.publish.ILdapPublisher;
+import com.netscape.certsrv.publish.ILdapRule;
+import com.netscape.certsrv.publish.IPublisherProcessor;
+import com.netscape.certsrv.publish.IXcertPublisherProcessor;
+import com.netscape.certsrv.publish.MapperPlugin;
+import com.netscape.certsrv.publish.MapperProxy;
+import com.netscape.certsrv.publish.PublisherPlugin;
+import com.netscape.certsrv.publish.PublisherProxy;
+import com.netscape.certsrv.publish.RulePlugin;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestNotifier;
+import com.netscape.cmscore.dbs.CertRecord;
+import com.netscape.cmscore.util.Debug;
+
+public class PublisherProcessor implements
+ IPublisherProcessor, IXcertPublisherProcessor {
+
+ public Hashtable<String, PublisherPlugin> mPublisherPlugins = new Hashtable<String, PublisherPlugin>();
+ public Hashtable<String, PublisherProxy> mPublisherInsts = new Hashtable<String, PublisherProxy>();
+ public Hashtable<String, MapperPlugin> mMapperPlugins = new Hashtable<String, MapperPlugin>();
+ public Hashtable<String, MapperProxy> mMapperInsts = new Hashtable<String, MapperProxy>();
+ public Hashtable<String, RulePlugin> mRulePlugins = new Hashtable<String, RulePlugin>();
+ public Hashtable<String, ILdapRule> mRuleInsts = new Hashtable<String, ILdapRule>();
+
+ /**
+ * protected PublishRuleSet mRuleSet = null;
+ **/
+ protected LdapConnModule mLdapConnModule = null;
+
+ private IConfigStore mConfig = null;
+ private IConfigStore mLdapConfig = null;
+ private String mId = null;
+ private ILogger mLogger = CMS.getLogger();
+
+ protected ICertAuthority mAuthority = null;
+ protected LdapRequestListener mLdapRequestListener = null;
+ private boolean mCreateOwnDNEntry = false;
+ private boolean mInited = false;
+
+ public PublisherProcessor(String id) {
+ mId = id;
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ public void setId(String id) {
+ mId = id;
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public void init(ISubsystem authority, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+ mAuthority = (ICertAuthority) authority;
+
+ // load publisher implementation
+ IConfigStore publisherConfig = config.getSubStore("publisher");
+ IConfigStore c = publisherConfig.getSubStore(PROP_IMPL);
+ mCreateOwnDNEntry = mConfig.getBoolean("createOwnDNEntry", false);
+ Enumeration<String> mImpls = c.getSubStoreNames();
+
+ while (mImpls.hasMoreElements()) {
+ String id = mImpls.nextElement();
+ String pluginPath = c.getString(id + "." + PROP_CLASS);
+ PublisherPlugin plugin = new PublisherPlugin(id, pluginPath);
+
+ mPublisherPlugins.put(id, plugin);
+ }
+ if (Debug.ON)
+ Debug.trace("loaded publisher plugins");
+
+ // load publisher instances
+ c = publisherConfig.getSubStore(PROP_INSTANCE);
+ Enumeration<String> instances = c.getSubStoreNames();
+
+ while (instances.hasMoreElements()) {
+ String insName = instances.nextElement();
+ String implName = c.getString(insName + "." +
+ PROP_PLUGIN);
+ PublisherPlugin plugin =
+ mPublisherPlugins.get(implName);
+
+ if (plugin == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_PLUGIN_NOT_FIND", implName));
+ throw new ELdapException(implName);
+ }
+ String className = plugin.getClassPath();
+
+ // Instantiate and init the publisher.
+ boolean isEnable = false;
+ ILdapPublisher publisherInst = null;
+
+ try {
+ publisherInst = (ILdapPublisher)
+ Class.forName(className).newInstance();
+ IConfigStore pConfig =
+ c.getSubStore(insName);
+
+ publisherInst.init(pConfig);
+ isEnable = true;
+
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+
+ } catch (Throwable e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_SKIP_PUBLISHER", insName, e.toString()));
+ // Let the server continue if it is a
+ // mis-configuration. But the instance
+ // will be skipped. This give another
+ // chance to the user to re-configure
+ // the server via console.
+ }
+
+ if (publisherInst == null) {
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ }
+
+ if (insName == null) {
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", insName));
+ }
+
+ // add publisher instance to list.
+ mPublisherInsts.put(insName, new
+ PublisherProxy(isEnable, publisherInst));
+ log(ILogger.LL_INFO, "publisher instance " + insName + " added");
+ if (Debug.ON)
+ Debug.trace("loaded publisher instance " + insName + " impl " + implName);
+ }
+
+ // load mapper implementation
+ IConfigStore mapperConfig = config.getSubStore("mapper");
+
+ c = mapperConfig.getSubStore(PROP_IMPL);
+ mImpls = c.getSubStoreNames();
+ while (mImpls.hasMoreElements()) {
+ String id = mImpls.nextElement();
+ String pluginPath = c.getString(id + "." + PROP_CLASS);
+ MapperPlugin plugin = new MapperPlugin(id, pluginPath);
+
+ mMapperPlugins.put(id, plugin);
+ }
+ if (Debug.ON)
+ Debug.trace("loaded mapper plugins");
+
+ // load mapper instances
+ c = mapperConfig.getSubStore(PROP_INSTANCE);
+ instances = c.getSubStoreNames();
+ while (instances.hasMoreElements()) {
+ String insName = instances.nextElement();
+ String implName = c.getString(insName + "." +
+ PROP_PLUGIN);
+ MapperPlugin plugin =
+ mMapperPlugins.get(implName);
+
+ if (plugin == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_MAPPER_NOT_FIND", implName));
+ throw new ELdapException(implName);
+ }
+ String className = plugin.getClassPath();
+
+ if (Debug.ON)
+ Debug.trace("loaded mapper className=" + className);
+
+ // Instantiate and init the mapper
+ boolean isEnable = false;
+ ILdapMapper mapperInst = null;
+
+ try {
+ mapperInst = (ILdapMapper)
+ Class.forName(className).newInstance();
+ IConfigStore mConfig =
+ c.getSubStore(insName);
+
+ mapperInst.init(mConfig);
+ isEnable = true;
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+
+ } catch (Throwable e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_SKIP_MAPPER", insName, e.toString()));
+ // Let the server continue if it is a
+ // mis-configuration. But the instance
+ // will be skipped. This give another
+ // chance to the user to re-configure
+ // the server via console.
+ }
+
+ if (mapperInst == null) {
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ }
+
+ // add manager instance to list.
+ mMapperInsts.put(insName, new MapperProxy(
+ isEnable, mapperInst));
+
+ log(ILogger.LL_INFO, "mapper instance " + insName + " added");
+ if (Debug.ON)
+ Debug.trace("loaded mapper instance " + insName + " impl " + implName);
+ }
+
+ // load rule implementation
+ IConfigStore ruleConfig = config.getSubStore("rule");
+
+ c = ruleConfig.getSubStore(PROP_IMPL);
+ mImpls = c.getSubStoreNames();
+ while (mImpls.hasMoreElements()) {
+ String id = mImpls.nextElement();
+ String pluginPath = c.getString(id + "." + PROP_CLASS);
+ RulePlugin plugin = new RulePlugin(id, pluginPath);
+
+ mRulePlugins.put(id, plugin);
+ }
+ if (Debug.ON)
+ Debug.trace("loaded rule plugins");
+
+ // load rule instances
+ c = ruleConfig.getSubStore(PROP_INSTANCE);
+ instances = c.getSubStoreNames();
+ while (instances.hasMoreElements()) {
+ String insName = instances.nextElement();
+ String implName = c.getString(insName + "." +
+ PROP_PLUGIN);
+ RulePlugin plugin =
+ mRulePlugins.get(implName);
+
+ if (plugin == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_RULE_NOT_FIND", implName));
+ throw new ELdapException(implName);
+ }
+ String className = plugin.getClassPath();
+
+ if (Debug.ON)
+ Debug.trace("loaded rule className=" + className);
+
+ // Instantiate and init the rule
+ IConfigStore mConfig = null;
+
+ try {
+ ILdapRule ruleInst = null;
+
+ ruleInst = (ILdapRule)
+ Class.forName(className).newInstance();
+ mConfig = c.getSubStore(insName);
+ ruleInst.init(this, mConfig);
+ ruleInst.setInstanceName(insName);
+
+ // add manager instance to list.
+ if (Debug.ON)
+ Debug.trace("ADDING RULE " + insName + " " + ruleInst);
+ mRuleInsts.put(insName, ruleInst);
+ log(ILogger.LL_INFO, "rule instance " +
+ insName + " added");
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+
+ } catch (Throwable e) {
+ if (mConfig == null) {
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ }
+ mConfig.putString(ILdapRule.PROP_ENABLE,
+ "false");
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_SKIP_RULE", insName, e.toString()));
+ // Let the server continue if it is a
+ // mis-configuration. But the instance
+ // will be skipped. This give another
+ // chance to the user to re-configure
+ // the server via console.
+ }
+ if (Debug.ON)
+ Debug.trace("loaded rule instance " + insName + " impl " + implName);
+ }
+
+ startup();
+ mInited = true;
+ log(ILogger.LL_INFO, "publishing initialization done");
+ }
+
+ /**
+ * Retrieves LDAP connection module.
+ * <P>
+ *
+ * @return LDAP connection instance
+ */
+ public ILdapConnModule getLdapConnModule() {
+ return mLdapConnModule;
+ }
+
+ public void setLdapConnModule(ILdapConnModule m) {
+ mLdapConnModule = (LdapConnModule) m;
+ }
+
+ /**
+ * init ldap connection
+ */
+ private void initLdapConn(IConfigStore ldapConfig)
+ throws EBaseException {
+ IConfigStore c = ldapConfig;
+
+ try {
+ //c = authConfig.getSubStore(PROP_LDAP_PUBLISH_SUBSTORE);
+ if (c != null && c.size() > 0) {
+ mLdapConnModule = new LdapConnModule();
+ mLdapConnModule.init(this, c);
+ CMS.debug("LdapPublishing connection inited");
+ } else {
+ log(ILogger.LL_FAILURE,
+ "No Ldap Module configuration found");
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_NO_LDAP_PUBLISH_CONFIG_FOUND"));
+ }
+
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE,
+ "Ldap Publishing Module failed with " + e);
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_INIT_LDAP_PUBLISH_MODULE_FAILED", e.toString()));
+ }
+ }
+
+ public void startup() throws EBaseException {
+ CMS.debug("PublisherProcessor: startup()");
+ mLdapConfig = mConfig.getSubStore(PROP_LDAP_PUBLISH_SUBSTORE);
+ if (mLdapConfig.getBoolean(PROP_ENABLE, false)) {
+ CMS.debug("PublisherProcessor: about to initLdapConn");
+ initLdapConn(mLdapConfig);
+ } else {
+ CMS.debug("No LdapPublishing enabled");
+ }
+
+ LdapRequestListener listener = null;
+ if (mConfig.getBoolean(PROP_ENABLE, false)) {
+ listener = new LdapRequestListener();
+ listener.init(this, mLdapConfig);
+ mAuthority.registerRequestListener(listener);
+ IConfigStore queueConfig = mConfig.getSubStore(PROP_QUEUE_PUBLISH_SUBSTORE);
+ if (queueConfig != null) {
+ boolean isPublishingQueueEnabled = queueConfig.getBoolean("enable", false);
+ int publishingQueuePriorityLevel = queueConfig.getInteger("priorityLevel", 0);
+ int maxNumberOfPublishingThreads = queueConfig.getInteger("maxNumberOfThreads", 1);
+ int publishingQueuePageSize = queueConfig.getInteger("pageSize", 100);
+ int savePublishingStatus = queueConfig.getInteger("saveStatus", 0);
+ CMS.debug("PublisherProcessor: startup: Publishing Queue Enabled: " + isPublishingQueueEnabled +
+ " Priority Level: " + publishingQueuePriorityLevel +
+ " Maximum Number of Threads: " + maxNumberOfPublishingThreads +
+ " Page Size: " + publishingQueuePageSize);
+ IRequestNotifier reqNotifier = ((ICertificateAuthority) mAuthority).getRequestNotifier();
+ reqNotifier.setPublishingQueue(isPublishingQueueEnabled,
+ publishingQueuePriorityLevel,
+ maxNumberOfPublishingThreads,
+ publishingQueuePageSize,
+ savePublishingStatus);
+ }
+ }
+ mLdapRequestListener = listener;
+ }
+
+ public void shutdown() {
+ CMS.debug("Shuting down publishing.");
+ try {
+ if (mLdapConnModule != null) {
+ mLdapConnModule.getLdapConnFactory().reset();
+ }
+ if (mAuthority != null && mLdapRequestListener != null) {
+ //mLdapRequestListener.shutdown();
+ mAuthority.removeRequestListener(mLdapRequestListener);
+ }
+ } catch (ELdapException e) {
+ // ignore
+ CMS.debug(e);
+ }
+ }
+
+ public Hashtable<String, RulePlugin> getRulePlugins() {
+ return mRulePlugins;
+ }
+
+ public Hashtable<String, ILdapRule> getRuleInsts() {
+ return mRuleInsts;
+ }
+
+ public Hashtable<String, MapperPlugin> getMapperPlugins() {
+ return mMapperPlugins;
+ }
+
+ public Hashtable<String, PublisherPlugin> getPublisherPlugins() {
+ return mPublisherPlugins;
+ }
+
+ public Hashtable<String, MapperProxy> getMapperInsts() {
+ return mMapperInsts;
+ }
+
+ public Hashtable<String, PublisherProxy> getPublisherInsts() {
+ return mPublisherInsts;
+ }
+
+ //certType can be client,server,ca,crl,smime
+ //XXXshould make it static to make it faster
+ public Enumeration<ILdapRule> getRules(String publishingType) {
+ Vector<ILdapRule> rules = new Vector<ILdapRule>();
+ Enumeration<String> e = mRuleInsts.keys();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ if (name == null) {
+ if (Debug.ON)
+ Debug.trace("rule name is " + "null");
+ return null;
+ } else {
+ if (Debug.ON)
+ Debug.trace("rule name is " + name);
+ }
+
+ //this is the only rule we support now
+ LdapRule rule = (LdapRule) (mRuleInsts.get(name));
+
+ if (rule.enabled() && publishingType.equals(rule.getType())) {
+ // check if the predicate match
+ ILdapExpression exp = rule.getPredicate();
+
+ try {
+ SessionContext sc = SessionContext.getContext();
+
+ if (exp != null && !exp.evaluate(sc))
+ continue;
+ } catch (Exception ex) {
+ // do nothing
+ }
+ rules.addElement(rule);
+ if (Debug.ON)
+ Debug.trace("added rule " + name + " for " + publishingType);
+ }
+
+ }
+ return rules.elements();
+ }
+
+ public Enumeration<ILdapRule> getRules(String publishingType, IRequest req) {
+ if (req == null) {
+ return getRules(publishingType);
+ }
+
+ Vector<ILdapRule> rules = new Vector<ILdapRule>();
+ Enumeration<ILdapRule> e = mRuleInsts.elements();
+
+ while (e.hasMoreElements()) {
+ //this is the only rule we support now
+ LdapRule rule = (LdapRule) e.nextElement();
+
+ if (rule.enabled() && publishingType.equals(rule.getType())) {
+ // check if the predicate match
+ ILdapExpression exp = rule.getPredicate();
+
+ try {
+ if (exp != null && !exp.evaluate(req))
+ continue;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ rules.addElement(rule);
+ if (Debug.ON)
+ Debug.trace("added rule " + rule.getInstanceName() + " for " + publishingType +
+ " request: " + req.getRequestId());
+ }
+
+ }
+ return rules.elements();
+ }
+
+ /**
+ * public PublishRuleSet getPublishRuleSet()
+ * {
+ * return mRuleSet;
+ * }
+ **/
+
+ public Vector<String> getMapperDefaultParams(String implName) throws
+ ELdapException {
+ // is this a registered implname?
+ MapperPlugin plugin = mMapperPlugins.get(implName);
+
+ if (plugin == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_MAPPER_NOT_FIND", implName));
+ throw new ELdapException(implName);
+ }
+
+ // XXX can find an instance of this plugin in existing
+ // mapper instances to avoid instantiation just for this.
+
+ // a temporary instance
+ ILdapMapper mapperInst = null;
+ String className = plugin.getClassPath();
+
+ try {
+ mapperInst = (ILdapMapper)
+ Class.forName(className).newInstance();
+ Vector<String> v = mapperInst.getDefaultParams();
+
+ return v;
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_MAPPER", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_MAPPER", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_MAPPER", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ }
+ }
+
+ public Vector<String> getMapperInstanceParams(String insName) throws
+ ELdapException {
+ ILdapMapper mapperInst = null;
+ MapperProxy proxy = mMapperInsts.get(insName);
+
+ if (proxy == null) {
+ return null;
+ }
+ mapperInst = proxy.getMapper();
+ if (mapperInst == null) {
+ return null;
+ }
+ Vector<String> v = mapperInst.getInstanceParams();
+
+ return v;
+ }
+
+ public Vector<String> getPublisherDefaultParams(String implName) throws
+ ELdapException {
+ // is this a registered implname?
+ PublisherPlugin plugin = mPublisherPlugins.get(implName);
+
+ if (plugin == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_PLUGIN_NOT_FIND", implName));
+ throw new ELdapException(implName);
+ }
+
+ // XXX can find an instance of this plugin in existing
+ // publisher instantces to avoid instantiation just for this.
+
+ // a temporary instance
+ ILdapPublisher publisherInst = null;
+ String className = plugin.getClassPath();
+
+ try {
+ publisherInst = (ILdapPublisher)
+ Class.forName(className).newInstance();
+ Vector<String> v = publisherInst.getDefaultParams();
+
+ return v;
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_PUBLISHER", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_PUBLISHER", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_PUBLISHER", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ }
+ }
+
+ public boolean isMapperInstanceEnable(String insName) {
+ MapperProxy proxy = mMapperInsts.get(insName);
+
+ if (proxy == null) {
+ return false;
+ }
+ return proxy.isEnable();
+ }
+
+ public ILdapMapper getActiveMapperInstance(String insName) {
+ MapperProxy proxy = mMapperInsts.get(insName);
+
+ if (proxy == null)
+ return null;
+ if (proxy.isEnable())
+ return proxy.getMapper();
+ else
+ return null;
+ }
+
+ public ILdapMapper getMapperInstance(String insName) {
+ MapperProxy proxy = mMapperInsts.get(insName);
+
+ if (proxy == null)
+ return null;
+ return proxy.getMapper();
+ }
+
+ public boolean isPublisherInstanceEnable(String insName) {
+ PublisherProxy proxy = mPublisherInsts.get(insName);
+
+ if (proxy == null) {
+ return false;
+ }
+ return proxy.isEnable();
+ }
+
+ public ILdapPublisher getActivePublisherInstance(String insName) {
+ PublisherProxy proxy = mPublisherInsts.get(insName);
+
+ if (proxy == null) {
+ return null;
+ }
+ if (proxy.isEnable())
+ return proxy.getPublisher();
+ else
+ return null;
+ }
+
+ public ILdapPublisher getPublisherInstance(String insName) {
+ PublisherProxy proxy = mPublisherInsts.get(insName);
+
+ if (proxy == null) {
+ return null;
+ }
+ return proxy.getPublisher();
+ }
+
+ public Vector<String> getPublisherInstanceParams(String insName) throws
+ ELdapException {
+ ILdapPublisher publisherInst = getPublisherInstance(insName);
+
+ if (publisherInst == null) {
+ return null;
+ }
+ Vector<String> v = publisherInst.getInstanceParams();
+
+ return v;
+ }
+
+ public Vector<String> getRuleDefaultParams(String implName) throws
+ ELdapException {
+ // is this a registered implname?
+ RulePlugin plugin = mRulePlugins.get(implName);
+
+ if (plugin == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_RULE_NOT_FIND", implName));
+ throw new ELdapException(implName);
+ }
+
+ // XXX can find an instance of this plugin in existing
+ // rule instantces to avoid instantiation just for this.
+
+ // a temporary instance
+ ILdapRule ruleInst = null;
+ String className = plugin.getClassPath();
+
+ try {
+ ruleInst = (ILdapRule)
+ Class.forName(className).newInstance();
+
+ Vector<String> v = ruleInst.getDefaultParams();
+
+ return v;
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_RULE", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_RULE", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_RULE", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ }
+ }
+
+ public Vector<String> getRuleInstanceParams(String implName) throws
+ ELdapException {
+ // is this a registered implname?
+ RulePlugin plugin = mRulePlugins.get(implName);
+
+ if (plugin == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_RULE_NOT_FIND", implName));
+ throw new ELdapException(implName);
+ }
+
+ // XXX can find an instance of this plugin in existing
+ // rule instantces to avoid instantiation just for this.
+
+ // a temporary instance
+ ILdapRule ruleInst = null;
+ String className = plugin.getClassPath();
+
+ try {
+ ruleInst = (ILdapRule)
+ Class.forName(className).newInstance();
+ Vector<String> v = ruleInst.getInstanceParams();
+
+ return v;
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_RULE", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_RULE", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_RULE", e.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className));
+ }
+ }
+
+ /**
+ * set published flag - true when published, false when unpublished.
+ * not exist means not published.
+ */
+ public void setPublishedFlag(BigInteger serialNo, boolean published) {
+ if (!(mAuthority instanceof ICertificateAuthority))
+ return;
+ ICertificateAuthority ca = (ICertificateAuthority) mAuthority;
+
+ try {
+ ICertificateRepository certdb = ca.getCertificateRepository();
+ ICertRecord certRec = certdb.readCertificateRecord(serialNo);
+ MetaInfo metaInfo = certRec.getMetaInfo();
+
+ if (metaInfo == null) {
+ metaInfo = new MetaInfo();
+ }
+ metaInfo.set(
+ CertRecord.META_LDAPPUBLISH, String.valueOf(published));
+ ModificationSet modSet = new ModificationSet();
+
+ modSet.add(ICertRecord.ATTR_META_INFO,
+ Modification.MOD_REPLACE, metaInfo);
+ certdb.modifyCertificateRecord(serialNo, modSet);
+ } catch (EBaseException e) {
+ // not fatal. just log warning.
+ log(ILogger.LL_WARN,
+ "Cannot mark cert 0x" + serialNo.toString(16)
+ + " published as " + published
+ + " in the ldap directory. Cert Record not found. Error: "
+ + e
+ + " Don't be alarmed if it's a subordinate ca or clone's ca siging cert. "
+ + "Otherwise your internal db may be corrupted.");
+ }
+ }
+
+ /**
+ * Publish ca cert, UpdateDir.java, jobs, request listeners
+ */
+ public void publishCACert(X509Certificate cert)
+ throws ELdapException {
+ boolean error = false;
+ StringBuffer errorRule = new StringBuffer();
+
+ if (!enabled())
+ return;
+
+ CMS.debug("PublishProcessor::publishCACert");
+
+ // get mapper and publisher for cert type.
+ Enumeration<ILdapRule> rules = getRules(PROP_LOCAL_CA);
+
+ if (rules == null || !rules.hasMoreElements()) {
+ if (isClone()) {
+ log(ILogger.LL_WARN, "No rule is found for publishing: " + PROP_LOCAL_CA + " in this clone.");
+ return;
+ } else {
+ Debug.trace(CMS.getLogMessage("CMSCORE_LDAP_NO_RULE_FOUND", PROP_LOCAL_CA));
+ //log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_RULE_FOUND", PROP_LOCAL_CA));
+ //throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_RULE_MATCHED", PROP_LOCAL_CA));
+ return;
+ }
+ }
+ while (rules.hasMoreElements()) {
+ LdapRule rule = (LdapRule) rules.nextElement();
+
+ if (rule == null) {
+ CMS.debug("PublisherProcessor::publishCACert() - "
+ + "rule is null!");
+ throw new ELdapException("rule is null");
+ }
+
+ log(ILogger.LL_INFO, "publish certificate type=" + PROP_LOCAL_CA +
+ " rule=" + rule.getInstanceName() + " publisher=" +
+ rule.getPublisher());
+
+ try {
+ ILdapMapper mapper = null;
+
+ String mapperName = rule.getMapper();
+
+ if (mapperName != null &&
+ !mapperName.trim().equals("")) {
+ mapper = getActiveMapperInstance(mapperName);
+ }
+
+ publishNow(mapper, getActivePublisherInstance(rule.getPublisher()), null/* NO REQUEsT */, cert);
+ log(ILogger.LL_INFO, "published certificate using rule=" +
+ rule.getInstanceName());
+ } catch (Exception e) {
+ // continue publishing even publisher has errors
+ //log(ILogger.LL_WARN, e.toString());
+ CMS.debug("PublisherProcessor::publishCACert returned error: " + e);
+ error = true;
+ errorRule.append(" " + rule.getInstanceName() + " error:" + e);
+ }
+ }
+ // set the ldap published flag.
+ if (!error) {
+ setPublishedFlag(cert.getSerialNumber(), true);
+ } else {
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_FAILED", errorRule.toString()));
+ }
+ }
+
+ /**
+ * This function is never called. CMS does not unpublish
+ * CA certificate.
+ */
+ public void unpublishCACert(X509Certificate cert)
+ throws ELdapException {
+ boolean error = false;
+ StringBuffer errorRule = new StringBuffer();
+
+ if (!enabled())
+ return;
+
+ // get mapper and publisher for cert type.
+ Enumeration<ILdapRule> rules = getRules(PROP_LOCAL_CA);
+
+ if (rules == null || !rules.hasMoreElements()) {
+ if (isClone()) {
+ log(ILogger.LL_WARN, "No rule is found for unpublishing: " + PROP_LOCAL_CA + " in this clone.");
+ return;
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_UNPUBLISHING_RULE_FOUND", PROP_LOCAL_CA));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_RULE_MATCHED", PROP_LOCAL_CA));
+ }
+ }
+
+ while (rules.hasMoreElements()) {
+ LdapRule rule = (LdapRule) rules.nextElement();
+
+ if (rule == null) {
+ CMS.debug("PublisherProcessor::unpublishCACert() - "
+ + "rule is null!");
+ throw new ELdapException("rule is null");
+ }
+
+ try {
+ log(ILogger.LL_INFO, "unpublish certificate type=" +
+ PROP_LOCAL_CA + " rule=" + rule.getInstanceName() +
+ " publisher=" + rule.getPublisher());
+
+ ILdapMapper mapper = null;
+
+ String mapperName = rule.getMapper();
+
+ if (mapperName != null &&
+ !mapperName.trim().equals("")) {
+ mapper = getActiveMapperInstance(mapperName);
+ }
+
+ unpublishNow(mapper, getActivePublisherInstance(rule.getPublisher()), null/* NO REQUEST */, cert);
+ log(ILogger.LL_INFO, "unpublished certificate using rule=" +
+ rule.getInstanceName());
+ } catch (Exception e) {
+ // continue publishing even publisher has errors
+ //log(ILogger.LL_WARN, e.toString());
+ error = true;
+ errorRule.append(" " + rule.getInstanceName());
+ }
+ }
+
+ // set the ldap published flag.
+ if (!error) {
+ setPublishedFlag(cert.getSerialNumber(), false);
+ } else {
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_UNPUBLISH_FAILED", errorRule.toString()));
+ }
+ }
+
+ /**
+ * Publish crossCertificatePair
+ */
+ public void publishXCertPair(byte[] pair)
+ throws ELdapException {
+ String errorRule = "";
+
+ if (!enabled())
+ return;
+ CMS.debug("PublisherProcessor: in publishXCertPair()");
+
+ // get mapper and publisher for cert type.
+ Enumeration<ILdapRule> rules = getRules(PROP_XCERT);
+
+ if (rules == null || !rules.hasMoreElements()) {
+ if (isClone()) {
+ log(ILogger.LL_WARN, "No rule is found for publishing: " + PROP_LOCAL_CA + " in this clone.");
+ return;
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_RULE_FOUND", PROP_XCERT));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_RULE_MATCHED", PROP_XCERT));
+ }
+ }
+ while (rules.hasMoreElements()) {
+ LdapRule rule = (LdapRule) rules.nextElement();
+
+ if (rule == null) {
+ CMS.debug("PublisherProcessor::publishXCertPair() - "
+ + "rule is null!");
+ throw new ELdapException("rule is null");
+ }
+
+ log(ILogger.LL_INFO, "publish certificate type=" + PROP_XCERT +
+ " rule=" + rule.getInstanceName() + " publisher=" +
+ rule.getPublisher());
+ try {
+ ILdapMapper mapper = null;
+
+ String mapperName = rule.getMapper();
+
+ if (mapperName != null &&
+ !mapperName.trim().equals("")) {
+ mapper = getActiveMapperInstance(mapperName);
+ }
+
+ publishNow(mapper, getActivePublisherInstance(rule.getPublisher()), null/* NO REQUEsT */, pair);
+ log(ILogger.LL_INFO, "published Xcertificates using rule=" +
+ rule.getInstanceName());
+ } catch (Exception e) {
+ // continue publishing even publisher has errors
+ //log(ILogger.LL_WARN, e.toString());
+ errorRule = errorRule + " " + rule.getInstanceName() +
+ " error:" + e;
+
+ CMS.debug("PublisherProcessor::publishXCertPair: error: " + e);
+ }
+ }
+ }
+
+ /**
+ * Publishs regular user certificate based on the criteria
+ * set in the request.
+ */
+ public void publishCert(X509Certificate cert, IRequest req)
+ throws ELdapException {
+ boolean error = false;
+ StringBuffer errorRule = new StringBuffer();
+
+ CMS.debug("In PublisherProcessor::publishCert");
+ if (!enabled())
+ return;
+
+ // get mapper and publisher for cert type.
+ Enumeration<ILdapRule> rules = getRules("certs", req);
+
+ // Bugscape #52306 - Remove superfluous log messages on failure
+ if (rules == null || !rules.hasMoreElements()) {
+ CMS.debug("Publishing: can't find publishing rule,exiting routine.");
+
+ error = true;
+ errorRule.append("No rules enabled");
+ }
+
+ while (rules != null && rules.hasMoreElements()) {
+ LdapRule rule = (LdapRule) rules.nextElement();
+
+ try {
+ log(ILogger.LL_INFO,
+ "publish certificate (with request) type=" +
+ "certs" + " rule=" + rule.getInstanceName() +
+ " publisher=" + rule.getPublisher());
+ ILdapPublisher p = getActivePublisherInstance(rule.getPublisher());
+ ILdapMapper m = null;
+ String mapperName = rule.getMapper();
+
+ if (mapperName != null) {
+ m = getActiveMapperInstance(mapperName);
+ }
+ publishNow(m, p, req, cert);
+ log(ILogger.LL_INFO, "published certificate using rule=" +
+ rule.getInstanceName());
+ } catch (Exception e) {
+ // continue publishing even publisher has errors
+ //log(ILogger.LL_WARN, e.toString());
+ error = true;
+ errorRule.append(" " + rule.getInstanceName());
+ }
+ }
+ // set the ldap published flag.
+ if (!error) {
+ setPublishedFlag(cert.getSerialNumber(), true);
+ } else {
+ CMS.debug("PublishProcessor::publishCert : " + CMS.getUserMessage("CMS_LDAP_PUBLISH_FAILED", errorRule.toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_FAILED", errorRule.toString()));
+ }
+ }
+
+ /**
+ * Unpublish user certificate. This is used by
+ * UnpublishExpiredJob.
+ */
+ public void unpublishCert(X509Certificate cert, IRequest req)
+ throws ELdapException {
+ boolean error = false;
+ StringBuffer errorRule = new StringBuffer();
+
+ if (!enabled())
+ return;
+
+ // get mapper and publisher for cert type.
+ Enumeration<ILdapRule> rules = getRules("certs", req);
+
+ if (rules == null || !rules.hasMoreElements()) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_UNPUBLISHING_RULE_FOUND_FOR_REQUEST", "certs",
+ req.getRequestId().toString()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_RULE_MATCHED",
+ req.getRequestId().toString()));
+ }
+
+ while (rules.hasMoreElements()) {
+ LdapRule rule = (LdapRule) rules.nextElement();
+
+ if (rule == null) {
+ CMS.debug("PublisherProcessor::unpublishCert() - "
+ + "rule is null!");
+ throw new ELdapException("rule is null");
+ }
+
+ try {
+ log(ILogger.LL_INFO,
+ "unpublish certificate (with request) type=" +
+ "certs" + " rule=" + rule.getInstanceName() +
+ " publisher=" + rule.getPublisher());
+
+ ILdapMapper mapper = null;
+
+ String mapperName = rule.getMapper();
+
+ if (mapperName != null &&
+ !mapperName.trim().equals("")) {
+ mapper = getActiveMapperInstance(mapperName);
+ }
+
+ unpublishNow(mapper, getActivePublisherInstance(rule.getPublisher()),
+ req, cert);
+ log(ILogger.LL_INFO, "unpublished certificate using rule=" +
+ rule.getInstanceName());
+ } catch (Exception e) {
+ // continue publishing even publisher has errors
+ //log(ILogger.LL_WARN, e.toString());
+ error = true;
+ errorRule.append(" " + rule.getInstanceName());
+ }
+ }
+
+ // set the ldap published flag.
+ if (!error) {
+ setPublishedFlag(cert.getSerialNumber(), false);
+ } else {
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_UNPUBLISH_FAILED", errorRule.toString()));
+ }
+ }
+
+ /**
+ * publishes a crl by mapping the issuer name in the crl to an entry
+ * and publishing it there. entry must be a certificate authority.
+ * Note that this is used by cmsgateway/cert/UpdateDir.java
+ */
+ public void publishCRL(X509CRLImpl crl, String crlIssuingPointId)
+ throws ELdapException {
+ boolean error = false;
+ String errorRule = "";
+
+ if (!enabled())
+ return;
+ ILdapMapper mapper = null;
+ ILdapPublisher publisher = null;
+
+ // get mapper and publisher for cert type.
+ Enumeration<ILdapRule> rules = getRules(PROP_LOCAL_CRL);
+
+ if (rules == null || !rules.hasMoreElements()) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_RULE_FOR_CRL"));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_RULE_MATCHED",
+ PROP_LOCAL_CRL));
+ }
+
+ LDAPConnection conn = null;
+ String dn = null;
+
+ try {
+ if (mLdapConnModule != null) {
+ conn = mLdapConnModule.getConn();
+ }
+ while (rules.hasMoreElements()) {
+ mapper = null;
+ dn = null;
+ String result = null;
+ LdapRule rule = (LdapRule) rules.nextElement();
+
+ log(ILogger.LL_INFO, "publish crl rule=" +
+ rule.getInstanceName() + " publisher=" +
+ rule.getPublisher());
+ try {
+ String mapperName = rule.getMapper();
+
+ if (mapperName != null &&
+ !mapperName.trim().equals("")) {
+ mapper = getActiveMapperInstance(mapperName);
+ }
+ if (mapper == null || mapper.getImplName().equals("NoMap")) {
+ dn = ((X500Name) crl.getIssuerDN()).toLdapDNString();
+ } else {
+
+ result = mapper.map(conn, crl);
+ dn = result;
+ if (!mCreateOwnDNEntry) {
+ if (dn == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_MAPPER_NOT_MAP", rule.getMapper()));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH",
+ crl.getIssuerDN().toString()));
+
+ }
+ }
+ }
+ publisher = getActivePublisherInstance(rule.getPublisher());
+ if (publisher != null) {
+ if (publisher instanceof com.netscape.cms.publish.publishers.FileBasedPublisher)
+ ((com.netscape.cms.publish.publishers.FileBasedPublisher) publisher)
+ .setIssuingPointId(crlIssuingPointId);
+ publisher.publish(conn, dn, crl);
+ log(ILogger.LL_INFO, "published crl using rule=" + rule.getInstanceName());
+ }
+ // continue publishing even publisher has errors
+ } catch (Exception e) {
+ //e.printStackTrace();
+ CMS.debug(
+ "Error publishing CRL to " + dn + ": " + e);
+ error = true;
+ errorRule = errorRule + " " + rule.getInstanceName();
+
+ CMS.debug("PublisherProcessor::publishCRL: error: " + e);
+ }
+ }
+ } catch (ELdapException e) {
+ //e.printStackTrace();
+ CMS.debug(
+ "Error publishing CRL to " + dn + ": " + e);
+ throw e;
+ } finally {
+ if (conn != null) {
+ mLdapConnModule.returnConn(conn);
+ }
+ }
+ if (error)
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_FAILED", errorRule));
+ }
+
+ /**
+ * publishes a crl by mapping the issuer name in the crl to an entry
+ * and publishing it there. entry must be a certificate authority.
+ */
+ public void publishCRL(String dn, X509CRL crl)
+ throws ELdapException {
+ boolean error = false;
+ String errorRule = "";
+
+ if (!enabled())
+ return;
+ // get mapper and publisher for cert type.
+ Enumeration<ILdapRule> rules = getRules(PROP_LOCAL_CRL);
+
+ if (rules == null || !rules.hasMoreElements()) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_RULE_FOR_CRL"));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_RULE_MATCHED",
+ PROP_LOCAL_CRL));
+ }
+
+ LDAPConnection conn = null;
+ ILdapPublisher publisher = null;
+
+ try {
+ if (mLdapConnModule != null) {
+ conn = mLdapConnModule.getConn();
+ }
+ while (rules.hasMoreElements()) {
+ LdapRule rule = (LdapRule) rules.nextElement();
+
+ log(ILogger.LL_INFO, "publish crl dn=" + dn + " rule=" +
+ rule.getInstanceName() + " publisher=" +
+ rule.getPublisher());
+ try {
+ publisher = getActivePublisherInstance(rule.getPublisher());
+ if (publisher != null) {
+ publisher.publish(conn, dn, crl);
+ log(ILogger.LL_INFO, "published crl using rule=" + rule.getInstanceName());
+ }
+ } catch (Exception e) {
+ CMS.debug(
+ "Error publishing CRL to " + dn + ": " + e);
+ error = true;
+ errorRule = errorRule + " " + rule.getInstanceName();
+ CMS.debug("PublisherProcessor::publishCRL: error: " + e);
+ }
+ }
+ } catch (ELdapException e) {
+ CMS.debug(
+ "Error publishing CRL to " + dn + ": " + e);
+ throw e;
+ } finally {
+ if (conn != null) {
+ mLdapConnModule.returnConn(conn);
+ }
+ }
+ if (error)
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_FAILED", errorRule));
+ }
+
+ private void publishNow(ILdapMapper mapper, ILdapPublisher publisher,
+ IRequest r, Object obj) throws ELdapException {
+ if (!enabled())
+ return;
+ CMS.debug("PublisherProcessor: in publishNow()");
+ LDAPConnection conn = null;
+
+ try {
+ Object dirdn = null;
+
+ if (mapper != null) {
+ if (mLdapConnModule != null) {
+ try {
+ conn = mLdapConnModule.getConn();
+ } catch (ELdapException e) {
+ throw e;
+ }
+ }
+ try {
+ if ((mapper instanceof com.netscape.cms.publish.mappers.LdapCertSubjMap) &&
+ ((com.netscape.cms.publish.mappers.LdapCertSubjMap) mapper).useAllEntries()) {
+ dirdn = ((com.netscape.cms.publish.mappers.LdapCertSubjMap) mapper).mapAll(conn, r, obj);
+ } else {
+ dirdn = mapper.map(conn, r, obj);
+ }
+ } catch (Throwable e1) {
+ CMS.debug("Error mapping: mapper=" + mapper + " error=" + e1.toString());
+ throw e1;
+ }
+ }
+
+ X509Certificate cert = (X509Certificate) obj;
+
+ try {
+ if (dirdn instanceof Vector) {
+ @SuppressWarnings("unchecked")
+ Vector<String> dirdnVector = (Vector<String>) dirdn;
+ int n = dirdnVector.size();
+ for (int i = 0; i < n; i++) {
+ publisher.publish(conn, dirdnVector.elementAt(i), cert);
+ }
+ } else if (dirdn instanceof String ||
+ publisher instanceof com.netscape.cms.publish.publishers.FileBasedPublisher) {
+ publisher.publish(conn, (String) dirdn, cert);
+ }
+ } catch (Throwable e1) {
+ CMS.debug("PublisherProcessor::publishNow : publisher=" + publisher + " error=" + e1.toString());
+ throw e1;
+ }
+ log(ILogger.LL_INFO, "published certificate serial number: 0x" +
+ cert.getSerialNumber().toString(16));
+ } catch (ELdapException e) {
+ throw e;
+ } catch (Throwable e) {
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH", e.toString()));
+ } finally {
+ if (conn != null) {
+ mLdapConnModule.returnConn(conn);
+ }
+ }
+ }
+
+ // for crosscerts
+ private void publishNow(ILdapMapper mapper, ILdapPublisher publisher,
+ IRequest r, byte[] bytes) throws ELdapException {
+ if (!enabled())
+ return;
+ CMS.debug("PublisherProcessor: in publishNow() for xcerts");
+
+ // use ca cert publishing map and rule
+ ICertificateAuthority ca = (ICertificateAuthority) mAuthority;
+ X509Certificate caCert = ca.getCACert();
+
+ LDAPConnection conn = null;
+
+ try {
+ String dirdn = null;
+
+ if (mapper != null) {
+ if (mLdapConnModule != null) {
+ conn = mLdapConnModule.getConn();
+ }
+ try {
+ dirdn = mapper.map(conn, r, caCert);
+ CMS.debug("PublisherProcessor: dirdn=" + dirdn);
+
+ } catch (Throwable e1) {
+ CMS.debug("Error mapping: mapper=" + mapper + " error=" + e1.toString());
+ throw e1;
+ }
+ }
+
+ try {
+ CMS.debug("PublisherProcessor: publisher impl name=" + publisher.getImplName());
+
+ publisher.publish(conn, dirdn, bytes);
+ } catch (Throwable e1) {
+ CMS.debug("Error publishing: publisher=" + publisher + " error=" + e1.toString());
+ throw e1;
+ }
+ log(ILogger.LL_INFO, "published crossCertPair");
+ } catch (ELdapException e) {
+ throw e;
+ } catch (Throwable e) {
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH", e.toString()));
+ } finally {
+ if (conn != null) {
+ mLdapConnModule.returnConn(conn);
+ }
+ }
+ }
+
+ private void unpublishNow(ILdapMapper mapper, ILdapPublisher publisher,
+ IRequest r, Object obj) throws ELdapException {
+ if (!enabled())
+ return;
+ LDAPConnection conn = null;
+
+ try {
+ String dirdn = null;
+
+ if (mapper != null) {
+ if (mLdapConnModule != null) {
+ conn = mLdapConnModule.getConn();
+ }
+ dirdn = mapper.map(conn, r, obj);
+ }
+ X509Certificate cert = (X509Certificate) obj;
+
+ publisher.unpublish(conn, dirdn, cert);
+ log(ILogger.LL_INFO, "unpublished certificate serial number: 0x" +
+ cert.getSerialNumber().toString(16));
+ } catch (ELdapException e) {
+ throw e;
+ } finally {
+ if (conn != null) {
+ mLdapConnModule.returnConn(conn);
+ }
+ }
+ }
+
+ public boolean ldapEnabled() {
+ try {
+ if (mInited)
+ return mLdapConfig.getBoolean(PROP_ENABLE, false);
+ else
+ return false;
+ } catch (EBaseException e) {
+ return false;
+ }
+ }
+
+ public boolean enabled() {
+ try {
+ if (mInited)
+ return mConfig.getBoolean(PROP_ENABLE, false);
+ else
+ return false;
+ } catch (EBaseException e) {
+ return false;
+ }
+ }
+
+ public ISubsystem getAuthority() {
+ return mAuthority;
+ }
+
+ public boolean isClone() {
+ if ((mAuthority instanceof ICertificateAuthority) &&
+ ((ICertificateAuthority) mAuthority).isClone())
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * logs an entry in the log file.
+ */
+ public void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM,
+ ILogger.S_LDAP, level, "Publishing: " + msg);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAnonConnFactory.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAnonConnFactory.java
new file mode 100644
index 000000000..dfc974e0b
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAnonConnFactory.java
@@ -0,0 +1,475 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldapconn;
+
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSocketFactory;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * Factory for getting LDAP Connections to a LDAP server
+ * each connection is a seperate thread that can be bound to a different
+ * authentication dn and password.
+ */
+public class LdapAnonConnFactory implements ILdapConnFactory {
+ protected int mMinConns = 5;
+ protected int mMaxConns = 1000;
+ protected LdapConnInfo mConnInfo = null;
+
+ private ILogger mLogger = CMS.getLogger();
+
+ public static final String PROP_MINCONNS = "minConns";
+ public static final String PROP_MAXCONNS = "maxConns";
+ public static final String PROP_LDAPCONNINFO = "ldapconn";
+
+ public static final String PROP_ERROR_IF_DOWN = "errorIfDown";
+
+ private int mNumConns = 0; // number of available conns in array
+ private int mTotal = 0; // total num conns
+ private AnonConnection mConns[] = null;
+
+ private boolean mInited = false;
+
+ private boolean mErrorIfDown;
+ private boolean mDefErrorIfDown = false;
+
+ /**
+ * Constructor for initializing from the config store.
+ * must be followed by init(IConfigStore)
+ */
+ public LdapAnonConnFactory() {
+ }
+
+ public LdapAnonConnFactory(boolean defErrorIfDown) {
+ mDefErrorIfDown = defErrorIfDown;
+ }
+
+ /**
+ * Constructor for LdapAnonConnFactory
+ *
+ * @param minConns minimum number of connections to have available
+ * @param maxConns max number of connections to have available. This is
+ * the maximum number of clones of this connection one wants to allow.
+ * @param serverInfo server connection info - host, port, etc.
+ */
+ public LdapAnonConnFactory(int minConns, int maxConns,
+ LdapConnInfo connInfo) throws ELdapException {
+ init(minConns, maxConns, connInfo);
+ }
+
+ public int totalConn() {
+ return mTotal;
+ }
+
+ public int freeConn() {
+ return mNumConns;
+ }
+
+ public int maxConn() {
+ return mMaxConns;
+ }
+
+ /**
+ * init routine to be called when initialize from config store.
+ */
+ public void init(IConfigStore config) throws EBaseException, ELdapException {
+ String minStr = config.getString(PROP_MINCONNS, "");
+ String maxStr = config.getString(PROP_MAXCONNS, "");
+ int minConns = mMinConns;
+ int maxConns = mMaxConns;
+
+ // if it is "", use the default value
+ if (!minStr.equals("")) {
+ try {
+ minConns = Integer.parseInt(minStr);
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAPCONN_MIN_CONN"));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_NUMBER_FORMAT_1", PROP_MINCONNS));
+ }
+ }
+
+ // if it is "", use the default value
+ if (!maxStr.equals("")) {
+ try {
+ maxConns = Integer.parseInt(maxStr);
+ } catch (NumberFormatException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAPCONN_MAX_CONN"));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_NUMBER_FORMAT_1", PROP_MAXCONNS));
+ }
+ }
+
+ mErrorIfDown = config.getBoolean(PROP_ERROR_IF_DOWN, mDefErrorIfDown);
+
+ init(minConns, maxConns,
+ new LdapConnInfo(config.getSubStore(PROP_LDAPCONNINFO)));
+ }
+
+ /**
+ * initialize routine from parameters.
+ */
+ protected void init(int minConns, int maxConns, LdapConnInfo connInfo)
+ throws ELdapException {
+ if (mInited)
+ return; // XXX should throw exception here ?
+
+ if (minConns <= 0 || maxConns <= 0 || minConns > maxConns)
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INVALID_NUMCONN_PARAMETERS"));
+ if (connInfo == null)
+ throw new IllegalArgumentException("connInfo is Null!");
+
+ mMinConns = minConns;
+ mMaxConns = maxConns;
+ mConnInfo = connInfo;
+
+ mConns = new AnonConnection[mMaxConns];
+
+ log(ILogger.LL_INFO,
+ "Created: min " + minConns + " max " + maxConns +
+ " host " + connInfo.getHost() + " port " + connInfo.getPort() +
+ " secure " + connInfo.getSecure());
+
+ // initalize minimum number of connection handles available.
+ makeMinimum(mErrorIfDown);
+ mInited = true;
+ }
+
+ /**
+ * make the mininum configured connections
+ */
+ protected void makeMinimum(boolean errorIfDown) throws ELdapException {
+ try {
+ if (mNumConns < mMinConns && mTotal < mMaxConns) {
+ int increment = Math.min(mMinConns - mNumConns, mMaxConns - mTotal);
+
+ CMS.debug(
+ "increasing minimum number of connections by " + increment);
+ for (int i = increment - 1; i >= 0; i--) {
+ mConns[i] = new AnonConnection(mConnInfo);
+ }
+ mTotal += increment;
+ mNumConns += increment;
+ CMS.debug(
+ "new total number of connections " + mTotal);
+ CMS.debug(
+ "new total available connections " + mNumConns);
+ }
+ } catch (LDAPException e) {
+ // XXX errorCodeToString() used here so users won't see message.
+ // though why are messages from exceptions being displayed to
+ // users ?
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ "Cannot connect to Ldap server. Error: " +
+ "Ldap Server host " + mConnInfo.getHost() +
+ " int " + mConnInfo.getPort() + " is unavailable.");
+ if (errorIfDown) {
+ throw new ELdapServerDownException(
+ CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE",
+ mConnInfo.getHost(), "" + mConnInfo.getPort()));
+ }
+ } else {
+ log(ILogger.LL_FAILURE,
+ "Cannot connect to ldap server. error: " + e.toString());
+ String errmsg = e.errorCodeToString();
+
+ if (errmsg == null)
+ errmsg = e.toString();
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_CONNECT_TO_LDAP_SERVER_FAILED",
+ mConnInfo.getHost(), "" + (Integer.valueOf(mConnInfo.getPort())), errmsg));
+ }
+ }
+ }
+
+ /**
+ * Gets connection from this factory.
+ * All connections gotten from this factory must be returned.
+ * If not the max number of connections may be reached prematurely.
+ * The best thing to put returnConn in a finally clause so it
+ * always gets called. For example,
+ *
+ * <pre>
+ * LDAPConnection c = null;
+ * try {
+ * c = factory.getConn();
+ * myclass.do_something_with_c(c);
+ * } catch (ELdapException e) {
+ * handle_error_here();
+ * } finally {
+ * factory.returnConn(c);
+ * }
+ * </pre>
+ */
+ public LDAPConnection getConn()
+ throws ELdapException {
+ return getConn(true);
+ }
+
+ /**
+ * Returns a LDAP connection - a clone of the master connection.
+ * All connections should be returned to the factory using returnConn()
+ * to recycle connection objects.
+ * If not returned the limited max number is affected but if that
+ * number is large not much harm is done.
+ * Returns null if maximum number of connections reached.
+ * <p>
+ * The best thing to put returnConn in a finally clause so it always gets called. For example,
+ *
+ * <pre>
+ * LDAPConnection c = null;
+ * try {
+ * c = factory.getConn();
+ * myclass.do_something_with_c(c);
+ * } catch (ELdapException e) {
+ * handle_error_here();
+ * } finally {
+ * factory.returnConn(c);
+ * }
+ * </pre>
+ */
+ public synchronized LDAPConnection getConn(boolean waitForConn)
+ throws ELdapException {
+ boolean waited = false;
+
+ CMS.debug("LdapAnonConnFactory::getConn");
+ if (mNumConns == 0)
+ makeMinimum(true);
+ if (mNumConns == 0) {
+ if (!waitForConn)
+ return null;
+ try {
+ CMS.debug("getConn(): out of ldap connections");
+ log(ILogger.LL_WARN,
+ "Ran out of ldap connections available " +
+ "in ldap connection pool to " +
+ mConnInfo.getHost() + ":" + mConnInfo.getPort() + ". " +
+ "This could be a temporary condition or an indication of " +
+ "something more serious that can cause the server to " +
+ "hang.");
+ waited = true;
+ while (mNumConns == 0) {
+ wait();
+ }
+ } catch (InterruptedException e) {
+ }
+ }
+
+ mNumConns--;
+ AnonConnection conn = mConns[mNumConns];
+
+ mConns[mNumConns] = null;
+ if (waited) {
+ log(ILogger.LL_WARN,
+ "Ldap connections are available again in ldap connection pool " +
+ "to " + mConnInfo.getHost() + ":" + mConnInfo.getPort());
+ }
+ CMS.debug("LdapAnonConnFactory.getConn(): num avail conns now " + mNumConns);
+ //Beginning of fix for Bugzilla #630176
+ boolean isConnected = false;
+ if (conn != null) {
+ isConnected = conn.isConnected();
+ }
+
+ if (!isConnected) {
+ CMS.debug("LdapAnonConnFactory.getConn(): selected conn is down, try to reconnect...");
+ conn = null;
+ try {
+ conn = new AnonConnection(mConnInfo);
+ } catch (LDAPException e) {
+ CMS.debug("LdapAnonConnFactory.getConn(): error when trying to bring back a down connection.");
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_CONNECT_TO_LDAP_SERVER_FAILED",
+ mConnInfo.getHost(), "" + (Integer.valueOf(mConnInfo.getPort())), e.toString()));
+ }
+ }
+ //This is the end of the fix for Bugzilla #630176
+
+ return conn;
+ }
+
+ /**
+ * Returns a connection to the factory for recycling.
+ * All connections gotten from this factory must be returned.
+ * If not the max number of connections may be reached prematurely.
+ * <p>
+ * The best thing to put returnConn in a finally clause so it always gets called. For example,
+ *
+ * <pre>
+ * LDAPConnection c = null;
+ * try {
+ * c = factory.getConn();
+ * myclass.do_something_with_c(c);
+ * } catch (ELdapException e) {
+ * handle_error_here();
+ * } finally {
+ * factory.returnConn(c);
+ * }
+ * </pre>
+ */
+ public synchronized void returnConn(LDAPConnection conn) {
+ if (conn == null) {
+ return;
+ }
+ AnonConnection anon = null;
+
+ // check if conn is valid and from this factory.
+ if (conn instanceof AnonConnection) {
+ anon = (AnonConnection) conn;
+ } else {
+ log(ILogger.LL_WARN, "returnConn : Connection is not an AnonConnection");
+ return;
+ }
+
+ if (anon.getFacId() != mConns) {
+ // returning a connection not from this factory.
+ log(ILogger.LL_WARN, "returnConn: unknown connection.");
+ }
+ // check if conn has already been returned.
+ for (int i = 0; i < mNumConns; i++) {
+ // returning connection already returned.
+ if (mConns[i] == anon) {
+
+ /* swallow this error but see who's doing it. */
+ log(ILogger.LL_WARN,
+ "returnConn: previously returned connection.");
+ }
+ }
+
+ // this returned connection might authenticate as someone other than
+ // anonymonus. Reset it to anonymous first before it returns
+ // to the pool. Do this by calling connect() again on this connection
+ // to avoid doing an explicit anonymous bind
+ try {
+ anon.connect(mConnInfo.getHost(), mConnInfo.getPort());
+
+ // return conn.
+ CMS.debug("returnConn: mNumConns now " + mNumConns);
+ } catch (LDAPException e) {
+ log(ILogger.LL_WARN,
+ "Could not re-authenticate ldap connection to anonymous." +
+ " Error " + e);
+ }
+ // return the connection even if can't reauthentication anon.
+ // most likely server was down.
+ mConns[mNumConns++] = anon;
+
+ notify();
+ }
+
+ protected void finalize()
+ throws Exception {
+ reset();
+ }
+
+ /**
+ * returns connection info.
+ */
+ public LdapConnInfo getConnInfo() {
+ return mConnInfo;
+ }
+
+ /**
+ * resets this factory - if no connections outstanding,
+ * disconnections all connections and resets everything to 0 as if
+ * no connections were ever made. intended to be called just before
+ * shutdown or exit to disconnection & cleanup connections.
+ */
+ // ok only if no connections outstanding.
+ public synchronized void reset()
+ throws ELdapException {
+ if (mNumConns == mTotal) {
+ for (int i = 0; i < mNumConns; i++) {
+ try {
+ CMS.debug("disconnecting connection " + i);
+ mConns[i].disconnect();
+ } catch (LDAPException e) {
+ log(ILogger.LL_INFO,
+ "exception during disconnect: " + e.toString());
+ }
+ mConns[i] = null;
+ }
+ mTotal = 0;
+ mNumConns = 0;
+ } else {
+ log(ILogger.LL_INFO,
+ "Cannot reset() while connections not all returned");
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_CANNOT_RESET_CONNFAC"));
+ }
+ }
+
+ /**
+ * handy routine for logging in this class.
+ */
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "In Ldap (anonymous) connection pool to" +
+ " host " + mConnInfo.getHost() +
+ " port " + mConnInfo.getPort() + ", " + msg);
+ }
+
+ /**
+ * used to keep track of connections from this factory.
+ */
+ public class AnonConnection extends LdapAnonConnection {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 4813780131074412404L;
+
+ public AnonConnection(LdapConnInfo connInfo)
+ throws LDAPException {
+ super(connInfo);
+ }
+
+ public AnonConnection(String host, int port, int version,
+ LDAPSocketFactory fac)
+ throws LDAPException {
+ super(host, port, version, fac);
+ }
+
+ /**
+ * instantiates a non-secure connection to a ldap server
+ */
+ public AnonConnection(String host, int port, int version)
+ throws LDAPException {
+ super(host, port, version);
+ }
+
+ /**
+ * used only to identify the factory from which this came.
+ * mConns to identify factory.
+ */
+ public AnonConnection[] getFacId() {
+ return mConns;
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAnonConnection.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAnonConnection.java
new file mode 100644
index 000000000..52cdc4b1e
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAnonConnection.java
@@ -0,0 +1,101 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldapconn;
+
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSocketFactory;
+import netscape.ldap.LDAPv2;
+
+/**
+ * A LDAP connection that is bound to a server host, port and secure type.
+ * Makes a LDAP connection when instantiated.
+ * Cannot establish another LDAP connection after construction.
+ * LDAPConnection connect methods are overridden to prevent this.
+ */
+public class LdapAnonConnection extends LDAPConnection {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 6671180208419384682L;
+
+ /**
+ * instantiates a connection to a ldap server
+ */
+ public LdapAnonConnection(LdapConnInfo connInfo)
+ throws LDAPException {
+ super(connInfo.getSecure() ? new LdapJssSSLSocketFactory() : null);
+
+ // Set option to automatically follow referrals.
+ // rebind info is also anonymous.
+ boolean followReferrals = connInfo.getFollowReferrals();
+
+ setOption(LDAPv2.REFERRALS, Boolean.valueOf(followReferrals));
+
+ if (connInfo.getVersion() == LDAPv2.PROTOCOL_VERSION) {
+ super.connect(connInfo.getVersion(),
+ connInfo.getHost(), connInfo.getPort(), null, null);
+ } else {
+ // use the following connect() call because it connects but does
+ // not authenticate with an anonymous bind. This requires LDAPv3.
+ super.connect(connInfo.getHost(), connInfo.getPort());
+ }
+ }
+
+ /**
+ * instantiates a connection to a ldap server
+ */
+ public LdapAnonConnection(String host, int port, int version,
+ LDAPSocketFactory fac)
+ throws LDAPException {
+ super(fac);
+ if (version == LDAPv2.PROTOCOL_VERSION) {
+ super.connect(version, host, port, null, null);
+ } else {
+ // use the following connect() call because it connects but does
+ // not authenticate with an anonymous bind. This requires LDAPv3.
+ super.connect(host, port);
+ }
+ }
+
+ /**
+ * instantiates a non-secure connection to a ldap server
+ */
+ public LdapAnonConnection(String host, int port, int version)
+ throws LDAPException {
+ super();
+ if (version == LDAPv2.PROTOCOL_VERSION) {
+ super.connect(version, host, port, null, null);
+ } else {
+ // use the following connect() call because it connects but does
+ // not authenticate with an anonymous bind. This requires LDAPv3.
+ super.connect(host, port);
+ }
+ }
+
+ /**
+ * overrides superclass connect.
+ * does not allow reconnect.
+ */
+ public void connect(int version, String host, int port,
+ String dn, String pw) throws LDAPException {
+ throw new RuntimeException(
+ "this LdapAnonConnection already connected: connect(v,h,p)");
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAuthInfo.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAuthInfo.java
new file mode 100644
index 000000000..eb3fde26c
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAuthInfo.java
@@ -0,0 +1,298 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldapconn;
+
+import java.util.Hashtable;
+
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ldap.ILdapAuthInfo;
+import com.netscape.cmsutil.password.IPasswordStore;
+
+/**
+ * class for reading ldap authentication info from config store
+ */
+public class LdapAuthInfo implements ILdapAuthInfo {
+
+ protected int mType = -1;
+ protected String[] mParms = null;
+
+ private boolean mInited = false;
+
+ private static Hashtable<String, String> passwords = new Hashtable<String, String>();
+
+ /**
+ * must call init(config) after this constructor.
+ */
+ public LdapAuthInfo() {
+ }
+
+ /**
+ * constructs ldap auth info directly from config store.
+ */
+ public LdapAuthInfo(IConfigStore config) throws EBaseException {
+ init(config);
+ }
+
+ /**
+ * constructs ldap auth info directly from config store, and verifies
+ * the password by attempting to connect to the server.
+ */
+ public LdapAuthInfo(IConfigStore config, String host, int port, boolean secure)
+ throws EBaseException {
+ init(config, host, port, secure);
+ }
+
+ public String getPasswordFromStore(String prompt) {
+ String pwd = null;
+ CMS.debug("LdapAuthInfo: getPasswordFromStore: try to get it from password store");
+
+ // hey - should use password store interface to allow different implementations
+ // but the problem is, other parts of the system just go directly to the file
+ // so calling CMS.getPasswordStore() will give you an outdated one
+ /*
+ IConfigStore mainConfig = CMS.getConfigStore();
+ String pwdFile = mainConfig.getString("passwordFile");
+ FileConfigStore pstore = new FileConfigStore(pwdFile);
+ */
+ IPasswordStore pwdStore = CMS.getPasswordStore();
+ CMS.debug("LdapAuthInfo: getPasswordFromStore: about to get from passwored store: " + prompt);
+
+ // support publishing dirsrv with different pwd than internaldb
+
+ // Finally, interactively obtain the password from the user
+ if (pwdStore != null) {
+ CMS.debug("LdapAuthInfo: getPasswordFromStore: password store available");
+ pwd = pwdStore.getPassword(prompt);
+ // pwd = pstore.getString(prompt);
+ if (pwd == null) {
+ CMS.debug("LdapAuthInfo: getPasswordFromStore: password for " + prompt +
+ " not found, trying internaldb");
+
+ // pwd = pstore.getString("internaldb");
+
+ pwd = pwdStore.getPassword("internaldb"); // last resort
+ } else
+ CMS.debug("LdapAuthInfo: getPasswordFromStore: password found for prompt in password store");
+ } else
+ CMS.debug("LdapAuthInfo: getPasswordFromStore: password store not available: pwdStore is null");
+
+ return pwd;
+ }
+
+ /**
+ * initialize this class from the config store.
+ */
+ public void init(IConfigStore config) throws EBaseException {
+ init(config, null, 0, true);
+ }
+
+ /**
+ * initialize this class from the config store, and verify the password.
+ *
+ * @param host The host that the directory server is running on.
+ * This will be used to verify the password by attempting to connect.
+ * If it is <code>null</code>, the password will not be verified.
+ * @param port The port that the directory server is running on.
+ */
+ public void init(IConfigStore config, String host, int port, boolean secure)
+ throws EBaseException {
+
+ CMS.debug("LdapAuthInfo: init()");
+ if (mInited) {
+ CMS.debug("LdapAuthInfo: already initialized");
+ return; // XXX throw exception here ?
+ }
+ CMS.debug("LdapAuthInfo: init begins");
+
+ String authTypeStr = config.getString(PROP_LDAPAUTHTYPE);
+
+ if (authTypeStr.equals(LDAP_BASICAUTH_STR)) {
+ // is the password found in memory?
+ boolean inMem = false;
+ mType = LDAP_AUTHTYPE_BASICAUTH;
+ mParms = new String[2];
+ mParms[0] = config.getString(PROP_BINDDN);
+
+ // Passwords should only be written to the file for testing,
+ // never in production
+ mParms[1] = config.getString(PROP_BINDPW, null);
+
+ // Next, see if this password has been requested before
+ String prompt = config.getString(PROP_BINDPW_PROMPT, null);
+
+ if (prompt == null) {
+ prompt = "LDAP Authentication";
+ CMS.debug("LdapAuthInfo: init: prompt is null, change to " + prompt);
+ } else
+ CMS.debug("LdapAuthInfo: init: prompt is " + prompt);
+
+ if (mParms[1] == null) {
+ CMS.debug("LdapAuthInfo: init: try getting from memory cache");
+ mParms[1] = passwords.get(prompt);
+ if (mParms[1] != null) {
+ inMem = true;
+ CMS.debug("LdapAuthInfo: init: got password from memory");
+ } else
+ CMS.debug("LdapAuthInfo: init: password not in memory");
+ } else
+ CMS.debug("LdapAuthInfo: init: found password from config");
+
+ if (mParms[1] == null) {
+ mParms[1] = getPasswordFromStore(prompt);
+ } else {
+ CMS.debug("LdapAuthInfo: init: password found for prompt.");
+ }
+
+ // verify the password
+ if ((mParms[1] != null) && (!mParms[1].equals("")) && (host == null ||
+ authInfoOK(host, port, secure, mParms[0], mParms[1]))) {
+ // The password is OK or uncheckable
+ CMS.debug("LdapAuthInfo: password ok: store in memory cache");
+ passwords.put(prompt, mParms[1]);
+ } else {
+ if (mParms[1] == null)
+ CMS.debug("LdapAuthInfo: password not found");
+ else {
+ CMS.debug("LdapAuthInfo: password does not work");
+ /* what do you know? Our IPasswordStore does not have a remove function.
+ pstore.remove("internaldb");
+ */
+ if (inMem) {
+ // this is for the case when admin changes pwd
+ // from console
+ mParms[1] = getPasswordFromStore(prompt);
+ if (authInfoOK(host, port, secure, mParms[0], mParms[1])) {
+ CMS.debug("LdapAuthInfo: password ok: store in memory cache");
+ passwords.put(prompt, mParms[1]);
+ }
+ }
+ }
+ }
+
+ } else if (authTypeStr.equals(LDAP_SSLCLIENTAUTH_STR)) {
+ mType = LDAP_AUTHTYPE_SSLCLIENTAUTH;
+ mParms = new String[1];
+ mParms[0] = config.getString(PROP_CLIENTCERTNICKNAME, null);
+ } else {
+ throw new IllegalArgumentException(
+ "Unknown Ldap authentication type " + authTypeStr);
+ }
+ mInited = true;
+ CMS.debug("LdapAuthInfo: init ends");
+ }
+
+ public void reset() {
+ try {
+ conn.disconnect();
+ } catch (LDAPException e) {
+ }
+ }
+
+ /**
+ * Verifies the distinguished name and password by attempting to
+ * authenticate to the server. If we connect to the server but cannot
+ * authenticate, we conclude that the DN or password is invalid. If
+ * we cannot connect at all, we don't know, so we return true
+ * (there's no sense asking for the password again since we can't verify
+ * it anyway). If we connect and authenticate successfully, we know
+ * the DN and password are correct, so we return true.
+ */
+ private static LDAPConnection conn = new LDAPConnection();
+
+ private static boolean
+ authInfoOK(String host, int port, boolean secure, String dn, String pw) {
+
+ // We dont perform auth checking if we are in SSL mode.
+ if (secure)
+ return true;
+
+ boolean connected = false, authenticated = false;
+
+ try {
+ conn.connect(host, port);
+ connected = true;
+ conn.authenticate(dn, pw);
+ authenticated = true;
+ } catch (LDAPException e) {
+ }
+
+ /**
+ * There is a bug in LDAP SDK. VM will crash on NT if
+ * we connect and disconnect too many times.
+ **/
+
+ /**
+ * if( connected ) {
+ * try {
+ * conn.disconnect();
+ * } catch( LDAPException e ) { }
+ * }
+ **/
+
+ if (connected && !authenticated) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * get authentication type.
+ *
+ * @return one of: <br>
+ * LdapAuthInfo.LDAP_AUTHTYPE_BASICAUTH or
+ * LdapAuthInfo.LDAP_AUTHTYPE_SSLCLIENTAUTH
+ */
+ public int getAuthType() {
+ return mType;
+ }
+
+ /**
+ * get params for authentication
+ *
+ * @return array of parameters for this authentication.
+ */
+ public String[] getParms() {
+ return mParms.clone();
+ }
+
+ /**
+ * add password
+ */
+ public void addPassword(String prompt, String pw) {
+ try {
+ passwords.put(prompt, pw);
+ } catch (Exception e) {
+ }
+ }
+
+ /**
+ * remove password
+ */
+ public void removePassword(String prompt) {
+ try {
+ passwords.remove(prompt);
+ } catch (Exception e) {
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapBoundConnFactory.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapBoundConnFactory.java
new file mode 100644
index 000000000..5be645b56
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapBoundConnFactory.java
@@ -0,0 +1,536 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldapconn;
+
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSocketFactory;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ELdapServerDownException;
+import com.netscape.certsrv.ldap.ILdapBoundConnFactory;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * Factory for getting LDAP Connections to a LDAP server with the same
+ * LDAP authentication.
+ * XXX not sure how useful this is given that LDAPConnection itself can
+ * be shared by multiple threads and cloned.
+ */
+public class LdapBoundConnFactory implements ILdapBoundConnFactory {
+ protected int mMinConns = 5;
+ protected int mMaxConns = 1000;
+ protected LdapConnInfo mConnInfo = null;
+ protected LdapAuthInfo mAuthInfo = null;
+
+ private ILogger mLogger = CMS.getLogger();
+
+ public static final String PROP_MINCONNS = "minConns";
+ public static final String PROP_MAXCONNS = "maxConns";
+ public static final String PROP_LDAPCONNINFO = "ldapconn";
+ public static final String PROP_LDAPAUTHINFO = "ldapauth";
+
+ public static final String PROP_ERROR_IF_DOWN = "errorIfDown";
+
+ private int mNumConns = 0; // number of available conns in array
+ private int mTotal = 0; // total num conns
+
+ private boolean doCloning = true;
+ private LdapBoundConnection mMasterConn = null; // master connection object.
+ private BoundConnection mConns[];
+
+ /**
+ * return error if server is down at creation time.
+ */
+ private boolean mErrorIfDown;
+
+ /**
+ * default value for the above at init time.
+ */
+ private boolean mDefErrorIfDown = false;
+
+ /**
+ * Constructor for initializing from the config store.
+ * must be followed by init(IConfigStore)
+ */
+ public LdapBoundConnFactory() {
+ }
+
+ public LdapBoundConnFactory(boolean defErrorIfDown) {
+ mDefErrorIfDown = defErrorIfDown;
+ }
+
+ public int totalConn() {
+ return mTotal;
+ }
+
+ public synchronized int freeConn() {
+ return mNumConns;
+ }
+
+ public int maxConn() {
+ return mMaxConns;
+ }
+
+ /**
+ * Constructor for LdapBoundConnFactory
+ *
+ * @param minConns minimum number of connections to have available
+ * @param maxConns max number of connections to have available. This is
+ * the maximum number of clones of this connection or separate connections one wants to allow.
+ * @param serverInfo server connection info - host, port, etc.
+ */
+ public LdapBoundConnFactory(int minConns, int maxConns,
+ LdapConnInfo connInfo, LdapAuthInfo authInfo) throws ELdapException {
+ init(minConns, maxConns, connInfo, authInfo);
+ }
+
+ /**
+ * Constructor for initialize
+ */
+ public void init(IConfigStore config)
+ throws ELdapException, EBaseException {
+
+ CMS.debug("LdapBoundConnFactory: init ");
+ LdapConnInfo connInfo =
+ new LdapConnInfo(config.getSubStore(PROP_LDAPCONNINFO));
+
+ mErrorIfDown = config.getBoolean(PROP_ERROR_IF_DOWN, mDefErrorIfDown);
+
+ doCloning = config.getBoolean("doCloning", true);
+
+ CMS.debug("LdapBoundConnFactory:doCloning " + doCloning);
+ init(config.getInteger(PROP_MINCONNS, mMinConns),
+ config.getInteger(PROP_MAXCONNS, mMaxConns),
+ connInfo,
+ new LdapAuthInfo(config.getSubStore(PROP_LDAPAUTHINFO),
+ connInfo.getHost(), connInfo.getPort(), connInfo.getSecure()));
+ }
+
+ /**
+ * initialize parameters obtained from either constructor or
+ * config store
+ *
+ * @param minConns minimum number of connection handls to have available.
+ * @param maxConns maximum total number of connections to ever have.
+ * @param connInfo ldap connection info.
+ * @param authInfo ldap authentication info.
+ * @exception ELdapException if any error occurs.
+ */
+ private void init(int minConns, int maxConns,
+ LdapConnInfo connInfo, LdapAuthInfo authInfo)
+ throws ELdapException {
+ if (minConns <= 0 || maxConns <= 0 || minConns > maxConns)
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_INVALID_NUMCONN_PARAMETERS"));
+ if (connInfo == null || authInfo == null)
+ throw new IllegalArgumentException("connInfo or authInfo is null!");
+
+ mMinConns = minConns;
+ mMaxConns = maxConns;
+ mConnInfo = connInfo;
+ mAuthInfo = authInfo;
+
+ mConns = new BoundConnection[mMaxConns];
+
+ // Create connection handle and make initial connection
+ CMS.debug(
+ "init: before makeConnection errorIfDown is " + mErrorIfDown);
+ makeConnection(mErrorIfDown);
+
+ CMS.debug(
+ "initializing with mininum " + mMinConns + " and maximum " + mMaxConns +
+ " connections to " +
+ "host " + mConnInfo.getHost() + " port " + mConnInfo.getPort() +
+ ", secure connection, " + mConnInfo.getSecure() +
+ ", authentication type " + mAuthInfo.getAuthType());
+
+ // initalize minimum number of connection handles available.
+ makeMinimum();
+ }
+
+ /**
+ * makes the initial master connection used to clone others..
+ *
+ * @exception ELdapException if any error occurs.
+ */
+ protected void makeConnection(boolean errorIfDown) throws ELdapException {
+ CMS.debug("makeConnection: errorIfDown " + errorIfDown);
+ try {
+ mMasterConn = new BoundConnection(mConnInfo, mAuthInfo);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAPCONN_CONNECT_SERVER",
+ mConnInfo.getHost(),
+ Integer.toString(mConnInfo.getPort())));
+ if (errorIfDown) {
+ throw new ELdapServerDownException(
+ CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE",
+ mConnInfo.getHost(), "" + mConnInfo.getPort()));
+ }
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAPCONN_FAILED_SERVER", e.toString()));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_CONNECT_TO_LDAP_SERVER_FAILED",
+ mConnInfo.getHost(), "" + (Integer.valueOf(mConnInfo.getPort())), e.toString()));
+ }
+ }
+ }
+
+ /**
+ * makes subsequent connections if cloning is not used .
+ *
+ * @exception ELdapException if any error occurs.
+ */
+ private LdapBoundConnection makeNewConnection(boolean errorIfDown) throws ELdapException {
+ CMS.debug("LdapBoundConnFactory:In makeNewConnection: errorIfDown " + errorIfDown);
+ LdapBoundConnection conn = null;
+ try {
+ conn = new BoundConnection(mConnInfo, mAuthInfo);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ // need to intercept this because message from LDAP is
+ // "DSA is unavailable" which confuses with DSA PKI.
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAPCONN_CONNECT_SERVER",
+ mConnInfo.getHost(),
+ Integer.toString(mConnInfo.getPort())));
+ if (errorIfDown) {
+ throw new ELdapServerDownException(
+ CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE",
+ mConnInfo.getHost(), "" + mConnInfo.getPort()));
+ }
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAPCONN_FAILED_SERVER", e.toString()));
+ throw new ELdapException(
+ CMS.getUserMessage("CMS_LDAP_CONNECT_TO_LDAP_SERVER_FAILED",
+ mConnInfo.getHost(), "" + (Integer.valueOf(mConnInfo.getPort())), e.toString()));
+ }
+ }
+
+ return conn;
+ }
+
+ /**
+ * makes the minumum number of connections
+ */
+ private void makeMinimum() throws ELdapException {
+ if (mMasterConn == null || mMasterConn.isConnected() == false)
+ return;
+ int increment;
+
+ if (mNumConns < mMinConns && mTotal <= mMaxConns) {
+ increment = Math.min(mMinConns - mNumConns, mMaxConns - mTotal);
+ CMS.debug(
+ "increasing minimum connections by " + increment);
+ for (int i = increment - 1; i >= 0; i--) {
+
+ if (doCloning == true) {
+ mConns[i] = (BoundConnection) mMasterConn.clone();
+ } else {
+ mConns[i] = (BoundConnection) makeNewConnection(true);
+ }
+
+ }
+ mTotal += increment;
+ mNumConns += increment;
+ CMS.debug("new total available connections " + mTotal);
+ CMS.debug("new number of connections " + mNumConns);
+ }
+ }
+
+ /**
+ * gets a conenction from this factory.
+ * All connections obtained from the factory must be returned by
+ * returnConn() method.
+ * The best thing to do is to put returnConn in a finally clause so it
+ * always gets called. For example,
+ *
+ * <pre>
+ * LDAPConnection c = null;
+ * try {
+ * c = factory.getConn();
+ * myclass.do_something_with_c(c);
+ * } catch (ELdapException e) {
+ * handle_error_here();
+ * } finally {
+ * factory.returnConn(c);
+ * }
+ * </pre>
+ */
+ public LDAPConnection getConn()
+ throws ELdapException {
+ return getConn(true);
+ }
+
+ /**
+ * Returns a LDAP connection - a clone of the master connection.
+ * All connections should be returned to the factory using returnConn()
+ * to recycle connection objects.
+ * If not returned the limited max number is affected but if that
+ * number is large not much harm is done.
+ * Returns null if maximum number of connections reached.
+ * The best thing to do is to put returnConn in a finally clause so it
+ * always gets called. For example,
+ *
+ * <pre>
+ * LDAPConnection c = null;
+ * try {
+ * c = factory.getConn();
+ * myclass.do_something_with_c(c);
+ * } catch (ELdapException e) {
+ * handle_error_here();
+ * } finally {
+ * factory.returnConn(c);
+ * }
+ * </pre>
+ */
+ public synchronized LDAPConnection getConn(boolean waitForConn)
+ throws ELdapException {
+ boolean waited = false;
+
+ CMS.debug("In LdapBoundConnFactory::getConn()");
+ if (mMasterConn != null)
+ CMS.debug("masterConn is connected: " + mMasterConn.isConnected());
+ else
+ CMS.debug("masterConn is null.");
+
+ if (mMasterConn == null || !mMasterConn.isConnected()) {
+ try {
+ makeConnection(true);
+ } catch (ELdapException e) {
+ mMasterConn = null;
+ CMS.debug("Can't create master connection in LdapBoundConnFactory::getConn! " + e.toString());
+ throw e;
+ }
+ }
+
+ if (mNumConns == 0)
+ makeMinimum();
+ if (mNumConns == 0) {
+ if (!waitForConn)
+ return null;
+ try {
+ CMS.debug("getConn: out of ldap connections");
+ log(ILogger.LL_WARN,
+ "Ran out of ldap connections available " +
+ "in ldap connection pool to " +
+ mConnInfo.getHost() + ":" + mConnInfo.getPort() + ". " +
+ "This could be a temporary condition or an indication of " +
+ "something more serious that can cause the server to " +
+ "hang.");
+ waited = true;
+ while (mNumConns == 0)
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ mNumConns--;
+ LDAPConnection conn = mConns[mNumConns];
+
+ boolean isConnected = false;
+ if (conn != null) {
+ isConnected = conn.isConnected();
+ }
+
+ CMS.debug("getConn: conn is connected " + isConnected);
+
+ //If masterConn is still alive, lets try to bring this one
+ //back to life
+
+ if ((isConnected == false) && (mMasterConn != null)
+ && (mMasterConn.isConnected() == true)) {
+ CMS.debug("Attempt to bring back down connection.");
+
+ if (doCloning == true) {
+ mConns[mNumConns] = (BoundConnection) mMasterConn.clone();
+ } else {
+ try {
+ mConns[mNumConns] = (BoundConnection) makeNewConnection(true);
+ } catch (ELdapException e) {
+ mConns[mNumConns] = null;
+ }
+ }
+ conn = mConns[mNumConns];
+
+ CMS.debug("Re-animated connection: " + conn);
+ }
+
+ mConns[mNumConns] = null;
+
+ if (waited) {
+ log(ILogger.LL_WARN,
+ "Ldap connections are available again in ldap connection pool " +
+ "to " + mConnInfo.getHost() + ":" + mConnInfo.getPort());
+ }
+ CMS.debug("getConn: mNumConns now " + mNumConns);
+
+ return conn;
+ }
+
+ /**
+ * Teturn connection to the factory.
+ * This is mandatory after a getConn().
+ * The best thing to do is to put returnConn in a finally clause so it
+ * always gets called. For example,
+ *
+ * <pre>
+ * LDAPConnection c = null;
+ * try {
+ * c = factory.getConn();
+ * myclass.do_something_with_c(c);
+ * } catch (ELdapException e) {
+ * handle_error_here();
+ * } finally {
+ * factory.returnConn(c);
+ * }
+ * </pre>
+ */
+ public synchronized void returnConn(LDAPConnection conn) {
+ if (conn == null) {
+ return;
+ }
+ BoundConnection boundconn = null;
+
+ if (conn instanceof BoundConnection) {
+ boundconn = (BoundConnection) conn;
+ } else {
+ log(ILogger.LL_WARN, "returnConn : Connection is not an BoundConnection");
+ return;
+ }
+
+ if (boundconn.getFacId() != mConns) {
+ log(ILogger.LL_WARN, "returnConn: unknown connection.");
+ }
+ for (int i = 0; i < mNumConns; i++) {
+ if (mConns[i] == conn) {
+ CMS.debug(
+ "returnConn: previously returned connection.");
+ }
+ }
+ mConns[mNumConns++] = boundconn;
+ CMS.debug("returnConn: mNumConns now " + mNumConns);
+ notify();
+ }
+
+ /**
+ * handy routine for logging in this class.
+ */
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_LDAP, level,
+ "In Ldap (bound) connection pool to" +
+ " host " + mConnInfo.getHost() +
+ " port " + mConnInfo.getPort() + ", " + msg);
+ }
+
+ protected void finalize()
+ throws Exception {
+ reset();
+ }
+
+ /**
+ * used for disconnecting all connections and reset everything to 0
+ * as if connections were never made. used just before a subsystem
+ * shutdown or process exit.
+ * useful only if no connections are outstanding.
+ */
+ public synchronized void reset()
+ throws ELdapException {
+ if (mNumConns == mTotal) {
+ for (int i = 0; i < mNumConns; i++) {
+ try {
+ mConns[i].disconnect();
+ } catch (LDAPException e) {
+ }
+ mConns[i] = null;
+ }
+ if (mMasterConn != null) {
+ try {
+ log(ILogger.LL_INFO, "disconnecting masterConn");
+ mMasterConn.disconnect();
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAPCONN_CANNOT_RESET",
+ e.toString()));
+ }
+ }
+ mMasterConn = null;
+ mTotal = 0;
+ mNumConns = 0;
+ } else {
+ CMS.debug(
+ "Cannot reset factory: connections not all returned");
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_CANNOT_RESET_CONNFAC"));
+ }
+
+ if (mAuthInfo != null) {
+ mAuthInfo.reset();
+ }
+ }
+
+ /**
+ * return ldap connection info
+ */
+ public LdapConnInfo getConnInfo() {
+ return mConnInfo;
+ }
+
+ /**
+ * return ldap authentication info
+ */
+ public LdapAuthInfo getAuthInfo() {
+ return mAuthInfo;
+ }
+
+ /**
+ * used to keep track of connections from this factory.
+ */
+ public class BoundConnection extends LdapBoundConnection {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1353616391879078337L;
+
+ public BoundConnection(LdapConnInfo connInfo, LdapAuthInfo authInfo)
+ throws LDAPException {
+ super(connInfo, authInfo);
+ }
+
+ public BoundConnection(String host, int port, int version,
+ LDAPSocketFactory fac,
+ String bindDN, String bindPW)
+ throws LDAPException {
+ super(host, port, version, fac, bindDN, bindPW);
+ }
+
+ /**
+ * used only to identify the factory from which this came.
+ */
+ public BoundConnection[] getFacId() {
+ return mConns;
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapBoundConnection.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapBoundConnection.java
new file mode 100644
index 000000000..787967a5f
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapBoundConnection.java
@@ -0,0 +1,204 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldapconn;
+
+import java.util.Properties;
+
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPRebind;
+import netscape.ldap.LDAPRebindAuth;
+import netscape.ldap.LDAPSocketFactory;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.apps.CMS;
+
+/**
+ * A LDAP connection that is bound to a server host, port, secure type.
+ * and authentication.
+ * Makes a LDAP connection and authentication when instantiated.
+ * Cannot establish another LDAP connection or authentication after
+ * construction. LDAPConnection connect and authentication methods are
+ * overridden to prevent this.
+ */
+public class LdapBoundConnection extends LDAPConnection {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2242077674357271559L;
+ // LDAPConnection calls authenticate so must set this for first
+ // authenticate call.
+ @SuppressWarnings("unused")
+ private boolean mAuthenticated;
+
+ /**
+ * Instantiates a connection to a ldap server, secure or non-secure
+ * connection with Ldap basic bind dn & pw authentication.
+ */
+ public LdapBoundConnection(
+ LdapConnInfo connInfo, LdapAuthInfo authInfo)
+ throws LDAPException {
+ // this LONG line to satisfy super being the first call. (yuk)
+ super(
+ authInfo.getAuthType() == LdapAuthInfo.LDAP_AUTHTYPE_SSLCLIENTAUTH ?
+ new LdapJssSSLSocketFactory(authInfo.getParms()[0]) :
+ (connInfo.getSecure() ? new LdapJssSSLSocketFactory() : null));
+
+ // Set option to automatically follow referrals.
+ // Use the same credentials to follow referrals; this is the easiest
+ // thing to do without any complicated configuration using
+ // different hosts.
+ // If client auth is used don't have dn and pw to follow referrals.
+
+ boolean followReferrals = connInfo.getFollowReferrals();
+
+ setOption(LDAPv2.REFERRALS,Boolean.valueOf(followReferrals));
+ if (followReferrals &&
+ authInfo.getAuthType() != LdapAuthInfo.LDAP_AUTHTYPE_SSLCLIENTAUTH) {
+ LDAPRebind rebindInfo =
+ new ARebindInfo(authInfo.getParms()[0],
+ authInfo.getParms()[1]);
+
+ setOption(LDAPv2.REFERRALS_REBIND_PROC, rebindInfo);
+ }
+
+ if (authInfo.getAuthType() == LdapAuthInfo.LDAP_AUTHTYPE_SSLCLIENTAUTH) {
+ // will be bound to client auth cert mapped entry.
+ super.connect(connInfo.getHost(), connInfo.getPort());
+ CMS.debug(
+ "Established LDAP connection with SSL client auth to " +
+ connInfo.getHost() + ":" + connInfo.getPort());
+ } else { // basic auth
+ String binddn = authInfo.getParms()[0];
+ String bindpw = authInfo.getParms()[1];
+
+ super.connect(connInfo.getVersion(),
+ connInfo.getHost(), connInfo.getPort(), binddn, bindpw);
+ CMS.debug(
+ "Established LDAP connection using basic authentication to" +
+ " host " + connInfo.getHost() +
+ " port " + connInfo.getPort() +
+ " as " + binddn);
+ }
+ }
+
+ /**
+ * Instantiates a connection to a ldap server, secure or non-secure
+ * connection with Ldap basic bind dn & pw authentication.
+ */
+ public LdapBoundConnection(String host, int port, int version,
+ LDAPSocketFactory fac,
+ String bindDN, String bindPW)
+ throws LDAPException {
+ super(fac);
+ if (bindDN != null) {
+ super.connect(version, host, port, bindDN, bindPW);
+ CMS.debug(
+ "Established LDAP connection using basic authentication " +
+ " as " + bindDN + " to " + host + ":" + port);
+ } else {
+ if (fac == null && bindDN == null) {
+ throw new IllegalArgumentException(
+ "Ldap bound connection must have authentication info.");
+ }
+ // automatically authenticated if it's ssl client auth.
+ super.connect(version, host, port, null, null);
+ CMS.debug(
+ "Established LDAP connection using SSL client authentication " +
+ "to " + host + ":" + port);
+ }
+ }
+
+ /**
+ * Overrides same method in LDAPConnection to do prevent re-authentication.
+ */
+ public void authenticate(int version, String dn, String pw)
+ throws LDAPException {
+
+ /**
+ * if (mAuthenticated) {
+ * throw new RuntimeException(
+ * "this LdapBoundConnection already authenticated: auth(v,dn,pw)");
+ * }
+ **/
+ super.authenticate(version, dn, pw);
+ mAuthenticated = true;
+ }
+
+ /**
+ * Overrides same method in LDAPConnection to do prevent re-authentication.
+ */
+ public void authenticate(String dn, String pw)
+ throws LDAPException {
+
+ /**
+ * if (mAuthenticated) {
+ * throw new RuntimeException(
+ * "this LdapBoundConnection already authenticated: auth(dn,pw)");
+ * }
+ **/
+ super.authenticate(3, dn, pw);
+ mAuthenticated = true;
+ }
+
+ /**
+ * Overrides same method in LDAPConnection to do prevent re-authentication.
+ */
+ public void authenticate(String dn, String mechs[],
+ Properties props, Object getter)
+ throws LDAPException {
+
+ /**
+ * if (mAuthenticated) {
+ * throw new RuntimeException(
+ * "this LdapBoundConnection is already authenticated: auth(mechs)");
+ * }
+ **/
+ super.authenticate(dn, mechs, props, getter);
+ mAuthenticated = true;
+ }
+
+ /**
+ * overrides parent's connect to prevent re-connect.
+ */
+ public void connect(String host, int port) throws LDAPException {
+ throw new RuntimeException(
+ "this LdapBoundConnection is already connected: conn(host,port)");
+ }
+
+ /**
+ * overrides parent's connect to prevent re-connect.
+ */
+ public void connect(int version, String host, int port,
+ String dn, String pw) throws LDAPException {
+ throw new RuntimeException(
+ "this LdapBoundConnection is already connected: conn(version,h,p)");
+ }
+}
+
+class ARebindInfo implements LDAPRebind {
+ private LDAPRebindAuth mRebindAuthInfo = null;
+
+ public ARebindInfo(String binddn, String pw) {
+ mRebindAuthInfo = new LDAPRebindAuth(binddn, pw);
+ }
+
+ public LDAPRebindAuth getRebindAuthentication(String host, int port) {
+ return mRebindAuthInfo;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapConnInfo.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapConnInfo.java
new file mode 100644
index 000000000..47dfb0fb1
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapConnInfo.java
@@ -0,0 +1,119 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldapconn;
+
+import netscape.ldap.LDAPv2;
+
+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.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ILdapConnInfo;
+
+/**
+ * class for reading ldap connection from the config store.
+ * ldap connection info: host, port, secure connection
+ */
+public class LdapConnInfo implements ILdapConnInfo {
+
+ private String mHost = null;
+ private int mPort = -1;
+ private boolean mSecure = false;
+ private int mVersion = LDAPv2.PROTOCOL_VERSION;
+ private boolean mFollowReferrals = true;
+
+ /**
+ * default constructor. must be followed by init(IConfigStore)
+ */
+ public LdapConnInfo(IConfigStore config) throws EBaseException, ELdapException {
+ init(config);
+ }
+
+ /**
+ * initializes an instance from a config store.
+ * required parms: host, port
+ * optional parms: secure connection, authentication method & info.
+ */
+ public void init(IConfigStore config) throws EBaseException, ELdapException {
+ mHost = config.getString(PROP_HOST);
+ mPort = config.getInteger(PROP_PORT);
+ String version = config.get(PROP_PROTOCOL);
+
+ if (version != null && version.equals("")) {
+ // provide a default when this field is blank from the
+ // configuration.
+ mVersion = LDAP_VERSION_3;
+ } else {
+ mVersion = config.getInteger(PROP_PROTOCOL, LDAP_VERSION_3);
+ if (mVersion != LDAP_VERSION_2 && mVersion != LDAP_VERSION_3) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_PROPERTY", PROP_PROTOCOL));
+ }
+ }
+ if (mHost == null || (mHost.length() == 0) || (mHost.trim().equals(""))) {
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", PROP_HOST));
+ }
+ if (mPort <= 0) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_PROPERTY", PROP_PORT));
+ }
+ mSecure = config.getBoolean(PROP_SECURE, false);
+ mFollowReferrals = config.getBoolean(PROP_FOLLOW_REFERRALS, true);
+ }
+
+ public LdapConnInfo(String host, int port, boolean secure) {
+ mHost = host;
+ mPort = port;
+ mSecure = secure;
+ if (mHost == null || mPort <= 0) {
+ // XXX log something here
+ throw new IllegalArgumentException("LDAP host or port is null");
+ }
+ }
+
+ public LdapConnInfo(String host, int port) {
+ mHost = host;
+ mPort = port;
+ if (mHost == null || mPort <= 0) {
+ // XXX log something here
+ throw new IllegalArgumentException("LDAP host or port is null");
+ }
+ }
+
+ public String getHost() {
+ return mHost;
+ }
+
+ public int getPort() {
+ return mPort;
+ }
+
+ public int getVersion() {
+ return mVersion;
+ }
+
+ public boolean getSecure() {
+ return mSecure;
+ }
+
+ public boolean getFollowReferrals() {
+ return mFollowReferrals;
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.java
new file mode 100644
index 000000000..4d9e60251
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldapconn;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSSLSocketFactoryExt;
+
+import org.mozilla.jss.ssl.SSLHandshakeCompletedEvent;
+import org.mozilla.jss.ssl.SSLHandshakeCompletedListener;
+import org.mozilla.jss.ssl.SSLSocket;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * Uses HCL ssl socket.
+ *
+ * @author Lily Hsiao lhsiao@netscape.com
+ */
+public class LdapJssSSLSocketFactory implements LDAPSSLSocketFactoryExt {
+ private String mClientAuthCertNickname = null;
+ private boolean mClientAuth = false;
+
+ public LdapJssSSLSocketFactory() {
+ }
+
+ public LdapJssSSLSocketFactory(String certNickname) {
+ mClientAuthCertNickname = certNickname;
+ }
+
+ public Socket makeSocket(String host, int port) throws LDAPException {
+ SSLSocket s = null;
+
+ try {
+ SSLSocket.enableSSL2Default(false);
+ s = new SSLSocket(host, port);
+ s.setUseClientMode(true);
+ s.enableSSL2(false);
+ //TODO Do we really want to set the default each time?
+ SSLSocket.enableSSL2Default(false);
+ s.enableV2CompatibleHello(false);
+
+ SSLHandshakeCompletedListener listener = null;
+
+ listener = new ClientHandshakeCB(this);
+ s.addHandshakeCompletedListener(listener);
+
+ if (mClientAuthCertNickname != null) {
+ mClientAuth = true;
+ CMS.debug(
+ "LdapJssSSLSocket set client auth cert nickname" +
+ mClientAuthCertNickname);
+ s.setClientCertNickname(mClientAuthCertNickname);
+ }
+ s.forceHandshake();
+ } catch (UnknownHostException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAPCONN_UNKNOWN_HOST"));
+ throw new LDAPException(
+ "Cannot Create JSS SSL Socket - Unknown host");
+ } catch (IOException e) {
+ if (s != null) {
+ try {
+ s.close();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAPCONN_IO_ERROR", e.toString()));
+ throw new LDAPException("IO Error creating JSS SSL Socket");
+ }
+ return s;
+ }
+
+ public boolean isClientAuth() {
+ return mClientAuth;
+ }
+
+ public Object getCipherSuites() {
+ return null;
+ }
+
+ public void log(int level, String msg) {
+ }
+
+ static class ClientHandshakeCB implements SSLHandshakeCompletedListener {
+ Object sc;
+
+ public ClientHandshakeCB(Object sc) {
+ this.sc = sc;
+ }
+
+ public void handshakeCompleted(SSLHandshakeCompletedEvent event) {
+ CMS.debug("SSL handshake happened");
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/listeners/ListenerPlugin.java b/base/server/cmscore/src/com/netscape/cmscore/listeners/ListenerPlugin.java
new file mode 100644
index 000000000..fbdeca579
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/listeners/ListenerPlugin.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.listeners;
+
+/**
+ * This class represents a registered listener plugin.
+ * <P>
+ *
+ * @author stevep
+ * @version $Revision$, $Date$
+ */
+public class ListenerPlugin {
+ protected String mId = null;
+ protected String mClassPath = null;
+ protected Class<?> mClass = null;
+
+ /**
+ * Constructs a Listener plugin.
+ *
+ * @param id listener implementation name
+ * @param classPath class path
+ */
+ public ListenerPlugin(String id, String classPath) {
+ // if (id == null || classPath == null)
+ // throw new AssertionException("Listener id or classpath can't be null");
+ mId = id;
+ mClassPath = classPath;
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ public String getClassPath() {
+ return mClassPath;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/logging/AuditEventFactory.java b/base/server/cmscore/src/com/netscape/cmscore/logging/AuditEventFactory.java
new file mode 100644
index 000000000..fea638eb6
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/logging/AuditEventFactory.java
@@ -0,0 +1,99 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.logging;
+
+import java.util.Properties;
+
+import com.netscape.certsrv.logging.AuditEvent;
+import com.netscape.certsrv.logging.IBundleLogEvent;
+import com.netscape.certsrv.logging.ILogEvent;
+import com.netscape.certsrv.logging.ILogEventFactory;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A log event object for handling audit messages
+ * <P>
+ *
+ * @author mikep
+ * @author mzhao
+ * @version $Revision$, $Date$
+ */
+public class AuditEventFactory implements ILogEventFactory {
+
+ /**
+ * List of supported properties.
+ */
+ public static final String PROP_BUNDLE = "bundleName";
+
+ /**
+ * Constructs a audit event factory.
+ */
+ public AuditEventFactory() {
+ }
+
+ /**
+ * Creates an log event.
+ *
+ * @param evtClass the event type
+ * @param prop the resource bundle
+ * @param source the subsystem ID who creates the log event
+ * @param level the severity of the log event
+ * @param multiline the log message has more than one line or not
+ * @param msg the detail message of the log
+ * @param params the parameters in the detail log message
+ */
+ public ILogEvent create(int evtClass, Properties prop, int source,
+ int level, boolean multiline, String msg, Object params[]) {
+ if (evtClass != ILogger.EV_AUDIT)
+ return null;
+ AuditEvent event = new AuditEvent(msg, params);
+
+ event.setLevel(level);
+ event.setSource(source);
+ event.setMultiline(multiline);
+ setProperties(prop, event);
+ return event;
+ }
+
+ /**
+ * Set the resource bundle of the log event.
+ *
+ * @param prop the properties
+ * @param event the log event
+ */
+ protected void setProperties(Properties prop, IBundleLogEvent event) {
+ if (prop == null) {
+ event.setBundleName(null);
+ } else {
+ String bundleName = (String) prop.get(PROP_BUNDLE);
+
+ if (bundleName != null) {
+ event.setBundleName(bundleName);
+ }
+ }
+ }
+
+ /**
+ * Releases an log event.
+ *
+ * @param e the log event
+ */
+ public void release(ILogEvent e) {
+ // do nothing
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/logging/AuditFormat.java b/base/server/cmscore/src/com/netscape/cmscore/logging/AuditFormat.java
new file mode 100644
index 000000000..42c3b0d6f
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/logging/AuditFormat.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.logging;
+
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * Define audit log message format
+ *
+ * @author mzhao
+ * @version $Revision$, $Date$
+ */
+public class AuditFormat {
+
+ /**
+ * default log level for writing audit log
+ */
+ public static final int LEVEL = ILogger.LL_INFO;
+
+ /**
+ * initiative: the event is from EE
+ */
+ public static final String FROMUSER = "fromUser";
+
+ /**
+ * initiative: the event is from agent
+ */
+ public static final String FROMAGENT = "fromAgent";
+
+ /**
+ * initiative: the event is from router
+ */
+ public static final String FROMROUTER = "fromRouter";
+
+ /**
+ * initiative: the event is from remote authority
+ */
+ public static final String FROMRA = "fromRemoteAuthority";
+
+ /**
+ * authentication module: no Authentication manager
+ */
+ public static final String NOAUTH = "noAuthManager";
+
+ // for ProcessCertReq.java ,kra
+ /* 0: request type
+ 1: request ID
+ 2: initiative
+ 3: auth module
+ 4: status
+ 5: cert dn
+ 6: other info. eg cert serial number, violation policies
+ */
+ public static final String FORMAT =
+ "{0} reqID {1} {2} authenticated by {3} is {4} DN requested: {5} {6}";
+ public static final String NODNFORMAT =
+ "{0} reqID {1} {2} authenticated by {3} is {4}";
+
+ public static final String ENROLLMENTFORMAT =
+ IRequest.ENROLLMENT_REQUEST + " reqID {0} {1} authenticated by {2} is {3}. DN requested: {4} {5}";
+ public static final String RENEWALFORMAT =
+ IRequest.RENEWAL_REQUEST
+ + " reqID {0} {1} authenticated by {2} is {3}. DN requested: {4} old serial number: 0x{5} {6}";
+ public static final String REVOCATIONFORMAT =
+ IRequest.REVOCATION_REQUEST
+ + " reqID {0} {1} authenticated by {2} is {3}. DN requested: {4} serial number: 0x{5} revocation reason: {6} {7}";
+
+ // 1: fromAgent AgentID: xxx authenticated by xxx
+ public static final String DOREVOKEFORMAT =
+ IRequest.REVOCATION_REQUEST
+ + " reqID {0} {1} is {2}. DN requested: {3} serial number: 0x{4} revocation reason: {5}";
+ // 1: fromAgent AgentID: xxx authenticated by xxx
+ public static final String DOUNREVOKEFORMAT =
+ IRequest.UNREVOCATION_REQUEST + " reqID {0} {1} is {2}. DN requested: {3} serial number: 0x{4}";
+
+ // 0:initiative
+ public static final String CRLUPDATEFORMAT =
+ "CRLUpdate request {0} authenticated by {1} is {2}. Id: {3}\ncrl Number: {4} last update time: {5} next update time: {6} number of entries in the CRL: {7}";
+
+ // audit user/group
+ public static final String ADDUSERFORMAT =
+ "Admin UID: {0} added User UID: {1}";
+ public static final String REMOVEUSERFORMAT =
+ "Admin UID: {0} removed User UID: {1} ";
+ public static final String MODIFYUSERFORMAT =
+ "Admin UID: {0} modified User UID: {1}";
+ public static final String ADDUSERCERTFORMAT =
+ "Admin UID: {0} added cert for User UID: {1}. cert DN: {2} serial number: 0x{3}";
+ public static final String REMOVEUSERCERTFORMAT =
+ "Admin UID: {0} removed cert of User UID: {1}. cert DN: {2} serial number: 0x{3}";
+ public static final String ADDUSERGROUPFORMAT =
+ "Admin UID: {0} added User UID: {1} to group: {2}";
+ public static final String REMOVEUSERGROUPFORMAT =
+ "Admin UID: {0} removed User UID: {1} from group: {2}";
+ public static final String ADDCERTSUBJECTDNFORMAT =
+ "Admin UID: {0} added cert subject DN for User UID: {1}. cert DN: {2}";
+ public static final String REMOVECERTSUBJECTDNFORMAT =
+ "Admin UID: {0} removed cert subject DN for User UID: {1}. cert DN: {2}";
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/logging/AuditService.java b/base/server/cmscore/src/com/netscape/cmscore/logging/AuditService.java
new file mode 100644
index 000000000..89ac6263e
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/logging/AuditService.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 com.netscape.cmscore.logging;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.commons.lang.StringUtils;
+import org.jboss.resteasy.plugins.providers.atom.Link;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.logging.AuditConfig;
+import com.netscape.certsrv.logging.AuditResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class AuditService extends PKIService implements AuditResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public final static int DEFAULT_SIZE = 20;
+
+ public AuditService() {
+ CMS.debug("AuditService.<init>()");
+ }
+
+ public AuditConfig createAuditConfig() throws UnsupportedEncodingException, EBaseException {
+
+ IConfigStore cs = CMS.getConfigStore();
+
+ AuditConfig auditConfig = new AuditConfig();
+ auditConfig.setEnabled(cs.getBoolean("log.instance.SignedAudit.enable", false));
+ auditConfig.setSigned(cs.getBoolean("log.instance.SignedAudit.logSigning", false));
+ auditConfig.setInterval(cs.getInteger("log.instance.SignedAudit.flushInterval", 5));
+ auditConfig.setBufferSize(cs.getInteger("log.instance.SignedAudit.bufferSize", 512));
+
+ // unselected events
+ for (String event : StringUtils.split(cs.getString("log.instance.SignedAudit.unselected.events", ""), ", ")) {
+ auditConfig.setOptionalEvent(event.trim(), false);
+ }
+
+ // in case of duplicates, selected events override unselected events
+ for (String event : StringUtils.split(cs.getString("log.instance.SignedAudit.events", ""), ", ")) {
+ auditConfig.setOptionalEvent(event.trim(), true);
+ }
+
+ // mandatory events
+ for (String event : StringUtils.split(cs.getString("log.instance.SignedAudit.mandatory.events", ""), ", ")) {
+ auditConfig.addMandatoryEvent(event.trim());
+ }
+
+ URI uri = uriInfo.getBaseUriBuilder().path(AuditResource.class).build();
+ auditConfig.setLink(new Link("self", uri));
+
+ return auditConfig;
+ }
+
+ @Override
+ public AuditConfig getAuditConfig() {
+
+ CMS.debug("AuditService.getAuditConfig()");
+
+ try {
+ return createAuditConfig();
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response updateAuditConfig(AuditConfig auditConfig) {
+
+ CMS.debug("AuditService.updateAuditConfig()");
+
+ try {
+ IConfigStore cs = CMS.getConfigStore();
+
+ if (auditConfig.getEnabled() != null) {
+ cs.putBoolean("log.instance.SignedAudit.enable", auditConfig.getEnabled());
+ }
+
+ if (auditConfig.getSigned() != null) {
+ cs.putBoolean("log.instance.SignedAudit.logSigning", auditConfig.getSigned());
+ }
+
+ if (auditConfig.getInterval() != null) {
+ cs.putInteger("log.instance.SignedAudit.flushInterval", auditConfig.getInterval());
+ }
+
+ if (auditConfig.getBufferSize() != null) {
+ cs.putInteger("log.instance.SignedAudit.bufferSize", auditConfig.getBufferSize());
+ }
+
+ // update events selection
+ Collection<String> selected = new LinkedHashSet<String>();
+ Collection<String> unselected = new LinkedHashSet<String>();
+
+ for (String name : auditConfig.getOptionalEvents().keySet()) {
+ Boolean value = auditConfig.getOptionalEvent(name);
+
+ if (value) {
+ selected.add(name);
+
+ } else {
+ unselected.add(name);
+ }
+ }
+
+ cs.putString("log.instance.SignedAudit.events", StringUtils.join(selected, ","));
+ cs.putString("log.instance.SignedAudit.unselected.events", StringUtils.join(unselected, ","));
+
+ // mandatory events cannot be updated
+
+ cs.commit(true);
+
+ auditConfig = createAuditConfig();
+
+ return Response
+ .ok(auditConfig)
+ .type(MediaType.APPLICATION_XML)
+ .build();
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/logging/Auditor.java b/base/server/cmscore/src/com/netscape/cmscore/logging/Auditor.java
new file mode 100644
index 000000000..f0bcb5bee
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/logging/Auditor.java
@@ -0,0 +1,210 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cmscore.logging;
+
+import java.util.Enumeration;
+import java.util.Map;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.logging.IAuditor;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class Auditor implements IAuditor {
+
+ public final static Auditor auditor = new Auditor();
+
+ public ILogger signedAuditLogger = CMS.getSignedAuditLogger();
+
+ public static IAuditor getAuditor() {
+ return auditor;
+ }
+
+ @Override
+ public String getSubjectID() {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) return null;
+
+ SessionContext context = SessionContext.getExistingContext();
+ if (context == null) return ILogger.UNIDENTIFIED;
+
+ // Initialize subject ID
+ String subjectID = (String)context.get(SessionContext.USER_ID);
+ if (subjectID == null) return ILogger.NONROLEUSER;
+
+ return subjectID.trim();
+ }
+
+ @Override
+ public String getGroups(String subjectID) {
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) return null;
+
+ if (subjectID == null || subjectID.equals(ILogger.UNIDENTIFIED))
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+
+ Enumeration<IGroup> groups;
+
+ try {
+ IUGSubsystem userGroupSubsystem = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+ groups = userGroupSubsystem.findGroups("*");
+
+ } catch (Exception e) {
+ return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+ }
+
+ StringBuilder sb = new StringBuilder();
+
+ while (groups.hasMoreElements()) {
+ IGroup group = groups.nextElement();
+
+ if (group.isMember(subjectID) == true) {
+ if (sb.length() != 0) sb.append(", ");
+ sb.append(group.getGroupID());
+ }
+ }
+
+ if (sb.length() == 0) return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+
+ return sb.toString();
+ }
+
+ @Override
+ public String getParamString(String scope, String type, String id, Map<String, String> params) {
+
+ // if no signed audit object exists, bail
+ if (signedAuditLogger == null) return null;
+ StringBuilder parameters = new StringBuilder();
+
+ // always identify the scope of the request
+ if (scope != null) {
+ parameters.append(SIGNED_AUDIT_SCOPE
+ + SIGNED_AUDIT_NAME_VALUE_DELIMITER
+ + scope);
+ } else {
+ parameters.append(SIGNED_AUDIT_EMPTY_NAME_VALUE_PAIR);
+ }
+
+ // identify the operation type of the request
+ if (type != null) {
+ parameters.append(SIGNED_AUDIT_NAME_VALUE_PAIRS_DELIMITER);
+
+ parameters.append(SIGNED_AUDIT_OPERATION
+ + SIGNED_AUDIT_NAME_VALUE_DELIMITER
+ + type);
+ }
+
+ // identify the resource type of the request
+ if (id != null) {
+ parameters.append(SIGNED_AUDIT_NAME_VALUE_PAIRS_DELIMITER);
+
+ parameters.append(SIGNED_AUDIT_RESOURCE
+ + SIGNED_AUDIT_NAME_VALUE_DELIMITER
+ + id);
+ }
+
+ if (params == null) return parameters.toString();
+
+ // identify any remaining request parameters
+
+ for (Map.Entry<String,String> entry : params.entrySet() ) {
+ String name = entry.getKey();
+
+ // skip "RULENAME" parameter
+ if (name.equals(SIGNED_AUDIT_RULENAME)) continue;
+
+ parameters.append(SIGNED_AUDIT_NAME_VALUE_PAIRS_DELIMITER);
+
+ String value = entry.getValue();
+
+ if (value == null) {
+ parameters.append(name
+ + SIGNED_AUDIT_NAME_VALUE_DELIMITER
+ + ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+ continue;
+ }
+
+ value = value.trim();
+
+ if (value.equals("")) {
+ parameters.append(name
+ + SIGNED_AUDIT_NAME_VALUE_DELIMITER
+ + ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+ continue;
+ }
+
+ //
+ // To fix Blackflag Bug # 613800:
+ //
+ // Check "com.netscape.certsrv.common.Constants" for
+ // case-insensitive "password", "pwd", and "passwd"
+ // name fields, and hide any password values:
+ //
+ if (name.equals(Constants.PASSWORDTYPE) || /* "password" */
+ name.equals(Constants.TYPE_PASSWORD) ||
+ name.equals(Constants.PR_USER_PASSWORD) ||
+ name.equals(Constants.PT_OLD_PASSWORD) ||
+ name.equals(Constants.PT_NEW_PASSWORD) ||
+ name.equals(Constants.PT_DIST_STORE) ||
+ name.equals(Constants.PT_DIST_EMAIL) ||
+ /* "pwd" */name.equals(Constants.PR_AUTH_ADMIN_PWD) ||
+ // ignore this one name.equals( Constants.PR_BINDPWD_PROMPT ) ||
+ name.equals(Constants.PR_DIRECTORY_MANAGER_PWD) ||
+ name.equals(Constants.PR_OLD_AGENT_PWD) ||
+ name.equals(Constants.PR_AGENT_PWD) ||
+ name.equals(Constants.PT_PUBLISH_PWD) ||
+ /* "passwd" */name.equals(Constants.PR_BIND_PASSWD) ||
+ name.equals(Constants.PR_BIND_PASSWD_AGAIN) ||
+ name.equals(Constants.PR_TOKEN_PASSWD)) {
+
+ // hide password value
+ parameters.append(name
+ + SIGNED_AUDIT_NAME_VALUE_DELIMITER
+ + SIGNED_AUDIT_PASSWORD_VALUE);
+
+ } else {
+ // process normally
+ parameters.append(name
+ + SIGNED_AUDIT_NAME_VALUE_DELIMITER
+ + value);
+ }
+ }
+
+ return parameters.toString();
+ }
+
+ @Override
+ public void log(String message) {
+
+ if (signedAuditLogger == null) return;
+
+ signedAuditLogger.log(
+ ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ message);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/logging/LogQueue.java b/base/server/cmscore/src/com/netscape/cmscore/logging/LogQueue.java
new file mode 100644
index 000000000..32af1bf2c
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/logging/LogQueue.java
@@ -0,0 +1,122 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.logging;
+
+import java.util.Vector;
+
+import com.netscape.certsrv.logging.ELogException;
+import com.netscape.certsrv.logging.ILogEvent;
+import com.netscape.certsrv.logging.ILogEventListener;
+import com.netscape.certsrv.logging.ILogQueue;
+
+/**
+ * A class represents a log queue.
+ * <P>
+ *
+ * @author mzhao
+ * @version $Revision$, $Date$
+ */
+public class LogQueue implements ILogQueue {
+
+ private static LogQueue mLogQueue = new LogQueue();
+ protected Vector<ILogEventListener> mListeners = null;
+
+ /**
+ * Constructs a log queue.
+ */
+ public LogQueue() {
+ }
+
+ public static ILogQueue getLogQueue() {
+ return mLogQueue;
+ }
+
+ /**
+ * Initializes the log queue.
+ * <P>
+ *
+ */
+ public void init() {
+ mListeners = new Vector<ILogEventListener>();
+
+ }
+
+ /**
+ * Stops this log queue: shuts down all registered listeners
+ * <P>
+ */
+ public void shutdown() {
+ if (mListeners == null)
+ return;
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.elementAt(i).shutdown();
+ }
+ }
+
+ /**
+ * Adds an event listener.
+ *
+ * @param listener the log event listener
+ */
+ public void addLogEventListener(ILogEventListener listener) {
+ //Make sure we don't have duplicated listener
+ if (!mListeners.contains(listener))
+ mListeners.addElement(listener);
+ }
+
+ /**
+ * Removes an event listener.
+ *
+ * @param listener the log event listener
+ */
+ public void removeLogEventListener(ILogEventListener listener) {
+ mListeners.removeElement(listener);
+ }
+
+ /**
+ * Logs an event, and notifies logger to reuse the event.
+ *
+ * @param event the log event
+ */
+ public void log(ILogEvent event) {
+ if (mListeners == null)
+ return;
+ for (int i = 0; i < mListeners.size(); i++) {
+ try {
+ mListeners.elementAt(i).log(event);
+ } catch (ELogException e) {
+ // Raidzilla Bug #57592: Don't display potentially
+ // incorrect log message.
+ // ConsoleError.send(new SystemEvent(CMS.getUserMessage("CMS_LOG_EVENT_FAILED",
+ // event.getEventType(), e.toString())));
+
+ // Don't do this again.
+ removeLogEventListener(mListeners.elementAt(i));
+ }
+ }
+ }
+
+ /**
+ * Flushes the log buffers (if any)
+ */
+ public void flush() {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.elementAt(i).flush();
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/logging/LogSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/logging/LogSubsystem.java
new file mode 100644
index 000000000..aa5714668
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/logging/LogSubsystem.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.logging;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.ELogException;
+import com.netscape.certsrv.logging.ILogEventListener;
+import com.netscape.certsrv.logging.ILogQueue;
+import com.netscape.certsrv.logging.ILogSubsystem;
+import com.netscape.certsrv.logging.LogPlugin;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * A class represents a log subsystem.
+ * <P>
+ *
+ * @author thomask
+ * @author mzhao
+ * @version $Revision$, $Date$
+ */
+public class LogSubsystem implements ILogSubsystem {
+
+ private static LogSubsystem mInstance = new LogSubsystem();
+ private static ILogQueue mLogQueue = LogQueue.getLogQueue();
+ private IConfigStore mConfig = null;
+
+ public static final String PROP_LOGGING = "log";
+
+ public static final String ID = "log";
+
+ public static final String PROP_CLASS = "class";
+ public static final String PROP_IMPL = "impl";
+ public static final String PROP_PLUGIN = "pluginName";
+ public static final String PROP_INSTANCE = "instance";
+
+ public Hashtable<String, LogPlugin> mLogPlugins = new Hashtable<String, LogPlugin>();
+ public Hashtable<String, ILogEventListener> mLogInsts = new Hashtable<String, ILogEventListener>();
+
+ /**
+ * Constructs a log subsystem.
+ */
+ private LogSubsystem() {
+ }
+
+ public String getId() {
+ return ID;
+ }
+
+ public void setId(String id) throws EBaseException {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION"));
+ }
+
+ /**
+ * Initializes the log subsystem.
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration store
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mConfig = config;
+ mLogQueue.init();
+
+ // load log plugin implementation
+ IConfigStore c = config.getSubStore(PROP_IMPL);
+ Enumeration<String> mImpls = c.getSubStoreNames();
+
+ while (mImpls.hasMoreElements()) {
+ String id = mImpls.nextElement();
+ String pluginPath = c.getString(id + "." + PROP_CLASS);
+ LogPlugin plugin = new LogPlugin(id, pluginPath);
+
+ mLogPlugins.put(id, plugin);
+ }
+ if (Debug.ON)
+ Debug.trace("loaded logger plugins");
+
+ // load log instances
+ c = config.getSubStore(PROP_INSTANCE);
+ Enumeration<String> instances = c.getSubStoreNames();
+
+ while (instances.hasMoreElements()) {
+ String insName = instances.nextElement();
+ String implName = c.getString(insName + "." +
+ PROP_PLUGIN);
+ LogPlugin plugin =
+ mLogPlugins.get(implName);
+
+ if (plugin == null) {
+ throw new EBaseException(implName);
+ }
+ String className = plugin.getClassPath();
+ // Instantiate and init the log listener.
+ ILogEventListener logInst = null;
+
+ try {
+ logInst = (ILogEventListener)
+ Class.forName(className).newInstance();
+ IConfigStore pConfig =
+ c.getSubStore(insName);
+
+ logInst.init(this, pConfig);
+ // for view from console
+
+ } catch (ClassNotFoundException e) {
+ throw new EBaseException(insName + ":Failed to instantiate class " + className);
+
+ } catch (IllegalAccessException e) {
+ throw new EBaseException(insName + ":Failed to instantiate class " + className);
+
+ } catch (InstantiationException e) {
+ throw new EBaseException(insName + ":Failed to instantiate class " + className);
+
+ } catch (Throwable e) {
+ e.printStackTrace();
+ throw new EBaseException(insName
+ + ":Failed to instantiate class " + className + " error: " + e.getMessage());
+ }
+
+ if (insName == null) {
+ throw new EBaseException("Failed to instantiate class " + insName);
+ }
+
+ // add log instance to list.
+ mLogInsts.put(insName, logInst);
+ if (Debug.ON)
+ Debug.trace("loaded log instance " + insName + " impl " + implName);
+ }
+
+ }
+
+ public void startup() throws EBaseException {
+ Debug.trace("entering LogSubsystem.startup()");
+ Enumeration<String> enum1 = mLogInsts.keys();
+
+ while (enum1.hasMoreElements()) {
+ String instName = enum1.nextElement();
+
+ Debug.trace("about to call inst=" + instName + " in LogSubsystem.startup()");
+ ILogEventListener inst = mLogInsts.get(instName);
+
+ inst.startup();
+ }
+ }
+
+ /**
+ * Stops this subsystem.
+ * <P>
+ */
+ public void shutdown() {
+ mLogQueue.shutdown();
+ }
+
+ /**
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Retrieves singleton: the LogSubsystem.
+ */
+ public static LogSubsystem getInstance() {
+ return mInstance;
+ }
+
+ /**
+ * Retrieves LogQueue.
+ */
+ public static ILogQueue getLogQueue() {
+ return mLogQueue;
+ }
+
+ public String getLogPluginName(ILogEventListener log) {
+ IConfigStore cs = log.getConfigStore();
+ if (cs == null) {
+ return "";
+ }
+ try {
+ return cs.getString("pluginName", "");
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+ /**
+ * Retrieve log instance by it's name
+ */
+ public ILogEventListener getLogInstance(String insName) {
+ return mLogInsts.get(insName);
+ }
+
+ public Hashtable<String, LogPlugin> getLogPlugins() {
+ return mLogPlugins;
+ }
+
+ public Hashtable<String, ILogEventListener> getLogInsts() {
+ return mLogInsts;
+ }
+
+ public Vector<String> getLogDefaultParams(String implName) throws
+ ELogException {
+ // is this a registered implname?
+ LogPlugin plugin = mLogPlugins.get(implName);
+
+ if (plugin == null) {
+ throw new ELogException(implName);
+ }
+
+ // a temporary instance
+ ILogEventListener LogInst = null;
+ String className = plugin.getClassPath();
+
+ try {
+ LogInst = (ILogEventListener)
+ Class.forName(className).newInstance();
+ Vector<String> v = LogInst.getDefaultParams();
+
+ return v;
+ } catch (InstantiationException e) {
+ throw new ELogException(
+ CMS.getUserMessage("CMS_LOG_LOAD_CLASS_FAIL", className));
+ } catch (ClassNotFoundException e) {
+ throw new ELogException(
+ CMS.getUserMessage("CMS_LOG_LOAD_CLASS_FAIL", className));
+ } catch (IllegalAccessException e) {
+ throw new ELogException(
+ CMS.getUserMessage("CMS_LOG_LOAD_CLASS_FAIL", className));
+ }
+ }
+
+ public Vector<String> getLogInstanceParams(String insName) throws
+ ELogException {
+ ILogEventListener logInst = getLogInstance(insName);
+
+ if (logInst == null) {
+ return null;
+ }
+ Vector<String> v = logInst.getInstanceParams();
+
+ return v;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/logging/Logger.java b/base/server/cmscore/src/com/netscape/cmscore/logging/Logger.java
new file mode 100644
index 000000000..aec4caec7
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/logging/Logger.java
@@ -0,0 +1,378 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.logging;
+
+import java.util.Hashtable;
+import java.util.Properties;
+
+import com.netscape.certsrv.logging.ILogEvent;
+import com.netscape.certsrv.logging.ILogEventFactory;
+import com.netscape.certsrv.logging.ILogQueue;
+import com.netscape.certsrv.logging.ILogger;
+
+/**
+ * A class represents certificate server logger
+ * implementation.
+ * <P>
+ *
+ * @author thomask
+ * @author mzhao
+ * @version $Revision$, $Date$
+ */
+public class Logger implements ILogger {
+
+ protected static Logger mLogger = new Logger();
+ protected ILogQueue mLogQueue = null;
+ protected Hashtable<Integer, ILogEventFactory> mFactories = new Hashtable<Integer, ILogEventFactory>();
+
+ /**
+ * Constructs a generic logger, and registers a list
+ * of resident event factories.
+ */
+ public Logger() {
+ mLogQueue = LogSubsystem.getLogQueue();
+
+ // register standard event factories
+ register(EV_AUDIT, new AuditEventFactory());
+ register(EV_SYSTEM, new SystemEventFactory());
+ register(EV_SIGNED_AUDIT, new SignedAuditEventFactory());
+ }
+
+ /**
+ * get default single global logger
+ */
+ static public Logger getLogger() {
+ return mLogger;
+ }
+
+ /**
+ * Retrieves the associated log queue.
+ */
+ public ILogQueue getLogQueue() {
+ return mLogQueue;
+ }
+
+ /**
+ * Registers log factory.
+ *
+ * @param evtClass the event class name: ILogger.EV_SYSTEM or ILogger.EV_AUDIT
+ * @param f the event factory name
+ */
+ public void register(int evtClass, ILogEventFactory f) {
+ mFactories.put(evtClass, f);
+ }
+
+ //************** default level ****************
+ /**
+ * Logs an event using default log level: ILogger.LL_INFO
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param source the source of the log event
+ * @param msg the one line detail message to be logged
+ */
+ public void log(int evtClass, int source, String msg) {
+ log(evtClass, null, source, ILogger.LL_INFO, msg, null);
+ }
+
+ /**
+ * Logs an event using default log level: ILogger.LL_INFO
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param props the resource bundle used for the detailed message
+ * @param source the source of the log event
+ * @param msg the one line detail message to be logged
+ */
+ public void log(int evtClass, Properties props, int source, String msg) {
+ log(evtClass, props, source, ILogger.LL_INFO, msg, null);
+ }
+
+ //************** no param ****************
+
+ /**
+ * Logs an event to the log queue.
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param source the source of the log event
+ * @param level the level of the log event
+ * @param msg the one line detail message to be logged
+ */
+ public void log(int evtClass, int source, int level, String msg) {
+ log(evtClass, null, source, level, msg, null);
+ }
+
+ /**
+ * Logs an event to the log queue.
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param props the resource bundle used for the detailed message
+ * @param source the source of the log event
+ * @param level the level of the log event
+ * @param msg the one line detail message to be logged
+ */
+ public void log(int evtClass, Properties props, int source, int level, String msg) {
+ log(evtClass, props, source, level, msg, null);
+ }
+
+ //********************* one param **********************
+
+ /**
+ * Logs an event to the log queue.
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param props the resource bundle used for the detailed message
+ * @param source the source of the log event
+ * @param msg the one line detail message to be logged
+ * @param param the parameter in the detail message
+ */
+ public void log(int evtClass, int source, int level, String msg, Object param) {
+ log(evtClass, null, source, level, msg, param);
+ }
+
+ /**
+ * Logs an event using default log level: ILogger.LL_INFO
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param props the resource bundle used for the detailed message
+ * @param source the source of the log event
+ * @param msg the one line detail message to be logged
+ * @param param the parameter in the detail message
+ */
+ public void log(int evtClass, Properties props, int source, String msg, Object param) {
+ log(evtClass, props, source, ILogger.LL_INFO, msg, param);
+ }
+
+ /**
+ * Logs an event to the log queue.
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param props the resource bundle used for the detailed message
+ * @param source the source of the log event
+ * @param level the level of the log event
+ * @param msg the one line detail message to be logged
+ * @param param the parameter in the detail message
+ */
+ public void log(int evtClass, Properties props, int source, int level, String msg,
+ Object param) {
+ Object o[] = new Object[1];
+
+ o[0] = param;
+ log(evtClass, props, source, level, msg, o);
+ }
+
+ //******************* multiple param **************************
+
+ /**
+ * Logs an event to the log queue.
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param source the source of the log event
+ * @param level the level of the log event
+ * @param msg the one line detail message to be logged
+ * @param params the parameters in the detail message
+ */
+ public void log(int evtClass, int source, int level, String msg,
+ Object params[]) {
+ log(evtClass, null, source, level, msg, params);
+ }
+
+ //*************** the real implementation *****************
+ /**
+ * Logs an event to the log queue.
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param props the resource bundle used for the detailed message
+ * @param source the source of the log event
+ * @param level the level of the log event
+ * @param msg the one line detail message to be logged
+ * @param params the parameters in the detail message
+ */
+ public void log(int evtClass, Properties prop, int source, int level, String msg,
+ Object params[]) {
+ ILogEvent iLEvent = create(evtClass, prop, source, level, msg, params, ILogger.L_SINGLELINE);
+ if (iLEvent != null)
+ mLogQueue.log(iLEvent);
+ }
+
+ //******************** multiline log *************************
+ //************** default level ****************
+ /**
+ * Logs an event using default log level: ILogger.LL_INFO
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param source the source of the log event
+ * @param msg the one line detail message to be logged
+ * @param multiline true if the message has more than one line, otherwise false
+ */
+ public void log(int evtClass, int source, String msg, boolean multiline) {
+ log(evtClass, null, source, ILogger.LL_INFO, msg, null, multiline);
+ }
+
+ /**
+ * Logs an event using default log level: ILogger.LL_INFO
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param props the resource bundle used for the detailed message
+ * @param source the source of the log event
+ * @param msg the one line detail message to be logged
+ * @param multiline true if the message has more than one line, otherwise false
+ */
+ public void log(int evtClass, Properties props, int source, String msg, boolean multiline) {
+ log(evtClass, props, source, ILogger.LL_INFO, msg, null, multiline);
+ }
+
+ //************** no param ****************
+
+ /**
+ * Logs an event to the log queue.
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param source the source of the log event
+ * @param level the level of the log event
+ * @param msg the one line detail message to be logged
+ * @param multiline true if the message has more than one line, otherwise false
+ */
+ public void log(int evtClass, int source, int level, String msg, boolean multiline) {
+ log(evtClass, null, source, level, msg, null, multiline);
+ }
+
+ /**
+ * Logs an event to the log queue.
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param props the resource bundle used for the detailed message
+ * @param source the source of the log event
+ * @param level the level of the log event
+ * @param msg the one line detail message to be logged
+ * @param multiline true if the message has more than one line, otherwise false
+ */
+ public void log(int evtClass, Properties props, int source, int level, String msg, boolean multiline) {
+ log(evtClass, props, source, level, msg, null, multiline);
+ }
+
+ //********************* one param **********************
+
+ /**
+ * Logs an event to the log queue.
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param props the resource bundle used for the detailed message
+ * @param source the source of the log event
+ * @param msg the one line detail message to be logged
+ * @param param the parameter in the detail message
+ * @param multiline true if the message has more than one line, otherwise false
+ */
+ public void log(int evtClass, int source, int level, String msg, Object param, boolean multiline) {
+ log(evtClass, null, source, level, msg, param, multiline);
+ }
+
+ /**
+ * Logs an event using default log level: ILogger.LL_INFO
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param props the resource bundle used for the detailed message
+ * @param source the source of the log event
+ * @param msg the one line detail message to be logged
+ * @param param the parameter in the detail message
+ * @param multiline true if the message has more than one line, otherwise false
+ */
+ public void log(int evtClass, Properties props, int source, String msg, Object param, boolean multiline) {
+ log(evtClass, props, source, ILogger.LL_INFO, msg, param, multiline);
+ }
+
+ /**
+ * Logs an event to the log queue.
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param props the resource bundle used for the detailed message
+ * @param source the source of the log event
+ * @param level the level of the log event
+ * @param msg the one line detail message to be logged
+ * @param param the parameter in the detail message
+ * @param multiline true if the message has more than one line, otherwise false
+ */
+ public void log(int evtClass, Properties props, int source, int level, String msg,
+ Object param, boolean multiline) {
+ Object o[] = new Object[1];
+
+ o[0] = param;
+ log(evtClass, props, source, level, msg, o, multiline);
+ }
+
+ //******************* multiple param **************************
+
+ /**
+ * Logs an event to the log queue.
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param source the source of the log event
+ * @param level the level of the log event
+ * @param msg the one line detail message to be logged
+ * @param params the parameters in the detail message
+ * @param multiline true if the message has more than one line, otherwise false
+ */
+ public void log(int evtClass, int source, int level, String msg,
+ Object params[], boolean multiline) {
+ log(evtClass, null, source, level, msg, params, multiline);
+ }
+
+ //*************** the real implementation *****************
+ /**
+ * Logs an event to the log queue.
+ *
+ * @param evtClass What kind of event it is: EV_AUDIT or EV_SYSTEM.
+ * @param props the resource bundle used for the detailed message
+ * @param source the source of the log event
+ * @param level the level of the log event
+ * @param msg the one line detail message to be logged
+ * @param params the parameters in the detail message
+ * @param multiline true if the message has more than one line, otherwise false
+ */
+ public void log(int evtClass, Properties prop, int source, int level, String msg,
+ Object params[], boolean multiline) {
+ ILogEvent iLEvent = create(evtClass, prop, source, level, msg, params, multiline);
+ if (iLEvent != null)
+ mLogQueue.log(iLEvent);
+ }
+
+ //******************** end multiline log *************************
+
+ /**
+ * Creates generic log event. If required, we can recycle
+ * events here.
+ */
+ //XXXXXXXXXXX prop is out dated!!!! XXXXXXXXXXXXXXX
+ public ILogEvent create(int evtClass, Properties prop, int source, int level,
+ String msg, Object params[], boolean multiline) {
+ ILogEventFactory f = mFactories.get(evtClass);
+
+ if (f == null)
+ return null;
+ return f.create(evtClass, prop, source, level, multiline, msg, params);
+ }
+
+ /**
+ * Notifies logger to reuse the event. This framework
+ * opens up possibility to reuse event.
+ *
+ * @param event a log event
+ */
+ public void release(ILogEvent event) {
+ // do nothing for now.
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/logging/SignedAuditEventFactory.java b/base/server/cmscore/src/com/netscape/cmscore/logging/SignedAuditEventFactory.java
new file mode 100644
index 000000000..6ba492dc3
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/logging/SignedAuditEventFactory.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.logging;
+
+import java.util.Properties;
+
+import com.netscape.certsrv.logging.IBundleLogEvent;
+import com.netscape.certsrv.logging.ILogEvent;
+import com.netscape.certsrv.logging.ILogEventFactory;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.SignedAuditEvent;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * A log event object for handling system messages
+ * <P>
+ *
+ * @author mikep
+ * @author mzhao
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class SignedAuditEventFactory implements ILogEventFactory {
+
+ /**
+ * List of supported properties.
+ */
+ public static final String PROP_BUNDLE = "bundleName";
+
+ /**
+ * Constructs a system event factory.
+ */
+ public SignedAuditEventFactory() {
+ }
+
+ /**
+ * Creates an log event.
+ *
+ * @param evtClass the event type
+ * @param prop the resource bundle
+ * @param source the subsystem ID who creates the log event
+ * @param level the severity of the log event
+ * @param multiline the log message has more than one line or not
+ * @param msg the detail message of the log
+ * @param params the parameters in the detail log message
+ */
+ public ILogEvent create(int evtClass, Properties prop, int source,
+ int level, boolean multiline, String msg, Object params[]) {
+ if (evtClass != ILogger.EV_SIGNED_AUDIT)
+ return null;
+
+ String message = null;
+ // assume msg format <type=...>:message
+ String typeMessage = msg.trim();
+ String eventType = null;
+ int typeBegin = typeMessage.indexOf("<type=");
+
+ if (typeBegin != -1) {
+ // type is specified
+ int colon = typeMessage.indexOf(">:");
+
+ eventType = typeMessage.substring(typeBegin + 6, colon);
+ message = typeMessage.substring(colon + 2);
+ Debug.trace("SignedAuditEventFactory: create() message=" + message + "\n");
+
+ } else {
+ // no type specified
+ message = msg;
+ }
+
+ SignedAuditEvent event = new SignedAuditEvent(message.trim(), params);
+
+ if (eventType != null)
+ event.setEventType(eventType.trim());
+
+ event.setLevel(level);
+ event.setSource(source);
+ event.setMultiline(multiline);
+ setProperties(prop, event);
+
+ return event;
+ }
+
+ /**
+ * Set the resource bundle of the log event.
+ *
+ * @param prop the properties
+ * @param event the log event
+ */
+ protected void setProperties(Properties prop, IBundleLogEvent event) {
+ if (prop == null) {
+ event.setBundleName(null);
+ } else {
+ String bundleName = (String) prop.get(PROP_BUNDLE);
+
+ if (bundleName != null) {
+ event.setBundleName(bundleName);
+ }
+ }
+ }
+
+ /**
+ * Releases an log event.
+ *
+ * @param e the log event
+ */
+ public void release(ILogEvent e) {
+ // do nothing
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/logging/SignedAuditLogger.java b/base/server/cmscore/src/com/netscape/cmscore/logging/SignedAuditLogger.java
new file mode 100644
index 000000000..4b6fd55a2
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/logging/SignedAuditLogger.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.logging;
+
+/**
+ * A class represents certificate server logger
+ * implementation.
+ * <P>
+ *
+ * @author thomask
+ * @author mzhao
+ * @version $Revision$, $Date$
+ */
+public class SignedAuditLogger extends Logger {
+
+ /**
+ * Constructs a generic logger, and registers a list
+ * of resident event factories.
+ */
+ public SignedAuditLogger() {
+ super();
+ register(EV_SIGNED_AUDIT, new SignedAuditEventFactory());
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/logging/SystemEventFactory.java b/base/server/cmscore/src/com/netscape/cmscore/logging/SystemEventFactory.java
new file mode 100644
index 000000000..6821fac6f
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/logging/SystemEventFactory.java
@@ -0,0 +1,99 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.logging;
+
+import java.util.Properties;
+
+import com.netscape.certsrv.logging.IBundleLogEvent;
+import com.netscape.certsrv.logging.ILogEvent;
+import com.netscape.certsrv.logging.ILogEventFactory;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.SystemEvent;
+
+/**
+ * A log event object for handling system messages
+ * <P>
+ *
+ * @author mikep
+ * @author mzhao
+ * @version $Revision$, $Date$
+ */
+public class SystemEventFactory implements ILogEventFactory {
+
+ /**
+ * List of supported properties.
+ */
+ public static final String PROP_BUNDLE = "bundleName";
+
+ /**
+ * Constructs a system event factory.
+ */
+ public SystemEventFactory() {
+ }
+
+ /**
+ * Creates an log event.
+ *
+ * @param evtClass the event type
+ * @param prop the resource bundle
+ * @param source the subsystem ID who creates the log event
+ * @param level the severity of the log event
+ * @param multiline the log message has more than one line or not
+ * @param msg the detail message of the log
+ * @param params the parameters in the detail log message
+ */
+ public ILogEvent create(int evtClass, Properties prop, int source,
+ int level, boolean multiline, String msg, Object params[]) {
+ if (evtClass != ILogger.EV_SYSTEM)
+ return null;
+ SystemEvent event = new SystemEvent(msg, params);
+
+ event.setLevel(level);
+ event.setSource(source);
+ event.setMultiline(multiline);
+ setProperties(prop, event);
+ return event;
+ }
+
+ /**
+ * Set the resource bundle of the log event.
+ *
+ * @param prop the properties
+ * @param event the log event
+ */
+ protected void setProperties(Properties prop, IBundleLogEvent event) {
+ if (prop == null) {
+ event.setBundleName(null);
+ } else {
+ String bundleName = (String) prop.get(PROP_BUNDLE);
+
+ if (bundleName != null) {
+ event.setBundleName(bundleName);
+ }
+ }
+ }
+
+ /**
+ * Releases an log event.
+ *
+ * @param e the log event
+ */
+ public void release(ILogEvent e) {
+ // do nothing
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/notification/EmailFormProcessor.java b/base/server/cmscore/src/com/netscape/cmscore/notification/EmailFormProcessor.java
new file mode 100644
index 000000000..2625d8efa
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/notification/EmailFormProcessor.java
@@ -0,0 +1,249 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.notification;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.notification.IEmailFormProcessor;
+
+/**
+ * formulates the final email. Escape character '\' is understood.
+ * '$' is used preceeding a token name. A token name should not be a
+ * substring of any other token name
+ * <p>
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class EmailFormProcessor implements IEmailFormProcessor {
+
+ protected final static String TOK_PREFIX = "$";
+ protected final static String TOK_ESC = "\\";
+ protected final static char TOK_END = ' ';
+ protected final static String TOK_VALUE_UNKNOWN = "VALUE UNKNOWN";
+ protected final static String TOK_TOKEN_UNKNOWN = "UNKNOWN TOKEN:";
+ protected ILogger mLogger = CMS.getLogger();
+
+ // stores all the available token keys; added so that we can
+ // parse strings to replace unresolvable token keys and replace
+ // them by the words "VALUE UNKNOWN"
+ protected static String[] token_keys = {
+ TOKEN_ID,
+ TOKEN_SERIAL_NUM,
+ TOKEN_HTTP_HOST,
+ TOKEN_HTTP_PORT,
+ TOKEN_ISSUER_DN,
+ TOKEN_SUBJECT_DN,
+ TOKEN_REQUESTOR_EMAIL,
+ TOKEN_CERT_TYPE,
+ TOKEN_REQUEST_TYPE,
+ TOKEN_STATUS,
+ TOKEN_NOT_AFTER,
+ TOKEN_NOT_BEFORE,
+ TOKEN_SENDER_EMAIL,
+ TOKEN_RECIPIENT_EMAIL,
+ TOKEN_SUMMARY_ITEM_LIST,
+ TOKEN_SUMMARY_TOTAL_NUM,
+ TOKEN_SUMMARY_SUCCESS_NUM,
+ TOKEN_SUMMARY_FAILURE_NUM,
+ TOKEN_EXECUTION_TIME
+ };
+
+ // stores the eventual content of the email
+ Vector<String> mContent = new Vector<String>();
+ Hashtable<String, Object> mTok2vals = null;
+
+ public EmailFormProcessor() {
+ }
+
+ /*
+ * takes the form template, parse and replace all $tokens with the
+ * right values. It handles escape character '\'
+ * @param form The locale specific form template,
+ * @param tok2vals a hashtable containing one to one mapping
+ * from $tokens used by the admins in the form template to the real
+ * values corresponding to the $tokens
+ * @return mail content
+ */
+ public String getEmailContent(String form,
+ Hashtable<String, Object> tok2vals) {
+ mTok2vals = tok2vals;
+
+ if (form == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_NOTIFY_TEMPLATE_NULL"));
+ return null;
+ }
+
+ if (mTok2vals == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_NOTIFY_TOKEN_NULL"));
+ return null;
+ }
+
+ /**
+ * first, take care of the escape characters '\'
+ */
+ StringTokenizer es = new StringTokenizer(form, TOK_ESC);
+
+ if (es.hasMoreTokens() && !form.startsWith(TOK_ESC)) {
+ dollarProcess(es.nextToken());
+ }
+
+ // rest of them start with '\'
+ while (es.hasMoreTokens()) {
+ String t = es.nextToken();
+
+ // put first character (escaped char) in mContent
+ char c = t.charAt(0);
+
+ Character ch = Character.valueOf(c);
+
+ mContent.add(ch.toString());
+
+ // process the rest for $tokens
+ String r = t.substring(1);
+
+ dollarProcess(r);
+ }
+
+ return formContent(mContent);
+ }
+
+ private void dollarProcess(String sub) {
+ StringTokenizer st = new StringTokenizer(sub, TOK_PREFIX);
+
+ // if first token is not a $token, put in mContent as is
+ if (st.hasMoreTokens() && !sub.startsWith(TOK_PREFIX)) {
+ String a = st.nextToken();
+
+ mContent.add(a);
+ }
+
+ /*
+ * all of the string tokens below begin with a '$'
+ * match it one by one with the mTok2vals table
+ */
+ while (st.hasMoreTokens()) {
+ String t = st.nextToken();
+
+ /*
+ * We don't know when a token ends. Compare with every
+ * token in the table for the first match. Which means, a
+ * token name should not be a substring of any token name
+ */
+ boolean matched = false;
+ String tok = null;
+
+ for (Enumeration<String> e = mTok2vals.keys(); e.hasMoreElements();) {
+ // get key
+ tok = e.nextElement();
+
+ // compare key with $token
+ if (t.startsWith(tok)) {
+ // match, put val in mContent
+ Object o = mTok2vals.get(tok);
+
+ if (o != null) {
+ String s = (String) o;
+
+ if (!s.equals("")) {
+ mContent.add(s);
+ } else {
+ break;
+ }
+ } else { // no value, bail out
+ break;
+ }
+
+ // now, put the rest of the non-token string in mContent
+ if (t.length() != tok.length()) {
+ mContent.add(t.substring(tok.length()));
+ }
+
+ matched = true;
+
+ // replaced! bail out.
+ break;
+ }
+ }
+
+ if (!matched) {
+ boolean keyFound = false;
+
+ // no match, put the token back, as is
+ // -- for bug 382162, don't remove the following line, in
+ // case John changes his mind for the better
+ // mContent.add(TOK_PREFIX+t);
+
+ for (int i = 0; i < token_keys.length; i++) {
+ if (t.startsWith(token_keys[i])) {
+ // match, replace it with the TOK_VALUE_UNKNOWN
+ mContent.add(TOK_VALUE_UNKNOWN);
+
+ // now, put the rest of the non-token string
+ // in mContent
+ if (t.length() != token_keys[i].length()) {
+ mContent.add(t.substring(token_keys[i].length()));
+ }
+ keyFound = true;
+ break;
+ }
+ // keep looking
+ }
+ if (keyFound == false) {
+ mContent.add(TOK_TOKEN_UNKNOWN + TOK_PREFIX + t);
+ }
+ }
+ }
+ }
+
+ /**
+ * takes a vector of strings and concatenate them
+ */
+ public String formContent(Vector<String> vec) {
+ StringBuffer content = new StringBuffer();
+
+ Enumeration<String> e = vec.elements();
+
+ // initialize content with first element
+ if (e.hasMoreElements()) {
+ content.append(e.nextElement());
+ }
+
+ while (e.hasMoreElements()) {
+ String v = e.nextElement();
+ content.append(v);
+ }
+
+ return content.toString();
+ }
+
+ /**
+ * logs an entry in the log file.
+ */
+ public void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, "EmailFormProcessor: " + msg);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/notification/EmailResolverKeys.java b/base/server/cmscore/src/com/netscape/cmscore/notification/EmailResolverKeys.java
new file mode 100644
index 000000000..7012801c5
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/notification/EmailResolverKeys.java
@@ -0,0 +1,93 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.notification;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.notification.IEmailResolverKeys;
+
+/**
+ * Email resolver keys as input to email resolvers
+ * <P>
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class EmailResolverKeys implements IEmailResolverKeys {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -8823197350102151516L;
+ private Hashtable<String, Object> mKeys = null;
+
+ public EmailResolverKeys() {
+ mKeys = new Hashtable<String, Object>();
+ }
+
+ /**
+ * sets a key with key name and the key
+ *
+ * @param name key name
+ * @param key key
+ * @exception com.netscape.certsrv.base.EBaseException NullPointerException
+ */
+ public void set(String name, Object key) throws EBaseException {
+ try {
+ mKeys.put(name, key);
+ } catch (NullPointerException e) {
+ System.out.println(e.toString());
+ throw new EBaseException("EmailResolverKeys.set()");
+ }
+ }
+
+ /**
+ * returns the key to which the specified name is mapped in this
+ * key set
+ *
+ * @param name key name
+ * @return the named email resolver key
+ */
+ public Object get(String name) {
+ return mKeys.get(name);
+ }
+
+ /**
+ * removes the name and its corresponding key from this
+ * key set. This method does nothing if the named
+ * key is not in the key set.
+ *
+ * @param name key name
+ */
+ public void delete(String name) {
+ mKeys.remove(name);
+ }
+
+ /**
+ * returns an enumeration of the key names in this key
+ * set. Use the Enumeration methods on the returned object to
+ * fetch the elements sequentially.
+ *
+ * @return an enumeration of the values in this key set
+ * @see java.util.Enumeration
+ */
+ public Enumeration<String> getElements() {
+ return mKeys.keys();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/notification/EmailTemplate.java b/base/server/cmscore/src/com/netscape/cmscore/notification/EmailTemplate.java
new file mode 100644
index 000000000..86c232630
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/notification/EmailTemplate.java
@@ -0,0 +1,175 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.notification;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.notification.IEmailTemplate;
+
+/**
+ * Files to be processed and returned to the requested parties. It
+ * is a template with $tokens to be used by the form/template processor.
+ *
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+
+public class EmailTemplate implements IEmailTemplate {
+
+ /*==========================================================
+ * variables
+ *==========================================================*/
+
+ /* private variables */
+ private String mTemplateFile = "";
+ private ILogger mLogger = CMS.getLogger();
+
+ /* public vaiables */
+ public String mFileContents;
+
+ /*==========================================================
+ * constructors
+ *==========================================================*/
+
+ /**
+ * Default Constructor
+ *
+ * @param templateFile File name of the template including the full path and
+ * file extension
+ */
+
+ public EmailTemplate(String templatePath) {
+ mTemplateFile = templatePath;
+ }
+
+ /*==========================================================
+ * public methods
+ *==========================================================*/
+
+ /*
+ * Load the template from the file
+ *
+ * @return true if successful
+ */
+ public boolean init() {
+
+ File template = new File(mTemplateFile);
+
+ /* check if file exists and is accessible */
+ if ((!template.exists()) || (!template.canRead()) || (template.isDirectory())) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_NOTIFY_TEMPLATE_NOT_EXIST", mTemplateFile));
+ return false;
+ }
+
+ /* create input stream */
+ FileReader input;
+
+ try {
+ input = new FileReader(template);
+ } catch (FileNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_NOTIFY_TEMPLATE_NOT_FOUND", mTemplateFile));
+
+ return false;
+ }
+
+ /* load template */
+ mFileContents = loadFile(input);
+ if (mFileContents == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_NOTIFY_TEMPLATE_LOAD_ERROR"));
+ return false;
+ }
+
+ // close the stream
+ try {
+ input.close();
+ } catch (IOException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @return Template Name in string form
+ */
+ public String getTemplateName() {
+ return mTemplateFile;
+ }
+
+ /**
+ * @return true if template is an html file, false otherwise
+ */
+ public boolean isHTML() {
+ if (mTemplateFile.endsWith(".html") ||
+ mTemplateFile.endsWith(".HTML") ||
+ mTemplateFile.endsWith(".htm") ||
+ mTemplateFile.endsWith(".HTM"))
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * @return Content of the template
+ */
+ public String toString() {
+ return mFileContents;
+ }
+
+ /*==========================================================
+ * private methods
+ *==========================================================*/
+
+ /* load file into string */
+ private String loadFile(FileReader input) {
+
+ BufferedReader in = new BufferedReader(input);
+ StringBuffer buf = new StringBuffer();
+ String line;
+
+ try {
+ while ((line = in.readLine()) != null) {
+ buf.append(line);
+ buf.append("\n");
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_NOTIFY_TEMPLATE_LOADING"));
+ return null;
+ }
+
+ return buf.toString();
+ }
+
+ public int length() {
+ return (mFileContents == null) ? 0 : mFileContents.length();
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, msg);
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/notification/ReqCertEmailResolver.java b/base/server/cmscore/src/com/netscape/cmscore/notification/ReqCertEmailResolver.java
new file mode 100644
index 000000000..de34f7be0
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/notification/ReqCertEmailResolver.java
@@ -0,0 +1,155 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.notification;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+
+import netscape.security.x509.X500Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.notification.ENotificationException;
+import com.netscape.certsrv.notification.IEmailResolver;
+import com.netscape.certsrv.notification.IEmailResolverKeys;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * An email resolver that first checks the request email, if none,
+ * then follows by checking the subjectDN of the certificate
+ * <p>
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class ReqCertEmailResolver implements IEmailResolver {
+ private ILogger mLogger = CMS.getLogger();
+
+ public static final String KEY_REQUEST = "request";
+ public static final String KEY_CERT = "cert";
+
+ // required keys for this resolver to figure out the email address
+ // protected static String[] mRequiredKeys = {KEY_REQUEST, KEY_CERT};
+
+ public ReqCertEmailResolver() {
+ }
+
+ /**
+ * returns an email address by using the resolver keys. The
+ * return value can possibly be null
+ *
+ * @param keys list of keys used for resolving the email address
+ */
+ public String getEmail(IEmailResolverKeys keys)
+ throws EBaseException, ENotificationException {
+ IRequest req = (IRequest) keys.get(KEY_REQUEST);
+
+ String mEmail = null;
+
+ if (req != null) {
+ mEmail = req.getExtDataInString(IRequest.HTTP_PARAMS,
+ "csrRequestorEmail");
+ if (mEmail == null) {
+ String mail = req.getExtDataInString("requestor_email");
+ log(ILogger.LL_INFO, "REQUESTOR_EMAIL = " + mail);
+ if (mail != null && !mail.equals(""))
+ return mail;
+ } else {
+ if (!mEmail.equals(""))
+ return mEmail;
+ }
+ } else {
+ log(ILogger.LL_INFO, "request null in keys");
+ }
+
+ X509Certificate cert = (X509Certificate) keys.get(KEY_CERT);
+
+ X500Name subjectDN = null;
+
+ if (cert != null) {
+ subjectDN =
+ (X500Name) cert.getSubjectDN();
+
+ try {
+ mEmail = subjectDN.getEmail();
+ } catch (IOException e) {
+ System.out.println("X500Name getEmail failed");
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_EMAIL_RESOLVE_FAILED",
+ subjectDN.toString()));
+ }
+ } else {
+ log(ILogger.LL_INFO, "cert null in keys");
+ }
+
+ // log it
+ if (mEmail == null) {
+ if (cert != null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_NOTIFY_NO_EMAIL", subjectDN.toString()));
+ CMS.debug(
+ "no email resolved, throwing NotificationResources.EMAIL_RESOLVE_FAILED_1 for " +
+ subjectDN.toString());
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_EMAIL_RESOLVE_FAILED",
+ "subjectDN= " + subjectDN.toString()));
+ } else if (req != null) {
+ log(ILogger.LL_FAILURE,
+ "no email resolved for request id =" +
+ req.getRequestId().toString());
+ CMS.debug(
+ "no email resolved, throwing NotificationResources.EMAIL_RESOLVE_FAILED_1 for request id =" +
+ req.getRequestId().toString());
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_EMAIL_RESOLVE_FAILED",
+ "requestId= " + req.getRequestId().toString()));
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_NOTIFY_NO_EMAIL_REQUEST"));
+ CMS.debug(
+ "no email resolved, throwing NotificationResources.EMAIL_RESOLVE_FAILED_1. No request id or cert info found");
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_EMAIL_RESOLVE_FAILED",
+ ": No request id or cert info found"));
+ }
+ } else {
+ log(ILogger.LL_INFO, "email resolved: " + mEmail);
+ }
+
+ return mEmail;
+ }
+
+ /**
+ * Returns array of required keys for this email resolver
+ *
+ * @return Array of required keys.
+ */
+
+ /* public String[] getRequiredKeys() {
+ return mRequiredKeys;
+ }*/
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, "ReqCertEmailResolver: " + msg);
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/notification/ReqCertSANameEmailResolver.java b/base/server/cmscore/src/com/netscape/cmscore/notification/ReqCertSANameEmailResolver.java
new file mode 100644
index 000000000..f3d5e8252
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/notification/ReqCertSANameEmailResolver.java
@@ -0,0 +1,276 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.notification;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.GeneralNameInterface;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.SubjectAlternativeNameExtension;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.notification.ENotificationException;
+import com.netscape.certsrv.notification.IEmailResolver;
+import com.netscape.certsrv.notification.IEmailResolverKeys;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * An email resolver that first checks the request email, if none,
+ * then follows by checking the subjectDN of the certificate, if none,
+ * then follows by checking the subjectalternatename extension
+ * <p>
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class ReqCertSANameEmailResolver implements IEmailResolver {
+ private ILogger mLogger = CMS.getLogger();
+
+ public static final String KEY_REQUEST = IEmailResolverKeys.KEY_REQUEST;
+ public static final String KEY_CERT = IEmailResolverKeys.KEY_CERT;
+
+ // required keys for this resolver to figure out the email address
+ // protected static String[] mRequiredKeys = {KEY_REQUEST, KEY_CERT};
+
+ public ReqCertSANameEmailResolver() {
+ }
+
+ /**
+ * returns an email address by using the resolver keys. The
+ * return value can possibly be null
+ *
+ * @param keys list of keys used for resolving the email address
+ */
+ public String getEmail(IEmailResolverKeys keys)
+ throws EBaseException, ENotificationException {
+ IRequest req = (IRequest) keys.get(KEY_REQUEST);
+
+ String mEmail = null;
+
+ if (req != null) {
+ mEmail = req.getExtDataInString(IRequest.HTTP_PARAMS,
+ IRequest.REQUESTOR_EMAIL);
+ if (mEmail == null) {
+ String mail = req.getExtDataInString("requestor_email");
+ log(ILogger.LL_INFO, "REQUESTOR_EMAIL = " + mail);
+ if (mail != null && !mail.equals(""))
+ return mail;
+ } else {
+ if (!mEmail.equals("")) {
+ log(ILogger.LL_INFO, "REQUESTOR_EMAIL = " + mEmail);
+ return mEmail;
+ }
+ log(ILogger.LL_INFO, "REQUESTOR_EMAIL is null ");
+ }
+ } else {
+ log(ILogger.LL_INFO, "request null in keys");
+ }
+ Object request = keys.get(KEY_CERT);
+ X509Certificate cert = null;
+
+ if (request instanceof RevokedCertImpl) {
+ RevokedCertImpl revCert = (RevokedCertImpl) request;
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ ICertificateRepository certDB = ca.getCertificateRepository();
+
+ cert = certDB.getX509Certificate(revCert.getSerialNumber());
+ } else
+ cert = (X509Certificate) request;
+
+ X500Name subjectDN = null;
+
+ if (cert != null) {
+ subjectDN =
+ (X500Name) cert.getSubjectDN();
+
+ try {
+ mEmail = subjectDN.getEmail();
+ if (mEmail != null) {
+ if (!mEmail.equals("")) {
+ log(ILogger.LL_INFO, "cert subjectDN E=" +
+ mEmail);
+ }
+ } else {
+ log(ILogger.LL_INFO, "no E component in subjectDN ");
+ }
+ } catch (IOException e) {
+ System.out.println("X500Name getEmail failed");
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_EMAIL_RESOLVE_FAILED",
+ subjectDN.toString()));
+ }
+
+ // try subjectalternatename
+ if (mEmail == null) {
+ X509CertInfo certInfo = null;
+
+ CMS.debug("about to try subjectalternatename");
+ try {
+ certInfo = (X509CertInfo)
+ ((X509CertImpl) cert).get(
+ X509CertImpl.NAME + "." + X509CertImpl.INFO);
+ } catch (CertificateParsingException ex) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_NOTIFY_NO_CERTINFO"));
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_EMAIL_RESOLVE_FAILED",
+ "subjectDN= " + subjectDN.toString()));
+ }
+
+ CertificateExtensions exts;
+
+ try {
+ exts = (CertificateExtensions)
+ certInfo.get(CertificateExtensions.NAME);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_NOTIFY_GET_EXT", e.toString()));
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_EMAIL_RESOLVE_FAILED",
+ "subjectDN= " + subjectDN.toString()));
+
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_NOTIFY_GET_EXT", e.toString()));
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_EMAIL_RESOLVE_FAILED",
+ "subjectDN= " + subjectDN.toString()));
+ }
+
+ if (exts != null) {
+ SubjectAlternativeNameExtension ext;
+
+ try {
+ ext =
+ (SubjectAlternativeNameExtension)
+ exts.get(SubjectAlternativeNameExtension.NAME);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_NOTIFY_GET_EXT", e.toString()));
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_EMAIL_RESOLVE_FAILED",
+ "subjectDN= " + subjectDN.toString()));
+
+ }
+
+ try {
+ if (ext != null) {
+ GeneralNames gn =
+ (GeneralNames) ext.get(SubjectAlternativeNameExtension.SUBJECT_NAME);
+
+ Enumeration<GeneralNameInterface> e = gn.elements();
+
+ while (e.hasMoreElements()) {
+ GeneralNameInterface gni = e.nextElement();
+
+ if (gni.getType() == GeneralNameInterface.NAME_RFC822) {
+ CMS.debug("got an subjectalternatename email");
+
+ String nameString = gni.toString();
+
+ // "RFC822Name: " + name
+ mEmail =
+ nameString.substring(nameString.indexOf(' ') + 1);
+ log(ILogger.LL_INFO,
+ "subjectalternatename email used:" +
+ mEmail);
+
+ break;
+ } else {
+ CMS.debug("not an subjectalternatename email");
+ }
+ }
+ }
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_NOTIFY_SUBJECTALTNAME"));
+ }
+ }
+ }
+ } else {
+ log(ILogger.LL_INFO, "cert null in keys");
+ }
+
+ // log it
+ if (mEmail == null) {
+ if (cert != null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_NOTIFY_NO_EMAIL", subjectDN.toString()));
+ CMS.debug(
+ "no email resolved, throwing NotificationResources.EMAIL_RESOLVE_FAILED_1 for " +
+ subjectDN.toString());
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_EMAIL_RESOLVE_FAILED",
+ "subjectDN= " + subjectDN.toString()));
+ } else if (req != null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_NOTIFY_NO_EMAIL_ID",
+ req.getRequestId().toString()));
+ CMS.debug(
+ "no email resolved, throwing NotificationResources.EMAIL_RESOLVE_FAILED_1 for request id =" +
+ req.getRequestId().toString());
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_EMAIL_RESOLVE_FAILED",
+ "requestId= " + req.getRequestId().toString()));
+ } else {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_NOTIFY_NO_EMAIL_REQUEST"));
+ CMS.debug(
+ "no email resolved, throwing NotificationResources.EMAIL_RESOLVE_FAILED_1. No request id or cert info found");
+ throw new ENotificationException(
+ CMS.getUserMessage("CMS_NOTIFICATION_EMAIL_RESOLVE_FAILED",
+ ": No request id or cert info found"));
+ }
+ } else {
+ log(ILogger.LL_INFO, "email resolved: " + mEmail);
+ }
+
+ return mEmail;
+ }
+
+ /**
+ * Returns array of required keys for this email resolver
+ *
+ * @return Array of required keys.
+ */
+
+ /* public String[] getRequiredKeys() {
+ return mRequiredKeys;
+ }*/
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER,
+ level, "ReqCertSANameEmailResolver: " + msg);
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/policy/AndExpression.java b/base/server/cmscore/src/com/netscape/cmscore/policy/AndExpression.java
new file mode 100644
index 000000000..9a2274b11
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/policy/AndExpression.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.policy;
+
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IExpression;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class represents an expression of the form
+ * <var1 op val1 AND var2 op va2>.
+ *
+ * Expressions are used as predicates for policy selection.
+ *
+ * @deprecated
+ * @author kanda
+ * @version $Revision$, $Date$
+ */
+public class AndExpression implements IExpression {
+ private IExpression mExp1;
+ private IExpression mExp2;
+
+ public AndExpression(IExpression exp1, IExpression exp2) {
+ mExp1 = exp1;
+ mExp2 = exp2;
+ }
+
+ public boolean evaluate(IRequest req)
+ throws EPolicyException {
+ // If an expression is missing we assume applicability.
+ if (mExp1 == null && mExp2 == null)
+ return true;
+ else if (mExp1 != null && mExp2 != null)
+ return mExp1.evaluate(req) && mExp2.evaluate(req);
+ else if (mExp1 == null)
+ return mExp2.evaluate(req);
+ else
+ // (if mExp2 == null)
+ return mExp1.evaluate(req);
+ }
+
+ public String toString() {
+ return mExp1.toString() + " AND " + mExp2.toString();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/policy/GeneralNameUtil.java b/base/server/cmscore/src/com/netscape/cmscore/policy/GeneralNameUtil.java
new file mode 100644
index 000000000..8d8c05bc6
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/policy/GeneralNameUtil.java
@@ -0,0 +1,694 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.policy;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.security.util.DerValue;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.DNSName;
+import netscape.security.x509.EDIPartyName;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNameInterface;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.IPAddressName;
+import netscape.security.x509.InvalidIPAddressException;
+import netscape.security.x509.OIDName;
+import netscape.security.x509.RFC822Name;
+import netscape.security.x509.URIName;
+import netscape.security.x509.X500Name;
+
+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.certsrv.policy.IGeneralNameAsConstraintsConfig;
+import com.netscape.certsrv.policy.IGeneralNameConfig;
+import com.netscape.certsrv.policy.IGeneralNameUtil;
+import com.netscape.certsrv.policy.IGeneralNamesAsConstraintsConfig;
+import com.netscape.certsrv.policy.IGeneralNamesConfig;
+import com.netscape.certsrv.policy.ISubjAltNameConfig;
+import com.netscape.cmscore.util.Debug;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Class that can be used to form general names from configuration file.
+ * Used by policies and extension commands.
+ * @deprecated
+ */
+public class GeneralNameUtil implements IGeneralNameUtil {
+
+ private static final String DOT = ".";
+
+ /**
+ * GeneralName can be used in the context of Constraints. Examples
+ * are NameConstraints, CertificateScopeOfUse extensions. In such
+ * cases, IPAddress may contain netmask component.
+ */
+ static public GeneralName
+ form_GeneralNameAsConstraints(String generalNameChoice, String value)
+ throws EBaseException {
+ try {
+ if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_IPADDRESS)) {
+ StringTokenizer st = new StringTokenizer(value, ",");
+ String ip = st.nextToken();
+ String netmask = null;
+
+ if (st.hasMoreTokens()) {
+ netmask = st.nextToken();
+ }
+ return new GeneralName(new IPAddressName(ip, netmask));
+ } else {
+ return form_GeneralName(generalNameChoice, value);
+ }
+ } catch (InvalidIPAddressException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_IP_ADDR", value));
+ }
+ }
+
+ /**
+ * Form a General Name from a General Name choice and value.
+ * The General Name choice must be one of the General Name Choice Strings
+ * defined in this class.
+ *
+ * @param generalNameChoice General Name choice. Must be one of the General
+ * Name choices defined in this class.
+ * @param value String value of the general name to form.
+ */
+ static public GeneralName
+ form_GeneralName(String generalNameChoice, String value)
+ throws EBaseException {
+ GeneralNameInterface generalNameI = null;
+ DerValue derVal = null;
+ GeneralName generalName = null;
+
+ try {
+ if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_OTHERNAME)) {
+ byte[] val = Utils.base64decode(value);
+
+ derVal = new DerValue(new ByteArrayInputStream(val));
+ Debug.trace("otherName formed");
+ } else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_RFC822NAME)) {
+ generalNameI = new RFC822Name(value);
+ Debug.trace("rfc822Name formed ");
+ } else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_DNSNAME)) {
+ generalNameI = new DNSName(value);
+ Debug.trace("dnsName formed");
+ }/**
+ * not supported -- no sun class
+ * else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_X400ADDRESS)) {
+ * }
+ **/
+ else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_DIRECTORYNAME)) {
+ generalNameI = new X500Name(value);
+ Debug.trace("X500Name formed");
+ } else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_EDIPARTYNAME)) {
+ generalNameI = new EDIPartyName(value);
+ Debug.trace("ediPartyName formed");
+ } else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_URL)) {
+ generalNameI = new URIName(value);
+ Debug.trace("url formed");
+ } else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_IPADDRESS)) {
+ generalNameI = new IPAddressName(value);
+ Debug.trace("ipaddress formed");
+ } else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_REGISTEREDID)) {
+ ObjectIdentifier oid;
+
+ try {
+ oid = new ObjectIdentifier(value);
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_VALUE_FOR_TYPE",
+ generalNameChoice,
+ "value must be a valid OID in the form n.n.n.n"));
+ }
+ generalNameI = new OIDName(oid);
+ Debug.trace("oidname formed");
+ } else {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ new String[] {
+ PROP_GENNAME_CHOICE,
+ "value must be one of: " +
+ GENNAME_CHOICE_OTHERNAME + ", " +
+ GENNAME_CHOICE_RFC822NAME + ", " +
+ GENNAME_CHOICE_DNSNAME + ", " +
+
+ /* GENNAME_CHOICE_X400ADDRESS +", "+ */
+ GENNAME_CHOICE_DIRECTORYNAME + ", " +
+ GENNAME_CHOICE_EDIPARTYNAME + ", " +
+ GENNAME_CHOICE_URL + ", " +
+ GENNAME_CHOICE_IPADDRESS + ", or " +
+ GENNAME_CHOICE_REGISTEREDID + "."
+ }
+ ));
+ }
+ } catch (IOException e) {
+ Debug.printStackTrace(e);
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_VALUE_FOR_TYPE",
+ generalNameChoice, e.toString()));
+ } catch (InvalidIPAddressException e) {
+ Debug.printStackTrace(e);
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_IP_ADDR", value));
+ } catch (RuntimeException e) {
+ Debug.printStackTrace(e);
+ throw e;
+ }
+
+ try {
+ if (generalNameI != null)
+ generalName = new GeneralName(generalNameI);
+ else
+ generalName = new GeneralName(derVal);
+ Debug.trace("general name formed");
+ return generalName;
+ } catch (IOException e) {
+ Debug.printStackTrace(e);
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", "Could not form GeneralName. Error: " + e));
+ }
+ }
+
+ /**
+ * Checks if given string is a valid General Name choice and returns
+ * the actual string that can be passed into form_GeneralName().
+ *
+ * @param generalNameChoice a General Name choice string.
+ * @return one of General Name choices defined in this class that can be
+ * passed into form_GeneralName().
+ */
+ static public String check_GeneralNameChoice(String generalNameChoice)
+ throws EBaseException {
+ String theGeneralNameChoice = null;
+
+ if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_OTHERNAME))
+ theGeneralNameChoice = GENNAME_CHOICE_OTHERNAME;
+ else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_RFC822NAME))
+ theGeneralNameChoice = GENNAME_CHOICE_RFC822NAME;
+ else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_DNSNAME))
+ theGeneralNameChoice = GENNAME_CHOICE_DNSNAME;
+
+ /* X400Address not supported.
+ else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_X400ADDRESS))
+ theGeneralNameChoice = GENNAME_CHOICE_X400ADDRESS;
+ */
+ else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_DIRECTORYNAME))
+ theGeneralNameChoice = GENNAME_CHOICE_DIRECTORYNAME;
+ else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_EDIPARTYNAME))
+ theGeneralNameChoice = GENNAME_CHOICE_EDIPARTYNAME;
+ else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_URL))
+ theGeneralNameChoice = GENNAME_CHOICE_URL;
+ else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_IPADDRESS))
+ theGeneralNameChoice = GENNAME_CHOICE_IPADDRESS;
+ else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_REGISTEREDID))
+ theGeneralNameChoice = GENNAME_CHOICE_REGISTEREDID;
+ else {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ new String[] {
+ PROP_GENNAME_CHOICE + "=" + generalNameChoice,
+ "value must be one of: " +
+ GENNAME_CHOICE_OTHERNAME + ", " +
+ GENNAME_CHOICE_RFC822NAME + ", " +
+ GENNAME_CHOICE_DNSNAME + ", " +
+
+ /* GENNAME_CHOICE_X400ADDRESS +", "+ */
+ GENNAME_CHOICE_DIRECTORYNAME + ", " +
+ GENNAME_CHOICE_EDIPARTYNAME + ", " +
+ GENNAME_CHOICE_URL + ", " +
+ GENNAME_CHOICE_IPADDRESS + ", " +
+ GENNAME_CHOICE_REGISTEREDID + "."
+ }
+ ));
+ }
+ return theGeneralNameChoice;
+ }
+
+ static public class GeneralNamesConfig implements IGeneralNamesConfig {
+ public String mName = null; // substore name of config if any.
+ public GeneralNameConfig[] mGenNameConfigs = null;
+ public IConfigStore mConfig = null;
+ public boolean mIsValueConfigured = true;
+ public boolean mIsPolicyEnabled = true;
+ public int mDefNumGenNames = DEF_NUM_GENERALNAMES;
+ public GeneralNames mGeneralNames = null;
+
+ private String mNameDotGeneralName = mName + DOT + PROP_GENERALNAME;
+
+ public GeneralNamesConfig(
+ String name,
+ IConfigStore config,
+ boolean isValueConfigured,
+ boolean isPolicyEnabled)
+ throws EBaseException {
+ mIsValueConfigured = isValueConfigured;
+ mIsPolicyEnabled = isPolicyEnabled;
+ mName = name;
+ if (mName != null)
+ mNameDotGeneralName = mName + DOT + PROP_GENERALNAME;
+ else
+ mNameDotGeneralName = PROP_GENERALNAME;
+ mConfig = config;
+
+ int numGNs = mConfig.getInteger(PROP_NUM_GENERALNAMES);
+
+ if (numGNs < 0) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE",
+ new String[] {
+ PROP_NUM_GENERALNAMES + "=" + numGNs,
+ "value must be greater than or equal to 0." }
+ ));
+ }
+ mGenNameConfigs = new GeneralNameConfig[numGNs];
+ for (int i = 0; i < numGNs; i++) {
+ String storeName = mNameDotGeneralName + i;
+
+ mGenNameConfigs[i] =
+ newGeneralNameConfig(
+ storeName, mConfig.getSubStore(storeName),
+ mIsValueConfigured, mIsPolicyEnabled);
+ }
+
+ if (mIsValueConfigured && mIsPolicyEnabled) {
+ mGeneralNames = new GeneralNames();
+ for (int j = 0; j < numGNs; j++) {
+ mGeneralNames.addElement(mGenNameConfigs[j].mGeneralName);
+ }
+ }
+ }
+
+ public GeneralNames getGeneralNames() {
+ return mGeneralNames;
+ }
+
+ protected GeneralNameConfig newGeneralNameConfig(
+ String name, IConfigStore config,
+ boolean isValueConfigured, boolean isPolicyEnabled)
+ throws EBaseException {
+ return new GeneralNameConfig(
+ name, config, isValueConfigured, isPolicyEnabled);
+ }
+
+ public GeneralNameConfig[] getGenNameConfig() {
+ return mGenNameConfigs.clone();
+ }
+
+ public int getNumGeneralNames() {
+ return mGenNameConfigs.length;
+ }
+
+ public IConfigStore getConfig() {
+ return mConfig;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public boolean isValueConfigured() {
+ return mIsValueConfigured;
+ }
+
+ public void setDefNumGenNames(int defNum) {
+ mDefNumGenNames = defNum;
+ }
+
+ public int getDefNumGenNames() {
+ return mDefNumGenNames;
+ }
+
+ /**
+ * adds params to default
+ */
+ public static void getDefaultParams(
+ String name, boolean isValueConfigured, Vector<String> params) {
+ String nameDot = "";
+
+ if (name != null)
+ nameDot = name + DOT;
+ params.addElement(
+ nameDot + PROP_NUM_GENERALNAMES + '=' + DEF_NUM_GENERALNAMES);
+ for (int i = 0; i < DEF_NUM_GENERALNAMES; i++) {
+ GeneralNameConfig.getDefaultParams(
+ nameDot + PROP_GENERALNAME + i, isValueConfigured, params);
+ }
+ }
+
+ /**
+ * Get instance params.
+ */
+ public void getInstanceParams(Vector<String> params) {
+ params.addElement(
+ PROP_NUM_GENERALNAMES + '=' + mGenNameConfigs.length);
+ for (int i = 0; i < mGenNameConfigs.length; i++) {
+ mGenNameConfigs[i].getInstanceParams(params);
+ }
+ }
+
+ /**
+ * Get extended plugin info.
+ */
+ public static void getExtendedPluginInfo(
+ String name, boolean isValueConfigured, Vector<String> info) {
+ String nameDot = "";
+
+ if (name != null && name.length() > 0)
+ nameDot = name + ".";
+ info.addElement(PROP_NUM_GENERALNAMES + ";" + NUM_GENERALNAMES_INFO);
+ for (int i = 0; i < DEF_NUM_GENERALNAMES; i++) {
+ GeneralNameConfig.getExtendedPluginInfo(
+ nameDot + PROP_GENERALNAME + i, isValueConfigured, info);
+ }
+ }
+
+ }
+
+ static public class GeneralNamesAsConstraintsConfig extends GeneralNamesConfig implements
+ IGeneralNamesAsConstraintsConfig {
+ public GeneralNamesAsConstraintsConfig(
+ String name,
+ IConfigStore config,
+ boolean isValueConfigured,
+ boolean isPolicyEnabled)
+ throws EBaseException {
+ super(name, config, isValueConfigured, isPolicyEnabled);
+ }
+
+ protected GeneralNameConfig newGeneralNameConfig(
+ String name, IConfigStore config,
+ boolean isValueConfigured, boolean isPolicyEnabled)
+ throws EBaseException {
+ return new GeneralNameAsConstraintsConfig(name, config,
+ isValueConfigured, isPolicyEnabled);
+ }
+ }
+
+ /**
+ * convenience class for policies use.
+ */
+ static public class GeneralNameConfig implements IGeneralNameConfig {
+ public String mName = null;
+ public String mNameDot = null;
+ public IConfigStore mConfig = null;
+ public String mGenNameChoice = null;
+ public boolean mIsValueConfigured = true;
+ public String mValue = null; // used only if isValueConfigured
+ public GeneralName mGeneralName = null; // used only if isValueConfiged.
+ public boolean mIsPolicyEnabled = true;
+
+ public String mNameDotChoice = null;
+ public String mNameDotValue = null;
+
+ public GeneralNameConfig(
+ String name,
+ IConfigStore config,
+ boolean isValueConfigured,
+ boolean isPolicyEnabled)
+ throws EBaseException {
+ mIsValueConfigured = isValueConfigured;
+ mIsPolicyEnabled = isPolicyEnabled;
+ mName = name;
+ if (mName != null && mName.length() > 0) {
+ mNameDot = mName + DOT;
+ mNameDotChoice = mNameDot + PROP_GENNAME_CHOICE;
+ mNameDotValue = mNameDot + PROP_GENNAME_VALUE;
+ } else {
+ mNameDot = "";
+ mNameDotChoice = PROP_GENNAME_CHOICE;
+ mNameDotValue = PROP_GENNAME_VALUE;
+ }
+ mConfig = config;
+
+ // necessary to expand/shrink # general names from console.
+ if (mConfig.size() == 0) {
+ config.putString(mNameDotChoice, "");
+ if (mIsValueConfigured)
+ config.putString(mNameDotValue, "");
+ }
+
+ String choice = null;
+
+ if (mIsPolicyEnabled) {
+ choice = mConfig.getString(PROP_GENNAME_CHOICE);
+ mGenNameChoice = check_GeneralNameChoice(choice);
+ } else {
+ choice = mConfig.getString(PROP_GENNAME_CHOICE, "");
+ if (choice.length() > 0 && !choice.equals("null")) {
+ mGenNameChoice = check_GeneralNameChoice(choice);
+ }
+ }
+ if (mIsValueConfigured) {
+ if (mIsPolicyEnabled) {
+ mValue = mConfig.getString(PROP_GENNAME_VALUE);
+ mGeneralName = formGeneralName(mGenNameChoice, mValue);
+ } else {
+ mValue = mConfig.getString(PROP_GENNAME_VALUE, "");
+ if (mValue != null && mValue.length() > 0)
+ mGeneralName = formGeneralName(mGenNameChoice, mValue);
+ }
+ }
+ }
+
+ /**
+ * Form a general name from the value string.
+ */
+ public GeneralName formGeneralName(String value)
+ throws EBaseException {
+ return formGeneralName(mGenNameChoice, value);
+ }
+
+ public GeneralName formGeneralName(String choice, String value)
+ throws EBaseException {
+ return form_GeneralName(choice, value);
+ }
+
+ /**
+ * @return a vector of General names from a value that can be
+ * either a Vector of strings, string array or just a string.
+ * Returned Vector can be null if value is not of expected type.
+ */
+ public Vector<GeneralName> formGeneralNames(Object value)
+ throws EBaseException {
+ Vector<GeneralName> gns = new Vector<GeneralName>();
+ GeneralName gn = null;
+
+ if (value instanceof String) {
+ if (((String) (value = ((String) value).trim())).length() > 0) {
+ gn = formGeneralName(mGenNameChoice, (String) value);
+ gns.addElement(gn);
+ }
+ } else if (value instanceof String[]) {
+ String[] vals = (String[]) value;
+
+ for (int i = 0; i < vals.length; i++) {
+ String val = vals[i].trim();
+
+ if (val != null && val.length() > 0) {
+ gn = formGeneralName(mGenNameChoice, val);
+ gns.addElement(gn);
+ }
+ }
+ } else if (value instanceof Vector) {
+ Vector<?> vals = (Vector<?>) value;
+
+ for (Enumeration<?> n = vals.elements(); n.hasMoreElements();) {
+ Object val = n.nextElement();
+
+ if (val != null && (val instanceof String) &&
+ ((String) (val = ((String) val).trim())).length() > 0) {
+ gn = formGeneralName(mGenNameChoice, (String) val);
+ gns.addElement(gn);
+ }
+ }
+ }
+ return gns;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public IConfigStore getConfig() {
+ return mConfig;
+ }
+
+ public String getGenNameChoice() {
+ return mGenNameChoice;
+ }
+
+ public String getValue() {
+ return mValue;
+ }
+
+ /*
+ public GeneralNameInterface getGeneralName() {
+ return mGeneralName;
+ }
+
+ */
+ public boolean isValueConfigured() {
+ return mIsValueConfigured;
+ }
+
+ /**
+ * Get default params
+ */
+
+ public static void getDefaultParams(
+ String name, boolean isValueConfigured, Vector<String> params) {
+ String nameDot = "";
+
+ if (name != null)
+ nameDot = name + ".";
+ Debug.trace("GeneralnameConfig getDefaultParams");
+ params.addElement(nameDot + PROP_GENNAME_CHOICE + "=");
+ if (isValueConfigured)
+ params.addElement(nameDot + PROP_GENNAME_VALUE + "=");
+ }
+
+ /**
+ * Get instance params
+ */
+ public void getInstanceParams(Vector<String> params) {
+ String value = (mValue == null) ? "" : mValue;
+ String choice = (mGenNameChoice == null) ? "" : mGenNameChoice;
+
+ params.addElement(mNameDotChoice + "=" + choice);
+ if (mIsValueConfigured)
+ params.addElement(mNameDotValue + "=" + value);
+ }
+
+ /**
+ * Get extended plugin info
+ */
+ public static void getExtendedPluginInfo(
+ String name, boolean isValueConfigured, Vector<String> info) {
+ String nameDot = "";
+
+ if (name != null && name.length() > 0)
+ nameDot = name + ".";
+ info.addElement(
+ nameDot + PROP_GENNAME_CHOICE + ";" + GENNAME_CHOICE_INFO);
+ if (isValueConfigured)
+ info.addElement(
+ nameDot + PROP_GENNAME_VALUE + ";" + GENNAME_VALUE_INFO);
+ }
+ }
+
+ /**
+ * convenience class for policies use.
+ */
+ static public class GeneralNameAsConstraintsConfig extends GeneralNameConfig implements
+ IGeneralNameAsConstraintsConfig {
+
+ public GeneralNameAsConstraintsConfig(
+ String name,
+ IConfigStore config,
+ boolean isValueConfigured,
+ boolean isPolicyEnabled)
+ throws EBaseException {
+ super(name, config, isValueConfigured, isPolicyEnabled);
+ }
+
+ public GeneralName getGeneralName() {
+ return mGeneralName;
+ }
+
+ /**
+ * Form a general name from the value string.
+ */
+ public GeneralName formGeneralName(String choice, String value)
+ throws EBaseException {
+ return form_GeneralNameAsConstraints(choice, value);
+ }
+ }
+
+ public static class SubjAltNameGN extends GeneralNameUtil.GeneralNameConfig implements ISubjAltNameConfig {
+ static final String REQUEST_ATTR_INFO =
+ "string;Request attribute name. " +
+ "The value of the request attribute will be used to form a " +
+ "General Name in the Subject Alternative Name extension.";
+
+ static final String PROP_REQUEST_ATTR = "requestAttr";
+
+ String mRequestAttr = null;
+ String mPfx = null;
+ String mAttr = null;
+
+ public SubjAltNameGN(
+ String name, IConfigStore config, boolean isPolicyEnabled)
+ throws EBaseException {
+ super(name, config, false, isPolicyEnabled);
+
+ mRequestAttr = mConfig.getString(PROP_REQUEST_ATTR, null);
+ if (mRequestAttr == null) {
+ mConfig.putString(mNameDot + PROP_REQUEST_ATTR, "");
+ mRequestAttr = "";
+ }
+ if (isPolicyEnabled && mRequestAttr.length() == 0) {
+ throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED",
+ mConfig.getName() + "." + PROP_REQUEST_ATTR));
+ }
+ int x = mRequestAttr.indexOf('.');
+
+ if (x == -1)
+ mAttr = mRequestAttr;
+ else {
+ mPfx = mRequestAttr.substring(0, x).trim();
+ mAttr = mRequestAttr.substring(x + 1).trim();
+ }
+ }
+
+ public String getPfx() {
+ return mPfx;
+ }
+
+ public String getAttr() {
+ return mAttr;
+ }
+
+ public void getInstanceParams(Vector<String> params) {
+ params.addElement(mNameDot + PROP_REQUEST_ATTR + "=" + mRequestAttr);
+ super.getInstanceParams(params);
+ }
+
+ public static void getDefaultParams(String name, Vector<String> params) {
+ String nameDot = "";
+
+ if (name != null && name.length() > 0)
+ nameDot = name + ".";
+ params.addElement(nameDot + PROP_REQUEST_ATTR + "=");
+ GeneralNameUtil.GeneralNameConfig.getDefaultParams(name, false, params);
+ }
+
+ public static void getExtendedPluginInfo(String name, Vector<String> params) {
+ String nameDot = "";
+
+ if (name != null && name.length() > 0)
+ nameDot = name + ".";
+ params.addElement(nameDot + PROP_REQUEST_ATTR + ";" + REQUEST_ATTR_INFO);
+ GeneralNameUtil.GeneralNameConfig.getExtendedPluginInfo(name, false, params);
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java b/base/server/cmscore/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java
new file mode 100644
index 000000000..7b3eac274
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java
@@ -0,0 +1,1532 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.policy;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+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.common.Constants;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IEnrollmentPolicy;
+import com.netscape.certsrv.policy.IExpression;
+import com.netscape.certsrv.policy.IKeyArchivalPolicy;
+import com.netscape.certsrv.policy.IKeyRecoveryPolicy;
+import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.policy.IPolicyRule;
+import com.netscape.certsrv.policy.IPolicySet;
+import com.netscape.certsrv.policy.IRenewalPolicy;
+import com.netscape.certsrv.policy.IRevocationPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cmscore.base.PropConfigStore;
+import com.netscape.cmscore.base.SubsystemRegistry;
+import com.netscape.cmscore.request.ARequestQueue;
+import com.netscape.cmscore.util.AssertionException;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * This is a Generic policy processor. The three main functions of
+ * this class are:
+ * 1. To initialize policies by reading policy configuration from the
+ * config file, and maintain 5 sets of policies - viz Enrollment,
+ * Renewal, Revocation and KeyRecovery and KeyArchival.
+ * 2. To apply the configured policies on the given request.
+ * 3. To enable policy listing/configuration via MCC console.
+ *
+ * Since the policy processor also implements the IPolicy interface
+ * the processor itself presents itself as one big policy to the
+ * request processor.
+ *
+ * @deprecated
+ * @author kanda
+ * @version $Revision$, $Date$
+ */
+public class GenericPolicyProcessor implements IPolicyProcessor {
+ protected IConfigStore mConfig = null;
+ protected IConfigStore mGlobalStore = null;
+ protected IAuthority mAuthority = null;
+
+ // Default System Policies
+ public final static String[] DEF_POLICIES =
+ { "com.netscape.cms.policy.constraints.ManualAuthentication" };
+
+ // Policies that can't be deleted nor disabled.
+ public final static Hashtable<String, IExpression> DEF_UNDELETABLE_POLICIES =
+ new Hashtable<String, IExpression>();
+
+ private String mId = "Policy";
+ private Vector<String> mPolicyOrder = new Vector<String>();
+ private Hashtable<String, RegisteredPolicy> mImplTable = new Hashtable<String, RegisteredPolicy>();
+ private Hashtable<String, PolicyInstance> mInstanceTable = new Hashtable<String, PolicyInstance>();
+ PolicySet mEnrollmentRules = new PolicySet("EnrollmentRules");
+ PolicySet mRenewalRules = new PolicySet("RenewalRules");
+ PolicySet mRevocationRules = new PolicySet("RevocationRules");
+ PolicySet mKeyRecoveryRules = new PolicySet("KeyRecoveryRules");
+ PolicySet mKeyArchivalRules = new PolicySet("KeyArchivalRules");
+ private String[] mSystemDefaults = null;
+ private boolean mInitSystemPolicies;
+
+ // A Table of persistent policies and their predicates.
+ // The predicates cannot be changed during configuration.
+ private Hashtable<String, IExpression> mUndeletablePolicies = null;
+
+ public GenericPolicyProcessor() {
+ mInitSystemPolicies = true; // CA & RA
+ }
+
+ public GenericPolicyProcessor(boolean initSystemPolicies) {
+ mInitSystemPolicies = initSystemPolicies; // KRA
+ }
+
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Shuts down this subsystem.
+ * <P>
+ */
+ public void shutdown() {
+ }
+
+ public ISubsystem getAuthority() {
+ return mAuthority;
+ }
+
+ /**
+ * Returns the configuration store.
+ * <P>
+ *
+ * @return configuration store
+ */
+ public synchronized IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Initializes the PolicyProcessor
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration of this subsystem
+ * @exception EBaseException failed to initialize this Subsystem.
+ */
+ public synchronized void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ // Debug.trace("GenericPolicyProcessor::init");
+ CMS.debug("GenericPolicyProcessor::init begins");
+ mAuthority = (IAuthority) owner;
+ mConfig = config;
+ mGlobalStore =
+ SubsystemRegistry.getInstance().get("MAIN").getConfigStore();
+
+ try {
+ IConfigStore configStore = CMS.getConfigStore();
+ String PKI_Subsystem = configStore.getString("subsystem.0.id",
+ null);
+
+ // CMS 6.1 began utilizing the "Certificate Profiles" framework
+ // instead of the legacy "Certificate Policies" framework.
+ //
+ // Beginning with CS 8.1, to meet the Common Criteria evaluation
+ // performed on this version of the product, it was determined
+ // that this legacy "Certificate Policies" framework would be
+ // deprecated and disabled by default (see Bugzilla Bug #472597).
+ //
+ // NOTE: The "Certificate Policies" framework ONLY applied to
+ // to CA, KRA, and legacy RA (pre-CMS 7.0) subsystems.
+ //
+ if (PKI_Subsystem.trim().equalsIgnoreCase("ca") ||
+ PKI_Subsystem.trim().equalsIgnoreCase("kra")) {
+ String policyStatus = PKI_Subsystem.trim().toLowerCase()
+ + "." + "Policy"
+ + "." + IPolicyProcessor.PROP_ENABLE;
+
+ if (configStore.getBoolean(policyStatus, true) == true) {
+ // NOTE: If "<subsystem>.Policy.enable=<boolean>" is
+ // missing, then the referenced instance existed
+ // prior to this name=value pair existing in its
+ // 'CS.cfg' file, and thus we err on the
+ // side that the user may still need to
+ // use the policy framework.
+ CMS.debug("GenericPolicyProcessor::init Certificate "
+ + "Policy Framework (deprecated) "
+ + "is ENABLED");
+ } else {
+ // CS 8.1 Default: <subsystem>.Policy.enable=false
+ CMS.debug("GenericPolicyProcessor::init Certificate "
+ + "Policy Framework (deprecated) "
+ + "is DISABLED");
+ return;
+ }
+ }
+ } catch (EBaseException e) {
+ throw e;
+ }
+
+ // Initialize default policies system that would be
+ // present in the system always.
+ if (mInitSystemPolicies) {
+ initSystemPolicies(mConfig);
+ }
+
+ // Read listing of undeletable policies if any.
+ initUndeletablePolicies(mConfig);
+
+ // Read all registered policies first..
+ IConfigStore c;
+
+ c = config.getSubStore(PROP_IMPL);
+ Enumeration<String> mImpls = c.getSubStoreNames();
+
+ while (mImpls.hasMoreElements()) {
+ String id = mImpls.nextElement();
+
+ // The implementation id should be unique
+ if (mImplTable.containsKey(id))
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_DUPLICATE_IMPL_ID", id));
+
+ String clPath = c.getString(id + "." + PROP_CLASS);
+
+ // We should n't let the CatchAll policies to be configurable.
+ if (isSystemDefaultPolicy(clPath))
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_SYSTEM_POLICY_CONFIG_ERROR", clPath));
+
+ // Verify if the class is a valid implementation of
+ // IPolicyRule
+ try {
+ Object o = Class.forName(clPath).newInstance();
+
+ if (!(o instanceof IEnrollmentPolicy) &&
+ !(o instanceof IRenewalPolicy) &&
+ !(o instanceof IRevocationPolicy) &&
+ !(o instanceof IKeyRecoveryPolicy) &&
+ !(o instanceof IKeyArchivalPolicy))
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_IMPL", clPath));
+ } catch (EBaseException e) {
+ throw e;
+ } catch (Exception e) {
+ Debug.printStackTrace(e);
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_NO_POLICY_IMPL",
+ id));
+ }
+
+ // Register the implementation.
+ RegisteredPolicy regPolicy =
+ new RegisteredPolicy(id, clPath);
+
+ mImplTable.put(id, regPolicy);
+ }
+
+ // Now read the priority ordering of rule configurations.
+ String policyOrder = config.getString(PROP_ORDER, null);
+
+ if (policyOrder == null) {
+ return;
+ // throw new EPolicyException(PolicyResources.NO_POLICY_ORDERING);
+ } else {
+ StringTokenizer tokens = new StringTokenizer(policyOrder, ",");
+
+ while (tokens.hasMoreTokens()) {
+ mPolicyOrder.addElement(tokens.nextToken().trim());
+ }
+ }
+
+ // Now Read Policy configurations and construct policy objects
+ int numPolicies = mPolicyOrder.size();
+ IConfigStore ruleStore = config.getSubStore(PROP_RULE);
+
+ for (int i = 0; i < numPolicies; i++) {
+ String instanceName = mPolicyOrder.elementAt(i);
+
+ // The instance id should be unique
+ if (mInstanceTable.containsKey(instanceName))
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_DUPLICATE_INST_ID", instanceName));
+
+ c = ruleStore.getSubStore(instanceName);
+ if (c == null || c.size() == 0)
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_NO_POLICY_CONFIG",
+ instanceName));
+ IPolicyRule rule = null;
+ String implName;
+ boolean enabled;
+ IExpression filterExp;
+
+ // If the policy rule is not enabled, skip it.
+ String enabledStr = c.getString(PROP_ENABLE, null);
+
+ if (enabledStr == null || enabledStr.trim().length() == 0 ||
+ enabledStr.trim().equalsIgnoreCase("true"))
+ enabled = true;
+ else
+ enabled = false;
+
+ implName = c.getString(PROP_IMPL_NAME, null);
+ if (implName == null) {
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_NO_POLICY_CONFIG",
+ instanceName));
+ }
+
+ // Make an instance of the specified policy.
+ RegisteredPolicy regPolicy = mImplTable.get(implName);
+
+ if (regPolicy == null) {
+ String[] params = { implName, instanceName };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_IMPL_NOT_FOUND", params));
+ }
+
+ String classpath = regPolicy.getClassPath();
+
+ try {
+ rule = (IPolicyRule)
+ Class.forName(classpath).newInstance();
+ rule.setInstanceName(instanceName);
+ rule.init(this, c);
+ } catch (Throwable e) {
+ mAuthority.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_POLICY_INIT_FAILED", instanceName, e.toString()));
+ // disable rule initialized if there is
+ // configuration error
+ enabled = false;
+ c.putString(PROP_ENABLE, "false");
+ }
+
+ if (rule == null)
+ continue;
+
+ // Read the predicate expression if any associated
+ // with the rule
+ String exp = c.getString(GenericPolicyProcessor.PROP_PREDICATE, null);
+
+ if (exp != null)
+ exp = exp.trim();
+ if (exp != null && exp.length() > 0) {
+ filterExp = PolicyPredicateParser.parse(exp);
+ rule.setPredicate(filterExp);
+ }
+
+ // Add the rule to the instance table
+ mInstanceTable.put(instanceName,
+ new PolicyInstance(instanceName, implName, rule, enabled));
+
+ if (!enabled)
+ continue;
+
+ // Add the rule to the policy set according to category if a
+ // rule is enabled.
+ addRule(instanceName, rule);
+ }
+
+ // Verify that the default policies are present and enabled.
+ verifyDefaultPolicyConfig();
+
+ // printPolicies();
+ }
+
+ public boolean isProfileRequest(IRequest request) {
+ String profileId = request.getExtDataInString("profileId");
+
+ if (profileId == null || profileId.equals(""))
+ return false;
+ else
+ return true;
+ }
+
+ /**
+ * Apply policies on the given request.
+ *
+ * @param IRequest The given request
+ * @return The policy result object.
+ */
+ public PolicyResult apply(IRequest req) {
+ IPolicySet rules = null;
+ String op = req.getRequestType();
+
+ CMS.debug("GenericPolicyProcessor: apply begins");
+ if (op == null) {
+ CMS.debug("GenericPolicyProcessor: apply op null");
+ // throw new AssertionException("Missing operation type in request. Can't happen!");
+ // Return ACCEPTED for now. Looks like even get CA chain
+ // is being passed in here with request type set elsewhere
+ // on the request.
+ return PolicyResult.ACCEPTED;
+ }
+ if (isProfileRequest(req)) {
+ Debug.trace("GenericPolicyProcessor: Profile-base Request " +
+ req.getRequestId().toString());
+ return PolicyResult.ACCEPTED;
+ }
+ CMS.debug("GenericPolicyProcessor: apply not ProfileRequest. op=" + op);
+
+ if (op.equalsIgnoreCase(IRequest.ENROLLMENT_REQUEST))
+ rules = mEnrollmentRules;
+ else if (op.equalsIgnoreCase(IRequest.RENEWAL_REQUEST))
+ rules = mRenewalRules;
+ else if (op.equalsIgnoreCase(IRequest.REVOCATION_REQUEST))
+ rules = mRevocationRules;
+ else if (op.equalsIgnoreCase(IRequest.KEY_RECOVERY_REQUEST))
+ rules = mKeyRecoveryRules;
+ else if (op.equalsIgnoreCase(IRequest.KEY_ARCHIVAL_REQUEST))
+ rules = mKeyArchivalRules;
+ else {
+ // It aint' a CMP request. We don't care.
+ return PolicyResult.ACCEPTED;
+ // throw new AssertionException("Invalid request type. Can't Happen!");
+ }
+
+ // ((PolicySet)rules).printPolicies();
+ // If there are no rules, then it is a serious error.
+ if (rules.count() == 0) {
+ CMS.debug("GenericPolicyProcessor: apply: rule count 0");
+ // if no policy is specified, just accept the request.
+ // KRA has no policy configured by default
+ return PolicyResult.ACCEPTED;
+
+ /**
+ * setError(req, PolicyResources.NO_RULES_CONFIGURED, op);
+ * return PolicyResult.REJECTED;
+ **/
+ }
+ CMS.debug("GenericPolicyProcessor: apply: rules.count=" + rules.count());
+
+ // request must be up to date or can't process it.
+ PolicyResult res = PolicyResult.ACCEPTED;
+ String mVersion = ARequestQueue.REQUEST_VERSION;
+ String vers = req.getRequestVersion();
+
+ if (vers == null || !vers.equals(mVersion)) {
+ if (vers == null || vers.length() == 0)
+ vers = "none";
+ res = PolicyResult.REJECTED;
+ }
+
+ if (res == PolicyResult.REJECTED)
+ return res;
+
+ CMS.debug("GenericPolicyProcessor: apply: calling rules.apply()");
+ // Apply the policy rules.
+ return rules.apply(req);
+ }
+
+ public void printPolicies() {
+ mEnrollmentRules.printPolicies();
+ mRenewalRules.printPolicies();
+ mRevocationRules.printPolicies();
+ mKeyRecoveryRules.printPolicies();
+ mKeyArchivalRules.printPolicies();
+ }
+
+ public String getPolicySubstoreId() {
+ return mAuthority.getId() + ".Policy";
+ }
+
+ public Enumeration<IPolicyRule> getPolicyImpls() {
+ Vector<IPolicyRule> impls = new Vector<IPolicyRule>();
+ Enumeration<RegisteredPolicy> enum1 = mImplTable.elements();
+ Enumeration<IPolicyRule> ret = null;
+
+ try {
+ while (enum1.hasMoreElements()) {
+ RegisteredPolicy regPolicy = enum1.nextElement();
+
+ // Make an Instance of it
+ IPolicyRule ruleImpl = (IPolicyRule)
+ Class.forName(regPolicy.getClassPath()).newInstance();
+
+ impls.addElement(ruleImpl);
+ }
+ ret = impls.elements();
+ } catch (Exception e) {
+ Debug.printStackTrace(e);
+ }
+ return ret;
+ }
+
+ public Enumeration<String> getPolicyImplsInfo() {
+ Vector<String> impls = new Vector<String>();
+ Enumeration<RegisteredPolicy> enum1 = mImplTable.elements();
+ Enumeration<String> ret = null;
+
+ try {
+ while (enum1.hasMoreElements()) {
+ RegisteredPolicy regPolicy = enum1.nextElement();
+ impls.addElement(regPolicy.getId());
+ }
+ ret = impls.elements();
+ } catch (Exception e) {
+ Debug.printStackTrace(e);
+ }
+ return ret;
+ }
+
+ public IPolicyRule getPolicyImpl(String id) {
+ RegisteredPolicy regImpl = mImplTable.get(id);
+
+ if (regImpl == null)
+ return null;
+ IPolicyRule impl = null;
+
+ try {
+ impl =
+ (IPolicyRule) Class.forName(regImpl.getClassPath()).newInstance();
+ } catch (Exception e) {
+ Debug.printStackTrace(e);
+ }
+ return impl;
+ }
+
+ public Vector<String> getPolicyImplConfig(String id) {
+ IPolicyRule rp = getPolicyImpl(id);
+
+ if (rp == null)
+ return null;
+ Vector<String> v = rp.getDefaultParams();
+
+ if (v == null)
+ v = new Vector<String>();
+ v.insertElementAt(IPolicyRule.PROP_ENABLE + "=" + "true", 0);
+ v.insertElementAt(IPolicyRule.PROP_PREDICATE + "=" + " ", 1);
+ return v;
+ }
+
+ public void deletePolicyImpl(String id)
+ throws EBaseException {
+ // First check if the id is valid;
+ RegisteredPolicy regPolicy = mImplTable.get(id);
+
+ if (regPolicy == null)
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_NO_POLICY_IMPL", id));
+
+ // If any instance exists for this impl, can't delete it.
+ boolean instanceExist = false;
+ Enumeration<PolicyInstance> e = mInstanceTable.elements();
+
+ for (; e.hasMoreElements();) {
+ PolicyInstance inst = e.nextElement();
+
+ if (inst.isInstanceOf(id)) {
+ instanceExist = true;
+ break;
+ }
+ }
+ if (instanceExist) // we found an instance
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_ACTIVE_POLICY_RULES_EXIST", id));
+
+ // Else delete the implementation
+ mImplTable.remove(id);
+ IConfigStore policyStore =
+ mGlobalStore.getSubStore(getPolicySubstoreId());
+ IConfigStore implStore =
+ policyStore.getSubStore(PROP_IMPL);
+
+ implStore.removeSubStore(id);
+
+ // committing
+ try {
+ mGlobalStore.commit(true);
+ } catch (Exception ex) {
+ Debug.printStackTrace(ex);
+ String[] params = { "implementation", id };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_DELETING_POLICY_ERROR", params));
+ }
+ }
+
+ public void addPolicyImpl(String id, String classPath)
+ throws EBaseException {
+ // See if the id is unique
+ if (mImplTable.containsKey(id))
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_DUPLICATE_IMPL_ID", id));
+
+ // See if the classPath is ok
+ Object impl = null;
+
+ try {
+ impl = Class.forName(classPath).newInstance();
+ } catch (Exception e) {
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_NO_POLICY_IMPL",
+ id));
+ }
+
+ // Does the class implement one of the four interfaces?
+ if (!(impl instanceof IEnrollmentPolicy) &&
+ !(impl instanceof IRenewalPolicy) &&
+ !(impl instanceof IRevocationPolicy) &&
+ !(impl instanceof IKeyRecoveryPolicy) &&
+ !(impl instanceof IKeyArchivalPolicy))
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_IMPL", classPath));
+
+ // Add the implementation to the registry
+ RegisteredPolicy regPolicy =
+ new RegisteredPolicy(id, classPath);
+
+ mImplTable.put(id, regPolicy);
+
+ // Store the impl in the configuration.
+ IConfigStore policyStore =
+ mGlobalStore.getSubStore(getPolicySubstoreId());
+ IConfigStore implStore =
+ policyStore.getSubStore(PROP_IMPL);
+ IConfigStore newStore = implStore.makeSubStore(id);
+
+ newStore.put(PROP_CLASS, classPath);
+ try {
+ mGlobalStore.commit(true);
+ } catch (Exception e) {
+ String[] params = { "implementation", id };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_ADDING_POLICY_ERROR", params));
+ }
+ }
+
+ public Enumeration<IPolicyRule> getPolicyInstances() {
+ Vector<IPolicyRule> rules = new Vector<IPolicyRule>();
+ Enumeration<String> enum1 = mPolicyOrder.elements();
+ Enumeration<IPolicyRule> ret = null;
+
+ try {
+ while (enum1.hasMoreElements()) {
+ PolicyInstance instance = mInstanceTable.get(enum1.nextElement());
+
+ rules.addElement(instance.getRule());
+
+ }
+ ret = rules.elements();
+ } catch (Exception e) {
+ Debug.printStackTrace(e);
+ }
+ return ret;
+ }
+
+ public Enumeration<String> getPolicyInstancesInfo() {
+ Vector<String> rules = new Vector<String>();
+ Enumeration<String> enum1 = mPolicyOrder.elements();
+ Enumeration<String> ret = null;
+
+ try {
+ while (enum1.hasMoreElements()) {
+ String ruleName = enum1.nextElement();
+ PolicyInstance instance = mInstanceTable.get(ruleName);
+ rules.addElement(instance.getRuleInfo());
+ }
+ ret = rules.elements();
+ } catch (Exception e) {
+ Debug.printStackTrace(e);
+ }
+ return ret;
+ }
+
+ public IPolicyRule getPolicyInstance(String id) {
+ PolicyInstance policyInstance = mInstanceTable.get(id);
+
+ return (policyInstance == null) ? null : policyInstance.getRule();
+ }
+
+ public Vector<String> getPolicyInstanceConfig(String id) {
+ PolicyInstance policyInstance = mInstanceTable.get(id);
+
+ if (policyInstance == null)
+ return null;
+ Vector<String> v = policyInstance.getRule().getInstanceParams();
+
+ if (v == null)
+ v = new Vector<String>();
+ v.insertElementAt(PROP_IMPL_NAME + "=" + policyInstance.getImplId(), 0);
+ v.insertElementAt(PROP_ENABLE + "=" + policyInstance.isActive(), 1);
+ String predicate = " ";
+
+ if (policyInstance.getRule().getPredicate() != null)
+ predicate = policyInstance.getRule().getPredicate().toString();
+ v.insertElementAt(PROP_PREDICATE + "=" + predicate, 2);
+ return v;
+ }
+
+ public void deletePolicyInstance(String id)
+ throws EBaseException {
+ // If the rule is a persistent rule, we can't delete it.
+ if (mUndeletablePolicies.containsKey(id))
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_CANT_DELETE_PERSISTENT_POLICY", id));
+
+ // First check if the instance is present.
+ PolicyInstance instance = mInstanceTable.get(id);
+
+ if (instance == null)
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_INSTANCE", id));
+
+ IConfigStore policyStore =
+ mGlobalStore.getSubStore(getPolicySubstoreId());
+ IConfigStore instanceStore =
+ policyStore.getSubStore(PROP_RULE);
+
+ instanceStore.removeSubStore(id);
+
+ // Remove the rulename from the rder list
+ int index = mPolicyOrder.indexOf(id);
+
+ mPolicyOrder.removeElement(id);
+
+ // Now change the ordering in the config file.
+ policyStore.put(PROP_ORDER, getRuleOrderString(mPolicyOrder));
+
+ // Commit changes to file.
+ try {
+ mGlobalStore.commit(true);
+ } catch (Exception e) {
+ // Put the rule back in the rule order vector.
+ mPolicyOrder.insertElementAt(id, index);
+
+ Debug.printStackTrace(e);
+ String[] params = { "instance", id };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_DELETING_POLICY_ERROR", params));
+ }
+
+ IPolicyRule rule = instance.getRule();
+
+ if (rule instanceof IEnrollmentPolicy)
+ mEnrollmentRules.removeRule(id);
+ if (rule instanceof IRenewalPolicy)
+ mRenewalRules.removeRule(id);
+ if (rule instanceof IRevocationPolicy)
+ mRevocationRules.removeRule(id);
+ if (rule instanceof IKeyRecoveryPolicy)
+ mKeyRecoveryRules.removeRule(id);
+ if (rule instanceof IKeyArchivalPolicy)
+ mKeyArchivalRules.removeRule(id);
+
+ // Delete the instance
+ mInstanceTable.remove(id);
+ }
+
+ public void addPolicyInstance(String id, Hashtable<String, String> ht)
+ throws EBaseException {
+ // The instance id should be unique
+ if (getPolicyInstance(id) != null)
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_DUPLICATE_INST_ID", id));
+ // There should be an implmentation for this rule.
+ String implName = ht.get(IPolicyRule.PROP_IMPLNAME);
+
+ // See if there is an implementation with this name.
+ IPolicyRule rule = getPolicyImpl(implName);
+
+ if (rule == null)
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_NO_POLICY_IMPL", implName));
+
+ // Prepare config file entries.
+ IConfigStore policyStore =
+ mGlobalStore.getSubStore(getPolicySubstoreId());
+ IConfigStore instanceStore =
+ policyStore.getSubStore(PROP_RULE);
+ IConfigStore newStore = instanceStore.makeSubStore(id);
+
+ for (Enumeration<String> keys = ht.keys(); keys.hasMoreElements();) {
+ String key = keys.nextElement();
+ String val = ht.get(key);
+
+ newStore.put(key, val);
+ }
+
+ // Set the order string.
+ policyStore.put(PROP_ORDER,
+ getRuleOrderString(mPolicyOrder, id));
+
+ // Try to initialize this rule.
+ rule.init(this, newStore);
+
+ // Add the rule to the table.
+ String enabledStr = ht.get(IPolicyRule.PROP_ENABLE);
+ boolean active = false;
+
+ if (enabledStr == null || enabledStr.trim().length() == 0 ||
+ enabledStr.equalsIgnoreCase("true"))
+ active = true;
+
+ // Set the predicate if any present on the rule.
+ String predicate = ht.get(IPolicyRule.PROP_PREDICATE).trim();
+ IExpression exp = null;
+
+ if (predicate.trim().length() > 0)
+ exp = PolicyPredicateParser.parse(predicate.trim());
+ rule.setPredicate(exp);
+
+ // Store the changes in the file.
+ try {
+ mGlobalStore.commit(true);
+ } catch (Exception e) {
+ String[] params = { "instance", id };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_ADDING_POLICY_ERROR", params));
+ }
+
+ // Add the rule to the instance table.
+ PolicyInstance policyInst = new PolicyInstance(id, implName,
+ rule, active);
+
+ mInstanceTable.put(id, policyInst);
+
+ // Add the rule to the end of order table.
+ mPolicyOrder.addElement(id);
+
+ // If the rule is not active, return.
+ if (!active)
+ return;
+
+ addRule(id, rule);
+ }
+
+ public void modifyPolicyInstance(String id, Hashtable<String, String> ht)
+ throws EBaseException {
+ // The instance id should be there already
+ PolicyInstance policyInstance = mInstanceTable.get(id);
+
+ if (policyInstance == null)
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_INSTANCE", id));
+ IPolicyRule rule = policyInstance.getRule();
+
+ // The impl id shouldn't change
+ String implId = ht.get(IPolicyRule.PROP_IMPLNAME);
+
+ if (!implId.equals(policyInstance.getImplId()))
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_IMPLCHANGE_ERROR", id));
+
+ // Make a new rule instance
+ IPolicyRule newRule = getPolicyImpl(implId);
+
+ if (newRule == null) // Can't happen, but just in case..
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_IMPL", implId));
+
+ // Try to init this rule.
+ IConfigStore policyStore =
+ mGlobalStore.getSubStore(getPolicySubstoreId());
+ IConfigStore instanceStore =
+ policyStore.getSubStore(PROP_RULE);
+ IConfigStore oldStore = instanceStore.getSubStore(id);
+ IConfigStore newStore = new PropConfigStore(id);
+
+ // See if the rule is disabled.
+ String enabledStr = ht.get(IPolicyRule.PROP_ENABLE);
+ boolean active = false;
+
+ if (enabledStr == null || enabledStr.trim().length() == 0 ||
+ enabledStr.equalsIgnoreCase("true"))
+ active = true;
+
+ // Set the predicate expression.
+ String predicate = ht.get(IPolicyRule.PROP_PREDICATE).trim();
+ IExpression exp = null;
+
+ if (predicate.trim().length() > 0)
+ exp = PolicyPredicateParser.parse(predicate.trim());
+
+ // See if this a persistent rule.
+ if (mUndeletablePolicies.containsKey(id)) {
+ // A persistent rule can't be disabled.
+ if (!active) {
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_INACTIVE", id));
+ }
+
+ IExpression defPred = mUndeletablePolicies.get(id);
+
+ if (defPred == SimpleExpression.NULL_EXPRESSION)
+ defPred = null;
+ if (exp == null && defPred != null) {
+ String[] params = { id, defPred.toString(),
+ "null" };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_MISCONFIG", params));
+ } else if (exp != null && defPred == null) {
+ String[] params = { id, "null", exp.toString() };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_MISCONFIG", params));
+ } else if (exp != null && defPred != null) {
+ if (!defPred.toString().equals(exp.toString())) {
+ String[] params = { id, defPred.toString(),
+ exp.toString() };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_MISCONFIG", params));
+ }
+ }
+ }
+
+ // Predicate for the persistent rule can't be changed.
+ ht.put(IPolicyRule.PROP_ENABLE, String.valueOf(active));
+
+ // put old config store parameters first.
+ for (Enumeration<String> oldkeys = oldStore.keys(); oldkeys.hasMoreElements();) {
+ String k = oldkeys.nextElement();
+ String v = oldStore.getString(k);
+
+ newStore.put(k, v);
+ }
+
+ // put modified params.
+ for (Enumeration<String> newkeys = ht.keys(); newkeys.hasMoreElements();) {
+ String k = newkeys.nextElement();
+ String v = ht.get(k);
+
+ Debug.trace("newstore key " + k + "=" + v);
+ if (v != null) {
+ if (!k.equals(Constants.OP_TYPE) && !k.equals(Constants.OP_SCOPE) &&
+ !k.equals(Constants.RS_ID) && !k.equals("RULENAME")) {
+ Debug.trace("newstore.put(" + k + "=" + v + ")");
+ newStore.put(k, v);
+ }
+ }
+ }
+
+ // include impl default params in case we missed any.
+
+ /*
+ for (Enumeration keys = ht.keys(); keys.hasMoreElements();)
+ {
+ String key = (String)keys.nextElement();
+ String val = (String)ht.get(key);
+ newStore.put(key, val);
+ }
+ */
+
+ // Try to initialize this rule.
+ newRule.init(this, newStore);
+
+ // If we are successfully initialized, replace the rule
+ // instance
+ policyInstance.setRule(newRule);
+ policyInstance.setActive(active);
+
+ // Set the predicate expression.
+ if (exp != null)
+ newRule.setPredicate(exp);
+
+ // Store the changes in the file.
+ try {
+ for (Enumeration<String> e = newStore.keys(); e.hasMoreElements();) {
+ String key = e.nextElement();
+
+ if (key != null) {
+ Debug.trace(
+ "oldstore.put(" + key + "," +
+ newStore.getString(key) + ")");
+ oldStore.put(key, newStore.getString(key));
+ }
+ }
+ mGlobalStore.commit(true);
+ } catch (Exception e) {
+ String[] params = { "instance", id };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_ADDING_POLICY_ERROR", params));
+ }
+
+ // If rule is disabled, we need to remove it from the
+ // policy set.
+ if (!active) {
+ if (rule instanceof IEnrollmentPolicy)
+ mEnrollmentRules.removeRule(id);
+ if (rule instanceof IRenewalPolicy)
+ mRenewalRules.removeRule(id);
+ if (rule instanceof IRevocationPolicy)
+ mRevocationRules.removeRule(id);
+ if (rule instanceof IKeyRecoveryPolicy)
+ mKeyRecoveryRules.removeRule(id);
+ if (rule instanceof IKeyArchivalPolicy)
+ mKeyArchivalRules.removeRule(id);
+ } else // replace the rule
+ {
+ if (rule instanceof IEnrollmentPolicy)
+ mEnrollmentRules.replaceRule(id, newRule);
+ if (rule instanceof IRenewalPolicy)
+ mRenewalRules.replaceRule(id, newRule);
+ if (rule instanceof IRevocationPolicy)
+ mRevocationRules.replaceRule(id, newRule);
+ if (rule instanceof IKeyRecoveryPolicy)
+ mKeyRecoveryRules.replaceRule(id, newRule);
+ if (rule instanceof IKeyArchivalPolicy)
+ mKeyArchivalRules.replaceRule(id, newRule);
+ }
+ }
+
+ public synchronized void changePolicyInstanceOrdering(
+ String policyOrderStr)
+ throws EBaseException {
+ Vector<String> policyOrder = new Vector<String>();
+ StringTokenizer tokens = new StringTokenizer(policyOrderStr, ",");
+
+ // Get all the elements
+ while (tokens.hasMoreTokens()) {
+ String instanceId = tokens.nextToken().trim();
+
+ // Check if we have that instance configured.
+ if (!mInstanceTable.containsKey(instanceId))
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_INSTANCE", instanceId));
+ policyOrder.addElement(instanceId);
+ }
+
+ // Now enforce the new ordering
+ // First if the order is the same as what we have,
+ // return.
+ if (policyOrder.size() == mPolicyOrder.size()) {
+ if (areSameVectors(policyOrder, mPolicyOrder))
+ return;
+ }
+ PolicySet enrollmentRules = new PolicySet("EnrollmentRules");
+ PolicySet renewalRules = new PolicySet("RenewalRules");
+ PolicySet revocationRules = new PolicySet("RevocationRules");
+ PolicySet keyRecoveryRules = new PolicySet("KeyRecoveryRules");
+ PolicySet keyArchivalRules = new PolicySet("KeyArchivalRules");
+
+ // add system default rules first.
+ try {
+ for (int i = 0; i < mSystemDefaults.length; i++) {
+ String defRuleName = mSystemDefaults[i].substring(
+ mSystemDefaults[i].lastIndexOf('.') + 1);
+ IPolicyRule defRule = (IPolicyRule)
+ Class.forName(mSystemDefaults[i]).newInstance();
+ IConfigStore ruleConfig =
+ mConfig.getSubStore(PROP_DEF_POLICIES + "." + defRuleName);
+
+ defRule.init(this, ruleConfig);
+ if (defRule instanceof IEnrollmentPolicy)
+ enrollmentRules.addRule(defRuleName, defRule);
+ else if (defRule instanceof IRenewalPolicy)
+ renewalRules.addRule(defRuleName, defRule);
+ else if (defRule instanceof IRevocationPolicy)
+ revocationRules.addRule(defRuleName, defRule);
+ else if (defRule instanceof IKeyRecoveryPolicy)
+ keyRecoveryRules.addRule(defRuleName, defRule);
+ else if (defRule instanceof IKeyArchivalPolicy)
+ keyArchivalRules.addRule(defRuleName, defRule);
+ // else ignore the darned rule.
+ }
+ } catch (Throwable e) {
+ Debug.printStackTrace(e);
+ EBaseException ex = new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Cannot create default policy rule. Error: " + e.getMessage()));
+
+ mAuthority.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_POLICY_DEF_CREATE", e.toString()));
+ throw ex;
+ }
+
+ // add rules specified in the new order.
+ for (Enumeration<String> enum1 = policyOrder.elements(); enum1.hasMoreElements();) {
+ String instanceName = enum1.nextElement();
+ PolicyInstance pInstance = mInstanceTable.get(instanceName);
+
+ if (!pInstance.isActive())
+ continue;
+
+ // Add the rule to the policy set according to category if a
+ // rule is enabled.
+ IPolicyRule rule = pInstance.getRule();
+
+ if (rule instanceof IEnrollmentPolicy)
+ enrollmentRules.addRule(instanceName, rule);
+ else if (rule instanceof IRenewalPolicy)
+ renewalRules.addRule(instanceName, rule);
+ else if (rule instanceof IRevocationPolicy)
+ revocationRules.addRule(instanceName, rule);
+ else if (rule instanceof IKeyRecoveryPolicy)
+ keyRecoveryRules.addRule(instanceName, rule);
+ else if (rule instanceof IKeyArchivalPolicy)
+ keyArchivalRules.addRule(instanceName, rule);
+ // else ignore the darned rule.
+ }
+
+ mEnrollmentRules = enrollmentRules;
+ mRenewalRules = renewalRules;
+ mRevocationRules = revocationRules;
+ mKeyRecoveryRules = keyRecoveryRules;
+ mKeyArchivalRules = keyArchivalRules;
+ mPolicyOrder = policyOrder;
+
+ // Now change the ordering in the config file.
+ IConfigStore policyStore =
+ mGlobalStore.getSubStore(getPolicySubstoreId());
+
+ policyStore.put(PROP_ORDER, policyOrderStr);
+
+ // committing
+ try {
+ mGlobalStore.commit(true);
+ } catch (Exception ex) {
+ Debug.printStackTrace(ex);
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_ORDER_ERROR", policyOrderStr));
+ }
+ }
+
+ private boolean areSameVectors(Vector<String> v1, Vector<String> v2) {
+ if (v1.size() != v2.size())
+ return false;
+ int size = v1.size();
+ int i = 0;
+
+ for (; i < size; i++)
+ if (v2.indexOf(v1.elementAt(i)) != i)
+ break;
+ return (i == size ? true : false);
+ }
+
+ private String getRuleOrderString(Vector<String> rules) {
+ StringBuffer sb = new StringBuffer();
+
+ for (Enumeration<String> e = rules.elements(); e.hasMoreElements();) {
+ sb.append(e.nextElement());
+ sb.append(",");
+ }
+ if (sb.length() > 0)
+ sb.setLength(sb.length() - 1);
+ return new String(sb);
+ }
+
+ private String getRuleOrderString(Vector<String> rules, String newRule) {
+ String currentRules = getRuleOrderString(rules);
+
+ if (currentRules == null || currentRules.length() == 0)
+ return newRule;
+ else
+ return currentRules + "," + newRule;
+ }
+
+ /**
+ * Initializes the default system policies. Currently there is only
+ * one policy - ManualAuthentication. More may be added later on.
+ *
+ * The default policies may be disabled - for example to over-ride
+ * agent approval for testing the system by setting the following
+ * property in the config file:
+ *
+ * <subsystemId>.Policy.systemPolicies.enable=false
+ *
+ * By default the value for this property is true.
+ *
+ * Users can over-ride the default system policies by listing their
+ * 'custom' system policies under the following property:
+ *
+ * <subsystemId>.Policy.systemPolicies=<system policy1 class path>,
+ * <system policy2 class path>
+ *
+ * There can only be one instance of the system policy in the system
+ * and will apply to all requests, and hence predicates are not used
+ * for a system policy. Due to the same reason, these properties are
+ * not configurable using the Console.
+ *
+ * A System policy may read config properties from a subtree under
+ * <subsystemId>.Policy.systemPolicies.<ClassName>. An example is
+ * ra.Policy.systemPolicies.ManualAuthentication.param1=value
+ */
+ private void initSystemPolicies(IConfigStore mConfig)
+ throws EBaseException {
+ // If system policies are disabled, return. No Deferral of
+ // requests may be done.
+ String enable = mConfig.getString(PROP_DEF_POLICIES + "." +
+ PROP_ENABLE, "true").trim();
+
+ if (enable.equalsIgnoreCase("false")) {
+ mSystemDefaults = DEF_POLICIES;
+ return;
+ }
+
+ // Load default policies that are always present.
+ String configuredDefaults = mConfig.getString(PROP_DEF_POLICIES,
+ null);
+
+ if (configuredDefaults == null ||
+ configuredDefaults.trim().length() == 0)
+ mSystemDefaults = DEF_POLICIES;
+ else {
+ Vector<String> rules = new Vector<String>();
+ StringTokenizer tokenizer = new
+ StringTokenizer(configuredDefaults.trim(), ",");
+
+ while (tokenizer.hasMoreTokens()) {
+ String rule = tokenizer.nextToken().trim();
+
+ rules.addElement(rule);
+ }
+ if (rules.size() > 0) {
+ mSystemDefaults = new String[rules.size()];
+ rules.copyInto(mSystemDefaults);
+ } else
+ mSystemDefaults = DEF_POLICIES;
+ }
+
+ // Now Initialize the rules. These defaults have only one
+ // instance and the rule name is the name of the class itself.
+ // Any configuration parameters required could be read from
+ // <subsystemId>.Policy.default.RuleName.
+ for (int i = 0; i < mSystemDefaults.length; i++) {
+ // Load the class and make an instance.
+ // Verify if the class is a valid implementation of
+ // IPolicyRule
+ String ruleName = null;
+
+ try {
+ Object o = Class.forName(mSystemDefaults[i]).newInstance();
+
+ if (!(o instanceof IEnrollmentPolicy) &&
+ !(o instanceof IRenewalPolicy) &&
+ !(o instanceof IRevocationPolicy) &&
+ !(o instanceof IKeyRecoveryPolicy) &&
+ !(o instanceof IKeyArchivalPolicy))
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_IMPL",
+ mSystemDefaults[i]));
+
+ IPolicyRule rule = (IPolicyRule) o;
+
+ // Initialize the rule.
+ ruleName = mSystemDefaults[i].substring(
+ mSystemDefaults[i].lastIndexOf('.') + 1);
+ IConfigStore ruleConfig = mConfig.getSubStore(
+ PROP_DEF_POLICIES + "." + ruleName);
+
+ rule.init(this, ruleConfig);
+
+ // Add the rule to the appropriate PolicySet.
+ addRule(ruleName, rule);
+ } catch (EBaseException e) {
+ throw e;
+ } catch (Exception e) {
+ Debug.printStackTrace(e);
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_NO_POLICY_IMPL",
+ ruleName));
+ }
+ }
+ }
+
+ /**
+ * Read list of undeletable policies if any configured in the
+ * system.
+ *
+ * These are required to protect the system from being misconfigured
+ * to the point that the requests wouldn't serialize or certain
+ * fields in the certificate(s) being checked will go unchecked
+ * ..etc.
+ *
+ * For now the following policies are undeletable:
+ *
+ * DirAuthRule: This is a default DirectoryAuthentication policy
+ * for user certificates that interprets directory
+ * credentials. The presence of this policy is needed
+ * if the OOTB DirectoryAuthentication-based automatic
+ * certificate issuance is supported.
+ *
+ * DefaultUserNameRule: This policy verifies/sets subjectDn for user
+ * certificates.
+ *
+ * DefaultServerNameRule: This policy verifies/sets subjectDn for
+ * server certificates.
+ *
+ * DefaultValidityRule: Verifies/sets validty for all certificates.
+ *
+ * DefaultRenewalValidityRule: Verifies/sets validity for certs being
+ * renewed.
+ *
+ * The 'undeletables' cannot be deleted from the config file, nor
+ * can the be disabled. If any predicates are associated with them
+ * the predicates can't be changed either. But, other config parameters
+ * such as maxValidity, renewalInterval ..etc can be changed to suit
+ * local policy requirements.
+ *
+ * During start up the policy processor will verify if the undeletables
+ * are present, and that they are enabled and that their predicates are
+ * not changed.
+ *
+ * The rules mentioned above are currently hard coded. If these need to
+ * read from the config file, the 'undeletables' can be configured as
+ * as follows:
+ *
+ * <subsystemId>.Policy.undeletablePolicies=<comma separated rule names>
+ * Example:
+ * ra.Policy.undeletablePolicies=DirAuthRule, DefaultUserNameRule, DefaultServerNameRule, DefaultValidityRule,
+ * DefaultRenewalValidityRule
+ *
+ * The predicates if any associated with them may be configured as
+ * follows:
+ * <subsystemId>.Policy.undeletablePolicies.DirAuthRule.predicate= certType == client.
+ *
+ * where subsystemId is ra or ca.
+ *
+ * If the undeletables are configured in the file,the configured entries
+ * take precedence over the hardcoded ones in this file. If you are
+ * configuring them in the file, please remember to configure the
+ * predicates if applicable.
+ *
+ * During policy configuration from MCC, the policy processor will not
+ * let you delete an 'undeletable', nor will it let you disable it.
+ * You will not be able to change the predicate either. Other parameters
+ * can be configured as needed.
+ *
+ * If a particular rule needs to be removed from the 'undeletables',
+ * either remove it from the hard coded list above, or configure the
+ * rules required rules only via the config file. The former needs
+ * recompilation of the source. The later is flexible to be able to
+ * make any rule an 'undeletable' or nor an 'undeletable'.
+ *
+ * Example: We want to use only manual forms for enrollment.
+ * We do n't need to burn in DirAuthRule. We need to configure all
+ * other rules except the DirAuthRule as follows:
+ *
+ * ra.Policy.undeletablePolicies = DefaultUserNameRule, DefaultServerNameRule, DefaultValidityRule,
+ * DefaultRenewalValidityRule
+ *
+ * The following predicates are necessary:
+ *
+ * ra.Policy.undeletablePolicies.DefaultUserNameRule.predicate = certType == client
+ * ra.Policy.undeletablePolicies.DefaultServerNameRule.predicate = certType == server
+ *
+ * The other two rules do not have any predicates.
+ */
+ private void initUndeletablePolicies(IConfigStore mConfig)
+ throws EBaseException {
+ // Read undeletable policies if any configured.
+ String configuredUndeletables =
+ mConfig.getString(PROP_UNDELETABLE_POLICIES, null);
+
+ if (configuredUndeletables == null ||
+ configuredUndeletables.trim().length() == 0) {
+ mUndeletablePolicies = DEF_UNDELETABLE_POLICIES;
+ return;
+ }
+
+ Vector<String> rules = new Vector<String>();
+ StringTokenizer tokenizer = new
+ StringTokenizer(configuredUndeletables.trim(), ",");
+
+ while (tokenizer.hasMoreTokens()) {
+ String rule = tokenizer.nextToken().trim();
+
+ rules.addElement(rule);
+ }
+
+ if (rules.size() == 0) {
+ mUndeletablePolicies = DEF_UNDELETABLE_POLICIES;
+ return;
+ }
+
+ // For each rule read from the config file, see if any
+ // predicate is set.
+ mUndeletablePolicies = new Hashtable<String, IExpression>();
+ for (Enumeration<String> e = rules.elements(); e.hasMoreElements();) {
+ String urn = e.nextElement();
+
+ // See if there is predicate in the file
+ String pred = mConfig.getString(PROP_UNDELETABLE_POLICIES +
+ "." + urn + "." + PROP_PREDICATE, null);
+
+ IExpression exp = SimpleExpression.NULL_EXPRESSION;
+
+ if (pred != null)
+ exp = PolicyPredicateParser.parse(pred);
+ mUndeletablePolicies.put(urn, exp);
+ }
+ }
+
+ private void addRule(String ruleName, IPolicyRule rule) {
+ if (rule instanceof IEnrollmentPolicy)
+ mEnrollmentRules.addRule(ruleName, rule);
+ if (rule instanceof IRenewalPolicy)
+ mRenewalRules.addRule(ruleName, rule);
+ if (rule instanceof IRevocationPolicy)
+ mRevocationRules.addRule(ruleName, rule);
+ if (rule instanceof IKeyRecoveryPolicy)
+ mKeyRecoveryRules.addRule(ruleName, rule);
+ if (rule instanceof IKeyArchivalPolicy)
+ mKeyArchivalRules.addRule(ruleName, rule);
+ }
+
+ private boolean isSystemDefaultPolicy(String clPath) {
+ boolean ret = false;
+
+ if (mSystemDefaults == null)
+ return false;
+ for (int i = 0; i < mSystemDefaults.length; i++) {
+ if (clPath.equals(mSystemDefaults[i])) {
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+ }
+
+ private void verifyDefaultPolicyConfig()
+ throws EPolicyException {
+ // For each policy in undeletable list make sure that
+ // the policy is present, is not disabled and its predicate
+ // is not tampered with.
+ for (Enumeration<String> e = mUndeletablePolicies.keys(); e.hasMoreElements();) {
+ String urn = e.nextElement();
+
+ // See if the rule is in the instance table.
+ PolicyInstance inst = mInstanceTable.get(urn);
+
+ if (inst == null)
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_MISSING_PERSISTENT_RULE", urn));
+
+ // See if the instance is disabled.
+ if (!inst.isActive())
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_INACTIVE", urn));
+
+ // See if the predicated is misconfigured.
+ IExpression defPred = mUndeletablePolicies.get(urn);
+
+ // We used SimpleExpression.NULL_EXPRESSION to indicate a null.
+ if (defPred == SimpleExpression.NULL_EXPRESSION)
+ defPred = null;
+ IExpression confPred = inst.getRule().getPredicate();
+
+ if (defPred == null && confPred != null) {
+ String[] params = { urn, "null", confPred.toString() };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_MISCONFIG", params));
+ } else if (defPred != null && confPred == null) {
+ String[] params = { urn, defPred.toString(), "null" };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_MISCONFIG", params));
+ } else if (defPred != null && confPred != null) {
+ if (!defPred.toString().equals(confPred.toString())) {
+ String[] params = { urn, defPred.toString(),
+ confPred.toString() };
+
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_MISCONFIG", params));
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Class to keep track of various configurable implementations.
+ */
+class RegisteredPolicy {
+ String mId;
+ String mClPath;
+
+ public RegisteredPolicy(String id, String clPath) {
+ if (id == null || clPath == null)
+ throw new AssertionException("Policy id or classpath can't be null");
+ mId = id;
+ mClPath = clPath;
+ }
+
+ public String getClassPath() {
+ return mClPath;
+ }
+
+ public String getId() {
+ return mId;
+ }
+}
+
+/**
+ * @deprecated
+ */
+class PolicyInstance {
+ String mInstanceId;
+ String mImplId;
+ IPolicyRule mRule;
+ boolean mIsEnabled;
+
+ public PolicyInstance(String instanceId, String implId,
+ IPolicyRule rule, boolean isEnabled) {
+ mInstanceId = instanceId;
+ mImplId = implId;
+ mRule = rule;
+ mIsEnabled = isEnabled;
+ }
+
+ public String getInstanceId() {
+ return mInstanceId;
+ }
+
+ public String getImplId() {
+ return mImplId;
+ }
+
+ public String getRuleInfo() {
+ String enabled = mIsEnabled ? "enabled" : "disabled";
+
+ return mInstanceId + ";" + mImplId + ";visible;" + enabled;
+ }
+
+ public IPolicyRule getRule() {
+ return mRule;
+ }
+
+ public boolean isInstanceOf(String implId) {
+ return mImplId.equals(implId);
+ }
+
+ public boolean isActive() {
+ return mIsEnabled;
+ }
+
+ public void setActive(boolean stat) {
+ mIsEnabled = stat;
+ }
+
+ public void setRule(IPolicyRule newRule) {
+ mRule = newRule;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java b/base/server/cmscore/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java
new file mode 100644
index 000000000..1fbcf2738
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java
@@ -0,0 +1,48 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.policy;
+
+import com.netscape.certsrv.policy.IPolicyRule;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+
+/**
+ *
+ * @deprecated
+ *
+ */
+public class JavaScriptRequestProxy {
+ IRequest req;
+
+ public JavaScriptRequestProxy(IRequest r) {
+ req = r;
+ }
+
+ public String getHTTP(String param) {
+ return req.getExtDataInString(IRequest.HTTP_PARAMS, param);
+ }
+
+ public String get(String param) {
+ return req.getExtDataInString(param);
+ }
+
+ public PolicyResult applyPolicy(IPolicyRule r) {
+ return r.apply(req);
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/policy/OrExpression.java b/base/server/cmscore/src/com/netscape/cmscore/policy/OrExpression.java
new file mode 100644
index 000000000..512bba256
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/policy/OrExpression.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.policy;
+
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IExpression;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This class represents an Or expression of the form
+ * (var1 op val1 OR var2 op val2).
+ *
+ * Expressions are used as predicates for policy selection.
+ *
+ * @deprecated
+ * @author kanda
+ * @version $Revision$, $Date$
+ */
+public class OrExpression implements IExpression {
+ private IExpression mExp1;
+ private IExpression mExp2;
+
+ public OrExpression(IExpression exp1, IExpression exp2) {
+ mExp1 = exp1;
+ mExp2 = exp2;
+ }
+
+ public boolean evaluate(IRequest req)
+ throws EPolicyException {
+ if (mExp1 == null && mExp2 == null)
+ return true;
+ else if (mExp1 != null && mExp2 != null)
+ return mExp1.evaluate(req) || mExp2.evaluate(req);
+ else if (mExp1 != null && mExp2 == null)
+ return mExp1.evaluate(req);
+ else
+ // (mExp1 == null && mExp2 != null)
+ return mExp2.evaluate(req);
+ }
+
+ public String toString() {
+ if (mExp1 == null && mExp2 == null)
+ return "";
+ else if (mExp1 != null && mExp2 != null)
+ return mExp1.toString() + " OR " + mExp2.toString();
+ else if (mExp1 != null && mExp2 == null)
+ return mExp1.toString();
+ else
+ // (mExp1 == null && mExp2 != null)
+ return mExp2.toString();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/policy/PolicyPredicateParser.java b/base/server/cmscore/src/com/netscape/cmscore/policy/PolicyPredicateParser.java
new file mode 100644
index 000000000..c55b84ece
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/policy/PolicyPredicateParser.java
@@ -0,0 +1,339 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.policy;
+
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IExpression;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * Default implementation of predicate parser.
+ *
+ * Limitations:
+ *
+ * 1. Currently parentheses are not suported.
+ * 2. Only ==, != <, >, <= and >= operators are supported.
+ * 3. The only boolean operators supported are AND and OR. AND takes precedence
+ * over OR. Example: a AND b OR e OR c AND d
+ * is treated as (a AND b) OR e OR (c AND d)
+ * 4. If this is n't adequate, roll your own.
+ *
+ * @deprecated
+ * @author kanda
+ * @version $Revision$, $Date$
+ */
+public class PolicyPredicateParser {
+ public static final int OP_AND = 1;
+ public static final int OP_OR = 2;
+ public static final int EXPRESSION = 0;
+
+ public static final String AND = "AND";
+ public static final String OR = "OR";
+
+ private static final char COMMA = ',';
+
+ /**
+ * Parse the predicate expression and return a vector of expressions.
+ *
+ * @param predicateExp The predicate expression as read from the config file.
+ * @return expVector The vector of expressions.
+ */
+ public static IExpression parse(String predicateExpression)
+ throws EPolicyException {
+ if (predicateExpression == null ||
+ predicateExpression.length() == 0)
+ return null;
+ PredicateTokenizer pt = new PredicateTokenizer(predicateExpression);
+
+ if (pt == null || !pt.hasMoreTokens())
+ return null;
+
+ // The first token cannot be an operator. We are not dealing with
+ // reverse-polish notation.
+ String token = pt.nextToken();
+
+ if (getOP(token) != EXPRESSION) {
+ if (Debug.ON)
+ Debug.trace("Malformed expression: " + predicateExpression);
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_BAD_POLICY_EXPRESSION", predicateExpression));
+ }
+
+ IExpression current = parseExpression(token);
+ boolean malformed = false;
+ Vector<IExpression> expSet = new Vector<IExpression>();
+ int prevType = EXPRESSION;
+
+ while (pt.hasMoreTokens()) {
+ token = pt.nextToken();
+ int curType = getOP(token);
+
+ if ((prevType != EXPRESSION && curType != EXPRESSION) ||
+ (prevType == EXPRESSION && curType == EXPRESSION)) {
+ malformed = true;
+ break;
+ }
+
+ // If an operator seen skip to the next token
+ if (curType != EXPRESSION) {
+ prevType = curType;
+ continue;
+ }
+
+ // If the previous type was an OR token, add the current expression to
+ // the expression set;
+ if (prevType == OP_OR) {
+ expSet.addElement(current);
+ current = parseExpression(token);
+ prevType = curType;
+ continue;
+ }
+
+ // If the previous type was an AND token, make an AND expression
+ if (prevType == OP_AND) {
+ current = new AndExpression(current, parseExpression(token));
+ prevType = curType;
+ }
+ }
+ if (malformed) {
+ if (Debug.ON)
+ Debug.trace("Malformed expression: " + predicateExpression);
+ throw new EPolicyException(
+ CMS.getUserMessage("CMS_POLICY_BAD_POLICY_EXPRESSION",
+ predicateExpression));
+ }
+
+ // Form an ORExpression
+ if (current != null)
+ expSet.addElement(current);
+
+ int size = expSet.size();
+
+ if (size == 0)
+ return null;
+ OrExpression orExp = new
+ OrExpression(expSet.elementAt(0), null);
+
+ for (int i = 1; i < size; i++)
+ orExp = new OrExpression(orExp,
+ expSet.elementAt(i));
+ return orExp;
+ }
+
+ private static int getOP(String token) {
+ if (token.equalsIgnoreCase(AND))
+ return OP_AND;
+ else if (token.equalsIgnoreCase(OR))
+ return OP_OR;
+ else
+ return EXPRESSION;
+ }
+
+ private static IExpression parseExpression(String input)
+ throws EPolicyException {
+ // If the expression has multiple parts separated by commas
+ // we need to construct an AND expression. Else we will return a
+ // simple expression.
+ int commaIndex = input.indexOf(COMMA);
+
+ if (commaIndex < 0)
+ return SimpleExpression.parse(input);
+ int currentIndex = 0;
+ Vector<SimpleExpression> expVector = new Vector<SimpleExpression>();
+
+ while (commaIndex > 0) {
+ SimpleExpression exp = (SimpleExpression)
+ SimpleExpression.parse(input.substring(currentIndex,
+ commaIndex));
+
+ expVector.addElement(exp);
+ currentIndex = commaIndex + 1;
+ commaIndex = input.indexOf(COMMA, currentIndex);
+ }
+ if (currentIndex < (input.length() - 1)) {
+ SimpleExpression exp = (SimpleExpression)
+ SimpleExpression.parse(input.substring(currentIndex));
+
+ expVector.addElement(exp);
+ }
+
+ int size = expVector.size();
+ SimpleExpression exp1 = expVector.elementAt(0);
+ SimpleExpression exp2 = expVector.elementAt(1);
+ AndExpression andExp = new AndExpression(exp1, exp2);
+
+ for (int i = 2; i < size; i++) {
+ andExp = new AndExpression(andExp, expVector.elementAt(i));
+ }
+ return andExp;
+ }
+
+ public static void main(String[] args) {
+
+ /*********
+ * IRequest req = new IRequest();
+ * try
+ * {
+ * req.set("ou", "people");
+ * req.set("cn", "John Doe");
+ * req.set("uid", "jdoes");
+ * req.set("o", "airius.com");
+ * req.set("certtype", "client");
+ * req.set("request", "issuance");
+ * req.set("id", new Integer(10));
+ * req.set("dualcerts", new Boolean(true));
+ *
+ * Vector v = new Vector();
+ * v.addElement("one");
+ * v.addElement("two");
+ * v.addElement("three");
+ * req.set("count", v);
+ * }
+ * catch (Exception e){e.printStackTrace();}
+ * String[] array = { "ou == people AND certtype == client",
+ * "ou == servergroup AND certtype == server",
+ * "uid == jdoes, ou==people, o==airius.com OR ou == people AND certType == client OR certType == server AND cn == needles.mcom.com"
+ * ,
+ * };
+ * for (int i = 0; i < array.length; i++)
+ * {
+ * System.out.println();
+ * System.out.println("String: " + array[i]);
+ * IExpression exp = null;
+ * try
+ * {
+ * exp = parse(array[i]);
+ * if (exp != null)
+ * {
+ * System.out.println("Parsed Expression: " + exp);
+ * boolean result = exp.evaluate(req);
+ * System.out.println("Result: " + result);
+ * }
+ * }
+ * catch (Exception e) {e.printStackTrace(); }
+ * }
+ *
+ *
+ * try
+ * {
+ * BufferedReader rdr = new BufferedReader(
+ * new FileReader(args[0]));
+ * String line;
+ * while((line=rdr.readLine()) != null)
+ * {
+ * System.out.println();
+ * System.out.println("Line Read: " + line);
+ * IExpression exp = null;
+ * try
+ * {
+ * exp = parse(line);
+ * if (exp != null)
+ * {
+ * System.out.println(exp);
+ * boolean result = exp.evaluate(req);
+ * System.out.println("Result: " + result);
+ * }
+ *
+ * }catch (Exception e){e.printStackTrace();}
+ * }
+ * }
+ * catch (Exception e){e.printStackTrace(); }
+ *******/
+ }
+
+}
+
+class PredicateTokenizer {
+ String input;
+ int currentIndex;
+ String nextToken;
+
+ public PredicateTokenizer(String predString) {
+ input = predString;
+ currentIndex = 0;
+ nextToken = null;
+ }
+
+ public boolean hasMoreTokens() {
+ return (currentIndex != -1);
+ }
+
+ public String nextToken() throws EPolicyException {
+ if (nextToken != null) {
+ String toReturn = nextToken;
+
+ nextToken = null;
+ return toReturn;
+ }
+
+ int andIndex = input.indexOf(" AND", currentIndex);
+
+ if (andIndex < 0)
+ andIndex = input.indexOf(" and", currentIndex);
+ int orIndex = input.indexOf(" OR", currentIndex);
+
+ if (orIndex < 0)
+ orIndex = input.indexOf(" or", currentIndex);
+ String toReturn = null;
+
+ if (andIndex == -1 && orIndex == -1) {
+ if (currentIndex == 0) {
+ currentIndex = -1;
+ toReturn = input;
+ } else {
+ int temp = currentIndex;
+
+ currentIndex = -1;
+ toReturn = input.substring(temp);
+ }
+ } else if (andIndex >= 0 && (andIndex < orIndex || orIndex == -1)) {
+ if (currentIndex != andIndex) {
+ toReturn = input.substring(currentIndex, andIndex);
+ nextToken = input.substring(andIndex + 1, andIndex + 4);
+ currentIndex = andIndex + 4;
+ } else {
+ toReturn = "AND";
+ currentIndex += 4;
+ }
+ } else if (orIndex >= 0 && (orIndex < andIndex || andIndex == -1)) {
+ if (currentIndex != orIndex) {
+ toReturn = input.substring(currentIndex, orIndex);
+ nextToken = input.substring(orIndex + 1, orIndex + 3);
+ currentIndex = orIndex + 3;
+ } else {
+ toReturn = "OR";
+ currentIndex += 3;
+ }
+ } else {
+ // Cannot happen; Assert here.
+ if (Debug.ON)
+ Debug.trace("Malformed Predicate Expression : No Tokens");
+ throw new EPolicyException("Malformed Predicate Expression : No Tokens");
+ }
+
+ String trimmed = toReturn.trim();
+
+ if (trimmed.length() == 0)
+ return nextToken();
+ else
+ return trimmed;
+
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/policy/PolicySet.java b/base/server/cmscore/src/com/netscape/cmscore/policy/PolicySet.java
new file mode 100644
index 000000000..b5e3459d1
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/policy/PolicySet.java
@@ -0,0 +1,299 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.policy;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.policy.IExpression;
+import com.netscape.certsrv.policy.IPolicyRule;
+import com.netscape.certsrv.policy.IPolicySet;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * Implements a policy set per IPolicySet interface. This class
+ * uses a vector of ordered policies to enforce priority.
+ *
+ * @deprecated
+ * @author kanda
+ * @version $Revision$, $Date$
+ */
+public class PolicySet implements IPolicySet {
+ private String mName;
+ private Vector<String> mRuleNames = new Vector<String>();
+ private Vector<IPolicyRule> mRules = new Vector<IPolicyRule>();
+ private ILogger mLogger = CMS.getLogger();
+
+ public PolicySet(String name) {
+ mName = name;
+ }
+
+ /**
+ * Returns the name of the rule set.
+ * <P>
+ *
+ * @return The name of the rule set.
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Returns the no of rules in a set.
+ * <P>
+ *
+ * @return the no of rules.
+ */
+ public int count() {
+ return mRules.size();
+ }
+
+ /**
+ * Add a policy rule.
+ * <P>
+ *
+ * @param ruleName The name of the rule to be added.
+ * @param rule The rule to be added.
+ */
+ public void addRule(String ruleName, IPolicyRule rule) {
+ if (mRuleNames.indexOf(ruleName) >= 0)
+ return; // XXX - Duplicate - Need to throw an exception.
+
+ if (ruleName != null && rule != null) {
+ mRuleNames.addElement(ruleName);
+ mRules.addElement(rule);
+ }
+ // XXX - TODO: else throw an exception.
+
+ }
+
+ /**
+ * Remplaces a policy rule identified by the given name.
+ *
+ * @param id The name of the rule to be replaced.
+ * @param rule The rule to be replaced.
+ */
+ public void replaceRule(String ruleName, IPolicyRule rule) {
+ int index = mRuleNames.indexOf(ruleName);
+
+ if (index < 0) {
+ addRule(ruleName, rule);
+ return;
+ }
+
+ mRuleNames.setElementAt(ruleName, index);
+ mRules.setElementAt(rule, index);
+ }
+
+ /**
+ * Removes a policy rule identified by the given name.
+ *
+ * @param id The name of the rule to be removed.
+ */
+ public void removeRule(String ruleName) {
+ int index = mRuleNames.indexOf(ruleName);
+
+ if (index < 0)
+ return; // XXX - throw an exception.
+
+ mRuleNames.removeElementAt(index);
+ mRules.removeElementAt(index);
+ }
+
+ /**
+ * Returns the rule identified by a given name.
+ * <P>
+ *
+ * @param id The name of the rule to be return.
+ * @return The rule identified by the given name or null if none exists.
+ */
+ public IPolicyRule getRule(String ruleName) {
+ int index = mRuleNames.indexOf(ruleName);
+
+ if (index < 0)
+ return null;
+ return mRules.elementAt(index);
+ }
+
+ /**
+ * Returns an enumeration of rules.
+ * <P>
+ *
+ * @return An enumeration of rules.
+ */
+ public Enumeration<IPolicyRule> getRules() {
+ return mRules.elements();
+ }
+
+ /**
+ * Apply policies on a given request from a rule set.
+ * The rules may modify the request.
+ *
+ * @param req The request to apply policies on.
+ * @return the PolicyResult.
+ */
+ public PolicyResult apply(IRequest req) {
+ // If there are no rules, we are done.
+
+ if (mRules.size() == 0)
+ return PolicyResult.ACCEPTED;
+
+ // All policies are applied before returning the result. Hence
+ // if atleast one of the policies returns a REJECTED, we need to
+ // return that status. If none of the policies REJECTED
+ // the request, but atleast one of them DEFERRED the request, we
+ // need to return DEFERRED.
+ boolean rejected = false;
+ boolean deferred = false;
+ int size = mRules.size();
+
+ for (int index = 0; index < size; index++) {
+ String name = mRuleNames.elementAt(index);
+ IPolicyRule rule = mRules.elementAt(index);
+ IExpression exp = rule.getPredicate();
+
+ try {
+ if (Debug.ON)
+ Debug.trace("evaluating predicate for rule " + rule.getName());
+ CMS.debug("PolicySet: apply()- evaluating predicate for rule " + rule.getName());
+ if (exp != null && !exp.evaluate(req))
+ continue;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ if (!typeMatched(rule, req))
+ continue;
+
+ try {
+ if (Debug.ON)
+ Debug.trace("Policy " + name + " selected");
+ CMS.debug("Policy " + name + " selected");
+ PolicyResult result = rule.apply(req);
+ CMS.debug("Policy applied");
+
+ if (Debug.ON)
+ Debug.trace("Policy " + name + " returned " + result);
+
+ if (result == PolicyResult.REJECTED) {
+ // It is hard to find out the owner at the moment unless
+ // we pass that info down the chain. For now use S_OTHER
+ // as the system id for the log entry.
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_POLICY_REJECT_RESULT", req.getRequestId().toString(), name));
+ rejected = true;
+ } else if (result == PolicyResult.DEFERRED) {
+ // It is hard to find out the owner at the moment unless
+ // we pass that info down the chain. For now use S_OTHER
+ // as the system id for the log entry.
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_WARN,
+ CMS.getLogMessage("CMSCORE_POLICY_DEFER_RESULT", req.getRequestId().toString(), name));
+ deferred = true;
+ } else if (result == PolicyResult.ACCEPTED) {
+ // It is hard to find out the owner at the moment unless
+ // we pass that info down the chain. For now use S_OTHER
+ // as the system id for the log entry.
+ } else {
+ // should not get to this status
+ // It is hard to find out the owner at the moment unless
+ // we pass that info down the chain. For now use S_OTHER
+ // as the system id for the log entry.
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_INFO,
+ "policy: Request " + req.getRequestId() + " - Result of applying rule: " + name +
+ " is: " + getPolicyResult(result));
+ }
+ } catch (Throwable ex) {
+ // Customer can install his own policies.
+ // The policy may have bug. We want to
+ // catch those problems and report
+ // them to the log
+ mLogger.log(
+ ILogger.EV_SYSTEM,
+ ILogger.S_OTHER,
+ ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_POLICY_ERROR_RESULT", req.getRequestId().toString(), name,
+ ex.toString()));
+ // treat as rejected to prevent request from going into
+ // a weird state. request queue doesn't handle this case.
+ rejected = true;
+ rule.setError(
+ req,
+ CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", rule.getName(), ex.toString()), null);
+ }
+ }
+
+ if (rejected) {
+ return PolicyResult.REJECTED;
+ } else if (deferred) {
+ return PolicyResult.DEFERRED;
+ } else {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_INFO,
+ "Request " + req.getRequestId() +
+ " Policy result: successful");
+ return PolicyResult.ACCEPTED;
+ }
+ }
+
+ public void printPolicies() {
+ if (mRules.size() == 0)
+ return;
+ System.out.println("Policy Set Name: " + mName);
+ System.out.println();
+ int size = mRules.size();
+
+ for (int index = 0; index < size; index++) {
+ String ruleName = mRuleNames.elementAt(index);
+
+ System.out.println("Rule Name: " + ruleName);
+ System.out.println("Implementation: " +
+ mRules.elementAt(index).getClass().getName());
+ }
+ }
+
+ String getPolicyResult(PolicyResult res) {
+ if (res == PolicyResult.ACCEPTED)
+ return "accepted";
+ else if (res == PolicyResult.DEFERRED)
+ return "deferred";
+ else if (res == PolicyResult.REJECTED)
+ return "rejected";
+ else
+ return "unknown";
+ }
+
+ boolean typeMatched(IPolicyRule rule, IRequest req) {
+
+ if (req.getExtDataInCertInfoArray(IRequest.CERT_INFO) != null) {
+ return true;
+ }
+
+ if (req.getExtDataInCertArray(IRequest.OLD_CERTS) != null) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/policy/SimpleExpression.java b/base/server/cmscore/src/com/netscape/cmscore/policy/SimpleExpression.java
new file mode 100644
index 000000000..4f8f0eb9a
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/policy/SimpleExpression.java
@@ -0,0 +1,434 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.policy;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.policy.EPolicyException;
+import com.netscape.certsrv.policy.IExpression;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cmscore.util.AssertionException;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * This class represents an expression of the form var = val,
+ * var != val, var < val, var > val, var <= val, var >= val.
+ *
+ * Expressions are used as predicates for policy selection.
+ *
+ * @deprecated
+ * @author kanda
+ * @version $Revision$, $Date$
+ */
+public class SimpleExpression implements IExpression {
+ private String mPfx;
+ private String mVar;
+ private String mVal;
+ private String mPartialMatch;
+ private int mOp;
+ private boolean hasWildCard;
+ public static final char WILDCARD_CHAR = '*';
+
+ // This is just for indicating a null expression.
+ public static SimpleExpression NULL_EXPRESSION = new SimpleExpression("null", OP_EQUAL, "null");
+
+ public static IExpression parse(String input)
+ throws EPolicyException {
+ // Get the index of operator
+ // Debug.trace("SimpleExpression::input: " + input);
+ String var = null;
+ int op = -1;
+ String val = null;
+
+ // XXX - Kanda - Need to change this parsing code eventually.
+ ExpressionComps comps = parseForEquality(input);
+
+ if (comps == null)
+ comps = parseForInEquality(input);
+ if (comps == null)
+ comps = parseForGE(input);
+ if (comps == null)
+ comps = parseForLE(input);
+ if (comps == null)
+ comps = parseForGT(input);
+ if (comps == null)
+ comps = parseForLT(input);
+ if (comps == null)
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_BAD_POLICY_EXPRESSION", input));
+ String pfx = null;
+ String rawVar = comps.getAttr();
+ int dotIdx = rawVar.indexOf('.');
+
+ if (dotIdx != -1) {
+ pfx = rawVar.substring(0, dotIdx).trim();
+ var = rawVar.substring(dotIdx + 1).trim();
+ } else {
+ var = rawVar;
+ }
+ op = comps.getOp();
+ val = comps.getVal();
+ return new SimpleExpression(pfx, var, op, val);
+ }
+
+ public SimpleExpression(String var, int op, String val) {
+ this(null, var, op, val);
+ }
+
+ public SimpleExpression(String prefix, String var, int op, String val) {
+ // Assert that op has to be either IExpression.OP_EQUAL or
+ // IExpression.OP_NEQUAL.
+ // If val or var is null throw an exception!
+ mPfx = prefix;
+ mVar = var;
+ mOp = op;
+ mVal = val;
+ int firstIndex;
+
+ if ((firstIndex = mVal.indexOf(WILDCARD_CHAR)) >= 0) {
+ hasWildCard = true;
+ int nextIndex = mVal.indexOf(WILDCARD_CHAR, firstIndex + 1);
+
+ if (nextIndex == -1) {
+ if (firstIndex == 0)
+ mPartialMatch = mVal.substring(1);
+ else
+ mPartialMatch = mVal.substring(0, firstIndex);
+ } else
+ mPartialMatch = mVal.substring(firstIndex + 1, nextIndex);
+ } else
+ hasWildCard = false;
+ }
+
+ public boolean evaluate(IRequest req)
+ throws EPolicyException {
+ // mPfx and mVar are looked up case-indendently
+ String givenVal = req.getExtDataInString(mPfx, mVar);
+
+ if (Debug.ON)
+ Debug.trace("mPfx: " + mPfx + " mVar: " + mVar +
+ ",Given Value: " + givenVal + ", Value to compare with: " + mVal);
+
+ return matchValue(givenVal);
+ }
+
+ private boolean matchVector(Vector<?> value)
+ throws EPolicyException {
+ boolean result = false;
+ Enumeration<?> e = value.elements();
+
+ for (; e.hasMoreElements();) {
+ result = matchValue(e.nextElement());
+ if (result)
+ break;
+ }
+ return result;
+ }
+
+ private boolean matchStringArray(String[] value)
+ throws EPolicyException {
+ boolean result = false;
+
+ for (int i = 0; i < value.length; i++) {
+ result = matchValue(value[i]);
+ if (result)
+ break;
+ }
+ return result;
+ }
+
+ private boolean matchValue(Object value)
+ throws EPolicyException {
+ boolean result;
+
+ // There is nothing to compare with!
+ if (value == null)
+ return false;
+
+ // XXX - Kanda: We need a better way of handling this!.
+ if (value instanceof String)
+ result = matchStringValue((String) value);
+ else if (value instanceof Integer)
+ result = matchIntegerValue((Integer) value);
+ else if (value instanceof Boolean)
+ result = matchBooleanValue((Boolean) value);
+ else if (value instanceof Vector)
+ result = matchVector((Vector<?>) value);
+ else if (value instanceof String[])
+ result = matchStringArray((String[]) value);
+ else
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_INVALID_ATTR_VALUE",
+ value.getClass().getName()));
+ return result;
+ }
+
+ private boolean matchStringValue(String givenVal)
+ throws EPolicyException {
+ boolean result;
+
+ switch (mOp) {
+ case OP_EQUAL:
+ if (hasWildCard)
+ result = (givenVal.indexOf(mPartialMatch) >= 0);
+ else
+ result = givenVal.equalsIgnoreCase(mVal);
+ break;
+
+ case OP_NEQUAL:
+ if (hasWildCard)
+ result = (givenVal.indexOf(mPartialMatch) < 0);
+ else
+ result = !givenVal.equalsIgnoreCase(mVal);
+ break;
+
+ case OP_LT:
+ result = (givenVal.compareTo(mVal) < 0);
+ break;
+
+ case OP_GT:
+ result = (givenVal.compareTo(mVal) > 0);
+ break;
+
+ case OP_GE:
+ result = (givenVal.compareTo(mVal) >= 0);
+ break;
+
+ case OP_LE:
+ result = (givenVal.compareTo(mVal) >= 0);
+ break;
+
+ default:
+ throw new AssertionException("Invalid operation code");
+ }
+ return result;
+ }
+
+ private boolean matchIntegerValue(Integer intVal)
+ throws EPolicyException {
+ boolean result;
+ int storedVal;
+ int givenVal = intVal.intValue();
+
+ try {
+ storedVal = new Integer(mVal).intValue();
+ } catch (Exception e) {
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_INVALID_ATTR_VALUE", mVal));
+
+ }
+ switch (mOp) {
+ case OP_EQUAL:
+ result = (givenVal == storedVal);
+ break;
+
+ case OP_NEQUAL:
+ result = (givenVal != storedVal);
+ break;
+
+ case OP_LT:
+ result = (givenVal < storedVal);
+ break;
+
+ case OP_GT:
+ result = (givenVal > storedVal);
+ break;
+
+ case OP_GE:
+ result = (givenVal >= storedVal);
+ break;
+
+ case OP_LE:
+ result = (givenVal >= storedVal);
+ break;
+
+ default:
+ throw new AssertionException("Invalid operation code");
+ }
+ return result;
+ }
+
+ private boolean matchBooleanValue(Boolean givenVal)
+ throws EPolicyException {
+ boolean result;
+ Boolean storedVal;
+
+ if (!(mVal.equalsIgnoreCase("true") || mVal.equalsIgnoreCase("false")))
+ throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_INVALID_ATTR_VALUE",
+ mVal));
+ storedVal = Boolean.valueOf(mVal);
+ switch (mOp) {
+ case OP_EQUAL:
+ result = (givenVal.equals(storedVal));
+ break;
+
+ case OP_NEQUAL:
+ case OP_LT:
+ case OP_GT:
+ case OP_GE:
+ case OP_LE:
+ result = (!givenVal.equals(storedVal));
+ break;
+
+ default:
+ throw new AssertionException("Invalid operation code");
+ }
+ return result;
+ }
+
+ public String toString() {
+ String op = null;
+
+ switch (mOp) {
+ case IExpression.OP_EQUAL:
+ op = IExpression.EQUAL_STR;
+ break;
+
+ case IExpression.OP_NEQUAL:
+ op = IExpression.NEQUAL_STR;
+ break;
+
+ case IExpression.OP_GT:
+ op = IExpression.GT_STR;
+ break;
+
+ case IExpression.OP_LT:
+ op = IExpression.LT_STR;
+ break;
+
+ case IExpression.OP_GE:
+ op = IExpression.GE_STR;
+ break;
+
+ case IExpression.OP_LE:
+ op = IExpression.LE_STR;
+ break;
+ }
+ if (mPfx != null && mPfx.length() > 0)
+ return mPfx + "." + mVar + " " + op + " " + mVal;
+ else
+ return mVar + " " + op + " " + mVal;
+ }
+
+ private static ExpressionComps parseForEquality(String expression) {
+ int index = expression.indexOf(IExpression.EQUAL_STR);
+
+ if (index < 0)
+ return null;
+ else {
+ String attr = expression.substring(0, index).trim();
+ int op = OP_EQUAL;
+ String val = expression.substring(index + 2).trim();
+
+ return new ExpressionComps(attr, op, val);
+ }
+ }
+
+ private static ExpressionComps parseForInEquality(String expression) {
+ int index = expression.indexOf(IExpression.NEQUAL_STR);
+
+ if (index < 0)
+ return null;
+ else {
+ String attr = expression.substring(0, index).trim();
+ int op = OP_NEQUAL;
+ String val = expression.substring(index + 2).trim();
+
+ return new ExpressionComps(attr, op, val);
+ }
+ }
+
+ private static ExpressionComps parseForGT(String expression) {
+ int index = expression.indexOf(IExpression.GT_STR);
+
+ if (index < 0)
+ return null;
+ else {
+ String attr = expression.substring(0, index).trim();
+ int op = OP_GT;
+ String val = expression.substring(index + 1).trim();
+
+ return new ExpressionComps(attr, op, val);
+ }
+ }
+
+ private static ExpressionComps parseForLT(String expression) {
+ int index = expression.indexOf(IExpression.LT_STR);
+
+ if (index < 0)
+ return null;
+ else {
+ String attr = expression.substring(0, index).trim();
+ int op = OP_LT;
+ String val = expression.substring(index + 1).trim();
+
+ return new ExpressionComps(attr, op, val);
+ }
+ }
+
+ private static ExpressionComps parseForGE(String expression) {
+ int index = expression.indexOf(IExpression.GE_STR);
+
+ if (index < 0)
+ return null;
+ else {
+ String attr = expression.substring(0, index).trim();
+ int op = OP_GE;
+ String val = expression.substring(index + 2).trim();
+
+ return new ExpressionComps(attr, op, val);
+ }
+ }
+
+ private static ExpressionComps parseForLE(String expression) {
+ int index = expression.indexOf(IExpression.LE_STR);
+
+ if (index < 0)
+ return null;
+ else {
+ String attr = expression.substring(0, index).trim();
+ int op = OP_LE;
+ String val = expression.substring(index + 2).trim();
+
+ return new ExpressionComps(attr, op, val);
+ }
+ }
+}
+
+class ExpressionComps {
+ String attr;
+ int op;
+ String val;
+
+ public ExpressionComps(String a, int o, String v) {
+ attr = a;
+ op = o;
+ val = v;
+ }
+
+ public String getAttr() {
+ return attr;
+ }
+
+ public int getOp() {
+ return op;
+ }
+
+ public String getVal() {
+ return val;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/profile/ProfileSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/profile/ProfileSubsystem.java
new file mode 100644
index 000000000..27e72352e
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/profile/ProfileSubsystem.java
@@ -0,0 +1,329 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.profile;
+
+import java.io.File;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.registry.IPluginInfo;
+import com.netscape.certsrv.registry.IPluginRegistry;
+
+public class ProfileSubsystem implements IProfileSubsystem {
+ private static final String PROP_LIST = "list";
+ private static final String PROP_CLASS_ID = "class_id";
+ private static final String PROP_CONFIG = "config";
+ private static final String PROP_CHECK_OWNER = "checkOwner";
+
+ private static final String PROP_ENABLE = "enable";
+ private static final String PROP_ENABLE_BY = "enableBy";
+
+ private IConfigStore mConfig = null;
+ @SuppressWarnings("unused")
+ private ISubsystem mOwner;
+ private Vector<String> mProfileIds = new Vector<String>();
+ private Hashtable<String, IProfile> mProfiles = new Hashtable<String, IProfile>();
+ private Hashtable<String, String> mProfileClassIds = new Hashtable<String, String>();
+
+ /**
+ * Retrieves the name of this subsystem.
+ */
+ public String getId() {
+ return null;
+ }
+
+ /**
+ * Sets specific to this subsystem.
+ */
+ public void setId(String id) throws EBaseException {
+ }
+
+ /**
+ * Initializes this subsystem with the given configuration
+ * store.
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration store
+ * @exception EBaseException failed to initialize
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ CMS.debug("ProfileSubsystem: start init");
+ IPluginRegistry registry = (IPluginRegistry)
+ CMS.getSubsystem(CMS.SUBSYSTEM_REGISTRY);
+
+ mConfig = config;
+ mOwner = owner;
+
+ // Configuration File Format:
+ // *.list=profile1,profile2
+ // *.profile1.class=com.netscape.cms.profile.common.BasicProfile
+ // *.profile1.config=config/profiles/profile1.cfg
+ // *.profile2.class=com.netscape.cms.profile.common.BasicProfile
+ // *.profile2.config=config/profiles/profile2.cfg
+
+ // read profile id, implementation, and its configuration files
+ String ids = config.getString(PROP_LIST, "");
+ StringTokenizer st = new StringTokenizer(ids, ",");
+
+ while (st.hasMoreTokens()) {
+ String id = st.nextToken();
+ IConfigStore subStore = config.getSubStore(id);
+ String classid = subStore.getString(PROP_CLASS_ID);
+ IPluginInfo info = registry.getPluginInfo("profile", classid);
+ if (info == null) {
+ throw new EBaseException("No plugins for type : profile, with id " + classid);
+ }
+ String configPath = subStore.getString(PROP_CONFIG);
+
+ CMS.debug("Start Profile Creation - " + id + " " + classid + " " + info.getClassName());
+ createProfile(id, classid, info.getClassName(),
+ configPath);
+
+ CMS.debug("Done Profile Creation - " + id);
+ }
+
+ Enumeration<String> ee = getProfileIds();
+
+ while (ee.hasMoreElements()) {
+ String id = ee.nextElement();
+
+ CMS.debug("Registered Confirmation - " + id);
+ }
+ }
+
+ /**
+ * Creates a profile instance.
+ */
+ public IProfile createProfile(String id, String classid, String className,
+ String configPath)
+ throws EProfileException {
+ IProfile profile = null;
+
+ try {
+ profile = (IProfile) Class.forName(className).newInstance();
+ IConfigStore subStoreConfig = CMS.createFileConfigStore(configPath);
+
+ CMS.debug("ProfileSubsystem: initing " + className);
+ profile.setId(id);
+ profile.init(this, subStoreConfig);
+ mProfileIds.addElement(id);
+ mProfiles.put(id, profile);
+ mProfileClassIds.put(id, classid);
+ return profile;
+ } catch (Exception e) {
+ // throw exceptions
+ CMS.debug(e.toString());
+ CMS.debug(e);
+ }
+ return null;
+ }
+
+ public void deleteProfile(String id, String configPath) throws EProfileException {
+
+ if (isProfileEnable(id)) {
+ throw new EProfileException("CMS_PROFILE_DELETE_ENABLEPROFILE");
+ }
+
+ String ids = "";
+ try {
+ ids = mConfig.getString(PROP_LIST, "");
+ } catch (Exception e) {
+ }
+
+ StringTokenizer tokenizer = new StringTokenizer(ids, ",");
+ StringBuffer list = new StringBuffer();
+
+ while (tokenizer.hasMoreTokens()) {
+ String element = tokenizer.nextToken();
+
+ if (!element.equals(id)) {
+ list.append(element + ",");
+ }
+ }
+ if (list.length() != 0)
+ list.deleteCharAt(list.length() - 1);
+
+ mConfig.putString(PROP_LIST, list.toString());
+ mConfig.removeSubStore(id);
+ File file1 = new File(configPath);
+
+ if (!file1.delete()) {
+ CMS.debug("ProfileSubsystem: deleteProfile: Cannot delete the configuration file : " + configPath);
+ }
+ mProfileIds.removeElement(id);
+ mProfiles.remove(id);
+ mProfileClassIds.remove(id);
+ try {
+ CMS.getConfigStore().commit(false);
+ } catch (Exception e) {
+ }
+ }
+
+ public void createProfileConfig(String id, String classId,
+ String configPath)
+ throws EProfileException {
+ try {
+ if (mProfiles.size() > 0) {
+ mConfig.putString(PROP_LIST,
+ mConfig.getString(PROP_LIST) + "," + id);
+ } else {
+ mConfig.putString(PROP_LIST, id);
+ }
+ mConfig.putString(id + "." + PROP_CLASS_ID, classId);
+ mConfig.putString(id + "." + PROP_CONFIG, configPath);
+ CMS.getConfigStore().commit(true);
+ } catch (EBaseException e) {
+ CMS.debug(e.toString());
+ }
+ }
+
+ /**
+ * Notifies this subsystem if owner is in running mode.
+ */
+ public void startup() throws EBaseException {
+ CMS.debug("ProfileSubsystem: startup");
+ }
+
+ /**
+ * Stops this system. The owner may call shutdown
+ * anytime after initialization.
+ * <P>
+ */
+ public void shutdown() {
+ mProfileIds.clear();
+ mProfiles.clear();
+ mProfileClassIds.clear();
+ }
+
+ /**
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Adds a profile.
+ */
+ public void addProfile(String id, IProfile profile)
+ throws EProfileException {
+ }
+
+ public boolean isProfileEnable(String id) {
+ IProfile profile = mProfiles.get(id);
+ String enable = null;
+
+ try {
+ enable = profile.getConfigStore().getString(PROP_ENABLE);
+ } catch (EBaseException e) {
+ }
+ if (enable == null || enable.equals("false"))
+ return false;
+ else
+ return true;
+ }
+
+ public String getProfileEnableBy(String id) {
+ if (!isProfileEnable(id))
+ return null;
+ IProfile profile = mProfiles.get(id);
+ String enableBy = null;
+
+ try {
+ enableBy = profile.getConfigStore().getString(PROP_ENABLE_BY);
+ } catch (EBaseException e) {
+ }
+ return enableBy;
+ }
+
+ /**
+ * Enables a profile for execution.
+ */
+ public void enableProfile(String id, String enableBy)
+ throws EProfileException {
+ IProfile profile = mProfiles.get(id);
+
+ profile.getConfigStore().putString(PROP_ENABLE, "true");
+ profile.getConfigStore().putString(PROP_ENABLE_BY, enableBy);
+ try {
+ profile.getConfigStore().commit(false);
+ } catch (EBaseException e) {
+ }
+ }
+
+ /**
+ * Disables a profile for execution.
+ */
+ public void disableProfile(String id)
+ throws EProfileException {
+ IProfile profile = mProfiles.get(id);
+
+ profile.getConfigStore().putString(PROP_ENABLE, "false");
+ try {
+ profile.getConfigStore().commit(false);
+ } catch (EBaseException e) {
+ }
+ }
+
+ /**
+ * Retrieves a profile by id.
+ */
+ public IProfile getProfile(String id)
+ throws EProfileException {
+ return mProfiles.get(id);
+ }
+
+ public String getProfileClassId(String id) {
+ return mProfileClassIds.get(id);
+ }
+
+ /**
+ * Retrieves a list of profile ids. The return
+ * list is of type String.
+ */
+ public Enumeration<String> getProfileIds() {
+ return mProfileIds.elements();
+ }
+
+ /**
+ * Checks if owner id should be enforced during profile approval.
+ *
+ * @return true if approval should be checked
+ */
+ public boolean checkOwner() {
+ try {
+ return mConfig.getBoolean(PROP_CHECK_OWNER, false);
+ } catch (EBaseException e) {
+ return false;
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/realm/ACL.java b/base/server/cmscore/src/com/netscape/cmscore/realm/ACL.java
new file mode 100644
index 000000000..13fcdac44
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/realm/ACL.java
@@ -0,0 +1,193 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.realm;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * A class represents an access control list (ACL). An ACL
+ * is associated with an protected resources. The policy
+ * enforcer can verify the ACLs with the current
+ * context to see if the corresponding resource is accessible.
+ * <P>
+ * An <code>ACL</code> may contain one or more <code>ACLEntry</code>. However, in case of multiple <code>ACLEntry</code>
+ * , a subject must pass ALL of the <code>ACLEntry</code> evaluation for permission to be granted
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class ACL {
+
+ /**
+ *
+ */
+
+ protected Vector<ACLEntry> entries = new Vector<ACLEntry>(); // ACL entries
+ protected Vector<String> rights = null; // possible rights entries
+ protected String resourceACLs = null; // exact resourceACLs string on ldap server
+ protected String name = null; // resource name
+ protected String description = null; // resource description
+
+ /**
+ * Class constructor.
+ */
+ public ACL() {
+ }
+
+ /**
+ * Class constructor.
+ * Constructs an access control list associated
+ * with a resource name
+ *
+ * @param name resource name
+ * @param rights applicable rights defined for this resource
+ * @param resourceACLs the entire ACL specification. For example:
+ * "certServer.log.configuration:read,modify:
+ * allow (read,modify)
+ * group=\"Administrators\":
+ * Allow administrators to read and modify log
+ * configuration"
+ */
+ public ACL(String name, Vector<String> rights, String resourceACLs) {
+ setName(name);
+ if (rights != null) {
+ this.rights = rights;
+ } else {
+ this.rights = new Vector<String>();
+ }
+ this.resourceACLs = resourceACLs;
+
+ }
+
+ /**
+ * Sets the name of the resource governed by this
+ * access control.
+ *
+ * @param name name of the resource
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Retrieves the name of the resource governed by
+ * this access control.
+ *
+ * @return name of the resource
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Retrieves the exact string of the resourceACLs
+ *
+ * @return resource's acl
+ */
+ public String getResourceACLs() {
+ return resourceACLs;
+ }
+
+ /**
+ * Sets the description of the resource governed by this
+ * access control.
+ *
+ * @param description Description of the protected resource
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * Retrieves the description of the resource governed by
+ * this access control.
+ *
+ * @return Description of the protected resource
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Adds an ACL entry to this list.
+ *
+ * @param entry the <code>ACLEntry</code> to be added to this resource
+ */
+ public void addEntry(ACLEntry entry) {
+ entries.addElement(entry);
+ }
+
+ /**
+ * Returns ACL entries.
+ *
+ * @return enumeration for the <code>ACLEntry</code> vector
+ */
+ public Enumeration<ACLEntry> entries() {
+ return entries.elements();
+ }
+
+ /**
+ * Returns the string reprsentation.
+ *
+ * @return the string representation of the ACL entries in the
+ * following format:
+ * <resource name>[<ACLEntry1>,<ACLEntry 2>,...<ACLEntry N>]
+ */
+ public String toString() {
+ StringBuilder entries = new StringBuilder();
+ Enumeration<ACLEntry> e = entries();
+
+ for (; e.hasMoreElements();) {
+ ACLEntry entry = e.nextElement();
+
+ entries.append(entry);
+ if (e.hasMoreElements())
+ entries.append(",");
+ }
+ return getName() + "[" + entries + "]";
+ }
+
+ /**
+ * Adds an rights entry to this list.
+ *
+ * @param right The right to be added for this ACL
+ */
+ public void addRight(String right) {
+ rights.addElement(right);
+ }
+
+ /**
+ * Tells if the permission is one of the defined "rights"
+ *
+ * @param permission permission to be checked
+ * @return true if it's one of the "rights"; false otherwise
+ */
+ public boolean checkRight(String permission) {
+ return (rights.contains(permission));
+ }
+
+ /**
+ * Returns rights entries.
+ *
+ * @return enumeration of rights defined for this ACL
+ */
+ public Enumeration<String> rights() {
+ return rights.elements();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/realm/ACLEntry.java b/base/server/cmscore/src/com/netscape/cmscore/realm/ACLEntry.java
new file mode 100644
index 000000000..1e13ad682
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/realm/ACLEntry.java
@@ -0,0 +1,243 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.realm;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+/**
+ * A class represents an ACI entry of an access control list.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class ACLEntry {
+ /**
+ *
+ */
+ protected Hashtable<String, String> mPerms = new Hashtable<String, String>();
+ protected String expressions = null;
+ protected boolean negative = false;
+ protected String ACLEntryString = null;
+
+ /**
+ * Class Constructor
+ */
+ public ACLEntry() {
+ }
+
+ /**
+ * Checks if this ACL entry is set to negative.
+ *
+ * @return true if this ACL entry expression is for "deny";
+ * false if this ACL entry expression is for "allow"
+ */
+ public boolean isNegative() {
+ return negative;
+ }
+
+ /**
+ * Sets this ACL entry negative. This ACL entry expression is for "deny".
+ */
+ public void setNegative() {
+ negative = true;
+ }
+
+ /**
+ * Sets the ACL entry string
+ *
+ * @param s string in the following format:
+ *
+ * <PRE>
+ * allow|deny (right[,right...]) attribute_expression
+ * </PRE>
+ */
+ public void setACLEntryString(String s) {
+ ACLEntryString = s;
+ }
+
+ /**
+ * Gets the ACL Entry String
+ *
+ * @return ACL Entry string in the following format:
+ *
+ * <PRE>
+ * allow|deny (right[,right...]) attribute_expression
+ * </PRE>
+ */
+ public String getACLEntryString() {
+ return ACLEntryString;
+ }
+
+ /**
+ * Adds permission to this entry. Permission must be one of the
+ * "rights" defined for each protected resource in its ACL
+ *
+ * @param acl the acl instance that this aclEntry is associated with
+ * @param permission one of the "rights" defined for each
+ * protected resource in its ACL
+ */
+ public void addPermission(ACL acl, String permission) {
+ if (acl.checkRight(permission) == true) {
+ mPerms.put(permission, permission);
+ } else {
+ // not a valid right...log it later
+ }
+ }
+
+ /**
+ * Returns a list of permissions associated with
+ * this entry.
+ *
+ * @return a list of permissions for this ACL entry
+ */
+ public Enumeration<String> permissions() {
+ return mPerms.elements();
+ }
+
+ /**
+ * Sets the expression associated with this entry.
+ *
+ * @param expressions the evaluator expressions. For example,
+ * group="Administrators"
+ */
+ public void setAttributeExpressions(String expressions) {
+ this.expressions = expressions;
+ }
+
+ /**
+ * Retrieves the expression associated with this entry.
+ *
+ * @return the evaluator expressions. For example,
+ * group="Administrators"
+ */
+ public String getAttributeExpressions() {
+ return expressions;
+ }
+
+ /**
+ * Checks to see if this <code>ACLEntry</code> contains a
+ * particular permission
+ *
+ * @param permission one of the "rights" defined for each
+ * protected resource in its ACL
+ * @return true if permission contained in the permission list
+ * for this <code>ACLEntry</code>; false otherwise.
+ */
+ public boolean containPermission(String permission) {
+ return (mPerms.get(permission) != null);
+ }
+
+ /**
+ * Checks if this entry has the given permission.
+ *
+ * @param permission one of the "rights" defined for each
+ * protected resource in its ACL
+ * @return true if the permission is allowed; false if the
+ * permission is denied. If a permission is not
+ * recognized by this ACL, it is considered denied
+ */
+ public boolean checkPermission(String permission) {
+ // default - if we dont know about the requested permission,
+ // don't grant permission
+ if (mPerms.get(permission) == null)
+ return false;
+ if (isNegative()) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Parse string in the following format:
+ *
+ * <PRE>
+ * allow|deny (right[,right...]) attribute_expression
+ * </PRE>
+ *
+ * into an instance of the <code>ACLEntry</code> class
+ *
+ * @param acl the acl instance associated with this aclentry
+ * @param aclEntryString aclEntryString in the specified format
+ * @return an instance of the <code>ACLEntry</code> class
+ */
+ public static ACLEntry parseACLEntry(ACL acl, String aclEntryString) {
+ if (aclEntryString == null) {
+ return null;
+ }
+
+ String te = aclEntryString.trim();
+
+ // locate first space
+ int i = te.indexOf(' ');
+ // prefix should be "allowed" or "deny"
+ String prefix = te.substring(0, i);
+ String suffix = te.substring(i + 1).trim();
+ ACLEntry entry = new ACLEntry();
+
+ if (prefix.equals("allow")) {
+ // do nothing
+ } else if (prefix.equals("deny")) {
+ entry.setNegative();
+ } else {
+ return null;
+ }
+ // locate the second space
+ i = suffix.indexOf(' ');
+ // this prefix should be rights list, delimited by ","
+ prefix = suffix.substring(1, i - 1);
+ // the suffix is the rest, which is the "expressions"
+ suffix = suffix.substring(i + 1).trim();
+
+ StringTokenizer st = new StringTokenizer(prefix, ",");
+
+ for (; st.hasMoreTokens();) {
+ entry.addPermission(acl, st.nextToken());
+ }
+ entry.setAttributeExpressions(suffix);
+ return entry;
+ }
+
+ /**
+ * Returns the string representation of this ACLEntry
+ *
+ * @return string representation of this ACLEntry
+ */
+ public String toString() {
+ StringBuffer entry = new StringBuffer();
+
+ if (isNegative()) {
+ entry.append("deny (");
+ } else {
+ entry.append("allow (");
+ }
+ Enumeration<String> e = permissions();
+
+ for (; e.hasMoreElements();) {
+ String p = e.nextElement();
+
+ entry.append(p);
+ if (e.hasMoreElements())
+ entry.append(",");
+ }
+ entry.append(") " + getAttributeExpressions());
+ return entry.toString();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/registry/PluginInfo.java b/base/server/cmscore/src/com/netscape/cmscore/registry/PluginInfo.java
new file mode 100644
index 000000000..f9f734b72
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/registry/PluginInfo.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.registry;
+
+import java.util.Locale;
+
+import com.netscape.certsrv.registry.IPluginInfo;
+
+/**
+ * The plugin information includes id, name,
+ * classname, and description.
+ *
+ * @author thomask
+ */
+public class PluginInfo implements IPluginInfo {
+ private String mName = null;
+ private String mDesc = null;
+ private String mClassPath = null;
+
+ public PluginInfo(String name, String desc, String classPath) {
+ mName = name;
+ mDesc = desc;
+ mClassPath = classPath;
+ }
+
+ public String getName(Locale locale) {
+ return mName;
+ }
+
+ public String getDescription(Locale locale) {
+ return mDesc;
+ }
+
+ public String getClassName() {
+ return mClassPath;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/registry/PluginRegistry.java b/base/server/cmscore/src/com/netscape/cmscore/registry/PluginRegistry.java
new file mode 100644
index 000000000..4e3593411
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/registry/PluginRegistry.java
@@ -0,0 +1,294 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.registry;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.registry.ERegistryException;
+import com.netscape.certsrv.registry.IPluginInfo;
+import com.netscape.certsrv.registry.IPluginRegistry;
+
+public class PluginRegistry implements IPluginRegistry {
+
+ private static final String PROP_TYPES = "types";
+ private static final String PROP_IDS = "ids";
+ private static final String PROP_NAME = "name";
+ private static final String PROP_DESC = "desc";
+ private static final String PROP_CLASSPATH = "class";
+ private static final String PROP_FILE = "file";
+
+ private IConfigStore mConfig = null;
+ private IConfigStore mFileConfig = null;
+ @SuppressWarnings("unused")
+ private ISubsystem mOwner;
+ private Hashtable<String, Hashtable<String, IPluginInfo>> mTypes =
+ new Hashtable<String, Hashtable<String, IPluginInfo>>();
+
+ public PluginRegistry() {
+ }
+
+ /**
+ * Retrieves the name of this subsystem.
+ */
+ public String getId() {
+ return null;
+ }
+
+ /**
+ * Sets specific to this subsystem.
+ */
+ public void setId(String id) throws EBaseException {
+ }
+
+ /**
+ * Initializes this subsystem with the given configuration
+ * store.
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration store
+ * @exception EBaseException failed to initialize
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ CMS.debug("RegistrySubsystem: start init");
+ mConfig = config;
+ mOwner = owner;
+
+ mFileConfig = CMS.createFileConfigStore(
+ mConfig.getString(PROP_FILE));
+
+ String types_str = null;
+
+ try {
+ types_str = mFileConfig.getString(PROP_TYPES, null);
+ } catch (EBaseException e) {
+ }
+ if (types_str == null) {
+ CMS.debug("PluginRegistry: no types");
+ return;
+ }
+ StringTokenizer st = new StringTokenizer(types_str, ",");
+
+ while (st.hasMoreTokens()) {
+ String type = st.nextToken();
+
+ loadPlugins(config, type);
+ }
+ }
+
+ /**
+ * Load plugins of the given type.
+ */
+ public void loadPlugins(IConfigStore config, String type)
+ throws EBaseException {
+ String ids_str = null;
+
+ try {
+ ids_str = mFileConfig.getString(type + "." + PROP_IDS, null);
+ } catch (EBaseException e) {
+ }
+ if (ids_str == null) {
+ return;
+ }
+ StringTokenizer st = new StringTokenizer(ids_str, ",");
+
+ while (st.hasMoreTokens()) {
+ String id = st.nextToken();
+
+ loadPlugin(config, type, id);
+ }
+ }
+
+ public IPluginInfo createPluginInfo(String name, String desc, String classPath) {
+ return new PluginInfo(name, desc, classPath);
+ }
+
+ /**
+ * Load plugins of the given type.
+ */
+ public void loadPlugin(IConfigStore config, String type, String id)
+ throws EBaseException {
+ String name = null;
+
+ try {
+ name = mFileConfig.getString(type + "." + id + "." + PROP_NAME, null);
+ } catch (EBaseException e) {
+ }
+ String desc = null;
+
+ try {
+ desc = mFileConfig.getString(type + "." + id + "." + PROP_DESC, null);
+ } catch (EBaseException e) {
+ }
+ String classpath = null;
+
+ try {
+ classpath = mFileConfig.getString(type + "." + id + "." + PROP_CLASSPATH,
+ null);
+ } catch (EBaseException e) {
+ }
+ PluginInfo info = new PluginInfo(name, desc, classpath);
+
+ addPluginInfo(type, id, info, 0);
+ }
+
+ public void removePluginInfo(String type, String id)
+ throws ERegistryException {
+ Hashtable<String, IPluginInfo> plugins = mTypes.get(type);
+ if (plugins == null)
+ return;
+ plugins.remove(id);
+ Locale locale = Locale.getDefault();
+ rebuildConfigStore(locale);
+ }
+
+ public void addPluginInfo(String type, String id, IPluginInfo info)
+ throws ERegistryException {
+ addPluginInfo(type, id, info, 1);
+ }
+
+ public void addPluginInfo(String type, String id, IPluginInfo info, int saveConfig)
+ throws ERegistryException {
+ Hashtable<String, IPluginInfo> plugins = mTypes.get(type);
+
+ if (plugins == null) {
+ plugins = new Hashtable<String, IPluginInfo>();
+ mTypes.put(type, plugins);
+ }
+ Locale locale = Locale.getDefault();
+
+ CMS.debug("added plugin " + type + " " + id + " " +
+ info.getName(locale) + " " + info.getDescription(locale) + " " +
+ info.getClassName());
+ plugins.put(id, info);
+
+ // rebuild configuration store
+ if (saveConfig == 1)
+ rebuildConfigStore(locale);
+ }
+
+ public void rebuildConfigStore(Locale locale)
+ throws ERegistryException {
+ Enumeration<String> types = mTypes.keys();
+ StringBuffer typesBuf = new StringBuffer();
+
+ while (types.hasMoreElements()) {
+ String type = types.nextElement();
+
+ typesBuf.append(type);
+ if (types.hasMoreElements()) {
+ typesBuf.append(",");
+ }
+ Hashtable<String, IPluginInfo> mPlugins = mTypes.get(type);
+ StringBuffer idsBuf = new StringBuffer();
+ Enumeration<String> plugins = mPlugins.keys();
+
+ while (plugins.hasMoreElements()) {
+ String id = plugins.nextElement();
+
+ idsBuf.append(id);
+ if (plugins.hasMoreElements()) {
+ idsBuf.append(",");
+ }
+ IPluginInfo plugin = mPlugins.get(id);
+
+ mFileConfig.putString(type + "." + id + ".class",
+ plugin.getClassName());
+ mFileConfig.putString(type + "." + id + ".name",
+ plugin.getName(locale));
+ mFileConfig.putString(type + "." + id + ".desc",
+ plugin.getDescription(locale));
+ }
+ mFileConfig.putString(type + ".ids", idsBuf.toString());
+ }
+ mFileConfig.putString("types", typesBuf.toString());
+ try {
+ mFileConfig.commit(false);
+ } catch (EBaseException e) {
+ CMS.debug("PluginRegistry: failed to commit registry.cfg");
+ }
+ }
+
+ /**
+ * Notifies this subsystem if owner is in running mode.
+ */
+ public void startup() throws EBaseException {
+ CMS.debug("RegistrySubsystem: startup");
+ }
+
+ /**
+ * Stops this system. The owner may call shutdown
+ * anytime after initialization.
+ * <P>
+ */
+ public void shutdown() {
+ mTypes.clear();
+ }
+
+ /**
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public IConfigStore getFileConfigStore() {
+ return mFileConfig;
+ }
+
+ /**
+ * Returns all type names.
+ */
+ public Enumeration<String> getTypeNames() {
+ return mTypes.keys();
+ }
+
+ /**
+ * Returns a list of identifiers of the given type.
+ */
+ public Enumeration<String> getIds(String type) {
+ Hashtable<String, IPluginInfo> plugins = mTypes.get(type);
+
+ if (plugins == null)
+ return null;
+ return plugins.keys();
+ }
+
+ /**
+ * Retrieves the plugin information.
+ */
+ public IPluginInfo getPluginInfo(String type, String id) {
+ Hashtable<String, IPluginInfo> plugins = mTypes.get(type);
+
+ if (plugins == null)
+ return null;
+ return plugins.get(id);
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/request/ARequestQueue.java b/base/server/cmscore/src/com/netscape/cmscore/request/ARequestQueue.java
new file mode 100644
index 000000000..446c3b18d
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/request/ARequestQueue.java
@@ -0,0 +1,1581 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CRLException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Set;
+import java.util.Vector;
+
+import netscape.security.util.DerInputStream;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509ExtensionException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IAttrSet;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.AgentApprovals;
+import com.netscape.certsrv.request.IEnrollmentRequest;
+import com.netscape.certsrv.request.INotify;
+import com.netscape.certsrv.request.IPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestList;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.IRequestScheduler;
+import com.netscape.certsrv.request.IService;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+
+/**
+ * The ARequestQueue class is an abstract class that implements
+ * most portions of the IRequestQueue interface. This includes
+ * the state engine as defined for processing IRequest objects.
+ * <p>
+ * !Put state machine description here!
+ * <p>
+ * This class defines several abstract protected functions that need to be defined by the concrete implementation. In
+ * particular, this class does not implement the operations for storing requests persistantly.
+ * <p>
+ * This class also provides several accessor functions for setting fields in the IRequest object. These functions are
+ * provided as an aid to saving and restoring the state in the database.
+ * <p>
+ * This class also implements the locking operations specified by the IRequestQueue interface.
+ * <p>
+ *
+ * @author thayes
+ * @version $Revision$ $Date$
+ */
+public abstract class ARequestQueue
+ implements IRequestQueue {
+
+ /**
+ * global request version for tracking request changes.
+ */
+ public final static String REQUEST_VERSION = "1.0.0";
+
+ /**
+ * Create a new (unique) RequestId. (abstract)
+ * <p>
+ * This method must be implemented by the specialized class to generate a new id from data in the persistant store.
+ * This id is used to create a new request object.
+ * <p>
+ *
+ * @return
+ * a new RequestId object.
+ * @exception EBaseException
+ * indicates that creation of the new id could not be completed.
+ * @see RequestId
+ */
+ protected abstract RequestId newRequestId()
+ throws EBaseException;
+
+ /**
+ * Read a request from the persistant store. (abstract)
+ * <p>
+ * This function is called to create the in-memory version of a request object.
+ * <p>
+ * The implementation of this object can use the createRequest member function to create a new instance of an
+ * IRequest, and use the setRequestStatus, setCreationTime and setModificationTime functions to set those values.
+ * <p>
+ *
+ * @param id
+ * the id of the request to read.
+ * @return
+ * a new IRequest object. null is returned if the object cannot
+ * be located.
+ * @exception EBaseException
+ * TODO: this is not implemented yet
+ * @see #createRequest
+ * @see #setRequestStatus
+ * @see #setModificationTime
+ * @see #setCreationTime
+ */
+ protected abstract IRequest readRequest(RequestId id);
+
+ /**
+ * Add the request to the store. (abstract)
+ * <p>
+ * This function is called when a new request immediately after creating a new request.
+ * <p>
+ *
+ * @param request
+ * the request to add.
+ * @exception EBaseException
+ * TODO: this is not implemented yet
+ */
+ protected abstract void addRequest(IRequest request) throws EBaseException;
+
+ /**
+ * Modify the request in the store. (abstract)
+ * <p>
+ * Update the persistant copy of this request with the current values in the object.
+ * <p>
+ * Currently there are no hints for what has changed, so the entire request should be updated.
+ * <p>
+ *
+ * @param request
+ * @exception EBaseException
+ * TODO: this is not implemented yet
+ */
+ protected abstract void modifyRequest(IRequest request);
+
+ /**
+ * Get complete list of RequestId values found i this
+ * queue.
+ * <p>
+ * This method can form the basis for creating other types of search/list operations (although there are probably
+ * more efficient ways of doing this. ARequestQueue implements default versions of some of the searching by using
+ * this method as a basis.
+ * <p>
+ * TODO: return IRequestList -or- just use listRequests as the basic engine.
+ * <p>
+ *
+ * @return
+ * an Enumeration that generates RequestId objects.
+ */
+ abstract protected Enumeration<RequestId> getRawList();
+
+ /**
+ * protected access for setting the current state of a request.
+ * <p>
+ *
+ * @param request
+ * The request to be modified.
+ * @param status
+ * The new value for the request status.
+ */
+ protected final void setRequestStatus(IRequest request, RequestStatus status) {
+ Request r = (Request) request;
+
+ r.setRequestStatus(status);
+ }
+
+ /**
+ * protected access for setting the modification time of a request.
+ * <p>
+ *
+ * @param request
+ * The request to be modified.
+ * @param date
+ * The new value for the time.
+ */
+ protected final void setModificationTime(IRequest request, Date date) {
+ Request r = (Request) request;
+
+ r.mModificationTime = date;
+ }
+
+ /**
+ * protected access for setting the creation time of a request.
+ * <p>
+ *
+ * @param request
+ * The request to be modified.
+ * @param date
+ * The new value for the time.
+ */
+ protected final void setCreationTime(IRequest request, Date date) {
+ Request r = (Request) request;
+
+ r.mCreationTime = date;
+ }
+
+ /**
+ * protected access for creating a new Request object
+ * <p>
+ *
+ * @param id
+ * The identifier for the new request
+ * @return
+ * A new request object. The caller should fill in other data
+ * values from the datastore.
+ */
+ protected final IRequest createRequest(RequestId id, String requestType) {
+ Request r;
+
+ /*
+ * Determine the specialized class to create for this type
+ *
+ * TODO: this set of classes is an example only. The real set
+ * needs to be determined and implemented.
+ */
+ if (requestType != null && requestType.equals("enrollment")) {
+ r = new EnrollmentRequest(id);
+ } else {
+ r = new Request(id);
+ }
+
+ return r;
+ }
+
+ /**
+ * Implements IRequestQueue.newRequest
+ * <p>
+ *
+ * @see IRequestQueue#newRequest
+ */
+ public IRequest newRequest(String requestType)
+ throws EBaseException {
+ if (requestType == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_REQUEST_TYPE", "null"));
+ }
+ RequestId rId = newRequestId();
+ IRequest r = createRequest(rId, requestType);
+
+ // Commented out the lock call because unlock is never called.
+ // mTable.lock(rId);
+
+ // TODO: move this to the first update. This will require
+ // some state information to track the current state.
+ r.setRequestType(requestType);
+ r.setExtData(IRequest.REQ_VERSION, REQUEST_VERSION);
+
+ // NOT_UPDATED mean request is in memory and has
+ // not been serialized to database yet. An add
+ // operation is required to serialize a NOT_UPDATED
+ // request.
+ r.setExtData("dbStatus", "NOT_UPDATED");
+ // addRequest(r);
+
+ // expose requestId to policy so that it can be
+ // used with predicate
+ r.setExtData("requestId", rId.toString());
+
+ return r;
+ }
+
+ /**
+ * Implements IRequestQueue.cloneRequest
+ * <p>
+ *
+ * @see IRequestQueue#cloneRequest
+ */
+ public IRequest cloneRequest(IRequest r)
+ throws EBaseException {
+ // 1. check for valid state. (Are any invalid ?)
+ RequestStatus rs = r.getRequestStatus();
+
+ if (rs == RequestStatus.BEGIN)
+ throw new EBaseException("Invalid Status");
+
+ // 2. create new request
+ String reqType = r.getRequestType();
+ IRequest clone = newRequest(reqType);
+
+ // 3. copy all attributes of original request to clone and modify.
+ // source id (from remote authority) is not copied.
+ // TODO: set the original request id to some place in the request.
+ clone.copyContents(r);
+ // NOT_UPDATED mean request is in memory and has
+ // not been serialized to database yet. An add
+ // operation is required to serialize a NOT_UPDATED
+ // request.
+ clone.setExtData("dbStatus", "NOT_UPDATED");
+
+ return clone;
+ }
+
+ /**
+ * Implements IRequestQueue.findRequest
+ * <p>
+ *
+ * @see IRequestQueue#findRequest
+ */
+ public IRequest findRequest(RequestId id)
+ throws EBaseException {
+ IRequest r;
+
+ // mTable.lock(id);
+
+ r = readRequest(id);
+
+ // if (r == null) mTable.unlock(id);
+
+ return r;
+ }
+
+ private IRequestScheduler mRequestScheduler = null;
+
+ public void setRequestScheduler(IRequestScheduler scheduler) {
+ mRequestScheduler = scheduler;
+ }
+
+ public IRequestScheduler getRequestScheduler() {
+ return mRequestScheduler;
+ }
+
+ /**
+ * Implements IRequestQueue.processRequest
+ * <p>
+ *
+ * @see IRequestQueue#processRequest
+ */
+ public final void processRequest(IRequest r)
+ throws EBaseException {
+
+ // #610553 Thread Scheduler
+ IRequestScheduler scheduler = getRequestScheduler();
+
+ if (scheduler != null) {
+ scheduler.requestIn(r);
+ }
+
+ try {
+ // 1. Check for valid state
+ RequestStatus rs = r.getRequestStatus();
+
+ if (rs != RequestStatus.BEGIN)
+ throw new EBaseException("Invalid Status");
+
+ stateEngine(r);
+ } finally {
+ if (scheduler != null) {
+ scheduler.requestOut(r);
+ }
+ }
+ }
+
+ /**
+ * Implements IRequestQueue.markRequestPending
+ * <p>
+ *
+ * @see IRequestQueue#markRequestPending
+ */
+ public final void markRequestPending(IRequest r)
+ throws EBaseException {
+ // 1. Check for valid state
+ RequestStatus rs = r.getRequestStatus();
+
+ if (rs != RequestStatus.BEGIN)
+ throw new EBaseException("Invalid Status");
+
+ // 2. Change the request state. This method of making
+ // a request PENDING does NOT invoke the PENDING notifiers.
+ // To change this, just call stateEngine at the completion of this
+ // routine.
+ setRequestStatus(r, RequestStatus.PENDING);
+
+ updateRequest(r);
+ stateEngine(r);
+ }
+
+ /**
+ * Implements IRequestQueue.cloneAndMarkPending
+ * <p>
+ *
+ * @see IRequestQueue#cloneAndMarkPending
+ */
+ public IRequest cloneAndMarkPending(IRequest r)
+ throws EBaseException {
+ IRequest clone = cloneRequest(r);
+
+ markRequestPending(clone);
+ return clone;
+ }
+
+ /**
+ * Implements IRequestQueue.approveRequest
+ * <p>
+ *
+ * @see IRequestQueue#approveRequest
+ */
+ public final void approveRequest(IRequest r)
+ throws EBaseException {
+ // 1. Check for valid state
+ RequestStatus rs = r.getRequestStatus();
+
+ if (rs != RequestStatus.PENDING)
+ throw new EBaseException("Invalid Status");
+
+ AgentApprovals aas = AgentApprovals.fromStringVector(
+ r.getExtDataInStringVector(AgentApprovals.class.getName()));
+ if (aas == null) {
+ aas = new AgentApprovals();
+ }
+
+ // Record agent who did this
+ String agentName = getUserIdentity();
+
+ if (agentName == null)
+ throw new EBaseException("Missing agent information");
+
+ aas.addApproval(agentName);
+ r.setExtData(AgentApprovals.class.getName(), aas.toStringVector());
+
+ PolicyResult pr = mPolicy.apply(r);
+
+ if (pr == PolicyResult.ACCEPTED) {
+ setRequestStatus(r, RequestStatus.APPROVED);
+ } else if (pr == PolicyResult.DEFERRED ||
+ pr == PolicyResult.REJECTED) {
+ }
+
+ // Always update. The policy code may have made changes to the
+ // request that we want to keep.
+ updateRequest(r);
+
+ stateEngine(r);
+ }
+
+ /**
+ * Implements IRequestQueue.rejectRequest
+ * <p>
+ *
+ * @see IRequestQueue#rejectRequest
+ */
+ public final void rejectRequest(IRequest r)
+ throws EBaseException {
+ // 1. Check for valid state
+ RequestStatus rs = r.getRequestStatus();
+
+ if (rs != RequestStatus.PENDING)
+ throw new EBaseException("Invalid Status");
+
+ // 2. Change state
+ setRequestStatus(r, RequestStatus.REJECTED);
+ updateRequest(r);
+
+ // 3. Continue processing
+ stateEngine(r); // does nothing
+ }
+
+ /**
+ * Implments IRequestQueue.cancelRequest
+ * <p>
+ *
+ * @see IRequestQueue#cancelRequest
+ */
+ public final void cancelRequest(IRequest r)
+ throws EBaseException {
+ setRequestStatus(r, RequestStatus.CANCELED);
+ updateRequest(r);
+
+ stateEngine(r);
+
+ return;
+ }
+
+ /**
+ * caller must lock request and release request
+ */
+ public final void markAsServiced(IRequest r) {
+ setRequestStatus(r, RequestStatus.COMPLETE);
+ updateRequest(r);
+
+ if (mNotify != null)
+ mNotify.notify(r);
+
+ return;
+ }
+
+ /**
+ * Implements IRequestQueue.listRequests
+ * <p>
+ * Should be overridden by the specialized class if a more efficient method is available for implementing this
+ * operation.
+ * <P>
+ *
+ * @see IRequestQueue#listRequests
+ */
+ public IRequestList listRequests() {
+ return new RequestList(getRawList());
+ }
+
+ /**
+ * Implements IRequestQueue.listRequestsByStatus
+ * <p>
+ * Should be overridden by the specialized class if a more efficient method is available for implementing this
+ * operation.
+ * <P>
+ *
+ * @see IRequestQueue#listRequestsByStatus
+ */
+ public IRequestList listRequestsByStatus(RequestStatus s) {
+ return new RequestListByStatus(getRawList(), s, this);
+ }
+
+ /**
+ * Implements IRequestQueue.releaseRequest
+ * <p>
+ *
+ * @see IRequestQueue#releaseRequest
+ */
+ public final void releaseRequest(IRequest request) {
+ // mTable.unlock(request.getRequestId());
+ }
+
+ public void updateRequest(IRequest r) {
+ ((Request) r).mModificationTime = CMS.getCurrentDate();
+
+ String name = getUserIdentity();
+
+ if (name != null)
+ r.setExtData(IRequest.UPDATED_BY, name);
+
+ // TODO: use a state flag to determine whether to call
+ // addRequest or modifyRequest (see newRequest as well)
+ modifyRequest(r);
+ }
+
+ // PRIVATE functions
+
+ private final void stateEngine(IRequest r)
+ throws EBaseException {
+ boolean complete = false;
+
+ while (!complete) {
+ RequestStatus rs = r.getRequestStatus();
+
+ if (rs == RequestStatus.BEGIN) {
+ PolicyResult pr = PolicyResult.ACCEPTED;
+
+ if (mPolicy != null)
+ pr = mPolicy.apply(r);
+
+ if (pr == PolicyResult.ACCEPTED) {
+ setRequestStatus(r, RequestStatus.APPROVED);
+ } else if (pr == PolicyResult.DEFERRED) {
+ setRequestStatus(r, RequestStatus.PENDING);
+ } else {
+ setRequestStatus(r, RequestStatus.REJECTED);
+ }
+
+ // if policy accepts the request, the request
+ // will be processed right away. So speed up
+ // the request processing, we do not want to
+ // have too many db operation.
+ if (pr != PolicyResult.ACCEPTED) {
+ updateRequest(r);
+ }
+ } else if (rs == RequestStatus.PENDING) {
+ if (mPendingNotify != null)
+ mPendingNotify.notify(r);
+
+ complete = true;
+ } else if (rs == RequestStatus.APPROVED) {
+ boolean svcComplete;
+
+ svcComplete = mService.serviceRequest(r);
+
+ // Completed requests call the notifier and are done. Others
+ // wait for the serviceComplete call.
+ if (svcComplete) {
+ setRequestStatus(r, RequestStatus.COMPLETE);
+ } else {
+ setRequestStatus(r, RequestStatus.SVC_PENDING);
+ }
+
+ updateRequest(r);
+ } else if (rs == RequestStatus.SVC_PENDING) {
+ complete = true;
+ } else if (rs == RequestStatus.CANCELED) {
+ if (mNotify != null)
+ mNotify.notify(r);
+
+ complete = true;
+ } else if (rs == RequestStatus.REJECTED) {
+ if (mNotify != null)
+ mNotify.notify(r);
+
+ complete = true;
+ } else if (rs == RequestStatus.COMPLETE) {
+ if (mNotify != null)
+ mNotify.notify(r);
+
+ complete = true;
+ }
+ }
+ }
+
+ /**
+ * log a change in the request status
+ */
+ protected void logChange(IRequest request) {
+ // write the queue name and request id
+ // write who changed it
+ // write what change (which state change) was made
+ // - new (processRequest)
+ // - approve
+ // - reject
+
+ // Ordering
+ // - make change in memory
+ // - log change and result
+ // - update record
+ }
+
+ /**
+ * get the identity of the current user
+ */
+ protected String getUserIdentity() {
+ // Record agent who did this
+ SessionContext s = SessionContext.getContext();
+ String name = (String) s.get(SessionContext.USER_ID);
+
+ return name;
+ }
+
+ /**
+ * New non-blocking recover method.
+ */
+ public void recover() {
+ if (CMS.isRunningMode()) {
+ RecoverThread t = new RecoverThread(this);
+
+ t.start();
+ }
+ }
+
+ /**
+ * recover from a crash. Resends all requests that are in
+ * the APPROVED state.
+ */
+ public void recoverWillBlock() {
+ // Get a list of all requests that are APPROVED
+ IRequestList list = listRequestsByStatus(RequestStatus.APPROVED);
+
+ while (list != null && list.hasMoreElements()) {
+ RequestId rid = list.nextRequestId();
+ IRequest request;
+
+ try {
+ request = findRequest(rid);
+
+ //if (request == null) log_error
+
+ // Recheck the status - should be the same!!
+ if (request.getRequestStatus() == RequestStatus.APPROVED) {
+ stateEngine(request);
+ }
+
+ releaseRequest(request);
+ } catch (EBaseException e) {
+ // log
+ }
+ }
+ }
+
+ public INotify getPendingNotify() {
+ return mPendingNotify;
+ }
+
+ // Constructor
+ protected ARequestQueue(IPolicy policy, IService service, INotify notify,
+ INotify pendingNotify) {
+ mPolicy = policy;
+ mService = service;
+ mNotify = notify;
+ mPendingNotify = pendingNotify;
+
+ mLogger = CMS.getLogger();
+ }
+
+ // Instance variables
+ // RequestIDTable mTable = new RequestIDTable();
+
+ IPolicy mPolicy;
+ IService mService;
+ INotify mNotify;
+ INotify mPendingNotify;
+
+ protected ILogger mLogger;
+}
+
+//
+// Table of RequestId values that are currently in use by some thread.
+// The fact that the request is in this table constitutes a lock
+// on the value.
+//
+/*
+ class RequestIDTable {
+ public synchronized void lock(RequestId id) {
+ while (true) {
+ if (mHashtable.put(id, id) == null)
+ break;
+
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ };
+ }
+ }
+
+ public synchronized void unlock(RequestId id) {
+ mHashtable.remove(id);
+
+ notifyAll();
+ }
+
+ // instance variables
+ Hashtable mHashtable = new Hashtable();
+ }
+ */
+
+//
+// Request - implementation of the IRequest interface. This
+// version is returned by ARequestQueue (and its derivatives)
+//
+class Request implements IRequest {
+
+ private static final long serialVersionUID = -1510479502681392568L;
+
+ // IRequest.getRequestId
+ public RequestId getRequestId() {
+ return mRequestId;
+ }
+
+ // IRequest.getRequestStatus
+ public RequestStatus getRequestStatus() {
+ return mRequestStatus;
+ }
+
+ // Obsolete
+ public void setRequestStatus(RequestStatus s) {
+ mRequestStatus = s;
+ // expose request status so that we can do predicate upon it
+ setExtData(IRequest.REQ_STATUS, s.toString());
+ }
+
+ public boolean isSuccess() {
+ Integer result = getExtDataInInteger(IRequest.RESULT);
+
+ if (result != null && result.equals(IRequest.RES_SUCCESS))
+ return true;
+ else
+ return false;
+ }
+
+ public String getError(Locale locale) {
+ return getExtDataInString(IRequest.ERROR);
+ }
+
+ // IRequest.getSourceId
+ public String getSourceId() {
+ return mSourceId;
+ }
+
+ // IRequest.setSourceId
+ public void setSourceId(String id) {
+ mSourceId = id;
+ }
+
+ // IRequest.getRequestOwner
+ public String getRequestOwner() {
+ return mOwner;
+ }
+
+ // IRequest.setRequestOwner
+ public void setRequestOwner(String id) {
+ mOwner = id;
+ }
+
+ // IRequest.getRequestType
+ public String getRequestType() {
+ return mRequestType;
+ }
+
+ // IRequest.setRequestType
+ public void setRequestType(String type) {
+ mRequestType = type;
+ setExtData(IRequest.REQ_TYPE, type);
+ }
+
+ // IRequest.getRequestVersion
+ public String getRequestVersion() {
+ return getExtDataInString(IRequest.REQ_VERSION);
+ }
+
+ // IRequest.getCreationTime
+ public Date getCreationTime() {
+ return mCreationTime;
+ }
+
+ public String getContext() {
+ return mContext;
+ }
+
+ public void setContext(String ctx) {
+ mContext = ctx;
+ }
+
+ // IRequest.getModificationTime
+ public Date getModificationTime() {
+ return mModificationTime;
+ }
+
+ /**
+ * this isn't that efficient but will do for now.
+ */
+ public void copyContents(IRequest req) {
+ Enumeration<String> e = req.getExtDataKeys();
+ while (e.hasMoreElements()) {
+ String key = e.nextElement();
+ if (!key.equals(IRequest.ISSUED_CERTS) &&
+ !key.equals(IRequest.ERRORS) &&
+ !key.equals(IRequest.REMOTE_REQID)) {
+ if (req.isSimpleExtDataValue(key)) {
+ setExtData(key, req.getExtDataInString(key));
+ } else {
+ setExtData(key, req.getExtDataInHashtable(key));
+ }
+ }
+ }
+ }
+
+ /**
+ * This function used to check that the keys obeyed LDAP attribute name
+ * syntax rules. Keys are being encoded now, so it is changed to just
+ * filter out null and empty string keys.
+ *
+ * @param key The key to check
+ * @return false if invalid
+ */
+ protected boolean isValidExtDataKey(String key) {
+ return key != null &&
+ (!key.equals(""));
+ }
+
+ protected boolean isValidExtDataHashtableValue(Hashtable<String, String> hash) {
+ if (hash == null) {
+ return false;
+ }
+ Enumeration<String> keys = hash.keys();
+ while (keys.hasMoreElements()) {
+ Object key = keys.nextElement();
+ if (!((key instanceof String) && isValidExtDataKey((String) key))) {
+ return false;
+ }
+ /*
+ * TODO should the Value type be String?
+ */
+ Object value = hash.get(key);
+ if (!(value instanceof String)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public boolean setExtData(String key, String value) {
+ if (!isValidExtDataKey(key)) {
+ return false;
+ }
+ if (value == null) {
+ return false;
+ }
+
+ mExtData.put(key, value);
+ return true;
+ }
+
+ public boolean setExtData(String key, Hashtable<String, String> value) {
+ if (!(isValidExtDataKey(key) && isValidExtDataHashtableValue(value))) {
+ return false;
+ }
+
+ mExtData.put(key, new ExtDataHashtable<String>(value));
+ return true;
+ }
+
+ public boolean isSimpleExtDataValue(String key) {
+ return (mExtData.get(key) instanceof String);
+ }
+
+ public String getExtDataInString(String key) {
+ Object value = mExtData.get(key);
+ if (value == null) {
+ return null;
+ }
+ if (!(value instanceof String)) {
+ return null;
+ }
+ return (String) value;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Hashtable<String, String> getExtDataInHashtable(String key) {
+ Object value = mExtData.get(key);
+ if (value == null) {
+ return null;
+ }
+ if (!(value instanceof Hashtable)) {
+ return null;
+ }
+ return new ExtDataHashtable<String>((Hashtable<String, String>) value);
+ }
+
+ public Enumeration<String> getExtDataKeys() {
+ return mExtData.keys();
+ }
+
+ public void deleteExtData(String type) {
+ mExtData.remove(type);
+ }
+
+ public boolean setExtData(String key, String subkey, String value) {
+ if (!(isValidExtDataKey(key) && isValidExtDataKey(subkey))) {
+ return false;
+ }
+ if (isSimpleExtDataValue(key)) {
+ return false;
+ }
+ if (value == null) {
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ Hashtable<String, String> existingValue = (Hashtable<String, String>) mExtData.get(key);
+ if (existingValue == null) {
+ existingValue = new ExtDataHashtable<String>();
+ mExtData.put(key, existingValue);
+ }
+ existingValue.put(subkey, value);
+ return true;
+ }
+
+ public String getExtDataInString(String key, String subkey) {
+ Hashtable<String, String> value = getExtDataInHashtable(key);
+ if (value == null) {
+ return null;
+ }
+ return value.get(subkey);
+ }
+
+ public boolean setExtData(String key, Integer value) {
+ if (value == null) {
+ return false;
+ }
+ return setExtData(key, value.toString());
+ }
+
+ public Integer getExtDataInInteger(String key) {
+ String strVal = getExtDataInString(key);
+ if (strVal == null) {
+ return null;
+ }
+ try {
+ return Integer.valueOf(strVal);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ }
+
+ public boolean setExtData(String key, Integer[] data) {
+ if (data == null) {
+ return false;
+ }
+ String[] stringArray = new String[data.length];
+ for (int index = 0; index < data.length; index++) {
+ stringArray[index] = data[index].toString();
+ }
+ return setExtData(key, stringArray);
+ }
+
+ public Integer[] getExtDataInIntegerArray(String key) {
+ String[] stringArray = getExtDataInStringArray(key);
+ if (stringArray == null) {
+ return null;
+ }
+ Integer[] intArray = new Integer[stringArray.length];
+ for (int index = 0; index < stringArray.length; index++) {
+ try {
+ intArray[index] = new Integer(stringArray[index]);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ }
+ return intArray;
+ }
+
+ public boolean setExtData(String key, BigInteger value) {
+ if (value == null) {
+ return false;
+ }
+ return setExtData(key, value.toString());
+ }
+
+ public BigInteger getExtDataInBigInteger(String key) {
+ String strVal = getExtDataInString(key);
+ if (strVal == null) {
+ return null;
+ }
+ try {
+ return new BigInteger(strVal);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ }
+
+ public boolean setExtData(String key, BigInteger[] data) {
+ if (data == null) {
+ return false;
+ }
+ String[] stringArray = new String[data.length];
+ for (int index = 0; index < data.length; index++) {
+ stringArray[index] = data[index].toString();
+ }
+ return setExtData(key, stringArray);
+ }
+
+ public BigInteger[] getExtDataInBigIntegerArray(String key) {
+ String[] stringArray = getExtDataInStringArray(key);
+ if (stringArray == null) {
+ return null;
+ }
+ BigInteger[] intArray = new BigInteger[stringArray.length];
+ for (int index = 0; index < stringArray.length; index++) {
+ try {
+ intArray[index] = new BigInteger(stringArray[index]);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ }
+ return intArray;
+ }
+
+ public boolean setExtData(String key, Throwable e) {
+ if (e == null) {
+ return false;
+ }
+ return setExtData(key, e.toString());
+ }
+
+ public boolean setExtData(String key, byte[] data) {
+ if (data == null) {
+ return false;
+ }
+ return setExtData(key, CMS.BtoA(data));
+ }
+
+ public byte[] getExtDataInByteArray(String key) {
+ String value = getExtDataInString(key);
+ if (value != null) {
+ return CMS.AtoB(value);
+ }
+ return null;
+ }
+
+ public boolean setExtData(String key, X509CertImpl data) {
+ if (data == null) {
+ return false;
+ }
+ try {
+ return setExtData(key, data.getEncoded());
+ } catch (CertificateEncodingException e) {
+ return false;
+ }
+ }
+
+ public X509CertImpl getExtDataInCert(String key) {
+ byte[] data = getExtDataInByteArray(key);
+ if (data != null) {
+ try {
+ return new X509CertImpl(data);
+ } catch (CertificateException e) {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public boolean setExtData(String key, X509CertImpl[] data) {
+ if (data == null) {
+ return false;
+ }
+ String[] stringArray = new String[data.length];
+ for (int index = 0; index < data.length; index++) {
+ try {
+ stringArray[index] = CMS.BtoA(data[index].getEncoded());
+ } catch (CertificateEncodingException e) {
+ return false;
+ }
+ }
+ return setExtData(key, stringArray);
+ }
+
+ public X509CertImpl[] getExtDataInCertArray(String key) {
+ String[] stringArray = getExtDataInStringArray(key);
+ if (stringArray == null) {
+ return null;
+ }
+ X509CertImpl[] certArray = new X509CertImpl[stringArray.length];
+ for (int index = 0; index < stringArray.length; index++) {
+ try {
+ certArray[index] = new X509CertImpl(CMS.AtoB(stringArray[index]));
+ } catch (CertificateException e) {
+ return null;
+ }
+ }
+ return certArray;
+ }
+
+ public boolean setExtData(String key, X509CertInfo data) {
+ if (data == null) {
+ return false;
+ }
+ try {
+ return setExtData(key, data.getEncodedInfo(true));
+ } catch (CertificateEncodingException e) {
+ return false;
+ }
+ }
+
+ public X509CertInfo getExtDataInCertInfo(String key) {
+ byte[] data = getExtDataInByteArray(key);
+ if (data != null) {
+ try {
+ return new X509CertInfo(data);
+ } catch (CertificateException e) {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public boolean setExtData(String key, X509CertInfo[] data) {
+ if (data == null) {
+ return false;
+ }
+ String[] stringArray = new String[data.length];
+ for (int index = 0; index < data.length; index++) {
+ try {
+ stringArray[index] = CMS.BtoA(data[index].getEncodedInfo(true));
+ } catch (CertificateEncodingException e) {
+ return false;
+ }
+ }
+ return setExtData(key, stringArray);
+ }
+
+ public X509CertInfo[] getExtDataInCertInfoArray(String key) {
+ String[] stringArray = getExtDataInStringArray(key);
+ if (stringArray == null) {
+ return null;
+ }
+ X509CertInfo[] certArray = new X509CertInfo[stringArray.length];
+ for (int index = 0; index < stringArray.length; index++) {
+ try {
+ certArray[index] = new X509CertInfo(CMS.AtoB(stringArray[index]));
+ } catch (CertificateException e) {
+ return null;
+ }
+ }
+ return certArray;
+ }
+
+ public boolean setExtData(String key, RevokedCertImpl[] data) {
+ if (data == null) {
+ return false;
+ }
+ String[] stringArray = new String[data.length];
+ for (int index = 0; index < data.length; index++) {
+ try {
+ stringArray[index] = CMS.BtoA(data[index].getEncoded());
+ } catch (CRLException e) {
+ return false;
+ }
+ }
+ return setExtData(key, stringArray);
+ }
+
+ public RevokedCertImpl[] getExtDataInRevokedCertArray(String key) {
+ String[] stringArray = getExtDataInStringArray(key);
+ if (stringArray == null) {
+ return null;
+ }
+ RevokedCertImpl[] certArray = new RevokedCertImpl[stringArray.length];
+ for (int index = 0; index < stringArray.length; index++) {
+ try {
+ certArray[index] = new RevokedCertImpl(CMS.AtoB(stringArray[index]));
+ } catch (CRLException e) {
+ return null;
+ } catch (X509ExtensionException e) {
+ return null;
+ }
+ }
+ return certArray;
+ }
+
+ public boolean setExtData(String key, Vector<?> stringVector) {
+ String[] stringArray;
+ if (stringVector == null) {
+ return false;
+ }
+ try {
+ stringArray = stringVector.toArray(new String[0]);
+ } catch (ArrayStoreException e) {
+ return false;
+ }
+ return setExtData(key, stringArray);
+ }
+
+ public Vector<String> getExtDataInStringVector(String key) {
+ String[] stringArray = getExtDataInStringArray(key);
+ if (stringArray == null) {
+ return null;
+ }
+ return new Vector<String>(Arrays.asList(stringArray));
+ }
+
+ public boolean getExtDataInBoolean(String key, boolean defVal) {
+ String val = getExtDataInString(key);
+ if (val == null)
+ return defVal;
+ return val.equalsIgnoreCase("true") || val.equalsIgnoreCase("ON");
+ }
+
+ public boolean getExtDataInBoolean(String prefix, String type, boolean defVal) {
+ String val = getExtDataInString(prefix, type);
+ if (val == null)
+ return defVal;
+ return val.equalsIgnoreCase("true") || val.equalsIgnoreCase("ON");
+ }
+
+ public boolean setExtData(String key, IAuthToken data) {
+ if (data == null) {
+ return false;
+ }
+ Hashtable<String, String> hash = new Hashtable<String, String>();
+ Enumeration<String> keys = data.getElements();
+ while (keys.hasMoreElements()) {
+ try {
+ String authKey = keys.nextElement();
+ hash.put(authKey, data.getInString(authKey));
+ } catch (ClassCastException e) {
+ return false;
+ }
+ }
+ return setExtData(key, hash);
+ }
+
+ public IAuthToken getExtDataInAuthToken(String key) {
+ Hashtable<String, String> hash = getExtDataInHashtable(key);
+ if (hash == null) {
+ return null;
+ }
+ AuthToken authToken = new AuthToken(null);
+ Enumeration<String> keys = hash.keys();
+ while (keys.hasMoreElements()) {
+ try {
+ String hashKey = keys.nextElement();
+ authToken.set(hashKey, hash.get(hashKey));
+ } catch (ClassCastException e) {
+ return null;
+ }
+ }
+ return authToken;
+ }
+
+ public boolean setExtData(String key, CertificateExtensions data) {
+ if (data == null) {
+ return false;
+ }
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ try {
+ data.encode(byteStream);
+ } catch (CertificateException e) {
+ return false;
+ } catch (IOException e) {
+ return false;
+ }
+ return setExtData(key, byteStream.toByteArray());
+ }
+
+ public CertificateExtensions getExtDataInCertExts(String key) {
+ CertificateExtensions exts = null;
+ byte[] extensionsData = getExtDataInByteArray(key);
+ if (extensionsData != null) {
+ exts = new CertificateExtensions();
+ try {
+ exts.decodeEx(new ByteArrayInputStream(extensionsData));
+ // exts.decode() does not work when the CertExts size is 0
+ // exts.decode(new ByteArrayInputStream(extensionsData));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return exts;
+ }
+
+ public boolean setExtData(String key, CertificateSubjectName data) {
+ if (data == null) {
+ return false;
+ }
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ try {
+ data.encode(byteStream);
+ } catch (IOException e) {
+ return false;
+ }
+ return setExtData(key, byteStream.toByteArray());
+ }
+
+ public CertificateSubjectName getExtDataInCertSubjectName(String key) {
+ CertificateSubjectName name = null;
+ byte[] nameData = getExtDataInByteArray(key);
+ if (nameData != null) {
+ try {
+ // You must use DerInputStream
+ // using ByteArrayInputStream fails
+ name = new CertificateSubjectName(
+ new DerInputStream(nameData));
+ } catch (IOException e) {
+ return null;
+ }
+ }
+ return name;
+ }
+
+ public boolean setExtData(String key, String[] values) {
+ if (values == null) {
+ return false;
+ }
+ Hashtable<String, String> hashValue = new Hashtable<String, String>();
+ for (int index = 0; index < values.length; index++) {
+ hashValue.put(Integer.toString(index), values[index]);
+ }
+ return setExtData(key, hashValue);
+ }
+
+ public String[] getExtDataInStringArray(String key) {
+ int index;
+
+ Hashtable<String, String> hashValue = getExtDataInHashtable(key);
+ if (hashValue == null) {
+ String s = getExtDataInString(key);
+ if (s == null) {
+ return null;
+ } else {
+ String[] sa = { s };
+ return sa;
+ }
+ }
+ Set<String> arrayKeys = hashValue.keySet();
+ Vector<Object> listValue = new Vector<Object>(arrayKeys.size());
+ for (Iterator<String> iter = arrayKeys.iterator(); iter.hasNext();) {
+ String arrayKey = iter.next();
+ try {
+ index = Integer.parseInt(arrayKey);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ if (listValue.size() < (index + 1)) {
+ listValue.setSize(index + 1);
+ }
+ listValue.set(index,
+ hashValue.get(arrayKey));
+ }
+ return listValue.toArray(new String[0]);
+ }
+
+ public IAttrSet asIAttrSet() {
+ return new RequestIAttrSetWrapper(this);
+ }
+
+ Request(RequestId id) {
+ mRequestId = id;
+ setRequestStatus(RequestStatus.BEGIN);
+ }
+
+ // instance variables
+ protected RequestId mRequestId;
+ protected RequestStatus mRequestStatus;
+ protected String mSourceId;
+ protected String mSource;
+ protected String mOwner;
+ protected String mRequestType;
+ protected String mContext; // string for now.
+ protected ExtDataHashtable<Object> mExtData = new ExtDataHashtable<Object>();
+
+ Date mCreationTime = CMS.getCurrentDate();
+ Date mModificationTime = CMS.getCurrentDate();
+}
+
+class RequestIAttrSetWrapper implements IAttrSet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8231914824991772682L;
+ IRequest mRequest;
+
+ public RequestIAttrSetWrapper(IRequest request) {
+ mRequest = request;
+ }
+
+ public void set(String name, Object obj) throws EBaseException {
+ try {
+ mRequest.setExtData(name, (String) obj);
+ } catch (ClassCastException e) {
+ throw new EBaseException(e.toString());
+ }
+ }
+
+ public Object get(String name) throws EBaseException {
+ return mRequest.getExtDataInString(name);
+ }
+
+ public void delete(String name) throws EBaseException {
+ mRequest.deleteExtData(name);
+ }
+
+ public Enumeration<String> getElements() {
+ return mRequest.getExtDataKeys();
+ }
+}
+
+/**
+ * Example of a specialized request class.
+ */
+class EnrollmentRequest extends Request implements IEnrollmentRequest {
+
+ private static final long serialVersionUID = 8214498908217267555L;
+
+ EnrollmentRequest(RequestId id) {
+ super(id);
+ }
+}
+
+class RequestListByStatus
+ implements IRequestList {
+ public boolean hasMoreElements() {
+ return (mNext != null);
+ }
+
+ public Object nextRequest() {
+ return null;
+ }
+
+ public IRequest nextRequestObject() {
+ return null;
+ }
+
+ public RequestId nextElement() {
+ RequestId next = mNext;
+
+ update();
+
+ return next;
+ }
+
+ public RequestId nextRequestId() {
+ RequestId next = mNext;
+
+ update();
+
+ return next;
+ }
+
+ public RequestListByStatus(Enumeration<RequestId> e, RequestStatus s, IRequestQueue q) {
+ mEnumeration = e;
+ mStatus = s;
+ mQueue = q;
+
+ update();
+ }
+
+ protected void update() {
+ RequestId rId;
+
+ mNext = null;
+
+ while (mNext == null) {
+ if (!mEnumeration.hasMoreElements())
+ break;
+
+ rId = mEnumeration.nextElement();
+
+ try {
+ IRequest r = mQueue.findRequest(rId);
+
+ if (r.getRequestStatus() == mStatus)
+ mNext = rId;
+
+ mQueue.releaseRequest(r);
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ protected RequestStatus mStatus;
+ protected IRequestQueue mQueue;
+ protected Enumeration<RequestId> mEnumeration;
+ protected RequestId mNext;
+}
+
+class RequestList
+ implements IRequestList {
+ public boolean hasMoreElements() {
+ return mEnumeration.hasMoreElements();
+ }
+
+ public RequestId nextElement() {
+ return mEnumeration.nextElement();
+ }
+
+ public RequestId nextRequestId() {
+ return mEnumeration.nextElement();
+ }
+
+ public Object nextRequest() {
+ return null;
+ }
+
+ public IRequest nextRequestObject() {
+ return null;
+ }
+
+ public RequestList(Enumeration<RequestId> e) {
+ mEnumeration = e;
+ }
+
+ protected Enumeration<RequestId> mEnumeration;
+}
+
+class RecoverThread extends Thread {
+ private ARequestQueue mQ = null;
+
+ public RecoverThread(ARequestQueue q) {
+ mQ = q;
+ setName("RequestRecoverThread");
+ }
+
+ public void run() {
+ mQ.recoverWillBlock();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/request/ARequestRecord.java b/base/server/cmscore/src/com/netscape/cmscore/request/ARequestRecord.java
new file mode 100644
index 000000000..5f2aa50b2
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/request/ARequestRecord.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+import java.util.Date;
+import java.util.Hashtable;
+
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+
+/**
+ * The low level (attributes only) version of the database
+ * record object. This exists so that RecordAttr methods can use
+ * this type definition,
+ *
+ * RequestRecord refers both to this class and to RecordAttr objects.
+ */
+class ARequestRecord {
+ RequestId mRequestId;
+ RequestStatus mRequestState;
+ Date mCreateTime;
+ Date mModifyTime;
+ String mSourceId;
+ String mOwner;
+ String mRequestType;
+ Hashtable<String, Object> mExtData;
+};
diff --git a/base/server/cmscore/src/com/netscape/cmscore/request/CertRequestConstants.java b/base/server/cmscore/src/com/netscape/cmscore/request/CertRequestConstants.java
new file mode 100644
index 000000000..9b9391d44
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/request/CertRequestConstants.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+/**
+ * temporary location for cert request constants.
+ * XXX we really need to centralize all these but for now they are here
+ * as needed.
+ */
+public class CertRequestConstants {
+ // request types - these have string values.
+ // made to match policy constants.
+ public final static String GETCRL_REQUEST = "getCRL";
+ public final static String GETCACHAIN_REQUEST = "getCAChain";
+ public final static String GETREVOCATIONINFO_REQUEST = "getRevocationInfo";
+
+ public final static String REVOCATION_CHECK_CHALLENGE_REQUEST = "checkChallengePhrase";
+ public final static String GETCERTS_FOR_CHALLENGE_REQUEST = "getCertsForChallenge";
+
+ // BigInteger Value and BigIntegerValue array.
+ public final static String SERIALNO = "serialNumber";
+ public final static String SERIALNOS = "serialNumbers";
+
+ // int value.
+ public final static String REVOKE_REASON = "revokeReason";
+
+ // this has a string value.
+ public final static String HOLDINSTRCODE = "holdInstrCode";
+ public final static String HOLDCALLISSUER = "holdCallIssuer";
+ public final static String HOLDREJECT = "holdReject";
+
+ // this has a Date value.
+ public final static String INVALIDITYDATE = "InvalidityDate";
+
+ // this has a CRLExtensions value.
+ public final static String CRLEXTS = "CRLExts";
+
+ // this has a String value - it is either null or set.
+ public final static String DOGETCACHAIN = "doGetCAChain";
+
+ // this has a CertificateChain value.
+ public final static String CACERTCHAIN = "CACertChain";
+
+ // this has a CRL value.
+ public final static String CRL = "CRL";
+
+ // this has a X509CertImpl value.
+ public final static String CERTIFICATE = "certificate";
+
+ // this is an array of EBaseException for service errors when
+ // there's an error processing an array of something such as
+ // certs to renew, certs to revoke, etc.
+ public final static String SVCERRORS = "serviceErrors";
+
+ // crl update status after a revocation.
+ public final static String CRL_UPDATE_STATUS = "crlUpdateStatus";
+ public final static String CRL_UPDATE_ERROR = "crlUpdateError";
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/request/ExtDataHashtable.java b/base/server/cmscore/src/com/netscape/cmscore/request/ExtDataHashtable.java
new file mode 100644
index 000000000..317b8e56c
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/request/ExtDataHashtable.java
@@ -0,0 +1,64 @@
+package com.netscape.cmscore.request;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+/**
+ * Subclass of Hashtable returned by IRequest.getExtDataInHashtable. Its
+ * purpose is to hide the fact that LDAP doesn't preserve the case of keys.
+ * It does this by lowercasing all keys used to access the Hashtable.
+ */
+public class ExtDataHashtable<V> extends Hashtable<String, V> {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8401134619951331450L;
+
+ public ExtDataHashtable() {
+ super();
+ }
+
+ public ExtDataHashtable(int i) {
+ super(i);
+ }
+
+ public ExtDataHashtable(int i, float v) {
+ super(i, v);
+ }
+
+ public ExtDataHashtable(Map<? extends String, ? extends V> map) {
+ // the super constructor seems to call putAll, but I can't
+ // rely on that behaviour
+ super();
+ putAll(map);
+ }
+
+ public boolean containsKey(Object o) {
+ if (o instanceof String) {
+ String key = (String) o;
+ return super.containsKey(key.toLowerCase());
+ }
+ return super.containsKey(o);
+ }
+
+ public V get(Object o) {
+ if (o instanceof String) {
+ String key = (String) o;
+ return super.get(key.toLowerCase());
+ }
+ return super.get(o);
+ }
+
+ public V put(String oKey, V val) {
+ return super.put(oKey.toLowerCase(), val);
+ }
+
+ public V remove(Object o) {
+ if (o instanceof String) {
+ String key = (String) o;
+ return super.remove(key.toLowerCase());
+ }
+ return super.remove(o);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/request/RequestAttr.java b/base/server/cmscore/src/com/netscape/cmscore/request/RequestAttr.java
new file mode 100644
index 000000000..a48fca1d2
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/request/RequestAttr.java
@@ -0,0 +1,61 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.ldap.IRequestMod;
+
+/**
+ * The RequestAttr class defines the methods used
+ * to transfer data between the various representations of
+ * a request. The three forms are:
+ * 1) LDAPAttributes (and Modifications)
+ * 2) Database record IDBAttrSet
+ * 3) IRequest (Request) object
+ */
+abstract class RequestAttr {
+
+ /**
+ *
+ */
+
+ abstract void set(ARequestRecord r, Object o);
+
+ abstract Object get(ARequestRecord r);
+
+ abstract void read(IRequestMod a, IRequest r, ARequestRecord rr);
+
+ abstract void add(IRequest r, ARequestRecord rr);
+
+ abstract void mod(ModificationSet mods, IRequest r);
+
+ RequestAttr(String attrName, IDBAttrMapper mapper) {
+ mAttrName = attrName;
+ mMapper = mapper;
+ }
+
+ protected void addmod(ModificationSet mods, Object o) {
+ mods.add(mAttrName, Modification.MOD_REPLACE, o);
+ }
+
+ String mAttrName;
+ IDBAttrMapper mMapper;
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/request/RequestQueue.java b/base/server/cmscore/src/com/netscape/cmscore/request/RequestQueue.java
new file mode 100644
index 000000000..6159a2ed5
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/request/RequestQueue.java
@@ -0,0 +1,709 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSearchResults;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.IDBVirtualList;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.dbs.repository.IRepository;
+import com.netscape.certsrv.request.INotify;
+import com.netscape.certsrv.request.IPolicy;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestList;
+import com.netscape.certsrv.request.IRequestRecord;
+import com.netscape.certsrv.request.IRequestVirtualList;
+import com.netscape.certsrv.request.IService;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.certsrv.request.ldap.IRequestMod;
+import com.netscape.cmscore.dbs.DBSubsystem;
+import com.netscape.cmscore.util.Debug;
+
+public class RequestQueue
+ extends ARequestQueue
+ implements IRequestMod {
+ // ARequestQueue.newRequestId
+ protected RequestId newRequestId()
+ throws EBaseException {
+ // get the next request Id
+ BigInteger next = mRepository.getNextSerialNumber();
+
+ RequestId rid = new RequestId(next);
+
+ return rid;
+ }
+
+ protected IRequest readRequest(RequestId id) {
+ RequestRecord record;
+
+ // String name = Schema.LDAP_ATTR_REQUEST_ID + "=" +
+ String name = "cn" + "=" +
+ id + "," + mBaseDN;
+
+ Object obj = null;
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ obj = dbs.read(name);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ // TODO Errors!!!
+ if (obj == null || !(obj instanceof RequestRecord))
+ return null;
+
+ record = (RequestRecord) obj;
+
+ /*
+ setRequestStatus(r, record.mRequestState);
+ r.setSourceId(record.mSourceId);
+ r.setRequestOwner(record.mOwner);
+ record.storeAttrs(r, record.mRequestAttrs);
+ setModificationTime(r, record.mModifyTime);
+ setCreationTime(r, record.mCreateTime);
+ */
+ return makeRequest(record);
+ }
+
+ protected void addRequest(IRequest r) throws EBaseException {
+ // setup to call dbs.add(name, IAttrSet)
+ RequestRecord record = new RequestRecord();
+
+ record.add(r);
+
+ // compute the name of the object
+ // String name = Schema.LDAP_ATTR_REQUEST_ID + "=" +
+ String name = "cn" + "=" +
+ record.mRequestId + "," + mBaseDN;
+
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ dbs.add(name, record);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ throw e;
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+ }
+
+ protected void modifyRequest(IRequest r) {
+ String dbStatus = r.getExtDataInString("dbStatus");
+
+ if (!dbStatus.equals("UPDATED")) {
+ try {
+ r.setExtData("dbStatus", "UPDATED");
+ addRequest(r);
+ } catch (EBaseException e) {
+ System.out.println(e.toString());
+ }
+ return;
+ }
+
+ ModificationSet mods = new ModificationSet();
+
+ try {
+ RequestRecord.mod(mods, r);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ }
+
+ /*
+ //
+ mods.add(IRequestRecord.ATTR_REQUEST_STATE,
+ Modification.MOD_REPLACE, r.getRequestStatus());
+
+ mods.add(IRequestRecord.ATTR_SOURCE_ID,
+ Modification.MOD_REPLACE, r.getSourceId());
+
+ mods.add(IRequestRecord.ATTR_REQUEST_OWNER,
+ Modification.MOD_REPLACE, r.getRequestOwner());
+
+ mods.add(IRequestRecord.ATTR_MODIFY_TIME,
+ Modification.MOD_REPLACE, r.getModificationTime());
+
+ java.util.Hashtable ht = RequestRecord.loadAttrs(r);
+ mods.add(RequestRecord.ATTR_REQUEST_ATTRS,
+ Modification.MOD_REPLACE, ht);
+ */
+
+ // String name = Schema.LDAP_ATTR_REQUEST_ID + "=" +
+ String name = "cn" + "=" +
+ r.getRequestId() + "," + mBaseDN;
+
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ dbs.modify(name, mods);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+ }
+
+ IRequest makeRequest(RequestRecord record) {
+ IRequest r = createRequest(record.mRequestId, record.mRequestType);
+
+ try {
+ // convert (copy) fields
+ record.read(this, r);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ }
+
+ return r;
+ }
+
+ public void modRequestStatus(IRequest r, RequestStatus s) {
+ setRequestStatus(r, s);
+ }
+
+ public void modCreationTime(IRequest r, Date d) {
+ setCreationTime(r, d);
+ }
+
+ public void modModificationTime(IRequest r, Date d) {
+ setModificationTime(r, d);
+ }
+
+ /**
+ * Resets serial number.
+ */
+ public void resetSerialNumber(BigInteger serial) throws EBaseException {
+ mRepository.resetSerialNumber(serial);
+ }
+
+ /**
+ * Removes all objects with this repository.
+ */
+ public void removeAllObjects() throws EBaseException {
+ mRepository.removeAllObjects();
+ }
+
+ public BigInteger getLastRequestIdInRange(BigInteger reqId_low_bound, BigInteger reqId_upper_bound) {
+ CMS.debug("RequestQueue: getLastRequestId: low " + reqId_low_bound + " high " + reqId_upper_bound);
+ if (reqId_low_bound == null || reqId_upper_bound == null || reqId_low_bound.compareTo(reqId_upper_bound) >= 0) {
+ CMS.debug("RequestQueue: getLastRequestId: bad upper and lower bound range.");
+ return null;
+ }
+
+ String filter = "(" + "requeststate" + "=*" + ")";
+
+ RequestId fromId = new RequestId(reqId_upper_bound);
+
+ CMS.debug("RequestQueue: getLastRequestId: filter " + filter + " fromId " + fromId);
+ ListEnumeration recList = (ListEnumeration) getPagedRequestsByFilter(fromId, filter, 5 * -1, "requestId");
+
+ int size = recList.getSize();
+
+ CMS.debug("RequestQueue: getLastRequestId: size " + size);
+
+ int ltSize = recList.getSizeBeforeJumpTo();
+
+ CMS.debug("RequestQueue: getSizeBeforeJumpTo: " + ltSize);
+
+ if (size <= 0) {
+ CMS.debug("RequestQueue: getLastRequestId: request list is empty.");
+
+ BigInteger ret = new BigInteger(reqId_low_bound.toString(10));
+
+ ret = ret.add(new BigInteger("-1"));
+
+ CMS.debug("CertificateRepository:getLastCertRecordSerialNo: returning " + ret);
+ return ret;
+ }
+
+ IRequest curRec = null;
+
+ RequestId curId = null;
+
+ String reqId = null;
+
+ for (int i = 0; i < 5; i++) {
+ curRec = recList.getElementAt(i);
+
+ if (curRec != null) {
+
+ curId = curRec.getRequestId();
+
+ reqId = curId.toString();
+
+ CMS.debug("RequestQueue: curReqId: " + reqId);
+
+ BigInteger curIdInt = new BigInteger(reqId);
+
+ if (((curIdInt.compareTo(reqId_low_bound) == 0) || (curIdInt.compareTo(reqId_low_bound) == 1)) &&
+ ((curIdInt.compareTo(reqId_upper_bound) == 0) || (curIdInt.compareTo(reqId_upper_bound) == -1))) {
+ CMS.debug("RequestQueue: getLastRequestId : returning value " + curIdInt);
+ return curIdInt;
+ }
+
+ }
+
+ }
+
+ BigInteger ret = new BigInteger(reqId_low_bound.toString(10));
+
+ ret = ret.add(new BigInteger("-1"));
+
+ CMS.debug("CertificateRepository:getLastCertRecordSerialNo: returning " + ret);
+ return ret;
+
+ }
+
+ /**
+ * Implements IRequestQueue.findRequestBySourceId
+ * <p>
+ *
+ * @see com.netscape.certsrv.request.IRequestQueue#findRequestBySourceId
+ */
+ public RequestId findRequestBySourceId(String id) {
+ IRequestList irl = findRequestsBySourceId(id);
+
+ if (irl == null)
+ return null;
+
+ return irl.nextRequestId();
+ }
+
+ /**
+ * Implements IRequestQueue.findRequestsBySourceId
+ * <p>
+ *
+ * @see com.netscape.certsrv.request.IRequestQueue#findRequestsBySourceId
+ */
+ public IRequestList findRequestsBySourceId(String id) {
+ IDBSearchResults results = null;
+ IDBSSession dbs = null;
+
+ // Need only the requestid in the result of the search
+ // TODO: generic search returning RequestId
+ String filter = "(" + IRequestRecord.ATTR_SOURCE_ID + "=" + id + ")";
+
+ try {
+ dbs = mDB.createSession();
+ results = dbs.search(mBaseDN, filter);
+ } catch (EBaseException e) {
+ Debug.trace("Error in Ldap Request searching code: " + e);
+ Debug.printStackTrace(e);
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ if (results == null || !results.hasMoreElements())
+ return null;
+
+ return new SearchEnumeration(this, results);
+
+ }
+
+ protected Enumeration<RequestId> getRawList() {
+ IDBSearchResults results = null;
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ results = dbs.search(mBaseDN, "(requestId=*)");
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ if (results == null)
+ return null;
+
+ return new SearchEnumeration(this, results);
+ }
+
+ /**
+ */
+ public IRequestList listRequestsByFilter(String f) {
+ IDBSearchResults results = null;
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ results = dbs.search(mBaseDN, f);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ if (results == null)
+ return null;
+
+ return new SearchEnumeration(this, results);
+ }
+
+ /**
+ */
+ public IRequestList listRequestsByFilter(String f, int maxSize) {
+ IDBSearchResults results = null;
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ results = dbs.search(mBaseDN, f, maxSize);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ if (results == null)
+ return null;
+
+ return new SearchEnumeration(this, results);
+ }
+
+ /**
+ */
+ public IRequestList listRequestsByFilter(String f, int maxSize, int timeLimit) {
+ IDBSearchResults results = null;
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ results = dbs.search(mBaseDN, f, maxSize, timeLimit);
+ } catch (EBaseException e) {
+ Debug.trace("Error: " + e);
+ Debug.printStackTrace(e);
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ if (results == null)
+ return null;
+
+ return new SearchEnumeration(this, results);
+ }
+
+ public IRequestList listRequestsByStatus(RequestStatus s) {
+ IDBSearchResults results = null;
+ IDBSSession dbs = null;
+
+ try {
+ String f1;
+ String f2;
+
+ f1 = "(" + IRequestRecord.ATTR_REQUEST_STATE + "=" + s + ")";
+ f2 = "(" + IRequestRecord.ATTR_REQUEST_ID + "=*)";
+
+ f1 = "(&" + f1 + f2 + ")";
+
+ dbs = mDB.createSession();
+ results = dbs.search(mBaseDN, f1);
+ } catch (EBaseException e) {
+ //System.err.println("Error: "+e);
+ //e.printStackTrace();
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null)
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ if (results == null)
+ return null;
+
+ return new SearchEnumeration(this, results);
+ }
+
+ /*
+ * Implements IRequestQueue.getPagedRequests
+ */
+ public IRequestVirtualList getPagedRequests(int pageSize) {
+ return getPagedRequestsByFilter("(requestId=*)", pageSize, "requestId");
+ }
+
+ /*
+ * Implements IRequestQueue.getPagedRequestsByFilter
+ */
+ public IRequestVirtualList
+ getPagedRequestsByFilter(String filter, int pageSize, String sortKey) {
+ return getPagedRequestsByFilter(null, filter, pageSize, sortKey);
+ }
+
+ public IRequestVirtualList
+ getPagedRequestsByFilter(RequestId from, String filter, int pageSize,
+ String sortKey) {
+ return getPagedRequestsByFilter(from, false, filter, pageSize, sortKey);
+ }
+
+ public IRequestVirtualList
+ getPagedRequestsByFilter(RequestId from, boolean jumpToEnd, String filter, int pageSize,
+ String sortKey) {
+ IDBVirtualList<Object> results = null;
+ IDBSSession dbs = null;
+
+ try {
+ dbs = mDB.createSession();
+ } catch (EBaseException e) {
+ return null;
+ }
+
+ try {
+
+ if (from == null) {
+ results = dbs.createVirtualList(mBaseDN, filter, (String[]) null,
+ sortKey, pageSize);
+ } else {
+ int len = from.toString().length();
+ String internalRequestId = null;
+
+ if (jumpToEnd) {
+ internalRequestId = "99";
+ } else {
+ if (len > 9) {
+ internalRequestId = Integer.toString(len) + from.toString();
+ } else {
+ internalRequestId = "0" + Integer.toString(len) +
+ from.toString();
+ }
+ }
+
+ results = dbs.createVirtualList(mBaseDN, filter, (String[]) null,
+ internalRequestId, sortKey, pageSize);
+ }
+ } catch (EBaseException e) {
+ return null;
+ } finally {
+ try {
+ dbs.close();
+ } catch (EBaseException e) {
+ }
+ }
+
+ try {
+ results.setSortKey(sortKey);
+ } catch (EBaseException e) {//XXX
+ System.out.println(e.toString());
+ return null;
+ }
+
+ return new ListEnumeration(this, results);
+ }
+
+ public RequestQueue(String name, int increment, IPolicy p, IService s, INotify n,
+ INotify pendingNotify)
+ throws EBaseException {
+ super(p, s, n, pendingNotify);
+
+ mDB = DBSubsystem.getInstance();
+ mBaseDN = "ou=" + name + ",ou=requests," + mDB.getBaseDN();
+
+ mRepository = new RequestRepository(name, increment, mDB, this);
+
+ }
+
+ /*
+ * list record attributes (debugging output)
+ */
+ static void listRecordAttrs(String s, Hashtable<String, Object> h) {
+ System.err.println(s);
+ Enumeration<String> e = h.keys();
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ System.err.println("Attr: " + name + " Value: " + h.get(name));
+ }
+ }
+
+ /*
+ * return request repository
+ */
+ public IRepository getRequestRepository() {
+ return mRepository;
+ }
+
+ public String getPublishingStatus() {
+ return mRepository.getPublishingStatus();
+ }
+
+ public void setPublishingStatus(String status) {
+ mRepository.setPublishingStatus(status);
+ }
+
+ protected String mBaseDN;
+ protected IDBSubsystem mDB;
+ protected RequestRepository mRepository;
+}
+
+class SearchEnumeration
+ implements IRequestList {
+ public RequestId nextRequestId() {
+ Object obj;
+
+ obj = mResults.nextElement();
+
+ if (obj == null || !(obj instanceof RequestRecord))
+ return null;
+
+ RequestRecord r = (RequestRecord) obj;
+
+ return r.mRequestId;
+ }
+
+ public boolean hasMoreElements() {
+ return mResults.hasMoreElements();
+ }
+
+ public RequestId nextElement() {
+ return nextRequestId();
+ }
+
+ public SearchEnumeration(IDBSearchResults r) {
+ mResults = r;
+ }
+
+ public SearchEnumeration(RequestQueue queue, IDBSearchResults r) {
+ mResults = r;
+ mQueue = queue;
+ }
+
+ public Object nextRequest() {
+ Object obj;
+
+ obj = mResults.nextElement();
+
+ if (obj == null || !(obj instanceof RequestRecord))
+ return null;
+
+ RequestRecord r = (RequestRecord) obj;
+
+ return r;
+ }
+
+ public IRequest nextRequestObject() {
+ RequestRecord record = (RequestRecord) nextRequest();
+ if (record != null)
+ return mQueue.makeRequest(record);
+ return null;
+ }
+
+ protected IDBSearchResults mResults;
+ protected RequestQueue mQueue;
+}
+
+class ListEnumeration
+ implements IRequestVirtualList {
+ public IRequest getElementAt(int i) {
+ RequestRecord record = (RequestRecord) mList.getElementAt(i);
+
+ if (record == null)
+ return null;
+
+ return mQueue.makeRequest(record);
+ }
+
+ public int getCurrentIndex() {
+ return mList.getCurrentIndex();
+ }
+
+ public int getSize() {
+ return mList.getSize();
+ }
+
+ public int getSizeBeforeJumpTo() {
+ return mList.getSizeBeforeJumpTo();
+
+ }
+
+ public int getSizeAfterJumpTo() {
+ return mList.getSizeAfterJumpTo();
+
+ }
+
+ ListEnumeration(RequestQueue queue, IDBVirtualList<Object> list) {
+ mQueue = queue;
+ mList = list;
+ }
+
+ protected RequestQueue mQueue;
+ protected IDBVirtualList<Object> mList;
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/request/RequestRecord.java b/base/server/cmscore/src/com/netscape/cmscore/request/RequestRecord.java
new file mode 100644
index 000000000..023dd9478
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/request/RequestRecord.java
@@ -0,0 +1,905 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.dbs.IDBDynAttrMapper;
+import com.netscape.certsrv.dbs.IDBObj;
+import com.netscape.certsrv.dbs.IDBRegistry;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestRecord;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.certsrv.request.ldap.IRequestMod;
+import com.netscape.cmscore.dbs.BigIntegerMapper;
+import com.netscape.cmscore.dbs.DateMapper;
+import com.netscape.cmscore.dbs.StringMapper;
+import com.netscape.cmscore.util.Debug;
+
+//
+// A request record is the stored version of a request.
+// It has a set of attributes that are mapped into LDAP
+// attributes for actual directory operations.
+//
+public class RequestRecord
+ extends ARequestRecord
+ implements IRequestRecord, IDBObj {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8044665107558872084L;
+
+ public RequestId getRequestId() {
+ return mRequestId;
+ }
+
+ public Enumeration<String> getAttrNames() {
+ return mAttrTable.keys();
+ }
+
+ // IDBObj.get
+ public Object get(String name) {
+ if (name.equals(IRequestRecord.ATTR_REQUEST_ID))
+ return mRequestId;
+ else if (name.equals(IRequestRecord.ATTR_REQUEST_STATE))
+ return mRequestState;
+ else if (name.equals(IRequestRecord.ATTR_REQUEST_TYPE))
+ return mRequestType;
+ else if (name.equals(IRequestRecord.ATTR_MODIFY_TIME))
+ return mModifyTime;
+ else if (name.equals(IRequestRecord.ATTR_CREATE_TIME))
+ return mCreateTime;
+ else if (name.equals(IRequestRecord.ATTR_SOURCE_ID))
+ return mSourceId;
+ else if (name.equals(IRequestRecord.ATTR_REQUEST_OWNER))
+ return mOwner;
+ else if (name.equals(IRequestRecord.ATTR_EXT_DATA))
+ return mExtData;
+ else {
+ RequestAttr ra = mAttrTable.get(name);
+
+ if (ra != null)
+ return ra.get(this);
+ }
+
+ return null;
+ }
+
+ // IDBObj.set
+ @SuppressWarnings("unchecked")
+ public void set(String name, Object o) {
+ if (name.equals(IRequestRecord.ATTR_REQUEST_ID))
+ mRequestId = (RequestId) o;
+ else if (name.equals(IRequestRecord.ATTR_REQUEST_STATE))
+ mRequestState = (RequestStatus) o;
+ else if (name.equals(IRequestRecord.ATTR_REQUEST_TYPE))
+ mRequestType = (String) o;
+ else if (name.equals(IRequestRecord.ATTR_CREATE_TIME))
+ mCreateTime = (Date) o;
+ else if (name.equals(IRequestRecord.ATTR_MODIFY_TIME))
+ mModifyTime = (Date) o;
+ else if (name.equals(IRequestRecord.ATTR_SOURCE_ID))
+ mSourceId = (String) o;
+ else if (name.equals(IRequestRecord.ATTR_REQUEST_OWNER))
+ mOwner = (String) o;
+ else if (name.equals(IRequestRecord.ATTR_EXT_DATA))
+ mExtData = (Hashtable<String, Object>) o;
+ else {
+ RequestAttr ra = mAttrTable.get(name);
+
+ if (ra != null)
+ ra.set(this, o);
+ }
+ }
+
+ // IDBObj.delete
+ public void delete(String name)
+ throws EBaseException {
+ throw new EBaseException("Invalid call to delete");
+ }
+
+ // IDBObj.getElements
+ public Enumeration<String> getElements() {
+ return mAttrs.elements();
+ }
+
+ // IDBObj.getSerializableAttrNames
+ public Enumeration<String> getSerializableAttrNames() {
+ return mAttrs.elements();
+ }
+
+ // copy values from r to the local record
+ void add(IRequest r) throws EBaseException {
+ // Collect the values for the record
+ mRequestId = r.getRequestId();
+ mRequestType = r.getRequestType();
+ mRequestState = r.getRequestStatus();
+ mSourceId = r.getSourceId();
+ mOwner = r.getRequestOwner();
+ mCreateTime = r.getCreationTime();
+ mModifyTime = r.getModificationTime();
+ mExtData = loadExtDataFromRequest(r);
+
+ for (int i = 0; i < mRequestA.length; i++) {
+ mRequestA[i].add(r, this);
+ }
+ }
+
+ void read(IRequestMod a, IRequest r) throws EBaseException {
+ a.modRequestStatus(r, mRequestState);
+ r.setSourceId(mSourceId);
+ r.setRequestOwner(mOwner);
+ a.modModificationTime(r, mModifyTime);
+ a.modCreationTime(r, mCreateTime);
+ storeExtDataIntoRequest(r);
+
+ for (int i = 0; i < mRequestA.length; i++) {
+ mRequestA[i].read(a, r, this);
+ }
+ }
+
+ static void mod(ModificationSet mods, IRequest r) throws EBaseException {
+ //
+ mods.add(IRequestRecord.ATTR_REQUEST_STATE,
+ Modification.MOD_REPLACE, r.getRequestStatus());
+
+ mods.add(IRequestRecord.ATTR_SOURCE_ID,
+ Modification.MOD_REPLACE, r.getSourceId());
+
+ mods.add(IRequestRecord.ATTR_REQUEST_OWNER,
+ Modification.MOD_REPLACE, r.getRequestOwner());
+
+ mods.add(IRequestRecord.ATTR_MODIFY_TIME,
+ Modification.MOD_REPLACE, r.getModificationTime());
+
+ mods.add(IRequestRecord.ATTR_EXT_DATA,
+ Modification.MOD_REPLACE, loadExtDataFromRequest(r));
+
+ for (int i = 0; i < mRequestA.length; i++) {
+ mRequestA[i].mod(mods, r);
+ }
+ }
+
+ static void register(IDBSubsystem db)
+ throws EDBException {
+ IDBRegistry reg = db.getRegistry();
+
+ reg.registerObjectClass(RequestRecord.class.getName(), mOC);
+
+ reg.registerAttribute(IRequestRecord.ATTR_REQUEST_ID, new RequestIdMapper());
+ reg.registerAttribute(IRequestRecord.ATTR_REQUEST_STATE, new RequestStateMapper());
+ reg.registerAttribute(IRequestRecord.ATTR_CREATE_TIME,
+ new DateMapper(Schema.LDAP_ATTR_CREATE_TIME));
+ reg.registerAttribute(IRequestRecord.ATTR_MODIFY_TIME,
+ new DateMapper(Schema.LDAP_ATTR_MODIFY_TIME));
+ reg.registerAttribute(IRequestRecord.ATTR_SOURCE_ID,
+ new StringMapper(Schema.LDAP_ATTR_SOURCE_ID));
+ reg.registerAttribute(IRequestRecord.ATTR_REQUEST_OWNER,
+ new StringMapper(Schema.LDAP_ATTR_REQUEST_OWNER));
+ ExtAttrDynMapper extAttrMapper = new ExtAttrDynMapper();
+ reg.registerAttribute(IRequestRecord.ATTR_EXT_DATA, extAttrMapper);
+ reg.registerDynamicMapper(extAttrMapper);
+
+ for (int i = 0; i < mRequestA.length; i++) {
+ RequestAttr ra = mRequestA[i];
+
+ reg.registerAttribute(ra.mAttrName, ra.mMapper);
+ }
+ }
+
+ protected static final String mOC[] =
+ { Schema.LDAP_OC_TOP, Schema.LDAP_OC_REQUEST, Schema.LDAP_OC_EXTENSIBLE };
+
+ protected static Hashtable<String, Object> loadExtDataFromRequest(IRequest r) throws EBaseException {
+ Hashtable<String, Object> h = new Hashtable<String, Object>();
+
+ Enumeration<String> e = r.getExtDataKeys();
+ while (e.hasMoreElements()) {
+ String key = e.nextElement();
+ if (r.isSimpleExtDataValue(key)) {
+ h.put(key, r.getExtDataInString(key));
+ } else {
+ h.put(key, r.getExtDataInHashtable(key));
+ }
+ }
+
+ return h;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void storeExtDataIntoRequest(IRequest r) throws EBaseException {
+ Enumeration<String> e = mExtData.keys();
+ while (e.hasMoreElements()) {
+ String key = e.nextElement();
+ Object value = mExtData.get(key);
+ if (value instanceof String) {
+ r.setExtData(key, (String) value);
+ } else if (value instanceof Hashtable) {
+ r.setExtData(key, (Hashtable<String, String>) value);
+ } else {
+ throw new EDBException("Illegal data value in RequestRecord: " +
+ r.toString());
+ }
+ }
+ }
+
+ protected static Vector<String> mAttrs = new Vector<String>();
+
+ static Hashtable<String, RequestAttr> mAttrTable = new Hashtable<String, RequestAttr>();
+
+ /*
+ * This table contains attribute handlers for attributes
+ * of the request. These attributes are ones that are stored
+ * apart from the generic name/value pairs supported by the get/set
+ * interface plus the hashtable for the name/value pairs themselves.
+ *
+ * NOTE: Eventually, all attributes should be done here. Currently
+ * only the last ones added are implemented this way.
+ */
+ static RequestAttr mRequestA[] = {
+
+ new RequestAttr(IRequest.ATTR_REQUEST_TYPE,
+ new StringMapper(Schema.LDAP_ATTR_REQUEST_TYPE)) {
+ void set(ARequestRecord r, Object o) {
+ r.mRequestType = (String) o;
+ }
+
+ Object get(ARequestRecord r) {
+ return r.mRequestType;
+ }
+
+ void read(IRequestMod a, IRequest r, ARequestRecord rr) {
+ r.setRequestType(rr.mRequestType);
+ }
+
+ void add(IRequest r, ARequestRecord rr) {
+ rr.mRequestType = r.getRequestType();
+ }
+
+ void mod(ModificationSet mods, IRequest r) {
+ addmod(mods, r.getRequestType());
+ }
+ }
+
+ };
+ static {
+ mAttrs.add(IRequestRecord.ATTR_REQUEST_ID);
+ mAttrs.add(IRequestRecord.ATTR_REQUEST_STATE);
+ mAttrs.add(IRequestRecord.ATTR_CREATE_TIME);
+ mAttrs.add(IRequestRecord.ATTR_MODIFY_TIME);
+ mAttrs.add(IRequestRecord.ATTR_SOURCE_ID);
+ mAttrs.add(IRequestRecord.ATTR_REQUEST_OWNER);
+ mAttrs.add(IRequestRecord.ATTR_EXT_DATA);
+
+ for (int i = 0; i < mRequestA.length; i++) {
+ RequestAttr ra = mRequestA[i];
+
+ mAttrs.add(ra.mAttrName);
+ mAttrTable.put(ra.mAttrName, ra);
+ }
+ }
+
+}
+
+//
+// A mapper between an request state object and
+// its LDAP attribute representation
+// <P>
+//
+// @author thayes
+// @version $Revision$ $Date$
+//
+class RequestStateMapper
+ implements IDBAttrMapper {
+ // IDBAttrMapper methods
+
+ //
+ //
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return mAttrs.elements();
+ }
+
+ //
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs) throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ RequestStatus rs = (RequestStatus) obj;
+
+ attrs.add(new LDAPAttribute(Schema.LDAP_ATTR_REQUEST_STATE,
+ rs.toString()));
+ }
+
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent)
+ throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(Schema.LDAP_ATTR_REQUEST_STATE);
+
+ if (attr == null)
+ throw new EBaseException("schema violation");
+
+ String value = (String) attr.getStringValues().nextElement();
+
+ parent.set(name, RequestStatus.fromString(value));
+ }
+
+ public String mapSearchFilter(String name, String op, String value) {
+ return Schema.LDAP_ATTR_REQUEST_STATE + op + value;
+ }
+
+ protected final static Vector<String> mAttrs = new Vector<String>();
+
+ static {
+ mAttrs.add(Schema.LDAP_ATTR_REQUEST_STATE);
+ }
+}
+
+//
+// A mapper between an request id object and
+// its LDAP attribute representation
+// <P>
+//
+// @author thayes
+// @version $Revision$ $Date$
+//
+class RequestIdMapper
+ implements IDBAttrMapper {
+ // IDBAttrMapper methods
+
+ //
+ //
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return mAttrs.elements();
+ }
+
+ //
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs) throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ RequestId rid = (RequestId) obj;
+
+ String v = BigIntegerMapper.BigIntegerToDB(new BigInteger(rid.toString()));
+
+ attrs.add(new LDAPAttribute(Schema.LDAP_ATTR_REQUEST_ID, v));
+ }
+
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent)
+ throws EBaseException {
+ LDAPAttribute attr = attrs.getAttribute(Schema.LDAP_ATTR_REQUEST_ID);
+
+ if (attr == null)
+ throw new EBaseException("schema violation");
+
+ String value = (String) attr.getStringValues().nextElement();
+
+ parent.set(name, new RequestId(
+ BigIntegerMapper.BigIntegerFromDB(value).toString()));
+ }
+
+ public String mapSearchFilter(String name, String op, String value) throws EBaseException {
+ String v = null;
+
+ try {
+ v = BigIntegerMapper.BigIntegerToDB(new BigInteger(value));
+ } catch (NumberFormatException e) {
+ v = value;
+ }
+ return Schema.LDAP_ATTR_REQUEST_ID + op + v;
+ }
+
+ protected final static Vector<String> mAttrs = new Vector<String>();
+
+ static {
+ mAttrs.add(Schema.LDAP_ATTR_REQUEST_ID);
+ }
+}
+
+/**
+ * A mapper between an request attr set and its LDAP attribute representation.
+ *
+ * The attr attribute is no longer used. This class is kept for historical
+ * and migration purposes.
+ *
+ * @author thayes
+ * @version $Revision$ $Date$
+ * @deprecated
+ */
+class RequestAttrsMapper
+ implements IDBAttrMapper {
+ // IDBAttrMapper methods
+
+ //
+ //
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return mAttrs.elements();
+ }
+
+ //
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs) throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ @SuppressWarnings("unchecked")
+ Hashtable<String, Object> ht = (Hashtable<String, Object>) obj;
+ Enumeration<String> e = ht.keys();
+ ByteArrayOutputStream bos = null;
+ ObjectOutputStream os = null;
+ try {
+ bos = new ByteArrayOutputStream();
+ os = new ObjectOutputStream(bos);
+
+ String key = null;
+ Object value = null;
+
+ while (e.hasMoreElements()) {
+ key = e.nextElement();
+ value = ht.get(key);
+ byte data[] = null;
+
+ try {
+ data = encode(value);
+ os.writeObject(key);
+ os.writeObject(data);
+ } catch (NotSerializableException x) {
+ if (Debug.ON) {
+ System.err.println("Error: attribute '" + key + "' (" +
+ x.getMessage() + ") is not serializable");
+ x.printStackTrace();
+ }
+ } catch (Exception x) {
+ if (Debug.ON) {
+ System.err.println("Error: attribute '" + key +
+ "' - error during serialization: " + x);
+ x.printStackTrace();
+ }
+ }
+ }
+
+ os.writeObject(null);
+
+ } catch (Exception x) {
+ if (parent != null)
+ Debug.trace("Output Mapping Error in requeset ID " +
+ ((RequestRecord) parent).getRequestId().toString() + " : " + x);
+ //if (Debug.ON) {
+ Debug.printStackTrace(x);
+ //}
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ } finally {
+ if (os != null) {
+ try {
+ os.close();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+ if (bos != null) {
+ try {
+ bos.close();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+ attrs.add(new LDAPAttribute(Schema.LDAP_ATTR_REQUEST_ATTRS,
+ bos.toByteArray()));
+ }
+
+ private byte[] encode(Object value)
+ throws NotSerializableException, IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream os = new ObjectOutputStream(bos);
+
+ os.writeObject(value);
+ os.close();
+
+ return bos.toByteArray();
+ }
+
+ private Object decode(byte[] data)
+ throws ObjectStreamException, IOException, ClassNotFoundException {
+ ByteArrayInputStream bis = new ByteArrayInputStream(data);
+ ObjectInputStream is = new ObjectInputStream(bis);
+
+ return is.readObject();
+ }
+
+ private Hashtable<String, Object> decodeHashtable(byte[] data)
+ throws ObjectStreamException, IOException, ClassNotFoundException {
+ Hashtable<String, Object> ht = new Hashtable<String, Object>();
+ ByteArrayInputStream bis = new ByteArrayInputStream(data);
+ ObjectInputStream is = new ObjectInputStream(bis);
+
+ String key = null;
+
+ try {
+
+ while (true) {
+ key = (String) is.readObject();
+
+ // end of table is marked with null
+ if (key == null)
+ break;
+
+ byte[] bytes = (byte[]) is.readObject();
+
+ ht.put(key, decode(bytes));
+ }
+ } catch (ObjectStreamException e) {
+ Debug.trace("Key " + key); // would be nice to know object type.
+ throw e;
+ } catch (IOException e) {
+ Debug.trace("Key " + key); // would be nice to know object type.
+ throw e;
+ } catch (ClassNotFoundException e) {
+ Debug.trace("Key " + key); // would be nice to know object type.
+ throw e;
+ }
+
+ return ht;
+ }
+
+ /**
+ * Implements IDBAttrMapper.mapLDAPAttributeSetToObject
+ * <p>
+ *
+ * @see IDBAttrMapper#mapLDAPAttributeSetToObject
+ */
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs,
+ String name, IDBObj parent)
+ throws EBaseException {
+ Hashtable<String, Object> ht = null;
+
+ //
+ // Data is stored in a (single valued) binary attribute
+ //
+ byte[] value;
+
+ LDAPAttribute attr = null;
+
+ try {
+ attr = attrs.getAttribute(Schema.LDAP_ATTR_REQUEST_ATTRS);
+
+ if (attr != null) {
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> values = attr.getByteValues();
+
+ value = values.nextElement();
+
+ ht = decodeHashtable(value);
+ }
+ } catch (Exception x) {
+ Debug.trace("Mapping error in request Id " +
+ ((RequestRecord) parent).getRequestId().toString() + " : " + x);
+ Debug.trace("Attr " + attr.getName());
+ //if (Debug.ON) {
+ Debug.printStackTrace(x);
+ //}
+ }
+
+ parent.set(name, ht);
+ }
+
+ public String mapSearchFilter(String name, String op, String value) {
+ return Schema.LDAP_ATTR_REQUEST_ID + op + value;
+ }
+
+ protected final static Vector<String> mAttrs = new Vector<String>();
+
+ static {
+ mAttrs.add(Schema.LDAP_ATTR_REQUEST_ATTRS);
+ }
+}
+
+/**
+ * Maps dynamic data for the extData- prefix to and from the extData Hashtable
+ * in RequestRecord.
+ *
+ * The data in RequestRecord is stored in a Hashtable. It comes in two forms:
+ * 1. String key1 => String value1
+ * String key2 => String value2
+ * This is stored in LDAP as:
+ * extData-key1 => value1
+ * extData-key2 => value2
+ *
+ * 2. String key => Hashtable value
+ * where value stores:
+ * String key2 => String value2
+ * String key3 => String value3
+ * This is stored in LDAP as:
+ * extData-key;key2 => value2
+ * extData-key;key3 => value3
+ *
+ * These can be mixed, but each top-level key can only be associated with
+ * a String value or a Hashtable value.
+ *
+ */
+class ExtAttrDynMapper implements IDBDynAttrMapper {
+
+ public boolean supportsLDAPAttributeName(String attrName) {
+ return (attrName != null) &&
+ attrName.toLowerCase().startsWith(extAttrPrefix);
+ }
+
+ public Enumeration<String> getSupportedLDAPAttributeNames() {
+ return mAttrs.elements();
+ }
+
+ /**
+ * Decodes extdata encoded keys.
+ * -- followed by a 4 digit hexadecimal string is decoded to the character
+ * representing the hex string.
+ *
+ * The routine is written to be highly efficient. It only allocates
+ * the StringBuffer if needed and copies the pieces in large chunks.
+ *
+ * @param key The key to decode
+ * @return The decoded key.
+ */
+ public String decodeKey(String key) {
+ StringBuffer output = null;
+ char[] input = key.toCharArray();
+ int startCopyIndex = 0;
+
+ int index = 0;
+ while (index < input.length) {
+ if (input[index] == '-') {
+ if (((index + 1) < input.length) &&
+ (input[index + 1] == '-')) {
+ if (output == null) {
+ output = new StringBuffer(input.length);
+ }
+ output.append(input, startCopyIndex, index - startCopyIndex);
+ index += 2;
+ if ((index + 3) < input.length) {
+ output.append(
+ Character.toChars(
+ Integer.parseInt(new String(input, index, 4),
+ 16))
+ );
+ }
+ index += 4;
+ startCopyIndex = index;
+ } else {
+ index++;
+ }
+ } else {
+ index++;
+ }
+ }
+
+ if (output == null) {
+ return key;
+ } else {
+ output.append(input, startCopyIndex, index - startCopyIndex);
+ return output.toString();
+ }
+ }
+
+ /**
+ * Encoded extdata keys for storage in LDAP.
+ *
+ * The rules for encoding are trickier than decoding. We want to allow
+ * '-' by itself to be stored in the database (for the common case of keys
+ * like 'Foo-Bar'. Therefore we are using '--' as the encoding character.
+ * The rules are:
+ * 1) All characters [^-a-zA-Z0-9] are encoded as --XXXX where XXXX is the
+ * hex representation of the digit.
+ * 2) [a-zA-Z0-9] are always passed through unencoded
+ * 3) [-] is passed through as long as it is preceded and followed
+ * by [a-zA-Z0-9] (or if it's at the beginning/end of the string)
+ * 4) If [-] is preceded or followed by [^a-zA-Z0-9] then
+ * the - as well as all following [^a-zA-Z0-9] characters are encoded
+ * as --XXXX.
+ *
+ * This routine tries to be as efficient as possible with StringBuffer and
+ * large copies. However, the encoding unfortunately requires several
+ * objects to be allocated.
+ *
+ * @param key The key to encode
+ * @return The encoded key
+ */
+ public String encodeKey(String key) {
+ StringBuffer output = null;
+ char[] input = key.toCharArray();
+ int startCopyIndex = 0;
+
+ int index = 0;
+ while (index < input.length) {
+ if (!isAlphaNum(input[index])) {
+ if ((input[index] == '-') &&
+ ((index + 1) < input.length) &&
+ (isAlphaNum(input[index + 1]))) {
+ index += 2;
+ } else if ((input[index] == '-') &&
+ ((index + 1) == input.length)) {
+ index += 1;
+ } else {
+ if (output == null) {
+ output = new StringBuffer(input.length + 5);
+ }
+ output.append(input, startCopyIndex, index - startCopyIndex);
+ while ((index < input.length) &&
+ (!isAlphaNum(input[index]))) {
+ output.append("--");
+ String hexString = Integer.toHexString(input[index]);
+ int padding = 4 - hexString.length();
+ while (padding > 0) {
+ output.append('0');
+ padding--;
+ }
+ output.append(hexString);
+ index++;
+ }
+ startCopyIndex = index;
+ }
+ } else {
+ index++;
+ }
+ }
+
+ if (output == null) {
+ return key;
+ } else {
+ output.append(input, startCopyIndex, index - startCopyIndex);
+ return output.toString();
+ }
+ }
+
+ protected boolean isAlphaNum(char in) {
+ if ((in >= 'a') && (in <= 'z')) {
+ return true;
+ }
+ if ((in >= 'A') && (in <= 'Z')) {
+ return true;
+ }
+ if ((in >= '0') && (in <= '9')) {
+ return true;
+ }
+ return false;
+ }
+
+ public void mapObjectToLDAPAttributeSet(IDBObj parent, String name,
+ Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ if (obj == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name));
+ }
+ @SuppressWarnings("unchecked")
+ Hashtable<String, Object> ht = (Hashtable<String, Object>) obj;
+ Enumeration<String> e = ht.keys();
+
+ while (e.hasMoreElements()) {
+ String key = e.nextElement();
+ Object value = ht.get(key);
+ if (value instanceof String) {
+ String stringValue = (String) value;
+ attrs.add(new LDAPAttribute(
+ extAttrPrefix + encodeKey(key),
+ stringValue));
+ } else if (value instanceof Hashtable) {
+ @SuppressWarnings("unchecked")
+ Hashtable<String, String> innerHash = (Hashtable<String, String>) value;
+ Enumeration<String> innerHashEnum = innerHash.keys();
+ while (innerHashEnum.hasMoreElements()) {
+ String innerKey = innerHashEnum.nextElement();
+ String innerValue = innerHash.get(innerKey);
+ attrs.add(new LDAPAttribute(
+ extAttrPrefix + encodeKey(key) + ";" + encodeKey(innerKey),
+ innerValue));
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, String name,
+ IDBObj parent)
+ throws EBaseException {
+ Hashtable<String, Object> ht = new Hashtable<String, Object>();
+ Hashtable<String, String> valueHashtable;
+
+ Enumeration<LDAPAttribute> attrEnum = attrs.getAttributes();
+ while (attrEnum.hasMoreElements()) {
+ LDAPAttribute attr = attrEnum.nextElement();
+ String baseName = attr.getBaseName();
+ if (baseName.toLowerCase().startsWith(extAttrPrefix)) {
+ String keyName = decodeKey(
+ baseName.substring(extAttrPrefix.length()));
+ String[] subTypes = attr.getSubtypes();
+ String[] values = attr.getStringValueArray();
+ if (values.length != 1) {
+ String message = "Output Mapping Error in request ID " +
+ ((IRequestRecord) parent).getRequestId().toString() + " : " +
+ "more than one value returned for " +
+ keyName;
+ Debug.trace(message);
+ throw new EBaseException(message);
+ }
+ if ((subTypes != null) && (subTypes.length > 0)) {
+ if (subTypes.length != 1) {
+ String message = "Output Mapping Error in request ID " +
+ ((IRequestRecord) parent).getRequestId().toString() + " : " +
+ "more than one subType returned for " +
+ keyName;
+ Debug.trace(message);
+ throw new EBaseException(message);
+ }
+ Object value = ht.get(keyName);
+ if ((value != null) && (!(value instanceof Hashtable))) {
+ String message = "Output Mapping Error in request ID " +
+ ((IRequestRecord) parent).getRequestId().toString() + " : " +
+ "combined no-subtype and subtype data for key " +
+ keyName;
+ Debug.trace(message);
+ throw new EBaseException(message);
+ }
+ valueHashtable = (Hashtable<String, String>) value;
+ if (valueHashtable == null) {
+ valueHashtable = new Hashtable<String, String>();
+ ht.put(keyName, valueHashtable);
+ }
+ valueHashtable.put(decodeKey(subTypes[0]), values[0]);
+ } else {
+ ht.put(keyName, values[0]);
+ }
+ }
+ }
+
+ parent.set(name, ht);
+ }
+
+ public String mapSearchFilter(String name, String op, String value) throws EBaseException {
+ return name + op + value;
+ }
+
+ protected final static String extAttrPrefix = "extdata-";
+
+ protected final static Vector<String> mAttrs = new Vector<String>();
+
+ static {
+ mAttrs.add(Schema.LDAP_ATTR_EXT_ATTR);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/request/RequestRepository.java b/base/server/cmscore/src/com/netscape/cmscore/request/RequestRepository.java
new file mode 100644
index 000000000..31edc31b0
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/request/RequestRepository.java
@@ -0,0 +1,217 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+import java.math.BigInteger;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSearchResults;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.dbs.repository.IRepositoryRecord;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.cmscore.dbs.Repository;
+import com.netscape.cmscore.dbs.RepositoryRecord;
+
+/**
+ * TODO: what does this class provide beyond the Repository
+ * base class??
+ * <p>
+ *
+ * @author thayes
+ * @version $Revision$ $Date$
+ */
+class RequestRepository
+ extends Repository {
+
+ IDBSubsystem mDB = null;
+ IRequestQueue mRequestQueue = null;
+
+ /**
+ * Create a request repository that uses the LDAP database
+ * <p>
+ *
+ * @param name
+ * the name of the repository. This String is used to
+ * construct the DN for the repository's LDAP entry.
+ * @param db
+ * the LDAP database system.
+ */
+ public RequestRepository(String name, int increment, IDBSubsystem db)
+ throws EDBException {
+ super(db, increment, "ou=" + name + ",ou=requests," + db.getBaseDN());
+
+ CMS.debug("RequestRepository: constructor 1");
+ mBaseDN = "ou=" + name + ",ou=requests," + db.getBaseDN();
+
+ // Let RequestRecord class register its
+ // database mapping and object mapping values
+ RequestRecord.register(db);
+ mDB = db;
+ }
+
+ public RequestRepository(String name, int increment, IDBSubsystem db, IRequestQueue requestQueue)
+ throws EDBException {
+ super(db, increment, "ou=" + name + ",ou=requests," + db.getBaseDN());
+
+ CMS.debug("RequestRepository: constructor2.");
+ mRequestQueue = requestQueue;
+ mBaseDN = "ou=" + name + ",ou=requests," + db.getBaseDN();
+
+ // Let RequestRecord class register its
+ // database mapping and object mapping values
+ RequestRecord.register(db);
+ mDB = db;
+ }
+
+ /**
+ * get the LDAP base DN for this repository. This
+ * value can be used by the request queue to create the
+ * name for the request records themselves.
+ * <p>
+ *
+ * @return
+ * the LDAP base DN.
+ */
+ public String getBaseDN() {
+ return mBaseDN;
+ }
+
+ /**
+ * Resets serial number.
+ */
+ public void resetSerialNumber(BigInteger serial) throws EBaseException {
+ setTheSerialNumber(serial);
+ }
+
+ /**
+ * Removes all objects with this repository.
+ */
+ public void removeAllObjects() throws EBaseException {
+ IDBSSession s = mDB.createSession();
+ try {
+ IDBSearchResults sr = s.search(getBaseDN(),
+ "(" + RequestRecord.ATTR_REQUEST_ID + "=*)");
+ while (sr.hasMoreElements()) {
+ RequestRecord r = (RequestRecord) sr.nextElement();
+ String name = "cn" + "=" +
+ r.getRequestId().toString() + "," + getBaseDN();
+ s.delete(name);
+ }
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ }
+
+ public BigInteger getLastSerialNumberInRange(BigInteger min, BigInteger max) {
+
+ CMS.debug("RequestRepository: in getLastSerialNumberInRange: min " + min + " max " + max);
+
+ CMS.debug("RequestRepository: mRequestQueue " + mRequestQueue);
+
+ BigInteger ret = null;
+
+ if (mRequestQueue == null) {
+
+ CMS.debug("RequestRepository: mRequestQueue is null.");
+
+ } else {
+
+ CMS.debug("RequestRepository: about to call mRequestQueue.getLastRequestIdInRange");
+ ret = mRequestQueue.getLastRequestIdInRange(min, max);
+
+ }
+
+ return ret;
+
+ }
+
+ /**
+ * the LDAP base DN for this repository
+ */
+ protected String mBaseDN;
+
+ public String getPublishingStatus() {
+ RepositoryRecord record = null;
+ Object obj = null;
+ IDBSSession dbs = null;
+ String status = null;
+
+ try {
+ dbs = mDB.createSession();
+ obj = dbs.read(mBaseDN);
+ } catch (Exception e) {
+ CMS.debug("RequestRepository: getPublishingStatus: Error: " + e);
+ CMS.debugStackTrace();
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null) {
+ try {
+ dbs.close();
+ } catch (Exception ex) {
+ CMS.debug("RequestRepository: getPublishingStatus: Error: " + ex);
+ }
+ }
+ }
+
+ if (obj != null && (obj instanceof RepositoryRecord)) {
+ record = (RepositoryRecord) obj;
+ status = record.getPublishingStatus();
+ } else {
+ CMS.debug("RequestRepository: obj is NOT instanceof RepositoryRecord");
+ }
+ CMS.debug("RequestRepository: getPublishingStatus mBaseDN: " + mBaseDN +
+ " status: " + ((status != null) ? status : "null"));
+
+ return status;
+ }
+
+ public void setPublishingStatus(String status) {
+ IDBSSession dbs = null;
+
+ CMS.debug("RequestRepository: setPublishingStatus mBaseDN: " + mBaseDN + " status: " + status);
+ ModificationSet mods = new ModificationSet();
+
+ if (status != null && status.length() > 0) {
+ mods.add(IRepositoryRecord.ATTR_PUB_STATUS,
+ Modification.MOD_REPLACE, status);
+
+ try {
+ dbs = mDB.createSession();
+ dbs.modify(mBaseDN, mods);
+ } catch (Exception e) {
+ CMS.debug("RequestRepository: setPublishingStatus: Error: " + e);
+ CMS.debugStackTrace();
+ } finally {
+ // Close session - ignoring errors (UTIL)
+ if (dbs != null) {
+ try {
+ dbs.close();
+ } catch (Exception ex) {
+ CMS.debug("RequestRepository: setPublishingStatus: Error: " + ex);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/request/RequestSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/request/RequestSubsystem.java
new file mode 100644
index 000000000..78d312851
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/request/RequestSubsystem.java
@@ -0,0 +1,186 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.INotify;
+import com.netscape.certsrv.request.IPolicy;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.IRequestSubsystem;
+import com.netscape.certsrv.request.IService;
+import com.netscape.cmscore.dbs.DBSubsystem;
+
+/**
+ * RequestSubsystem
+ * <p>
+ * This class is reponsible for managing storage of request objects in the local database.
+ * <p>
+ * TODO: review this It provides: + registration of LDAP/JAVA mapping classes with the DBSubsystem + creation of
+ * RequestQueue storage in the database + retrieval of existing RequestQueue objects from the database
+ * <p>
+ *
+ * @author thayes
+ * @version $Revision$, $Date$
+ */
+public class RequestSubsystem
+ implements IRequestSubsystem, ISubsystem {
+
+ public final static String ID = IRequestSubsystem.SUB_ID;
+
+ // singleton enforcement
+
+ private static RequestSubsystem mInstance = new RequestSubsystem();
+
+ public static RequestSubsystem getInstance() {
+ return mInstance;
+ }
+
+ private RequestSubsystem() {
+ }
+
+ // end singleton enforcement.
+
+ //
+ // Create a new request queue. The LDAP DN for the entry
+ // in the database is supplied by the caller.
+ //
+ public void createRequestQueue(String name)
+ throws EBaseException {
+
+ /*
+ String dbName = makeQueueName(name);
+ IDBSSession dbs = createDBSSession();
+
+ // Create Repository record here
+
+ dbs.add(dbName, r);
+ */
+ }
+
+ public IRequestQueue
+ getRequestQueue(String name, int increment, IPolicy p, IService s, INotify n)
+ throws EBaseException {
+ return getRequestQueue(name, increment, p, s, n, null);
+ }
+
+ public IRequestQueue
+ getRequestQueue(String name, int increment, IPolicy p, IService s, INotify n,
+ INotify pendingNotifier)
+ throws EBaseException {
+ RequestQueue rq = new RequestQueue(name, increment, p, s, n, pendingNotifier);
+
+ // can't do this here because the service depends on getting rq
+ // (to get request) and since this method hasn't returned it's rq is null.
+ //rq.recover();
+
+ return rq;
+ }
+
+ //
+ // ISubsystem methods:
+ // getId, setId, init, startup, shutdown, getConfigStore
+ //
+
+ /**
+ * Implements ISubsystem.getId
+ * <p>
+ *
+ * @see ISubsystem#getId
+ */
+ public String getId() {
+ return mId;
+ }
+
+ // ISubsystem.setId
+ public void setId(String id)
+ throws EBaseException {
+ mId = id;
+ }
+
+ // ISubsystem.init
+ public void init(ISubsystem parent, IConfigStore config) {
+ mParent = parent;
+ mConfig = config;
+ }
+
+ /**
+ * Implements ISubsystem.startup
+ * <p>
+ *
+ * @see ISubsystem#startup
+ */
+ public void startup()
+ throws EBaseException {
+ mLogger = CMS.getLogger();
+
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_REQQUEUE, ILogger.LL_INFO,
+ "Request subsystem started");
+ }
+
+ public void shutdown() {
+
+ if (mLogger != null) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_REQQUEUE, ILogger.LL_INFO,
+ "Request subsystem stopped");
+ }
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ //
+ // Access to the DBSubsystem environment value
+ //
+ protected IDBSubsystem getDBSubsystem() {
+ return DBSubsystem.getInstance();
+ }
+
+ //
+ // Create a database session in the default database
+ // system.
+ //
+ protected IDBSSession createDBSSession()
+ throws EBaseException {
+ return getDBSubsystem().createSession();
+ }
+
+ //
+ // Make a queue name
+ //
+ protected String makeQueueName(String name) {
+ IDBSubsystem db = getDBSubsystem();
+
+ return "cn=" + name + "," + db.getBaseDN();
+ }
+
+ // Instance variables
+
+ private IConfigStore mConfig;
+ @SuppressWarnings("unused")
+ private ISubsystem mParent;
+ private String mId = IRequestSubsystem.SUB_ID;
+
+ protected ILogger mLogger;
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/request/Schema.java b/base/server/cmscore/src/com/netscape/cmscore/request/Schema.java
new file mode 100644
index 000000000..89a7b74b9
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/request/Schema.java
@@ -0,0 +1,50 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.request;
+
+//
+// The Schema class contains constant string values for
+// LDAP attribute and object class names used in this package
+//
+class Schema {
+ public static final String LDAP_OC_TOP = "top";
+ public static final String LDAP_OC_REQUEST = "request";
+ public static final String LDAP_OC_EXTENSIBLE = "extensibleObject";
+
+ public static final String LDAP_ATTR_REQUEST_ID = "requestId";
+ public static final String LDAP_ATTR_REQUEST_STATE = "requestState";
+ public static final String LDAP_ATTR_CREATE_TIME = "dateOfCreate";
+ public static final String LDAP_ATTR_MODIFY_TIME = "dateOfModify";
+ public static final String LDAP_ATTR_REQUEST_XATTRS = "adminMessages";
+ public static final String LDAP_ATTR_SOURCE_ID = "requestSourceId";
+
+ public static final String LDAP_ATTR_REQUEST_OWNER = "requestOwner";
+ public static final String LDAP_ATTR_REQUEST_ATTRS = "requestAttributes";
+ public static final String LDAP_ATTR_AGENT_GROUP = "requestAgentGroup";
+ public static final String LDAP_ATTR_REQUEST_TYPE = "requestType";
+ public static final String LDAP_ATTR_REQUEST_ERROR = "requestError";
+
+ // This attribute is a placeholder used by ExtAttrDynMapper
+ public static final String LDAP_ATTR_EXT_ATTR = "extAttr";
+
+ // Indicates a special state that may be searched for exactly
+ // such as requiresAgentService. The idea is to reduce the space
+ // used in indexes to optimize common queries.
+ // NOT IMPLEMENTED
+ public static final String LDAP_ATTR_REQUEST_FLAG = "requestFlag";
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/security/CASigningCert.java b/base/server/cmscore/src/com/netscape/cmscore/security/CASigningCert.java
new file mode 100644
index 000000000..701ac4c18
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/security/CASigningCert.java
@@ -0,0 +1,161 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.KeyPair;
+
+import netscape.security.x509.KeyUsageExtension;
+
+import org.mozilla.jss.crypto.PQGParamGenException;
+import org.mozilla.jss.crypto.PQGParams;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ConfigConstants;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.security.KeyCertData;
+
+/**
+ * CA signing certificate.
+ *
+ * @author Christine Ho
+ * @version $Revision$, $Date$
+ */
+public class CASigningCert extends CertificateInfo {
+
+ public static final String SUBJECT_NAME =
+ "CN=Certificate Authority, O=Netscape Communications, C=US";
+
+ public CASigningCert(KeyCertData properties) {
+ this(properties, null);
+ }
+
+ public CASigningCert(KeyCertData properties, KeyPair pair) {
+ super(properties, pair);
+ /* included in console UI
+ try {
+ if (mProperties.get(Constants.PR_AKI) == null) {
+ mProperties.put(Constants.PR_AKI, Constants.FALSE);
+ }
+ } catch (Exception e) {
+ mProperties.put(Constants.PR_AKI, Constants.FALSE);
+ }
+ */
+ try {
+ if (mProperties.get(Constants.PR_CERT_LEN) == null) {
+ mProperties.put(Constants.PR_CERT_LEN, "-1");
+ }
+ } catch (Exception e) {
+ mProperties.put(Constants.PR_CERT_LEN, "-1");
+ }
+ try {
+ if (mProperties.get(Constants.PR_IS_CA) == null) {
+ // "null" mean no BasicConstriant
+ mProperties.put(Constants.PR_IS_CA, "null");
+ }
+ } catch (Exception e) {
+ // "null" mean no BasicConstriant
+ mProperties.put(Constants.PR_IS_CA, "null");
+ }
+ /* included in console UI
+ try {
+ if (mProperties.get(Constants.PR_SKI) == null) {
+ mProperties.put(Constants.PR_SKI, Constants.FALSE);
+ }
+ } catch (Exception e) {
+ mProperties.put(Constants.PR_SKI, Constants.FALSE);
+ }
+ */
+ }
+
+ public String getSubjectName() {
+ return (String) mProperties.get(Constants.PR_SUBJECT_NAME);
+ }
+
+ // get PQG params from the configuration file
+ public PQGParams getPQGParams() throws EBaseException, IOException, PQGParamGenException {
+
+ byte[] p = mConfig.getByteArray("ca.dsaP", null);
+ byte[] q = mConfig.getByteArray("ca.dsaQ", null);
+ byte[] g = mConfig.getByteArray("ca.dsaG", null);
+ byte[] seed = mConfig.getByteArray("ca.dsaSeed", null);
+ byte[] H = mConfig.getByteArray("ca.dsaH", null);
+ int counter = mConfig.getInteger("ca.dsaCounter", 0);
+
+ if (p != null && q != null && g != null) {
+ BigInteger P = new BigInteger(p);
+ BigInteger Q = new BigInteger(q);
+ BigInteger G = new BigInteger(g);
+ BigInteger pqgSeed = new BigInteger(seed);
+ BigInteger pqgH = new BigInteger(H);
+
+ return new PQGParams(P, Q, G, pqgSeed, counter, pqgH);
+ }
+ return null;
+ }
+
+ public void updateConfig(IConfigStore cmsFileTmp) throws EBaseException {
+ String tokenname = (String) mProperties.get(Constants.PR_TOKEN_NAME);
+ String nickname = getNickname();
+
+ cmsFileTmp.putString("ca.signing.tokenname", tokenname);
+ String keyType = (String) mProperties.get(Constants.PR_KEY_TYPE);
+ String alg = "";
+
+ if (keyType.equals("DSA"))
+ alg = "SHA1withDSA";
+ else if (keyType.equals("RSA"))
+ alg = "SHA1withRSA";
+ else
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED", keyType));
+
+ cmsFileTmp.putString("ca.signing.defaultSigningAlgorithm", alg);
+ if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME))
+ cmsFileTmp.putString("ca.signing.cacertnickname", nickname);
+ else
+ cmsFileTmp.putString("ca.signing.cacertnickname",
+ tokenname + ":" + nickname);
+ cmsFileTmp.commit(false);
+ }
+
+ public String getNickname() {
+ String name = (String) mProperties.get(Constants.PR_NICKNAME);
+ String instanceName = (String) mProperties.get(ConfigConstants.PR_CERT_INSTANCE_NAME);
+
+ if (name != null)
+ return name;
+ return "caSigningCert " + instanceName;
+ }
+
+ public String getKeyAlgorithm() {
+ return (String) mProperties.get(Constants.PR_KEY_TYPE);
+ }
+
+ protected KeyUsageExtension getKeyUsageExtension() throws IOException {
+ KeyUsageExtension extension = new KeyUsageExtension();
+
+ extension.set(KeyUsageExtension.DIGITAL_SIGNATURE,Boolean.valueOf(true));
+ extension.set(KeyUsageExtension.NON_REPUDIATION, Boolean.valueOf(true));
+ extension.set(KeyUsageExtension.KEY_CERTSIGN, Boolean.valueOf(true));
+ extension.set(KeyUsageExtension.CRL_SIGN, Boolean.valueOf(true));
+ return extension;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/security/CertificateInfo.java b/base/server/cmscore/src/com/netscape/cmscore/security/CertificateInfo.java
new file mode 100644
index 000000000..58eb9ae63
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/security/CertificateInfo.java
@@ -0,0 +1,280 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateParsingException;
+import java.util.Calendar;
+import java.util.Date;
+
+import netscape.security.util.DerInputStream;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.AuthorityKeyIdentifierExtension;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateIssuerName;
+import netscape.security.x509.CertificateSerialNumber;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.KeyIdentifier;
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.SubjectKeyIdentifierExtension;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.crypto.PQGParamGenException;
+import org.mozilla.jss.crypto.SignatureAlgorithm;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ConfigConstants;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.security.KeyCertData;
+
+/**
+ * This base class provides methods to import CA signing cert or get certificate
+ * request.
+ *
+ * @author Christine Ho
+ * @version $Revision$, $Date$
+ */
+public abstract class CertificateInfo {
+
+ protected KeyCertData mProperties;
+ protected KeyPair mKeyPair;
+ protected IConfigStore mConfig;
+
+ public CertificateInfo(KeyCertData properties) {
+ this(properties, null);
+ }
+
+ public CertificateInfo(KeyCertData properties, KeyPair pair) {
+ mProperties = properties;
+ if (pair == null) {
+ mKeyPair = (KeyPair) properties.get("keypair");
+ } else {
+ mKeyPair = pair;
+ }
+ mConfig = (IConfigStore) (mProperties.get("cmsFile"));
+ }
+
+ protected abstract KeyUsageExtension getKeyUsageExtension() throws IOException;
+
+ public abstract String getSubjectName();
+
+ //public abstract SignatureAlgorithm getSigningAlgorithm();
+ public abstract String getKeyAlgorithm();
+
+ public abstract String getNickname();
+
+ public abstract void updateConfig(IConfigStore store) throws EBaseException;
+
+ public CertificateValidity getCertificateValidity() throws EBaseException {
+
+ /*
+ String period = (String)mProperties.get(Constants.PR_VALIDITY_PERIOD);
+ Date notBeforeDate = CMS.getCurrentDate();
+ Date notAfterDate = new Date(notBeforeDate.getYear(),
+ notBeforeDate.getMonth(),
+ notBeforeDate.getDate()+Integer.parseInt(period));
+ return new CertificateValidity(notBeforeDate, notAfterDate);
+ */
+ Date notBeforeDate = null;
+ Date notAfterDate = null;
+ String notBeforeStr = (String) mProperties.get("notBeforeStr");
+ String notAfterStr = (String) mProperties.get("notAfterStr");
+
+ if (notBeforeStr != null && notAfterStr != null) {
+ notBeforeDate = new Date(Long.parseLong(notBeforeStr));
+ notAfterDate = new Date(Long.parseLong(notAfterStr));
+ } else {
+ int beginYear =
+ Integer.parseInt(mProperties.getBeginYear()) - 1900;
+ int afterYear =
+ Integer.parseInt(mProperties.getAfterYear()) - 1900;
+ int beginMonth =
+ Integer.parseInt(mProperties.getBeginMonth());
+ int afterMonth =
+ Integer.parseInt(mProperties.getAfterMonth());
+ int beginDate =
+ Integer.parseInt(mProperties.getBeginDate());
+ int afterDate =
+ Integer.parseInt(mProperties.getAfterDate());
+ int beginHour =
+ Integer.parseInt(mProperties.getBeginHour());
+ int afterHour =
+ Integer.parseInt(mProperties.getAfterHour());
+ int beginMin =
+ Integer.parseInt(mProperties.getBeginMin());
+ int afterMin =
+ Integer.parseInt(mProperties.getAfterMin());
+ int beginSec =
+ Integer.parseInt(mProperties.getBeginSec());
+ int afterSec =
+ Integer.parseInt(mProperties.getAfterSec());
+
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(beginYear, beginMonth, beginDate,
+ beginHour, beginMin, beginSec);
+ notBeforeDate = calendar.getTime();
+ calendar.set(afterYear, afterMonth, afterDate,
+ afterHour, afterMin, afterSec);
+ notAfterDate = calendar.getTime();
+ }
+ return new CertificateValidity(notBeforeDate, notAfterDate);
+ }
+
+ public X509CertInfo getCertInfo() throws EBaseException, PQGParamGenException {
+ X509CertInfo certInfo = new X509CertInfo();
+
+ try {
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ BigInteger serialNumber = mProperties.getSerialNumber();
+
+ certInfo.set(X509CertInfo.SERIAL_NUMBER,
+ new CertificateSerialNumber(serialNumber));
+ certInfo.set(X509CertInfo.EXTENSIONS, getExtensions());
+ certInfo.set(X509CertInfo.VALIDITY, getCertificateValidity());
+ String issuerName = mProperties.getIssuerName();
+
+ if (issuerName == null) {
+ issuerName = getSubjectName();
+ }
+
+ certInfo.set(X509CertInfo.ISSUER,
+ new CertificateIssuerName(new X500Name(issuerName)));
+ certInfo.set(X509CertInfo.SUBJECT,
+ new CertificateSubjectName(new X500Name(getSubjectName())));
+ certInfo.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+
+ PublicKey pubk = mKeyPair.getPublic();
+ X509Key xKey = KeyCertUtil.convertPublicKeyToX509Key(pubk);
+
+ certInfo.set(X509CertInfo.KEY, new CertificateX509Key(xKey));
+ //SignatureAlgorithm algm = getSigningAlgorithm();
+ SignatureAlgorithm algm =
+ (SignatureAlgorithm) mProperties.get(Constants.PR_SIGNATURE_ALGORITHM);
+
+ if (algm == null) {
+ String hashtype = (String) mProperties.get(ConfigConstants.PR_HASH_TYPE);
+ String key = getKeyAlgorithm();
+ algm = KeyCertUtil.getSigningAlgorithm(key, hashtype);
+ if (algm == null) {
+ throw new NoSuchAlgorithmException("Key : " + key + "/ Hashtype : " + hashtype);
+ }
+ mProperties.put(Constants.PR_SIGNATURE_ALGORITHM, algm);
+ }
+
+ AlgorithmId sigAlgId = getAlgorithmId();
+
+ if (sigAlgId == null) {
+ byte[] encodedOID = ASN1Util.encode(algm.toOID());
+
+ sigAlgId = new AlgorithmId(new ObjectIdentifier(
+ new DerInputStream(encodedOID)));
+ }
+ certInfo.set(X509CertInfo.ALGORITHM_ID,
+ new CertificateAlgorithmId(sigAlgId));
+ } catch (InvalidKeyException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY"));
+ } catch (CertificateException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_CERT", e.toString()));
+ } catch (IOException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_CERT", e.toString()));
+ } catch (NoSuchAlgorithmException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED", e.getMessage()));
+ }
+
+ return certInfo;
+ }
+
+ public CertificateExtensions getExtensions() throws IOException,
+ CertificateException, InvalidKeyException, NoSuchAlgorithmException {
+ CertificateExtensions exts = new CertificateExtensions();
+
+ KeyCertUtil.setExtendedKeyUsageExtension(exts, mProperties);
+ KeyCertUtil.setDERExtension(exts, mProperties);
+ KeyCertUtil.setBasicConstraintsExtension(exts, mProperties);
+ KeyCertUtil.setSubjectKeyIdentifier(mKeyPair, exts, mProperties);
+ //KeyCertUtil.setOCSPSigning(mKeyPair, exts, mProperties);
+ KeyCertUtil.setAuthInfoAccess(mKeyPair, exts, mProperties);
+ KeyCertUtil.setOCSPNoCheck(mKeyPair, exts, mProperties);
+ String aki = mProperties.getAKI();
+
+ if ((aki != null) && (aki.equals(Constants.TRUE))) {
+ CertificateExtensions caexts = null;
+
+ // if (this instanceof CASigningCert) {
+ if (this.getClass().getName().indexOf("CASigningCert") != -1) {
+ caexts = exts;
+ } else {
+ caexts = mProperties.getCAExtensions();
+ }
+ setAuthorityKeyIdExt(caexts, exts);
+ }
+ boolean isKeyUsageEnabled = mProperties.getKeyUsageExtension();
+
+ if (isKeyUsageEnabled) {
+ KeyCertUtil.setKeyUsageExtension(
+ exts, getKeyUsageExtension());
+ }
+ return exts;
+ }
+
+ public AlgorithmId getAlgorithmId() {
+ return (AlgorithmId) (mProperties.get(Constants.PR_ALGORITHM_ID));
+ }
+
+ public void setAuthorityKeyIdExt(CertificateExtensions caexts, CertificateExtensions ext)
+ throws IOException, CertificateException, CertificateEncodingException,
+ CertificateParsingException {
+ SubjectKeyIdentifierExtension subjKeyExt = null;
+
+ try {
+ subjKeyExt =
+ (SubjectKeyIdentifierExtension) caexts.get(SubjectKeyIdentifierExtension.NAME);
+ } catch (IOException e) {
+ }
+
+ if (subjKeyExt == null)
+ return;
+ else {
+ KeyIdentifier keyId = (KeyIdentifier) subjKeyExt.get(
+ SubjectKeyIdentifierExtension.KEY_ID);
+ AuthorityKeyIdentifierExtension authExt =
+ new AuthorityKeyIdentifierExtension(false, keyId, null, null);
+
+ ext.set(AuthorityKeyIdentifierExtension.NAME, authExt);
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/security/JssSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/security/JssSubsystem.java
new file mode 100644
index 000000000..e3b744220
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/security/JssSubsystem.java
@@ -0,0 +1,2174 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.math.BigInteger;
+import java.net.SocketException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import netscape.ldap.util.DN;
+import netscape.security.x509.AlgIdDSA;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.NicknameConflictException;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.CryptoManager.UserCertConflictException;
+import org.mozilla.jss.NoSuchTokenException;
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.asn1.SET;
+import org.mozilla.jss.crypto.AlreadyInitializedException;
+import org.mozilla.jss.crypto.CryptoStore;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.InternalCertificate;
+import org.mozilla.jss.crypto.KeyPairAlgorithm;
+import org.mozilla.jss.crypto.NoSuchItemOnTokenException;
+import org.mozilla.jss.crypto.ObjectNotFoundException;
+import org.mozilla.jss.crypto.PQGParamGenException;
+import org.mozilla.jss.crypto.PQGParams;
+import org.mozilla.jss.crypto.PrivateKey;
+import org.mozilla.jss.crypto.SignatureAlgorithm;
+import org.mozilla.jss.crypto.TokenCertificate;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.pkcs11.PK11SecureRandom;
+import org.mozilla.jss.pkcs7.ContentInfo;
+import org.mozilla.jss.pkcs7.SignedData;
+import org.mozilla.jss.pkix.cert.Certificate;
+import org.mozilla.jss.ssl.SSLServerSocket;
+import org.mozilla.jss.ssl.SSLSocket;
+import org.mozilla.jss.util.IncorrectPasswordException;
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.util.PasswordCallback;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.security.ICryptoSubsystem;
+import com.netscape.certsrv.security.KeyCertData;
+import com.netscape.cmscore.cert.CertPrettyPrint;
+import com.netscape.cmscore.cert.CertUtils;
+import com.netscape.cmscore.util.Debug;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * Subsystem for initializing JSS>
+ * <P>
+ *
+ * @version $Revision$ $Date$
+ */
+public final class JssSubsystem implements ICryptoSubsystem {
+ public static final String ID = "jss";
+
+ private static final String CONFIG_DIR = "configDir";
+ private static final String PROP_ENABLE = "enable";
+ private static final String PASSWORD_ALIAS = "password";
+ private static final String mId = ID;
+ protected IConfigStore mConfig = null;
+ private boolean mInited = false;
+ private ILogger mLogger = null;
+ private CryptoManager mCryptoManager = null;
+
+ protected PasswordCallback mPWCB = null;
+
+ private static JssSubsystem mInstance = new JssSubsystem();
+ private Hashtable<String, X509Certificate[]> mNicknameMapCertsTable = new Hashtable<String, X509Certificate[]>();
+ private Hashtable<String, X509Certificate[]> mNicknameMapUserCertsTable =
+ new Hashtable<String, X509Certificate[]>();
+
+ private FileInputStream devRandomInputStream = null;
+
+ // This date format is to format the date string of the certificate in such a way as
+ // May 01, 1999 01:55:55.
+ private static SimpleDateFormat mFormatter = new SimpleDateFormat("MMMMM dd, yyyy HH:mm:ss");
+
+ // SSL related variables.
+
+ private IConfigStore mSSLConfig = null;
+
+ private static final String PROP_SSL = "ssl";
+ private static final String PROP_SSL_CIPHERPREF = Constants.PR_CIPHER_PREF;
+ private static final String PROP_SSL_ECTYPE = Constants.PR_ECTYPE;
+
+ private static Hashtable<String, Integer> mCipherNames = new Hashtable<String, Integer>();
+
+ /* default sslv2 and sslv3 cipher suites(all), set if no prefs in config.*/
+ private static final String DEFAULT_CIPHERPREF =
+ "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA," +
+ "TLS_RSA_WITH_AES_128_CBC_SHA," +
+ "TLS_RSA_WITH_AES_256_CBC_SHA," +
+ "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA," +
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA," +
+ // "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA," +
+ // "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA," +
+ // "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA," +
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA," +
+ "TLS_DHE_DSS_WITH_AES_256_CBC_SHA," +
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA," +
+ "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
+
+ /* list of all ciphers JSS supports */
+ private static final int mJSSCipherSuites[] = {
+ SSLSocket.SSL2_RC4_128_WITH_MD5,
+ SSLSocket.SSL2_RC4_128_EXPORT40_WITH_MD5,
+ SSLSocket.SSL2_RC2_128_CBC_WITH_MD5,
+ SSLSocket.SSL2_RC2_128_CBC_EXPORT40_WITH_MD5,
+ SSLSocket.SSL2_DES_64_CBC_WITH_MD5,
+ SSLSocket.SSL2_DES_192_EDE3_CBC_WITH_MD5,
+ SSLSocket.SSL3_RSA_EXPORT_WITH_RC4_40_MD5,
+ SSLSocket.SSL3_RSA_WITH_RC4_128_MD5,
+ SSLSocket.SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
+ SSLSocket.SSL3_RSA_WITH_DES_CBC_SHA,
+ SSLSocket.SSL3_RSA_WITH_3DES_EDE_CBC_SHA,
+ SSLSocket.SSL3_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA,
+ SSLSocket.SSL3_FORTEZZA_DMS_WITH_RC4_128_SHA,
+ SSLSocket.TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,
+ SSLSocket.TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,
+ };
+
+ static {
+
+ /* set ssl cipher string names. */
+ /* disallowing SSL2 ciphers to be turned on
+ mCipherNames.put(Constants.PR_SSL2_RC4_128_WITH_MD5,
+ Integer.valueOf(SSLSocket.SSL2_RC4_128_WITH_MD5));
+ mCipherNames.put(Constants.PR_SSL2_RC4_128_EXPORT40_WITH_MD5,
+ Integer.valueOf(SSLSocket.SSL2_RC4_128_EXPORT40_WITH_MD5));
+ mCipherNames.put(Constants.PR_SSL2_RC2_128_CBC_WITH_MD5,
+ Integer.valueOf(SSLSocket.SSL2_RC2_128_CBC_WITH_MD5));
+ mCipherNames.put(Constants.PR_SSL2_RC2_128_CBC_EXPORT40_WITH_MD5,
+ Integer.valueOf(SSLSocket.SSL2_RC2_128_CBC_EXPORT40_WITH_MD5));
+ mCipherNames.put(Constants.PR_SSL2_DES_64_CBC_WITH_MD5,
+ Integer.valueOf(SSLSocket.SSL2_DES_64_CBC_WITH_MD5));
+ mCipherNames.put(Constants.PR_SSL2_DES_192_EDE3_CBC_WITH_MD5,
+ Integer.valueOf(SSLSocket.SSL2_DES_192_EDE3_CBC_WITH_MD5));
+ */
+ mCipherNames.put(Constants.PR_SSL3_RSA_WITH_NULL_MD5,
+ Integer.valueOf(SSLSocket.SSL3_RSA_WITH_NULL_MD5));
+ mCipherNames.put(Constants.PR_SSL3_RSA_EXPORT_WITH_RC4_40_MD5,
+ Integer.valueOf(SSLSocket.SSL3_RSA_EXPORT_WITH_RC4_40_MD5));
+ mCipherNames.put(Constants.PR_SSL3_RSA_WITH_RC4_128_MD5,
+ Integer.valueOf(SSLSocket.SSL3_RSA_WITH_RC4_128_MD5));
+ mCipherNames.put(Constants.PR_SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
+ Integer.valueOf(SSLSocket.SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5));
+ mCipherNames.put(Constants.PR_SSL3_RSA_WITH_DES_CBC_SHA,
+ Integer.valueOf(SSLSocket.SSL3_RSA_WITH_DES_CBC_SHA));
+ mCipherNames.put(Constants.PR_SSL3_RSA_WITH_3DES_EDE_CBC_SHA,
+ Integer.valueOf(SSLSocket.SSL3_RSA_WITH_3DES_EDE_CBC_SHA));
+ mCipherNames.put(Constants.PR_SSL3_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA,
+ Integer.valueOf(SSLSocket.SSL3_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA));
+ mCipherNames.put(Constants.PR_SSL3_FORTEZZA_DMS_WITH_RC4_128_SHA,
+ Integer.valueOf(SSLSocket.SSL3_FORTEZZA_DMS_WITH_RC4_128_SHA));
+ mCipherNames.put(Constants.PR_SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,
+ Integer.valueOf(SSLSocket.SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA));
+ mCipherNames.put(Constants.PR_SSL_RSA_FIPS_WITH_DES_CBC_SHA,
+ Integer.valueOf(SSLSocket.SSL_RSA_FIPS_WITH_DES_CBC_SHA));
+ mCipherNames.put(Constants.PR_TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,
+ Integer.valueOf(SSLSocket.TLS_RSA_EXPORT1024_WITH_RC4_56_SHA));
+ mCipherNames.put(Constants.PR_TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,
+ Integer.valueOf(SSLSocket.TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA));
+ }
+
+ public static JssSubsystem getInstance() {
+ return mInstance;
+ }
+
+ /**
+ * Constructs a Security service subsystem.
+ */
+ private JssSubsystem() {
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ public void setId(String id) throws EBaseException {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION"));
+
+ }
+
+ // Add entropy to the 'default' RNG token
+ public void addEntropy(int bits)
+ throws org.mozilla.jss.util.NotImplementedException,
+ IOException,
+ TokenException {
+ int read = 0;
+ int bytes = (7 + bits) / 8;
+ byte[] b = new byte[bytes];
+ if (devRandomInputStream == null) {
+ throw new IOException(CMS.getLogMessage("CMSCORE_SECURITY_NO_ENTROPY_STREAM"));
+ }
+ do {
+ int c = devRandomInputStream.read(b, read, bytes - read);
+ read += c;
+ } while (read < bytes);
+
+ CMS.debug("JssSubsystem adding " + bits + " bits (" + bytes + " bytes) of entropy to default RNG token");
+ CMS.debug(b);
+ PK11SecureRandom sr = new PK11SecureRandom();
+ sr.setSeed(b);
+ }
+
+ /**
+ * Initializes the Jss security subsystem.
+ * <P>
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mLogger = CMS.getLogger();
+
+ if (mInited) {
+ // This used to throw an exeception (e.g. - on Solaris).
+ // If JSS is already initialized simply return.
+ CMS.debug("JssSubsystem already inited.. returning.");
+ return;
+ }
+
+ mConfig = config;
+
+ // If disabled, just return
+ boolean enabled = config.getBoolean(PROP_ENABLE, true);
+
+ if (!enabled)
+ return;
+
+ try {
+ devRandomInputStream = new FileInputStream("/dev/urandom");
+ } catch (IOException ioe) {
+ // XXX - add new exception
+ }
+
+ // get hardcoded password (for debugging.
+ String pw;
+
+ if ((pw = config.getString(PASSWORD_ALIAS, null)) != null) {
+ // hardcoded password in config file
+ mPWCB = new Password(pw.toCharArray());
+ CMS.debug("JssSubsystem init() got password from hardcoded in config");
+ }
+
+ String certDir;
+
+ certDir = config.getString(CONFIG_DIR, null);
+
+ CryptoManager.InitializationValues vals = new CryptoManager.InitializationValues(certDir, "", "", "secmod.db");
+
+ vals.removeSunProvider = false;
+ vals.installJSSProvider = true;
+ try {
+ CryptoManager.initialize(vals);
+ } catch (AlreadyInitializedException e) {
+ // do nothing
+ } catch (Exception e) {
+ String[] params = { mId, e.toString() };
+ EBaseException ex = new EBaseException(CMS.getUserMessage("CMS_BASE_CREATE_SERVICE_FAILED", params));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GENERAL_ERROR", ex.toString()));
+ throw ex;
+ }
+
+ try {
+ mCryptoManager = CryptoManager.getInstance();
+ initSSL();
+ } catch (CryptoManager.NotInitializedException e) {
+ String[] params = { mId, e.toString() };
+ EBaseException ex = new EBaseException(CMS.getUserMessage("CMS_BASE_CREATE_SERVICE_FAILED", params));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GENERAL_ERROR", ex.toString()));
+ throw ex;
+ }
+
+ mInited = true;
+ }
+
+ public String getCipherVersion() throws EBaseException {
+ return "cipherdomestic";
+ }
+
+ public String getCipherPreferences() throws EBaseException {
+ String cipherpref = "";
+
+ if (mSSLConfig != null) {
+ cipherpref = mSSLConfig.getString(PROP_SSL_CIPHERPREF, "");
+ if (cipherpref.equals("")) {
+ cipherpref = DEFAULT_CIPHERPREF;
+ }
+ }
+ return cipherpref;
+ }
+
+ public String getECType(String certType) throws EBaseException {
+ if (mSSLConfig != null) {
+ // for SSL server, check the value of jss.ssl.sslserver.ectype
+ return mSSLConfig.getString(certType + "." + PROP_SSL_ECTYPE, "ECDHE");
+ } else {
+ return "ECDHE";
+ }
+ }
+
+ public String isCipherFortezza() throws EBaseException {
+ // we always display fortezza suites.
+ // too much work to display tokens/certs corresponding to the
+ // suites.
+ return "true";
+ }
+
+ void installProvider() {
+ int position = java.security.Security.insertProviderAt(
+ new com.netscape.cmscore.security.Provider(),
+ 1);
+
+ if (position == -1) {
+ Debug.trace("Unable to install CMS provider");
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_SECURITY_INSTALL_PROVIDER"));
+ }
+ }
+
+ public void setCipherPreferences(String cipherPrefs)
+ throws EBaseException {
+ if (mSSLConfig != null) {
+ if (cipherPrefs.equals(""))
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_NO_EMPTY_CIPHERPREFS"));
+ mSSLConfig.putString(Constants.PR_CIPHER_PREF, cipherPrefs);
+ }
+ }
+
+ /**
+ * Initialize SSL cipher suites from config file.
+ *
+ */
+ private void initSSL() throws EBaseException {
+ // JSS will AND what is set and what is allowed by export policy
+ // so we can set what is requested.
+
+ try {
+ SSLServerSocket.configServerSessionIDCache(10, 0, 0, null);
+ } catch (SocketException e) {
+ }
+
+ mSSLConfig = mConfig.getSubStore(PROP_SSL);
+ String sslCiphers = null;
+
+ if (mSSLConfig != null)
+ sslCiphers = getCipherPreferences();
+ if (Debug.ON)
+ Debug.trace("configured ssl cipher prefs is " + sslCiphers);
+
+ // first, disable all ciphers, since JSS defaults to all-enabled
+ for (int i = mJSSCipherSuites.length - 1; i >= 0; i--) {
+ try {
+ SSLSocket.setCipherPreferenceDefault(mJSSCipherSuites[i],
+ false);
+ } catch (SocketException e) {
+ }
+ }
+
+ // the sslCiphers string will always contain something
+
+ if (sslCiphers != null && sslCiphers.length() != 0) {
+ StringTokenizer ciphers = new StringTokenizer(sslCiphers, ",");
+
+ if (!ciphers.hasMoreTokens()) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_SECURITY_INVALID_CIPHER", sslCiphers));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_PROPERTY", PROP_SSL_CIPHERPREF));
+ }
+ while (ciphers.hasMoreTokens()) {
+ String cipher = ciphers.nextToken();
+ Integer sslcipher = mCipherNames.get(cipher);
+
+ if (sslcipher != null) {
+ String msg = "setting ssl cipher " + cipher;
+
+ CMS.debug("JSSSubsystem: initSSL(): " + msg);
+ log(ILogger.LL_INFO, msg);
+ if (Debug.ON)
+ Debug.trace(msg);
+ try {
+ SSLSocket.setCipherPreferenceDefault(
+ sslcipher.intValue(), true);
+ } catch (SocketException e) {
+ }
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Retrieves a configuration store of this subsystem.
+ * <P>
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Starts up this service.
+ */
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Shutdowns this subsystem.
+ * <P>
+ */
+ public void shutdown() {
+ try {
+ // After talking to NSS teamm, we should not call close databases
+ // which will call NSS_Shutdown. Web Server will call NSS_Shutdown
+ boolean isClosing = mConfig.getBoolean("closeDatabases", false);
+ if (isClosing) {
+ JSSDatabaseCloser closer = new JSSDatabaseCloser();
+ closer.closeDatabases();
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ public void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, level, "JSS " + msg);
+ }
+
+ public PasswordCallback getPWCB() {
+ return mPWCB;
+ }
+
+ public String getInternalTokenName() throws EBaseException {
+ CryptoToken c = mCryptoManager.getInternalKeyStorageToken();
+ String name = "";
+
+ try {
+ name = c.getName();
+ } catch (TokenException e) {
+ String[] params = { mId, e.toString() };
+ EBaseException ex = new EBaseException(
+ CMS.getUserMessage("CMS_BASE_CREATE_SERVICE_FAILED", params));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GENERAL_ERROR", ex.toString()));
+ throw ex;
+ }
+
+ return name;
+ }
+
+ public String getTokenList() throws EBaseException {
+ StringBuffer tokenList = new StringBuffer();
+
+ @SuppressWarnings("unchecked")
+ Enumeration<CryptoToken> tokens = mCryptoManager.getExternalTokens();
+ int num = 0;
+
+ try {
+ while (tokens.hasMoreElements()) {
+ CryptoToken c = tokens.nextElement();
+
+ // skip builtin object token
+ if (c.getName() != null && c.getName().equals("Builtin Object Token")) {
+ continue;
+ }
+
+ if (num++ != 0)
+ tokenList.append(",");
+ tokenList.append(c.getName());
+ }
+ } catch (TokenException e) {
+ String[] params = { mId, e.toString() };
+ EBaseException ex = new EBaseException(
+ CMS.getUserMessage("CMS_BASE_CREATE_SERVICE_FAILED", params));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GENERAL_ERROR", ex.toString()));
+ throw ex;
+ }
+
+ if (tokenList.length()==0)
+ return Constants.PR_INTERNAL_TOKEN;
+ else
+ return tokenList.append("," + Constants.PR_INTERNAL_TOKEN).toString();
+ }
+
+ public boolean isTokenLoggedIn(String name) throws EBaseException {
+ try {
+ if (name.equals(Constants.PR_INTERNAL_TOKEN_NAME))
+ name = Constants.PR_FULL_INTERNAL_TOKEN_NAME;
+ CryptoToken ctoken = mCryptoManager.getTokenByName(name);
+
+ return ctoken.isLoggedIn();
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_TOKEN_LOGGED_IN", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_ERROR"));
+ } catch (NoSuchTokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_TOKEN_LOGGED_IN", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ }
+ }
+
+ public void loggedInToken(String tokenName, String pwd) throws EBaseException {
+ try {
+ CryptoToken ctoken = mCryptoManager.getTokenByName(tokenName);
+ Password clk = new Password(pwd.toCharArray());
+
+ ctoken.login(clk);
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_TOKEN_LOGGED_IN", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_ERROR"));
+ } catch (IncorrectPasswordException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_TOKEN_LOGGED_IN", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_LOGIN_FAILED"));
+ } catch (NoSuchTokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_TOKEN_LOGGED_IN", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ }
+ }
+
+ public String getCertSubjectName(String tokenname, String nickname)
+ throws EBaseException {
+ try {
+ return KeyCertUtil.getCertSubjectName(tokenname, nickname);
+ } catch (NoSuchTokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_SUBJECT_NAME", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_SUBJECT_NAME", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_SUBJECT_NAME", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_SUBJECT_NAME", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", ""));
+ }
+ }
+
+ public String getAllCerts() throws EBaseException {
+ StringBuffer certNames = new StringBuffer();
+
+ try {
+ @SuppressWarnings("unchecked")
+ Enumeration<CryptoToken> enums = mCryptoManager.getAllTokens();
+
+ while (enums.hasMoreElements()) {
+ CryptoToken token = enums.nextElement();
+ CryptoStore store = token.getCryptoStore();
+ X509Certificate[] list = store.getCertificates();
+
+ for (int i = 0; i < list.length; i++) {
+ String nickname = list[i].getNickname();
+
+ if (certNames.length() < 1) {
+ certNames.append(nickname);
+ } else {
+ certNames.append("," + nickname);
+ }
+ }
+ }
+ } catch (TokenException e) {
+ String[] params = { mId, e.toString() };
+ EBaseException ex = new EBaseException(
+ CMS.getUserMessage("CMS_BASE_CREATE_SERVICE_FAILED", params));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GENERAL_ERROR", ex.toString()));
+ throw ex;
+ }
+
+ return certNames.toString();
+ }
+
+ public String getCertListWithoutTokenName(String name) throws EBaseException {
+
+ CryptoToken c = null;
+ StringBuffer certNames = new StringBuffer();
+
+ try {
+ if (name.equals(Constants.PR_INTERNAL_TOKEN)) {
+ c = mCryptoManager.getInternalKeyStorageToken();
+ } else {
+ c = mCryptoManager.getTokenByName(name);
+ }
+
+ if (c != null) {
+ CryptoStore store = c.getCryptoStore();
+ X509Certificate[] list = store.getCertificates();
+
+ if (list == null)
+ return "";
+
+ for (int i = 0; i < list.length; i++) {
+ String nickname = list[i].getNickname();
+ int index = nickname.indexOf(":");
+
+ if (index != -1)
+ nickname = nickname.substring(index + 1);
+ if (i != 0)
+ certNames.append(",");
+ certNames.append(nickname);
+ }
+ return certNames.toString();
+ } else
+ return "";
+
+ } catch (TokenException e) {
+ String[] params = { mId, e.toString() };
+ EBaseException ex = new EBaseException(
+ CMS.getUserMessage("CMS_BASE_CREATE_SERVICE_FAILED", params));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GENERAL_ERROR", ex.toString()));
+ throw ex;
+ } catch (NoSuchTokenException e) {
+ String[] params = { mId, e.toString() };
+ EBaseException ex = new EBaseException(
+ CMS.getUserMessage("CMS_BASE_CREATE_SERVICE_FAILED", params));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GENERAL_ERROR", ex.toString()));
+ throw ex;
+ }
+ }
+
+ public String getCertList(String name) throws EBaseException {
+
+ CryptoToken c = null;
+ StringBuffer certNames = new StringBuffer();
+
+ try {
+ if (name.equals(Constants.PR_INTERNAL_TOKEN)) {
+ c = mCryptoManager.getInternalKeyStorageToken();
+ } else {
+ c = mCryptoManager.getTokenByName(name);
+ }
+
+ if (c != null) {
+ CryptoStore store = c.getCryptoStore();
+ X509Certificate[] list = store.getCertificates();
+
+ if (list == null)
+ return "";
+
+ for (int i = 0; i < list.length; i++) {
+ String nickname = list[i].getNickname();
+
+ if (i != 0)
+ certNames.append(",");
+ certNames.append(nickname);
+ }
+
+ return certNames.toString();
+ } else
+ return "";
+
+ } catch (TokenException e) {
+ String[] params = { mId, e.toString() };
+ EBaseException ex = new EBaseException(
+ CMS.getUserMessage("CMS_BASE_CREATE_SERVICE_FAILED", params));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GENERAL_ERROR", ex.toString()));
+ throw ex;
+ } catch (NoSuchTokenException e) {
+ String[] params = { mId, e.toString() };
+ EBaseException ex = new EBaseException(
+ CMS.getUserMessage("CMS_BASE_CREATE_SERVICE_FAILED", params));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GENERAL_ERROR", ex.toString()));
+ throw ex;
+ }
+ }
+
+ public AlgorithmId getAlgorithmId(String algname, IConfigStore store)
+ throws EBaseException {
+ try {
+ if (algname.equals("DSA")) {
+ byte[] p = store.getByteArray("ca.dsaP", null);
+ byte[] q = store.getByteArray("ca.dsaQ", null);
+ byte[] g = store.getByteArray("ca.dsaG", null);
+
+ if (p != null && q != null && g != null) {
+ BigInteger P = new BigInteger(p);
+ BigInteger Q = new BigInteger(q);
+ BigInteger G = new BigInteger(g);
+
+ return new AlgIdDSA(P, Q, G);
+ }
+ }
+ return AlgorithmId.get(algname);
+ } catch (NoSuchAlgorithmException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED", ""));
+ }
+ }
+
+ public String getSignatureAlgorithm(String nickname) throws EBaseException {
+ try {
+ X509Certificate cert = CryptoManager.getInstance().findCertByNickname(nickname);
+ X509CertImpl impl = new X509CertImpl(cert.getEncoded());
+
+ return impl.getSigAlgName();
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_ALG", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (ObjectNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_ALG", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_ALG", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_ALG", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", ""));
+ }
+ }
+
+ public KeyPair getKeyPair(String nickname) throws EBaseException {
+ try {
+ X509Certificate cert = CryptoManager.getInstance().findCertByNickname(nickname);
+ PrivateKey priKey = CryptoManager.getInstance().findPrivKeyByCert(cert);
+ PublicKey publicKey = cert.getPublicKey();
+
+ return new KeyPair(publicKey, priKey);
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, "Key Pair Error " + e);
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (ObjectNotFoundException e) {
+ log(ILogger.LL_FAILURE, "Key Pair Error " + e);
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, "Key Pair Error " + e);
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ }
+ }
+
+ public KeyPair getKeyPair(String tokenName, String alg,
+ int keySize) throws EBaseException {
+ return getKeyPair(tokenName, alg, keySize, null);
+ }
+
+ public KeyPair getKeyPair(String tokenName, String alg,
+ int keySize, PQGParams pqg) throws EBaseException {
+
+ String t = tokenName;
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN))
+ t = Constants.PR_FULL_INTERNAL_TOKEN_NAME;
+ CryptoToken token = null;
+
+ try {
+ token = mCryptoManager.getTokenByName(t);
+ } catch (NoSuchTokenException e) {
+ log(ILogger.LL_FAILURE, "Generate Key Pair Error " + e);
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", tokenName));
+ }
+
+ KeyPairAlgorithm kpAlg = null;
+
+ if (alg.equals("RSA"))
+ kpAlg = KeyPairAlgorithm.RSA;
+ else {
+ kpAlg = KeyPairAlgorithm.DSA;
+ }
+
+ try {
+ KeyPair kp = KeyCertUtil.generateKeyPair(token, kpAlg, keySize, pqg);
+ return kp;
+ } catch (InvalidParameterException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_KEY_PAIR", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEYSIZE_PARAMS",
+ "" + keySize));
+ } catch (PQGParamGenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_KEY_PAIR", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_PQG_GEN_FAILED"));
+ } catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_KEY_PAIR", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED",
+ kpAlg.toString()));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_KEY_PAIR", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_KEY_GEN_FAILED"));
+ } catch (InvalidAlgorithmParameterException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_KEY_PAIR", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED", "DSA"));
+ }
+ }
+
+ public void isX500DN(String dn) throws EBaseException {
+ try {
+ new X500Name(dn); // check for errors
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_X500_NAME", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_X500_NAME", dn));
+ }
+ }
+
+ public String getCertRequest(String subjectName, KeyPair kp)
+ throws EBaseException {
+ try {
+ netscape.security.pkcs.PKCS10 pkcs = KeyCertUtil.getCertRequest(subjectName, kp);
+ ByteArrayOutputStream bs = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(bs);
+ pkcs.print(ps);
+ return bs.toString();
+ } catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_REQUEST", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED", ""));
+ } catch (NoSuchProviderException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_REQUEST", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_PROVIDER_NOT_SUPPORTED"));
+ } catch (InvalidKeyException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_REQUEST", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY"));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_REQUEST", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_REQ_FAILED"));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_REQUEST", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_CERT", e.toString()));
+ } catch (SignatureException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_REQUEST", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_SIGNATURE"));
+ }
+ }
+
+ public void importCert(String b64E, String nickname, String certType)
+ throws EBaseException {
+ try {
+ KeyCertUtil.importCert(b64E, nickname, certType);
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_DECODE_CERT_FAILED"));
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (TokenException e) {
+ String eString = e.toString();
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString()));
+ if (eString.contains("Failed to find certificate that was just imported")) {
+ throw new EBaseException(eString);
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ }
+ } catch (UserCertConflictException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_USERCERT_CONFLICT"));
+ } catch (NicknameConflictException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_NICKNAME_CONFLICT"));
+ } catch (NoSuchItemOnTokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN"));
+ }
+ }
+
+ public KeyPair getKeyPair(KeyCertData properties) throws EBaseException {
+ String tokenname = Constants.PR_INTERNAL_TOKEN_NAME;
+ String keyType = "RSA";
+ int keyLength = 512;
+
+ String tmp = (String) properties.get(Constants.PR_TOKEN_NAME);
+
+ if ((tmp != null) &&
+ (!tmp.equals(Constants.PR_INTERNAL_TOKEN)))
+ tokenname = tmp;
+ tmp = (String) properties.get(Constants.PR_KEY_TYPE);
+ if (tmp != null)
+ keyType = tmp;
+ tmp = (String) properties.get(Constants.PR_KEY_LENGTH);
+ if (tmp != null)
+ keyLength = Integer.parseInt(tmp);
+
+ KeyPair pair = getKeyPair(tokenname, keyType, keyLength);
+
+ return pair;
+ }
+
+ public KeyPair getECCKeyPair(KeyCertData properties) throws EBaseException {
+ String token = Constants.PR_INTERNAL_TOKEN_NAME;
+ String keyCurve = "nistp512";
+ String certType = null;
+ KeyPair pair = null;
+
+ String tmp = (String) properties.get(Constants.PR_TOKEN_NAME);
+ if (tmp != null)
+ token = tmp;
+
+ tmp = (String) properties.get(Constants.PR_KEY_CURVENAME);
+ if (tmp != null)
+ keyCurve = tmp;
+
+ certType = (String) properties.get(Constants.RS_ID);
+
+ pair = getECCKeyPair(token, keyCurve, certType);
+
+ return pair;
+ }
+
+ public KeyPair getECCKeyPair(String token, String keyCurve, String certType) throws EBaseException {
+ KeyPair pair = null;
+
+ if ((token == null) || (token.equals("")))
+ token = Constants.PR_INTERNAL_TOKEN_NAME;
+
+ if ((keyCurve == null) || (keyCurve.equals("")))
+ keyCurve = "nistp512";
+
+ String ectype = getECType(certType);
+
+ // ECDHE needs "SIGN" but no "DERIVE"
+ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage usages_mask[] = {
+ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.DERIVE
+ };
+
+ // ECDH needs "DERIVE" but no any kind of "SIGN"
+ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage ECDH_usages_mask[] = {
+ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN,
+ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN_RECOVER,
+ };
+
+ try {
+ if (ectype.equals("ECDHE"))
+ pair = CryptoUtil.generateECCKeyPair(token, keyCurve, null, usages_mask);
+ else
+ pair = CryptoUtil.generateECCKeyPair(token, keyCurve, null, ECDH_usages_mask);
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ECC_KEY", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (NoSuchTokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ECC_KEY", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ECC_KEY", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_NO_SUCH_ALGORITHM", e.toString()));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ECC_KEY", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ }
+
+ return pair;
+ }
+
+ public void importCert(X509CertImpl signedCert, String nickname,
+ String certType) throws EBaseException {
+
+ try {
+ KeyCertUtil.importCert(signedCert, nickname, certType);
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (CertificateEncodingException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ENCODE_CERT_FAILED"));
+ } catch (UserCertConflictException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_USERCERT_CONFLICT"));
+ } catch (NicknameConflictException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_NICKNAME_CONFLICT"));
+ } catch (NoSuchItemOnTokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN"));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ENCODE_CERT_FAILED"));
+ }
+ }
+
+ public NameValuePairs getCertInfo(String b64E) throws EBaseException {
+ try {
+ byte[] b = KeyCertUtil.convertB64EToByteArray(b64E);
+ X509CertImpl impl = new X509CertImpl(b);
+ NameValuePairs results = new NameValuePairs();
+
+ results.put(Constants.PR_CERT_SUBJECT_NAME, impl.getSubjectDN().getName());
+ results.put(Constants.PR_ISSUER_NAME, impl.getIssuerDN().getName());
+ results.put(Constants.PR_SERIAL_NUMBER, impl.getSerialNumber().toString());
+ results.put(Constants.PR_BEFORE_VALIDDATE, impl.getNotBefore().toString());
+ results.put(Constants.PR_AFTER_VALIDDATE, impl.getNotAfter().toString());
+
+ // fingerprint is using MD5 hash
+
+ return results;
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_INFO", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_DECODE_CERT_FAILED"));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_INFO", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_DECODE_CERT_FAILED"));
+ }
+ }
+
+ public void deleteUserCert(String nickname, String serialno, String issuername)
+ throws EBaseException {
+ try {
+ X509Certificate cert = getCertificate(nickname, serialno, issuername);
+ if (cert instanceof TokenCertificate) {
+ TokenCertificate tcert = (TokenCertificate) cert;
+
+ CMS.debug("*** deleting this token cert");
+ tcert.getOwningToken().getCryptoStore().deleteCert(tcert);
+ CMS.debug("*** finish deleting this token cert");
+ } else {
+ CryptoToken token = CryptoManager.getInstance().getInternalKeyStorageToken();
+ CryptoStore store = token.getCryptoStore();
+
+ CMS.debug("*** deleting this interna cert");
+ store.deleteCert(cert);
+ CMS.debug("*** removing this interna cert");
+ }
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (NoSuchItemOnTokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN"));
+ }
+ }
+
+ public void deleteRootCert(String nickname, String serialno,
+ String issuername) throws EBaseException {
+ int index = nickname.indexOf(":");
+ String tokenname = nickname.substring(0, index);
+ if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ nickname = nickname.substring(index + 1);
+ }
+ try {
+ if (mNicknameMapCertsTable != null) {
+ X509Certificate[] certs = mNicknameMapCertsTable.get(nickname);
+
+ if (certs == null) {
+ EBaseException e = new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CA_CERT", e.toString()));
+ throw e;
+ } else {
+ for (int i = 0; i < certs.length; i++) {
+ X509Certificate cert = certs[i];
+ X509CertImpl impl = new X509CertImpl(cert.getEncoded());
+ String num = impl.getSerialNumber().toString();
+ String issuer = impl.getIssuerDN().toString();
+ CMS.debug("*** num " + num);
+ CMS.debug("*** issuer " + issuer);
+ if (num.equals(serialno) && issuername.equals(issuer)) {
+ CMS.debug("*** removing root cert");
+ if (cert instanceof TokenCertificate) {
+ TokenCertificate tcert = (TokenCertificate) cert;
+
+ CMS.debug("*** deleting this token cert");
+ tcert.getOwningToken().getCryptoStore().deleteCert(tcert);
+ CMS.debug("*** finish deleting this token cert");
+ } else {
+ CryptoToken token = CryptoManager.getInstance().getInternalKeyStorageToken();
+ CryptoStore store = token.getCryptoStore();
+
+ CMS.debug("*** deleting this interna cert");
+ store.deleteCert(cert);
+ CMS.debug("*** removing this interna cert");
+ }
+ mNicknameMapCertsTable.remove(nickname);
+ break;
+ }
+ }
+ }
+ }
+
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (NoSuchItemOnTokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN"));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+ }
+
+ public NameValuePairs getRootCerts() throws EBaseException {
+ NameValuePairs nvps = new NameValuePairs();
+ try {
+ @SuppressWarnings("unchecked")
+ Enumeration<CryptoToken> enums = mCryptoManager.getAllTokens();
+ if (mNicknameMapCertsTable != null) {
+ mNicknameMapCertsTable.clear();
+ } else {
+ CMS.debug("JssSubsystem::getRootCerts() - mNicknameMapCertsTable is null");
+ throw new EBaseException("JssSubsystem::getRootCerts() - mNicknameMapCertsTable is null");
+ }
+
+ // a temp hashtable with vectors
+ Hashtable<String, Vector<X509Certificate>> vecTable = new Hashtable<String, Vector<X509Certificate>>();
+
+ while (enums.hasMoreElements()) {
+ CryptoToken token = enums.nextElement();
+ String tokenName = token.getName();
+
+ CryptoStore store = token.getCryptoStore();
+ X509Certificate[] list = store.getCertificates();
+
+ for (int i = 0; i < list.length; i++) {
+ try {
+ @SuppressWarnings("unused")
+ PrivateKey key = CryptoManager.getInstance().findPrivKeyByCert(list[i]); // check for errors
+ Debug.trace("JssSubsystem getRootCerts: find private key "
+ + list[i].getNickname());
+ } catch (ObjectNotFoundException e) {
+ String nickname = list[i].getNickname();
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ nickname = Constants.PR_INTERNAL_TOKEN_NAME + ":" + nickname;
+ }
+ X509CertImpl impl = null;
+
+ try {
+ Vector<X509Certificate> v;
+ if (vecTable.containsKey(nickname) == true) {
+ v = vecTable.get(nickname);
+ } else {
+ v = new Vector<X509Certificate>();
+ }
+ v.addElement(list[i]);
+ vecTable.put(nickname, v);
+ impl = new X509CertImpl(list[i].getEncoded());
+ } catch (CertificateException ex) {
+ // skip bad certificate
+ CMS.debug("bad certificate - " + nickname);
+ continue;
+ }
+ String serialno = impl.getSerialNumber().toString();
+ String issuer = impl.getIssuerDN().toString();
+ nvps.put(nickname + "," + serialno, issuer);
+ Debug.trace("getRootCerts: nickname=" + nickname + ", serialno=" +
+ serialno + ", issuer=" + issuer);
+ continue;
+ } catch (CryptoManager.NotInitializedException e) {
+ continue;
+ }
+ }
+ // convert hashtable of vectors to hashtable of arrays
+ Enumeration<String> elms = vecTable.keys();
+
+ while (elms.hasMoreElements()) {
+ String key = elms.nextElement();
+ Vector<X509Certificate> v = vecTable.get(key);
+ X509Certificate[] a = new X509Certificate[v.size()];
+
+ v.copyInto(a);
+ mNicknameMapCertsTable.put(key, a);
+ }
+ }
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ALL_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", ""));
+ }
+
+ return nvps;
+
+ }
+
+ public NameValuePairs getUserCerts() throws EBaseException {
+ NameValuePairs nvps = new NameValuePairs();
+ try {
+ @SuppressWarnings("unchecked")
+ Enumeration<CryptoToken> enums = mCryptoManager.getAllTokens();
+
+ while (enums.hasMoreElements()) {
+ CryptoToken token = enums.nextElement();
+ String tokenName = token.getName();
+
+ CryptoStore store = token.getCryptoStore();
+ X509Certificate[] list = store.getCertificates();
+
+ for (int i = 0; i < list.length; i++) {
+ try {
+ @SuppressWarnings("unused")
+ PrivateKey key =
+ CryptoManager.getInstance().findPrivKeyByCert(list[i]); // check for errors
+ String nickname = list[i].getNickname();
+ if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME) ||
+ tokenName.equals(Constants.PR_FULL_INTERNAL_TOKEN_NAME)) {
+ nickname = Constants.PR_INTERNAL_TOKEN_NAME + ":" + nickname;
+ }
+ X509CertImpl impl = null;
+
+ try {
+ impl = new X509CertImpl(list[i].getEncoded());
+ } catch (CertificateException e) {
+ // skip bad certificate
+ CMS.debug("bad certificate - " + nickname);
+ continue;
+ }
+ String serialno = impl.getSerialNumber().toString();
+ String issuer = impl.getIssuerDN().toString();
+ nvps.put(nickname + "," + serialno, issuer);
+ Debug.trace("getUserCerts: nickname=" + nickname + ", serialno=" +
+ serialno + ", issuer=" + issuer);
+ } catch (ObjectNotFoundException e) {
+ Debug.trace("JssSubsystem getUserCerts: cant find private key "
+ + list[i].getNickname());
+ continue;
+ } catch (CryptoManager.NotInitializedException e) {
+ continue;
+ }
+ }
+ }
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ALL_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", ""));
+ }
+
+ return nvps;
+
+ }
+
+ /*
+ * get all certificates on all tokens for Certificate Database Management
+ */
+ public NameValuePairs getAllCertsManage() throws EBaseException {
+
+ /*
+ * first get all CA certs (internal only),
+ * then all user certs (both internal and external)
+ */
+
+ NameValuePairs pairs = getCACerts();
+
+ if (mNicknameMapUserCertsTable != null) {
+ mNicknameMapUserCertsTable.clear();
+ } else {
+ CMS.debug("JssSubsystem:: getAllCertsManage() : mNicknameMapCertsTable is null");
+ throw new EBaseException("JssSubsystem:: getAllCertsManage() : mNicknameMapCertsTable is null");
+ }
+
+ try {
+ @SuppressWarnings("unchecked")
+ Enumeration<CryptoToken> enums = mCryptoManager.getAllTokens();
+
+ while (enums.hasMoreElements()) {
+ CryptoToken token = enums.nextElement();
+
+ CryptoStore store = token.getCryptoStore();
+ X509Certificate[] list = store.getCertificates();
+
+ for (int i = 0; i < list.length; i++) {
+ String nickname = list[i].getNickname();
+ X509Certificate[] certificates =
+ CryptoManager.getInstance().findCertsByNickname(nickname);
+
+ mNicknameMapUserCertsTable.put(nickname, certificates);
+
+ X509CertImpl impl = null;
+
+ try {
+ impl = new X509CertImpl(list[i].getEncoded());
+ } catch (CertificateException e) {
+ // skip bad certificate
+ CMS.debug("bad certificate - " + nickname);
+ continue;
+ }
+ Date date = impl.getNotAfter();
+ String dateStr = mFormatter.format(date);
+ String vvalue = pairs.get(nickname);
+
+ /* always user cert here*/
+ String certValue = dateStr + "," + "u";
+
+ if (vvalue == null)
+ pairs.put(nickname, certValue);
+ else {
+ if (vvalue.endsWith(",u")) {
+ pairs.put(nickname, vvalue + ";" + certValue);
+ }
+ }
+
+ }
+ } /* while */
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ALL_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ // } catch (CertificateException e) {
+ // log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ALL_CERT", e.toString()));
+ // throw new EBaseException(BaseResources.CERT_ERROR);
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ALL_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", ""));
+ }
+
+ return pairs;
+ }
+
+ public NameValuePairs getCACerts() throws EBaseException {
+ NameValuePairs pairs = new NameValuePairs();
+
+ //InternalCertificate[] certs;
+ X509Certificate[] certs;
+
+ try {
+ certs = CryptoManager.getInstance().getCACerts();
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_CA_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ }
+
+ if (mNicknameMapCertsTable == null) {
+ CMS.debug("JssSubsystem::getCACerts() - " + "mNicknameMapCertsTable is null!");
+ throw new EBaseException("JssSubsystem::getCACerts() - mNicknameMapCertsTable is null");
+ } else {
+ mNicknameMapCertsTable.clear();
+ }
+
+ // a temp hashtable with vectors
+ Hashtable<String, Vector<X509Certificate>> vecTable = new Hashtable<String, Vector<X509Certificate>>();
+
+ for (int i = 0; i < certs.length; i++) {
+ String nickname = certs[i].getNickname();
+
+ /* build a table of our own */
+ Vector<X509Certificate> v;
+
+ if (vecTable.containsKey(nickname) == true) {
+ v = vecTable.get(nickname);
+ } else {
+ v = new Vector<X509Certificate>();
+ }
+ v.addElement(certs[i]);
+ vecTable.put(nickname, v);
+ }
+
+ // convert hashtable of vectors to hashtable of arrays
+ Enumeration<String> elms = vecTable.keys();
+
+ while (elms.hasMoreElements()) {
+ String key = elms.nextElement();
+ Vector<X509Certificate> v = vecTable.get(key);
+ X509Certificate[] a = new X509Certificate[v.size()];
+
+ v.copyInto(a);
+ mNicknameMapCertsTable.put(key, a);
+ }
+
+ Enumeration<String> keys = mNicknameMapCertsTable.keys();
+
+ while (keys.hasMoreElements()) {
+ String nickname = keys.nextElement();
+ X509Certificate[] value = mNicknameMapCertsTable.get(nickname);
+
+ for (int i = 0; i < value.length; i++) {
+ InternalCertificate icert = null;
+
+ if (value[i] instanceof InternalCertificate)
+ icert = (InternalCertificate) value[i];
+ else {
+ Debug.trace("cert is not an InternalCertificate");
+ Debug.trace("nickname: " + nickname + " index " + i);
+ Debug.trace("cert: " + value[i]);
+ continue;
+ }
+
+ int flag = icert.getSSLTrust();
+ String trust = "U";
+
+ if ((InternalCertificate.TRUSTED_CLIENT_CA & flag) == InternalCertificate.TRUSTED_CLIENT_CA)
+ trust = "T";
+ X509CertImpl impl = null;
+
+ try {
+ impl = new X509CertImpl(icert.getEncoded());
+ Date date = impl.getNotAfter();
+ String dateStr = mFormatter.format(date);
+ String vvalue = pairs.get(nickname);
+ String certValue = dateStr + "," + trust;
+
+ if (vvalue == null)
+ pairs.put(nickname, certValue);
+ else {
+ pairs.put(nickname, vvalue + ";" + certValue);
+ }
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_SECURITY_GET_CA_CERT_FOR", nickname, e.toString()));
+ // allow it to continue with other certs even if one blows
+ // up
+ // throw new EBaseException(BaseResources.CERT_ERROR);
+ }
+ }
+ }
+ return pairs;
+ }
+
+ public void trustCert(String nickname, String date, String trust) throws
+ EBaseException {
+ try {
+ if (mNicknameMapCertsTable != null) {
+ X509Certificate[] certs = mNicknameMapCertsTable.get(nickname);
+
+ if (certs == null) {
+ EBaseException e = new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_TRUST_CERT", e.toString()));
+ throw e;
+ } else {
+ for (int i = 0; i < certs.length; i++) {
+ X509Certificate cert = certs[i];
+ X509CertImpl certImpl = new X509CertImpl(cert.getEncoded());
+ Date notAfter = certImpl.getNotAfter();
+ Date qualifier = mFormatter.parse(date);
+
+ if (notAfter.equals(qualifier)) {
+ if (cert instanceof InternalCertificate) {
+ if (trust.equals("Trust")) {
+ int trustflag = InternalCertificate.TRUSTED_CA |
+ InternalCertificate.TRUSTED_CLIENT_CA |
+ InternalCertificate.VALID_CA;
+
+ ((InternalCertificate) cert).setSSLTrust(trustflag);
+ } else
+ ((InternalCertificate) cert).setSSLTrust(InternalCertificate.VALID_CA);
+ break;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", ""));
+ }
+ }
+ }
+ }
+ }
+ } catch (ParseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_TRUST_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_TRUST_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+ }
+
+ /**
+ * Delete the CA certificate from the perm database.
+ *
+ * @param nickname The nickname of the CA certificate.
+ * @param notAfterTime The notAfter of the certificate. It is possible to get multiple
+ * certificates under the same nickname. If one of the certificates match the notAfterTime,
+ * then the certificate will get deleted. The format of the notAfterTime has to be
+ * in "MMMMM dd, yyyy HH:mm:ss" format.
+ */
+ public void deleteCACert(String nickname, String notAfterTime) throws EBaseException {
+ try {
+ if (mNicknameMapCertsTable != null) {
+ X509Certificate[] certs = mNicknameMapCertsTable.get(nickname);
+
+ if (certs == null) {
+ EBaseException e = new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CA_CERT", e.toString()));
+ throw e;
+ } else {
+ for (int i = 0; i < certs.length; i++) {
+ X509Certificate cert = certs[i];
+ X509CertImpl certImpl = new X509CertImpl(cert.getEncoded());
+ Date notAfter = certImpl.getNotAfter();
+ Date qualifier = mFormatter.parse(notAfterTime);
+
+ if (notAfter.equals(qualifier)) {
+ if (cert instanceof TokenCertificate) {
+ TokenCertificate tcert = (TokenCertificate) cert;
+
+ tcert.getOwningToken().getCryptoStore().deleteCert(tcert);
+ } else {
+ CryptoToken token = CryptoManager.getInstance().getInternalKeyStorageToken();
+ CryptoStore store = token.getCryptoStore();
+
+ store.deleteCert(cert);
+ }
+ mNicknameMapCertsTable.remove(nickname);
+ break;
+ }
+ }
+ }
+ }
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (NoSuchItemOnTokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN"));
+ } catch (ParseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+ }
+
+ /**
+ * Delete any certificate from the any token.
+ *
+ * @param nickname The nickname of the certificate.
+ * @param notAfterTime The notAfter of the certificate. It is possible to get multiple
+ * certificates under the same nickname. If one of the certificates match the notAfterTime,
+ * then the certificate will get deleted. The format of the notAfterTime has to be
+ * in "MMMMM dd, yyyy HH:mm:ss" format.
+ */
+ public void deleteCert(String nickname, String notAfterTime) throws EBaseException {
+ boolean isUserCert = false;
+ X509Certificate[] certs = null;
+
+ try {
+ if (mNicknameMapCertsTable != null) {
+ certs = mNicknameMapCertsTable.get(nickname);
+ }
+
+ if (certs == null) {
+ if (mNicknameMapUserCertsTable != null) {
+ certs = mNicknameMapUserCertsTable.get(nickname);
+ if (certs != null) {
+ CMS.debug("in mNicknameMapUserCertsTable, isUserCert is true");
+ isUserCert = true;
+ }
+
+ } else
+ CMS.debug("mNicknameMapUserCertsTable is null");
+ }
+
+ if (certs == null) {
+ EBaseException e = new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw e;
+ } else {
+
+ for (int i = 0; i < certs.length; i++) {
+ X509Certificate cert = certs[i];
+ X509CertImpl certImpl = new X509CertImpl(cert.getEncoded());
+ Date notAfter = certImpl.getNotAfter();
+ Date qualifier = mFormatter.parse(notAfterTime);
+
+ if (notAfter.equals(qualifier)) {
+ if (cert instanceof TokenCertificate) {
+ TokenCertificate tcert = (TokenCertificate) cert;
+
+ tcert.getOwningToken().getCryptoStore().deleteCert(tcert);
+ } else {
+ CryptoToken token = CryptoManager.getInstance().getInternalKeyStorageToken();
+ CryptoStore store = token.getCryptoStore();
+
+ store.deleteCert(cert);
+ }
+ if (isUserCert == true) {
+ mNicknameMapUserCertsTable.remove(nickname);
+ } else {
+ mNicknameMapCertsTable.remove(nickname);
+ }
+ break;
+ }
+ }
+ }
+
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (NoSuchItemOnTokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN"));
+ } catch (ParseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+ }
+
+ public void deleteTokenCertificate(String nickname, String pathname) throws EBaseException {
+ try {
+ X509Certificate cert = CryptoManager.getInstance().findCertByNickname(nickname);
+ Principal principal = cert.getSubjectDN();
+ DN dn = new DN(principal.getName());
+ BigInteger serialno = cert.getSerialNumber();
+ String suffix = "." + System.currentTimeMillis();
+ String b64E = Utils.base64encode(cert.getEncoded());
+ PrintStream stream = new PrintStream(new FileOutputStream(pathname + suffix));
+
+ stream.println("-----BEGIN CERTIFICATE-----");
+ stream.print(b64E);
+ stream.println("-----END CERTIFICATE-----");
+ stream.close();
+ if (cert instanceof TokenCertificate) {
+ TokenCertificate tcert = (TokenCertificate) cert;
+
+ tcert.getOwningToken().getCryptoStore().deleteCert(tcert);
+ } else
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_NOT_TOKEN_CERT"));
+
+ int index = nickname.indexOf(":");
+
+ // the deleted certificate is on the hardware token. We should delete the same one from
+ // the internal token.
+ if (index > 0) {
+ CryptoToken cToken = CryptoManager.getInstance().getInternalKeyStorageToken();
+ CryptoStore store = cToken.getCryptoStore();
+ X509Certificate[] allcerts = CryptoManager.getInstance().getCACerts();
+
+ for (int i = 0; i < allcerts.length; i++) {
+ try {
+ X509CertImpl certImpl = new X509CertImpl(allcerts[i].getEncoded());
+ Principal certPrincipal = certImpl.getSubjectDN();
+ DN certdn = new DN(certPrincipal.getName());
+ BigInteger certSerialNo = certImpl.getSerialNumber();
+
+ if (dn.equals(certdn) && certSerialNo.compareTo(serialno) == 0) {
+ store.deleteCert(allcerts[i]);
+ break;
+ }
+ } catch (Exception ee) {
+ Debug.trace("JssSubsystem:deleteTokenCertificate: " + ee.toString());
+ }
+ }
+ }
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (NoSuchItemOnTokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN"));
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (ObjectNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN"));
+ } catch (CertificateEncodingException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+ }
+
+ public String getSubjectDN(String nickname) throws EBaseException {
+ try {
+ X509Certificate cert = CryptoManager.getInstance().findCertByNickname(nickname);
+ X509CertImpl impl = new X509CertImpl(cert.getEncoded());
+
+ return impl.getSubjectDN().getName();
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_SUBJECT_NAME", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_SUBJECT_NAME", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (ObjectNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_SUBJECT_NAME", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_SUBJECT_NAME", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+ }
+
+ public void setRootCertTrust(String nickname, String serialno,
+ String issuerName, String trust) throws EBaseException {
+
+ X509Certificate cert = getCertificate(nickname, serialno, issuerName);
+ if (cert instanceof InternalCertificate) {
+ if (trust.equals("trust")) {
+ int trustflag = InternalCertificate.TRUSTED_CA |
+ InternalCertificate.TRUSTED_CLIENT_CA |
+ InternalCertificate.VALID_CA;
+
+ ((InternalCertificate) cert).setSSLTrust(trustflag);
+ } else {
+ ((InternalCertificate) cert).setSSLTrust(InternalCertificate.VALID_CA);
+ }
+ }
+ }
+
+ public X509Certificate getCertificate(String nickname, String serialno,
+ String issuerName) throws EBaseException {
+
+ int index = nickname.indexOf(":");
+ String tokenname = nickname.substring(0, index);
+ if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ nickname = nickname.substring(index + 1);
+ }
+ try {
+ X509Certificate[] certs = CryptoManager.getInstance().findCertsByNickname(nickname);
+
+ X509CertImpl impl = null;
+ int i = 0;
+ if (certs != null && certs.length > 0) {
+ for (; i < certs.length; i++) {
+ impl = new X509CertImpl(certs[i].getEncoded());
+ if (impl.getIssuerDN().toString().equals(issuerName) &&
+ impl.getSerialNumber().toString().equals(serialno))
+ return certs[i];
+ }
+ } else {
+ EBaseException e = new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw e;
+ }
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+
+ return null;
+ }
+
+ public String getRootCertTrustBit(String nickname, String serialno,
+ String issuerName) throws EBaseException {
+ int index = nickname.indexOf(":");
+ String tokenname = nickname.substring(0, index);
+ if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ nickname = nickname.substring(index + 1);
+ }
+ try {
+ X509Certificate[] certs = CryptoManager.getInstance().findCertsByNickname(nickname);
+
+ X509CertImpl impl = null;
+ int i = 0;
+ if (certs != null && certs.length > 0) {
+ for (; i < certs.length; i++) {
+ impl = new X509CertImpl(certs[i].getEncoded());
+ if (impl.getIssuerDN().toString().equals(issuerName) &&
+ impl.getSerialNumber().toString().equals(serialno))
+ break;
+ }
+ } else {
+ EBaseException e = new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw e;
+ }
+
+ String trust = "U";
+ if (certs[i] instanceof InternalCertificate) {
+ InternalCertificate icert = (InternalCertificate) certs[i];
+ int flag = icert.getSSLTrust();
+ if ((InternalCertificate.TRUSTED_CLIENT_CA & flag) == InternalCertificate.TRUSTED_CLIENT_CA)
+ trust = "T";
+ } else
+ trust = "N/A";
+ return trust;
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+ }
+
+ public String getCertPrettyPrint(String nickname, String serialno,
+ String issuerName, Locale locale) throws EBaseException {
+ int index = nickname.indexOf(":");
+ String tokenname = nickname.substring(0, index);
+ if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ nickname = nickname.substring(index + 1);
+ }
+ try {
+ X509Certificate[] certs = CryptoManager.getInstance().findCertsByNickname(nickname);
+
+ X509CertImpl impl = null;
+ if (certs != null && certs.length > 0) {
+ for (int i = 0; i < certs.length; i++) {
+ impl = new X509CertImpl(certs[i].getEncoded());
+ if (impl.getIssuerDN().toString().equals(issuerName) &&
+ impl.getSerialNumber().toString().equals(serialno))
+ break;
+ }
+ } else {
+ EBaseException e = new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw e;
+ }
+ CertPrettyPrint print = null;
+
+ if (impl != null)
+ print = new CertPrettyPrint(impl);
+
+ if (print != null)
+ return print.toString(locale);
+ else
+ return null;
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+ }
+
+ public String getCertPrettyPrintAndFingerPrint(String nickname, String serialno,
+ String issuerName, Locale locale) throws EBaseException {
+ int index = nickname.indexOf(":");
+ String tokenname = nickname.substring(0, index);
+ if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ nickname = nickname.substring(index + 1);
+ }
+ try {
+ X509Certificate[] certs = CryptoManager.getInstance().findCertsByNickname(nickname);
+
+ X509CertImpl impl = null;
+ if (certs != null && certs.length > 0) {
+ for (int i = 0; i < certs.length; i++) {
+ impl = new X509CertImpl(certs[i].getEncoded());
+ if (impl.getIssuerDN().toString().equals(issuerName) &&
+ impl.getSerialNumber().toString().equals(serialno))
+ break;
+ }
+ } else {
+ EBaseException e = new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw e;
+ }
+ CertPrettyPrint print = null;
+ String fingerPrint = "";
+
+ if (impl != null) {
+ print = new CertPrettyPrint(impl);
+ fingerPrint = CMS.getFingerPrints(impl.getEncoded());
+ }
+
+ if ((print != null) && (fingerPrint != "")) {
+ String pp = print.toString(locale) + "\n" +
+ "Certificate Fingerprints:" + '\n' + fingerPrint;
+ return pp;
+ } else
+ return null;
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ } catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_NO_SUCH_ALGORITHM", e.toString()));
+ }
+ }
+
+ public String getCertPrettyPrint(String nickname, String date,
+ Locale locale) throws EBaseException {
+ try {
+ X509Certificate[] certs = CryptoManager.getInstance().findCertsByNickname(nickname);
+
+ if ((certs == null || certs.length == 0) &&
+ mNicknameMapCertsTable != null) {
+ certs = mNicknameMapCertsTable.get(nickname);
+ }
+ if (certs == null) {
+ EBaseException e = new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw e;
+ }
+ X509CertImpl impl = null;
+ Date qualifier = mFormatter.parse(date);
+
+ for (int i = 0; i < certs.length; i++) {
+ impl = new X509CertImpl(certs[i].getEncoded());
+ Date d = impl.getNotAfter();
+
+ if (d.equals(qualifier))
+ break;
+ }
+
+ CertPrettyPrint print = null;
+
+ if (impl != null)
+ print = new CertPrettyPrint(impl);
+
+ if (print != null)
+ return print.toString(locale);
+ else
+ return null;
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ } catch (ParseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+ }
+
+ public String getCertPrettyPrint(String b64E, Locale locale) throws EBaseException {
+ try {
+ try {
+ byte[] b = KeyCertUtil.convertB64EToByteArray(b64E);
+ X509CertImpl impl = new X509CertImpl(b);
+ CertPrettyPrint print = new CertPrettyPrint(impl);
+
+ return print.toString(locale);
+ } catch (CertificateException e) {
+ // failed to decode as a certificate, try decoding
+ // as a PKCS #7 blob
+ StringBuffer content = new StringBuffer();
+
+ String noHeader = CertUtils.stripCertBrackets(b64E);
+ String normalized = CertUtils.normalizeCertStr(noHeader);
+ byte data[] = Utils.base64decode(normalized);
+
+ ContentInfo ci = (ContentInfo)
+ ASN1Util.decode(ContentInfo.getTemplate(), data);
+
+ if (!ci.getContentType().equals(ContentInfo.SIGNED_DATA)) {
+ throw new CertificateException(
+ "PKCS #7 structure is not a SignedData");
+ }
+ SignedData sd = (SignedData) ci.getInterpretedContent();
+
+ if (!sd.hasCertificates()) {
+ throw new CertificateException(
+ "No certificates in PKCS #7 structure");
+ }
+ SET certs = sd.getCertificates();
+
+ for (int i = 0; i < certs.size(); i++) {
+ Certificate cert = (Certificate) certs.elementAt(i);
+ X509CertImpl certImpl = new X509CertImpl(
+ ASN1Util.encode(cert));
+ CertPrettyPrint print = new CertPrettyPrint(certImpl);
+
+ content.append(print.toString(Locale.getDefault()));
+ }
+
+ return content.toString();
+ }
+ } catch (InvalidBERException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR",
+ "Failed to decode"));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.getMessage()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", ""));
+ }
+ }
+
+ public X509CertImpl getSignedCert(KeyCertData data, String certType, java.security.PrivateKey priKey)
+ throws EBaseException {
+ CertificateInfo cert = null;
+
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT)) {
+ cert = new CASigningCert(data);
+ } else if (certType.equals(Constants.PR_OCSP_SIGNING_CERT)) {
+ cert = new OCSPSigningCert(data);
+ } else if (certType.equals(Constants.PR_SERVER_CERT)) {
+ cert = new SSLCert(data);
+ } else if (certType.equals(Constants.PR_SERVER_CERT_RADM)) {
+ cert = new SSLSelfSignedCert(data);
+ }
+
+ if (cert == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", ""));
+ }
+
+ X509CertInfo certInfo = null;
+ X509CertImpl signedCert = null;
+
+ try {
+ certInfo = cert.getCertInfo();
+ SignatureAlgorithm sigAlg = (SignatureAlgorithm) data.get(Constants.PR_SIGNATURE_ALGORITHM);
+
+ signedCert = KeyCertUtil.signCert(priKey, certInfo, sigAlg);
+ } catch (NoSuchTokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_SIGN_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", ""));
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_SIGN_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (PQGParamGenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_SIGN_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_PQG_GEN_FAILED"));
+ }
+
+ return signedCert;
+ }
+
+ public boolean isCACert(String fullNickname) throws EBaseException {
+ try {
+ X509Certificate cert = mCryptoManager.findCertByNickname(fullNickname);
+ X509CertImpl impl = new X509CertImpl(cert.getEncoded());
+ X509CertInfo certinfo = (X509CertInfo) impl.get(
+ X509CertImpl.NAME + "." + X509CertImpl.INFO);
+
+ if (certinfo == null)
+ return false;
+ else {
+ CertificateExtensions exts = (CertificateExtensions) certinfo.get(X509CertInfo.EXTENSIONS);
+
+ if (exts == null)
+ return false;
+ else {
+ try {
+ BasicConstraintsExtension ext = (BasicConstraintsExtension) exts
+ .get(BasicConstraintsExtension.NAME);
+
+ if (ext == null)
+ return false;
+ else {
+ Boolean bool = (Boolean) ext.get(BasicConstraintsExtension.IS_CA);
+
+ return bool.booleanValue();
+ }
+ } catch (IOException ee) {
+ return false;
+ }
+ }
+ }
+ } catch (ObjectNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IS_CA_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IS_CA_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_ERROR"));
+ } catch (CertificateEncodingException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IS_CA_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_ERROR"));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IS_CA_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", ""));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IS_CA_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_DECODE_CERT_FAILED"));
+ }
+ }
+
+ public CertificateExtensions getExtensions(String tokenname, String nickname)
+ throws EBaseException {
+ try {
+ return KeyCertUtil.getExtensions(tokenname, nickname);
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_EXTENSIONS", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ } catch (TokenException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_EXTENSIONS", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_ERROR"));
+ } catch (ObjectNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_EXTENSIONS", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND"));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_EXTENSIONS", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_DECODE_CERT_FAILED"));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_EXTENSIONS", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", ""));
+ }
+ }
+
+ public void checkCertificateExt(String ext) throws EBaseException {
+ KeyCertUtil.checkCertificateExt(ext);
+ }
+
+ public void checkKeyLength(String keyType, int keyLength, String certType, int minRSAKeyLen) throws EBaseException {
+ // KeyCertUtil.checkKeyLength(keyType, keyLength, certType, minRSAKeyLen);
+ }
+
+ public PQGParams getPQG(int keysize) {
+ return KeyCertUtil.getPQG(keysize);
+ }
+
+ public PQGParams getCAPQG(int keysize, IConfigStore store)
+ throws EBaseException {
+ return KeyCertUtil.getCAPQG(keysize, store);
+ }
+
+ public CertificateExtensions getCertExtensions(String tokenname, String nickname)
+ throws NotInitializedException, TokenException, ObjectNotFoundException,
+
+ IOException, CertificateException {
+ return KeyCertUtil.getExtensions(tokenname, nickname);
+ }
+}
+
+class JSSDatabaseCloser extends org.mozilla.jss.DatabaseCloser {
+ public JSSDatabaseCloser() throws Exception {
+ super();
+ }
+
+ public void closeDatabases() {
+ super.closeDatabases();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/security/KRATransportCert.java b/base/server/cmscore/src/com/netscape/cmscore/security/KRATransportCert.java
new file mode 100644
index 000000000..58c269796
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/security/KRATransportCert.java
@@ -0,0 +1,101 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+import java.io.IOException;
+import java.security.KeyPair;
+
+import netscape.security.x509.KeyUsageExtension;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ConfigConstants;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.security.KeyCertData;
+
+/**
+ * KRA transport certificate
+ *
+ * @author Christine Ho
+ * @version $Revision$, $Date$
+ */
+public class KRATransportCert extends CertificateInfo {
+ public static final String SUBJECT_NAME =
+ "CN=Data Recovery Manager, O=Netscape Communications, C=US";
+
+ public KRATransportCert(KeyCertData properties) {
+ this(properties, null);
+ }
+
+ public KRATransportCert(KeyCertData properties, KeyPair pair) {
+ super(properties, pair);
+ mProperties.put(Constants.PR_AKI, Constants.TRUE);
+ }
+
+ public void updateConfig(IConfigStore cmsFileTmp) throws EBaseException {
+ String tokenname = (String) mProperties.get(Constants.PR_TOKEN_NAME);
+ String nickname = getNickname();
+
+ if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME))
+ cmsFileTmp.putString("kra.transportUnit.nickName", nickname);
+ else
+ cmsFileTmp.putString("kra.transportUnit.nickName", tokenname + ":" + nickname);
+ cmsFileTmp.commit(false);
+ }
+
+ public String getSubjectName() {
+ return (String) mProperties.get(Constants.PR_SUBJECT_NAME);
+ }
+
+ public String getNickname() {
+ String name = (String) mProperties.get(Constants.PR_NICKNAME);
+ String instanceName =
+ (String) mProperties.get(ConfigConstants.PR_CERT_INSTANCE_NAME);
+
+ if (name != null)
+ return name;
+ return "kraTransportCert " + instanceName;
+ }
+
+ /*
+ public SignatureAlgorithm getSigningAlgorithm() {
+ SignatureAlgorithm sAlg =
+ (SignatureAlgorithm)mProperties.get(Constants.PR_SIGNATURE_ALGORITHM);
+ if (sAlg != null) {
+ return sAlg;
+ }
+ String alg = (String)mProperties.get(Constants.PR_KEY_TYPE);
+
+ if (alg.equals("RSA"))
+ return SignatureAlgorithm.RSASignatureWithMD5Digest;
+ else
+ return SignatureAlgorithm.DSASignatureWithSHA1Digest;
+ }
+ */
+
+ public String getKeyAlgorithm() {
+ return (String) mProperties.get(Constants.PR_KEY_TYPE);
+ }
+
+ protected KeyUsageExtension getKeyUsageExtension() throws IOException {
+ KeyUsageExtension extension = new KeyUsageExtension();
+
+ extension.set(KeyUsageExtension.KEY_ENCIPHERMENT,Boolean.valueOf(true));
+ return extension;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/security/KeyCertUtil.java b/base/server/cmscore/src/com/netscape/cmscore/security/KeyCertUtil.java
new file mode 100644
index 000000000..b91b4cf93
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/security/KeyCertUtil.java
@@ -0,0 +1,1134 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.math.BigInteger;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.KeyPair;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.security.extensions.AuthInfoAccessExtension;
+import netscape.security.extensions.ExtendedKeyUsageExtension;
+import netscape.security.extensions.NSCertTypeExtension;
+import netscape.security.extensions.OCSPNoCheckExtension;
+import netscape.security.pkcs.PKCS10;
+import netscape.security.pkcs.PKCS10Attribute;
+import netscape.security.pkcs.PKCS10Attributes;
+import netscape.security.pkcs.PKCS9Attribute;
+import netscape.security.util.BigInt;
+import netscape.security.util.DerOutputStream;
+import netscape.security.util.DerValue;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AlgIdDSA;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.AuthorityKeyIdentifierExtension;
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.Extension;
+import netscape.security.x509.Extensions;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.KeyIdentifier;
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.SubjectKeyIdentifierExtension;
+import netscape.security.x509.URIName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X500Signer;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.NicknameConflictException;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.CryptoManager.UserCertConflictException;
+import org.mozilla.jss.NoSuchTokenException;
+import org.mozilla.jss.asn1.ANY;
+import org.mozilla.jss.asn1.ASN1Header;
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.BIT_STRING;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.InternalCertificate;
+import org.mozilla.jss.crypto.KeyPairAlgorithm;
+import org.mozilla.jss.crypto.KeyPairGenerator;
+import org.mozilla.jss.crypto.NoSuchItemOnTokenException;
+import org.mozilla.jss.crypto.ObjectNotFoundException;
+import org.mozilla.jss.crypto.PQGParamGenException;
+import org.mozilla.jss.crypto.PQGParams;
+import org.mozilla.jss.crypto.Signature;
+import org.mozilla.jss.crypto.SignatureAlgorithm;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.pkcs11.PK11ECPublicKey;
+import org.mozilla.jss.util.Base64OutputStream;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.security.KeyCertData;
+import com.netscape.cmscore.cert.CertUtils;
+import com.netscape.cmscore.dbs.BigIntegerMapper;
+import com.netscape.cmscore.dbs.DateMapper;
+import com.netscape.cmscore.dbs.X509CertImplMapper;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+import com.netscape.cmsutil.util.Utils;
+
+/**
+ * This class provides all the base methods to generate the key for different
+ * kinds of certificates.
+ *
+ * @author Christine Ho
+ * @version $Revision$, $Date$
+ */
+public class KeyCertUtil {
+
+ public static final String CA_SIGNINGCERT_NICKNAME = "caSigningCert";
+
+ public static void checkCertificateExt(String ext) throws EBaseException {
+ byte[] b = null;
+
+ if (ext != null) {
+ try {
+
+ b = Utils.base64decode(ext);
+ // this b can be "Extension" Or "SEQUENCE OF Extension"
+ DerValue b_der = new DerValue(b);
+
+ while (b_der.data.available() != 0) {
+ new Extension(b_der.data.getDerValue()); // check for errors
+ }
+ } catch (IOException e) {
+ try {
+ new Extension(new DerValue(b)); // check for errors
+ } catch (IOException ex) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_CERT_EXTENSION"));
+ }
+ }
+ }
+ }
+
+ public static String getTokenNames(CryptoManager manager)
+ throws TokenException {
+ StringBuffer tokenList = new StringBuffer();
+
+ @SuppressWarnings("unchecked")
+ Enumeration<CryptoToken> tokens = manager.getExternalTokens();
+ int num = 0;
+
+ while (tokens.hasMoreElements()) {
+ CryptoToken c = tokens.nextElement();
+
+ if (num++ != 0)
+ tokenList.append(",");
+ tokenList.append(c.getName());
+ }
+
+ if (tokenList.length() == 0)
+ return Constants.PR_INTERNAL_TOKEN;
+ else
+ return (tokenList.toString() + "," + Constants.PR_INTERNAL_TOKEN);
+ }
+
+ public static String base64Encode(byte[] bytes) throws IOException {
+ // All this streaming is lame, but Base64OutputStream needs a
+ // PrintStream
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ try (Base64OutputStream b64 = new Base64OutputStream(
+ new PrintStream(new FilterOutputStream(output)))) {
+
+ b64.write(bytes);
+ b64.flush();
+
+ // This is internationally safe because Base64 chars are
+ // contained within 8859_1
+ return output.toString("8859_1");
+ }
+ }
+
+ public static byte[] makeDSSParms(BigInteger P, BigInteger Q, BigInteger G)
+ throws IOException {
+ try (DerOutputStream sequence = new DerOutputStream()) {
+
+ // Write P, Q, G to a DER stream
+ DerOutputStream contents = new DerOutputStream();
+
+ contents.putInteger(new BigInt(P));
+ contents.putInteger(new BigInt(Q));
+ contents.putInteger(new BigInt(G));
+
+ // Make a sequence from the PQG stream
+ sequence.write(DerValue.tag_Sequence, contents);
+
+ return sequence.toByteArray();
+ }
+ }
+
+ public static PrivateKey getPrivateKey(String tokenname, String nickname)
+ throws TokenException, EBaseException,
+ NoSuchTokenException, NotInitializedException, CertificateException,
+ CertificateEncodingException, EBaseException, ObjectNotFoundException {
+
+ /*
+ String caNickname = store.getString("ca.signing.tokenname");
+ String tokenName = store.getString("ca.signing.cacertnickname");
+ */
+ X509Certificate cert = getCertificate(tokenname, nickname);
+
+ return CryptoManager.getInstance().findPrivKeyByCert(cert);
+ }
+
+ public static String getCertSubjectName(String tokenname, String nickname)
+ throws TokenException, EBaseException, NoSuchTokenException,
+ NotInitializedException, CertificateException,
+ CertificateEncodingException, EBaseException {
+
+ X509Certificate cert = getCertificate(tokenname, nickname);
+ X509CertImpl impl = new X509CertImpl(cert.getEncoded());
+
+ return impl.getSubjectDN().getName();
+ }
+
+ public static X509CertImpl signCert(PrivateKey privateKey, X509CertInfo certInfo,
+ SignatureAlgorithm sigAlg)
+ throws NoSuchTokenException, EBaseException, NotInitializedException {
+ try (DerOutputStream out = new DerOutputStream()) {
+ CertificateAlgorithmId sId = (CertificateAlgorithmId)
+ certInfo.get(X509CertInfo.ALGORITHM_ID);
+ AlgorithmId sigAlgId =
+ (AlgorithmId) sId.get(CertificateAlgorithmId.ALGORITHM);
+
+ org.mozilla.jss.crypto.PrivateKey priKey =
+ (org.mozilla.jss.crypto.PrivateKey) privateKey;
+ CryptoToken token = priKey.getOwningToken();
+
+ DerOutputStream tmp = new DerOutputStream();
+
+ certInfo.encode(tmp);
+
+ Signature signer = token.getSignatureContext(sigAlg);
+
+ signer.initSign(priKey);
+ signer.update(tmp.toByteArray());
+ byte signed[] = signer.sign();
+
+ sigAlgId.encode(tmp);
+ tmp.putBitString(signed);
+
+ out.write(DerValue.tag_Sequence, tmp);
+
+ X509CertImpl signedCert = new X509CertImpl(out.toByteArray());
+
+ return signedCert;
+ } catch (IOException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_SIGNED_FAILED", e.toString()));
+ } catch (NoSuchAlgorithmException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED", e.toString()));
+ } catch (TokenException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_ERROR_1", e.toString()));
+ } catch (SignatureException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_SIGNED_FAILED", e.toString()));
+ } catch (InvalidKeyException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1", e.toString()));
+ } catch (CertificateException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+ }
+
+ public static SignatureAlgorithm getSigningAlgorithm(String keyType) {
+ SignatureAlgorithm sAlg = null;
+
+ if (keyType.equals("RSA"))
+ sAlg = SignatureAlgorithm.RSASignatureWithMD5Digest;
+ else
+ sAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest;
+
+ return sAlg;
+ }
+
+ public static SignatureAlgorithm getSigningAlgorithm(String keyType, String hashtype) {
+ SignatureAlgorithm sAlg = null;
+
+ if (keyType.equals("RSA")) {
+ if (hashtype.equals("MD2"))
+ sAlg = SignatureAlgorithm.RSASignatureWithMD2Digest;
+ else if (hashtype.equals("MD5"))
+ sAlg = SignatureAlgorithm.RSASignatureWithMD5Digest;
+ else if (hashtype.equals("SHA1"))
+ sAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest;
+ else if (hashtype.equals("SHA256"))
+ sAlg = SignatureAlgorithm.RSASignatureWithSHA256Digest;
+ else if (hashtype.equals("SHA512"))
+ sAlg = SignatureAlgorithm.RSASignatureWithSHA512Digest;
+ } else {
+ sAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest;
+ }
+
+ return sAlg;
+ }
+
+ public static AlgorithmId getAlgorithmId(String algname, IConfigStore store)
+ throws EBaseException {
+ try {
+
+ if (algname.equals("DSA")) {
+ byte[] p = store.getByteArray("ca.dsaP", null);
+ byte[] q = store.getByteArray("ca.dsaQ", null);
+ byte[] g = store.getByteArray("ca.dsaG", null);
+
+ if (p != null && q != null && g != null) {
+ BigInteger P = new BigInteger(p);
+ BigInteger Q = new BigInteger(q);
+ BigInteger G = new BigInteger(g);
+
+ return new AlgIdDSA(P, Q, G);
+ }
+ }
+ return AlgorithmId.get(algname);
+ } catch (NoSuchAlgorithmException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED"));
+ }
+ }
+
+ public static X509Certificate getCertificate(String tokenname,
+ String nickname) throws NotInitializedException, NoSuchTokenException,
+ EBaseException, TokenException {
+ CryptoManager manager = CryptoManager.getInstance();
+ CryptoToken token = null;
+
+ if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ token = manager.getInternalKeyStorageToken();
+ } else {
+ token = manager.getTokenByName(tokenname);
+ }
+ StringBuffer certname = new StringBuffer();
+
+ if (!token.equals(manager.getInternalKeyStorageToken())) {
+ certname.append(tokenname);
+ certname.append(":");
+ }
+ certname.append(nickname);
+ try {
+ return manager.findCertByNickname(certname.toString());
+ } catch (ObjectNotFoundException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CA_SIGNINGCERT_NOT_FOUND"));
+ }
+ }
+
+ public static KeyPair getKeyPair(String tokenname, String nickname)
+ throws NotInitializedException, NoSuchTokenException, TokenException,
+ ObjectNotFoundException, EBaseException {
+ X509Certificate cert = getCertificate(tokenname, nickname);
+ PrivateKey priKey =
+ CryptoManager.getInstance().findPrivKeyByCert(cert);
+ PublicKey publicKey = cert.getPublicKey();
+
+ return new KeyPair(publicKey, priKey);
+ }
+
+ public static PQGParams getPQG(int keysize) {
+ try {
+ return PQGParams.generate(keysize);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public static PQGParams getCAPQG(int keysize, IConfigStore store)
+ throws EBaseException {
+ if (store != null) {
+ try {
+ int pqgKeySize = store.getInteger("ca.dsaPQG.keyLength", 0);
+
+ if ((pqgKeySize > 0) && (pqgKeySize == keysize)) {
+ byte[] p = store.getByteArray("ca.dsaP", null);
+ byte[] q = store.getByteArray("ca.dsaQ", null);
+ byte[] g = store.getByteArray("ca.dsaG", null);
+ byte[] seed = store.getByteArray("ca.dsaSeed", null);
+ byte[] H = store.getByteArray("ca.dsaH", null);
+ int counter = store.getInteger("ca.dsaCounter", 0);
+
+ if (p != null && q != null && g != null) {
+ BigInteger P = new BigInteger(p);
+ BigInteger Q = new BigInteger(q);
+ BigInteger G = new BigInteger(g);
+ BigInteger pqgSeed = new BigInteger(seed);
+ BigInteger pqgH = new BigInteger(H);
+
+ return new PQGParams(P, Q, G, pqgSeed, counter, pqgH);
+ }
+ }
+ PQGParams pqg = PQGParams.generate(keysize);
+
+ store.putInteger("ca.dsaPQG.keyLength", keysize);
+ store.putString("ca.dsaP", KeyCertUtil.base64Encode(
+ pqg.getP().toByteArray()));
+ store.putString("ca.dsaQ", KeyCertUtil.base64Encode(
+ pqg.getQ().toByteArray()));
+ store.putString("ca.dsaG", KeyCertUtil.base64Encode(
+ pqg.getG().toByteArray()));
+ store.putString("ca.dsaSeed", KeyCertUtil.base64Encode(
+ pqg.getSeed().toByteArray()));
+ store.putInteger("ca.dsaCounter", pqg.getCounter());
+ store.putString("ca.dsaH", KeyCertUtil.base64Encode(
+ pqg.getH().toByteArray()));
+ store.putString("ca.DSSParms",
+ KeyCertUtil.base64Encode(
+ KeyCertUtil.makeDSSParms(pqg.getP(), pqg.getQ(), pqg.getG())));
+ store.commit(false);
+ return pqg;
+ } catch (IOException ee) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_PQG_GEN_FAILED"));
+ } catch (EBaseException ee) {
+ throw ee;
+ } catch (PQGParamGenException ee) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_PQG_GEN_FAILED"));
+ }
+ }
+ return null;
+ }
+
+ public static KeyPair generateKeyPair(CryptoToken token,
+ KeyPairAlgorithm kpAlg, int keySize, PQGParams pqg)
+ throws NoSuchAlgorithmException, TokenException, InvalidAlgorithmParameterException,
+ InvalidParameterException, PQGParamGenException {
+
+ KeyPairGenerator kpGen = token.getKeyPairGenerator(kpAlg);
+
+ if (kpAlg == KeyPairAlgorithm.DSA) {
+ if (pqg == null) {
+ kpGen.initialize(keySize);
+ } else {
+ kpGen.initialize(pqg);
+ }
+ } else {
+ kpGen.initialize(keySize);
+ }
+
+ if (pqg == null) {
+ return kpGen.genKeyPair();
+ } else {
+ // DSA
+ KeyPair kp = null;
+
+ do {
+ // 602548 NSS bug - to overcome it, we use isBadDSAKeyPair
+ kp = kpGen.genKeyPair();
+ } while (isBadDSAKeyPair(kp));
+ return kp;
+ }
+ }
+
+ /**
+ * Test for a DSA key pair that will trigger a bug in NSS.
+ * The problem occurs when the first byte of the key is 0. This
+ * happens when the value otherwise would have been negative, and a
+ * zero byte is prepended to force it to be positive.
+ * This is blackflag bug 602548.
+ */
+ public static boolean isBadDSAKeyPair(KeyPair pair) {
+ try {
+ byte[] pubkBytes = pair.getPublic().getEncoded();
+ SEQUENCE.Template outerSeq = new SEQUENCE.Template();
+
+ outerSeq.addElement(new ANY.Template()); // algid
+ outerSeq.addElement(new BIT_STRING.Template()); // key value
+ SEQUENCE seq = (SEQUENCE) ASN1Util.decode(outerSeq, pubkBytes);
+
+ BIT_STRING bs = (BIT_STRING) seq.elementAt(1);
+ ByteArrayInputStream bitstream = new ByteArrayInputStream(bs.getBits());
+ ASN1Header wrapper = new ASN1Header(bitstream);
+ byte[] valBytes = new byte[(int) wrapper.getContentLength()];
+
+ ASN1Util.readFully(valBytes, bitstream);
+
+ boolean isBroken = (valBytes[0] == 0);
+
+ return isBroken;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ public static KeyPair generateKeyPair(String tokenName, String alg,
+ int keySize, PQGParams pqg) throws EBaseException {
+
+ CryptoToken token = null;
+
+ if (tokenName.equalsIgnoreCase(Constants.PR_INTERNAL_TOKEN))
+ tokenName = Constants.PR_INTERNAL_TOKEN_NAME;
+
+ try {
+ if (tokenName.equalsIgnoreCase(Constants.PR_INTERNAL_TOKEN)) {
+ token = CryptoManager.getInstance().getInternalKeyStorageToken();
+ } else {
+ token = CryptoManager.getInstance().getTokenByName(tokenName);
+ }
+ } catch (NoSuchTokenException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", tokenName));
+ } catch (NotInitializedException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED"));
+ }
+
+ KeyPairAlgorithm kpAlg = null;
+
+ if (alg.equals("RSA"))
+ kpAlg = KeyPairAlgorithm.RSA;
+ else
+ kpAlg = KeyPairAlgorithm.DSA;
+
+ try {
+ KeyPair kp = generateKeyPair(token, kpAlg, keySize, pqg);
+
+ return kp;
+ } catch (InvalidParameterException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEYSIZE_PARAMS",
+ "" + keySize));
+ } catch (PQGParamGenException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_PQG_GEN_FAILED"));
+ } catch (NoSuchAlgorithmException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED",
+ kpAlg.toString()));
+ } catch (TokenException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_ERROR_1", e.toString()));
+ } catch (InvalidAlgorithmParameterException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED", "DSA"));
+ }
+ }
+
+ public static PKCS10 getCertRequest(String subjectName, KeyPair keyPair)
+ throws NoSuchAlgorithmException, NoSuchProviderException,
+ InvalidKeyException, IOException, CertificateException,
+ SignatureException {
+ PublicKey pubk = keyPair.getPublic();
+ X509Key key = convertPublicKeyToX509Key(pubk);
+ String alg;
+
+ if (pubk instanceof RSAPublicKey) {
+ alg = "MD5/RSA";
+ } else if (pubk instanceof PK11ECPublicKey) {
+ alg = "SHA256withEC";
+ } else {
+ alg = "DSA";
+ }
+ java.security.Signature sig =
+ java.security.Signature.getInstance(alg, "Mozilla-JSS");
+
+ sig.initSign(keyPair.getPrivate());
+
+ PKCS10 pkcs10 = new PKCS10(key);
+
+ X500Name name = new X500Name(subjectName);
+ X500Signer signer = new X500Signer(sig, name);
+
+ pkcs10.encodeAndSign(signer);
+
+ return pkcs10;
+ }
+
+ public static PKCS10 getCertRequest(String subjectName, KeyPair
+ keyPair, Extensions
+ exts)
+ throws NoSuchAlgorithmException, NoSuchProviderException,
+ InvalidKeyException, IOException, CertificateException,
+ SignatureException {
+ PublicKey pubk = keyPair.getPublic();
+ X509Key key = convertPublicKeyToX509Key(pubk);
+ String alg;
+
+ if (pubk instanceof RSAPublicKey) {
+ alg = "MD5/RSA";
+ } else if (pubk instanceof PK11ECPublicKey) {
+ alg = "SHA256withEC";
+ } else {
+ alg = "DSA";
+ }
+ java.security.Signature sig =
+ java.security.Signature.getInstance(alg, "Mozilla-JSS");
+
+ sig.initSign(keyPair.getPrivate());
+
+ PKCS10 pkcs10 = null;
+
+ if (exts != null) {
+ PKCS10Attribute attr = new
+ PKCS10Attribute(PKCS9Attribute.EXTENSION_REQUEST_OID,
+ exts);
+ PKCS10Attributes attrs = new PKCS10Attributes();
+
+ attrs.setAttribute(attr.getAttributeValue().getName(), attr);
+
+ pkcs10 = new PKCS10(key, attrs);
+ } else {
+ pkcs10 = new PKCS10(key);
+ }
+
+ X500Name name = new X500Name(subjectName);
+ X500Signer signer = new X500Signer(sig, name);
+
+ pkcs10.encodeAndSign(signer);
+
+ return pkcs10;
+ }
+
+ public static X509Key convertPublicKeyToX509Key(PublicKey pubk)
+ throws InvalidKeyException {
+
+ X509Key xKey;
+
+ if (pubk instanceof RSAPublicKey) {
+ RSAPublicKey rsaKey = (RSAPublicKey) pubk;
+
+ // REMOVED constructors from parameters by MLH on 1/9/99
+ xKey = new netscape.security.provider.RSAPublicKey(
+ new BigInt(rsaKey.getModulus()),
+ new BigInt(rsaKey.getPublicExponent()));
+ } else if (pubk instanceof PK11ECPublicKey) {
+ byte encoded[] = pubk.getEncoded();
+ xKey = CryptoUtil.getPublicX509ECCKey(encoded);
+
+ } else {
+ DSAPublicKey dsaKey = (DSAPublicKey) pubk;
+ DSAParams params = dsaKey.getParams();
+
+ xKey = new netscape.security.provider.DSAPublicKey(
+ dsaKey.getY(),
+ params.getP(),
+ params.getQ(),
+ params.getG());
+ }
+ return xKey;
+ }
+
+ public static X509Certificate
+ importCert(X509CertImpl signedCert, String nickname,
+ String certType) throws NotInitializedException, TokenException,
+ CertificateEncodingException, UserCertConflictException,
+ NicknameConflictException, NoSuchItemOnTokenException, CertificateException {
+
+ return importCert(signedCert.getEncoded(), nickname, certType);
+ }
+
+ public static X509Certificate
+ importCert(String b64E, String nickname, String certType)
+ throws NotInitializedException, TokenException,
+ CertificateEncodingException, UserCertConflictException,
+ NicknameConflictException, NoSuchItemOnTokenException, CertificateException {
+
+ byte b[] = b64E.getBytes();
+ X509Certificate cert = getInternalCertificate(b, nickname, certType);
+
+ if (cert instanceof InternalCertificate) {
+ setTrust(certType, (InternalCertificate) cert);
+ }
+ return cert;
+ }
+
+ public static X509Certificate
+ importCert(byte[] b, String nickname, String certType)
+ throws NotInitializedException, TokenException,
+ CertificateEncodingException, UserCertConflictException,
+ NicknameConflictException, NoSuchItemOnTokenException, CertificateException {
+
+ X509Certificate cert = getInternalCertificate(b, nickname, certType);
+
+ if (cert instanceof InternalCertificate) {
+ setTrust(certType, (InternalCertificate) cert);
+ }
+ return cert;
+ }
+
+ public static X509Certificate getInternalCertificate(byte[] b, String nickname, String certType)
+ throws NotInitializedException, TokenException, CertificateEncodingException,
+ UserCertConflictException, NicknameConflictException, NoSuchItemOnTokenException,
+ CertificateException {
+ X509Certificate cert = null;
+
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT)) {
+ cert = CryptoManager.getInstance().importUserCACertPackage(b,
+ nickname);
+ } else if (certType.equals(Constants.PR_RA_SIGNING_CERT) ||
+ certType.equals(Constants.PR_KRA_TRANSPORT_CERT) ||
+ certType.equals(Constants.PR_OCSP_SIGNING_CERT) ||
+ certType.equals(Constants.PR_SERVER_CERT) ||
+ certType.equals(Constants.PR_SERVER_CERT_RADM) ||
+ certType.equals(Constants.PR_OTHER_CERT) ||
+ certType.equals(Constants.PR_SUBSYSTEM_CERT)) {
+ cert = CryptoManager.getInstance().importCertPackage(b,
+ nickname);
+ } else if (certType.equals(Constants.PR_SERVER_CERT_CHAIN)) {
+ cert = CryptoManager.getInstance().importCACertPackage(b);
+ } else if (certType.equals(Constants.PR_TRUSTED_CA_CERT)) {
+ cert = CryptoManager.getInstance().importCACertPackage(b);
+ X509Certificate[] certchain = CryptoManager.getInstance().buildCertificateChain(cert);
+
+ if (certchain != null) {
+ cert = certchain[certchain.length - 1];
+ }
+ }
+ return cert;
+ }
+
+ public static void setTrust(String certType, InternalCertificate inCert) {
+ if (certType.equals(Constants.PR_CA_SIGNING_CERT)) {
+ int flag = InternalCertificate.VALID_CA |
+ InternalCertificate.TRUSTED_CA |
+ InternalCertificate.USER |
+ InternalCertificate.TRUSTED_CLIENT_CA;
+
+ inCert.setSSLTrust(flag);
+ inCert.setObjectSigningTrust(flag);
+ inCert.setEmailTrust(flag);
+ } else if (certType.equals(Constants.PR_RA_SIGNING_CERT)) {
+ int flag = InternalCertificate.USER | InternalCertificate.VALID_CA;
+
+ inCert.setSSLTrust(flag);
+ inCert.setObjectSigningTrust(flag);
+ inCert.setEmailTrust(flag);
+ } else if (certType.equals(Constants.PR_OCSP_SIGNING_CERT)) {
+ int flag = InternalCertificate.USER | InternalCertificate.VALID_CA;
+
+ inCert.setSSLTrust(flag);
+ inCert.setObjectSigningTrust(flag);
+ inCert.setEmailTrust(flag);
+ } else if (certType.equals(Constants.PR_SERVER_CERT) ||
+ certType.equals(Constants.PR_SUBSYSTEM_CERT)) {
+ int flag = InternalCertificate.USER | InternalCertificate.VALID_CA;
+
+ inCert.setSSLTrust(flag);
+ inCert.setObjectSigningTrust(flag);
+ inCert.setEmailTrust(flag);
+ } else if (certType.equals(Constants.PR_TRUSTED_CA_CERT)) {
+ inCert.setSSLTrust(InternalCertificate.TRUSTED_CA | InternalCertificate.TRUSTED_CLIENT_CA |
+ InternalCertificate.VALID_CA);
+ //inCert.setEmailTrust(InternalCertificate.TRUSTED_CA);
+
+ // cannot set this bit. If set, then the cert will not appear when you called getCACerts().
+ //inCert.setObjectSigningTrust(InternalCertificate.TRUSTED_CA);
+ }
+ }
+
+ public static byte[] convertB64EToByteArray(String b64E)
+ throws CertificateException, IOException {
+ String str = CertUtils.stripCertBrackets(b64E);
+ byte bCert[] = Utils.base64decode(str);
+
+ /*
+ java.security.cert.X509Certificate cert =
+ java.security.cert.X509Certificate.getInstance(bCert);
+ return cert;
+ */
+ return bCert;
+ }
+
+ /**
+ * ASN.1 structure:
+ * 0 30 142: SEQUENCE {
+ * 3 30 69: SEQUENCE {
+ * 5 06 3: OBJECT IDENTIFIER issuerAltName (2 5 29 18)
+ * 10 04 62: OCTET STRING
+ * : 30 3C 82 01 61 82 01 61 A4 10 30 0E 31 0C 30 0A
+ * : 06 03 55 04 03 13 03 64 73 61 87 04 01 01 01 01
+ * : 86 01 61 81 14 74 68 6F 6D 61 73 6B 40 6E 65 74
+ * : 73 63 61 70 65 2E 63 6F 6D 88 03 29 01 01
+ * : }
+ * 74 30 69: SEQUENCE {
+ * 76 06 3: OBJECT IDENTIFIER subjectAltName (2 5 29 17)
+ * 81 04 62: OCTET STRING
+ * : 30 3C 82 01 61 82 01 61 A4 10 30 0E 31 0C 30 0A
+ * : 06 03 55 04 03 13 03 64 73 61 87 04 01 01 01 01
+ * : 86 01 61 81 14 74 68 6F 6D 61 73 6B 40 6E 65 74
+ * : 73 63 61 70 65 2E 63 6F 6D 88 03 29 01 01
+ * : }
+ * : }
+ * Uses the following to test with configuration wizard:
+ * MIGOMEUGA1UdEQQ+MDyCAWGCAWGkEDAOMQwwCgYDVQQDEwNkc2GHBAEBAQGGAWGB
+ * FHRob21hc2tAbmV0c2NhcGUuY29tiAMpAQEwRQYDVR0SBD4wPIIBYYIBYaQQMA4x
+ * DDAKBgNVBAMTA2RzYYcEAQEBAYYBYYEUdGhvbWFza0BuZXRzY2FwZS5jb22IAykB
+ * AQ==
+ */
+ public static void setDERExtension(
+ CertificateExtensions ext, KeyCertData properties)
+ throws IOException {
+
+ String b64E = properties.getDerExtension();
+
+ if (b64E != null) {
+ byte[] b = Utils.base64decode(b64E);
+
+ // this b can be "Extension" Or "SEQUENCE OF Extension"
+ try {
+ DerValue b_der = new DerValue(b);
+
+ while (b_der.data.available() != 0) {
+ Extension de = new Extension(b_der.data.getDerValue());
+
+ ext.set(de.getExtensionId().toString(), de);
+ }
+ } catch (IOException e) {
+ Extension de = new Extension(new DerValue(b));
+
+ ext.set(de.getExtensionId().toString(), de);
+ }
+ }
+ }
+
+ public static void setBasicConstraintsExtension(
+ CertificateExtensions ext, KeyCertData properties)
+ throws IOException {
+ String isCA = properties.isCA();
+ String certLen = properties.getCertLen();
+
+ if (isCA == null)
+ return; // isCA is not optional
+ if (isCA.equals("null"))
+ return; // no BasicConstraints requested
+ int len = 0;
+ boolean bool = false;
+
+ if ((certLen == null) || (certLen.equals("")))
+ len = 0;
+ else
+ len = Integer.parseInt(certLen);
+
+ if ((isCA == null) || (isCA.equals("")) ||
+ (isCA.equals(Constants.FALSE)))
+ bool = false;
+ else
+ bool = true;
+
+ BasicConstraintsExtension basic = new BasicConstraintsExtension(
+ bool, len);
+
+ ext.set(BasicConstraintsExtension.NAME, basic);
+ }
+
+ public static void setExtendedKeyUsageExtension(
+ CertificateExtensions ext, KeyCertData properties) throws IOException,
+ CertificateException {
+ ExtendedKeyUsageExtension ns = new ExtendedKeyUsageExtension();
+ boolean anyExt = false;
+
+ String sslClient = properties.getSSLClientBit();
+
+ if ((sslClient != null) && (sslClient.equals(Constants.TRUE))) {
+ ns.addOID(new ObjectIdentifier("1.3.6.1.5.5.7.3.2"));
+ anyExt = true;
+ }
+
+ String sslServer = properties.getSSLServerBit();
+
+ if ((sslServer != null) && (sslServer.equals(Constants.TRUE))) {
+ ns.addOID(new ObjectIdentifier("1.3.6.1.5.5.7.3.1"));
+ anyExt = true;
+ }
+
+ String sslMail = properties.getSSLMailBit();
+
+ if ((sslMail != null) && (sslMail.equals(Constants.TRUE))) {
+ ns.addOID(new ObjectIdentifier("1.3.6.1.5.5.7.3.4"));
+ anyExt = true;
+ }
+
+ String objectSigning = properties.getObjectSigningBit();
+
+ if ((objectSigning != null) && (objectSigning.equals(Constants.TRUE))) {
+ ns.addOID(new ObjectIdentifier("1.3.6.1.5.5.7.3.3"));
+ anyExt = true;
+ }
+
+ String timestamping = properties.getTimeStampingBit();
+ if ((timestamping != null) && (timestamping.equals(Constants.TRUE))) {
+ ns.addOID(new ObjectIdentifier("1.3.6.1.5.5.7.3.8"));
+ anyExt = true;
+ }
+
+ String ocspSigning = properties.getOCSPSigning();
+
+ if ((ocspSigning != null) && (ocspSigning.equals(Constants.TRUE))) {
+ ns.addOID(new ObjectIdentifier("1.3.6.1.5.5.7.3.9"));
+ anyExt = true;
+ }
+
+ if (anyExt)
+ ext.set(ExtendedKeyUsageExtension.NAME, ns);
+ }
+
+ public static void setNetscapeCertificateExtension(
+ CertificateExtensions ext, KeyCertData properties) throws IOException,
+ CertificateException {
+
+ NSCertTypeExtension ns = new NSCertTypeExtension();
+ boolean anyExt = false;
+
+ String sslClient = properties.getSSLClientBit();
+
+ if ((sslClient != null) && (sslClient.equals(Constants.TRUE))) {
+ ns.set(NSCertTypeExtension.SSL_CLIENT, Boolean.valueOf(true));
+ anyExt = true;
+ }
+
+ String sslServer = properties.getSSLServerBit();
+
+ if ((sslServer != null) && (sslServer.equals(Constants.TRUE))) {
+ ns.set(NSCertTypeExtension.SSL_SERVER, Boolean.valueOf(true));
+ anyExt = true;
+ }
+
+ String sslMail = properties.getSSLMailBit();
+
+ if ((sslMail != null) && (sslMail.equals(Constants.TRUE))) {
+ ns.set(NSCertTypeExtension.EMAIL, Boolean.valueOf(true));
+ anyExt = true;
+ }
+
+ String sslCA = properties.getSSLCABit();
+
+ if ((sslCA != null) && (sslCA.equals(Constants.TRUE))) {
+ ns.set(NSCertTypeExtension.SSL_CA, Boolean.valueOf(true));
+ anyExt = true;
+ }
+
+ String objectSigning = properties.getObjectSigningBit();
+
+ if ((objectSigning != null) && (objectSigning.equals(Constants.TRUE))) {
+ ns.set(NSCertTypeExtension.OBJECT_SIGNING, Boolean.valueOf(true));
+ anyExt = true;
+ }
+
+ String mailCA = properties.getMailCABit();
+
+ if ((mailCA != null) && (mailCA.equals(Constants.TRUE))) {
+ ns.set(NSCertTypeExtension.EMAIL_CA, Boolean.valueOf(true));
+ anyExt = true;
+ }
+
+ String objectSigningCA = properties.getObjectSigningCABit();
+
+ if ((objectSigningCA != null) && (objectSigningCA.equals(Constants.TRUE))) {
+ ns.set(NSCertTypeExtension.OBJECT_SIGNING_CA, Boolean.valueOf(true));
+ anyExt = true;
+ }
+ if (anyExt)
+ ext.set(NSCertTypeExtension.NAME, ns);
+ }
+
+ public static void setOCSPNoCheck(KeyPair keypair,
+ CertificateExtensions ext, KeyCertData properties) throws IOException,
+ NoSuchAlgorithmException, InvalidKeyException {
+ String noCheck = properties.getOCSPNoCheck();
+
+ if ((noCheck != null) && (noCheck.equals(Constants.TRUE))) {
+ OCSPNoCheckExtension noCheckExt =
+ new OCSPNoCheckExtension();
+
+ ext.set(OCSPNoCheckExtension.NAME, noCheckExt);
+ }
+ }
+
+ public static void setOCSPSigning(KeyPair keypair,
+ CertificateExtensions ext, KeyCertData properties) throws IOException,
+ NoSuchAlgorithmException, InvalidKeyException {
+ String signing = properties.getOCSPSigning();
+
+ if ((signing != null) && (signing.equals(Constants.TRUE))) {
+ Vector<ObjectIdentifier> oidSet = new Vector<ObjectIdentifier>();
+ oidSet.addElement(
+ ObjectIdentifier.getObjectIdentifier(
+ ExtendedKeyUsageExtension.OID_OCSPSigning));
+ ExtendedKeyUsageExtension ocspExt =
+ new ExtendedKeyUsageExtension(false, oidSet);
+ ext.set(ExtendedKeyUsageExtension.NAME, ocspExt);
+ }
+ }
+
+ public static void setAuthInfoAccess(KeyPair keypair,
+ CertificateExtensions ext, KeyCertData properties) throws IOException,
+ NoSuchAlgorithmException, InvalidKeyException {
+ String aia = properties.getAIA();
+
+ if ((aia != null) && (aia.equals(Constants.TRUE))) {
+ String hostname = CMS.getEENonSSLHost();
+ String port = CMS.getEENonSSLPort();
+ AuthInfoAccessExtension aiaExt = new AuthInfoAccessExtension(false);
+ if (hostname != null && port != null) {
+ String location = "http://" + hostname + ":" + port + "/ca/ocsp";
+ GeneralName ocspName = new GeneralName(new URIName(location));
+ aiaExt.addAccessDescription(AuthInfoAccessExtension.METHOD_OCSP, ocspName);
+ }
+
+ ext.set(AuthInfoAccessExtension.NAME, aiaExt);
+ }
+ }
+
+ public static void setAuthorityKeyIdentifier(KeyPair keypair,
+ CertificateExtensions ext, KeyCertData properties) throws IOException,
+ NoSuchAlgorithmException, InvalidKeyException {
+ String aki = properties.getAKI();
+
+ if ((aki != null) && (aki.equals(Constants.TRUE))) {
+ KeyIdentifier id = createKeyIdentifier(keypair);
+ AuthorityKeyIdentifierExtension akiExt =
+ new AuthorityKeyIdentifierExtension(id, null, null);
+
+ ext.set(AuthorityKeyIdentifierExtension.NAME, akiExt);
+ }
+ }
+
+ public static void setSubjectKeyIdentifier(KeyPair keypair,
+ CertificateExtensions ext,
+ KeyCertData properties) throws IOException, NoSuchAlgorithmException,
+ InvalidKeyException {
+ String ski = properties.getSKI();
+
+ if ((ski != null) && (ski.equals(Constants.TRUE))) {
+ KeyIdentifier id = createKeyIdentifier(keypair);
+ SubjectKeyIdentifierExtension skiExt =
+ new SubjectKeyIdentifierExtension(id.getIdentifier());
+
+ ext.set(SubjectKeyIdentifierExtension.NAME, skiExt);
+ }
+ }
+
+ public static void setKeyUsageExtension(CertificateExtensions ext,
+ KeyUsageExtension keyUsage) throws IOException {
+ ext.set(KeyUsageExtension.NAME, keyUsage);
+ }
+
+ public static KeyIdentifier createKeyIdentifier(KeyPair keypair)
+ throws NoSuchAlgorithmException, InvalidKeyException {
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+ X509Key subjectKeyInfo = convertPublicKeyToX509Key(
+ keypair.getPublic());
+
+ //md.update(subjectKeyInfo.getEncoded());
+ md.update(subjectKeyInfo.getKey());
+ return new KeyIdentifier(md.digest());
+ }
+
+ public static BigInteger getSerialNumber(LDAPConnection conn, String baseDN)
+ throws LDAPException, EBaseException {
+ String dn = "ou=certificateRepository,ou=ca," + baseDN;
+ BigInteger serialno = null;
+ LDAPEntry entry = conn.read(dn);
+ LDAPAttribute serialNo = entry.getAttribute("serialno");
+ if (serialNo == null) {
+ throw new LDAPException("No value for attribute serial number in LDAP entry " + entry.getDN());
+ }
+ String serialnoStr = (String) serialNo.getStringValues().nextElement();
+
+ serialno = BigIntegerMapper.BigIntegerFromDB(serialnoStr);
+ LDAPAttribute attr = new LDAPAttribute("serialno");
+
+ attr.addValue(BigIntegerMapper.BigIntegerToDB(
+ serialno.add(new BigInteger("1"))));
+ LDAPModification mod = new LDAPModification(
+ LDAPModification.REPLACE, attr);
+
+ conn.modify(dn, mod);
+
+ return serialno;
+ }
+
+ public static void setSerialNumber(LDAPConnection conn,
+ String baseDN, BigInteger serial)
+ throws LDAPException, EBaseException {
+ String dn = "ou=certificateRepository,ou=ca," + baseDN;
+ LDAPAttribute attr = new LDAPAttribute("serialno");
+
+ // the serial number should already be set
+ attr.addValue(BigIntegerMapper.BigIntegerToDB(
+ serial));
+ LDAPModification mod = new LDAPModification(
+ LDAPModification.REPLACE, attr);
+
+ conn.modify(dn, mod);
+
+ }
+
+ public static void addCertToDB(LDAPConnection conn, String dn, X509CertImpl cert)
+ throws LDAPException, EBaseException {
+ BigInteger serialno = cert.getSerialNumber();
+ X509CertImplMapper mapper = new X509CertImplMapper();
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+
+ mapper.mapObjectToLDAPAttributeSet(null, null,
+ cert, attrs);
+ attrs.add(new LDAPAttribute("objectclass", "top"));
+ attrs.add(new LDAPAttribute("objectclass",
+ "certificateRecord"));
+ attrs.add(new LDAPAttribute("serialno",
+ BigIntegerMapper.BigIntegerToDB(
+ serialno)));
+ attrs.add(new LDAPAttribute("dateOfCreate",
+ DateMapper.dateToDB((CMS.getCurrentDate()))));
+ attrs.add(new LDAPAttribute("dateOfModify",
+ DateMapper.dateToDB((CMS.getCurrentDate()))));
+ attrs.add(new LDAPAttribute("certStatus",
+ "VALID"));
+ attrs.add(new LDAPAttribute("autoRenew",
+ "ENABLED"));
+ attrs.add(new LDAPAttribute("issuedBy",
+ "installation"));
+ LDAPEntry entry = new LDAPEntry("cn=" + serialno.toString() + "," + dn, attrs);
+
+ conn.add(entry);
+ }
+
+ public static CertificateExtensions getExtensions(String tokenname, String nickname)
+ throws NotInitializedException, TokenException, ObjectNotFoundException,
+ IOException, CertificateException {
+ String fullnickname = nickname;
+
+ if (!tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME))
+ fullnickname = tokenname + ":" + nickname;
+ CryptoManager manager = CryptoManager.getInstance();
+ X509Certificate cert = manager.findCertByNickname(fullnickname);
+ X509CertImpl impl = new X509CertImpl(cert.getEncoded());
+ X509CertInfo info = (X509CertInfo) impl.get(X509CertImpl.NAME + "." + X509CertImpl.INFO);
+
+ return (CertificateExtensions) info.get(X509CertInfo.EXTENSIONS);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/security/OCSPSigningCert.java b/base/server/cmscore/src/com/netscape/cmscore/security/OCSPSigningCert.java
new file mode 100644
index 000000000..08cdd92e8
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/security/OCSPSigningCert.java
@@ -0,0 +1,139 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.KeyPair;
+
+import netscape.security.x509.KeyUsageExtension;
+
+import org.mozilla.jss.crypto.PQGParamGenException;
+import org.mozilla.jss.crypto.PQGParams;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ConfigConstants;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.security.KeyCertData;
+
+/**
+ * OCSP signing certificate.
+ *
+ * @author Christine Ho
+ * @version $Revision$, $Date$
+ */
+public class OCSPSigningCert extends CertificateInfo {
+ public static final String SUBJECT_NAME =
+ "CN=Certificate Authority, O=Netscape Communications, C=US";
+
+ public OCSPSigningCert(KeyCertData properties) {
+ this(properties, null);
+ }
+
+ public OCSPSigningCert(KeyCertData properties, KeyPair pair) {
+ super(properties, pair);
+ /* included in console UI
+ try {
+ if (mProperties.get(Constants.PR_OCSP_SIGNING) == null) {
+ mProperties.put(Constants.PR_OCSP_SIGNING, Constants.TRUE);
+ }
+ if (mProperties.get(Constants.PR_OCSP_NOCHECK) == null) {
+ mProperties.put(Constants.PR_OCSP_NOCHECK, Constants.TRUE);
+ }
+ } catch (Exception e) {
+ mProperties.put(Constants.PR_OCSP_SIGNING, Constants.TRUE);
+ mProperties.put(Constants.PR_OCSP_NOCHECK, Constants.TRUE);
+ }
+ */
+ }
+
+ public String getSubjectName() {
+ return (String) mProperties.get(Constants.PR_SUBJECT_NAME);
+ }
+
+ // get PQG params from the configuration file
+ public PQGParams getPQGParams() throws EBaseException, IOException, PQGParamGenException {
+
+ byte[] p = mConfig.getByteArray("ca.dsaP", null);
+ byte[] q = mConfig.getByteArray("ca.dsaQ", null);
+ byte[] g = mConfig.getByteArray("ca.dsaG", null);
+ byte[] seed = mConfig.getByteArray("ca.dsaSeed", null);
+ byte[] H = mConfig.getByteArray("ca.dsaH", null);
+ int counter = mConfig.getInteger("ca.dsaCounter", 0);
+
+ if (p != null && q != null && g != null) {
+ BigInteger P = new BigInteger(p);
+ BigInteger Q = new BigInteger(q);
+ BigInteger G = new BigInteger(g);
+ BigInteger pqgSeed = new BigInteger(seed);
+ BigInteger pqgH = new BigInteger(H);
+
+ return new PQGParams(P, Q, G, pqgSeed, counter, pqgH);
+ }
+ return null;
+ }
+
+ public void updateConfig(IConfigStore cmsFileTmp) throws EBaseException {
+ String tokenname = (String) mProperties.get(Constants.PR_TOKEN_NAME);
+ String nickname = getNickname();
+
+ cmsFileTmp.putString("ca.signing.tokenname", tokenname);
+ String keyType = (String) mProperties.get(Constants.PR_KEY_TYPE);
+ String alg;
+
+ if (keyType.equals("RSA"))
+ alg = "SHA1withRSA";
+ else if (keyType.equals("DSA"))
+ alg = "SHA1withDSA";
+ else
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED", keyType));
+
+ cmsFileTmp.putString("ca.signing.defaultSigningAlgorithm", alg);
+ if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME))
+ cmsFileTmp.putString("ca.signing.cacertnickname", nickname);
+ else
+ cmsFileTmp.putString("ca.signing.cacertnickname",
+ tokenname + ":" + nickname);
+ cmsFileTmp.commit(false);
+ }
+
+ public String getNickname() {
+ String name = (String) mProperties.get(Constants.PR_NICKNAME);
+ String instanceName = (String) mProperties.get(ConfigConstants.PR_CERT_INSTANCE_NAME);
+
+ if (name != null)
+ return name;
+ return "ocspSigningCert " + instanceName;
+ }
+
+ public String getKeyAlgorithm() {
+ return (String) mProperties.get(Constants.PR_KEY_TYPE);
+ }
+
+ protected KeyUsageExtension getKeyUsageExtension() throws IOException {
+ KeyUsageExtension extension = new KeyUsageExtension();
+
+ extension.set(KeyUsageExtension.DIGITAL_SIGNATURE, Boolean.valueOf(true));
+ extension.set(KeyUsageExtension.NON_REPUDIATION, Boolean.valueOf(true));
+ extension.set(KeyUsageExtension.KEY_CERTSIGN, Boolean.valueOf(true));
+ extension.set(KeyUsageExtension.CRL_SIGN, Boolean.valueOf(true));
+ return extension;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/security/PWCBsdr.java b/base/server/cmscore/src/com/netscape/cmscore/security/PWCBsdr.java
new file mode 100644
index 000000000..a62a8561d
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/security/PWCBsdr.java
@@ -0,0 +1,257 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.util.PasswordCallback;
+import org.mozilla.jss.util.PasswordCallbackInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmscore.base.JDialogPasswordCallback;
+
+/*
+ * A class to retrieve passwords from the SDR password cache
+ *
+ * @author Christina Fu
+ * @version $Revision$, $Date$
+ */
+
+public class PWCBsdr implements PasswordCallback {
+ String mprompt = "";
+ boolean firsttime = true;
+ private PasswordCallback mCB = null;
+ private String mPWcachedb = null;
+ private ILogger mLogger = null;
+
+ public PWCBsdr() {
+ this(null);
+ }
+
+ public PWCBsdr(String prompt) {
+ mprompt = prompt;
+
+ /* to get the test program work
+ System.out.println("before CMS.getLogger");
+ try {
+ */
+ mLogger = CMS.getLogger();
+
+ /*
+ } catch (NullPointerException e) {
+ System.out.println("after CMS.getLoggergot NullPointerException ... testing ok");
+ }
+ System.out.println("after CMS.getLogger");
+ */
+ // get path to password cache
+ try {
+ mPWcachedb = CMS.getConfigStore().getString("pwCache");
+ CMS.debug("got pwCache from configstore: " +
+ mPWcachedb);
+ } catch (NullPointerException e) {
+ System.out.println("after CMS.getConfigStore got NullPointerException ... testing ok");
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_CONFIG"));
+ // let it fall through
+ }
+
+ // System.out.println("after CMS.getConfigStore");
+
+ // Unix
+ mCB = new PWsdrConsolePasswordCallback(prompt);
+
+ // mCB = new PWsdrDialogPasswordCallback( prompt );
+
+
+ // System.out.println( "Created PWCBsdr with prompt of "
+ // + mprompt );
+ }
+
+ /* We are now assuming that PasswordCallbackInfo.getname() returns
+ * the tag we are hoping to match in the cache.
+ */
+
+ public Password getPasswordFirstAttempt(PasswordCallbackInfo info)
+ throws PasswordCallback.GiveUpException {
+
+ CMS.debug("in getPasswordFirstAttempt");
+
+ /* debugging code to see if token is logged in
+ try {
+ CryptoManager cm = CryptoManager.getInstance();
+ CryptoToken token =
+ cm.getInternalKeyStorageToken();
+ if (token.isLoggedIn() == false) {
+ // missed it.
+ CMS.debug("token not yet logged in!!");
+ } else {
+ CMS.debug("token logged in.");
+ }
+ } catch (Exception e) {
+ CMS.debug("crypto manager error:"+e.toString());
+ }
+ CMS.debug("still in getPasswordFirstAttempt");
+ */
+ Password pw = null;
+ String tmpPrompt = info.getName();
+
+ String skip_token = System.getProperty("cms.skip_token");
+
+ if (skip_token != null) {
+ if (tmpPrompt.equals(skip_token)) {
+ throw new PasswordCallback.GiveUpException();
+ }
+ }
+
+ try {
+ String defpw = System.getProperty("cms.defaultpassword");
+
+ if (defpw != null) {
+ return new Password(defpw.toCharArray());
+ }
+
+ /* mprompt has precedence over info.name */
+ if (!(mprompt == null)) {
+ tmpPrompt = mprompt;
+ }
+
+ if (tmpPrompt == null) { /* no name, fail */
+ System.out.println("Shouldn't get here");
+ throw new PasswordCallback.GiveUpException();
+ } else { /* get password from password cache */
+
+ CMS.debug("getting tag = " + tmpPrompt);
+ PWsdrCache pwc = new PWsdrCache(mPWcachedb, mLogger);
+
+ pw = pwc.getEntry(tmpPrompt);
+
+ if (pw != null) {
+ CMS.debug("non-null password returned in first attempt");
+ return pw;
+ } else { /* password not found */
+ // we don't want caller to do getPasswordAgain, for now
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_THROW_CALLBACK"));
+ throw new PasswordCallback.GiveUpException();
+ }
+ }
+ } catch (Throwable e) {
+ // System.out.println( "BUG HERE!!!!first!!!!!!!!!!!!!!!!!" );
+ // e.printStackTrace();
+ throw new PasswordCallback.GiveUpException();
+ }
+ }
+
+ /* The password cache has failed to return a password (or a usable password.
+ * Now we will try and get the password from the user and hopefully add
+ * the password to the cache pw cache
+ */
+ public Password getPasswordAgain(PasswordCallbackInfo info)
+ throws PasswordCallback.GiveUpException {
+
+ CMS.debug("in getPasswordAgain");
+ try {
+ Password pw = null;
+
+ try {
+ if (firsttime) {
+ try {
+ firsttime = false;
+
+ pw = mCB.getPasswordFirstAttempt(info);
+ } catch (PasswordCallback.GiveUpException e) {
+ throw new PasswordCallback.GiveUpException();
+ }
+ } else {
+ pw = mCB.getPasswordAgain(info);
+ }
+ return (pw);
+ } catch (PasswordCallback.GiveUpException e) {
+ throw new PasswordCallback.GiveUpException();
+ }
+ } catch (Throwable e) {
+ // System.out.println( "BUG HERE!! in the password again!!"
+ // + "!!!!!!!!!!!" );
+ // e.printStackTrace();
+ throw new PasswordCallback.GiveUpException();
+ }
+ }
+
+ public void log(int level, String msg) {
+ if (mLogger == null) {
+ System.out.println(msg);
+ } else {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, level, "PWCBsdr " + msg);
+ }
+ }
+}
+
+class PWsdrConsolePasswordCallback implements PasswordCallback {
+ private String mPrompt = null;
+
+ public PWsdrConsolePasswordCallback(String p) {
+ mPrompt = p;
+ }
+
+ public String getPrompt() {
+ return mPrompt;
+ }
+
+ public Password getPasswordFirstAttempt(PasswordCallbackInfo info)
+ throws PasswordCallback.GiveUpException {
+ if (mPrompt == null) {
+ System.out.println("Get password " + info.getName());
+ } else {
+ System.out.println(getPrompt());
+ }
+
+ Password tmppw = PWUtil.readPasswordFromStream();
+
+ return (tmppw);
+ }
+
+ public Password getPasswordAgain(PasswordCallbackInfo info)
+ throws PasswordCallback.GiveUpException {
+ System.out.println("Password Incorrect.");
+ if (mPrompt == null) {
+ System.out.println("Get password " + info.getName());
+ } else {
+ System.out.println(getPrompt());
+ }
+
+ Password tmppw = PWUtil.readPasswordFromStream();
+
+ return (tmppw);
+ }
+}
+
+class PWsdrDialogPasswordCallback extends JDialogPasswordCallback {
+ private String mPrompt = null;
+
+ public PWsdrDialogPasswordCallback(String p) {
+ super();
+ mPrompt = p;
+ }
+
+ public String getPrompt(PasswordCallbackInfo info) {
+ if (mPrompt == null) {
+ return super.getPrompt(info);
+ } else {
+ return mPrompt;
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/security/PWUtil.java b/base/server/cmscore/src/com/netscape/cmscore/security/PWUtil.java
new file mode 100644
index 000000000..78678b98b
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/security/PWUtil.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.util.PasswordCallback;
+
+public class PWUtil {
+
+ public static Password readPasswordFromStream() throws PasswordCallback.GiveUpException {
+
+ StringBuffer buf = new StringBuffer();
+ String passwordString = "";
+ int c;
+ // System.out.println( "about to do read" );
+ try {
+ while ((c = System.in.read()) != -1) {
+ char ch = (char) c;
+
+ // System.out.println( "read [" + ch + "]" );
+ // System.out.println( "char is [" + ch + "]" );
+ if (ch != '\r') {
+ if (ch != '\n') {
+ buf.append(ch);
+ } else {
+ passwordString = buf.toString();
+ buf.setLength(0);
+ break;
+ }
+ }
+ }
+ } catch (Exception e) {
+ System.out.println("READ EXCEPTION");
+ }
+
+ // memory problem?
+ // String passwordString = in.readLine();
+ // System.out.println( "done read" );
+ // System.out.println( " password recieved is ["
+ // + passwordString + "]" );
+ if (passwordString == null) {
+ throw new PasswordCallback.GiveUpException();
+ }
+
+ if (passwordString.equals("")) {
+ throw new PasswordCallback.GiveUpException();
+ }
+
+ // System.out.println( "returning pw" );
+ return (new Password(passwordString.toCharArray()));
+
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/security/PWsdrCache.java b/base/server/cmscore/src/com/netscape/cmscore/security/PWsdrCache.java
new file mode 100644
index 000000000..729a368f2
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/security/PWsdrCache.java
@@ -0,0 +1,650 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.SecretDecoderRing.Decryptor;
+import org.mozilla.jss.SecretDecoderRing.Encryptor;
+import org.mozilla.jss.SecretDecoderRing.KeyManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.util.Base64OutputStream;
+import org.mozilla.jss.util.Password;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmsutil.util.Utils;
+
+/*
+ * A class for managing passwords in the SDR password cache
+ *
+ * @author Christina Fu
+ * @version $Revision$, $Date$
+ */
+public class PWsdrCache {
+ public static final String PROP_PWC_TOKEN_NAME = "pwcTokenname";
+ public static final String PROP_PWC_KEY_ID = "pwcKeyid";
+ public static final String PROP_PWC_NICKNAME = "sso_key";
+
+ private ILogger mLogger = null;
+ private String mPWcachedb = null;
+ // mTool tells if this is called from the PasswordCache tool
+ private boolean mIsTool = false;
+ private byte[] mKeyID = null;
+ private String mTokenName = null;
+ private CryptoToken mToken = null;
+
+ // for CMSEngine
+ public PWsdrCache() throws EBaseException {
+ mLogger = CMS.getLogger();
+ try {
+ mPWcachedb = CMS.getConfigStore().getString("pwCache");
+ CMS.debug("got pwCache file path from configstore");
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_CONFIG"));
+ // let it fall through
+ }
+ initToken();
+ initKey();
+ }
+
+ private void initToken() throws EBaseException {
+ if (mToken == null) {
+ CryptoManager cm = null;
+ try {
+ cm = CryptoManager.getInstance();
+ mTokenName = CMS.getConfigStore().getString(PROP_PWC_TOKEN_NAME);
+ log(ILogger.LL_DEBUG, "pwcTokenname specified. Use token for SDR key. tokenname= " + mTokenName);
+ mToken = cm.getTokenByName(mTokenName);
+ } catch (NotInitializedException e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ throw new EBaseException(e.toString());
+ } catch (Exception e) {
+ log(ILogger.LL_DEBUG, "no pwcTokenname specified, use internal token for SDR key");
+ mToken = cm.getInternalKeyStorageToken();
+ }
+ }
+ }
+
+ // called from PWCBsdr or CMSEngine only
+ private void initKey() throws EBaseException {
+ if (mKeyID == null) {
+ try {
+ String keyID = CMS.getConfigStore().getString(PROP_PWC_KEY_ID);
+ log(ILogger.LL_DEBUG, "retrieved PWC SDR key");
+ mKeyID = base64Decode(keyID);
+
+ } catch (Exception e) {
+ log(ILogger.LL_DEBUG, "no pwcSDRKey specified");
+ throw new EBaseException(e.toString());
+ }
+ }
+ }
+
+ // for PasswordCache tool (isTool == true)
+ // and installation wizard (isTool == false)
+ // Do not use for PWCBsdr, since we don't want to mistakenly
+ // generate SDR keys in case of configuration errors
+ public PWsdrCache(String pwCache, String pwcTokenname, byte[] keyId,
+ boolean isTool) throws Exception {
+ mPWcachedb = pwCache;
+ mIsTool = isTool;
+ mTokenName = pwcTokenname;
+ CryptoManager cm = null;
+
+ if (keyId != null) {
+ mKeyID = keyId;
+ }
+
+ cm = CryptoManager.getInstance();
+ if (mTokenName != null) {
+ mToken = cm.getTokenByName(mTokenName);
+ debug("PWsdrCache: mToken = " + mTokenName);
+ } else {
+ mToken = cm.getInternalKeyStorageToken();
+ debug("PWsdrCache: mToken = internal");
+ }
+ }
+
+ public byte[] getKeyId() {
+ return mKeyID;
+ }
+
+ public String getTokenName() {
+ return mTokenName;
+ }
+
+ public void deleteUniqueNamedKey(String nickName)
+ throws Exception {
+ KeyManager km = new KeyManager(mToken);
+ km.deleteUniqueNamedKey(nickName);
+ }
+
+ public byte[] generateSDRKey() throws Exception {
+ return generateSDRKeyWithNickName(PROP_PWC_NICKNAME);
+ }
+
+ public byte[] generateSDRKeyWithNickName(String nickName)
+ throws Exception {
+ try {
+
+ if (mIsTool != true) {
+ // generate SDR key
+ KeyManager km = new KeyManager(mToken);
+ try {
+ // Bugscape Bug #54838: Due to the CMS cloning feature,
+ // we must check for the presence of
+ // a uniquely named symmetric key
+ // prior to making an attempt to
+ // generate it!
+ //
+ if (!(km.uniqueNamedKeyExists(nickName))) {
+ mKeyID = km.generateUniqueNamedKey(nickName);
+ }
+ } catch (TokenException e) {
+ log(0, "generateSDRKey() failed on " + e.toString());
+ throw e;
+ }
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, e.toString());
+ throw e;
+ }
+ return mKeyID;
+ }
+
+ public byte[] base64Decode(String s) throws IOException {
+ byte[] d = Utils.base64decode(s);
+ return d;
+ }
+
+ public static String base64Encode(byte[] bytes) throws IOException {
+ // All this streaming is lame, but Base64OutputStream needs a
+ // PrintStream
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ try (Base64OutputStream b64 = new Base64OutputStream(
+ new PrintStream(new FilterOutputStream(output)))) {
+
+ b64.write(bytes);
+ b64.flush();
+
+ // This is internationally safe because Base64 chars are
+ // contained within 8859_1
+ return output.toString("8859_1");
+ }
+ }
+
+ // for PWCBsdr
+ public PWsdrCache(String pwCache, ILogger logger) throws
+ EBaseException {
+ mLogger = logger;
+ mPWcachedb = pwCache;
+ initToken();
+ initKey();
+ }
+
+ public void addEntry(String tag, String pwd) throws EBaseException {
+ addEntry(tag, pwd, (Hashtable<String, String>) null);
+ }
+
+ /*
+ * Store passwd in pwcache.
+ */
+ public void addEntry(Hashtable<String, String> ht) throws EBaseException {
+ addEntry((String) null, (String) null, ht);
+ }
+
+ /*
+ * add passwd in pwcache.
+ */
+ public void addEntry(String tag, String pwd, Hashtable<String, String> tagPwds) throws EBaseException {
+ StringBuffer stringToAdd = new StringBuffer();
+
+ String bufs = null;
+
+ if (tagPwds == null) {
+ stringToAdd.append(tag + ":" + pwd + "\n");
+ } else {
+ Enumeration<String> enum1 = tagPwds.keys();
+
+ while (enum1.hasMoreElements()) {
+ tag = enum1.nextElement();
+ pwd = tagPwds.get(tag);
+ debug("password tag: " + tag + " stored in " + mPWcachedb);
+
+ stringToAdd.append(tag + ":" + pwd + "\n");
+ }
+ }
+
+ String dcrypts = readPWcache();
+
+ if (dcrypts != null) {
+ // converts to Hashtable, replace if tag exists, add
+ // if tag doesn't exist
+ Hashtable<String, String> ht = string2Hashtable(dcrypts);
+
+ if (ht.containsKey(tag) == false) {
+ debug("adding new tag: " + tag);
+ ht.put(tag, pwd);
+ } else {
+ debug("replacing tag: " + tag);
+ ht.put(tag, pwd);
+ }
+ bufs = hashtable2String(ht);
+ } else {
+ debug("adding new tag: " + tag);
+ bufs = stringToAdd.toString();
+ }
+
+ // write update to cache
+ writePWcache(bufs);
+ }
+
+ /*
+ * delete passwd in pwcache.
+ */
+ public void deleteEntry(String tag) throws EBaseException {
+ String bufs = null;
+
+ String dcrypts = readPWcache();
+
+ if (dcrypts != null) {
+ // converts to Hashtable, replace if tag exists, add
+ // if tag doesn't exist
+ Hashtable<String, String> ht = string2Hashtable(dcrypts);
+
+ if (ht.containsKey(tag) == false) {
+ debug("tag: " + tag + " does not exist");
+ return;
+ } else {
+ debug("deleting tag: " + tag);
+ ht.remove(tag);
+ }
+ bufs = hashtable2String(ht);
+ } else {
+ debug("password cache contains no tags");
+ return;
+ }
+
+ // write update to cache
+ writePWcache(bufs);
+ }
+
+ /*
+ * reads and decrypts the pwcache.db content
+ */
+ public String readPWcache() throws EBaseException {
+ debug("about to read password cache");
+ String dcrypts = null;
+ Decryptor sdr = new Decryptor(mToken);
+
+ // not used, but could used for debugging
+ int totalRead = 0;
+ FileInputStream inputs = null;
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ try {
+ // for SDR -> read, decrypt, append, and write
+ inputs = new FileInputStream(mPWcachedb);
+ byte[] readbuf = new byte[2048]; // for now
+ int numRead = 0;
+
+ while ((numRead = inputs.read(readbuf)) != -1) {
+ bos.write(readbuf, 0, numRead);
+ totalRead += numRead;
+ }
+
+ } catch (FileNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PW_FILE", mPWcachedb, e.toString()));
+ throw new EBaseException(e.toString() + ": " + mPWcachedb);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PW_FILE", mPWcachedb, e.toString()));
+ throw new EBaseException(e.toString() + ": " + mPWcachedb);
+ } finally {
+ if (inputs != null) {
+ try {
+ inputs.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ if (totalRead > 0) {
+ try {
+ // decrypt it first to append
+ byte[] dcryptb = sdr.decrypt(bos.toByteArray());
+
+ dcrypts = new String(dcryptb, "UTF-8");
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PW_DECRYPT", e.toString()));
+ e.printStackTrace();
+ throw new EBaseException("password cache decrypt failed");
+ }
+ }
+
+ return dcrypts;
+ }
+
+ /*
+ * encrypts and writes the whole String buf into pwcache.db
+ */
+ public void writePWcache(String bufs) throws EBaseException {
+ FileOutputStream outstream = null;
+ try {
+ Encryptor sdr = new Encryptor(mToken, mKeyID,
+ Encryptor.DEFAULT_ENCRYPTION_ALG);
+
+ byte[] writebuf = null;
+
+ try {
+ // now encrypt it again
+ writebuf = sdr.encrypt(bufs.getBytes("UTF-8"));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PW_ENCRYPT", e.toString()));
+ e.printStackTrace();
+ throw new EBaseException("password cache encrypt failed");
+ }
+
+ File tmpPWcache = new File(mPWcachedb + ".tmp");
+
+ if (tmpPWcache.exists()) {
+ // it wasn't removed?
+ if (!tmpPWcache.delete()) {
+ debug("Could not delete the existing " + mPWcachedb + ".tmp file.");
+ }
+ tmpPWcache = new File(mPWcachedb + ".tmp");
+ }
+ outstream = new FileOutputStream(mPWcachedb + ".tmp");
+
+ outstream.write(writebuf);
+
+
+ File origFile = new File(mPWcachedb);
+
+ try {
+ if (Utils.isNT()) {
+ // NT is very picky on the path
+ Utils.exec("copy " +
+ tmpPWcache.getAbsolutePath().replace('/',
+ '\\') +
+ " " +
+ origFile.getAbsolutePath().replace('/',
+ '\\'));
+ } else {
+ // Create a copy of the original file which
+ // preserves the original file permissions.
+ Utils.exec("cp -p " + tmpPWcache.getAbsolutePath() + " " +
+ origFile.getAbsolutePath());
+ }
+
+ // Remove the original file if and only if
+ // the backup copy was successful.
+ if (origFile.exists()) {
+ if (!Utils.isNT()) {
+ try {
+ Utils.exec("chmod 00660 " +
+ origFile.getCanonicalPath());
+ } catch (IOException e) {
+ CMS.debug("Unable to change file permissions on "
+ + origFile.toString());
+ }
+ }
+ if (!tmpPWcache.delete()) {
+ debug("Could not delete the existing " + mPWcachedb + ".tmp file.");
+ }
+ debug("operation completed for " + mPWcachedb);
+ }
+ } catch (Exception exx) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PW_CACHE", exx.toString()));
+ throw new EBaseException(exx.toString() + ": " + mPWcachedb);
+ }
+ } catch (FileNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PW_FILE", mPWcachedb, e.toString()));
+ throw new EBaseException(e.toString() + ": " + mPWcachedb);
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PW_FILE", mPWcachedb, e.toString()));
+ throw new EBaseException(e.toString() + ": " + mPWcachedb);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PW_FILE", mPWcachedb, e.toString()));
+ throw new EBaseException(e.toString() + ": " + mPWcachedb);
+ } finally {
+ if (outstream != null) {
+ try {
+ outstream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public String hashtable2String(Hashtable<String, String> ht) {
+ Enumeration<String> enum1 = ht.keys();
+ StringBuffer returnString = new StringBuffer();
+
+ while (enum1.hasMoreElements()) {
+ String tag = enum1.nextElement();
+ String pwd = ht.get(tag);
+ returnString.append(tag + ":" + pwd + "\n");
+ }
+ return returnString.toString();
+ }
+
+ public Hashtable<String, String> string2Hashtable(String cache) {
+ Hashtable<String, String> ht = new Hashtable<String, String>();
+
+ // first, break into lines
+ StringTokenizer st = new StringTokenizer(cache, "\n");
+
+ while (st.hasMoreTokens()) {
+ String line = st.nextToken();
+ // break into tag:password format for each line
+ int colonIdx = line.indexOf(":");
+
+ if (colonIdx != -1) {
+ String tag = line.substring(0, colonIdx);
+ String passwd = line.substring(colonIdx + 1,
+ line.length());
+
+ ht.put(tag.trim(), passwd.trim());
+ } else {
+ //invalid format...log or throw...later
+ }
+ }
+ return ht;
+ }
+
+ /*
+ * get password from cache. This one supplies cache file name
+ */
+ public Password getEntry(String fileName, String tag) {
+ mPWcachedb = fileName;
+ return getEntry(tag);
+ }
+
+ /*
+ * if tag found with pwd, return it
+ * if tag not found, return null, which will cause it to give up
+ */
+ public Password getEntry(String tag) {
+ Hashtable<String, String> pwTable = null;
+ String pw = null;
+
+ debug("in getEntry, tag=" + tag);
+
+ if (mPWcachedb == null) {
+ debug("mPWcachedb file path name is not initialized");
+ return null;
+ }
+
+ String dcrypts = null;
+
+ try {
+ dcrypts = readPWcache();
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PW_READ", e.toString()));
+ return null;
+ }
+
+ if (dcrypts != null) {
+ // parse the cache
+ String cache = dcrypts;
+
+ // this is created and destroyed at each use
+ pwTable = string2Hashtable(cache);
+ debug("in getEntry, pw cache parsed");
+ pw = pwTable.get(tag);
+ }
+
+ if (pw != null) {
+ debug("getEntry gotten password for " + tag);
+ return new Password(pw.toCharArray());
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PW_TAG", tag));
+ return null;
+ }
+ }
+
+ //copied from IOUtil.java
+ /**
+ * Checks if this is NT.
+ */
+ public static boolean isNT() {
+ return ((File.separator).equals("\\"));
+ }
+
+ public static boolean exec(String cmd) throws IOException {
+ String cmds[] = null;
+
+ if (isNT()) {
+ // NT
+ cmds = new String[3];
+ cmds[0] = "cmd";
+ cmds[1] = "/c";
+ cmds[2] = cmd;
+ } else {
+ // UNIX
+ cmds = new String[3];
+ cmds[0] = "/bin/sh";
+ cmds[1] = "-c";
+ cmds[2] = cmd;
+ }
+ Process process = null;
+ try {
+ process = Runtime.getRuntime().exec(cmds);
+ process.waitFor();
+ } catch (IOException e) {
+ throw e;
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+
+ if (process != null && process.exitValue() == 0) {
+
+ /**
+ * pOut = new BufferedReader(
+ * new InputStreamReader(process.getInputStream()));
+ * while ((l = pOut.readLine()) != null) {
+ * System.out.println(l);
+ * }
+ **/
+ return true;
+ } else {
+
+ /**
+ * pOut = new BufferedReader(
+ * new InputStreamReader(process.getErrorStream()));
+ * l = null;
+ * while ((l = pOut.readLine()) != null) {
+ * System.out.println(l);
+ * }
+ **/
+ return false;
+ }
+ }
+
+ public void debug(String msg) {
+ if (mLogger != null) {
+ CMS.debug(msg);
+ }
+ }
+
+ public void log(int level, String msg) {
+ if (mLogger != null) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, level,
+ "PWsdrCache " + msg);
+ } else if (mIsTool) {
+ System.out.println(msg);
+ } // else it's most likely the installation wizard...no logging
+ }
+
+ /*
+ * list passwds in pwcache.
+ */
+ public boolean pprint() {
+ String dcrypts = null;
+
+ try {
+ dcrypts = readPWcache();
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PW_READ", e.toString()));
+ return false;
+ }
+
+ debug("----- Password Cache Content -----");
+
+ if (dcrypts != null) {
+ // first, break into lines
+ StringTokenizer st = new StringTokenizer(dcrypts, "\n");
+
+ while (st.hasMoreTokens()) {
+ String line = st.nextToken();
+ // break into tag:password format for each line
+ int colonIdx = line.indexOf(":");
+
+ if (colonIdx != -1) {
+ String tag = line.substring(0, colonIdx);
+ String passwd = line.substring(colonIdx + 1,
+ line.length());
+
+ debug(tag.trim() +
+ " : " + passwd.trim());
+ } else {
+ //invalid format...log or throw...later
+ debug("invalid format");
+ }
+ }
+ } // else print nothing
+ return true;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/security/Provider.java b/base/server/cmscore/src/com/netscape/cmscore/security/Provider.java
new file mode 100644
index 000000000..540fe2201
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/security/Provider.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+public class Provider extends java.security.Provider {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -8050884788034389693L;
+
+ public Provider() {
+ super("CMS", 1.4,
+ "Provides Signature and Message Digesting");
+
+ /////////////////////////////////////////////////////////////
+ // Signature
+ /////////////////////////////////////////////////////////////
+
+ put("Signature.SHA1withDSA", "org.mozilla.jss.provider.DSASignature");
+
+ put("Alg.Alias.Signature.DSA", "SHA1withDSA");
+ put("Alg.Alias.Signature.DSS", "SHA1withDSA");
+ put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA");
+ put("Alg.Alias.Signature.SHA-1/DSA", "SHA1withDSA");
+ put("Alg.Alias.Signature.SHA1/DSA", "SHA1withDSA");
+ put("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA");
+ put("Alg.Alias.Signature.SHAwithDSA", "SHA1withDSA");
+
+ put("Signature.MD5/RSA", "org.mozilla.jss.provider.MD5RSASignature");
+ put("Signature.MD2/RSA", "org.mozilla.jss.provider.MD2RSASignature");
+ put("Signature.SHA-1/RSA",
+ "org.mozilla.jss.provider.SHA1RSASignature");
+
+ put("Alg.Alias.Signature.SHA1/RSA", "SHA-1/RSA");
+
+ /////////////////////////////////////////////////////////////
+ // Message Digesting
+ /////////////////////////////////////////////////////////////
+
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/security/RASigningCert.java b/base/server/cmscore/src/com/netscape/cmscore/security/RASigningCert.java
new file mode 100644
index 000000000..51e05b5e9
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/security/RASigningCert.java
@@ -0,0 +1,107 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+import java.io.IOException;
+import java.security.KeyPair;
+
+import netscape.security.x509.KeyUsageExtension;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ConfigConstants;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.security.KeyCertData;
+
+/**
+ * RA signing certificate
+ *
+ * @author Christine Ho
+ * @version $Revision$, $Date$
+ */
+public class RASigningCert extends CertificateInfo {
+ public static final String SUBJECT_NAME =
+ "CN=Registration Authority, O=Netscape Communications, C=US";
+
+ public RASigningCert(KeyCertData properties) {
+ this(properties, null);
+ }
+
+ public RASigningCert(KeyCertData properties, KeyPair pair) {
+ super(properties, pair);
+ try {
+ if (mProperties.get(Constants.PR_AKI) == null) {
+ mProperties.put(Constants.PR_AKI, Constants.FALSE);
+ }
+ } catch (Exception e) {
+ mProperties.put(Constants.PR_AKI, Constants.FALSE);
+ }
+ }
+
+ public void updateConfig(IConfigStore cmsFileTmp) throws EBaseException {
+ String tokenname = (String) mProperties.get(Constants.PR_TOKEN_NAME);
+ String nickname = getNickname();
+
+ if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME))
+ cmsFileTmp.putString("ra.certNickname", nickname);
+ else
+ cmsFileTmp.putString("ra.certNickname", tokenname + ":" + nickname);
+ cmsFileTmp.commit(false);
+ }
+
+ public String getSubjectName() {
+ return (String) mProperties.get(Constants.PR_SUBJECT_NAME);
+ }
+
+ public String getNickname() {
+ String name = (String) mProperties.get(Constants.PR_NICKNAME);
+ String instanceName =
+ (String) mProperties.get(ConfigConstants.PR_CERT_INSTANCE_NAME);
+
+ if (name != null)
+ return name;
+ return "raSigningCert " + instanceName;
+ }
+
+ /*
+ public SignatureAlgorithm getSigningAlgorithm() {
+ SignatureAlgorithm sAlg =
+ (SignatureAlgorithm)mProperties.get(Constants.PR_SIGNATURE_ALGORITHM);
+ if (sAlg != null) {
+ return sAlg;
+ }
+ String alg = (String)mProperties.get(Constants.PR_KEY_TYPE);
+
+ if (alg.equals("RSA"))
+ return SignatureAlgorithm.RSASignatureWithMD5Digest;
+ else
+ return SignatureAlgorithm.DSASignatureWithSHA1Digest;
+ }
+ */
+
+ public String getKeyAlgorithm() {
+ return (String) mProperties.get(Constants.PR_KEY_TYPE);
+ }
+
+ protected KeyUsageExtension getKeyUsageExtension() throws IOException {
+ KeyUsageExtension extension = new KeyUsageExtension();
+
+ extension.set(KeyUsageExtension.DIGITAL_SIGNATURE, Boolean.valueOf(true));
+ return extension;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/security/SSLCert.java b/base/server/cmscore/src/com/netscape/cmscore/security/SSLCert.java
new file mode 100644
index 000000000..99b920c98
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/security/SSLCert.java
@@ -0,0 +1,119 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+import java.io.IOException;
+import java.security.KeyPair;
+
+import netscape.security.x509.KeyUsageExtension;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ConfigConstants;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.security.KeyCertData;
+
+/**
+ * SSL server certificate
+ *
+ * @author Christine Ho
+ * @version $Revision$, $Date$
+ */
+public class SSLCert extends CertificateInfo {
+ public static final String SUBJECT_NAME =
+ "CN=SSL, O=Netscape Communications, C=US";
+
+ public SSLCert(KeyCertData properties) {
+ this(properties, null);
+ }
+
+ public SSLCert(KeyCertData properties, KeyPair pair) {
+ super(properties, pair);
+ try {
+ if (mProperties.get(Constants.PR_AKI) == null) {
+ mProperties.put(Constants.PR_AKI, Constants.FALSE);
+ }
+ } catch (Exception e) {
+ mProperties.put(Constants.PR_AKI, Constants.FALSE);
+ }
+
+ // 020598: The server bit has to be turned on. Otherwise, it might
+ // crash jss.
+ //mProperties.put(Constants.PR_SSL_SERVER_BIT, Constants.TRUE);
+ }
+
+ public void updateConfig(IConfigStore cmsFileTmp) throws EBaseException {
+ String tokenname = (String) mProperties.get(Constants.PR_TOKEN_NAME);
+ String nickname = getNickname();
+ String fullNickname = "";
+
+ if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ fullNickname = nickname;
+ } else {
+ fullNickname = tokenname + ":" + nickname;
+ }
+ cmsFileTmp.putString("agent.nickName", fullNickname);
+ cmsFileTmp.putString("ee.nickName", fullNickname);
+ cmsFileTmp.putString("radm.nickName", fullNickname);
+ cmsFileTmp.commit(false);
+ }
+
+ public String getSubjectName() {
+ return (String) mProperties.get(Constants.PR_SUBJECT_NAME);
+ }
+
+ public String getNickname() {
+ String name = (String) mProperties.get(Constants.PR_NICKNAME);
+ String instanceName =
+ (String) mProperties.get(ConfigConstants.PR_CERT_INSTANCE_NAME);
+
+ if (name != null)
+ return name;
+ return "Server-Cert " + instanceName;
+ }
+
+ /*
+ public SignatureAlgorithm getSigningAlgorithm() {
+ SignatureAlgorithm sAlg =
+ (SignatureAlgorithm)mProperties.get(Constants.PR_SIGNATURE_ALGORITHM);
+ if (sAlg != null) {
+ return sAlg;
+ }
+ String alg = (String)mProperties.get(Constants.PR_KEY_TYPE);
+
+ if (alg.equals("RSA"))
+ return SignatureAlgorithm.RSASignatureWithMD5Digest;
+ else
+ return SignatureAlgorithm.DSASignatureWithSHA1Digest;
+ }
+ */
+
+ public String getKeyAlgorithm() {
+ return (String) mProperties.get(Constants.PR_KEY_TYPE);
+ }
+
+ protected KeyUsageExtension getKeyUsageExtension() throws IOException {
+ KeyUsageExtension extension = new KeyUsageExtension();
+
+ extension.set(KeyUsageExtension.DIGITAL_SIGNATURE, Boolean.valueOf(true));
+ extension.set(KeyUsageExtension.NON_REPUDIATION, Boolean.valueOf(true));
+ extension.set(KeyUsageExtension.KEY_ENCIPHERMENT, Boolean.valueOf(true));
+ extension.set(KeyUsageExtension.DATA_ENCIPHERMENT, Boolean.valueOf(true));
+ return extension;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/security/SSLSelfSignedCert.java b/base/server/cmscore/src/com/netscape/cmscore/security/SSLSelfSignedCert.java
new file mode 100644
index 000000000..8cee1d155
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/security/SSLSelfSignedCert.java
@@ -0,0 +1,113 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+import java.io.IOException;
+import java.security.KeyPair;
+
+import netscape.security.x509.KeyUsageExtension;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ConfigConstants;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.security.KeyCertData;
+
+/**
+ * SSL server certificate
+ *
+ * @author Christine Ho
+ * @version $Revision$, $Date$
+ */
+public class SSLSelfSignedCert extends CertificateInfo {
+ public static final String SUBJECT_NAME =
+ "CN=SSL, O=Netscape Communications, C=US";
+
+ public SSLSelfSignedCert(KeyCertData properties) {
+ this(properties, null);
+ }
+
+ public SSLSelfSignedCert(KeyCertData properties, KeyPair pair) {
+ super(properties, pair);
+ mProperties.remove(Constants.PR_AKI);
+
+ // 020599: This SSL server bit has to be turned on. Otherwise, it
+ // might crash jss.
+ mProperties.put(Constants.PR_SSL_SERVER_BIT, Constants.TRUE);
+ }
+
+ public void updateConfig(IConfigStore cmsFileTmp) throws EBaseException {
+ String tokenname = (String) mProperties.get(Constants.PR_TOKEN_NAME);
+ String nickname = getNickname();
+ String fullNickname = "";
+
+ if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) {
+ fullNickname = nickname;
+ } else {
+ fullNickname = tokenname + ":" + nickname;
+ }
+ cmsFileTmp.putString("radm.https.nickName", fullNickname);
+ cmsFileTmp.commit(false);
+ }
+
+ public String getSubjectName() {
+ return (String) mProperties.get(Constants.PR_SUBJECT_NAME);
+ }
+
+ public String getNickname() {
+ String name = (String) mProperties.get(Constants.PR_NICKNAME);
+ String instanceName =
+ (String) mProperties.get(ConfigConstants.PR_CERT_INSTANCE_NAME);
+
+ if (name != null)
+ return name;
+ return "Remote Admin Server-Cert " + instanceName;
+ }
+
+ /*
+ public SignatureAlgorithm getSigningAlgorithm() {
+ SignatureAlgorithm sAlg =
+ (SignatureAlgorithm)mProperties.get(Constants.PR_SIGNATURE_ALGORITHM);
+ if (sAlg != null) {
+ return sAlg;
+ }
+ String alg = (String)mProperties.get(Constants.PR_KEY_TYPE);
+
+ if (alg.equals("RSA"))
+ return SignatureAlgorithm.RSASignatureWithMD5Digest;
+ else
+ return SignatureAlgorithm.DSASignatureWithSHA1Digest;
+ }
+ */
+
+ public String getKeyAlgorithm() {
+ return (String) mProperties.get(Constants.PR_KEY_TYPE);
+ }
+
+ public void signed() {
+ }
+
+ protected KeyUsageExtension getKeyUsageExtension() throws IOException {
+ KeyUsageExtension extension = new KeyUsageExtension();
+
+ extension.set(KeyUsageExtension.DIGITAL_SIGNATURE, Boolean.valueOf(true));
+ //extension.set(KeyUsageExtension.NON_REPUDIATION, Boolean.valueOf(true));
+ extension.set(KeyUsageExtension.KEY_ENCIPHERMENT, Boolean.valueOf(true));
+ return extension;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/security/SubsystemCert.java b/base/server/cmscore/src/com/netscape/cmscore/security/SubsystemCert.java
new file mode 100644
index 000000000..5ad3e11f2
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/security/SubsystemCert.java
@@ -0,0 +1,81 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+import java.io.IOException;
+import java.security.KeyPair;
+
+import netscape.security.x509.KeyUsageExtension;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.common.ConfigConstants;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.security.KeyCertData;
+
+/**
+ * Subsystem certificate.
+ *
+ * @author Christine Ho
+ * @version $Revision$, $Date$
+ */
+public class SubsystemCert extends CertificateInfo {
+
+ public SubsystemCert(KeyCertData properties) {
+ this(properties, null);
+ }
+
+ public SubsystemCert(KeyCertData properties, KeyPair pair) {
+ super(properties, pair);
+ try {
+ if (mProperties.get(Constants.PR_SSL_CLIENT_BIT) == null)
+ mProperties.put(Constants.PR_SSL_CLIENT_BIT, Constants.TRUE);
+ } catch (Exception e) {
+ mProperties.put(Constants.PR_SSL_CLIENT_BIT, Constants.TRUE);
+ }
+ }
+
+ public String getSubjectName() {
+ return (String) mProperties.get(Constants.PR_SUBJECT_NAME);
+ }
+
+ public void updateConfig(IConfigStore cmsFileTmp) throws EBaseException {
+ }
+
+ public String getNickname() {
+ String name = (String) mProperties.get(Constants.PR_NICKNAME);
+ String instanceName = (String) mProperties.get(ConfigConstants.PR_CERT_INSTANCE_NAME);
+
+ if (name != null)
+ return name;
+ return "subsystemCert " + instanceName;
+ }
+
+ public String getKeyAlgorithm() {
+ return (String) mProperties.get(Constants.PR_KEY_TYPE);
+ }
+
+ protected KeyUsageExtension getKeyUsageExtension() throws IOException {
+ KeyUsageExtension extension = new KeyUsageExtension();
+
+ extension.set(KeyUsageExtension.DIGITAL_SIGNATURE, Boolean.valueOf(true));
+ extension.set(KeyUsageExtension.NON_REPUDIATION, Boolean.valueOf(true));
+ extension.set(KeyUsageExtension.KEY_ENCIPHERMENT, Boolean.valueOf(true));
+ return extension;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestOrderedInstance.java b/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestOrderedInstance.java
new file mode 100644
index 000000000..62bf09063
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestOrderedInstance.java
@@ -0,0 +1,136 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cmscore.selftests;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+import java.util.StringTokenizer;
+
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * This class implements a single element in
+ * an ordered list of self test instances.
+ * <P>
+ *
+ * @author mharmsen
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class SelfTestOrderedInstance {
+ ////////////////////////
+ // default parameters //
+ ////////////////////////
+
+ private static final String ELEMENT_DELIMITER = ":";
+ private static final String CRITICAL = "critical";
+
+ ////////////////////////////////////////
+ // SelfTestOrderedInstance parameters //
+ ////////////////////////////////////////
+
+ private String mInstanceName = null;
+ private boolean mCritical = false;
+
+ /////////////////////
+ // default methods //
+ /////////////////////
+
+ /**
+ * Constructs a single element within an ordered list of self tests.
+ * A "listElement" contains a string of the form "[instanceName]" or
+ * "[instanceName]:critical".
+ * <P>
+ *
+ * @param listElement a string containing the "instanceName" and
+ * information indictating whether or not the instance is "critical"
+ */
+ public SelfTestOrderedInstance(String listElement) {
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (listElement != null) {
+ listElement = listElement.trim();
+ } else {
+ // no listElement is present
+ return;
+ }
+
+ StringTokenizer token = new StringTokenizer(listElement,
+ ELEMENT_DELIMITER);
+
+ // extract the mInstanceName
+ if (token.hasMoreTokens()) {
+ // prior to the ELEMENT_DELIMITER
+ mInstanceName = token.nextToken().trim();
+
+ // extract the mCritical indicator
+ if (token.hasMoreTokens()) {
+ // something exists after the ELEMENT_DELIMITER
+ if (token.nextToken().trim().equals(CRITICAL)) {
+ mCritical = true;
+ }
+ }
+ } else {
+ // no ELEMENT_DELIMITER is present
+ mInstanceName = listElement;
+ }
+
+ }
+
+ /////////////////////////////////////
+ // SelfTestOrderedInstance methods //
+ /////////////////////////////////////
+
+ /**
+ * Returns the name associated with this self test; may be null.
+ * <P>
+ *
+ * @return instanceName of this self test
+ */
+ public String getSelfTestName() {
+ return mInstanceName;
+ }
+
+ /**
+ * Returns the criticality associated with this self test.
+ * <P>
+ *
+ * @return true if failure of this self test is fatal when
+ * it is executed; otherwise return false
+ */
+ public boolean isSelfTestCritical() {
+ return mCritical;
+ }
+
+ /**
+ * Sets/resets the criticality associated with this self test.
+ * <P>
+ *
+ * @param criticalMode the criticality of this self test
+ */
+ public void setSelfTestCriticalMode(boolean criticalMode) {
+ mCritical = criticalMode;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestService.java b/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestService.java
new file mode 100644
index 000000000..da7708e49
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestService.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) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cmscore.selftests;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+
+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.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.selftests.EMissingSelfTestException;
+import com.netscape.certsrv.selftests.ISelfTestSubsystem;
+import com.netscape.certsrv.selftests.SelfTestCollection;
+import com.netscape.certsrv.selftests.SelfTestData;
+import com.netscape.certsrv.selftests.SelfTestResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class SelfTestService extends PKIService implements SelfTestResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public final static int DEFAULT_SIZE = 20;
+
+ public SelfTestService() {
+ CMS.debug("SelfTestService.<init>()");
+ }
+
+ public SelfTestData createSelfTestData(ISelfTestSubsystem subsystem, String selfTestID) throws UnsupportedEncodingException, EMissingSelfTestException {
+
+ SelfTestData selfTestData = new SelfTestData();
+ selfTestData.setID(selfTestID);
+ selfTestData.setEnabledAtStartup(subsystem.isSelfTestEnabledAtStartup(selfTestID));
+
+ try {
+ selfTestData.setCriticalAtStartup(subsystem.isSelfTestCriticalAtStartup(selfTestID));
+ } catch (EMissingSelfTestException e) {
+ // ignore
+ }
+
+ selfTestData.setEnabledOnDemand(subsystem.isSelfTestEnabledOnDemand(selfTestID));
+
+ try {
+ selfTestData.setCriticalOnDemand(subsystem.isSelfTestCriticalOnDemand(selfTestID));
+ } catch (EMissingSelfTestException e) {
+ // ignore
+ }
+
+ selfTestID = URLEncoder.encode(selfTestID, "UTF-8");
+ URI uri = uriInfo.getBaseUriBuilder().path(SelfTestResource.class).path("{selfTestID}").build(selfTestID);
+ selfTestData.setLink(new Link("self", uri));
+
+ return selfTestData;
+ }
+
+ @Override
+ public SelfTestCollection findSelfTests(Integer start, Integer size) {
+
+ CMS.debug("SelfTestService.findSelfTests()");
+
+ try {
+ SelfTestCollection response = new SelfTestCollection();
+
+ ISelfTestSubsystem subsystem = (ISelfTestSubsystem)CMS.getSubsystem(ISelfTestSubsystem.ID);
+ for (String name : subsystem.listSelfTestsEnabledOnDemand()) {
+ SelfTestData data = createSelfTestData(subsystem, name);
+ response.addEntry(data);
+ }
+
+ return response;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public SelfTestData getSelfTest(String selfTestID) {
+
+ CMS.debug("SelfTestService.getSelfTest(\"" + selfTestID + "\")");
+
+ try {
+ ISelfTestSubsystem subsystem = (ISelfTestSubsystem)CMS.getSubsystem(ISelfTestSubsystem.ID);
+ return createSelfTestData(subsystem, selfTestID);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public void executeSelfTests(String action) {
+
+ CMS.debug("SelfTestService.executeSelfTests(\"" + action + "\")");
+
+ if (!"run".equals(action)) {
+ throw new BadRequestException("Invalid action: " + action);
+ }
+
+ try {
+ ISelfTestSubsystem subsystem = (ISelfTestSubsystem)CMS.getSubsystem(ISelfTestSubsystem.ID);
+ subsystem.runSelfTestsOnDemand();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestSubsystem.java
new file mode 100644
index 000000000..c44476dd6
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/selftests/SelfTestSubsystem.java
@@ -0,0 +1,1884 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cmscore.selftests;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.ListIterator;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+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.certsrv.base.ISubsystem;
+import com.netscape.certsrv.logging.AuditEvent;
+import com.netscape.certsrv.logging.ELogException;
+import com.netscape.certsrv.logging.ILogEventListener;
+import com.netscape.certsrv.logging.ILogger;
+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.ISelfTest;
+import com.netscape.certsrv.selftests.ISelfTestSubsystem;
+
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * This class implements a container for self tests.
+ * <P>
+ *
+ * @author mharmsen
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class SelfTestSubsystem
+ implements ISelfTestSubsystem {
+ ////////////////////////
+ // default parameters //
+ ////////////////////////
+
+ ///////////////////////
+ // helper parameters //
+ ///////////////////////
+
+ //////////////////////////////////
+ // SelfTestSubsystem parameters //
+ //////////////////////////////////
+
+ @SuppressWarnings("unused")
+ private ISubsystem mOwner;
+ private IConfigStore mConfig = null;
+ private ILogEventListener mLogger = null;
+ private ILogger mErrorLogger = CMS.getLogger();
+ private ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+ private String mRootPrefix = null;
+ private String mPrefix = null;
+
+ public Hashtable<String, ISelfTest> mSelfTestInstances = new Hashtable<String, ISelfTest>();
+ public Vector<SelfTestOrderedInstance> mOnDemandOrder = new Vector<SelfTestOrderedInstance>();
+ public Vector<SelfTestOrderedInstance> mStartupOrder = new Vector<SelfTestOrderedInstance>();
+
+ ///////////////////////////
+ // ISubsystem parameters //
+ ///////////////////////////
+
+ private static final String LIST_DELIMITER = ",";
+
+ private static final String ELEMENT_DELIMITER = ":";
+ private static final String CRITICAL = "critical";
+
+ private static final String LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION =
+ "LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION_2";
+
+ /////////////////////
+ // default methods //
+ /////////////////////
+
+ ////////////////////
+ // helper methods //
+ ////////////////////
+
+ /**
+ * Signed Audit Log
+ *
+ * This helper method is called to store messages to the signed audit log.
+ * <P>
+ *
+ * @param msg signed audit log message
+ */
+ private void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+
+ if (mSignedAuditLogger == null) {
+ return;
+ }
+
+ mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+
+ /**
+ * This helper method returns the "full" property name (the corresponding
+ * substore name prepended in front of the plugin/parameter name). This
+ * method may return null.
+ * <P>
+ *
+ * @param instancePrefix full name of configuration store
+ * @param instanceName instance name of self test
+ * @return fullname of this self test plugin
+ */
+ private String getFullName(String instancePrefix,
+ String instanceName) {
+ String instanceFullName = null;
+
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instancePrefix != null) {
+ instancePrefix = instancePrefix.trim();
+ }
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ }
+
+ if ((instancePrefix != null) &&
+ (instancePrefix != "")) {
+ if ((instanceName != null) &&
+ (instanceName != "")) {
+ instanceFullName = instancePrefix
+ + "."
+ + instanceName;
+ }
+ } else {
+ instanceFullName = instanceName;
+ }
+
+ return instanceFullName;
+ }
+
+ /**
+ * This helper method checks to see if an instance name/value
+ * pair exists for the corresponding ordered list element.
+ * <P>
+ *
+ * @param element owner of this subsystem
+ * @param instanceName instance name of self test
+ * @exception EMissingSelfTestException subsystem has missing name/value
+ */
+ private void checkInstance(SelfTestOrderedInstance element)
+ throws EInvalidSelfTestException, EMissingSelfTestException {
+ String instanceFullName = null;
+ String instanceName = null;
+ String instanceValue = null;
+
+ String instancePath = PROP_CONTAINER + "." + PROP_INSTANCE;
+ IConfigStore instanceConfig = mConfig.getSubStore(instancePath);
+
+ instanceName = element.getSelfTestName();
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ instanceFullName = getFullName(mPrefix,
+ instanceName);
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ try {
+ // extract the self test plugin value(s)
+ instanceValue = instanceConfig.getString(instanceName);
+
+ if ((instanceValue == null) ||
+ (instanceValue.equals(""))) {
+ // self test plugin instance property name exists,
+ // but it contains no value(s)
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_MISSING_VALUES",
+ instanceFullName));
+
+ throw new EMissingSelfTestException(instanceFullName,
+ instanceValue);
+ } else {
+ instanceValue = instanceValue.trim();
+ }
+
+ } catch (EPropertyNotFound e) {
+ // self test plugin instance property name is not present
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_MISSING_NAME",
+ instanceFullName));
+
+ throw new EMissingSelfTestException(instanceFullName);
+ } catch (EBaseException e) {
+ // self test plugin instance EBaseException
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_THREW_EBASEEXCEPTION",
+ instanceFullName,
+ instanceValue));
+
+ throw new EInvalidSelfTestException(instanceFullName,
+ instanceValue);
+ }
+ }
+
+ ///////////////////////////////
+ // SelfTestSubsystem methods //
+ ///////////////////////////////
+
+ //
+ // methods associated with the list of on demand self tests
+ //
+
+ /**
+ * List the instance names of all the self tests enabled to run on demand
+ * (in execution order); may return null.
+ * <P>
+ *
+ * @return list of self test instance names run on demand
+ */
+ public String[] listSelfTestsEnabledOnDemand() {
+ String[] mList;
+
+ int numElements = mOnDemandOrder.size();
+
+ if (numElements != 0) {
+ mList = new String[numElements];
+ } else {
+ return null;
+ }
+
+ // loop through all self test plugin instances
+ // specified to be executed on demand
+ Enumeration<SelfTestOrderedInstance> instances = mOnDemandOrder.elements();
+
+ int i = 0;
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = instances.nextElement();
+
+ mList[i] = instance.getSelfTestName();
+ if (mList[i] != null) {
+ mList[i] = mList[i].trim();
+ }
+ i++;
+ }
+
+ return mList;
+ }
+
+ /**
+ * Enable the specified self test to be executed on demand.
+ * <P>
+ *
+ * @param instanceName instance name of self test
+ * @param isCritical isCritical is either a critical failure (true) or
+ * a non-critical failure (false)
+ * @exception EInvalidSelfTestException subsystem has invalid name/value
+ * @exception EMissingSelfTestException subsystem has missing name/value
+ */
+ public void enableSelfTestOnDemand(String instanceName,
+ boolean isCritical)
+ throws EInvalidSelfTestException, EMissingSelfTestException {
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ // loop through all self test plugin instances
+ // specified to be executed on demand
+ Enumeration<SelfTestOrderedInstance> instances = mOnDemandOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = instances.nextElement();
+
+ if (instanceName.equals(instance.getSelfTestName())) {
+ instance.setSelfTestCriticalMode(isCritical);
+ return;
+ }
+ }
+
+ // append a new element to the on-demand ordered list
+ String elementName = null;
+
+ if (isCritical) {
+ elementName = instanceName
+ + ELEMENT_DELIMITER
+ + CRITICAL;
+ } else {
+ elementName = instanceName;
+ }
+
+ SelfTestOrderedInstance element;
+
+ element = new SelfTestOrderedInstance(elementName);
+
+ // SANITY CHECK: find the corresponding instance property
+ // name for this self test plugin
+ checkInstance(element);
+
+ // store this self test plugin in on-demand order
+ mOnDemandOrder.add(element);
+ }
+
+ /**
+ * Disable the specified self test from being able to be executed on demand.
+ * <P>
+ *
+ * @param instanceName instance name of self test
+ * @exception EMissingSelfTestException subsystem has missing name
+ */
+ public void disableSelfTestOnDemand(String instanceName)
+ throws EMissingSelfTestException {
+ String instanceFullName = null;
+
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ instanceFullName = getFullName(mPrefix,
+ instanceName);
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ // loop through all self test plugin instances
+ // specified to be executed on demand
+ Enumeration<SelfTestOrderedInstance> instances = mOnDemandOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = instances.nextElement();
+
+ if (instanceName.equals(instance.getSelfTestName())) {
+ mOnDemandOrder.remove(instance);
+ return;
+ }
+ }
+
+ // self test plugin instance property name is not present
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_MISSING_NAME",
+ instanceFullName));
+
+ throw new EMissingSelfTestException(instanceFullName);
+ }
+
+ /**
+ * Determine if the specified self test is enabled to be executed on demand.
+ * <P>
+ *
+ * @param instanceName instance name of self test
+ * @return true if the specified self test is enabled on demand
+ * @exception EMissingSelfTestException subsystem has missing name
+ */
+ public boolean isSelfTestEnabledOnDemand(String instanceName)
+ throws EMissingSelfTestException {
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ // loop through all self test plugin instances
+ // specified to be executed on demand
+ Enumeration<SelfTestOrderedInstance> instances = mOnDemandOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = instances.nextElement();
+
+ if (instanceName.equals(instance.getSelfTestName())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Determine if failure of the specified self test is fatal when
+ * it is executed on demand.
+ * <P>
+ *
+ * @param instanceName instance name of self test
+ * @return true if failure of the specified self test is fatal when
+ * it is executed on demand
+ * @exception EMissingSelfTestException subsystem has missing name
+ */
+ public boolean isSelfTestCriticalOnDemand(String instanceName)
+ throws EMissingSelfTestException {
+ String instanceFullName = null;
+
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ instanceFullName = getFullName(mPrefix,
+ instanceName);
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ // loop through all self test plugin instances
+ // specified to be executed on demand
+ Enumeration<SelfTestOrderedInstance> instances = mOnDemandOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = instances.nextElement();
+
+ if (instanceName.equals(instance.getSelfTestName())) {
+ if (instance.isSelfTestCritical()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ // self test plugin instance property name is not present
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_MISSING_NAME",
+ instanceFullName));
+
+ throw new EMissingSelfTestException(instanceFullName);
+ }
+
+ /**
+ * Execute all self tests specified to be run on demand.
+ * <P>
+ *
+ * @exception EMissingSelfTestException subsystem has missing name
+ * @exception ESelfTestException self test exception
+ */
+ public void runSelfTestsOnDemand()
+ throws EMissingSelfTestException, ESelfTestException {
+ if (CMS.debugOn()) {
+ CMS.debug("SelfTestSubsystem::runSelfTestsOnDemand():"
+ + " ENTERING . . .");
+ }
+
+ // loop through all self test plugin instances
+ // specified to be executed on demand
+ Enumeration<SelfTestOrderedInstance> instances = mOnDemandOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = instances.nextElement();
+
+ String instanceFullName = null;
+ String instanceName = instance.getSelfTestName();
+
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ instanceFullName = getFullName(mPrefix,
+ instanceName);
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ if (mSelfTestInstances.containsKey(instanceName)) {
+ ISelfTest test = mSelfTestInstances.get(instanceName);
+
+ try {
+ if (CMS.debugOn()) {
+ CMS.debug("SelfTestSubsystem::runSelfTestsOnDemand():"
+ + " running \""
+ + test.getSelfTestName()
+ + "\"");
+ }
+
+ test.runSelfTest(mLogger);
+ } catch (ESelfTestException e) {
+ // Check to see if the self test was critical:
+ if (isSelfTestCriticalOnDemand(instanceName)) {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_RUN_ON_DEMAND_FAILED",
+ instanceFullName));
+
+ // shutdown the system gracefully
+ CMS.shutdown();
+
+ return;
+ }
+ }
+ } else {
+ // self test plugin instance property name is not present
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_MISSING_NAME",
+ instanceFullName));
+
+ throw new EMissingSelfTestException(instanceFullName);
+ }
+ }
+
+ if (CMS.debugOn()) {
+ CMS.debug("SelfTestSubsystem::runSelfTestsOnDemand():"
+ + " EXITING.");
+ }
+ }
+
+ //
+ // methods associated with the list of startup self tests
+ //
+
+ /**
+ * List the instance names of all the self tests enabled to run
+ * at server startup (in execution order); may return null.
+ * <P>
+ *
+ * @return list of self test instance names run at server startup
+ */
+ public String[] listSelfTestsEnabledAtStartup() {
+ String[] mList;
+
+ int numElements = mStartupOrder.size();
+
+ if (numElements != 0) {
+ mList = new String[numElements];
+ } else {
+ return null;
+ }
+
+ // loop through all self test plugin instances
+ // specified to be executed at server startup
+ Enumeration<SelfTestOrderedInstance> instances = mStartupOrder.elements();
+
+ int i = 0;
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = instances.nextElement();
+
+ mList[i] = instance.getSelfTestName();
+ if (mList[i] != null) {
+ mList[i] = mList[i].trim();
+ }
+ i++;
+ }
+
+ return mList;
+ }
+
+ /**
+ * Enable the specified self test at server startup.
+ * <P>
+ *
+ * @param instanceName instance name of self test
+ * @param isCritical isCritical is either a critical failure (true) or
+ * a non-critical failure (false)
+ * @exception EInvalidSelfTestException subsystem has invalid name/value
+ * @exception EMissingSelfTestException subsystem has missing name/value
+ */
+ public void enableSelfTestAtStartup(String instanceName,
+ boolean isCritical)
+ throws EInvalidSelfTestException, EMissingSelfTestException {
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ // loop through all self test plugin instances
+ // specified to be executed at server startup
+ Enumeration<SelfTestOrderedInstance> instances = mStartupOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = instances.nextElement();
+
+ if (instanceName.equals(instance.getSelfTestName())) {
+ instance.setSelfTestCriticalMode(isCritical);
+ return;
+ }
+ }
+
+ // append a new element to the startup ordered list
+ String elementName = null;
+
+ if (isCritical) {
+ elementName = instanceName
+ + ELEMENT_DELIMITER
+ + CRITICAL;
+ } else {
+ elementName = instanceName;
+ }
+
+ SelfTestOrderedInstance element;
+
+ element = new SelfTestOrderedInstance(elementName);
+
+ // SANITY CHECK: find the corresponding instance property
+ // name for this self test plugin
+ checkInstance(element);
+
+ // store this self test plugin in startup order
+ mStartupOrder.add(element);
+ }
+
+ /**
+ * Disable the specified self test at server startup.
+ * <P>
+ *
+ * @param instanceName instance name of self test
+ * @exception EMissingSelfTestException subsystem has missing name
+ */
+ public void disableSelfTestAtStartup(String instanceName)
+ throws EMissingSelfTestException {
+ String instanceFullName = null;
+
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ instanceFullName = getFullName(mPrefix,
+ instanceName);
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ // loop through all self test plugin instances
+ // specified to be executed at server startup
+ Enumeration<SelfTestOrderedInstance> instances = mStartupOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = instances.nextElement();
+
+ if (instanceName.equals(instance.getSelfTestName())) {
+ mStartupOrder.remove(instance);
+ return;
+ }
+ }
+
+ // self test plugin instance property name is not present
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_MISSING_NAME",
+ instanceFullName));
+
+ throw new EMissingSelfTestException(instanceFullName);
+ }
+
+ /**
+ * Determine if the specified self test is executed automatically
+ * at server startup.
+ * <P>
+ *
+ * @param instanceName instance name of self test
+ * @return true if the specified self test is executed at server startup
+ * @exception EMissingSelfTestException subsystem has missing name
+ */
+ public boolean isSelfTestEnabledAtStartup(String instanceName)
+ throws EMissingSelfTestException {
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ // loop through all self test plugin instances
+ // specified to be executed at server startup
+ Enumeration<SelfTestOrderedInstance> instances = mStartupOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = instances.nextElement();
+
+ if (instanceName.equals(instance.getSelfTestName())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Determine if failure of the specified self test is fatal to
+ * server startup.
+ * <P>
+ *
+ * @param instanceName instance name of self test
+ * @return true if failure of the specified self test is fatal to
+ * server startup
+ * @exception EMissingSelfTestException subsystem has missing name
+ */
+ public boolean isSelfTestCriticalAtStartup(String instanceName)
+ throws EMissingSelfTestException {
+ String instanceFullName = null;
+
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ instanceFullName = getFullName(mPrefix,
+ instanceName);
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ // loop through all self test plugin instances
+ // specified to be executed at server startup
+ Enumeration<SelfTestOrderedInstance> instances = mStartupOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = instances.nextElement();
+
+ if (instanceName.equals(instance.getSelfTestName())) {
+ if (instance.isSelfTestCritical()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ // self test plugin instance property name is not present
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_MISSING_NAME",
+ instanceFullName));
+
+ throw new EMissingSelfTestException(instanceFullName);
+ }
+
+ /**
+ * Execute all self tests specified to be run at server startup.
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION used when self tests are run at server startup
+ * </ul>
+ *
+ * @exception EMissingSelfTestException subsystem has missing name
+ * @exception ESelfTestException self test exception
+ */
+ public void runSelfTestsAtStartup()
+ throws EMissingSelfTestException, ESelfTestException {
+ String auditMessage = null;
+
+ // ensure that any low-level exceptions are reported
+ // to the signed audit log and stored as failures
+ try {
+ if (CMS.debugOn()) {
+ CMS.debug("SelfTestSubsystem::runSelfTestsAtStartup():"
+ + " ENTERING . . .");
+ }
+
+ // loop through all self test plugin instances
+ // specified to be executed at server startup
+ Enumeration<SelfTestOrderedInstance> instances = mStartupOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = instances.nextElement();
+
+ String instanceFullName = null;
+ String instanceName = instance.getSelfTestName();
+
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ instanceFullName = getFullName(mPrefix,
+ instanceName);
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ throw new EMissingSelfTestException();
+ }
+
+ if (mSelfTestInstances.containsKey(instanceName)) {
+ ISelfTest test = mSelfTestInstances.get(instanceName);
+
+ try {
+ if (CMS.debugOn()) {
+ CMS.debug("SelfTestSubsystem::runSelfTestsAtStartup():"
+ + " running \""
+ + test.getSelfTestName()
+ + "\"");
+ }
+
+ test.runSelfTest(mLogger);
+ } catch (ESelfTestException e) {
+ // Check to see if the self test was critical:
+ if (isSelfTestCriticalAtStartup(instanceName)) {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_RUN_AT_STARTUP_FAILED",
+ instanceFullName));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ // shutdown the system gracefully
+ CMS.shutdown();
+
+ return;
+ }
+ }
+ } else {
+ // self test plugin instance property name is not present
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_MISSING_NAME",
+ instanceFullName));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ throw new EMissingSelfTestException(instanceFullName);
+ }
+ }
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION,
+ ILogger.SYSTEM_UID,
+ ILogger.SUCCESS);
+
+ audit(auditMessage);
+
+ if (CMS.debugOn()) {
+ CMS.debug("SelfTestSubsystem::runSelfTestsAtStartup():"
+ + " EXITING.");
+ }
+ } catch (EMissingSelfTestException eAudit1) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION,
+ ILogger.SYSTEM_UID,
+ ILogger.FAILURE);
+
+ audit(auditMessage);
+
+ // rethrow the specific exception to be handled later
+ throw eAudit1;
+ }
+ }
+
+ public void log(int level, String msg) {
+ }
+
+ //
+ // methods associated with the list of self test instances
+ //
+
+ /**
+ * Retrieve an individual self test from the instances list
+ * given its instance name. This method may return null.
+ * <P>
+ *
+ * @param instanceName instance name of self test
+ * @return individual self test
+ */
+ public ISelfTest getSelfTest(String instanceName) {
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ } else {
+ return null;
+ }
+
+ // loop through all self test plugin instances
+ Enumeration<ISelfTest> instances = mSelfTestInstances.elements();
+
+ while (instances.hasMoreElements()) {
+ ISelfTest instance = instances.nextElement();
+
+ if (instanceName.equals(instance.getSelfTestName())) {
+ return instance;
+ }
+ }
+
+ return null;
+ }
+
+ //
+ // methods associated with multiple self test lists
+ //
+
+ /**
+ * Returns the ILogEventListener of this subsystem.
+ * This method may return null.
+ * <P>
+ *
+ * @return ILogEventListener of this subsystem
+ */
+ public ILogEventListener getSelfTestLogger() {
+ return mLogger;
+ }
+
+ /**
+ * This method represents the log interface for the self test subsystem.
+ * <P>
+ *
+ * @param logger log event listener
+ * @param msg self test log message
+ */
+ public void log(ILogEventListener logger, String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+
+ if (logger != null) {
+ // log the message to the "selftests.log" log
+ AuditEvent ev = new AuditEvent(msg);
+
+ ev.setSource(ILogger.S_OTHER);
+ ev.setLevel(ILogger.LL_INFO);
+ try {
+ logger.log(ev);
+ } catch (ELogException le) {
+ // log the message to the "transactions" log
+ mErrorLogger.log(ILogger.EV_AUDIT,
+ null,
+ ILogger.S_OTHER,
+ ILogger.LL_INFO,
+ msg + " - " + le.toString());
+ }
+ } else {
+ // log the message to the "transactions" log
+ mErrorLogger.log(ILogger.EV_AUDIT,
+ null,
+ ILogger.S_OTHER,
+ ILogger.LL_INFO,
+ msg);
+ }
+ }
+
+ /**
+ * Register an individual self test on the instances list AND
+ * on the "on demand" list (note that the specified self test
+ * will be appended to the end of each list).
+ * <P>
+ *
+ * @param instanceName instance name of self test
+ * @param isCritical isCritical is either a critical failure (true) or
+ * a non-critical failure (false)
+ * @param instance individual self test
+ * @exception EDuplicateSelfTestException subsystem has duplicate name
+ * @exception EInvalidSelfTestException subsystem has invalid name/value
+ * @exception EMissingSelfTestException subsystem has missing name/value
+ */
+ public void registerSelfTestOnDemand(String instanceName,
+ boolean isCritical,
+ ISelfTest instance)
+ throws EDuplicateSelfTestException,
+ EInvalidSelfTestException,
+ EMissingSelfTestException {
+ String instanceFullName = null;
+
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ instanceFullName = getFullName(mPrefix,
+ instanceName);
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ if (mSelfTestInstances.containsKey(instanceName)) {
+ // self test plugin instance property name is a duplicate
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_DUPLICATE_NAME",
+ instanceFullName));
+
+ throw new EDuplicateSelfTestException(instanceFullName);
+ } else {
+ // append this self test plugin instance to the end of the list
+ mSelfTestInstances.put(instanceName, instance);
+ }
+
+ // register the individual self test on the "on demand" list
+ enableSelfTestOnDemand(instanceName, isCritical);
+ }
+
+ /**
+ * Deregister an individual self test on the instances list AND
+ * on the "on demand" list (note that the specified self test
+ * will be removed from each list).
+ * <P>
+ *
+ * @param instanceName instance name of self test
+ * @exception EMissingSelfTestException subsystem has missing name
+ */
+ public void deregisterSelfTestOnDemand(String instanceName)
+ throws EMissingSelfTestException {
+ String instanceFullName = null;
+
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ instanceFullName = getFullName(mPrefix,
+ instanceName);
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ // deregister the individual self test from the instances list
+ ISelfTest test = getSelfTest(instanceName);
+
+ if (test == null) {
+ // self test plugin instance property name is not present
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_MISSING_NAME",
+ instanceFullName));
+
+ throw new EMissingSelfTestException(instanceFullName);
+ } else {
+ // append this self test plugin instance to the end of the list
+ mSelfTestInstances.remove(instanceName);
+ }
+
+ // deregister the individual self test from the "on demand" list
+ disableSelfTestOnDemand(instanceName);
+ }
+
+ /**
+ * Register an individual self test on the instances list AND
+ * on the "startup" list (note that the specified self test
+ * will be appended to the end of each list).
+ * <P>
+ *
+ * @param instanceName instance name of self test
+ * @param isCritical isCritical is either a critical failure (true) or
+ * a non-critical failure (false)
+ * @param instance individual self test
+ * @exception EDuplicateSelfTestException subsystem has duplicate name
+ * @exception EInvalidSelfTestException subsystem has invalid name/value
+ * @exception EMissingSelfTestException subsystem has missing name/value
+ */
+ public void registerSelfTestAtStartup(String instanceName,
+ boolean isCritical,
+ ISelfTest instance)
+ throws EDuplicateSelfTestException,
+ EInvalidSelfTestException,
+ EMissingSelfTestException {
+ String instanceFullName = null;
+
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ instanceFullName = getFullName(mPrefix,
+ instanceName);
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ if (mSelfTestInstances.containsKey(instanceName)) {
+ // self test plugin instance property name is a duplicate
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_DUPLICATE_NAME",
+ instanceFullName));
+
+ throw new EDuplicateSelfTestException(instanceFullName);
+ } else {
+ // append this self test plugin instance to the end of the list
+ mSelfTestInstances.put(instanceName, instance);
+ }
+
+ // register the individual self test on the "startup" list
+ enableSelfTestAtStartup(instanceName, isCritical);
+ }
+
+ /**
+ * Deregister an individual self test on the instances list AND
+ * on the "startup" list (note that the specified self test
+ * will be removed from each list).
+ * <P>
+ *
+ * @param instanceName instance name of self test
+ * @exception EMissingSelfTestException subsystem has missing name
+ */
+ public void deregisterSelfTestAtStartup(String instanceName)
+ throws EMissingSelfTestException {
+ String instanceFullName = null;
+
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ instanceFullName = getFullName(mPrefix,
+ instanceName);
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ // deregister the individual self test from the instances list
+ ISelfTest test = getSelfTest(instanceName);
+
+ if (test == null) {
+ // self test plugin instance property name is not present
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_MISSING_NAME",
+ instanceFullName));
+
+ throw new EMissingSelfTestException(instanceFullName);
+ } else {
+ // append this self test plugin instance to the end of the list
+ mSelfTestInstances.remove(instanceName);
+ }
+
+ // deregister the individual self test from the "startup" list
+ disableSelfTestAtStartup(instanceName);
+ }
+
+ ////////////////////////
+ // ISubsystem methods //
+ ////////////////////////
+
+ /**
+ * This method retrieves the name of this subsystem. This method
+ * may return null.
+ * <P>
+ *
+ * @return identification of this subsystem
+ */
+ public String getId() {
+ return ID;
+ }
+
+ /**
+ * This method sets information specific to this subsystem.
+ * <P>
+ *
+ * @param id identification of this subsystem
+ * @exception EBaseException base CMS exception
+ */
+ public void setId(String id)
+ throws EBaseException {
+
+ if (id == null) {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EBaseException("id is null");
+ }
+
+ // nothing needs to be done
+ }
+
+ /**
+ * This method initializes this subsystem.
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration store
+ * @exception EBaseException base CMS exception
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ if (CMS.debugOn()) {
+ CMS.debug("SelfTestSubsystem::init():"
+ + " ENTERING . . .");
+ }
+
+ if (config == null) {
+ CMS.debug("SelfTestSubsystem::init() - config is null!");
+ throw new EBaseException("config is null");
+ }
+
+ mOwner = owner;
+ mConfig = config;
+
+ if ((mConfig != null) &&
+ (mConfig.getName() != null) &&
+ (mConfig.getName() != "")) {
+ mRootPrefix = mConfig.getName().trim();
+ }
+
+ int loadStatus = 0;
+
+ // NOTE: Obviously, we must load the self test logger parameters
+ // first, since the "selftests.log" log file does not
+ // exist until this is accomplished!!!
+
+ ////////////////////////////////////
+ // loggerPropertyName=loggerValue //
+ ////////////////////////////////////
+
+ if (CMS.debugOn()) {
+ CMS.debug("SelfTestSubsystem::init():"
+ + " loading self test logger parameters");
+ }
+
+ String loggerPrefix = null;
+ String loggerFullName = null;
+ String loggerName = PROP_LOGGER_CLASS;
+ String loggerValue = null;
+
+ // compose self test plugins logger property prefix
+ String loggerPath = PROP_CONTAINER + "." + PROP_LOGGER;
+ IConfigStore loggerConfig = mConfig.getSubStore(loggerPath);
+
+ if ((loggerConfig != null) &&
+ (loggerConfig.getName() != null) &&
+ (loggerConfig.getName() != "")) {
+ loggerPrefix = loggerConfig.getName().trim();
+ } else {
+ // NOTE: These messages can only be logged to the "transactions"
+ // log, since the "selftests.log" will not exist!
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_INITIALIZATION_NOTIFICATION"));
+
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ Enumeration<String> loggerInstances = loggerConfig.getPropertyNames();
+
+ if (loggerInstances.hasMoreElements()) {
+ loadStatus++;
+
+ try {
+ loggerFullName = getFullName(loggerPrefix,
+ loggerName);
+
+ // retrieve the associated logger class
+ loggerValue = loggerConfig.getString(loggerName);
+ if (loggerValue != null) {
+ loggerValue = loggerValue.trim();
+ } else {
+ // self test plugin instance property name exists,
+ // but it contains no value(s)
+
+ // NOTE: This message can only be logged to the
+ // "transactions" log, since the "selftests.log"
+ // will not exist!
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_MISSING_VALUES",
+ loggerFullName));
+
+ throw new EMissingSelfTestException(loggerFullName,
+ loggerValue);
+ }
+
+ Object o = Class.forName(loggerValue).newInstance();
+
+ if (!(o instanceof ILogEventListener)) {
+ // NOTE: These messages can only be logged to the
+ // "transactions" log, since the "selftests.log"
+ // will not exist!
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_INITIALIZATION_NOTIFICATION"));
+
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_INVALID_INSTANCE",
+ loggerFullName,
+ loggerValue));
+
+ throw new EInvalidSelfTestException(loggerFullName,
+ loggerValue);
+ }
+
+ // initialize the self tests logger
+ mLogger = (ILogEventListener) o;
+ mLogger.init(this, loggerConfig);
+ } catch (EBaseException e) {
+ // self test property name EBaseException
+
+ // NOTE: These messages can only be logged to the
+ // "transactions" log, since the "selftests.log"
+ // will not exist!
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_INITIALIZATION_NOTIFICATION"));
+
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_THREW_EBASEEXCEPTION",
+ loggerFullName,
+ loggerValue));
+
+ throw new EInvalidSelfTestException(loggerFullName,
+ loggerValue);
+ } catch (Exception e) {
+ // NOTE: These messages can only be logged to the
+ // "transactions" log, since the "selftests.log"
+ // will not exist!
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_INITIALIZATION_NOTIFICATION"));
+
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_THREW_EXCEPTION",
+ loggerFullName,
+ loggerValue));
+
+ CMS.debugStackTrace();
+
+ throw new EInvalidSelfTestException(loggerFullName,
+ loggerValue);
+ }
+ }
+
+ // Barring any exceptions thrown above, we begin logging messages
+ // to either the "transactions" log, or the "selftests.log" log.
+ if (loadStatus == 0) {
+ // NOTE: These messages can only be logged to the
+ // "transactions" log, since the "selftests.log"
+ // will not exist!
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_INITIALIZATION_NOTIFICATION"));
+
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_DONT_LOAD_LOGGER_PARAMETERS"));
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_INITIALIZATION_NOTIFICATION"));
+
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_LOAD_LOGGER_PARAMETERS"));
+ }
+
+ ////////////////////////////////////////
+ // instancePropertyName=instanceValue //
+ ////////////////////////////////////////
+
+ if (CMS.debugOn()) {
+ CMS.debug("SelfTestSubsystem::init():"
+ + " loading self test plugins");
+ }
+
+ // compose self test plugins instance property prefix
+ String instancePath = PROP_CONTAINER + "." + PROP_INSTANCE;
+ IConfigStore instanceConfig = mConfig.getSubStore(instancePath);
+
+ if ((instanceConfig != null) &&
+ (instanceConfig.getName() != null) &&
+ (instanceConfig.getName() != "")) {
+ mPrefix = instanceConfig.getName().trim();
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ Enumeration<String> instances = instanceConfig.getPropertyNames();
+
+ if (instances.hasMoreElements()) {
+ loadStatus++;
+
+ log(mLogger,
+ CMS.getLogMessage("CMSCORE_SELFTESTS_LOAD_PLUGINS"));
+ } else {
+ log(mLogger,
+ CMS.getLogMessage("CMSCORE_SELFTESTS_DONT_LOAD_PLUGINS"));
+ }
+
+ // load all self test plugin instances
+ String instanceFullName = null;
+ String instanceName = null;
+ String instanceValue = null;
+ boolean first_time = true;
+
+ while (instances.hasMoreElements()) {
+ // the instance property name should be unique
+ instanceName = instances.nextElement();
+ if (instanceName != null) {
+ instanceName = instanceName.trim();
+ instanceFullName = getFullName(mPrefix,
+ instanceName);
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_NAME_IS_NULL"));
+
+ throw new EMissingSelfTestException();
+ }
+
+ if (mSelfTestInstances.containsKey(instanceName)) {
+ // self test plugin instance property name is a duplicate
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_DUPLICATE_NAME",
+ instanceFullName));
+
+ throw new EDuplicateSelfTestException(instanceFullName);
+ }
+
+ // an associated instance property value, a class, must exist
+ try {
+ instanceValue = instanceConfig.getString(instanceName);
+ if (instanceValue != null) {
+ instanceValue = instanceValue.trim();
+ } else {
+ // self test plugin instance property name exists,
+ // but it contains no value(s)
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_MISSING_VALUES",
+ instanceFullName));
+
+ throw new EMissingSelfTestException(instanceFullName,
+ instanceValue);
+ }
+ } catch (EBaseException e) {
+ // self test property name EBaseException
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_THREW_EBASEEXCEPTION",
+ instanceFullName,
+ instanceValue));
+
+ throw new EInvalidSelfTestException(instanceFullName,
+ instanceValue);
+ }
+
+ // verify that the associated class is a valid instance of ISelfTest
+ Object o;
+
+ try {
+ o = Class.forName(instanceValue).newInstance();
+
+ if (!(o instanceof ISelfTest)) {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_INVALID_INSTANCE",
+ instanceFullName,
+ instanceValue));
+
+ throw new EInvalidSelfTestException(instanceFullName,
+ instanceValue);
+ }
+ } catch (Exception e) {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_THREW_EXCEPTION",
+ instanceFullName,
+ instanceValue));
+
+ CMS.debugStackTrace();
+
+ throw new EInvalidSelfTestException(instanceFullName,
+ instanceValue);
+ }
+
+ // retrieve all ISelfTest parameters associated with this class
+ try {
+ if (first_time) {
+ first_time = false;
+
+ if (CMS.debugOn()) {
+ CMS.debug("SelfTestSubsystem::init():"
+ + " loading self test plugin parameters");
+ }
+
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_LOAD_PLUGIN_PARAMETERS"));
+ }
+
+ ISelfTest test = (ISelfTest) o;
+
+ test.initSelfTest(this, instanceName, mConfig);
+
+ // store this self test plugin instance
+ mSelfTestInstances.put(instanceName, test);
+ } catch (EDuplicateSelfTestException e) {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PLUGIN_DUPLICATE_PARAMETER",
+ instanceFullName,
+ e.getInstanceParameter()));
+
+ throw e;
+ } catch (EMissingSelfTestException e) {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PLUGIN_MISSING_PARAMETER",
+ instanceFullName,
+ e.getInstanceParameter()));
+
+ throw e;
+ } catch (EInvalidSelfTestException e) {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PLUGIN_INVALID_PARAMETER",
+ instanceFullName,
+ e.getInstanceParameter()));
+
+ throw e;
+ }
+ }
+
+ //////////////////////////////////////////////////////////
+ // onDemandOrderPropertyName=onDemandOrderValue1, . . . //
+ //////////////////////////////////////////////////////////
+
+ if (CMS.debugOn()) {
+ CMS.debug("SelfTestSubsystem::init():"
+ + " loading on demand self tests");
+ }
+
+ // compose self test plugins on-demand ordering property name
+ String onDemandOrderName = PROP_CONTAINER + "."
+ + PROP_ORDER + "."
+ + PROP_ON_DEMAND;
+ String onDemandOrderFullName = getFullName(mRootPrefix,
+ onDemandOrderName);
+ String onDemandOrderValues = null;
+
+ try {
+ // extract all self test plugins on-demand
+ // ordering property values
+ onDemandOrderValues = mConfig.getString(onDemandOrderName);
+ if (onDemandOrderValues != null) {
+ onDemandOrderValues = onDemandOrderValues.trim();
+ }
+
+ loadStatus++;
+
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_LOAD_PLUGINS_ON_DEMAND"));
+
+ if ((onDemandOrderValues == null) ||
+ (onDemandOrderValues.equals(""))) {
+ // self test plugins on-demand ordering property name
+ // exists, but it contains no values, which means that
+ // no self tests are configured to run on-demand
+ if ((onDemandOrderFullName != null) &&
+ (!onDemandOrderFullName.equals(""))) {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_MISSING_ON_DEMAND_VALUES",
+ onDemandOrderFullName));
+ }
+ throw new EBaseException("onDemandOrderValues is null "
+ + "or empty");
+ }
+
+ StringTokenizer tokens = new StringTokenizer(onDemandOrderValues,
+ LIST_DELIMITER);
+
+ while (tokens.hasMoreTokens()) {
+ // create a new element in the on-demand ordered list
+ SelfTestOrderedInstance element;
+
+ element = new SelfTestOrderedInstance(
+ tokens.nextToken().trim());
+
+ // SANITY CHECK: find the corresponding instance property
+ // name for this self test plugin
+ checkInstance(element);
+
+ // store this self test plugin in on-demand order
+ mOnDemandOrder.add(element);
+ }
+
+ } catch (EPropertyNotFound e) {
+ // self test plugins on-demand ordering property name
+ // is not present
+
+ // presently, we merely log this fact
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_DONT_LOAD_PLUGINS_ON_DEMAND"));
+
+ // throw new EMissingSelfTestException( onDemandOrderFullName );
+ } catch (EBaseException e) {
+ // self test property name EBaseException
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_THREW_EBASEEXCEPTION",
+ onDemandOrderFullName,
+ onDemandOrderValues));
+
+ throw new EInvalidSelfTestException(onDemandOrderFullName,
+ onDemandOrderValues);
+ }
+
+ ////////////////////////////////////////////////////////
+ // startupOrderPropertyName=startupOrderValue1, . . . //
+ ////////////////////////////////////////////////////////
+
+ if (CMS.debugOn()) {
+ CMS.debug("SelfTestSubsystem::init():"
+ + " loading startup self tests");
+ }
+
+ // compose self test plugins startup ordering property name
+ String startupOrderName = PROP_CONTAINER + "."
+ + PROP_ORDER + "."
+ + PROP_STARTUP;
+ String startupOrderFullName = getFullName(mRootPrefix,
+ startupOrderName);
+ String startupOrderValues = null;
+
+ try {
+ // extract all self test plugins startup ordering
+ // property values
+ startupOrderValues = mConfig.getString(startupOrderName);
+ if (startupOrderValues != null) {
+ startupOrderValues = startupOrderValues.trim();
+ }
+
+ loadStatus++;
+
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_LOAD_PLUGINS_AT_STARTUP"));
+
+ if ((startupOrderValues == null) ||
+ (startupOrderValues.equals(""))) {
+ // self test plugins startup ordering property name
+ // exists, but it contains no values, which means that
+ // no self tests are configured to run at server startup
+ if ((startupOrderFullName != null) &&
+ (!startupOrderFullName.equals(""))) {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_MISSING_STARTUP_VALUES",
+ startupOrderFullName));
+ }
+ }
+
+ StringTokenizer tokens = new StringTokenizer(startupOrderValues,
+ LIST_DELIMITER);
+
+ while (tokens.hasMoreTokens()) {
+ // create a new element in the startup ordered list
+ SelfTestOrderedInstance element;
+
+ element = new SelfTestOrderedInstance(
+ tokens.nextToken().trim());
+
+ // SANITY CHECK: find the corresponding instance property
+ // name for this self test plugin
+ checkInstance(element);
+
+ // store this self test plugin in startup order
+ mStartupOrder.add(element);
+ }
+
+ } catch (EPropertyNotFound e) {
+ // self test plugins startup ordering property name is
+ // not present
+
+ // presently, we merely log this fact
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_DONT_LOAD_PLUGINS_AT_STARTUP"));
+
+ // throw new EMissingSelfTestException( startupOrderFullName );
+ } catch (EBaseException e) {
+ // self test property name EBaseException
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PROPERTY_THREW_EBASEEXCEPTION",
+ startupOrderFullName,
+ startupOrderValues));
+
+ throw new EInvalidSelfTestException(startupOrderFullName,
+ startupOrderValues);
+ }
+
+ // notify user whether or not self test plugins have been loaded
+ if (loadStatus == 0) {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PLUGINS_NONE_LOADED"));
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_PLUGINS_LOADED"));
+ }
+
+ if (CMS.debugOn()) {
+ CMS.debug("SelfTestSubsystem::init():"
+ + " EXITING.");
+ }
+ }
+
+ /**
+ * Notifies this subsystem if owner is in running mode.
+ * <P>
+ *
+ * @exception EBaseException base CMS exception
+ */
+ public void startup()
+ throws EBaseException {
+ // loop through all self test plugin instances
+ Enumeration<ISelfTest> instances = mSelfTestInstances.elements();
+
+ while (instances.hasMoreElements()) {
+ ISelfTest instance = instances.nextElement();
+
+ instance.startupSelfTest();
+ }
+
+ if (!CMS.isPreOpMode()) {
+ // run all self test plugin instances (designated at startup)
+ Enumeration<SelfTestOrderedInstance> selftests = mStartupOrder.elements();
+
+ if (selftests.hasMoreElements()) {
+ // log that execution of startup self tests has begun
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_RUN_AT_STARTUP"));
+
+ // execute all startup self tests
+ runSelfTestsAtStartup();
+
+ // log that execution of all "critical" startup self tests
+ // has completed "successfully"
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_RUN_AT_STARTUP_SUCCEEDED"));
+ } else {
+ log(mLogger,
+ CMS.getLogMessage(
+ "CMSCORE_SELFTESTS_NOT_RUN_AT_STARTUP"));
+ }
+ }
+ }
+
+ /**
+ * Stops this subsystem. The owner may call shutdown
+ * anytime after initialization.
+ * <P>
+ */
+ public void shutdown() {
+ // reverse order of all self test plugin instances
+ Collection<ISelfTest> collection = mSelfTestInstances.values();
+ Vector<ISelfTest> list = new Vector<ISelfTest>(collection);
+
+ Collections.reverse(list);
+
+ // loop through all self test plugin instances
+ ListIterator<ISelfTest> instances = list.listIterator();
+
+ while (instances.hasNext()) {
+ ISelfTest instance = instances.next();
+
+ instance.shutdownSelfTest();
+ }
+ }
+
+ /**
+ * Returns the root configuration storage of this subsystem.
+ * This method may return null.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/session/LDAPSecurityDomainSessionTable.java b/base/server/cmscore/src/com/netscape/cmscore/session/LDAPSecurityDomainSessionTable.java
new file mode 100644
index 000000000..064ae7ecb
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/session/LDAPSecurityDomainSessionTable.java
@@ -0,0 +1,303 @@
+// --- 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) 2010 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.session;
+
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISecurityDomainSessionTable;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.ldap.ILdapConnFactory;
+
+/**
+ * This object stores the values for IP, uid and group based on the cookie id in LDAP.
+ * Entries are stored under ou=Security Domain, ou=sessions, $basedn
+ */
+public class LDAPSecurityDomainSessionTable
+ implements ISecurityDomainSessionTable {
+
+ private long m_timeToLive;
+ private ILdapConnFactory mLdapConnFactory = null;
+
+ public LDAPSecurityDomainSessionTable(long timeToLive) throws ELdapException, EBaseException {
+ m_timeToLive = timeToLive;
+ IConfigStore cs = CMS.getConfigStore();
+ IConfigStore internaldb = cs.getSubStore("internaldb");
+ mLdapConnFactory = CMS.getLdapBoundConnFactory();
+ mLdapConnFactory.init(internaldb);
+ }
+
+ public int addEntry(String sessionId, String ip,
+ String uid, String group) {
+ IConfigStore cs = CMS.getConfigStore();
+ LDAPConnection conn = null;
+ boolean sessions_exists = true;
+ int status = FAILURE;
+
+ String basedn = null;
+ String sessionsdn = null;
+ try {
+ basedn = cs.getString("internaldb.basedn");
+ sessionsdn = "ou=sessions,ou=Security Domain," + basedn;
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainSessionTable: addEntry: failed to read basedn" + e);
+ return status;
+ }
+
+ try {
+ // create session entry (if it does not exist)
+ conn = mLdapConnFactory.getConn();
+
+ LDAPEntry entry = null;
+ LDAPAttributeSet attrs = null;
+ attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass", "top"));
+ attrs.add(new LDAPAttribute("objectclass", "organizationalUnit"));
+ attrs.add(new LDAPAttribute("ou", "sessions"));
+ entry = new LDAPEntry(sessionsdn, attrs);
+ conn.add(entry);
+ } catch (Exception e) {
+ if ((e instanceof LDAPException)
+ && (((LDAPException) e).getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS)) {
+ // continue
+ } else {
+ CMS.debug("SecurityDomainSessionTable: unable to create ou=sessions:" + e);
+ sessions_exists = false;
+ }
+ }
+
+ // add new entry
+ try {
+ LDAPEntry entry = null;
+ LDAPAttributeSet attrs = null;
+ String entrydn = "cn=" + sessionId + "," + sessionsdn;
+ attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass", "top"));
+ attrs.add(new LDAPAttribute("objectclass", "securityDomainSessionEntry"));
+ attrs.add(new LDAPAttribute("cn", sessionId));
+ attrs.add(new LDAPAttribute("host", ip));
+ attrs.add(new LDAPAttribute("uid", uid));
+ attrs.add(new LDAPAttribute("cmsUserGroup", group));
+ attrs.add(new LDAPAttribute("dateOfCreate", Long.toString((new Date()).getTime())));
+
+ entry = new LDAPEntry(entrydn, attrs);
+ if (sessions_exists) {
+ conn.add(entry);
+ CMS.debug("SecurityDomainSessionTable: added session entry" + sessionId);
+ status = SUCCESS;
+ }
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainSessionTable: unable to create session entry" + sessionId + ": " + e);
+ }
+
+ try {
+ mLdapConnFactory.returnConn(conn);
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainSessionTable:addEntry: Error in disconnecting from database: " + e);
+ }
+ return status;
+ }
+
+ public int removeEntry(String sessionId) {
+ IConfigStore cs = CMS.getConfigStore();
+ LDAPConnection conn = null;
+ int status = FAILURE;
+ try {
+ String basedn = cs.getString("internaldb.basedn");
+ String dn = "cn=" + sessionId + ",ou=sessions,ou=Security Domain," + basedn;
+ conn = mLdapConnFactory.getConn();
+ conn.delete(dn);
+ status = SUCCESS;
+ } catch (Exception e) {
+ if ((e instanceof LDAPException)
+ && (((LDAPException) e).getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT)) {
+ // continue
+ } else {
+ CMS.debug("SecurityDomainSessionTable: unable to delete session " + sessionId + ": " + e);
+ }
+ }
+ try {
+ mLdapConnFactory.returnConn(conn);
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainSessionTable: removeEntry: Error in disconnecting from database: " + e);
+ }
+ return status;
+ }
+
+ public boolean isSessionIdExist(String sessionId) {
+ IConfigStore cs = CMS.getConfigStore();
+ LDAPConnection conn = null;
+ boolean ret = false;
+ try {
+ String basedn = cs.getString("internaldb.basedn");
+ String sessionsdn = "ou=sessions,ou=Security Domain," + basedn;
+ String filter = "(cn=" + sessionId + ")";
+ String[] attrs = { "cn" };
+
+ conn = mLdapConnFactory.getConn();
+ LDAPSearchResults res = conn.search(sessionsdn, LDAPv2.SCOPE_SUB, filter, attrs, false);
+ if (res.getCount() > 0)
+ ret = true;
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainSessionTable: unable to query session " + sessionId + ": " + e);
+ }
+
+ try {
+ mLdapConnFactory.returnConn(conn);
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainSessionTable: isSessionIdExist: Error in disconnecting from database: " + e);
+ }
+ return ret;
+ }
+
+ public Enumeration<String> getSessionIds() {
+ IConfigStore cs = CMS.getConfigStore();
+ LDAPConnection conn = null;
+ Vector<String> ret = new Vector<String>();
+
+ try {
+ String basedn = cs.getString("internaldb.basedn");
+ String sessionsdn = "ou=sessions,ou=Security Domain," + basedn;
+ String filter = "(objectclass=securityDomainSessionEntry)";
+ String[] attrs = { "cn" };
+
+ conn = mLdapConnFactory.getConn();
+ LDAPSearchResults res = conn.search(sessionsdn, LDAPv2.SCOPE_SUB, filter, attrs, false);
+ while (res.hasMoreElements()) {
+ LDAPEntry entry = res.next();
+ LDAPAttribute sid = entry.getAttribute("cn");
+ if (sid == null) {
+ throw new Exception("Invalid LDAP Entry." + entry.getDN() + " No session id(cn).");
+ }
+ ret.add(sid.getStringValueArray()[0]);
+ }
+ } catch (LDAPException e) {
+ switch (e.getLDAPResultCode()) {
+ case LDAPException.NO_SUCH_OBJECT:
+ CMS.debug("SecurityDomainSessionTable: getSessionIds(): no sessions have been created");
+ break;
+ default:
+ CMS.debug("SecurityDomainSessionTable: unable to query sessionIds due to ldap exception: " + e);
+ }
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainSessionTable: unable to query sessionIds: " + e);
+ }
+
+ try {
+ mLdapConnFactory.returnConn(conn);
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainSessionTable: getSessionIds: Error in disconnecting from database: " + e);
+ }
+
+ return ret.elements();
+ }
+
+ private String getStringValue(String sessionId, String attr) {
+ IConfigStore cs = CMS.getConfigStore();
+ LDAPConnection conn = null;
+ String ret = null;
+ try {
+ String basedn = cs.getString("internaldb.basedn");
+ String sessionsdn = "ou=sessions,ou=Security Domain," + basedn;
+ String filter = "(cn=" + sessionId + ")";
+ String[] attrs = { attr };
+ conn = mLdapConnFactory.getConn();
+ LDAPSearchResults res = conn.search(sessionsdn, LDAPv2.SCOPE_SUB, filter, attrs, false);
+ if (res.getCount() > 0) {
+ LDAPEntry entry = res.next();
+ LDAPAttribute searchAttribute = entry.getAttribute(attr);
+ if (searchAttribute == null) {
+ throw new Exception("No Attribute " + attr + " for this session in LDAPEntry "+entry.getDN());
+ }
+ ret = searchAttribute.getStringValueArray()[0];
+ }
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainSessionTable: unable to query session " + sessionId + ": " + e.getMessage());
+ }
+
+ try {
+ mLdapConnFactory.returnConn(conn);
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainSessionTable: isSessionIdExist: Error in disconnecting from database: " + e);
+ }
+ return ret;
+ }
+
+ public String getIP(String sessionId) {
+ return getStringValue(sessionId, "host");
+ }
+
+ public String getUID(String sessionId) {
+ return getStringValue(sessionId, "uid");
+ }
+
+ public String getGroup(String sessionId) {
+ return getStringValue(sessionId, "cmsUserGroup");
+ }
+
+ public long getBeginTime(String sessionId) {
+ String beginStr = getStringValue(sessionId, "dateOfCreate");
+ if (beginStr != null) {
+ return Long.parseLong(beginStr);
+ }
+ return -1;
+ }
+
+ public long getTimeToLive() {
+ return m_timeToLive;
+ }
+
+ public int getSize() {
+ IConfigStore cs = CMS.getConfigStore();
+ LDAPConnection conn = null;
+ int ret = 0;
+
+ try {
+ String basedn = cs.getString("internaldb.basedn");
+ String sessionsdn = "ou=sessions,ou=Security Domain," + basedn;
+ String filter = "(objectclass=securityDomainSessionEntry)";
+ String[] attrs = { "cn" };
+
+ conn = mLdapConnFactory.getConn();
+ LDAPSearchResults res = conn.search(sessionsdn, LDAPv2.SCOPE_SUB, filter, attrs, false);
+ ret = res.getCount();
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainSessionTable: unable to query sessionIds: " + e);
+ }
+
+ try {
+ mLdapConnFactory.returnConn(conn);
+ } catch (Exception e) {
+ CMS.debug("SecurityDomainSessionTable: getSessionIds: Error in disconnecting from database: " + e);
+ }
+
+ return ret;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/session/SecurityDomainSessionTable.java b/base/server/cmscore/src/com/netscape/cmscore/session/SecurityDomainSessionTable.java
new file mode 100644
index 000000000..497f42f7a
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/session/SecurityDomainSessionTable.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.session;
+
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.netscape.certsrv.base.ISecurityDomainSessionTable;
+
+/**
+ * This object stores the values for IP, uid and group based on the cookie id.
+ */
+public class SecurityDomainSessionTable
+ implements ISecurityDomainSessionTable {
+
+ private Hashtable<String, Vector<Comparable<?>>> m_sessions;
+ private long m_timeToLive;
+
+ public SecurityDomainSessionTable(long timeToLive) {
+ m_sessions = new Hashtable<String, Vector<Comparable<?>>>();
+ m_timeToLive = timeToLive;
+ }
+
+ public int addEntry(String sessionId, String ip,
+ String uid, String group) {
+ Vector<Comparable<?>> v = new Vector<Comparable<?>>();
+ v.addElement(ip);
+ v.addElement(uid);
+ v.addElement(group);
+ Date d = new Date();
+ long t = d.getTime();
+ v.addElement(Long.valueOf(t));
+ m_sessions.put(sessionId, v);
+ return SUCCESS;
+ }
+
+ public int removeEntry(String sessionId) {
+ m_sessions.remove(sessionId);
+ return SUCCESS;
+ }
+
+ public boolean isSessionIdExist(String sessionId) {
+ return m_sessions.containsKey(sessionId);
+ }
+
+ public Enumeration<String> getSessionIds() {
+ return m_sessions.keys();
+ }
+
+ public String getIP(String sessionId) {
+ Vector<Comparable<?>> v = m_sessions.get(sessionId);
+ if (v != null)
+ return (String) v.elementAt(0);
+ return null;
+ }
+
+ public String getUID(String sessionId) {
+ Vector<Comparable<?>> v = m_sessions.get(sessionId);
+ if (v != null)
+ return (String) v.elementAt(1);
+ return null;
+ }
+
+ public String getGroup(String sessionId) {
+ Vector<Comparable<?>> v = m_sessions.get(sessionId);
+ if (v != null)
+ return (String) v.elementAt(2);
+ return null;
+ }
+
+ public long getBeginTime(String sessionId) {
+ Vector<Comparable<?>> v = m_sessions.get(sessionId);
+ if (v != null) {
+ Long n = (Long) v.elementAt(3);
+ if (n != null)
+ return n.longValue();
+ }
+ return -1;
+ }
+
+ public long getTimeToLive() {
+ return m_timeToLive;
+ }
+
+ public int getSize() {
+ return m_sessions.size();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/session/SessionTimer.java b/base/server/cmscore/src/com/netscape/cmscore/session/SessionTimer.java
new file mode 100644
index 000000000..28c06de32
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/session/SessionTimer.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.session;
+
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.TimerTask;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.ISecurityDomainSessionTable;
+import com.netscape.certsrv.logging.ILogger;
+
+public class SessionTimer extends TimerTask {
+ private ISecurityDomainSessionTable m_sessiontable = null;
+ private ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+ private final static String LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE =
+ "LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE_1";
+
+ public SessionTimer(ISecurityDomainSessionTable table) {
+ super();
+ m_sessiontable = table;
+ }
+
+ public void run() {
+ Enumeration<String> keys = m_sessiontable.getSessionIds();
+ while (keys.hasMoreElements()) {
+ String sessionId = keys.nextElement();
+ long beginTime = m_sessiontable.getBeginTime(sessionId);
+ Date nowDate = new Date();
+ long nowTime = nowDate.getTime();
+ long timeToLive = m_sessiontable.getTimeToLive();
+ if ((nowTime - beginTime) > timeToLive) {
+ m_sessiontable.removeEntry(sessionId);
+ CMS.debug("SessionTimer run: successfully remove the session id entry from the table.");
+
+ // audit message
+ String auditParams = "operation;;expire_token+token;;" + sessionId;
+ String auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE,
+ "system",
+ ILogger.SUCCESS,
+ auditParams);
+
+ mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ auditMessage);
+
+ }
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/time/SimpleTimeSource.java b/base/server/cmscore/src/com/netscape/cmscore/time/SimpleTimeSource.java
new file mode 100644
index 000000000..ab832b7cc
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/time/SimpleTimeSource.java
@@ -0,0 +1,29 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.time;
+
+import java.util.Date;
+
+import com.netscape.certsrv.base.ITimeSource;
+
+public class SimpleTimeSource implements ITimeSource {
+
+ public Date getCurrentDate() {
+ return new Date();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/usrgrp/CertDNCertUserLocator.java b/base/server/cmscore/src/com/netscape/cmscore/usrgrp/CertDNCertUserLocator.java
new file mode 100644
index 000000000..673146695
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/usrgrp/CertDNCertUserLocator.java
@@ -0,0 +1,77 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.usrgrp;
+
+import java.security.cert.X509Certificate;
+
+import netscape.ldap.LDAPException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.usrgrp.Certificates;
+import com.netscape.certsrv.usrgrp.EUsrGrpException;
+import com.netscape.certsrv.usrgrp.ICertUserLocator;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+
+/**
+ * This interface defines a strategy on how to match
+ * the incoming certificate(s) with the certificate(s)
+ * in the scope. It matches the "certdn" field which contains
+ * the subject dn of the certificate
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class CertDNCertUserLocator implements ICertUserLocator {
+ private IUGSubsystem mUG = null;
+ protected static final String LDAP_ATTR_CERTDN = "seeAlso";
+
+ /**
+ * Constructs certificate matching agent.
+ */
+ public CertDNCertUserLocator() {
+ }
+
+ /**
+ * Retrieves description.
+ */
+ public String getDescription() {
+ return "A subject is authenticated if its first" +
+ " certificate can be matched with one of the" +
+ " certificate in the scope";
+ }
+
+ /**
+ * Do the cert-user mapping
+ */
+ public IUser locateUser(Certificates certs) throws
+ EUsrGrpException, LDAPException, ELdapException {
+ mUG = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+
+ X509Certificate certificates[] = certs.getCertificates();
+
+ if (certificates == null)
+ return null;
+
+ String filter = LDAP_ATTR_CERTDN + "=" +
+ certificates[0].getSubjectDN();
+
+ return mUG.findUsersByCert(filter);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/usrgrp/ExactMatchCertUserLocator.java b/base/server/cmscore/src/com/netscape/cmscore/usrgrp/ExactMatchCertUserLocator.java
new file mode 100644
index 000000000..d9a39afb8
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/usrgrp/ExactMatchCertUserLocator.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.usrgrp;
+
+import java.security.cert.X509Certificate;
+
+import netscape.ldap.LDAPException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.usrgrp.Certificates;
+import com.netscape.certsrv.usrgrp.EUsrGrpException;
+import com.netscape.certsrv.usrgrp.ICertUserLocator;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+
+/**
+ * This interface defines a strategy on how to match
+ * the incoming certificate(s) with the certificate(s)
+ * in the scope. It matches the "description" field which contains a
+ * stringied certificate.
+ *
+ * @author thomask
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class ExactMatchCertUserLocator implements ICertUserLocator {
+ private IUGSubsystem mUG = null;
+
+ /**
+ * Constructs certificate matching agent.
+ */
+ public ExactMatchCertUserLocator() {
+ }
+
+ /**
+ * Retrieves description.
+ */
+ public String getDescription() {
+ return "A subject is authenticated if its first" +
+ " certificate can be matched with one of the" +
+ " certificate in the scope";
+ }
+
+ /**
+ * Do the cert-user mapping
+ */
+ public IUser locateUser(Certificates certs) throws
+ EUsrGrpException, LDAPException, ELdapException {
+ mUG = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG);
+
+ X509Certificate certificates[] = certs.getCertificates();
+
+ if (certificates == null)
+ return null;
+ int pos = 0;
+
+ if (certificates[0].getSubjectDN().toString().equals(
+ certificates[0].getIssuerDN().toString())) {
+ pos = certificates.length - 1;
+ }
+
+ String filter = "description=" +
+ mUG.getCertificateString(certificates[pos]);
+
+ return mUG.findUsersByCert(filter);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/usrgrp/Group.java b/base/server/cmscore/src/com/netscape/cmscore/usrgrp/Group.java
new file mode 100644
index 000000000..25917e901
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/usrgrp/Group.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.usrgrp;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUsrGrp;
+
+/**
+ * A class represents a group.
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class Group implements IGroup {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1264387079578766750L;
+ @SuppressWarnings("unused")
+ private IUsrGrp mBase;
+ private String mName = null;
+ private Vector<String> mMembers = new Vector<String>();
+ private String mDescription = null;
+
+ private static final Vector<String> mNames = new Vector<String>();
+ static {
+ mNames.addElement(ATTR_NAME);
+ mNames.addElement(ATTR_ID);
+ mNames.addElement(ATTR_DESCRIPTION);
+ mNames.addElement(ATTR_MEMBERS);
+ }
+
+ /**
+ * Constructs local group.
+ */
+ public Group(IUsrGrp base, String name) {
+ mBase = base;
+ mName = name;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public String getGroupID() {
+ return mName;
+ }
+
+ public String getDescription() {
+ return mDescription;
+ }
+
+ public void addMemberName(String name) {
+ mMembers.addElement(name);
+ }
+
+ public Enumeration<String> getMemberNames() {
+ return mMembers.elements();
+ }
+
+ public boolean isMember(String name) {
+ for (int i = 0; i < mMembers.size(); i++) {
+ String id = mMembers.elementAt(i);
+
+ if (name.equals(id)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void set(String name, Object object) throws EBaseException {
+ if (name.equals(ATTR_NAME)) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ } else if (name.equals(ATTR_ID)) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ } else if (name.equals(ATTR_MEMBERS)) {
+ mMembers = (Vector<String>) object;
+ } else if (name.equals(ATTR_DESCRIPTION)) {
+ mDescription = (String) object;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+ }
+
+ public Object get(String name) throws EBaseException {
+ if (name.equals(ATTR_NAME)) {
+ return getName();
+ } else if (name.equals(ATTR_ID)) {
+ return getGroupID();
+ } else if (name.equals(ATTR_MEMBERS)) {
+ return mMembers;
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+ }
+
+ public void delete(String name) throws EBaseException {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+
+ public Enumeration<String> getElements() {
+ return mNames.elements();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/usrgrp/UGSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/usrgrp/UGSubsystem.java
new file mode 100644
index 000000000..3833c2937
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/usrgrp/UGSubsystem.java
@@ -0,0 +1,1904 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.usrgrp;
+
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Vector;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPDN;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPModificationSet;
+import netscape.ldap.LDAPSearchConstraints;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv2;
+import netscape.security.x509.X509CertImpl;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ldap.ELdapException;
+import com.netscape.certsrv.logging.AuditFormat;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.usrgrp.EUsrGrpException;
+import com.netscape.certsrv.usrgrp.ICertUserLocator;
+import com.netscape.certsrv.usrgrp.IGroup;
+import com.netscape.certsrv.usrgrp.IUGSubsystem;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.certsrv.usrgrp.IUsrGrp;
+import com.netscape.cmscore.ldapconn.LdapBoundConnFactory;
+import com.netscape.cmscore.util.Debug;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+/**
+ * This class defines low-level LDAP usr/grp management
+ * usr/grp information is located remotely on another
+ * LDAP server.
+ *
+ * @author thomask
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public final class UGSubsystem implements IUGSubsystem {
+
+ private static final long serialVersionUID = 8080165044652629774L;
+ public static final String ID = "usrgrp";
+ private String mId = ID;
+
+ protected static final String OBJECTCLASS_ATTR = "objectclass";
+ protected static final String MEMBER_ATTR = "uniquemember";
+ protected static final String GROUP_ATTR_VALUE = "groupofuniquenames";
+
+ protected static final String LDAP_ATTR_USER_CERT_STRING = "description";
+ protected static final String LDAP_ATTR_CERTDN = "seeAlso";
+ protected static final String LDAP_ATTR_USER_CERT = "userCertificate";
+ protected static final String LDAP_ATTR_PROFILE_ID = "profileID";
+
+ protected static final String PROP_BASEDN = "basedn";
+
+ protected IConfigStore mConfig = null;
+ protected transient LdapBoundConnFactory mLdapConnFactory = null;
+ protected String mBaseDN = null;
+ protected static UGSubsystem mUG = null;
+
+ private transient ILogger mLogger = null;
+
+ // singleton enforcement
+
+ private static UGSubsystem mInstance = new UGSubsystem();
+
+ public static UGSubsystem getInstance() {
+ return mInstance;
+ }
+
+ // end singleton enforcement.
+
+ /**
+ * Constructs LDAP based usr/grp management
+ */
+ private UGSubsystem() {
+ }
+
+ /**
+ * Retrieves identifier of this scope.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * Sets identifier of this manager
+ */
+ public void setId(String id) throws EBaseException {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION"));
+ }
+
+ /**
+ * Connects to LDAP server.
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mLogger = CMS.getLogger();
+ mConfig = config;
+
+ // initialize LDAP connection factory
+ try {
+ IConfigStore ldapConfig = mConfig.getSubStore("ldap");
+
+ mBaseDN = ldapConfig.getString(PROP_BASEDN, null);
+
+ mLdapConnFactory = new LdapBoundConnFactory();
+ mLdapConnFactory.init(ldapConfig);
+ } catch (EBaseException e) {
+ if (CMS.isPreOpMode())
+ return;
+ throw e;
+ }
+ }
+
+ /**
+ * Starts up this service.
+ */
+ public void startup() throws EBaseException {
+ // register admin servlet
+
+ }
+
+ /**
+ * Disconnects usr/grp manager from the LDAP
+ */
+ public void shutdown() {
+ try {
+ if (mLdapConnFactory != null) {
+ mLdapConnFactory.reset();
+ }
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_LDAP_SHUT", e.toString()));
+ }
+ }
+
+ public IUser createUser(String id) {
+ return new User(this, id);
+ }
+
+ public IGroup createGroup(String id) {
+ return new Group(this, id);
+ }
+
+ /**
+ * Retrieves configuration store.
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Retrieves the description of this scope.
+ */
+ public String getDescription() {
+ return "User/Group Manager";
+ }
+
+ /**
+ * Retrieves a user from LDAP
+ */
+ public IUser getUser(String userid) throws EUsrGrpException {
+ if (userid == null) {
+ return null;
+ }
+
+ try {
+ if (userid.indexOf('=') == -1) {
+ Enumeration<IUser> e = findUsers(userid);
+
+ if (e != null && e.hasMoreElements()) {
+ IUser u = e.nextElement();
+
+ return u;
+ } else {
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_USER_NOT_FOUND"));
+ }
+ } else {
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ // read DN
+ LDAPSearchResults res =
+ ldapconn.search(userid,
+ LDAPv2.SCOPE_SUB, "(objectclass=*)", null, false);
+ Enumeration<IUser> e = buildUsers(res);
+
+ if (e.hasMoreElements()) {
+ return e.nextElement();
+ }
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_GET_USER", e.toString()));
+ // throws...
+ }
+ return null;
+ }
+
+ /**
+ * Locates a user by certificate.
+ */
+ public User findUser(X509Certificate cert) throws EUsrGrpException {
+ if (cert == null) {
+ return null;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ String filter = LDAP_ATTR_USER_CERT_STRING + "=" + LDAPUtil.escapeFilter(getCertificateString(cert));
+ LDAPSearchResults res =
+ ldapconn.search(getUserBaseDN(),
+ LDAPConnection.SCOPE_SUB, filter, null, false);
+ Enumeration<IUser> e = buildUsers(res);
+
+ return (User) e.nextElement();
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_FIND_USER", e.toString()));
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_INTERNAL_DB", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ return null;
+ }
+
+ /**
+ * Searchs for identities that matches the certificate locater
+ * generated filter.
+ */
+ public IUser findUsersByCert(String filter) throws
+ EUsrGrpException, LDAPException {
+ if (filter == null) {
+ return null;
+ }
+
+ // To handle \ in the issuer DN or subject DN
+ // (see also RFC 2254, and bug #348303
+ int hasSlash = filter.indexOf('\\');
+
+ if (hasSlash != -1) {
+ String up = filter;
+ StringBuffer stripped = new StringBuffer();
+
+ hasSlash = up.indexOf('\\');
+ while (hasSlash != -1) {
+ stripped.append(up.substring(0, hasSlash) + "\\5c");
+
+ up = up.substring(hasSlash + 1);
+ hasSlash = up.indexOf('\\');
+ }
+ filter = stripped.toString() + up;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ LDAPSearchResults res = ldapconn.search(getUserBaseDN(),
+ LDAPv2.SCOPE_SUB, "(" + filter + ")",
+ null, false);
+
+ Enumeration<IUser> e = buildUsers(res);
+
+ return e.nextElement();
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_FIND_USER_BY_CERT", e.toString()));
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_FIND_USER_BY_CERT", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+
+ return null;
+ }
+
+ /**
+ * Searchs for identities that matches the filter.
+ */
+ public Enumeration<IUser> findUsers(String filter) throws EUsrGrpException {
+ if (filter == null) {
+ return null;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ LDAPSearchResults res = ldapconn.search(getUserBaseDN(),
+ LDAPv2.SCOPE_SUB, "(uid=" + filter + ")",
+ null, false);
+
+ Enumeration<IUser> e = buildUsers(res);
+
+ return e;
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_FIND_USERS", e.toString()));
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_FIND_USERS", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+
+ return null;
+ }
+
+ /**
+ * Searchs for identities that matches the filter.
+ * retrieves uid only, for efficiency of user listing
+ */
+ public Enumeration<IUser> listUsers(String filter) throws EUsrGrpException {
+ if (filter == null) {
+ return null;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ String attrs[] = new String[2];
+
+ attrs[0] = "uid";
+ attrs[1] = "cn";
+
+ ldapconn = getConn();
+ LDAPSearchConstraints cons = new LDAPSearchConstraints();
+
+ cons.setMaxResults(0);
+ LDAPSearchResults res = ldapconn.search(getUserBaseDN(),
+ LDAPv2.SCOPE_SUB, "(uid=" + filter + ")", attrs, false, cons);
+ Enumeration<IUser> e = lbuildUsers(res);
+
+ return e;
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_LIST_USERS", e.toString()));
+ } catch (Exception e) {
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_INTERNAL_ERROR"));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+
+ return null;
+ }
+
+ protected Enumeration<IUser> lbuildUsers(LDAPSearchResults res) throws
+ EUsrGrpException {
+ Vector<IUser> v = new Vector<IUser>();
+
+ while (res.hasMoreElements()) {
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+ IUser user = lbuildUser(entry);
+
+ v.addElement(user);
+ }
+ return v.elements();
+ }
+
+ protected Enumeration<IUser> buildUsers(LDAPSearchResults res) throws
+ EUsrGrpException {
+ Vector<IUser> v = new Vector<IUser>();
+
+ if (res != null) {
+ while (res.hasMoreElements()) {
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+ IUser user = buildUser(entry);
+
+ v.addElement(user);
+ }
+ }
+
+ // if v contains nothing, just throw exception
+ if (v.size() == 0) {
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_USER_NOT_FOUND"));
+ }
+
+ return v.elements();
+ }
+
+ /**
+ * builds a User instance. Sets only uid for user entry retrieved
+ * from LDAP server. for listing efficiency only.
+ *
+ * @return the User entity.
+ */
+ protected IUser lbuildUser(LDAPEntry entry) throws EUsrGrpException {
+ LDAPAttribute uid = entry.getAttribute("uid");
+ if (uid == null) {
+ throw new EUsrGrpException("No Attribute UID in LDAP Entry " + entry.getDN());
+ }
+ IUser id = createUser(this, (String) uid.getStringValues().nextElement());
+ LDAPAttribute cnAttr = entry.getAttribute("cn");
+
+ if (cnAttr != null) {
+ String cn = (String) cnAttr.getStringValues().nextElement();
+
+ if (cn != null) {
+ id.setFullName(cn);
+ }
+
+ }
+
+ LDAPAttribute certAttr =
+ entry.getAttribute(LDAP_ATTR_USER_CERT);
+
+ if (certAttr != null) {
+ Vector<X509Certificate> certVector = new Vector<X509Certificate>();
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> e = certAttr.getByteValues();
+
+ try {
+ for (; e != null && e.hasMoreElements();) {
+ X509Certificate cert = new X509CertImpl(
+ e.nextElement());
+
+ certVector.addElement(cert);
+ }
+ } catch (Exception ex) {
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_INTERNAL_ERROR"));
+ }
+
+ if (certVector != null && certVector.size() != 0) {
+ // Make an array of certs
+ X509Certificate[] certArray = new X509Certificate[certVector.size()];
+ Enumeration<X509Certificate> en = certVector.elements();
+ int i = 0;
+
+ while (en.hasMoreElements()) {
+ certArray[i++] = en.nextElement();
+ }
+
+ id.setX509Certificates(certArray);
+ }
+ }
+
+ return id;
+ }
+
+ /**
+ * builds a User instance. Set all attributes retrieved from
+ * LDAP server and set them on User.
+ *
+ * @return the User entity.
+ */
+ protected IUser buildUser(LDAPEntry entry) throws EUsrGrpException {
+ LDAPAttribute uid = entry.getAttribute("uid");
+ if (uid == null) {
+ throw new EUsrGrpException("No Attribute UID in LDAP Entry " + entry.getDN());
+ }
+ IUser id = createUser(this, (String) uid.getStringValues().nextElement());
+ LDAPAttribute cnAttr = entry.getAttribute("cn");
+
+ if (cnAttr != null) {
+ String cn = (String) cnAttr.getStringValues().nextElement();
+
+ if (cn != null) {
+ id.setFullName(cn);
+ }
+ }
+
+ String userdn = entry.getDN();
+
+ if (userdn != null) {
+ id.setUserDN(userdn);
+ } else { // the impossible
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_BUILD_USER", userdn));
+
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_INTERNAL_ERROR"));
+ }
+
+ /*
+ LDAPAttribute certdnAttr = entry.getAttribute(LDAP_ATTR_CERTDN);
+ if (certdnAttr != null) {
+ String cdn = (String)certdnAttr.getStringValues().nextElement();
+ if (cdn != null) {
+ id.setCertDN(cdn);
+ }
+ }
+ */
+ LDAPAttribute mailAttr = entry.getAttribute("mail");
+
+ if (mailAttr != null) {
+ @SuppressWarnings("unchecked")
+ Enumeration<String> en = mailAttr.getStringValues();
+
+ if (en != null && en.hasMoreElements()) {
+ String mail = en.nextElement();
+
+ if (mail != null) {
+ id.setEmail(mail);
+ }
+ }
+ }
+ if (id.getEmail() == null) {
+ id.setEmail(""); // safety net
+ }
+
+ LDAPAttribute pwdAttr = entry.getAttribute("userpassword");
+
+ if (pwdAttr != null) {
+ String pwd = (String) pwdAttr.getStringValues().nextElement();
+
+ if (pwd != null) {
+ id.setPassword(pwd);
+ }
+ }
+ LDAPAttribute phoneAttr = entry.getAttribute("telephonenumber");
+
+ if (phoneAttr != null) {
+ @SuppressWarnings("unchecked")
+ Enumeration<String> en = phoneAttr.getStringValues();
+
+ if (en != null && en.hasMoreElements()) {
+ String phone = en.nextElement();
+
+ if (phone != null) {
+ id.setPhone(phone);
+ }
+ }
+ }
+ if (id.getPhone() == null) {
+ id.setPhone(""); // safety net
+ }
+
+ LDAPAttribute userTypeAttr = entry.getAttribute("usertype");
+
+ if (userTypeAttr == null)
+ id.setUserType("");
+ else {
+ @SuppressWarnings("unchecked")
+ Enumeration<String> en = userTypeAttr.getStringValues();
+
+ if (en != null && en.hasMoreElements()) {
+ String userType = en.nextElement();
+
+ if ((userType != null) && (!userType.equals("undefined")))
+ id.setUserType(userType);
+ else
+ id.setUserType("");
+
+ }
+ }
+
+ LDAPAttribute userStateAttr = entry.getAttribute("userstate");
+
+ if (userStateAttr == null)
+ id.setState("");
+ else {
+ @SuppressWarnings("unchecked")
+ Enumeration<String> en = userStateAttr.getStringValues();
+
+ if (en != null && en.hasMoreElements()) {
+ String userState = en.nextElement();
+
+ if (userState != null)
+ id.setState(userState);
+ else
+ id.setState("");
+
+ }
+ }
+
+ LDAPAttribute certAttr =
+ entry.getAttribute(LDAP_ATTR_USER_CERT);
+
+ if (certAttr != null) {
+ Vector<X509Certificate> certVector = new Vector<X509Certificate>();
+ @SuppressWarnings("unchecked")
+ Enumeration<byte[]> e = certAttr.getByteValues();
+
+ try {
+ for (; e != null && e.hasMoreElements();) {
+ X509Certificate cert = new X509CertImpl(e.nextElement());
+ certVector.addElement(cert);
+ }
+ } catch (Exception ex) {
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_INTERNAL_ERROR"));
+ }
+
+ if (certVector != null && certVector.size() != 0) {
+ // Make an array of certs
+ X509Certificate[] certArray = new X509Certificate[certVector.size()];
+ Enumeration<X509Certificate> en = certVector.elements();
+ int i = 0;
+
+ while (en.hasMoreElements()) {
+ certArray[i++] = en.nextElement();
+ }
+
+ id.setX509Certificates(certArray);
+ }
+ }
+
+ LDAPAttribute profileAttr = entry.getAttribute(LDAP_ATTR_PROFILE_ID);
+ if (profileAttr != null) {
+ @SuppressWarnings("unchecked")
+ Enumeration<String> profiles = profileAttr.getStringValues();
+ id.setTpsProfiles(Collections.list(profiles));
+ }
+
+ return id;
+ }
+
+ protected IUser createUser(IUsrGrp base, String id) {
+ return new User(base, id);
+ }
+
+ /**
+ * Adds identity. Certificates handled by a separate call to
+ * addUserCert()
+ */
+ public void addUser(IUser identity) throws EUsrGrpException, LDAPException {
+ User id = (User) identity;
+
+ if (id == null) {
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_ADD_USER_FAIL"));
+ }
+
+ if (id.getUserID() == null) {
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_ADD_USER_FAIL_NO_UID"));
+ }
+
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+ List<String> oclist = new ArrayList<String>();
+ oclist.add("top");
+ oclist.add("person");
+ oclist.add("organizationalPerson");
+ oclist.add("inetOrgPerson");
+ oclist.add("cmsuser");
+
+ if (id.getTpsProfiles() != null) {
+ oclist.add("tpsProfileID");
+ }
+
+ String oc[] = new String[oclist.size()];
+ oc = oclist.toArray(oc);
+
+ attrs.add(new LDAPAttribute(OBJECTCLASS_ATTR, oc));
+ attrs.add(new LDAPAttribute("uid", id.getUserID()));
+ attrs.add(new LDAPAttribute("sn", id.getFullName()));
+ attrs.add(new LDAPAttribute("cn", id.getFullName()));
+ attrs.add(new LDAPAttribute("mail", id.getEmail()));
+
+ if (id.getPhone() != null) {
+ // DS syntax checking requires a value for PrintableString syntax
+ if (!id.getPhone().equals("")) {
+ attrs.add(new LDAPAttribute("telephonenumber", id.getPhone()));
+ }
+ }
+
+ attrs.add(new LDAPAttribute("userpassword",
+ id.getPassword()));
+
+ if (id.getUserType() != null) {
+ // DS syntax checking requires a value for Directory String syntax
+ // but usertype is a MUST attribute, so we need to add something here
+ // if it is undefined.
+
+ if (!id.getUserType().equals("")) {
+ attrs.add(new LDAPAttribute("usertype", id.getUserType()));
+ } else {
+ attrs.add(new LDAPAttribute("usertype", "undefined"));
+ }
+ }
+
+ if (id.getState() != null) {
+ // DS syntax checking requires a value for Directory String syntax
+ if (!id.getState().equals("")) {
+ attrs.add(new LDAPAttribute("userstate", id.getState()));
+ }
+ }
+
+ // TODO add audit logging for profile
+ if (id.getTpsProfiles() != null) {
+ List<String> profiles = id.getTpsProfiles();
+ for (String profile: profiles) {
+ attrs.add(new LDAPAttribute(LDAP_ATTR_PROFILE_ID, profile));
+ }
+ }
+
+ LDAPEntry entry = new LDAPEntry("uid=" + LDAPUtil.escapeRDNValue(id.getUserID()) +
+ "," + getUserBaseDN(), attrs);
+ // for audit log
+ SessionContext sessionContext = SessionContext.getContext();
+ String adminId = (String) sessionContext.get(SessionContext.USER_ID);
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP,
+ AuditFormat.LEVEL, AuditFormat.ADDUSERFORMAT,
+ new Object[] { adminId, id.getUserID() }
+ );
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ ldapconn.add(entry);
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_ADD_USER", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ }
+
+ /**
+ * adds a user certificate to user
+ */
+ public void addUserCert(IUser identity) throws EUsrGrpException,
+ LDAPException {
+ User user = (User) identity;
+
+ if (user == null) {
+ return;
+ }
+
+ X509Certificate cert[] = null;
+ LDAPModificationSet addCert = new LDAPModificationSet();
+
+ if ((cert = user.getX509Certificates()) != null) {
+ LDAPAttribute attrCertStr = new LDAPAttribute(LDAP_ATTR_USER_CERT_STRING);
+ LDAPAttribute attrCertBin = new LDAPAttribute(LDAP_ATTR_USER_CERT);
+
+ try {
+ attrCertBin.addValue(cert[0].getEncoded());
+ attrCertStr.addValue(getCertificateString(cert[0]));
+ } catch (CertificateEncodingException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_ADD_USER_CERT", e.toString()));
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_USR_CERT_ERROR"));
+ }
+
+ addCert.add(LDAPModification.ADD, attrCertStr);
+ addCert.add(LDAPModification.ADD, attrCertBin);
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ ldapconn.modify("uid=" + LDAPUtil.escapeRDNValue(user.getUserID()) +
+ "," + getUserBaseDN(), addCert);
+ // for audit log
+ SessionContext sessionContext = SessionContext.getContext();
+ String adminId = (String) sessionContext.get(SessionContext.USER_ID);
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP,
+ AuditFormat.LEVEL, AuditFormat.ADDUSERCERTFORMAT,
+ new Object[] { adminId, user.getUserID(),
+ cert[0].getSubjectDN().toString(),
+ cert[0].getSerialNumber().toString(16) }
+ );
+
+ } catch (LDAPException e) {
+ if (Debug.ON) {
+ e.printStackTrace();
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_ADD_USER", e.toString()));
+ throw e;
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_ADD_USER", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ }
+
+ return;
+ }
+
+ public void addCertSubjectDN(IUser identity) throws EUsrGrpException, LDAPException {
+ User user = (User) identity;
+
+ if (user == null) {
+ return;
+ }
+
+ X509Certificate cert[] = null;
+ LDAPModificationSet addCert = new LDAPModificationSet();
+
+ if ((cert = user.getX509Certificates()) != null) {
+ LDAPAttribute attrCertDNStr = new LDAPAttribute(LDAP_ATTR_CERTDN);
+ attrCertDNStr.addValue(cert[0].getSubjectDN().toString());
+ addCert.add(LDAPModification.ADD, attrCertDNStr);
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ ldapconn.modify("uid=" + LDAPUtil.escapeRDNValue(user.getUserID()) +
+ "," + getUserBaseDN(), addCert);
+ // for audit log
+ SessionContext sessionContext = SessionContext.getContext();
+ String adminId = (String) sessionContext.get(SessionContext.USER_ID);
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP,
+ AuditFormat.LEVEL, AuditFormat.ADDCERTSUBJECTDNFORMAT,
+ new Object[] { adminId, user.getUserID(),
+ cert[0].getSubjectDN().toString()}
+ );
+
+ } catch (LDAPException e) {
+ if (Debug.ON) {
+ e.printStackTrace();
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_ADD_USER", e.toString()));
+ throw e;
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_ADD_USER", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ }
+
+ return;
+ }
+
+ public void removeCertSubjectDN(IUser identity) throws EUsrGrpException, LDAPException {
+ User user = (User) identity;
+
+ if (user == null) {
+ CMS.debug("removeCertSubjectDN: null user passed in");
+ return;
+ }
+
+ X509Certificate cert[] = null;
+ LDAPModificationSet delAttr = new LDAPModificationSet();
+
+ if ((cert = user.getX509Certificates()) != null) {
+ LDAPAttribute attrCertDNStr = new LDAPAttribute(LDAP_ATTR_CERTDN);
+ attrCertDNStr.addValue(cert[0].getSubjectDN().toString());
+ delAttr.add(LDAPModification.DELETE, attrCertDNStr);
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ ldapconn.modify("uid=" + LDAPUtil.escapeRDNValue(user.getUserID()) +
+ "," + getUserBaseDN(), delAttr);
+ // for audit log
+ SessionContext sessionContext = SessionContext.getContext();
+ String adminId = (String) sessionContext.get(SessionContext.USER_ID);
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP,
+ AuditFormat.LEVEL, AuditFormat.REMOVECERTSUBJECTDNFORMAT,
+ new Object[] { adminId, user.getUserID(),
+ cert[0].getSubjectDN().toString() }
+ );
+
+ } catch (LDAPException e) {
+ if (Debug.ON) {
+ e.printStackTrace();
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_ADD_USER", e.toString()));
+ throw e;
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_ADD_USER", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ }
+ return;
+ }
+
+ /**
+ * Removes a user certificate for a user entry
+ * given a user certificate DN (actually, a combination of version,
+ * serialNumber, issuerDN, and SubjectDN), and it gets removed
+ */
+ public void removeUserCert(IUser identity) throws EUsrGrpException {
+ User user = (User) identity;
+ User ldapUser = null;
+
+ if (user == null) {
+ return;
+ }
+
+ // retrieve all certs of the user, then match the cert String for
+ // removal
+ ldapUser = (User) getUser(user.getUserID());
+
+ if (ldapUser == null) {
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_USER_NOT_FOUND"));
+ }
+
+ X509Certificate[] certs = ldapUser.getX509Certificates();
+
+ if (certs == null) {
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_CERT_NOT_FOUND"));
+ }
+
+ String delCertdn = user.getCertDN();
+
+ if (delCertdn == null) {
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_CERT_NOT_FOUND"));
+ }
+
+ int certCount = 0;
+
+ for (int i = 0; i < certs.length; i++) {
+ String certStr;
+
+ if (delCertdn.startsWith("-1;")) {
+ certStr = getCertificateStringWithoutVersion(certs[i]);
+ } else {
+ certStr = getCertificateString(certs[i]);
+ }
+
+ if (!delCertdn.equalsIgnoreCase(certStr)) continue;
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+
+ String dn = "uid=" + LDAPUtil.escapeRDNValue(user.getUserID()) + "," + getUserBaseDN();
+
+ try {
+ // remove seeAlso attribute
+ LDAPModificationSet attrs = new LDAPModificationSet();
+ LDAPAttribute certDNAttrS = new LDAPAttribute(LDAP_ATTR_CERTDN);
+ certDNAttrS.addValue(certs[i].getSubjectDN().toString());
+ attrs.add(LDAPModification.DELETE, certDNAttrS);
+ ldapconn.modify(dn, attrs);
+
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() == 16) { // ignore missing seeAlso attribute
+ CMS.debug("removeUserCert: No attribute "+LDAP_ATTR_CERTDN+" in entry "+dn);
+ } else {
+ throw e;
+ }
+ }
+
+ // remove userCertificate and description attributes
+ LDAPModificationSet attrs = new LDAPModificationSet();
+
+ LDAPAttribute certAttr = new LDAPAttribute(LDAP_ATTR_USER_CERT);
+ certAttr.addValue(certs[i].getEncoded());
+ attrs.add(LDAPModification.DELETE, certAttr);
+
+ LDAPAttribute certAttrS = new LDAPAttribute(LDAP_ATTR_USER_CERT_STRING);
+ certAttrS.addValue(getCertificateString(certs[i]));
+ attrs.add(LDAPModification.DELETE, certAttrS);
+
+ ldapconn.modify(dn, attrs);
+
+ certCount++;
+
+ // for audit log
+ SessionContext sessionContext = SessionContext.getContext();
+ String adminId = (String) sessionContext.get(SessionContext.USER_ID);
+
+ mLogger.log(ILogger.EV_AUDIT,
+ ILogger.S_USRGRP,
+ AuditFormat.LEVEL,
+ AuditFormat.REMOVEUSERCERTFORMAT,
+ new Object[] { adminId, user.getUserID(),
+ certs[0].getSubjectDN().toString(),
+ certs[i].getSerialNumber().toString(16) }
+ );
+
+ } catch (CertificateEncodingException e) {
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_USR_CERT_ERROR"));
+
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_REMOVE_USER", e.toString()));
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_MOD_USER_FAIL"));
+
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_REMOVE_USER", e.toString()));
+
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ }
+
+ if (certCount == 0) {
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_CERT_NOT_FOUND"));
+ }
+ }
+
+ public void addUserToGroup(IGroup grp, String userid)
+ throws EUsrGrpException {
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ String groupDN = "cn=" + LDAPUtil.escapeRDNValue(grp.getGroupID()) +
+ "," + getGroupBaseDN();
+ LDAPAttribute memberAttr = new LDAPAttribute(
+ "uniquemember", "uid=" + LDAPUtil.escapeRDNValue(userid) + "," + getUserBaseDN());
+ LDAPModification singleChange = new LDAPModification(
+ LDAPModification.ADD, memberAttr);
+
+ ldapconn.modify(groupDN, singleChange);
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_ADD_USER_TO_GROUP", e.toString()));
+
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_ADD_USER_FAIL"));
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_ADD_USER_TO_GROUP", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ }
+
+ public void removeUserFromGroup(IGroup grp, String userid)
+ throws EUsrGrpException {
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ String groupDN = "cn=" + LDAPUtil.escapeRDNValue(grp.getGroupID()) +
+ "," + getGroupBaseDN();
+ LDAPAttribute memberAttr = new LDAPAttribute(
+ "uniquemember", "uid=" + LDAPUtil.escapeRDNValue(userid) + "," + getUserBaseDN());
+ LDAPModification singleChange = new LDAPModification(
+ LDAPModification.DELETE, memberAttr);
+
+ ldapconn.modify(groupDN, singleChange);
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_REMOVE_USER_FROM_GROUP", e.toString()));
+
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_REMOVE_USER_FAIL"));
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_REMOVE_USER_FROM_GROUP", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ }
+
+ /**
+ * Removes identity.
+ */
+ public void removeUser(String userid) throws EUsrGrpException {
+ if (userid == null) {
+ return;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ ldapconn.delete("uid=" + LDAPUtil.escapeRDNValue(userid) + "," + getUserBaseDN());
+ // for audit log
+ SessionContext sessionContext = SessionContext.getContext();
+ String adminId = (String) sessionContext.get(SessionContext.USER_ID);
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP,
+ AuditFormat.LEVEL, AuditFormat.REMOVEUSERFORMAT,
+ new Object[] { adminId, userid }
+ );
+
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_REMOVE_USER", e.toString()));
+
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_REMOVE_USER_FAIL"));
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_REMOVE_USER", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ }
+
+
+ /**
+ * modifies user attributes. Certs are handled separately
+ */
+ public void modifyUser(IUser identity) throws EUsrGrpException {
+ User user = (User) identity;
+ String st = null;
+
+ /**
+ * X509Certificate certs[] = null;
+ **/
+ LDAPModificationSet attrs = new LDAPModificationSet();
+
+ if (user == null) {
+ return;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ if ((st = user.getFullName()) != null) {
+ attrs.add(LDAPModification.REPLACE,
+ new LDAPAttribute("sn", st));
+ attrs.add(LDAPModification.REPLACE,
+ new LDAPAttribute("cn", st));
+ }
+ if ((st = user.getEmail()) != null) {
+ LDAPAttribute ld = new LDAPAttribute("mail", st);
+
+ attrs.add(LDAPModification.REPLACE, ld);
+ }
+ if ((st = user.getPassword()) != null && (!st.equals(""))) {
+ attrs.add(LDAPModification.REPLACE,
+ new LDAPAttribute("userpassword", st));
+ }
+ if ((st = user.getPhone()) != null) {
+ if (!st.equals("")) {
+ attrs.add(LDAPModification.REPLACE,
+ new LDAPAttribute("telephonenumber", st));
+ } else {
+ try {
+ LDAPModification singleChange = new LDAPModification(
+ LDAPModification.DELETE, new LDAPAttribute("telephonenumber"));
+ ldapconn.modify("uid=" + LDAPUtil.escapeRDNValue(user.getUserID()) +
+ "," + getUserBaseDN(), singleChange);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() != LDAPException.NO_SUCH_ATTRIBUTE) {
+ CMS.debug("modifyUser: Error in deleting telephonenumber");
+ throw e;
+ }
+ }
+ }
+ }
+
+ if ((st = user.getState()) != null) {
+ if (!st.equals("")) {
+ attrs.add(LDAPModification.REPLACE,
+ new LDAPAttribute("userstate", st));
+ } else {
+ try {
+ LDAPModification singleChange = new LDAPModification(
+ LDAPModification.DELETE, new LDAPAttribute("userstate"));
+ ldapconn.modify("uid=" + LDAPUtil.escapeRDNValue(user.getUserID()) +
+ "," + getUserBaseDN(), singleChange);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() != LDAPException.NO_SUCH_ATTRIBUTE) {
+ CMS.debug("modifyUser: Error in deleting userstate");
+ throw e;
+ }
+ }
+ }
+ }
+
+ if (user.getTpsProfiles() != null) {
+ // TODO add audit logging for profile
+
+ // replace the objectclass in case tpsProfile is not present
+ String oc[] = { "top", "person", "organizationalPerson",
+ "inetOrgPerson", "cmsuser", "tpsProfileID" };
+ attrs.add(LDAPModification.REPLACE,
+ new LDAPAttribute(OBJECTCLASS_ATTR, oc));
+
+ User ldapUser = (User) getUser(user.getUserID());
+ List<String> oldProfiles = ldapUser.getTpsProfiles();
+ List<String> profiles = user.getTpsProfiles();
+
+ if (oldProfiles == null) {
+ for (String profile : profiles) {
+ attrs.add(LDAPModification.ADD,
+ new LDAPAttribute(LDAP_ATTR_PROFILE_ID, profile));
+ }
+ } else {
+ for (String profile : profiles) {
+ boolean found = false;
+ for (String oldProfile : oldProfiles) {
+ if (profile.equals(oldProfile)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ attrs.add(LDAPModification.ADD,
+ new LDAPAttribute(LDAP_ATTR_PROFILE_ID, profile));
+ }
+ }
+
+ for (String oldProfile : oldProfiles) {
+ boolean found = false;
+ for (String profile : profiles) {
+ if (profile.equals(oldProfile)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ attrs.add(LDAPModification.DELETE,
+ new LDAPAttribute(LDAP_ATTR_PROFILE_ID, oldProfile));
+ }
+ }
+ }
+ }
+
+ /**
+ * if ((certs = user.getCertificates()) != null) {
+ * LDAPAttribute attrCertStr = new
+ * LDAPAttribute("description");
+ * LDAPAttribute attrCertBin = new
+ * LDAPAttribute(LDAP_ATTR_USER_CERT);
+ * for (int i = 0 ; i < certs.length; i++) {
+ * attrCertBin.addValue(certs[i].getEncoded());
+ * attrCertStr.addValue(getCertificateString(certs[i]));
+ * }
+ * attrs.add(attrCertStr);
+ *
+ * if (user.getCertOp() == OpDef.ADD) {
+ * attrs.add(LDAPModification.ADD, attrCertBin);
+ * } else if (user.getCertOp() == OpDef.DELETE) {
+ * attrs.add(LDAPModification.DELETE, attrCertBin);
+ * } else {
+ * throw new EUsrGrpException(UsrGrpResources.USR_MOD_ILL_CERT_OP);
+ * }
+ * }
+ **/
+ ldapconn.modify("uid=" + LDAPUtil.escapeRDNValue(user.getUserID()) +
+ "," + getUserBaseDN(), attrs);
+ // for audit log
+ SessionContext sessionContext = SessionContext.getContext();
+ String adminId = (String) sessionContext.get(SessionContext.USER_ID);
+
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP,
+ AuditFormat.LEVEL, AuditFormat.MODIFYUSERFORMAT,
+ new Object[] { adminId, user.getUserID() }
+ );
+
+ } catch (Exception e) {
+ //e.printStackTrace();
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_MOD_USER_FAIL"));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ }
+
+ protected Enumeration<IGroup> buildGroups(LDAPSearchResults res) throws EUsrGrpException {
+ Vector<IGroup> v = new Vector<IGroup>();
+
+ while (res.hasMoreElements()) {
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+
+ v.addElement(buildGroup(entry));
+ }
+ return v.elements();
+ }
+
+ /**
+ * Finds groups.
+ * @throws EUsrGrpException
+ */
+ public Enumeration<IGroup> findGroups(String filter) throws EUsrGrpException {
+ if (filter == null) {
+ return null;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ LDAPSearchResults res =
+ ldapconn.search(getGroupBaseDN(), LDAPv2.SCOPE_SUB,
+ "(&(objectclass=groupofuniquenames)(cn=" + filter + "))",
+ null, false);
+
+ return buildGroups(res);
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_FIND_GROUPS", e.toString()));
+ return null;
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_FIND_GROUPS", e.toString()));
+ return null;
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ }
+
+ public IGroup findGroup(String filter) throws EUsrGrpException {
+ Enumeration<IGroup> groups = findGroups(filter);
+
+ if (groups == null || !groups.hasMoreElements())
+ return null;
+ return groups.nextElement();
+ }
+
+ /**
+ * List groups. more efficient than find Groups. only retrieves
+ * group names and description.
+ */
+ public Enumeration<IGroup> listGroups(String filter) throws EUsrGrpException {
+ if (filter == null) {
+ return null;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ String attrs[] = new String[2];
+
+ attrs[0] = "cn";
+ attrs[1] = "description";
+
+ ldapconn = getConn();
+ LDAPSearchResults res =
+ ldapconn.search(getGroupBaseDN(), LDAPv2.SCOPE_SUB,
+ "(&(objectclass=groupofuniquenames)(cn=" + filter + "))",
+ attrs, false);
+
+ return buildGroups(res);
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_LIST_GROUPS", e.toString()));
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_LIST_GROUPS", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ return null;
+ }
+
+ public Enumeration<IGroup> findGroupsByUser(String userDn) throws EUsrGrpException {
+ if (userDn == null) {
+ return null;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ String attrs[] = new String[2];
+
+ attrs[0] = "cn";
+ attrs[1] = "description";
+
+ ldapconn = getConn();
+ LDAPSearchResults res =
+ ldapconn.search(getGroupBaseDN(), LDAPv2.SCOPE_SUB,
+ "(&(objectclass=groupofuniquenames)(uniqueMember=" + LDAPUtil.escapeFilter(userDn) + "))",
+ attrs, false);
+
+ return buildGroups(res);
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_LIST_GROUPS", e.toString()));
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_LIST_GROUPS", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ return null;
+ }
+
+ /**
+ * builds an instance of a Group entry
+ * @throws EUsrGrpException
+ */
+ protected IGroup buildGroup(LDAPEntry entry) throws EUsrGrpException {
+ LDAPAttribute cn = entry.getAttribute("cn");
+ if (cn == null) {
+ throw new EUsrGrpException("Cannot build group. No Attribute cn in LDAP Entry " + entry.getDN());
+ }
+ String groupName = (String) cn.getStringValues().nextElement();
+ IGroup grp = createGroup(this, groupName);
+
+ LDAPAttribute grpDesc = entry.getAttribute("description");
+
+ if (grpDesc != null) {
+ @SuppressWarnings("unchecked")
+ Enumeration<String> en = grpDesc.getStringValues();
+
+ if (en != null && en.hasMoreElements()) {
+ String desc = en.nextElement();
+
+ if (desc != null) {
+ try {
+ grp.set("description", desc);
+ } catch (EBaseException ex) {
+ // later...
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_BUILD_GROUP", ex.toString()));
+ }
+ }
+ }
+ }
+ if (grp.getDescription() == null) {
+ try {
+ grp.set("description", ""); // safety net
+ } catch (EBaseException ex) {
+ // later...
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_BUILD_GROUP", ex.toString()));
+ }
+ }
+
+ // parser member (should use late-materialization)
+ LDAPAttribute attr = entry.getAttribute("uniquemember");
+
+ if (attr == null) {
+ return grp;
+ }
+
+ @SuppressWarnings("unchecked")
+ Enumeration<String> e = attr.getStringValues();
+
+ while (e.hasMoreElements()) {
+ String v = e.nextElement();
+
+ // grp.addMemberName(v);
+ // DOES NOT SUPPORT NESTED GROUPS...
+
+ /* BAD_GROUP_MEMBER message goes to system log
+ * We are testing unique member attribute for
+ * 1. presence of uid string
+ * 2. presence and sequence of equal sign and comma
+ * 3. absence of equal sign between previously found equal sign and comma
+ * 4. absence of non white space characters between uid string and equal sign
+ */
+ int i = -1;
+ int j = -1;
+ if (v == null || v.length() < 3 || (!(v.substring(0, 3)).equalsIgnoreCase("uid")) ||
+ ((i = v.indexOf('=')) < 0) || ((j = v.indexOf(',')) < 0) || i > j ||
+ (v.substring(i + 1, j)).indexOf('=') > -1 || ((v.substring(3, i)).trim()).length() > 0) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_BAD_GROUP_MEMBER", groupName, v));
+ } else {
+ grp.addMemberName(v.substring(v.indexOf('=') + 1, v.indexOf(',')));
+ }
+ }
+
+ return grp;
+ }
+
+ protected IGroup createGroup(IUsrGrp scope, String id) {
+ return new Group(scope, id);
+ }
+
+ /**
+ * Retrieves a group from LDAP
+ * NOTE - this takes just the group name.
+ */
+ public IGroup getGroupFromName(String name) {
+ return getGroup("cn=" + LDAPUtil.escapeRDNValue(name) + "," + getGroupBaseDN());
+ }
+
+ /**
+ * Retrieves a group from LDAP
+ * NOTE - LH This takes a full LDAP DN.
+ */
+ public IGroup getGroup(String groupDN) {
+ if (groupDN == null) {
+ return null;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ // read the group object
+ LDAPSearchResults res = ldapconn.search(groupDN,
+ LDAPConnection.SCOPE_BASE, "(objectclass=*)", null, false);
+ Enumeration<IGroup> e = buildGroups(res);
+
+ if (e == null || e.hasMoreElements() == false)
+ return null;
+ return e.nextElement();
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_GET_GROUP", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ return null;
+ }
+
+ /**
+ * Checks if the given group exists
+ */
+ public boolean isGroupPresent(String name) {
+ if (name == null) {
+ return false;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ LDAPEntry entry = ldapconn.read(name);
+ LDAPAttribute attr = entry.getAttribute(OBJECTCLASS_ATTR);
+
+ if (attr == null) {
+ return false;
+ }
+ @SuppressWarnings("unchecked")
+ Enumeration<String> en = attr.getStringValues();
+
+ for (; en.hasMoreElements();) {
+ String v = en.nextElement();
+
+ if (v.equalsIgnoreCase(GROUP_ATTR_VALUE)) {
+ return true;
+ }
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_IS_GROUP_PRESENT", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ return false;
+ }
+
+ public boolean isMemberOf(String userid, String groupname) {
+ try {
+ IUser user = getUser(userid);
+ if (user != null) {
+ return isMemberOfLdapGroup(user.getUserDN(), groupname);
+ }
+ } catch (Exception e) {
+ /* do nothing */
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the given user is a member of the given group
+ * (now runs an ldap search to find the user, instead of
+ * fetching the entire group entry)
+ */
+ public boolean isMemberOf(IUser id, String name) {
+ if (id == null) {
+ log(ILogger.LL_WARN, "isMemberOf(): id is null");
+ return false;
+ }
+
+ if (name == null) {
+ log(ILogger.LL_WARN, "isMemberOf(): name is null");
+ return false;
+ }
+
+ Debug.trace("UGSubsystem.isMemberOf() using new lookup code");
+ return isMemberOfLdapGroup(id.getUserDN(), name);
+ }
+
+ /**
+ * checks if the given user DN is in the specified group
+ * by running an ldap search for the user in the group
+ */
+ protected boolean isMemberOfLdapGroup(String userid, String groupname) {
+ String basedn = "cn=" + LDAPUtil.escapeRDNValue(groupname) + ",ou=groups," + mBaseDN;
+ LDAPConnection ldapconn = null;
+ boolean founduser = false;
+ try {
+ // the group could potentially have many thousands
+ // of members, (many values of the uniquemember
+ // attribute). So, we don't want to fetch this
+ // list each time. We'll just fetch the CN.
+ String attrs[] = new String[1];
+ attrs[0] = "cn";
+
+ ldapconn = getConn();
+
+ String filter = "(uniquemember=" + LDAPUtil.escapeFilter(userid) + ")";
+ Debug.trace("authorization search base: " + basedn);
+ Debug.trace("authorization search filter: " + filter);
+ LDAPSearchResults res =
+ ldapconn.search(basedn, LDAPv2.SCOPE_BASE,
+ filter,
+ attrs, false);
+ // If the result had at least one entry, we know
+ // that the filter matched, and so the user correctly
+ // authenticated.
+ if (res.hasMoreElements()) {
+ res.nextElement(); // consume the entry
+ founduser = true;
+ }
+ Debug.trace("authorization result: " + founduser);
+ } catch (LDAPException e) {
+ String errMsg =
+ "isMemberOfLdapGroup: could not find group " + groupname + ". Error " + e;
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ errMsg = "isMemberOfLdapGroup: " + "Internal DB is unavailable";
+ }
+ Debug.trace("authorization exception: " + errMsg);
+ // too chatty in system log
+ // log(ILogger.LL_FAILURE, errMsg);
+ } catch (ELdapException e) {
+ String errMsg =
+ "isMemberOfLdapGroup: Could not get connection to internaldb. Error " + e;
+ Debug.trace("authorization exception: " + errMsg);
+ log(ILogger.LL_FAILURE, errMsg);
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ return founduser;
+ }
+
+ /**
+ * Adds a group of identities.
+ */
+ public void addGroup(IGroup group) throws EUsrGrpException {
+ Group grp = (Group) group;
+
+ if (grp == null) {
+ return;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+ String oc[] = { "top", "groupOfUniqueNames" };
+
+ attrs.add(new LDAPAttribute("objectclass", oc));
+ attrs.add(new LDAPAttribute("cn", group.getGroupID()));
+ attrs.add(new LDAPAttribute("description", group.getDescription()));
+ Enumeration<String> e = grp.getMemberNames();
+
+ if (e.hasMoreElements() == true) {
+ LDAPAttribute attrMembers = new LDAPAttribute("uniquemember");
+
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ // DOES NOT SUPPORT NESTED GROUPS...
+ attrMembers.addValue("uid=" + LDAPUtil.escapeRDNValue(name) + "," +
+ getUserBaseDN());
+ }
+ attrs.add(attrMembers);
+ }
+ LDAPEntry entry = new LDAPEntry("cn=" + LDAPUtil.escapeRDNValue(grp.getGroupID()) +
+ "," + getGroupBaseDN(), attrs);
+
+ ldapconn = getConn();
+ ldapconn.add(entry);
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_ADD_GROUP", e.toString()));
+
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_ADD_GROUP_FAIL"));
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_ADD_GROUP", e.toString()));
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_ADD_GROUP_FAIL"));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ }
+
+ /**
+ * Removes a group. Can't remove SUPER_CERT_ADMINS
+ */
+ public void removeGroup(String name) throws EUsrGrpException {
+ if (name == null) {
+ return;
+ } else if (name.equalsIgnoreCase(SUPER_CERT_ADMINS)) {
+ log(ILogger.LL_WARN, "removing Certificate Server Administrators group is not allowed");
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_REMOVE_GROUP_FAIL"));
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ ldapconn.delete("cn=" + LDAPUtil.escapeRDNValue(name) + "," + getGroupBaseDN());
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_REMOVE_GROUP", e.toString()));
+
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_REMOVE_GROUP_FAIL"));
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_REMOVE_GROUP", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ }
+
+ public void modifyGroup(IGroup group) throws EUsrGrpException {
+ Group grp = (Group) group;
+
+ if (grp == null) {
+ return;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ LDAPAttribute attrMembers = new LDAPAttribute("uniquemember");
+ LDAPModificationSet mod = new LDAPModificationSet();
+
+ String desc = grp.getDescription();
+
+ if (desc != null) {
+ mod.add(LDAPModification.REPLACE,
+ new LDAPAttribute("description", desc));
+ }
+
+ Enumeration<String> e = grp.getMemberNames();
+
+ if (e.hasMoreElements() == true) {
+ while (e.hasMoreElements()) {
+ String name = e.nextElement();
+
+ // DOES NOT SUPPORT NESTED GROUPS...
+ attrMembers.addValue("uid=" + LDAPUtil.escapeRDNValue(name) + "," +
+ getUserBaseDN());
+ }
+ mod.add(LDAPModification.REPLACE, attrMembers);
+ } else {
+ if (!grp.getName().equalsIgnoreCase(SUPER_CERT_ADMINS)) {
+ mod.add(LDAPModification.DELETE, attrMembers);
+ } else {
+ // not allowed
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_ILL_GRP_MOD"));
+ }
+ }
+
+ ldapconn = getConn();
+ ldapconn.modify("cn=" + LDAPUtil.escapeRDNValue(grp.getGroupID()) +
+ "," + getGroupBaseDN(), mod);
+ } catch (LDAPException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_MODIFY_GROUP", e.toString()));
+
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_MOD_GROUP_FAIL"));
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_MODIFY_GROUP", e.toString()));
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_MOD_GROUP_FAIL"));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ }
+
+ /**
+ * Evalutes the given context with the attribute
+ * critieria.
+ */
+ public boolean evaluate(String type, IUser id,
+ String op, String value) {
+ if (op.equals("=")) {
+ if (type.equalsIgnoreCase("user")) {
+ if (isMatched(value, id.getName()))
+ return true;
+ }
+ if (type.equalsIgnoreCase("group")) {
+ return isMemberOf(id, value);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Converts an uid attribute to a DN.
+ */
+ protected String convertUIDtoDN(String uid) throws
+ LDAPException {
+ String u = uid;
+
+ if (u == null) {
+ return null;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ LDAPSearchResults res = ldapconn.search(getUserBaseDN(),
+ LDAPv2.SCOPE_SUB, "(uid=" + LDAPUtil.escapeFilter(u) + ")", null, false);
+
+ if (res.hasMoreElements()) {
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+
+ return entry.getDN();
+ }
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_CONVERT_UID", e.toString()));
+ } finally {
+ if (ldapconn != null)
+ returnConn(ldapconn);
+ }
+ return null;
+ }
+
+ /**
+ * Checks if the given DNs are the same after
+ * normalization.
+ */
+ protected boolean isMatched(String dn1, String dn2) {
+ String rdn1[] = LDAPDN.explodeDN(dn1, false);
+ String rdn2[] = LDAPDN.explodeDN(dn2, false);
+ if (rdn1 == null && rdn2 == null) {
+ return true;
+ }
+ if (rdn1 == null || rdn2 == null) {
+ return false;
+ }
+
+ if (rdn1.length == rdn2.length) {
+ for (int j = 0; j < rdn1.length; j++) {
+ if (!rdn1[j].equalsIgnoreCase(rdn2[j])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Converts certificate into string format.
+ * should eventually go into the locator itself
+ */
+ protected String getCertificateStringWithoutVersion(X509Certificate cert) {
+ if (cert == null) {
+ return null;
+ }
+ // note that it did not represent a certificate fully
+ return "-1;" + cert.getSerialNumber().toString() +
+ ";" + cert.getIssuerDN() + ";" + cert.getSubjectDN();
+ }
+
+ public String getCertificateString(X509Certificate cert) {
+ if (cert == null) {
+ return null;
+ }
+
+ // note that it did not represent a certificate fully
+ return cert.getVersion() + ";" + cert.getSerialNumber().toString() +
+ ";" + cert.getIssuerDN() + ";" + cert.getSubjectDN();
+ }
+
+ /**
+ * Retrieves user base dn.
+ */
+ private String getUserBaseDN() {
+ return "ou=People," + mBaseDN;
+ }
+
+ /**
+ * Retrieves group base dn.
+ */
+ private String getGroupBaseDN() {
+ return "ou=Groups," + mBaseDN;
+ }
+
+ protected LDAPConnection getConn() throws ELdapException {
+ if (mLdapConnFactory != null) {
+ LDAPConnection conn = mLdapConnFactory.getConn();
+ if (conn == null) {
+ throw new ELdapException("No Ldap Connection Available");
+ } else {
+ return conn;
+ }
+ }
+
+ throw new ELdapException("Ldap Connection Factory is Unavailable");
+ }
+
+ protected void returnConn(LDAPConnection conn) {
+ if (mLdapConnFactory != null)
+ mLdapConnFactory.returnConn(conn);
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_USRGRP,
+ level, "UGSubsystem: " + msg);
+ }
+
+ public ICertUserLocator getCertUserLocator() {
+ return new ExactMatchCertUserLocator();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/usrgrp/User.java b/base/server/cmscore/src/com/netscape/cmscore/usrgrp/User.java
new file mode 100644
index 000000000..ef09a1ab5
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/usrgrp/User.java
@@ -0,0 +1,250 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.usrgrp;
+
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.usrgrp.IUser;
+import com.netscape.certsrv.usrgrp.IUsrGrp;
+import com.netscape.cms.servlet.admin.UserService;
+
+/**
+ * A class represents a user.
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class User implements IUser {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7407288327775546979L;
+ public static final String ATTR_X509_CERTIFICATES = "userCertificates";
+ @SuppressWarnings("unused")
+ private IUsrGrp mBase;
+ private String mUserid = null;
+ private String mUserDN = null;
+ private String mFullName = null;
+ private String mPassword = null;
+ private String mEmail = null;
+ private String mPhone = null;
+ private String mState = null;
+ private String mCertDN = null;
+ private String mUserType = null;
+ private X509Certificate mx509Certs[] = null;
+ private List<String> tpsProfiles = null;
+
+ private static final Vector<String> mNames = new Vector<String>();
+ static {
+ mNames.addElement(ATTR_NAME);
+ mNames.addElement(ATTR_ID);
+ mNames.addElement(ATTR_FULLNAME);
+ mNames.addElement(ATTR_PASSWORD);
+ mNames.addElement(ATTR_STATE);
+ mNames.addElement(ATTR_EMAIL);
+ // mNames.addElement(ATTR_PHONENUMBER);
+ mNames.addElement(ATTR_X509_CERTIFICATES);
+ mNames.addElement(ATTR_USERTYPE);
+ mNames.addElement(ATTR_TPS_PROFILES);
+ }
+
+ public List<String> getTpsProfiles() {
+ return tpsProfiles;
+ }
+
+ public void setTpsProfiles(List<String> tpsProfiles) {
+ boolean setAll = false;
+ for (String profile: tpsProfiles) {
+ if (profile.equals(UserService.ALL_PROFILES)) {
+ setAll = true;
+ break;
+ }
+ }
+ if (!setAll) {
+ this.tpsProfiles = tpsProfiles;
+ } else {
+ List<String> list = new ArrayList<String>();
+ list.add(UserService.ALL_PROFILES);
+ this.tpsProfiles = list;
+ }
+ }
+
+ /**
+ * Constructs a user.
+ */
+ public User(IUsrGrp base, String userid) {
+ mBase = base;
+ mUserid = userid;
+ }
+
+ /**
+ * Retrieves the name of this identity.
+ */
+ public String getName() {
+ // return mScope.getId() + "://" + mUserid;
+ return mUserid;
+ }
+
+ /**
+ * Retrieves user identifier.
+ */
+ public String getUserID() {
+ return mUserid;
+ }
+
+ /**
+ * Retrieves user full name.
+ */
+ public String getFullName() {
+ return mFullName;
+ }
+
+ public void setFullName(String name) {
+ mFullName = name;
+ }
+
+ /**
+ * Retrieves user ldap dn
+ */
+ public String getUserDN() {
+ return mUserDN;
+ }
+
+ public void setUserDN(String userdn) {
+ mUserDN = userdn;
+ }
+
+ public String getUserType() {
+ return mUserType;
+ }
+
+ public void setUserType(String userType) {
+ mUserType = userType;
+ }
+
+ /**
+ * Retrieves user password.
+ */
+ public String getPassword() {
+ return mPassword;
+ }
+
+ public void setPassword(String password) {
+ mPassword = password;
+ }
+
+ public String getEmail() {
+ return mEmail;
+ }
+
+ public void setEmail(String email) {
+ mEmail = email;
+ }
+
+ public String getPhone() {
+ return mPhone;
+ }
+
+ public String getState() {
+ return mState;
+ }
+
+ public void setPhone(String phone) {
+ mPhone = phone;
+ }
+
+ public void setState(String state) {
+ mState = state;
+ }
+
+ public X509Certificate[] getX509Certificates() {
+ return mx509Certs;
+ }
+
+ public void setX509Certificates(X509Certificate certs[]) {
+ mx509Certs = certs;
+ }
+
+ public String getCertDN() {
+ return mCertDN;
+ }
+
+ public void setCertDN(String dn) {
+ mCertDN = dn;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void set(String name, Object object) throws EBaseException {
+ if (name.equals(ATTR_NAME)) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ } else if (name.equals(ATTR_ID)) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ } else if (name.equals(ATTR_FULLNAME)) {
+ setFullName((String) object);
+ } else if (name.equals(ATTR_STATE)) {
+ setState((String) object);
+ } else if (name.equals(ATTR_PASSWORD)) {
+ setPassword((String) object);
+ } else if (name.equals(ATTR_X509_CERTIFICATES)) {
+ setX509Certificates((X509Certificate[]) object);
+ } else if (name.equals(ATTR_USERTYPE)) {
+ setUserType((String) object);
+ } else if (name.equals(ATTR_TPS_PROFILES)) {
+ setTpsProfiles((List<String>) object);
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+ }
+
+ public Object get(String name) throws EBaseException {
+ if (name.equals(ATTR_NAME)) {
+ return getName();
+ } else if (name.equals(ATTR_ID)) {
+ return getUserID();
+ } else if (name.equals(ATTR_STATE)) {
+ return getState();
+ } else if (name.equals(ATTR_FULLNAME)) {
+ return getFullName();
+ } else if (name.equals(ATTR_PASSWORD)) {
+ return getPassword();
+ } else if (name.equals(ATTR_X509_CERTIFICATES)) {
+ return getX509Certificates();
+ } else if (name.equals(ATTR_USERTYPE)) {
+ return getUserType();
+ } else if (name.equals(ATTR_TPS_PROFILES)) {
+ return getTpsProfiles();
+ } else {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+ }
+
+ public void delete(String name) throws EBaseException {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
+ }
+
+ public Enumeration<String> getElements() {
+ return mNames.elements();
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/util/Assert.java b/base/server/cmscore/src/com/netscape/cmscore/util/Assert.java
new file mode 100644
index 000000000..246599290
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/util/Assert.java
@@ -0,0 +1,48 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.util;
+
+public class Assert {
+ public static final boolean ON = true;
+
+ public static void Assertion(boolean e) {
+ if (!e) {
+ throw new AssertionException("assertion");
+ }
+ }
+
+ public static void NotReached(String msg) {
+ throw new AssertionException("not reached: " + msg);
+ }
+
+ public static void NotYetImplemented(String msg) {
+ throw new AssertionException("not yet implemented: " + msg);
+ }
+
+ public static void PreCondition(boolean e) {
+ if (!e) {
+ throw new AssertionException("precondition");
+ }
+ }
+
+ public static void PostCondition(boolean e) {
+ if (!e) {
+ throw new AssertionException("precondition");
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/util/AssertionException.java b/base/server/cmscore/src/com/netscape/cmscore/util/AssertionException.java
new file mode 100644
index 000000000..46b3f32da
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/util/AssertionException.java
@@ -0,0 +1,36 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.util;
+
+/**
+ * Assertion exceptions are thrown when assertion code is invoked
+ * and fails to operate properly.
+ */
+public class AssertionException extends Error {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5647721098177211353L;
+
+ public AssertionException() {
+ }
+
+ public AssertionException(String msg) {
+ super(msg);
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/util/Debug.java b/base/server/cmscore/src/com/netscape/cmscore/util/Debug.java
new file mode 100644
index 000000000..bd10a493c
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/util/Debug.java
@@ -0,0 +1,385 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.util;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.cmsutil.util.Utils;
+
+public class Debug
+ implements ISubsystem {
+
+ private static Debug mInstance = new Debug();
+ private static boolean mShowCaller = false;
+
+ /* This dateformatter is used to put the date on each
+ debug line. But the DateFormatter is not thread safe,
+ so I create a thread-local DateFormatter for each thread
+ */
+ private static String DATE_PATTERN = "dd/MMM/yyyy:HH:mm:ss";
+ private static ThreadLocal<SimpleDateFormat> mFormatObject = new ThreadLocal<SimpleDateFormat>() {
+ protected synchronized SimpleDateFormat initialValue() {
+ return new SimpleDateFormat(DATE_PATTERN);
+ }
+ };
+
+ /* the dateformatter should be accessed with this function */
+ private static SimpleDateFormat getDateFormatter() {
+ return mFormatObject.get();
+ }
+
+ public static final boolean ON = false;
+ public static final int OBNOXIOUS = 10;
+ public static final int VERBOSE = 5;
+ public static final int INFORM = 1;
+
+ // the difference between this and 'ON' is that this is always
+ // guaranteed to log to 'mOut', whereas other parts of the server
+ // may do:
+ // if (Debug.ON) {
+ // System.out.println("..");
+ // }
+ // I want to make sure that any Debug.trace() is not logged to
+ // System.out if the server is running under watchdog
+
+ private static boolean TRACE_ON = false;
+
+ private static int mDebugLevel = VERBOSE;
+
+ private static PrintStream mOut = null;
+ private static Hashtable<String, String> mHK = null;
+
+ static {
+ if (TRACE_ON == true) {
+ mOut = System.out;
+ }
+ }
+
+ public static void trace(int level, String t) {
+ trace(level, t, null, true);
+ }
+
+ /**
+ * Output a debug message at the output stream sepcified in the init()
+ * method. This method is very lightweight if debugging is turned off, since
+ * it will return immediately. However, the caller should be aware that
+ * if the argument to Debug.trace() is an object whose toString() is
+ * expensive, that this toString() will still be called in any case.
+ * In such a case, it is wise to wrap the Debug.trace like this:
+ *
+ * <pre>
+ * if (Debug.on()) {
+ * Debug.trace(&quot;obj is: &quot; + obj);
+ * }
+ * </pre>
+ *
+ * @param level the message level. If this is >= than the currently set
+ * level (set with setLevel() ), the message is printed
+ * @param t the message to print
+ * @param ignoreStack when walking the stack to determine the
+ * location of the method that called the trace() method,
+ * ignore any classes with this string in. Can be null
+ * @param printCaller if true, (and if static mShowCaller is true)
+ * dump caller information in this format:
+ * (source-file:line) methodname():
+ */
+ public static void trace(int level, String t, String ignoreStack, boolean printCaller) {
+ String callerinfo = "";
+ if (!TRACE_ON)
+ return;
+ if (level >= mDebugLevel) {
+ if (mShowCaller && printCaller) {
+ String method = "";
+ String fileAndLine = "";
+
+ try {
+ Throwable tr = new Throwable();
+ StackTraceElement ste[] = tr.getStackTrace();
+ int i = 0;
+ while ((i < ste.length) &&
+ (ste[i].getMethodName().toLowerCase().indexOf("debug") > -1) ||
+ (ste[i].getMethodName().toLowerCase().indexOf("hashkey") > -1) ||
+ (ste[i].getClassName().toLowerCase().indexOf("propconfigstore") > -1) ||
+ (ste[i].getClassName().toLowerCase().indexOf("argblock") > -1) ||
+ (ste[i].getClassName().toLowerCase().indexOf("debug") > -1) ||
+ (ste[i].getMethodName().toLowerCase().indexOf("trace") > -1))
+ i++;
+
+ if (i < ste.length) {
+ fileAndLine = ste[i].getFileName() + ":" +
+ ste[i].getLineNumber();
+ method = ste[i].getMethodName() + "()";
+ }
+
+ callerinfo = fileAndLine + ":" + method + " ";
+ } catch (Exception f) {
+ }
+ }
+
+ outputTraceMessage(callerinfo + t);
+ }
+ }
+
+ private static void outputTraceMessage(String t) {
+ if (!TRACE_ON)
+ return;
+ SimpleDateFormat d = getDateFormatter();
+ if (mOut != null && d != null) {
+ mOut.println("[" + d.format(new Date()) + "][" + Thread.currentThread().getName() + "]: " + t);
+ mOut.flush();
+ }
+ }
+
+ private static boolean hkdotype(String type) {
+ if (mHK != null && mHK.get(type) != null) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static void traceHashKey(String type, String key) {
+ if (hkdotype(type)) {
+ trace("GET r=" + type + ",k=" + key);
+ }
+ }
+
+ public static void traceHashKey(String type, String key, String val) {
+ if (hkdotype(type)) {
+ trace("GET r=" + type + ",k=" + key + ",v=" + val);
+ }
+ }
+
+ public static void traceHashKey(String type, String key, String val, String def) {
+ if (hkdotype(type)) {
+ trace("GET r=" + type + ",k=" +
+ key + ",v=" + val + ",d=" + def);
+ }
+ }
+
+ public static void putHashKey(String type, String key, String value) {
+ if (hkdotype(type)) {
+ outputTraceMessage("PUT r=" + type + ",k=" + key + ",v=" + value);
+ }
+ }
+
+ public static void trace(String t) {
+ trace(VERBOSE, t);
+ }
+
+ public static void print(int level, String t) {
+ if (!TRACE_ON)
+ return;
+ if (mOut != null) {
+ if (level >= mDebugLevel)
+ mOut.print(t);
+ }
+ }
+
+ public static void print(String t) {
+ print(VERBOSE, t);
+ }
+
+ private static void printNybble(byte b) {
+ if (mOut == null)
+ return;
+ if (b < 10)
+ mOut.write('0' + b);
+ else
+ mOut.write('a' + b - 10);
+ }
+
+ /**
+ * If tracing enabled, dump a byte array to debugging printstream
+ * as hex, colon-seperated bytes, 16 bytes to a line
+ */
+ public static void print(byte[] b) {
+ if (!TRACE_ON)
+ return;
+ if (mOut == null)
+ return;
+
+ for (int i = 0; i < b.length; i++) {
+ printNybble((byte) ((b[i] & 0xf0) >> 4));
+ printNybble((byte) (b[i] & 0x0f));
+ mOut.print(" ");
+ if (((i % 16) == 15) && i != b.length)
+ mOut.println("");
+ }
+ mOut.println("");
+ mOut.flush();
+ }
+
+ /**
+ * Print the current stack trace to the debug printstream
+ */
+ public static void printStackTrace() {
+ if (!TRACE_ON)
+ return;
+ Exception e = new Exception("Debug");
+
+ printStackTrace(e);
+ }
+
+ /**
+ * Print the stack trace of the named exception
+ * to the debug printstream
+ */
+ public static void printStackTrace(Throwable e) {
+ if (!TRACE_ON)
+ return;
+ if (mOut == null)
+ return;
+
+ e.printStackTrace(mOut);
+ }
+
+ /**
+ * Set the current debugging level. You can use:
+ *
+ * <pre>
+ * OBNOXIOUS = 10
+ * VERBOSE = 5
+ * INFORM = 1
+ * </pre>
+ *
+ * Or another value
+ */
+
+ public static void setLevel(int level) {
+ mDebugLevel = level;
+ }
+
+ public static int getLevel(int level) {
+ return mDebugLevel;
+ }
+
+ /**
+ * Test if debugging is on. Do NOT write to System.out in your debug code
+ */
+ public static boolean on() {
+ return TRACE_ON;
+ }
+
+ /* ISubsystem methods: */
+
+ public static String ID = "debug";
+ private static IConfigStore mConfig = null;
+
+ public String getId() {
+ return ID;
+ }
+
+ public void setId(String id) {
+ ID = id;
+ }
+
+ private static final String PROP_ENABLED = "enabled";
+ private static final String PROP_FILENAME = "filename";
+ private static final String PROP_HASHKEYS = "hashkeytypes";
+ private static final String PROP_SHOWCALLER = "showcaller";
+ private static final String PROP_LEVEL = "level";
+ private static final String PROP_APPEND = "append";
+
+ /**
+ * Debug subsystem initialization. This subsystem is usually
+ * given the following parameters:
+ *
+ * <pre>
+ * debug.enabled : (true|false) default false
+ * debug.filename : can be a pathname, or STDOUT
+ * debug.hashkeytypes: comma-separated list of hashkey types
+ * possible values: "CS.cfg"
+ * debug.showcaller: (true|false) default false [show caller method name for Debug.trace()]
+ * </pre>
+ */
+ public void init(ISubsystem owner, IConfigStore config) {
+ mConfig = config;
+ String filename = null;
+ String hashkeytypes = null;
+ boolean append = true;
+
+ try {
+ TRACE_ON = mConfig.getBoolean(PROP_ENABLED, false);
+ if (TRACE_ON) {
+ filename = mConfig.getString(PROP_FILENAME, null);
+ if (filename == null) {
+ TRACE_ON = false;
+ }
+ hashkeytypes = mConfig.getString(PROP_HASHKEYS, null);
+ mShowCaller = mConfig.getBoolean(PROP_SHOWCALLER, false);
+ append = mConfig.getBoolean(PROP_APPEND, true);
+ }
+ if (TRACE_ON) {
+ if (filename.equals("STDOUT")) {
+ mOut = System.out;
+ } else {
+ if (!Utils.isNT()) {
+ // Always insure that a physical file exists!
+ Utils.exec("touch " + filename);
+ Utils.exec("chmod 00640 " + filename);
+ }
+ OutputStream os = new FileOutputStream(filename, append);
+ mOut = new PrintStream(os, true); /* true == autoflush */
+ }
+ if (hashkeytypes != null) {
+ StringTokenizer st = new StringTokenizer(hashkeytypes,
+ ",", false);
+ mHK = new Hashtable<String, String>();
+ while (st.hasMoreElements()) {
+ String hkr = st.nextToken();
+ mHK.put(hkr, "true");
+ }
+ }
+ }
+ outputTraceMessage("============================================");
+ outputTraceMessage("===== DEBUG SUBSYSTEM INITIALIZED =======");
+ outputTraceMessage("============================================");
+ int level = mConfig.getInteger(PROP_LEVEL, VERBOSE);
+ setLevel(level);
+ } catch (Exception e) {
+ // Don't do anything. Logging is not set up yet, and
+ // we can't write to STDOUT.
+ }
+ }
+
+ public void startup() {
+ }
+
+ public void shutdown() {
+ }
+
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ // for singleton
+
+ public static Debug getInstance() {
+ return mInstance;
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/util/ExceptionFormatter.java b/base/server/cmscore/src/com/netscape/cmscore/util/ExceptionFormatter.java
new file mode 100644
index 000000000..14351cd7b
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/util/ExceptionFormatter.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.util;
+
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintWriter;
+
+public class ExceptionFormatter {
+
+ /**
+ * Routines for pretty-printing java exceptions
+ * prints okay in a single-line.
+ */
+ /*
+ * Take an exception stacktrace, and reformat it so that is
+ * prints okay in a single-line.
+ */
+
+ public static String getStackTraceAsString(Throwable e) {
+ String returnvalue = e.toString();
+
+ PipedOutputStream po = new PipedOutputStream();
+ try (PipedInputStream pi = new PipedInputStream(po)) {
+
+ PrintWriter ps = new PrintWriter(po);
+ e.printStackTrace(ps);
+ ps.flush();
+
+ int avail = pi.available();
+ byte[] b = new byte[avail];
+
+ pi.read(b, 0, avail);
+ returnvalue = new String(b);
+ } catch (Exception ex) {
+ }
+ return returnvalue;
+ }
+
+ /* test code below */
+
+ public static void test()
+ throws TestException {
+ throw new TestException("** testexception **");
+ }
+
+ public static void main(String[] argv) {
+ try {
+ test();
+ } catch (Exception e) {
+ System.out.println("\n------- Exception.toString() ------");
+ System.out.println(e.toString());
+ System.out.println("\n------- Exception.printStackTrace() ------");
+ e.printStackTrace();
+ System.out.println("\n------- ExceptionFormatter.format() ------");
+ System.out.println(ExceptionFormatter.getStackTraceAsString(e));
+ }
+ }
+
+}
+
+class TestException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5737463439434110385L;
+
+ public TestException() {
+ }
+
+ public TestException(String s) {
+ super(s);
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/util/FileAsString.java b/base/server/cmscore/src/com/netscape/cmscore/util/FileAsString.java
new file mode 100644
index 000000000..ea8fb796d
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/util/FileAsString.java
@@ -0,0 +1,118 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.util;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+public class FileAsString {
+
+ protected String mFilename;
+ protected long mLastRead = 0;
+
+ private String fileContents = null;
+ private Object userObject = null;
+
+ /**
+ * This class enables you to get treat a file as a string
+ * If the file changes underneath you, it will automatically
+ * be read
+ */
+ public FileAsString(String filename) throws IOException {
+ mFilename = filename;
+ readFile();
+ }
+
+ public boolean fileHasChanged() throws IOException {
+ File file = new File(mFilename);
+ long lastmodified = file.lastModified();
+
+ return (lastmodified != mLastRead);
+ }
+
+ private void readFile()
+ throws IOException {
+ BufferedReader br = createBufferedReader(mFilename);
+ StringBuffer buf = new StringBuffer();
+ int bytesread = 0;
+ try {
+ do {
+ char cbuf[] = new char[16];
+
+ bytesread = br.read(cbuf, 0, cbuf.length);
+ if (bytesread > 0) {
+ buf.append(cbuf, 0, bytesread);
+ }
+ } while (bytesread != -1);
+ } finally {
+ if (br != null)
+ br.close();
+ }
+
+ fileContents = new String(buf);
+ }
+
+ private BufferedReader createBufferedReader(String filename)
+ throws IOException {
+ Debug.trace("createBufferedReader(filename=" + filename + ")");
+ BufferedReader br = null;
+ FileReader fr = null;
+
+ try {
+ File file = new File(filename);
+
+ mLastRead = file.lastModified();
+ fr = new FileReader(file);
+ br = new BufferedReader(fr);
+ mFilename = filename;
+ } catch (IOException e) {
+ throw e;
+ }
+ return br;
+ }
+
+ public String getAsString()
+ throws IOException {
+ if (fileHasChanged()) {
+ readFile();
+ }
+ return fileContents;
+ }
+
+ public Object getUserObject() {
+ try {
+ if (fileHasChanged()) {
+ userObject = null;
+ }
+ } catch (Exception e) {
+ userObject = null;
+ }
+ return userObject;
+ }
+
+ public void setUserObject(Object x) {
+ userObject = x;
+ }
+
+ public String getFilename() {
+ return mFilename;
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/util/FileDialogFilter.java b/base/server/cmscore/src/com/netscape/cmscore/util/FileDialogFilter.java
new file mode 100644
index 000000000..c62d7b8b5
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/util/FileDialogFilter.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.util;
+
+import java.io.File;
+import java.io.FilenameFilter;
+
+/**
+ * checks the filename and directory with the specified filter
+ * checks with multiple "*".
+ * the filter has to start with a '*' character.
+ * this to keep the search the same as in the motif version
+ * <P>
+ * Copied verbatium from sun.awt.tiny.TinyFileDialogPeer. Used by RollingLogFile expiration code
+ * <P>
+ *
+ * @author mikep
+ * @version $Revision$, $Date$
+ */
+public class FileDialogFilter implements FilenameFilter {
+
+ String filter;
+
+ public FileDialogFilter(String f) {
+ filter = f;
+ }
+
+ public String toString() {
+ return filter;
+ }
+
+ /**
+ * return true if match
+ */
+ public boolean accept(File dir, String fileName) {
+
+ File f = new File(dir, fileName);
+
+ if (f.isDirectory()) {
+ return true;
+ } else {
+ return searchPattern(fileName, filter);
+ }
+ }
+
+ /**
+ * start searching
+ */
+ boolean searchPattern(String fileName, String filter) {
+ int filterCursor = 0;
+
+ int filterChar = filter.charAt(filterCursor);
+
+ if (filterCursor == 0 && filterChar != '*') {
+ return false;
+ }
+ String ls = filter.substring(filterCursor + 1);
+
+ return handleStar(fileName, ls);
+ }
+
+ /**
+ * call this method when character was an *
+ */
+ boolean handleStar(String fileName, String filter) {
+ int ftLen = filter.length();
+ int flLen = fileName.length();
+ char ftChar;
+ char flChar;
+ int ftCur = 0;
+ int flCur = 0;
+ int c = 0;
+
+ if (ftLen == 0) {
+ return true;
+ }
+
+ while (c < flLen) {
+ ftChar = filter.charAt(ftCur);
+
+ if (ftChar == '*') {
+ String ls = filter.substring(ftCur + 1);
+ String fs = fileName.substring(flCur);
+
+ if (handleStar(fs, ls)) {
+ return true;
+ }
+ c++;
+ flCur = c;
+ ftCur = 0;
+ continue;
+ }
+ flChar = fileName.charAt(flCur);
+
+ if (ftChar == flChar) {
+ ftCur++;
+ flCur++;
+
+ if (flCur == flLen && ftCur == ftLen) {
+ return true;
+ }
+
+ if (flCur < flLen && ftCur == ftLen) {
+ return false;
+ }
+
+ if (flCur == flLen) {
+ c = flLen;
+ }
+ } else {
+ c++;
+ flCur = c;
+ ftCur = 0;
+ if (c == flLen) {
+ return false;
+ }
+ }
+ }
+
+ for (int i = ftCur; i < ftLen; i++) {
+ ftChar = filter.charAt(i);
+ if (ftChar != '*') {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/util/PFXUtils.java b/base/server/cmscore/src/com/netscape/cmscore/util/PFXUtils.java
new file mode 100644
index 000000000..ed0e6d641
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/util/PFXUtils.java
@@ -0,0 +1,167 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.util;
+
+import java.io.ByteArrayOutputStream;
+import java.security.MessageDigest;
+import java.security.cert.X509Certificate;
+
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.ASN1Value;
+import org.mozilla.jss.asn1.BMPString;
+import org.mozilla.jss.asn1.OCTET_STRING;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.asn1.SET;
+import org.mozilla.jss.crypto.PBEAlgorithm;
+import org.mozilla.jss.pkcs12.AuthenticatedSafes;
+import org.mozilla.jss.pkcs12.CertBag;
+import org.mozilla.jss.pkcs12.PFX;
+import org.mozilla.jss.pkcs12.PasswordConverter;
+import org.mozilla.jss.pkcs12.SafeBag;
+import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo;
+import org.mozilla.jss.pkix.primitive.PrivateKeyInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+
+public class PFXUtils {
+
+ /**
+ * Creates a PKCS12 package.
+ */
+ public static byte[] createPFX(String pwd, X509Certificate x509cert,
+ byte privateKeyInfo[]) throws EBaseException {
+ try {
+ // add certificate
+ SEQUENCE encSafeContents = new SEQUENCE();
+ ASN1Value cert = new OCTET_STRING(
+ x509cert.getEncoded());
+ byte localKeyId[] = createLocalKeyId(x509cert);
+ SET certAttrs = createBagAttrs(
+ x509cert.getSubjectDN().toString(), localKeyId);
+ // attributes: user friendly name, Local Key ID
+ SafeBag certBag = new SafeBag(SafeBag.CERT_BAG,
+ new CertBag(CertBag.X509_CERT_TYPE, cert),
+ certAttrs);
+
+ encSafeContents.addElement(certBag);
+
+ // add key
+ org.mozilla.jss.util.Password pass = new
+ org.mozilla.jss.util.Password(
+ pwd.toCharArray());
+
+ SEQUENCE safeContents = new SEQUENCE();
+ PasswordConverter passConverter = new
+ PasswordConverter();
+
+ // XXX - should generate salt
+ byte salt[] = { 0x01, 0x01, 0x01, 0x01 };
+ PrivateKeyInfo pki = (PrivateKeyInfo)
+ ASN1Util.decode(PrivateKeyInfo.getTemplate(),
+ privateKeyInfo);
+ ASN1Value key = EncryptedPrivateKeyInfo.createPBE(
+ PBEAlgorithm.PBE_SHA1_DES3_CBC,
+ pass, salt, 1, passConverter, pki);
+ SET keyAttrs = createBagAttrs(
+ x509cert.getSubjectDN().toString(),
+ localKeyId);
+ SafeBag keyBag = new SafeBag(
+ SafeBag.PKCS8_SHROUDED_KEY_BAG, key,
+ keyAttrs); // ??
+
+ safeContents.addElement(keyBag);
+
+ // build contents
+ AuthenticatedSafes authSafes = new
+ AuthenticatedSafes();
+
+ authSafes.addSafeContents(safeContents);
+ authSafes.addSafeContents(encSafeContents);
+
+ // authSafes.addEncryptedSafeContents(
+ // authSafes.DEFAULT_KEY_GEN_ALG,
+ // pass, null, 1,
+ // encSafeContents);
+ PFX pfx = new PFX(authSafes);
+
+ pfx.computeMacData(pass, null, 5); // ??
+ ByteArrayOutputStream fos = new
+ ByteArrayOutputStream();
+
+ pfx.encode(fos);
+ pass.clear();
+
+ // put final PKCS12 into volatile request
+ return fos.toByteArray();
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Failed to create PKCS12 - " + e.toString()));
+ }
+ }
+
+ /**
+ * Creates local key identifier.
+ */
+ public static byte[] createLocalKeyId(X509Certificate cert)
+ throws EBaseException {
+ try {
+ byte certDer[] = cert.getEncoded();
+ MessageDigest md = MessageDigest.getInstance("SHA");
+
+ md.update(certDer);
+ return md.digest();
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Failed to create Key ID - " + e.toString()));
+ }
+ }
+
+ /**
+ * Creates bag attributes.
+ */
+ public static SET createBagAttrs(String nickName, byte localKeyId[])
+ throws EBaseException {
+ try {
+ SET attrs = new SET();
+ SEQUENCE nickNameAttr = new SEQUENCE();
+
+ nickNameAttr.addElement(SafeBag.FRIENDLY_NAME);
+ SET nickNameSet = new SET();
+
+ nickNameSet.addElement(new BMPString(nickName));
+ nickNameAttr.addElement(nickNameSet);
+ attrs.addElement(nickNameAttr);
+ SEQUENCE localKeyAttr = new SEQUENCE();
+
+ localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID);
+ SET localKeySet = new SET();
+
+ localKeySet.addElement(new OCTET_STRING(localKeyId));
+ localKeyAttr.addElement(localKeySet);
+ attrs.addElement(localKeyAttr);
+ return attrs;
+ } catch (Exception e) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Failed to create Key Bag - " + e.toString()));
+ }
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/util/ProfileSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/util/ProfileSubsystem.java
new file mode 100644
index 000000000..296aadea5
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/util/ProfileSubsystem.java
@@ -0,0 +1,308 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.util;
+
+import java.awt.Frame;
+import java.awt.TextArea;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.Vector;
+
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTable;
+import javax.swing.JTextArea;
+import javax.swing.table.AbstractTableModel;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+
+/**
+ * A class represents a internal subsystem. This subsystem
+ * can be loaded into cert server kernel to perform
+ * run time system profiling.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class ProfileSubsystem extends Frame implements ISubsystem, Runnable {
+
+ private static final long serialVersionUID = -7411549542009497317L;
+ private String mId = null;
+ private Thread mMonitoring = new Thread(this);
+ private TextArea mTextArea = null;
+ private JScrollPane mThreads = null;
+ private JTable mThreadTable = null;
+ private ThreadTableModel mThreadModel = null;
+
+ /**
+ * Constructs a certificate server.
+ */
+ public ProfileSubsystem() {
+ super();
+ }
+
+ /**
+ * Retrieves subsystem identifier.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ /**
+ * Initializes this subsystem with the given
+ * configuration store.
+ * It first initializes resident subsystems,
+ * and it loads and initializes loadable
+ * subsystem specified in the configuration
+ * store.
+ * <P>
+ * Note that individual subsystem should be initialized in a separated thread if it has dependency on the
+ * initialization of other subsystems.
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration store
+ */
+ public synchronized void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ JTabbedPane tabPane = new JTabbedPane();
+
+ // general panel
+ JPanel pane = new JPanel();
+
+ mTextArea = new TextArea();
+ // mTextArea.setSize(500, 180);
+ //mGC = new JButton("GC");
+ // pane.setLayout(new GridLayout(2, 1));
+ pane.add(mTextArea);
+ // pane.add(mGC);
+ mTextArea.setEditable(false);
+ tabPane.addTab("General", mTextArea);
+ tabPane.setSelectedIndex(0);
+
+ // thread panel
+ mThreadModel = new ThreadTableModel();
+ updateThreadPanel();
+ mThreadTable = new JTable(mThreadModel);
+ // table.setEditable(false);
+ mThreads = new JScrollPane(mThreadTable);
+ tabPane.addTab("Threads", mThreads);
+
+ mThreadTable.addMouseListener(new ThreadTableEvent(mThreadTable));
+
+ add(tabPane);
+ setSize(500, 200);
+ setVisible(true);
+ mMonitoring.start();
+ }
+
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Stops this system.
+ */
+ public synchronized void shutdown() {
+ }
+
+ /*
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return null;
+ }
+
+ public synchronized void updateGeneralPanel() {
+ Runtime.getRuntime().gc();
+ String text =
+ "JDK VM Information " + "\n" +
+ "Total Memory: " +
+ Runtime.getRuntime().totalMemory() + "\n" +
+ "Used Memory: " +
+ (Runtime.getRuntime().totalMemory() -
+ Runtime.getRuntime().freeMemory()) + "\n" +
+ "Free Memory: " +
+ Runtime.getRuntime().freeMemory() + "\n" +
+ "Number of threads: " +
+ Thread.activeCount() + "\n";
+
+ mTextArea.setText(text);
+ }
+
+ public synchronized void updateThreadPanel() {
+ Thread currentThread = Thread.currentThread();
+ Vector<Vector<String>> data = new Vector<Vector<String>>();
+ Thread threads[] = new Thread[100];
+ int numThreads = Thread.enumerate(threads);
+
+ for (int i = 0; i < numThreads; i++) {
+ Vector<String> row = new Vector<String>();
+
+ row.addElement(threads[i].getName());
+ row.addElement(threads[i].getThreadGroup().getName());
+ row.addElement(Integer.toString(threads[i].getPriority()));
+ if (currentThread.getName().equals(threads[i].getName())) {
+ row.addElement("true");
+ } else {
+ row.addElement("false");
+ }
+ row.addElement(Boolean.toString(threads[i].isInterrupted()));
+ row.addElement(Boolean.toString(threads[i].isDaemon()));
+ data.addElement(row);
+ }
+
+ Vector<String> colNames = new Vector<String>();
+
+ colNames.addElement("Name");
+ colNames.addElement("Group");
+ colNames.addElement("Priority");
+ colNames.addElement("isCurrent");
+ colNames.addElement("isInterrupted");
+ colNames.addElement("isDaemon");
+
+ mThreadModel.setInfo(data, colNames);
+ if (mThreadTable != null) {
+ mThreadTable.setModel(mThreadModel);
+ mThreadTable.updateUI();
+ }
+ }
+
+ public void run() {
+ while (true) {
+ // To get exact memory statistics
+ try {
+ updateGeneralPanel();
+ updateThreadPanel();
+ // update every second
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+}
+
+class ThreadTableModel extends AbstractTableModel {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6977965542104110870L;
+ Vector<Vector<String>> rowData;
+ Vector<String> columnNames;
+
+ public ThreadTableModel() {
+ }
+
+ public void setInfo(Vector<Vector<String>> _rowData, Vector<String> _columnNames) {
+ rowData = _rowData;
+ columnNames = _columnNames;
+ }
+
+ public String getColumnName(int column) {
+ return columnNames.elementAt(column).toString();
+ }
+
+ public int getRowCount() {
+ return rowData.size();
+ }
+
+ public int getColumnCount() {
+ return columnNames.size();
+ }
+
+ public String getValueAt(int row, int column) {
+ return rowData.elementAt(row).elementAt(column);
+ }
+
+ public boolean isCellEditable(int row, int column) {
+ return false;
+ }
+
+ public void setValueAt(String value, int row, int column) {
+ rowData.elementAt(row).setElementAt(value, column);
+ fireTableCellUpdated(row, column);
+ }
+}
+
+class ThreadTableEvent extends MouseAdapter {
+
+ private JTable mThreadTable = null;
+
+ public ThreadTableEvent(JTable table) {
+ mThreadTable = table;
+ }
+
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount() == 2) {
+ int row = mThreadTable.getSelectedRow();
+
+ if (row != -1) {
+ String name = (String) mThreadTable.getValueAt(row, 0);
+ JDialog dialog = new JDialog();
+ JTextArea field = new JTextArea();
+ JScrollPane pane = new JScrollPane(field);
+
+ field.setEditable(false);
+
+ // get stack trace
+ Thread threads[] = new Thread[100];
+ int numThreads = Thread.enumerate(threads);
+
+ ByteArrayOutputStream outArray = new ByteArrayOutputStream();
+
+ for (int i = 0; i < numThreads; i++) {
+ if (!threads[i].getName().equals(name))
+ continue;
+ PrintStream err = System.err;
+
+ System.setErr(new PrintStream(outArray));
+ //TODO remove. This was being called on the array object
+ //But you can only dump stack on the current thread
+ Thread.dumpStack();
+
+ System.setErr(err);
+ }
+
+ String str = outArray.toString();
+
+ field.setText(str);
+ dialog.setTitle(name);
+ dialog.setSize(500, 400);
+ dialog.setVisible(true);
+
+ dialog.setContentPane(pane);
+ dialog.setVisible(true);
+ }
+ }
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/util/StatsSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/util/StatsSubsystem.java
new file mode 100644
index 000000000..cfac63f21
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/util/StatsSubsystem.java
@@ -0,0 +1,195 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.util;
+
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.util.IStatsSubsystem;
+import com.netscape.certsrv.util.StatsEvent;
+
+/**
+ * A class represents a internal subsystem. This subsystem
+ * can be loaded into cert server kernel to perform
+ * statistics collection.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class StatsSubsystem implements IStatsSubsystem {
+ private String mId = null;
+ private StatsEvent mAllTrans = new StatsEvent(null);
+ private Date mStartTime = new Date();
+ private Hashtable<String, Vector<StatsMilestone>> mHashtable = new Hashtable<String, Vector<StatsMilestone>>();
+
+ /**
+ * Constructs a certificate server.
+ */
+ public StatsSubsystem() {
+ super();
+ }
+
+ /**
+ * Retrieves subsystem identifier.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ /**
+ * Initializes this subsystem with the given
+ * configuration store.
+ * It first initializes resident subsystems,
+ * and it loads and initializes loadable
+ * subsystem specified in the configuration
+ * store.
+ * <P>
+ * Note that individual subsystem should be initialized in a separated thread if it has dependency on the
+ * initialization of other subsystems.
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration store
+ */
+ public synchronized void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ }
+
+ public Date getStartTime() {
+ return mStartTime;
+ }
+
+ public void startTiming(String id) {
+ startTiming(id, false /* not the main */);
+ }
+
+ public void startTiming(String id, boolean mainAction) {
+ Thread t = Thread.currentThread();
+ Vector<StatsMilestone> milestones = null;
+ if (mHashtable.containsKey(t.toString())) {
+ milestones = mHashtable.get(t.toString());
+ } else {
+ milestones = new Vector<StatsMilestone>();
+ mHashtable.put(t.toString(), milestones);
+ }
+ long startTime = CMS.getCurrentDate().getTime();
+ StatsEvent currentST = null;
+ for (int i = 0; i < milestones.size(); i++) {
+ StatsMilestone se = milestones.elementAt(i);
+ if (currentST == null) {
+ currentST = mAllTrans.getSubEvent(se.getId());
+ } else {
+ currentST = currentST.getSubEvent(se.getId());
+ }
+ }
+ if (currentST == null) {
+ if (!mainAction) {
+ return; /* ignore none main action */
+ }
+ currentST = mAllTrans;
+ }
+ StatsEvent newST = currentST.getSubEvent(id);
+ if (newST == null) {
+ newST = new StatsEvent(currentST);
+ newST.setName(id);
+ currentST.addSubEvent(newST);
+ }
+ milestones.addElement(new StatsMilestone(id, startTime, newST));
+ }
+
+ public void endTiming(String id) {
+ long endTime = CMS.getCurrentDate().getTime();
+ Thread t = Thread.currentThread();
+ if (!mHashtable.containsKey(t.toString())) {
+ return; /* error */
+ }
+ Vector<StatsMilestone> milestones = mHashtable.get(t.toString());
+ if (milestones.size() == 0) {
+ return; /* error */
+ }
+ StatsMilestone last = milestones.remove(milestones.size() - 1);
+ StatsEvent st = last.getStatsEvent();
+ st.incNoOfOperations(1);
+ st.incTimeTaken(endTime - last.getStartTime());
+ if (milestones.size() == 0) {
+ mHashtable.remove(t.toString());
+ }
+ }
+
+ public void resetCounters() {
+ mStartTime = CMS.getCurrentDate();
+ mAllTrans.resetCounters();
+ }
+
+ public StatsEvent getMainStatsEvent() {
+ return mAllTrans;
+ }
+
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Stops this system.
+ */
+ public synchronized void shutdown() {
+ }
+
+ /*
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return null;
+ }
+}
+
+class StatsMilestone {
+ private String mId = null;
+ private long mStartTime = 0;
+ private StatsEvent mST = null;
+
+ public StatsMilestone(String id, long startTime, StatsEvent st) {
+ mId = id;
+ mStartTime = startTime;
+ mST = st;
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ public long getStartTime() {
+ return mStartTime;
+ }
+
+ public StatsEvent getStatsEvent() {
+ return mST;
+ }
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/util/UtilMessage.java b/base/server/cmscore/src/com/netscape/cmscore/util/UtilMessage.java
new file mode 100644
index 000000000..ce2132dc4
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/util/UtilMessage.java
@@ -0,0 +1,181 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.util;
+
+import java.util.Locale;
+
+import com.netscape.certsrv.base.MessageFormatter;
+
+/**
+ * This object is used to easily create I18N messages for utility
+ * classes and standalone programs.
+ *
+ * @author mikep
+ * @version $Revision$, $Date$
+ * @see com.netscape.certsrv.base.MessageFormatter
+ * @see com.netscape.cmscore.util.UtilResources
+ */
+public class UtilMessage {
+
+ protected Object mParams[] = null;
+
+ private String mMessage = null;
+
+ /**
+ * The bundle name for this event.
+ */
+ static String mBundleName = UtilResources.class.getName();
+
+ /**
+ * Constructs a message event
+ * <P>
+ *
+ * @param msgFormat the message string
+ */
+ public UtilMessage(String msgFormat) {
+ mMessage = msgFormat;
+ mParams = null;
+ }
+
+ /**
+ * Constructs a message with a parameter. For example,
+ *
+ * <PRE>
+ * new UtilMessage(&quot;failed to load {0}&quot;, fileName);
+ * </PRE>
+ * <P>
+ *
+ * @param msgFormat details in message string format
+ * @param param message string parameter
+ */
+ public UtilMessage(String msgFormat, String param) {
+ this(msgFormat);
+ mParams = new String[1];
+ mParams[0] = param;
+ }
+
+ /**
+ * Constructs a message from an exception. It can be used to carry
+ * a system exception that may contain information about
+ * the context. For example,
+ *
+ * <PRE>
+ * try {
+ * ...
+ * } catch (IOExeption e) {
+ * out.println(new UtilMessage("Encountered System Error {0}", e);
+ * }
+ * </PRE>
+ * <P>
+ *
+ * @param msgFormat exception details in message string format
+ * @param exception system exception
+ */
+ public UtilMessage(String msgFormat, Exception exception) {
+ this(msgFormat);
+ mParams = new Exception[1];
+ mParams[0] = exception;
+ }
+
+ /**
+ * Constructs a message from a base exception. This will use the msgFormat
+ * from the exception itself.
+ *
+ * <PRE>
+ * try {
+ * ...
+ * } catch (Exception e) {
+ * System.out.println(new UtilMessage(e));
+ * }
+ * </PRE>
+ * <P>
+ *
+ * @param exception CMS exception
+ */
+ public UtilMessage(Exception e) {
+ this(e.getMessage());
+ mParams = new Exception[1];
+ mParams[0] = e;
+ }
+
+ /**
+ * Constructs a message event with a list of parameters
+ * that will be substituted into the message format.
+ * <P>
+ *
+ * @param msgFormat message string format
+ * @param params list of message format parameters
+ */
+ public UtilMessage(String msgFormat, Object params[]) {
+ this(msgFormat);
+ mParams = params;
+ }
+
+ /**
+ * Returns the current message format string.
+ * <P>
+ *
+ * @return details message
+ */
+ public String getMessage() {
+ return mMessage;
+ }
+
+ /**
+ * Returns a list of parameters.
+ * <P>
+ *
+ * @return list of message format parameters
+ */
+ public Object[] getParameters() {
+ return mParams;
+ }
+
+ /**
+ * Returns localized message string. This method should
+ * only be called if a localized string is necessary.
+ * <P>
+ *
+ * @return details message
+ */
+ public String toString() {
+ return toString(Locale.getDefault());
+ }
+
+ /**
+ * Returns the string based on the given locale.
+ * <P>
+ *
+ * @param locale locale
+ * @return details message
+ */
+ public String toString(Locale locale) {
+ return MessageFormatter.getLocalizedString(locale, getBundleName(),
+ getMessage(),
+ getParameters());
+ }
+
+ /**
+ * Gets the resource bundle name for this class instance. This should
+ * be overridden by subclasses who have their own resource bundles.
+ */
+ protected String getBundleName() {
+ return mBundleName;
+ }
+
+}
diff --git a/base/server/cmscore/src/com/netscape/cmscore/util/UtilResources.java b/base/server/cmscore/src/com/netscape/cmscore/util/UtilResources.java
new file mode 100644
index 000000000..9ea7648f5
--- /dev/null
+++ b/base/server/cmscore/src/com/netscape/cmscore/util/UtilResources.java
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.util;
+
+import java.util.ListResourceBundle;
+
+/**
+ * A class represents a resource bundle for miscellanous utilities
+ * <P>
+ *
+ * @author mikep
+ * @version $Revision$, $Date$
+ * @see java.util.ListResourceBundle
+ */
+public class UtilResources extends ListResourceBundle {
+
+ /**
+ * Returns the content of this resource.
+ */
+ public Object[][] getContents() {
+ return contents;
+ }
+
+ /**
+ * Constants. The suffix represents the number of
+ * possible parameters.
+ */
+ public final static String HASH_FILE_CHECK_USAGE = "hashFileCheckUsage";
+ public final static String BAD_ARG_COUNT = "badArgCount";
+ public final static String NO_SUCH_FILE_1 = "noSuchFile";
+ public final static String DIGEST_MATCH_1 = "digestMatch";
+ public final static String DIGEST_DONT_MATCH_1 = "digestDontMatch";
+ public final static String FILE_TRUNCATED = "fileTruncated";
+ public final static String EXCEPTION_1 = "exception";
+ public final static String LOG_PASSWORD = "logPassword";
+ public final static String NO_USERID = "noUserId";
+ public final static String NO_SUCH_USER_2 = "noSuchUser";
+ public final static String NO_UID_PERMISSION_2 = "noUidPermission";
+ public final static String SHUTDOWN_SIG = "shutdownSignal";
+ public final static String RESTART_SIG = "restartSignal";
+
+ static final Object[][] contents = {
+ { HASH_FILE_CHECK_USAGE, "usage: HashFileCheck <filename>" },
+ { BAD_ARG_COUNT, "incorrect number of arguments" },
+ { NO_SUCH_FILE_1, "can''t find file {0}" },
+ { FILE_TRUNCATED, "Log file has been truncated." },
+ { DIGEST_MATCH_1, "Hash digest matches log file. {0} OK" },
+ {
+ DIGEST_DONT_MATCH_1,
+ "Hash digest does NOT match log file. {0} and/or hash file is corrupt or the password is incorrect." },
+ { EXCEPTION_1, "Caught unexpected exception {0}" },
+ { LOG_PASSWORD, "Please enter the log file hash digest password: " },
+ { NO_USERID, "No user id in config file. Running as {0}" },
+ { NO_SUCH_USER_2, "No such user as {0}. Running as {1}" },
+ { NO_UID_PERMISSION_2, "Can''t change process uid to {0}. Running as {1}" },
+ { SHUTDOWN_SIG, "Received shutdown signal" },
+ { RESTART_SIG, "Received restart signal" },
+ };
+}
diff --git a/base/server/cmscore/src/pki-cmscore.mf b/base/server/cmscore/src/pki-cmscore.mf
new file mode 100644
index 000000000..c23d7b299
--- /dev/null
+++ b/base/server/cmscore/src/pki-cmscore.mf
@@ -0,0 +1,3 @@
+Name: pki-cmscore
+Specification-Version: ${APPLICATION_VERSION}
+Implementation-Version: ${VERSION}
diff --git a/base/server/tomcat/CMakeLists.txt b/base/server/tomcat/CMakeLists.txt
new file mode 100644
index 000000000..555a9329d
--- /dev/null
+++ b/base/server/tomcat/CMakeLists.txt
@@ -0,0 +1,3 @@
+project(tomcat)
+
+add_subdirectory(src)
diff --git a/base/server/tomcat/src/CMakeLists.txt b/base/server/tomcat/src/CMakeLists.txt
new file mode 100644
index 000000000..d9808a803
--- /dev/null
+++ b/base/server/tomcat/src/CMakeLists.txt
@@ -0,0 +1,158 @@
+project(pki-tomcat)
+
+find_file(JSS_JAR
+ NAMES
+ jss4.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(LDAPJDK_JAR
+ NAMES
+ ldapjdk.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(COMMONS_CODEC_JAR
+ NAMES
+ commons-codec.jar
+ PATHS
+ /usr/share/java
+)
+
+find_file(COMMONS_HTTPCLIENT_JAR
+ NAMES
+ commons-httpclient.jar
+ PATHS
+ /usr/share/java
+)
+
+find_file(APACHE_COMMONS_LANG_JAR
+ NAMES
+ apache-commons-lang.jar
+ PATHS
+ /usr/share/java
+)
+
+find_file(TOMCAT_CATALINA_JAR
+ NAMES
+ catalina.jar
+ PATHS
+ /usr/share/java/tomcat
+)
+
+find_file(TOMCAT_UTIL_JAR
+ NAMES
+ tomcat-util.jar
+ PATHS
+ /usr/share/java/tomcat
+)
+
+find_file(SERVLET_JAR
+ NAMES
+ servlet.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(VELOCITY_JAR
+ NAMES
+ velocity.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(XALAN_JAR
+ NAMES
+ xalan-j2.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(XERCES_JAR
+ NAMES
+ xerces-j2.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+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(HTTPCLIENT_JAR
+ NAMES
+ httpclient.jar
+ PATHS
+ /usr/share/java/httpcomponents
+)
+
+find_file(HTTPCORE_JAR
+ NAMES
+ httpcore.jar
+ PATHS
+ /usr/share/java/httpcomponents
+)
+
+# build pki-tomcat
+javac(pki-tomcat-classes
+ SOURCES
+ com/netscape/cms/tomcat/*.java
+ CLASSPATH
+ ${SERVLET_JAR} ${TOMCAT_CATALINA_JAR}
+ OUTPUT_DIR
+ ${CMAKE_BINARY_DIR}/classes
+)
+
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/pki-tomcat.mf
+ ${CMAKE_CURRENT_BINARY_DIR}/pki-tomcat.mf
+)
+
+jar(pki-tomcat-jar
+ CREATE
+ ${CMAKE_BINARY_DIR}/dist/pki-tomcat.jar
+ OPTIONS
+ m
+ PARAMS
+ ${CMAKE_CURRENT_BINARY_DIR}/pki-tomcat.mf
+ INPUT_DIR
+ ${CMAKE_BINARY_DIR}/classes
+ FILES
+ com/netscape/cms/tomcat/*.class
+ DEPENDS
+ pki-tomcat-classes
+)
+
+install(
+ FILES
+ ${CMAKE_BINARY_DIR}/dist/pki-tomcat.jar
+ DESTINATION
+ ${JAVA_JAR_INSTALL_DIR}/pki
+)
+
+set(PKI_TOMCAT_JAR ${CMAKE_BINARY_DIR}/dist/pki-tomcat.jar CACHE INTERNAL "pki-tomcat jar file")
diff --git a/base/server/tomcat/src/com/netscape/cms/tomcat/ProxyRealm.java b/base/server/tomcat/src/com/netscape/cms/tomcat/ProxyRealm.java
new file mode 100644
index 000000000..094c0561f
--- /dev/null
+++ b/base/server/tomcat/src/com/netscape/cms/tomcat/ProxyRealm.java
@@ -0,0 +1,139 @@
+package com.netscape.cms.tomcat;
+
+import java.beans.PropertyChangeListener;
+import java.io.IOException;
+import java.security.Principal;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.Context;
+import org.apache.catalina.Realm;
+import org.apache.catalina.Wrapper;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.deploy.SecurityConstraint;
+import org.ietf.jgss.GSSContext;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class ProxyRealm implements Realm {
+
+ public static Map<String, ProxyRealm> proxies = new HashMap<String, ProxyRealm>();
+
+ public Container container;
+ public Realm realm;
+
+ public ProxyRealm() {
+ }
+
+ @Override
+ public Container getContainer() {
+ return container;
+ }
+
+ @Override
+ public void setContainer(Container container) {
+ this.container = container;
+ if (container instanceof Context) {
+ Context context = (Context)container;
+ proxies.put(context.getBaseName(), this);
+ }
+ }
+
+ public Realm getRealm() {
+ return realm;
+ }
+
+ public void setRealm(Realm realm) {
+ this.realm = realm;
+ realm.setContainer(container);
+ }
+
+ public static void registerRealm(String contextName, Realm realm) {
+ ProxyRealm proxy = proxies.get(contextName);
+ if (proxy == null) return;
+
+ proxy.setRealm(realm);
+ }
+
+ @Override
+ public Principal authenticate(String username, String password) {
+ return realm.authenticate(username, password);
+ }
+
+ @Override
+ public Principal authenticate(X509Certificate certs[]) {
+ return realm.authenticate(certs);
+ }
+
+ @Override
+ public Principal authenticate(
+ String username,
+ String digest,
+ String nonce,
+ String nc,
+ String cnonce,
+ String qop,
+ String realmName,
+ String md5a2
+ ) {
+ return realm.authenticate(username, digest, nonce, nc, cnonce, qop, realmName, md5a2);
+ }
+
+ @Override
+ public Principal authenticate(GSSContext gssContext, boolean storeCreds) {
+ return realm.authenticate(gssContext, storeCreds);
+ }
+
+ @Override
+ public boolean hasResourcePermission(
+ Request request,
+ Response response,
+ SecurityConstraint[] constraints,
+ Context context
+ ) throws IOException {
+ return realm.hasResourcePermission(request, response, constraints, context);
+ }
+
+ @Override
+ public String getInfo() {
+ return realm.getInfo();
+ }
+
+ @Override
+ public void backgroundProcess() {
+ realm.backgroundProcess();
+ }
+
+ @Override
+ public SecurityConstraint[] findSecurityConstraints(Request request, Context context) {
+ return realm.findSecurityConstraints(request, context);
+ }
+
+ @Override
+ public boolean hasRole(Wrapper wrapper, Principal principal, String role) {
+ return realm.hasRole(wrapper, principal, role);
+ }
+
+ @Override
+ public boolean hasUserDataPermission(
+ Request request,
+ Response response,
+ SecurityConstraint[] constraint
+ ) throws IOException {
+ return realm.hasUserDataPermission(request, response, constraint);
+ }
+
+ @Override
+ public void addPropertyChangeListener(PropertyChangeListener listener) {
+ realm.addPropertyChangeListener(listener);
+ }
+
+ @Override
+ public void removePropertyChangeListener(PropertyChangeListener listener) {
+ realm.removePropertyChangeListener(listener);
+ }
+}
diff --git a/base/server/tomcat/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java b/base/server/tomcat/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java
new file mode 100644
index 000000000..20bf85d22
--- /dev/null
+++ b/base/server/tomcat/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java
@@ -0,0 +1,172 @@
+// --- 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) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.tomcat;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.Globals;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.authenticator.AuthenticatorBase;
+import org.apache.catalina.authenticator.BasicAuthenticator;
+import org.apache.catalina.authenticator.FormAuthenticator;
+import org.apache.catalina.authenticator.SSLAuthenticator;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.deploy.LoginConfig;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class SSLAuthenticatorWithFallback extends AuthenticatorBase {
+
+ public final static String BASIC_AUTHENTICATOR = "BASIC";
+ public final static String FORM_AUTHENTICATOR = "FORM";
+
+ String fallbackMethod = BASIC_AUTHENTICATOR;
+
+ AuthenticatorBase sslAuthenticator = new SSLAuthenticator();
+ AuthenticatorBase fallbackAuthenticator = new BasicAuthenticator();
+
+ public SSLAuthenticatorWithFallback() {
+ log("Creating SSL authenticator with fallback");
+ }
+
+ @Override
+ public String getInfo() {
+ return "SSL authenticator with "+fallbackMethod+" fallback.";
+ }
+
+ public String getFallbackMethod() {
+ return fallbackMethod;
+ }
+
+ public void setFallbackMethod(String fallbackMethod) {
+ log("Fallback method: "+fallbackMethod);
+ this.fallbackMethod = fallbackMethod;
+
+ if (BASIC_AUTHENTICATOR.equalsIgnoreCase(fallbackMethod)) {
+ fallbackAuthenticator = new BasicAuthenticator();
+
+ } else if (FORM_AUTHENTICATOR.equalsIgnoreCase(fallbackMethod)) {
+ fallbackAuthenticator = new FormAuthenticator();
+ }
+
+ }
+
+ @Override
+ public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
+
+ X509Certificate certs[] = (X509Certificate[]) request.getAttribute(Globals.CERTIFICATES_ATTR);
+ boolean result;
+
+ if (certs != null && certs.length > 0) {
+ log("Authenticate with client certificate authentication");
+ HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper(response) {
+ public void setHeader(String name, String value) {
+ log("SSL auth header: "+name+"="+value);
+ };
+ public void sendError(int code) {
+ log("SSL auth return code: "+code);
+ }
+ };
+ result = sslAuthenticator.authenticate(request, wrapper, config);
+
+ } else {
+ log("Authenticating with "+fallbackMethod+" authentication");
+ HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper(response) {
+ public void setHeader(String name, String value) {
+ log("Fallback auth header: "+name+"="+value);
+ };
+ public void sendError(int code) {
+ log("Fallback auth return code: "+code);
+ }
+ };
+ result = fallbackAuthenticator.authenticate(request, wrapper, config);
+ }
+
+ if (result)
+ return true;
+
+ log("Result: "+result);
+
+ StringBuilder value = new StringBuilder(16);
+ value.append("Basic realm=\"");
+ if (config.getRealmName() == null) {
+ value.append(REALM_NAME);
+ } else {
+ value.append(config.getRealmName());
+ }
+ value.append('\"');
+ response.setHeader(AUTH_HEADER_NAME, value.toString());
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+
+ return false;
+ }
+
+ @Override
+ protected String getAuthMethod() {
+ return HttpServletRequest.CLIENT_CERT_AUTH;
+ };
+
+ @Override
+ public void setContainer(Container container) {
+ log("Setting container");
+ super.setContainer(container);
+ sslAuthenticator.setContainer(container);
+ fallbackAuthenticator.setContainer(container);
+ }
+
+ @Override
+ protected void initInternal() throws LifecycleException {
+ log("Initializing authenticators");
+
+ super.initInternal();
+
+ sslAuthenticator.setAlwaysUseSession(alwaysUseSession);
+ sslAuthenticator.init();
+
+ fallbackAuthenticator.setAlwaysUseSession(alwaysUseSession);
+ fallbackAuthenticator.init();
+ }
+
+ @Override
+ public void startInternal() throws LifecycleException {
+ log("Starting authenticators");
+ super.startInternal();
+ sslAuthenticator.start();
+ fallbackAuthenticator.start();
+ }
+
+ @Override
+ public void stopInternal() throws LifecycleException {
+ log("Stopping authenticators");
+ super.stopInternal();
+ sslAuthenticator.stop();
+ fallbackAuthenticator.stop();
+ }
+
+ public void log(String message) {
+ System.out.println("SSLAuthenticatorWithFallback: "+message);
+ }
+}
diff --git a/base/server/tomcat/src/pki-tomcat.mf b/base/server/tomcat/src/pki-tomcat.mf
new file mode 100644
index 000000000..ca8d3bf1b
--- /dev/null
+++ b/base/server/tomcat/src/pki-tomcat.mf
@@ -0,0 +1,3 @@
+Name: pki-tomcat
+Specification-Version: ${APPLICATION_VERSION}
+Implementation-Version: ${VERSION}