summaryrefslogtreecommitdiffstats
path: root/pki/base/common/src/com/netscape/cmscore
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/common/src/com/netscape/cmscore')
-rw-r--r--pki/base/common/src/com/netscape/cmscore/apps/CMSEngine.java1915
-rw-r--r--pki/base/common/src/com/netscape/cmscore/apps/CommandQueue.java98
-rw-r--r--pki/base/common/src/com/netscape/cmscore/apps/PKIServerEvent.java43
-rw-r--r--pki/base/common/src/com/netscape/cmscore/apps/PKIServerListener.java36
-rw-r--r--pki/base/common/src/com/netscape/cmscore/apps/Setup.java347
-rw-r--r--pki/base/common/src/com/netscape/cmscore/apps/Upgrade.java339
-rw-r--r--pki/base/common/src/com/netscape/cmscore/authentication/AuthSubsystem.java501
-rw-r--r--pki/base/common/src/com/netscape/cmscore/authentication/CertUserDBAuthentication.java266
-rw-r--r--pki/base/common/src/com/netscape/cmscore/authentication/ChallengePhraseAuthentication.java408
-rw-r--r--pki/base/common/src/com/netscape/cmscore/authentication/NullAuthentication.java154
-rw-r--r--pki/base/common/src/com/netscape/cmscore/authentication/PasswdUserDBAuthentication.java264
-rw-r--r--pki/base/common/src/com/netscape/cmscore/authentication/SSLClientCertAuthentication.java286
-rw-r--r--pki/base/common/src/com/netscape/cmscore/authentication/VerifiedCert.java93
-rw-r--r--pki/base/common/src/com/netscape/cmscore/authentication/VerifiedCerts.java161
-rw-r--r--pki/base/common/src/com/netscape/cmscore/authorization/AuthzSubsystem.java459
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/ArgBlock.java712
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/FileConfigStore.java213
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/JDialogPasswordCallback.java256
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/PropConfigStore.java767
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/SimpleProperties.java610
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/SourceConfigStore.java55
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/SubsystemLoader.java74
-rw-r--r--pki/base/common/src/com/netscape/cmscore/base/SubsystemRegistry.java43
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CertDateCompare.java52
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CertPrettyPrint.java44
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CertUtils.java1072
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CertificatePair.java271
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CrlCachePrettyPrint.java257
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CrlPrettyPrint.java44
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CrossCertPairSubsystem.java491
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/ExtPrettyPrint.java47
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/OidLoaderSubsystem.java183
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintFormat.java166
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintResources.java294
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/PubKeyPrettyPrint.java45
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/X500NameSubsystem.java277
-rw-r--r--pki/base/common/src/com/netscape/cmscore/connector/HttpConnFactory.java315
-rw-r--r--pki/base/common/src/com/netscape/cmscore/connector/HttpConnection.java238
-rw-r--r--pki/base/common/src/com/netscape/cmscore/connector/HttpConnector.java198
-rw-r--r--pki/base/common/src/com/netscape/cmscore/connector/HttpPKIMessage.java221
-rw-r--r--pki/base/common/src/com/netscape/cmscore/connector/HttpRequestEncoder.java73
-rw-r--r--pki/base/common/src/com/netscape/cmscore/connector/LocalConnector.java203
-rw-r--r--pki/base/common/src/com/netscape/cmscore/connector/RemoteAuthority.java70
-rw-r--r--pki/base/common/src/com/netscape/cmscore/connector/RequestTransfer.java124
-rw-r--r--pki/base/common/src/com/netscape/cmscore/connector/Resender.java249
-rw-r--r--pki/base/common/src/com/netscape/cmscore/crmf/CRMFParser.java122
-rw-r--r--pki/base/common/src/com/netscape/cmscore/crmf/PKIArchiveOptionsContainer.java33
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/BigIntegerMapper.java118
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/ByteArrayMapper.java93
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/CRLDBSchema.java57
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/CRLIssuingPointRecord.java325
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/CRLRepository.java365
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/CertDBSchema.java64
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/CertRecord.java278
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/CertRecordList.java118
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/CertRecordMapper.java98
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java1985
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/DBRegistry.java553
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/DBSSession.java447
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/DBSUtil.java56
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/DBSearchResults.java92
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java951
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/DBVirtualList.java769
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/DateArrayMapper.java105
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/DateMapper.java108
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/IntegerMapper.java86
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/KeyDBSchema.java58
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/KeyRecord.java348
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordList.java93
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordMapper.java111
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java553
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/KeyStateMapper.java80
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/LdapFilterConverter.java61
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/LongMapper.java117
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/MetaInfoMapper.java119
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/ObjectStreamMapper.java135
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/PublicKeyMapper.java150
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/ReplicaIDRepository.java82
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/Repository.java504
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java112
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java44
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfo.java81
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfoMapper.java167
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/StringMapper.java91
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/StringVectorMapper.java106
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/X500NameMapper.java107
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/X509CertImplMapper.java363
-rw-r--r--pki/base/common/src/com/netscape/cmscore/extensions/CMSExtensionsMap.java159
-rw-r--r--pki/base/common/src/com/netscape/cmscore/extensions/KeyUsage.java239
-rw-r--r--pki/base/common/src/com/netscape/cmscore/jobs/CronItem.java167
-rw-r--r--pki/base/common/src/com/netscape/cmscore/jobs/CronRange.java88
-rw-r--r--pki/base/common/src/com/netscape/cmscore/jobs/JobCron.java355
-rw-r--r--pki/base/common/src/com/netscape/cmscore/jobs/JobsScheduler.java541
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldap/LdapAndExpression.java75
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldap/LdapConnModule.java141
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldap/LdapOrExpression.java79
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldap/LdapPredicateParser.java374
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldap/LdapPublishModule.java796
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldap/LdapRequestListener.java531
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldap/LdapRule.java297
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldap/LdapSimpleExpression.java475
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldap/PublishObject.java92
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldap/PublisherProcessor.java1504
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldapconn/LdapAnonConnFactory.java468
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldapconn/LdapAnonConnection.java87
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldapconn/LdapAuthInfo.java299
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldapconn/LdapBoundConnFactory.java530
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldapconn/LdapBoundConnection.java214
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldapconn/LdapConnInfo.java118
-rw-r--r--pki/base/common/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.java104
-rw-r--r--pki/base/common/src/com/netscape/cmscore/listeners/ListenerPlugin.java57
-rw-r--r--pki/base/common/src/com/netscape/cmscore/logging/AuditEventFactory.java97
-rw-r--r--pki/base/common/src/com/netscape/cmscore/logging/AuditFormat.java110
-rw-r--r--pki/base/common/src/com/netscape/cmscore/logging/LogQueue.java127
-rw-r--r--pki/base/common/src/com/netscape/cmscore/logging/LogSubsystem.java272
-rw-r--r--pki/base/common/src/com/netscape/cmscore/logging/Logger.java374
-rw-r--r--pki/base/common/src/com/netscape/cmscore/logging/SignedAuditEventFactory.java124
-rw-r--r--pki/base/common/src/com/netscape/cmscore/logging/SignedAuditLogger.java47
-rw-r--r--pki/base/common/src/com/netscape/cmscore/logging/SystemEventFactory.java98
-rw-r--r--pki/base/common/src/com/netscape/cmscore/notification/EmailFormProcessor.java250
-rw-r--r--pki/base/common/src/com/netscape/cmscore/notification/EmailResolverKeys.java86
-rw-r--r--pki/base/common/src/com/netscape/cmscore/notification/EmailTemplate.java185
-rw-r--r--pki/base/common/src/com/netscape/cmscore/notification/ReqCertEmailResolver.java151
-rw-r--r--pki/base/common/src/com/netscape/cmscore/notification/ReqCertSANameEmailResolver.java268
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/AndExpression.java59
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/GeneralNameUtil.java672
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java1552
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java46
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/OrExpression.java65
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/PolicyPredicateParser.java373
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/PolicySet.java301
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/SimpleExpression.java435
-rw-r--r--pki/base/common/src/com/netscape/cmscore/profile/ProfileSubsystem.java319
-rw-r--r--pki/base/common/src/com/netscape/cmscore/registry/PluginInfo.java54
-rw-r--r--pki/base/common/src/com/netscape/cmscore/registry/PluginRegistry.java287
-rw-r--r--pki/base/common/src/com/netscape/cmscore/request/ARequestQueue.java1540
-rw-r--r--pki/base/common/src/com/netscape/cmscore/request/ARequestRecord.java44
-rw-r--r--pki/base/common/src/com/netscape/cmscore/request/CertRequestConstants.java74
-rw-r--r--pki/base/common/src/com/netscape/cmscore/request/ExtDataHashtable.java71
-rw-r--r--pki/base/common/src/com/netscape/cmscore/request/RequestAttr.java63
-rw-r--r--pki/base/common/src/com/netscape/cmscore/request/RequestQueue.java708
-rw-r--r--pki/base/common/src/com/netscape/cmscore/request/RequestRecord.java870
-rw-r--r--pki/base/common/src/com/netscape/cmscore/request/RequestRepository.java214
-rw-r--r--pki/base/common/src/com/netscape/cmscore/request/RequestSubsystem.java190
-rw-r--r--pki/base/common/src/com/netscape/cmscore/request/Schema.java51
-rw-r--r--pki/base/common/src/com/netscape/cmscore/security/CASigningCert.java169
-rw-r--r--pki/base/common/src/com/netscape/cmscore/security/CertificateInfo.java255
-rw-r--r--pki/base/common/src/com/netscape/cmscore/security/JssSubsystem.java2153
-rw-r--r--pki/base/common/src/com/netscape/cmscore/security/KRATransportCert.java110
-rw-r--r--pki/base/common/src/com/netscape/cmscore/security/KeyCertUtil.java1088
-rw-r--r--pki/base/common/src/com/netscape/cmscore/security/OCSPSigningCert.java147
-rw-r--r--pki/base/common/src/com/netscape/cmscore/security/PWCBsdr.java276
-rw-r--r--pki/base/common/src/com/netscape/cmscore/security/PWUtil.java83
-rw-r--r--pki/base/common/src/com/netscape/cmscore/security/PWsdrCache.java639
-rw-r--r--pki/base/common/src/com/netscape/cmscore/security/Provider.java53
-rw-r--r--pki/base/common/src/com/netscape/cmscore/security/RASigningCert.java125
-rw-r--r--pki/base/common/src/com/netscape/cmscore/security/SSLCert.java137
-rw-r--r--pki/base/common/src/com/netscape/cmscore/security/SSLSelfSignedCert.java131
-rw-r--r--pki/base/common/src/com/netscape/cmscore/security/SubsystemCert.java93
-rw-r--r--pki/base/common/src/com/netscape/cmscore/selftests/SelfTestOrderedInstance.java139
-rw-r--r--pki/base/common/src/com/netscape/cmscore/selftests/SelfTestSubsystem.java1907
-rw-r--r--pki/base/common/src/com/netscape/cmscore/time/SimpleTimeSource.java30
-rw-r--r--pki/base/common/src/com/netscape/cmscore/usrgrp/CertDNCertUserLocator.java76
-rw-r--r--pki/base/common/src/com/netscape/cmscore/usrgrp/ExactMatchCertUserLocator.java82
-rw-r--r--pki/base/common/src/com/netscape/cmscore/usrgrp/Group.java119
-rw-r--r--pki/base/common/src/com/netscape/cmscore/usrgrp/UGSubsystem.java1747
-rw-r--r--pki/base/common/src/com/netscape/cmscore/usrgrp/User.java216
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/Assert.java49
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/AssertionException.java32
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/Debug.java363
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/ExceptionFormatter.java91
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/FileAsString.java123
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/FileDialogFilter.java146
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/OsSubsystem.java488
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/PFXUtils.java162
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/ProfileSubsystem.java294
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/StatsSubsystem.java210
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/UtilMessage.java179
-rw-r--r--pki/base/common/src/com/netscape/cmscore/util/UtilResources.java74
179 files changed, 53292 insertions, 0 deletions
diff --git a/pki/base/common/src/com/netscape/cmscore/apps/CMSEngine.java b/pki/base/common/src/com/netscape/cmscore/apps/CMSEngine.java
new file mode 100644
index 000000000..afaa5c9fc
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/apps/CMSEngine.java
@@ -0,0 +1,1915 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.math.*;
+import java.text.*;
+import java.io.*;
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.Date;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.security.cert.X509CRL;
+
+import netscape.ldap.*;
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import com.netscape.cms.servlet.csadmin.*;
+import com.netscape.cmsutil.net.*;
+import netscape.security.extensions.*;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import java.security.NoSuchAlgorithmException;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.policy.*;
+import com.netscape.certsrv.password.*;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.acls.*;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.notification.*;
+import com.netscape.certsrv.authority.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.connector.*;
+import com.netscape.certsrv.logging.ELogException;
+import com.netscape.certsrv.logging.ILogEvent;
+import com.netscape.certsrv.logging.ILogQueue;
+import com.netscape.certsrv.logging.ILogEventListener;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.dbs.crldb.*;
+import com.netscape.certsrv.dbs.repository.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.ra.*;
+import com.netscape.certsrv.kra.*;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.apps.*;
+
+import com.netscape.cmscore.cert.CertPrettyPrint;
+import com.netscape.cmscore.cert.CrlPrettyPrint;
+import com.netscape.cmscore.cert.ExtPrettyPrint;
+import com.netscape.cmscore.policy.*;
+import com.netscape.cmscore.time.*;
+import com.netscape.cmscore.ldapconn.*;
+import com.netscape.cmscore.base.*;
+import com.netscape.cmscore.util.Debug;
+import com.netscape.cmscore.connector.*;
+import com.netscape.cmscore.notification.*;
+import com.netscape.cmscore.request.*;
+import com.netscape.cmscore.cert.*;
+import com.netscape.cmscore.logging.LogSubsystem;
+import com.netscape.cmscore.logging.Logger;
+import com.netscape.cmscore.logging.SignedAuditLogger;
+import com.netscape.cmscore.util.OsSubsystem;
+import com.netscape.cmscore.security.JssSubsystem;
+import com.netscape.cmscore.dbs.DBSubsystem;
+import com.netscape.cmscore.dbs.*;
+import com.netscape.cmscore.authentication.*;
+import com.netscape.cmscore.authorization.AuthzSubsystem;
+import com.netscape.cmscore.usrgrp.UGSubsystem;
+import com.netscape.cmscore.request.RequestSubsystem;
+import com.netscape.cmscore.jobs.JobsScheduler;
+import com.netscape.osutil.*;
+
+import com.netscape.cmscore.cert.OidLoaderSubsystem;
+import com.netscape.cmscore.cert.X500NameSubsystem;
+
+import org.mozilla.jss.util.PasswordCallback;
+import org.mozilla.jss.CryptoManager.CertificateUsage;
+import netscape.security.pkcs.*;
+import com.netscape.cmscore.security.*;
+import com.netscape.cmscore.registry.*;
+import com.netscape.cmsutil.password.*;
+import org.w3c.dom.*;
+import org.apache.xerces.parsers.DOMParser;
+
+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 static String instanceDir; /* path to instance <server-root>/cert-<instance-name> */
+
+ private IConfigStore mConfig = null;
+ private ISubsystem mOwner = null;
+ 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;
+
+ // static subsystems - must be singletons
+ private static SubsystemInfo[] mStaticSubsystems = {
+ new SubsystemInfo(
+ Debug.ID, Debug.getInstance()),
+ new SubsystemInfo(LogSubsystem.ID,
+ LogSubsystem.getInstance()),
+ new SubsystemInfo(
+ OsSubsystem.ID, OsSubsystem.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;
+ 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 mServerCertNickname = null;
+ 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() {
+ }
+
+ /**
+ * 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");
+
+ if (pwdClass != null) {
+ try {
+ mPasswordStore = (IPasswordStore)Class.forName(pwdClass).newInstance();
+ } catch (Exception e) {
+ CMS.debug("CMSEngine: getPasswordStore(): password store initialization failure:" + e.toString());
+ }
+ }
+ } 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");
+ String sd = mConfig.getString("securitydomain.select", "");
+ // 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");
+
+ 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);
+ if ((state != 1) || (sd.equals("existing"))) {
+ // for non-security domain hosts or if not yet configured,
+ // do not check session domain table
+ } else {
+ mSDTimer.schedule(timertask, 5, (new Long(secdomain_check_interval)).longValue());
+ }
+
+ 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");
+
+ 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=" + (String)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();
+ }
+
+ /**
+ * 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 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();
+ 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, ";");
+
+ if (atok == null) {
+ throw new EACLsException(CMS.getUserMessage("CMS_ACL_NULL_VALUE", "atok"));
+ }
+
+ while (atok.hasMoreTokens()) {
+ String acs = (String) 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
+ */
+ private void parseServerXML() {
+ 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());
+ }
+ }
+
+ 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);
+ if (!f.exists()) {
+ f.createNewFile();
+ }
+ } catch (Exception e) {
+ }
+
+
+ return new FileConfigStore(path);
+ }
+
+ public IArgBlock createArgBlock() {
+ return new ArgBlock();
+ }
+
+ public IArgBlock createArgBlock(Hashtable httpReq) {
+ return new ArgBlock(httpReq);
+ }
+
+ public IArgBlock createArgBlock(String realm, Hashtable 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 getSubsystemNames() {
+ return mSSReg.keys();
+ }
+
+ public Enumeration getSubsystems() {
+ return mSSReg.elements();
+ }
+
+ public ISubsystem getSubsystem(String name) {
+ return (ISubsystem) 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 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];
+ ssnames = ssconfig.getSubStoreNames();
+ 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 {
+ //OsSubsystem.nativeExit(0);
+ 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;
+ }
+
+ private String lineParsing(String input, String newName) {
+ //<SSLPARAMS servercertnickname="Server-Cert cert-firefly"
+ int index = input.indexOf("servercertnickname");
+
+ if (index >= 0) {
+ String str = input.substring(index + 20);
+ int index2 = str.indexOf("\"");
+ String newLine = input.substring(0, index + 20)
+ + newName + str.substring(index2);
+
+ return newLine;
+ } else {
+ return input;
+ }
+ }
+
+ 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 params) {
+ GeneralNameUtil.SubjAltNameGN.getDefaultParams(name, params);
+ }
+
+ public void getSubjAltNameConfigExtendedPluginInfo(String name,
+ Vector 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 params) {
+ GeneralNameUtil.GeneralNameConfig.getDefaultParams(name, isValueConfigured, params);
+ }
+
+ public void getGeneralNamesConfigDefaultParams(String name,
+ boolean isValueConfigured, Vector params) {
+ GeneralNameUtil.GeneralNamesConfig.getDefaultParams(name, isValueConfigured, params);
+ }
+
+ public void getGeneralNameConfigExtendedPluginInfo(String name,
+ boolean isValueConfigured, Vector info) {
+ GeneralNameUtil.GeneralNameConfig.getExtendedPluginInfo(name, isValueConfigured, info);
+ }
+
+ public void getGeneralNamesConfigExtendedPluginInfo(String name,
+ boolean isValueConfigured, Vector 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 OSUtil.BtoA(data);
+ }
+
+ public byte[] AtoB(String data) {
+ return OSUtil.AtoB(data);
+ }
+
+ public String getEncodedCert(X509Certificate cert) {
+ try {
+ return
+ "-----BEGIN CERTIFICATE-----\n" +
+ CMS.BtoA(cert.getEncoded()) +
+ "\n-----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 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() {
+ java.util.Enumeration e = CommandQueue.mCommandQueue.keys();
+
+ while (e.hasMoreElements()) {
+ Object thisRequest = e.nextElement();
+
+ HttpServlet thisServlet = (HttpServlet) CommandQueue.mCommandQueue.get(thisRequest);
+
+ if (thisServlet != null) {
+ CommandQueue.mCommandQueue.remove((Object) thisRequest);
+ thisServlet.destroy();
+ }
+ }
+ }
+ public static boolean isNT() {
+ return (File.separator.equals("\\"));
+ }
+
+ private static 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();
+
+ BufferedReader pOut = null;
+ String l = null;
+ } catch (Exception e) {
+
+ }
+ } // 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);
+
+ System.exit(0);
+ }
+
+ /**
+ * 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.currentThread().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() {
+ return OsSubsystem.getpid();
+ }
+
+ 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 = (ICertificateRepository) 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);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTH_AGENT_PROCESS_CHECKING"));
+ }
+
+ RequestStatus status = checkRevReq.getRequestStatus();
+
+ if (status == RequestStatus.COMPLETE) {
+ Enumeration enum1 = checkRevReq.getExtDataKeys();
+
+ while (enum1.hasMoreElements()) {
+ String name = (String) 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);
+ }
+ }
+ }
+ } 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);
+ }
+}
+
+
+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 req) throws ServletException,
+ IOException, EBaseException {
+ return null;
+ }
+
+ /**
+ * Retrieve log file list.
+ */
+ public synchronized NameValuePairs retrieveLogList(Hashtable req) throws ServletException,
+ IOException, EBaseException {
+ return null;
+ }
+
+ public String getImplName() {
+ return "ConsoleLog";
+ }
+
+ public String getDescription() {
+ return "ConsoleLog";
+ }
+
+ public Vector getDefaultParams() {
+ Vector v = new Vector();
+
+ return v;
+ }
+
+ public Vector getInstanceParams() {
+ Vector v = new Vector();
+
+ 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/pki/base/common/src/com/netscape/cmscore/apps/CommandQueue.java b/pki/base/common/src/com/netscape/cmscore/apps/CommandQueue.java
new file mode 100644
index 000000000..638eae082
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/apps/CommandQueue.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.apps;
+
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.util.TimeZone;
+import com.netscape.certsrv.apps.*;
+
+
+/*---------------------------------------------------------------
+ ** CommandQueue - Class
+ */
+
+/**
+ * register and unregister proccess for clean shutdown
+ */
+public class CommandQueue implements Runnable, ICommandQueue {
+
+ public static Hashtable mCommandQueue = new Hashtable();
+ 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.currentThread().sleep(5 * 1000);
+ //gcProcess();
+ } catch (Exception e) {
+
+ }
+ }
+ } // run
+
+ public boolean registerProcess(Object currentRequest, Object 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) {
+ java.util.Enumeration 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/pki/base/common/src/com/netscape/cmscore/apps/PKIServerEvent.java b/pki/base/common/src/com/netscape/cmscore/apps/PKIServerEvent.java
new file mode 100644
index 000000000..27d2e3f7d
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/apps/PKIServerEvent.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.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/pki/base/common/src/com/netscape/cmscore/apps/PKIServerListener.java b/pki/base/common/src/com/netscape/cmscore/apps/PKIServerListener.java
new file mode 100644
index 000000000..78fe9069f
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/apps/PKIServerListener.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.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/pki/base/common/src/com/netscape/cmscore/apps/Setup.java b/pki/base/common/src/com/netscape/cmscore/apps/Setup.java
new file mode 100644
index 000000000..21a39ec8f
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/apps/Setup.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.cmscore.apps;
+
+
+import java.io.File;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.base.EBaseException;
+import netscape.ldap.*;
+import java.io.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/apps/Upgrade.java b/pki/base/common/src/com/netscape/cmscore/apps/Upgrade.java
new file mode 100644
index 000000000..f04eb1869
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/apps/Upgrade.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.apps;
+
+
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.cmscore.util.*;
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.util.PasswordCallback;
+import org.mozilla.jss.util.PasswordCallbackInfo;
+import org.mozilla.jss.util.ConsolePasswordCallback;
+import java.io.File;
+import java.lang.*;
+
+
+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 (!OsSubsystem.isUnix()) {
+ 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;
+ boolean isKRA = 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;
+ }
+ cs = c.getSubStore("kra");
+ if (cs != null && cs.size() > 0) {
+ isKRA = 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/pki/base/common/src/com/netscape/cmscore/authentication/AuthSubsystem.java b/pki/base/common/src/com/netscape/cmscore/authentication/AuthSubsystem.java
new file mode 100644
index 000000000..b6cb0e6f7
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/authentication/AuthSubsystem.java
@@ -0,0 +1,501 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.lang.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.authentication.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.cmscore.util.*;
+
+
+/**
+ * Default authentication subsystem
+ * <P>
+ *
+ * @author cfu
+ * @author lhsiao
+ * @version $Revision$, $Date$
+ */
+public class AuthSubsystem implements IAuthSubsystem {
+ public static final String ID = "auths";
+
+ public Hashtable mAuthMgrPlugins = new Hashtable();
+ public Hashtable mAuthMgrInsts = new Hashtable();
+ 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 mImpls = c.getSubStoreNames();
+
+ while (mImpls.hasMoreElements()) {
+ String id = (String) 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 instances = c.getSubStoreNames();
+
+ while (instances.hasMoreElements()) {
+ String insName = (String) instances.nextElement();
+ String implName = c.getString(insName + "." + PROP_PLUGIN);
+ AuthMgrPlugin plugin =
+ (AuthMgrPlugin) 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 = (AuthManagerProxy)
+ 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 = (AuthMgrPlugin) 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 = (AuthManagerProxy) mAuthMgrInsts.get(name);
+
+ if (proxy == null)
+ return null;
+ return proxy.getAuthManager();
+ }
+
+ /**
+ * Enumerate all authentication manager instances.
+ */
+ public Enumeration getAuthManagers() {
+ Vector inst = new Vector();
+ Enumeration e = mAuthMgrInsts.keys();
+
+ while (e.hasMoreElements()) {
+ IAuthManager p = get((String) e.nextElement());
+
+ if (p != null) {
+ inst.addElement(p);
+ }
+ }
+ return (inst.elements());
+ }
+
+ /**
+ * Enumerate all registered authentication manager plugins.
+ */
+ public Enumeration getAuthManagerPlugins() {
+ return (mAuthMgrPlugins.elements());
+ }
+
+ /**
+ * retrieve a single auth manager plugin by name
+ */
+ public AuthMgrPlugin getAuthManagerPluginImpl(String name) {
+ return (AuthMgrPlugin) 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 = (AuthMgrPlugin) 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 (Enumeration e = mAuthMgrInsts.keys();
+ e.hasMoreElements();) {
+
+ IAuthManager mgr = (IAuthManager) get((String) e.nextElement());
+
+ log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_AUTH_INSTANCE_SHUTDOWN", mgr.getName()));
+
+ mgr.shutdown();
+ }
+
+ mAuthMgrPlugins.clear();
+ mAuthMgrPlugins = null;
+ mAuthMgrInsts.clear();
+ mAuthMgrInsts = null;
+ }
+
+ public Hashtable getPlugins() {
+ return mAuthMgrPlugins;
+ }
+
+ public Hashtable 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 ((IAuthManager) 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/pki/base/common/src/com/netscape/cmscore/authentication/CertUserDBAuthentication.java b/pki/base/common/src/com/netscape/cmscore/authentication/CertUserDBAuthentication.java
new file mode 100644
index 000000000..b9e0ede9d
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/authentication/CertUserDBAuthentication.java
@@ -0,0 +1,266 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.util.*;
+import java.lang.Class;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.cmscore.base.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.usrgrp.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.authentication.*;
+import com.netscape.certsrv.policy.*;
+
+import com.netscape.cmscore.ldapconn.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.cmscore.dbs.*;
+import com.netscape.certsrv.ra.*;
+import com.netscape.cmscore.request.*;
+import com.netscape.certsrv.kra.*;
+import com.netscape.cmscore.usrgrp.*;
+
+import com.netscape.cmscore.util.*;
+
+
+/**
+ * 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 {
+
+ /* 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;
+
+ private ICertUserLocator mCULocator = null;
+ private ILogger mLogger = CMS.getLogger();
+
+ private boolean mRevocationCheckingEnabled = false;
+ private IConfigStore mRevocationChecking = null;
+ private String mRequestor = 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 = (long) mRevocationChecking.getInteger("validityInterval", 28800);
+ long unknownStateInterval = (long) 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/pki/base/common/src/com/netscape/cmscore/authentication/ChallengePhraseAuthentication.java b/pki/base/common/src/com/netscape/cmscore/authentication/ChallengePhraseAuthentication.java
new file mode 100644
index 000000000..518e89f53
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/authentication/ChallengePhraseAuthentication.java
@@ -0,0 +1,408 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.math.BigInteger;
+import java.security.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.cmscore.base.*;
+import com.netscape.certsrv.usrgrp.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.authentication.*;
+
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.ra.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.cmscore.dbs.*;
+import com.netscape.cmscore.util.*;
+
+
+/**
+ * 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 ICertUserLocator mCULocator = null;
+ private ILogger mLogger = CMS.getLogger();
+ private String mRequestor = null;
+ private Vector mID = null;
+ 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 = (CertificateRepository) 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();
+ }
+ */
+
+ X509CertImpl[] certsToRevoke = null;
+ 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 String getDecimalStr(String str) {
+ String newStr = str;
+
+ if (str.startsWith("0x") || str.startsWith("0X")) {
+ newStr = "" + Integer.parseInt(str.trim().substring(2), 16);
+ }
+
+ return newStr;
+ }
+
+ 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();
+ mRequestor = IRequest.REQUESTOR_RA;
+ }
+ } 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 = com.netscape.osutil.OSUtil.BtoA(pwdDigest);
+
+ return "{SHA}" + b64E;
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/authentication/NullAuthentication.java b/pki/base/common/src/com/netscape/cmscore/authentication/NullAuthentication.java
new file mode 100644
index 000000000..b2914686e
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/authentication/NullAuthentication.java
@@ -0,0 +1,154 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.lang.Class;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.authentication.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/authentication/PasswdUserDBAuthentication.java b/pki/base/common/src/com/netscape/cmscore/authentication/PasswdUserDBAuthentication.java
new file mode 100644
index 000000000..1c675b8ae
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/authentication/PasswdUserDBAuthentication.java
@@ -0,0 +1,264 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import netscape.ldap.LDAPEntry;
+import java.util.*;
+import java.lang.Class;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.usrgrp.*;
+import com.netscape.certsrv.authentication.*;
+import com.netscape.certsrv.apps.*;
+
+import com.netscape.cmscore.util.*;
+import com.netscape.cmscore.ldap.*;
+import com.netscape.cmscore.ldapconn.*;
+import com.netscape.cmscore.dbs.*;
+import com.netscape.cmscore.usrgrp.*;
+
+
+/**
+ * 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 {
+
+ /* required credentials. uid, pwd are strings */
+ public static final String CRED_UID = "uid";
+ public static final String CRED_PWD = "pwd";
+ protected static String[] mRequiredCred = { CRED_UID, CRED_PWD };
+
+ /* attribute in returned token */
+ public static final String TOKEN_USERDN = "userdn";
+ public static final String TOKEN_USERID = "userid";
+
+ /* 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"));
+ }
+ 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
+ mConnFactory.reset();
+ mConnFactory = null;
+ } 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/pki/base/common/src/com/netscape/cmscore/authentication/SSLClientCertAuthentication.java b/pki/base/common/src/com/netscape/cmscore/authentication/SSLClientCertAuthentication.java
new file mode 100644
index 000000000..7aca9ae54
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/authentication/SSLClientCertAuthentication.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.cmscore.authentication;
+
+
+// ldap java sdk
+
+// cert server imports.
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.EBaseException;
+ import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.authentication.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.ra.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.request.*;
+
+// cert server x509 imports
+import netscape.security.x509.*;
+
+import java.security.*;
+import java.security.cert.*;
+
+// java sdk imports.
+import java.math.*;
+
+import com.netscape.cmscore.util.*;
+
+
+/**
+ * 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;
+ private String mRequestor = 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 = (ICertificateRepository) mCA.getCertificateRepository();
+ }
+
+ X509CertImpl clientCert = (X509CertImpl) x509Certs[0];
+
+ BigInteger serialNum = null;
+
+ try {
+ serialNum = (BigInteger) 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();
+ BigInteger[] bigIntArray = null;
+
+ if (mCertDB != null) { /* is CA */
+ ICertRecord record = null;
+
+ try {
+ record = (ICertRecord) 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();
+ mRequestor = IRequest.REQUESTOR_RA;
+ }
+ } 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/pki/base/common/src/com/netscape/cmscore/authentication/VerifiedCert.java b/pki/base/common/src/com/netscape/cmscore/authentication/VerifiedCert.java
new file mode 100644
index 000000000..90963e324
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/authentication/VerifiedCert.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.authentication;
+
+
+import java.util.*;
+import java.math.BigInteger;
+
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/authentication/VerifiedCerts.java b/pki/base/common/src/com/netscape/cmscore/authentication/VerifiedCerts.java
new file mode 100644
index 000000000..9ceae4487
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/authentication/VerifiedCerts.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 java.util.*;
+import java.math.BigInteger;
+import netscape.security.x509.*;
+
+
+/**
+ * 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 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 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/pki/base/common/src/com/netscape/cmscore/authorization/AuthzSubsystem.java b/pki/base/common/src/com/netscape/cmscore/authorization/AuthzSubsystem.java
new file mode 100644
index 000000000..9dd1ef57d
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/authorization/AuthzSubsystem.java
@@ -0,0 +1,459 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.lang.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.authentication.*;
+import com.netscape.certsrv.authorization.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.cmscore.util.*;
+
+
+/**
+ * Default authorization subsystem
+ * <P>
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class AuthzSubsystem implements IAuthzSubsystem {
+ public static final String ID = "authz";
+
+ public Hashtable mAuthzMgrPlugins = new Hashtable();
+ public Hashtable mAuthzMgrInsts = new Hashtable();
+ 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 mImpls = c.getSubStoreNames();
+
+ while (mImpls.hasMoreElements()) {
+ String id = (String) 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 instances = c.getSubStoreNames();
+
+ while (instances.hasMoreElements()) {
+ String insName = (String) instances.nextElement();
+ String implName = c.getString(insName + "." + PROP_PLUGIN);
+ AuthzMgrPlugin plugin =
+ (AuthzMgrPlugin) 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 = (AuthzManagerProxy)
+ 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 = (AuthzManagerProxy)
+ 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 = (AuthzManagerProxy)
+ 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 = (AuthzMgrPlugin) 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 = (AuthzManagerProxy) mAuthzMgrInsts.get(name);
+
+ if (proxy == null)
+ return null;
+ return proxy.getAuthzManager();
+ }
+
+ /**
+ * Enumerate all authorization manager instances.
+ */
+ public Enumeration getAuthzManagers() {
+ Vector inst = new Vector();
+ Enumeration e = mAuthzMgrInsts.keys();
+
+ while (e.hasMoreElements()) {
+ IAuthzManager p = get((String) e.nextElement());
+
+ if (p != null) {
+ inst.addElement(p);
+ }
+ }
+ return (inst.elements());
+ }
+
+ /**
+ * Enumerate all registered authorization manager plugins.
+ */
+ public Enumeration getAuthzManagerPlugins() {
+ return (mAuthzMgrPlugins.elements());
+ }
+
+ /**
+ * retrieve a single authz manager plugin by name
+ */
+ public AuthzMgrPlugin getAuthzManagerPluginImpl(String name) {
+ return (AuthzMgrPlugin) 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 = (AuthzMgrPlugin) 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 (Enumeration e = mAuthzMgrInsts.keys();
+ e.hasMoreElements();) {
+
+ IAuthzManager mgr = (IAuthzManager) get((String) e.nextElement());
+
+ String infoMsg =
+ "Shutting down authz manager instance " + mgr.getName();
+
+ //log(ILogger.LL_INFO, infoMsg);
+
+ mgr.shutdown();
+ }
+ mAuthzMgrPlugins.clear();
+ mAuthzMgrInsts.clear();
+ mAuthzMgrPlugins = null;
+ mAuthzMgrInsts = null;
+ }
+
+ public Hashtable getPlugins() {
+ return mAuthzMgrPlugins;
+ }
+
+ public Hashtable 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 ((IAuthzManager) 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/pki/base/common/src/com/netscape/cmscore/base/ArgBlock.java b/pki/base/common/src/com/netscape/cmscore/base/ArgBlock.java
new file mode 100644
index 000000000..2e0d19201
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/ArgBlock.java
@@ -0,0 +1,712 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.io.*;
+import netscape.security.pkcs.*;
+import java.security.*;
+import java.math.BigInteger;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.CMS;
+
+
+/**
+ * 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 {
+
+ /*==========================================================
+ * 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 mArgs = new Hashtable();
+
+ 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 httpReq) {
+ mType = realm;
+ populate(httpReq);
+ }
+
+ /**
+ * Constructs an argument block with the given hashtable values.
+ *
+ * @param httpReq hashtable keys and values
+ */
+ public ArgBlock(Hashtable httpReq) {
+ populate(httpReq);
+ }
+
+ private void populate(Hashtable httpReq) {
+ // Add all parameters from the request
+ Enumeration e = httpReq.keys();
+
+ if (e != null) {
+ while (e.hasMoreElements()) {
+ String name = (String) e.nextElement();
+ String value = (String) 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 getElements() {
+ return mArgs.keys();
+ }
+
+ /**
+ * Retrieves a list of argument keys.
+ *
+ * @return a list of string-based keys
+ */
+ public Enumeration 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) {
+ if (v) {
+ return mArgs.put(n, new Boolean("true"));
+ } else {
+ return mArgs.put(n, new Boolean("false"));
+ }
+ }
+
+ /**
+ * 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 = com.netscape.osutil.OSUtil.AtoB(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/pki/base/common/src/com/netscape/cmscore/base/FileConfigStore.java b/pki/base/common/src/com/netscape/cmscore/base/FileConfigStore.java
new file mode 100644
index 000000000..79bb60c67
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/FileConfigStore.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.base;
+
+
+import java.io.*;
+import java.util.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.CMS;
+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 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 {
+ FileOutputStream fo = new FileOutputStream(fileName);
+ PrintWriter writer = new PrintWriter(new OutputStreamWriter(fo));
+
+ printSubStore(writer, this, "");
+ writer.close();
+ fo.close();
+ } catch (IOException e) {
+ throw new EBaseException("output stream error " + fileName, e);
+ }
+ }
+
+ private void printSubStore(PrintWriter writer, IConfigStore store,
+ String name) throws EBaseException,
+ IOException {
+ // print keys
+ Enumeration e0 = store.getPropertyNames();
+ Vector v = new Vector();
+
+ while (e0.hasMoreElements()) {
+ v.addElement(e0.nextElement());
+ }
+
+ // sorting them lexicographically
+ while (v.size() > 0) {
+ String pname = (String) v.firstElement();
+ int j = 0;
+
+ for (int i = 1; i < v.size(); i++) {
+ String s = (String) v.elementAt(i);
+
+ if (pname.compareTo(s) > 0) {
+ j = i;
+ pname = (String) v.elementAt(i);
+ }
+ }
+ v.removeElementAt(j);
+ writer.println(name + pname + "=" + store.getString(pname));
+ }
+
+ // print substores
+ Enumeration e1 = store.getSubStoreNames();
+
+ while (e1.hasMoreElements()) {
+ v.addElement(e1.nextElement());
+ }
+ while (v.size() > 0) {
+ String pname = (String) v.firstElement();
+ int j = 0;
+
+ for (int i = 1; i < v.size(); i++) {
+ String s = (String) v.elementAt(i);
+
+ if (pname.compareTo(s) > 0) {
+ j = i;
+ pname = (String) v.elementAt(i);
+ }
+ }
+ v.removeElementAt(j);
+ printSubStore(writer, store.getSubStore(pname), name +
+ pname + ".");
+ }
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/base/JDialogPasswordCallback.java b/pki/base/common/src/com/netscape/cmscore/base/JDialogPasswordCallback.java
new file mode 100644
index 000000000..93d88a550
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/JDialogPasswordCallback.java
@@ -0,0 +1,256 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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 javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.util.PasswordCallback;
+import org.mozilla.jss.util.PasswordCallbackInfo;
+import org.mozilla.jss.*;
+import org.mozilla.jss.crypto.CryptoToken;
+import javax.swing.border.EmptyBorder;
+
+
+/**
+ * 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 = gbc.RELATIVE;
+ gbc.gridy = gbc.RELATIVE;
+ gbc.gridwidth = 1;
+ gbc.gridheight = 1;
+ gbc.fill = gbc.HORIZONTAL;
+ gbc.anchor = gbc.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 = c.NORTHWEST;
+ c.gridwidth = c.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 = c.NORTHWEST;
+ c.gridwidth = c.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();
+
+ // XXX!!! Change to char[] in JDK 1.2
+ String pwString = pwField.getText();
+
+ pwHolder.password = new Password(pwString.toCharArray());
+ 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 = c.CENTER;
+ c.fill = c.NONE;
+ c.insets = new Insets(16, 0, 0, 0);
+ c.gridwidth = c.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 = c.NONE;
+ c.anchor = c.CENTER;
+ c.gridheight = c.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 = c.NONE;
+ c.anchor = c.CENTER;
+ c.insets = new Insets(10, 4, 0, 0);
+ c.gridheight = c.REMAINDER;
+ c.gridwidth = c.REMAINDER;
+ buttonPanel.add(cancel, c);
+
+ resetGBC(c);
+ c.fill = c.NONE;
+ c.anchor = c.CENTER;
+ c.gridwidth = c.REMAINDER;
+ c.gridheight = c.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.show();
+
+ ///////////////////////////////////////////////////
+ // 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/pki/base/common/src/com/netscape/cmscore/base/PropConfigStore.java b/pki/base/common/src/com/netscape/cmscore/base/PropConfigStore.java
new file mode 100644
index 000000000..f8dd97aa5
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/PropConfigStore.java
@@ -0,0 +1,767 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.util.*;
+import java.math.BigInteger;
+import org.mozilla.jss.util.Base64OutputStream;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.CMS;
+
+
+/**
+ * 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 {
+
+ 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 Object 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 Object 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 void put(String name, Object value) {
+ 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 keys() {
+ Hashtable h = new Hashtable();
+
+ enumerate(h);
+ return h.keys();
+ }
+
+ /**
+ * Retrieves the hashtable where all the properties are kept.
+ *
+ * @return hashtable
+ */
+ public Hashtable hashtable() {
+ Hashtable h = new Hashtable();
+
+ enumerate(h);
+ return h;
+ }
+
+ /**
+ * Return the number of items in this substore
+ */
+ public int size() {
+ Hashtable h = new Hashtable();
+
+ enumerate(h);
+ return h.size();
+ }
+
+ /**
+ * Fills the given hash table with all key/value pairs in the current
+ * config store, removing the config store name prefix
+ * <P>
+ *
+ * @param h the hashtable
+ */
+ private synchronized void enumerate(Hashtable h) {
+ Enumeration 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 = (String) e.nextElement();
+
+ if (key.startsWith(fullName)) {
+ h.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 = (String) 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 = (String) get(name);
+
+ byte returnval;
+
+ if (str == null || str.length() == 0) {
+ CMS.traceHashKey(mDebugType,getFullName(name),
+ "<notpresent>","<bytearray>");
+ return defval;
+ }
+ else {
+ CMS.traceHashKey(mDebugType,getFullName(name),
+ "<bytearray>","<bytearray>");
+ return com.netscape.osutil.OSUtil.AtoB(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();
+ Base64OutputStream b64 = new Base64OutputStream(new
+ PrintStream(new FilterOutputStream(output)));
+
+ try {
+ 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 = (String) 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 = (String) 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 = (String) 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
+ */
+ public void removeSubStore(String name) {
+ // this operation is expensive!!!
+
+ Enumeration 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);
+ int kIndex = fullName.length();
+
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+
+ if (key.startsWith(fullName + ".")) {
+ ((Hashtable) 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 = (String) 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 getPropertyNames() {
+ // XXX - this operation is expensive!!!
+ Hashtable h = new Hashtable();
+
+ enumerate(h);
+ Enumeration e = h.keys();
+ Vector v = new Vector();
+
+ while (e.hasMoreElements()) {
+ String pname = (String) e.nextElement();
+ int i = pname.indexOf('.'); // substores have "."
+
+ if (i == -1) {
+ String n = pname;
+
+ if (!v.contains(n)) {
+ v.addElement(n);
+ }
+ }
+ }
+ return v.elements();
+ }
+
+ /**
+ * Returns a list of sub store names.
+ * <P>
+ *
+ * @return list of substore names
+ */
+ public Enumeration getSubStoreNames() {
+ // XXX - this operation is expensive!!!
+ Hashtable h = new Hashtable();
+
+ enumerate(h);
+ Enumeration e = h.keys();
+ Vector v = new Vector();
+
+ while (e.hasMoreElements()) {
+ String pname = (String) e.nextElement();
+ int i = pname.indexOf('.'); // substores have "."
+
+ if (i != -1) {
+ String n = pname.substring(0, i);
+
+ if (!v.contains(n)) {
+ v.addElement(n);
+ }
+ }
+ }
+ 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 keys = mSource.keys();
+
+ while (keys.hasMoreElements()) {
+ String key = (String) 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 subs = getSubStoreNames();
+
+ while (subs.hasMoreElements()) {
+ IConfigStore sub = (IConfigStore)
+ subs.nextElement();
+ IConfigStore newSub = that.makeSubStore(
+ sub.getName());
+ Enumeration props = sub.getPropertyNames();
+
+ while (props.hasMoreElements()) {
+ String n = (String) 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/pki/base/common/src/com/netscape/cmscore/base/SimpleProperties.java b/pki/base/common/src/com/netscape/cmscore/base/SimpleProperties.java
new file mode 100644
index 000000000..e2584accf
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/SimpleProperties.java
@@ -0,0 +1,610 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.util.Date;
+import java.util.Enumeration;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.BufferedWriter;
+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 {
+
+ /**
+ * 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 specialSaveChars = "=: \t\r\n\f#!";
+
+ 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>"apple, banana, pear, cantaloupe, watermelon,kiwi, mango"</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 = new String(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);
+ }
+
+ /*
+ * Converts encoded \\uxxxx to unicode chars
+ * and changes special saved chars to their original forms
+ */
+ private String loadConvert(String theString) {
+ char aChar;
+ int len = theString.length();
+ StringBuffer outBuffer = new StringBuffer(len);
+
+ for (int x = 0; x < len;) {
+ aChar = theString.charAt(x++);
+ if (aChar == '\\') {
+ aChar = theString.charAt(x++);
+ if (aChar == 'u') {
+ // Read the xxxx
+ int value = 0;
+
+ for (int i = 0; i < 4; i++) {
+ aChar = theString.charAt(x++);
+ switch (aChar) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ value = (value << 4) + aChar - '0';
+ break;
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ value = (value << 4) + 10 + aChar - 'a';
+ break;
+
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ value = (value << 4) + 10 + aChar - 'A';
+ break;
+
+ default:
+ throw new IllegalArgumentException(
+ "Malformed \\uxxxx encoding.");
+ }
+ }
+ outBuffer.append((char) value);
+ } else {
+ if (aChar == 't') aChar = '\t';
+ else if (aChar == 'r') aChar = '\r';
+ else if (aChar == 'n') aChar = '\n';
+ else if (aChar == 'f') aChar = '\f';
+ outBuffer.append(aChar);
+ }
+ } else
+ outBuffer.append(aChar);
+ }
+ return outBuffer.toString();
+ }
+
+ /*
+ * Converts unicodes to encoded \\uxxxx
+ * and writes out any of the characters in specialSaveChars
+ * with a preceding slash
+ */
+ private String saveConvert(String theString) {
+ char aChar;
+ int len = theString.length();
+ StringBuffer outBuffer = new StringBuffer(len * 2);
+
+ for (int x = 0; x < len;) {
+ aChar = theString.charAt(x++);
+ switch (aChar) {
+ case '\\':
+ outBuffer.append('\\');
+ outBuffer.append('\\');
+ continue;
+
+ case '\t':
+ outBuffer.append('\\');
+ outBuffer.append('t');
+ continue;
+
+ case '\n':
+ outBuffer.append('\\');
+ outBuffer.append('n');
+ continue;
+
+ case '\r':
+ outBuffer.append('\\');
+ outBuffer.append('r');
+ continue;
+
+ case '\f':
+ outBuffer.append('\\');
+ outBuffer.append('f');
+ continue;
+
+ default:
+ if ((aChar < 20) || (aChar > 127)) {
+ outBuffer.append('\\');
+ outBuffer.append('u');
+ outBuffer.append(toHex((aChar >> 12) & 0xF));
+ outBuffer.append(toHex((aChar >> 8) & 0xF));
+ outBuffer.append(toHex((aChar >> 4) & 0xF));
+ outBuffer.append(toHex((aChar >> 0) & 0xF));
+ } else {
+ if (specialSaveChars.indexOf(aChar) != -1)
+ outBuffer.append('\\');
+ outBuffer.append(aChar);
+ }
+ }
+ }
+ return outBuffer.toString();
+ }
+
+ /**
+ * 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 e = keys(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+ String val = (String) 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 String getProperty(String key) {
+ Object oval = super.get(key);
+ String sval = (oval instanceof String) ? (String) oval : null;
+
+ return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
+ }
+
+ /**
+ * 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 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 propertyNames() {
+ Hashtable h = new Hashtable();
+
+ 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 h = new Hashtable();
+
+ enumerate(h);
+ for (Enumeration e = h.keys(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+ String val = (String) 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 h = new Hashtable();
+
+ enumerate(h);
+ for (Enumeration e = h.keys(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+ String val = (String) 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 h) {
+ if (defaults != null) {
+ defaults.enumerate(h);
+ }
+ for (Enumeration e = keys(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+
+ h.put(key, get(key));
+ }
+ }
+
+ /**
+ * Convert a nibble to a hex character
+ * @param nibble the nibble to convert.
+ */
+ private static char toHex(int nibble) {
+ return hexDigit[(nibble & 0xF)];
+ }
+
+ /** A table of hex digits */
+ private static final char[] hexDigit = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/base/SourceConfigStore.java b/pki/base/common/src/com/netscape/cmscore/base/SourceConfigStore.java
new file mode 100644
index 000000000..9b192905f
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/SourceConfigStore.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.base;
+
+
+import com.netscape.certsrv.base.*;
+
+
+/**
+ * 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 {
+
+ /**
+ * Retrieves a property from the config store
+ * <P>
+ *
+ * @param name property name
+ * @return property value
+ */
+ public Object 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
+ */
+ public void put(String name, Object value) {
+ super.put(name, value); // from Properties->Hashtable
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/base/SubsystemLoader.java b/pki/base/common/src/com/netscape/cmscore/base/SubsystemLoader.java
new file mode 100644
index 000000000..442a93671
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/base/SubsystemLoader.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.base;
+
+
+import com.netscape.certsrv.apps.CMS;
+import java.util.*;
+import com.netscape.certsrv.base.*;
+
+
+/**
+ * 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 load(IConfigStore config) throws EBaseException {
+ Vector v = new Vector();
+
+ // 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/pki/base/common/src/com/netscape/cmscore/base/SubsystemRegistry.java b/pki/base/common/src/com/netscape/cmscore/base/SubsystemRegistry.java
new file mode 100644
index 000000000..f95a61610
--- /dev/null
+++ b/pki/base/common/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.*;
+
+
+public class SubsystemRegistry extends Hashtable {
+ 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 (ISubsystem) super.get(key);
+ }
+
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/CertDateCompare.java b/pki/base/common/src/com/netscape/cmscore/cert/CertDateCompare.java
new file mode 100644
index 000000000..9b6c3dfe0
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CertDateCompare.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.cert;
+
+
+import java.util.*;
+import netscape.security.x509.*;
+
+
+/**
+ * Compares validity dates for use in sorting.
+ *
+ * @author kanda
+ * @version $Revision$, $Date$
+ */
+public class CertDateCompare implements Comparator {
+ public CertDateCompare() {
+ }
+
+ public int compare(Object cert1, Object cert2) {
+ Date d1 = null;
+ Date d2 = null;
+
+ try {
+ d1 = ((X509CertImpl) cert1).getNotAfter();
+ d2 = ((X509CertImpl) cert2).getNotAfter();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if (d1 == d2) return 0;
+ if (d1.after(d2))
+ return 1;
+ else
+ return -1;
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/CertPrettyPrint.java b/pki/base/common/src/com/netscape/cmscore/cert/CertPrettyPrint.java
new file mode 100644
index 000000000..882a38c0c
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CertPrettyPrint.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.cmscore.cert;
+
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.security.PublicKey;
+import java.security.cert.*;
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.base.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/cert/CertUtils.java b/pki/base/common/src/com/netscape/cmscore/cert/CertUtils.java
new file mode 100644
index 000000000..6731ae35d
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CertUtils.java
@@ -0,0 +1,1072 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.util.*;
+import java.math.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import netscape.security.extensions.*;
+import netscape.security.util.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.osutil.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.logging.ILogger;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import netscape.security.pkcs.*;
+import java.net.SocketException;
+
+import javax.servlet.http.HttpServletRequest;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.CertificateUsage;
+
+/**
+ * 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 = com.netscape.osutil.OSUtil.AtoB(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.getAlgorithmId(
+ "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.getAlgorithmId(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) {
+ 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?
+ try {
+ 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);
+ }
+ }
+ }
+ }catch (Exception e) {
+ }
+ 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 = 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);
+ fin.close();
+ return ba;
+ }
+
+ public static void storeInFile(String fileName, byte[] ba)
+ throws IOException {
+ FileOutputStream fout = new FileOutputStream(fileName);
+
+ fout.write(ba);
+ fout.close();
+ }
+
+ public static String toMIME64(X509CertImpl cert) {
+ try {
+ return
+ "-----BEGIN CERTIFICATE-----\n" +
+ com.netscape.osutil.OSUtil.BtoA(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[] = com.netscape.osutil.OSUtil.AtoB(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[] = com.netscape.osutil.OSUtil.AtoB(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[] = com.netscape.osutil.OSUtil.AtoB(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[] = OSUtil.AtoB(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) {
+ String val = "";
+
+ 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 += s.charAt(i);
+ }
+ return val;
+ }
+
+ 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"};
+ 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] + ":\n" +
+ pp.toHexString(md.digest(), 8, 16);
+ }
+ return certFingerprints;
+ }
+
+ /**
+ * 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.
+ try {
+ DerOutputStream 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));
+ }
+ 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 == "")
+ 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();
+ String certlsit = "";
+ boolean r = true;
+ 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);
+ r = false;
+ return r;
+ }
+ 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 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);
+ r = false;
+ return r;
+ }
+ StringTokenizer tokenizer = new StringTokenizer(certlist, ",");
+ while (tokenizer.hasMoreTokens()) {
+ String tag = tokenizer.nextToken();
+ tag = tag.trim();
+ CMS.debug("CertUtils: verifySystemCerts() cert tag=" + tag);
+ r = verifySystemCertByTag(tag);
+ }
+ } 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) {
+ String x = null;
+ if (s.equalsIgnoreCase("CA")) {
+ x = "ca";
+ } else if (s.equalsIgnoreCase("KRA")) {
+ x = "kra";
+ } else if (s.equalsIgnoreCase("OCSP")) {
+ x = "ocsp";
+ } else if (s.equalsIgnoreCase("TKS")) {
+ x = "tks";
+ }
+
+ return x;
+ }
+
+ /**
+ * 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/pki/base/common/src/com/netscape/cmscore/cert/CertificatePair.java b/pki/base/common/src/com/netscape/cmscore/cert/CertificatePair.java
new file mode 100644
index 000000000..979e0fdd8
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CertificatePair.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.cert;
+
+
+import java.io.*;
+import java.security.cert.*;
+import org.mozilla.jss.asn1.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.ca.*;
+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 = (X509Certificate) 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.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/pki/base/common/src/com/netscape/cmscore/cert/CrlCachePrettyPrint.java b/pki/base/common/src/com/netscape/cmscore/cert/CrlCachePrettyPrint.java
new file mode 100644
index 000000000..693d881c5
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CrlCachePrettyPrint.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.cert;
+
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.ca.*;
+
+import com.netscape.certsrv.apps.*;
+
+/**
+ * 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 revokedCerts = mIP.getRevokedCertificates((int)(pageStart-1), (int)upperLimit);
+
+ if (revokedCerts != null) {
+ Iterator i = revokedCerts.iterator();
+ long l = 1;
+
+ while ((i.hasNext()) && ((crlSize == 0) || (upperLimit - pageStart + 1 >= l))) {
+ RevokedCertImpl revokedCert = (RevokedCertImpl)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 = (Extension) 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/pki/base/common/src/com/netscape/cmscore/cert/CrlPrettyPrint.java b/pki/base/common/src/com/netscape/cmscore/cert/CrlPrettyPrint.java
new file mode 100644
index 000000000..2f7c08dee
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CrlPrettyPrint.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.cmscore.cert;
+
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.security.cert.*;
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.cmscore.util.*;
+import java.security.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/cert/CrossCertPairSubsystem.java b/pki/base/common/src/com/netscape/cmscore/cert/CrossCertPairSubsystem.java
new file mode 100644
index 000000000..41020abd1
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CrossCertPairSubsystem.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.cmscore.cert;
+
+
+import netscape.ldap.*;
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import java.security.cert.*;
+import netscape.security.util.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.cert.*;
+import com.netscape.certsrv.publish.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.cmscore.ldapconn.*;
+
+
+/**
+ * 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();
+ 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((Object) 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;
+ }
+
+ Enumeration 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 = (byte[]) 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((Object) cert2.getSubjectDN()))
+ && (cert2.getIssuerDN().equals((Object) 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;
+ }
+ Enumeration vals = attr.getByteValues();
+ byte[] val = null;
+
+ while (vals.hasMoreElements()) {
+ val = (byte[]) 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;
+ }
+
+ Enumeration 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 = (byte[]) 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)
+ return mLdapConnFactory.getConn();
+
+ return 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() {
+ mCa = null;
+ mPublisherProcessor = null;
+ if (mLdapConnFactory != null) {
+ try {
+ mLdapConnFactory.reset();
+ } catch (ELdapException e) {
+ CMS.debug("CrossCertPairSubsystem shutdown exception: "+e.toString());
+ }
+ }
+ mLdapConnFactory = null;
+ }
+
+ /*
+ * 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/pki/base/common/src/com/netscape/cmscore/cert/ExtPrettyPrint.java b/pki/base/common/src/com/netscape/cmscore/cert/ExtPrettyPrint.java
new file mode 100644
index 000000000..09aea0aca
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/ExtPrettyPrint.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.cert;
+
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.math.BigInteger;
+import netscape.security.util.*;
+import netscape.security.extensions.*;
+import netscape.security.x509.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.base.*;
+import java.security.*;
+import netscape.security.x509.CRLDistributionPointsExtension.Reason;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/cert/OidLoaderSubsystem.java b/pki/base/common/src/com/netscape/cmscore/cert/OidLoaderSubsystem.java
new file mode 100644
index 000000000..7fd33f95f
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/OidLoaderSubsystem.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.cmscore.cert;
+
+
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import com.netscape.certsrv.base.*;
+import netscape.security.x509.*;
+import netscape.security.extensions.*;
+import netscape.security.util.ObjectIdentifier;
+import java.security.cert.CertificateException;
+import com.netscape.cmscore.util.*;
+
+
+/**
+ *
+ * @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 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 = (String) 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 IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintFormat.java b/pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintFormat.java
new file mode 100644
index 000000000..550756f31
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintFormat.java
@@ -0,0 +1,166 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.util.*;
+import java.text.*;
+import com.netscape.certsrv.base.*;
+
+
+/**
+ * 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) {
+ StringBuffer sb = new StringBuffer();
+ 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);
+
+ sb.append(indent(indentSize));
+ 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/pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintResources.java b/pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintResources.java
new file mode 100644
index 000000000..026dbfcbc
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/PrettyPrintResources.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.cert;
+
+
+import java.util.*;
+import netscape.security.x509.*;
+import netscape.security.extensions.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/cert/PubKeyPrettyPrint.java b/pki/base/common/src/com/netscape/cmscore/cert/PubKeyPrettyPrint.java
new file mode 100644
index 000000000..1f2d16136
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/PubKeyPrettyPrint.java
@@ -0,0 +1,45 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.cert;
+
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.security.cert.*;
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import netscape.security.provider.RSAPublicKey;
+import com.netscape.cmscore.util.*;
+import java.security.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/cert/X500NameSubsystem.java b/pki/base/common/src/com/netscape/cmscore/cert/X500NameSubsystem.java
new file mode 100644
index 000000000..0efc09d33
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/X500NameSubsystem.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.cmscore.cert;
+
+
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import com.netscape.certsrv.base.*;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * 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 attrNames = attrSubStore.getSubStoreNames();
+
+ while (attrNames.hasMoreElements()) {
+ String name = (String) 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 = (String) 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 mDerStr2TagHash = new Hashtable();
+
+ 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 = (Byte) 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 void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM,
+ ILogger.S_ADMIN, level, msg);
+ }
+
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/connector/HttpConnFactory.java b/pki/base/common/src/com/netscape/cmscore/connector/HttpConnFactory.java
new file mode 100644
index 000000000..208fc5e7f
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/connector/HttpConnFactory.java
@@ -0,0 +1,315 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.connector.*;
+import com.netscape.cmscore.connector.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.cmsutil.http.*;
+import com.netscape.cmsutil.net.*;
+import com.netscape.certsrv.authority.*;
+import java.util.*;
+import java.io.*;
+
+
+/**
+ * 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 mMasterConn = null; // master connection object.
+ private IHttpConnection mConns[];
+ private IAuthority mSource = null;
+ private IRemoteAuthority mDest = null;
+ private String mNickname = "";
+ private int mTimeout = 0;
+
+ /**
+ * 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 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] = (IHttpConnection) 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 = (IHttpConnection) 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);
+ }
+
+ protected void finalize()
+ throws Exception {
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/connector/HttpConnection.java b/pki/base/common/src/com/netscape/cmscore/connector/HttpConnection.java
new file mode 100644
index 000000000..7db508fb6
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/connector/HttpConnection.java
@@ -0,0 +1,238 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.cmsutil.http.*;
+import com.netscape.cmsutil.net.*;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.connector.*;
+import com.netscape.certsrv.authority.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.cmscore.util.Debug;
+import com.netscape.certsrv.apps.*;
+import java.io.*;
+import java.util.*;
+
+
+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/pki/base/common/src/com/netscape/cmscore/connector/HttpConnector.java b/pki/base/common/src/com/netscape/cmscore/connector/HttpConnector.java
new file mode 100644
index 000000000..4ce3ed848
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/connector/HttpConnector.java
@@ -0,0 +1,198 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.connector.*;
+import com.netscape.certsrv.authority.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.cmsutil.http.*;
+import com.netscape.cmsutil.net.*;
+import java.util.*;
+
+
+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 Thread mResendThread = null;
+ private IResender mResender = null;
+ 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);
+ mResendThread = new Thread(mResender, "HttpConnector");
+ }
+
+ // 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);
+ mResendThread = new Thread(mResender, "HttpConnector");
+ }
+
+ // 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 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() {
+ mResendThread.start();
+ }
+
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/connector/HttpPKIMessage.java b/pki/base/common/src/com/netscape/cmscore/connector/HttpPKIMessage.java
new file mode 100644
index 000000000..b9e32cbd9
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/connector/HttpPKIMessage.java
@@ -0,0 +1,221 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.request.IRequest;
+import com.netscape.certsrv.connector.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.cmscore.util.Debug;
+import java.util.*;
+import java.io.*;
+
+
+/**
+ * simple name/value pair message.
+ */
+public class HttpPKIMessage implements IHttpPKIMessage {
+ // initialized to "" because nulls don't serialize well.
+ public String reqType = "";
+ public String reqId = "";
+ protected String reqStatus = "";
+ protected Vector mNameVals = new Vector(); // 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);
+ int len = attrs.length;
+ String[] names = attrs;
+ Object value = null;
+
+ for (int i = 0; i < len; 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.
+ */
+ 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);
+
+ int len = RequestTransfer.getTransferAttributes(r).length;
+ String key;
+ Object value;
+ Enumeration 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) 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 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 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/pki/base/common/src/com/netscape/cmscore/connector/HttpRequestEncoder.java b/pki/base/common/src/com/netscape/cmscore/connector/HttpRequestEncoder.java
new file mode 100644
index 000000000..50b09fd2a
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/connector/HttpRequestEncoder.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.connector;
+
+
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.connector.*;
+import com.netscape.cmscore.util.Debug;
+
+import java.io.*;
+
+
+/**
+ * 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 = com.netscape.osutil.OSUtil.BtoA(serial);
+ return s;
+ }
+
+ public Object decode(String s)
+ throws IOException {
+ Object result = null;
+ byte[] serial = null;
+
+ try {
+
+ serial = com.netscape.osutil.OSUtil.AtoB(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/pki/base/common/src/com/netscape/cmscore/connector/LocalConnector.java b/pki/base/common/src/com/netscape/cmscore/connector/LocalConnector.java
new file mode 100644
index 000000000..efc97c435
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/connector/LocalConnector.java
@@ -0,0 +1,203 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.connector.*;
+import com.netscape.certsrv.authority.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+
+
+public class LocalConnector implements IConnector {
+ ILogger mLogger = CMS.getLogger();
+ ICertAuthority mSource = null;
+ IAuthority mDest = null;
+ Hashtable mSourceReqs = new Hashtable();
+
+ 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 = (IRequest) mSourceReqs.get(rId);
+ 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() {
+ }
+
+ protected void transferRequest(IRequest src, IRequest dest) {
+ RequestTransfer.transfer(src, dest);
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/connector/RemoteAuthority.java b/pki/base/common/src/com/netscape/cmscore/connector/RemoteAuthority.java
new file mode 100644
index 000000000..6a9703b69
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/connector/RemoteAuthority.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.cmscore.connector;
+
+
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.connector.*;
+
+
+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/pki/base/common/src/com/netscape/cmscore/connector/RequestTransfer.java b/pki/base/common/src/com/netscape/cmscore/connector/RequestTransfer.java
new file mode 100644
index 000000000..825f4d564
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/connector/RequestTransfer.java
@@ -0,0 +1,124 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.connector;
+
+
+import java.util.*;
+
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.apps.*;
+
+import com.netscape.cmscore.authentication.ChallengePhraseAuthentication;
+
+
+public class RequestTransfer {
+
+ private static final String DOT = ".";
+
+ 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 e = r.getExtDataKeys();
+ Vector v = new Vector();
+
+ while (e.hasMoreElements()) {
+ String k = (String) 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());
+ if (v.size() == 0)
+ return null;
+ String attrs[] = new String[v.size()];
+
+ v.copyInto(attrs);
+ return attrs;
+ } 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/pki/base/common/src/com/netscape/cmscore/connector/Resender.java b/pki/base/common/src/com/netscape/cmscore/connector/Resender.java
new file mode 100644
index 000000000..78fddaf5c
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/connector/Resender.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.connector;
+
+
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.connector.*;
+import com.netscape.certsrv.authority.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.authentication.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.cmscore.util.Debug;
+import com.netscape.cmsutil.http.*;
+
+import java.util.Vector;
+import java.util.Enumeration;
+import java.io.*;
+
+
+/**
+ * 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 SECOND = 1000; //milliseconds
+ public static final int MINUTE = 60 * SECOND;
+ public static final int HOUR = 60 * MINUTE;
+ public static final int DAY = 24 * HOUR;
+
+ protected IAuthority mAuthority = null;
+ IRequestQueue mQueue = null;
+ protected IRemoteAuthority mDest = null;
+
+ /* Vector of Request Id *Strings* */
+ protected Vector mRequestIds = new Vector();
+
+ protected HttpConnection mConn = null;
+
+ protected String mNickName = null;
+
+ // 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;
+
+ //mConn = new HttpConnection(dest,
+ // new JssSSLSocketFactory(nickName));
+ }
+
+ public Resender(
+ IAuthority authority, String nickName,
+ IRemoteAuthority dest, int interval) {
+ mAuthority = authority;
+ mQueue = mAuthority.getRequestQueue();
+ mDest = dest;
+ if (interval > 0)
+ mInterval = interval * SECOND; // interval specified in seconds.
+
+ //mConn = new HttpConnection(dest,
+ // new JssSSLSocketFactory(nickName));
+ }
+
+ // 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 run() {
+
+ CMS.debug("Resender: In resender Thread run:");
+ mConn = new HttpConnection(mDest,
+ new JssSSLSocketFactory(mNickName));
+ initRequests();
+
+ do {
+ resend();
+ try {
+ Thread.sleep(mInterval);
+ } catch (InterruptedException e) {
+ mAuthority.log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_CONNECTOR_RESENDER_INTERRUPTED"));
+ continue;
+ }
+ }
+ while (true);
+ }
+
+ private void resend() {
+ // clone a seperate list so mRequestIds can be modified
+ Vector rids = (Vector) mRequestIds.clone();
+ Vector completedRids = new Vector();
+
+ // resend each request to CA to ping for status.
+ Enumeration enum1 = rids.elements();
+
+ while (enum1.hasMoreElements()) {
+ // request ids are added as strings.
+ String ridString = (String) 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 en = completedRids.elements();
+
+ synchronized (mRequestIds) {
+ while (en.hasMoreElements()) {
+ RequestId id = (RequestId) 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 {
+ IRequest reply = null;
+
+ 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/pki/base/common/src/com/netscape/cmscore/crmf/CRMFParser.java b/pki/base/common/src/com/netscape/cmscore/crmf/CRMFParser.java
new file mode 100644
index 000000000..fbb652282
--- /dev/null
+++ b/pki/base/common/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 org.mozilla.jss.*;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.util.*;
+import org.mozilla.jss.crypto.PrivateKey;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.pkix.crmf.*;
+import org.mozilla.jss.pkix.primitive.*;
+import org.mozilla.jss.pkix.primitive.AVA;
+import org.mozilla.jss.pkcs11.*;
+import java.io.*;
+import java.util.*;
+
+import com.netscape.certsrv.apps.*;
+
+
+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 options = new Vector();
+
+ 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/pki/base/common/src/com/netscape/cmscore/crmf/PKIArchiveOptionsContainer.java b/pki/base/common/src/com/netscape/cmscore/crmf/PKIArchiveOptionsContainer.java
new file mode 100644
index 000000000..04529be69
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/crmf/PKIArchiveOptionsContainer.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.cmscore.crmf;
+
+
+import org.mozilla.jss.pkix.crmf.*;
+
+
+public class PKIArchiveOptionsContainer {
+
+ public PKIArchiveOptions mAO = null;
+ public int mReqPos;
+
+ public PKIArchiveOptionsContainer(PKIArchiveOptions ao, int reqpos) {
+ mAO = ao;
+ mReqPos = reqpos;
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/BigIntegerMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/BigIntegerMapper.java
new file mode 100644
index 000000000..c0afbe742
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/BigIntegerMapper.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.dbs;
+
+
+import java.util.*;
+import java.math.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.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 BigIntegerMapper implements IDBAttrMapper {
+
+ private String mLdapName = null;
+ private Vector v = new Vector();
+
+ /**
+ * Constructs BigInteger mapper.
+ */
+ public BigIntegerMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Returns a list of supported ldap attribute names.
+ */
+ public Enumeration getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps object into ldap attribute set.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ 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/pki/base/common/src/com/netscape/cmscore/dbs/ByteArrayMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/ByteArrayMapper.java
new file mode 100644
index 000000000..fcb806bb5
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/ByteArrayMapper.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.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * 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 v = new Vector();
+
+ /**
+ * Constructs a byte array mapper.
+ */
+ public ByteArrayMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Lists a list of supported ldap attribute names.
+ */
+ public Enumeration 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, (byte[]) 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/pki/base/common/src/com/netscape/cmscore/dbs/CRLDBSchema.java b/pki/base/common/src/com/netscape/cmscore/dbs/CRLDBSchema.java
new file mode 100644
index 000000000..ad065f924
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/CRLDBSchema.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.dbs;
+
+
+import java.util.*;
+import java.io.*;
+import java.math.*;
+import netscape.ldap.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.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/pki/base/common/src/com/netscape/cmscore/dbs/CRLIssuingPointRecord.java b/pki/base/common/src/com/netscape/cmscore/dbs/CRLIssuingPointRecord.java
new file mode 100644
index 000000000..8d7f19ca6
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/CRLIssuingPointRecord.java
@@ -0,0 +1,325 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.math.*;
+import java.io.*;
+import java.security.cert.*;
+import netscape.ldap.*;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import netscape.security.pkcs.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.dbs.crldb.*;
+
+
+/**
+ * A class represents a CRL issuing point record.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class CRLIssuingPointRecord implements ICRLIssuingPointRecord, IDBObj {
+
+ 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 mCRLCache = null;
+ protected Hashtable mRevokedCerts = null;
+ protected Hashtable mUnrevokedCerts = null;
+ protected Hashtable mExpiredCerts = null;
+ protected byte mDeltaCRL[] = null;
+ protected static Vector mNames = new Vector();
+ 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 revokedCerts, Hashtable unrevokedCerts, Hashtable 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;
+ }
+
+ 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) obj;
+ } else if (name.equalsIgnoreCase(ATTR_REVOKED_CERTS)) {
+ mRevokedCerts = (Hashtable) obj;
+ } else if (name.equalsIgnoreCase(ATTR_UNREVOKED_CERTS)) {
+ mUnrevokedCerts = (Hashtable) obj;
+ } else if (name.equalsIgnoreCase(ATTR_EXPIRED_CERTS)) {
+ mExpiredCerts = (Hashtable) 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 getElements() {
+ return mNames.elements();
+ }
+
+ public Enumeration 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 getCRLCacheNoClone() {
+ if (mCRLCache == null)
+ return null;
+ else
+ return (Hashtable) mCRLCache;
+ }
+
+ public Hashtable getCRLCache() {
+ if (mCRLCache == null)
+ return null;
+ else
+ return (Hashtable) mCRLCache.clone();
+ }
+
+ /**
+ * Retrieves cache info of revoked certificates.
+ */
+ public Hashtable getRevokedCerts() {
+ if (mRevokedCerts == null)
+ return null;
+ else
+ return (Hashtable) mRevokedCerts.clone();
+ }
+
+ /**
+ * Retrieves cache info of unrevoked certificates.
+ */
+ public Hashtable getUnrevokedCerts() {
+ if (mUnrevokedCerts == null)
+ return null;
+ else
+ return (Hashtable) mUnrevokedCerts.clone();
+ }
+
+ /**
+ * Retrieves cache info of expired certificates.
+ */
+ public Hashtable getExpiredCerts() {
+ if (mExpiredCerts == null)
+ return null;
+ else
+ return (Hashtable) mExpiredCerts.clone();
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/CRLRepository.java b/pki/base/common/src/com/netscape/cmscore/dbs/CRLRepository.java
new file mode 100644
index 000000000..c2eba5acb
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/CRLRepository.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.cmscore.dbs;
+
+
+import java.math.*;
+import java.util.*;
+import java.io.*;
+import java.security.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.crldb.*;
+import com.netscape.certsrv.dbs.repository.*;
+
+import com.netscape.cmscore.dbs.*;
+import com.netscape.cmscore.util.*;
+
+import com.netscape.certsrv.apps.*;
+
+/**
+ * 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;
+
+ IDBRegistry 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 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 v = new Vector();
+ 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 revokedCerts, Hashtable unrevokedCerts, Hashtable 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 revokedCerts,
+ Hashtable 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 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 revokedCerts,
+ Hashtable unrevokedCerts,
+ Hashtable 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/pki/base/common/src/com/netscape/cmscore/dbs/CertDBSchema.java b/pki/base/common/src/com/netscape/cmscore/dbs/CertDBSchema.java
new file mode 100644
index 000000000..c444a45ac
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/CertDBSchema.java
@@ -0,0 +1,64 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.io.*;
+import java.math.*;
+import netscape.ldap.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.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/pki/base/common/src/com/netscape/cmscore/dbs/CertRecord.java b/pki/base/common/src/com/netscape/cmscore/dbs/CertRecord.java
new file mode 100644
index 000000000..308d801e3
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/CertRecord.java
@@ -0,0 +1,278 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.math.*;
+import java.util.*;
+import java.security.cert.*;
+import netscape.ldap.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * A class represents a serializable certificate record.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class CertRecord implements IDBObj, ICertRecord {
+
+ 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 mNames = new Vector();
+ 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 getElements() {
+ return mNames.elements();
+ }
+
+ public Enumeration 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();
+
+ buf.append("CertRecord: ");
+ if (getSerialNumber() != null)
+ buf.append(" " + getSerialNumber().toString());
+ return buf.toString();
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/CertRecordList.java b/pki/base/common/src/com/netscape/cmscore/dbs/CertRecordList.java
new file mode 100644
index 000000000..18b8c1bf5
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/CertRecordList.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.dbs;
+
+
+import java.util.*;
+import java.io.*;
+import java.math.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.certdb.*;
+
+import com.netscape.cmscore.dbs.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * A class represents a list of certificate records.
+ * <P>
+ *
+ * @author thomask mzhao
+ * @version $Revision$, $Date$
+ */
+public class CertRecordList implements ICertRecordList {
+
+ private IDBVirtualList mVlist = null;
+
+ /**
+ * Constructs a request list.
+ */
+ public CertRecordList(IDBVirtualList 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 getCertRecords(int startidx, int endidx)
+ throws EBaseException {
+ Vector entries = new Vector();
+
+ for (int i = startidx; i <= endidx; i++) {
+ Object element = mVlist.getElementAt(i);
+
+ // CMS.debug("gerCertRecords[" + i + "] element: " + element);
+ if (element != null) {
+ entries.addElement(element);
+ }
+ }
+ return entries.elements();
+ }
+
+ public Object getCertRecord(int index)
+ throws EBaseException {
+
+ Object element = mVlist.getElementAt(index);
+
+ return element;
+
+ }
+
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/CertRecordMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/CertRecordMapper.java
new file mode 100644
index 000000000..6b910ebbb
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/CertRecordMapper.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.dbs;
+
+
+import java.math.*;
+import java.io.*;
+import java.util.*;
+import java.security.cert.*;
+import netscape.ldap.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.cmscore.dbs.*;
+import com.netscape.cmscore.util.Debug;
+import com.netscape.certsrv.apps.CMS;
+
+
+/**
+ * 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 getSupportedLDAPAttributeNames() {
+ Vector v = new Vector();
+
+ v.addElement(CertDBSchema.LDAP_ATTR_CERT_RECORD_ID);
+ return v.elements();
+ }
+
+ public void mapObjectToLDAPAttributeSet(IDBObj parent, String name,
+ Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ try {
+ CertRecord rec = (CertRecord) obj;
+
+ attrs.add(new LDAPAttribute(
+ CertDBSchema.LDAP_ATTR_CERT_RECORD_ID,
+ rec.getSerialNumber().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_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/pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java b/pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java
new file mode 100644
index 000000000..526e855e6
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java
@@ -0,0 +1,1985 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.io.*;
+import java.security.*;
+import java.security.cert.*;
+import java.security.cert.Certificate;
+import netscape.security.x509.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.dbs.repository.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.ca.*;
+
+import com.netscape.cmscore.dbs.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.cmscore.cert.*;
+
+
+/**
+ * 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 IDBSubsystem mDBService;
+ private String mBaseDN;
+ private String mRequestBaseDN;
+ private boolean mConsistencyCheck = false;
+ private boolean mSkipIfInconsistent = false;
+
+ private int mCertStatusUpdateInterval = 0;
+ private Hashtable mCRLIssuingPoints = new Hashtable();
+
+ private int mTransitMaxRecords = 1000000;
+ private int mTransitRecordPageSize = 200;
+
+ /**
+ * Constructs a certificate repository.
+ */
+ public CertificateRepository(IDBSubsystem dbService, String certRepoBaseDN, int increment, String baseDN)
+ throws EDBException {
+ super(dbService, increment, baseDN);
+ mBaseDN = certRepoBaseDN;
+
+ mDBService = dbService;
+
+ // registers CMS database attributes
+ IDBRegistry reg = dbService.getRegistry();
+
+ IConfigStore cfg = mDBService.getConfigStore();
+ }
+
+ public ICertRecord createCertRecord(BigInteger id, Certificate cert, MetaInfo meta) {
+ return new CertRecord(id, cert, meta);
+ }
+
+ 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;
+
+ }
+
+ String ldapfilter = "(" + "certstatus" + "=*" + ")";
+
+ 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.add(new BigInteger("-1"));
+ CMS.debug("CertificateRepository:getLastCertRecordSerialNo: returning " + ret);
+ return ret;
+ }
+ int ltSize = recList.getSizeBeforeJumpTo();
+
+ Vector cList = new Vector(ltSize);
+
+ 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);
+ return serial;
+ }
+ } else {
+ CMS.debug("getLastSerialNumberInRange:found null from getCertRecord");
+ }
+ }
+
+
+ BigInteger ret = new BigInteger(serial_low_bound.toString(10));
+
+ ret = ret.add(new BigInteger("-1"));
+
+ CMS.debug("CertificateRepository:getLastCertRecordSerialNo: returning " + ret);
+ 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 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 CertStatusUpdateThread mCertStatusUpdateThread = null;
+ public RetrieveModificationsThread mRetrieveModificationsThread = null;
+
+ public void setCertStatusUpdateInterval(IRepository requestRepo, int interval, boolean listenToCloneModifications) {
+ CMS.debug("In setCertStatusUpdateInterval " + interval);
+ if (interval == 0) {
+ CMS.debug("In setCertStatusUpdateInterval interval = 0" + interval);
+ if (mCertStatusUpdateThread != null) {
+ mCertStatusUpdateThread.stop();
+ }
+ if (mRetrieveModificationsThread != null) {
+ mRetrieveModificationsThread.stop();
+ }
+ return;
+ }
+
+ CMS.debug("In setCertStatusUpdateInterval listenToCloneModifications="+listenToCloneModifications+
+ " mRetrieveModificationsThread="+mRetrieveModificationsThread);
+ if (listenToCloneModifications && mRetrieveModificationsThread == null) {
+ CMS.debug("In setCertStatusUpdateInterval about to create RetrieveModificationsThread");
+ mRetrieveModificationsThread = new RetrieveModificationsThread(this, "RetrieveModificationsThread");
+ LDAPSearchResults mResults = null;
+ try {
+ mResults = startSearchForModifiedCertificateRecords();
+ } catch (Exception e) {
+ mResults = null;
+ }
+ if (mResults != null) {
+ mRetrieveModificationsThread.setResults(mResults);
+ mRetrieveModificationsThread.start();
+ }
+ }
+
+ CMS.debug("In setCertStatusUpdateInterval mCertStatusUpdateThread " + mCertStatusUpdateThread);
+ if (mCertStatusUpdateThread == null) {
+ CMS.debug("In setCertStatusUpdateInterval about to create CertStatusUpdateThread ");
+ mCertStatusUpdateThread = new CertStatusUpdateThread(this, requestRepo, "CertStatusUpdateThread");
+ mCertStatusUpdateThread.setInterval(interval);
+ mCertStatusUpdateThread.start();
+ } else {
+ CMS.debug("In setCertStatusUpdateInterval it thinks the thread is up already ");
+ mCertStatusUpdateThread.setInterval(interval);
+ // dont do anything if we have a thread running already
+ }
+ }
+
+
+ /**
+ * Blocking method.
+ */
+ 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"));
+ }
+
+ /**
+ * 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 cList = new Vector(ltSize);
+
+ CMS.debug("transidValidCertificates: list size: " + size);
+ CMS.debug("transitValidCertificates: 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 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");
+ }
+ }
+
+ CertRecord cRec = null;
+ BigInteger serial = null;
+
+ 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 cList = new Vector(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 cList = new Vector(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 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 eIPs = mCRLIssuingPoints.elements();
+
+ while (eIPs.hasMoreElements()) {
+ ICRLIssuingPoint ip = (ICRLIssuingPoint) 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 {
+ X509CertImpl cert = null;
+ 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 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 searchCertificates(String filter, int maxSize)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration 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 searchCertificates(String filter, int maxSize, int timeLimit)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration e = null;
+
+ CMS.debug("searchCertificateswith time limit filter " + filter);
+ try {
+ e = s.search(getDN(), filter, maxSize, timeLimit);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ /**
+ * Returns a list of X509CertImp that satisfies the filter.
+ * @deprecated replaced by <code>findCertificatesInList</code>
+ */
+ public Enumeration findCertRecs(String filter)
+ throws EBaseException {
+ CMS.debug("findCertRecs " + filter);
+ IDBSSession s = mDBService.createSession();
+ Enumeration e = null;
+ try {
+ e = s.search(getDN(), filter);
+ } finally {
+ if (s != null) s.close();
+ }
+ return e;
+ }
+
+ public Enumeration findCertRecs(String filter, String[] attrs)
+ throws EBaseException {
+
+ CMS.debug( "findCertRecs " + filter
+ + "attrs " + Arrays.toString( attrs ) );
+ IDBSSession s = mDBService.createSession();
+ Enumeration e = null;
+ try {
+ e = s.search(getDN(), filter, attrs);
+ } finally {
+ if (s != null) s.close();
+ }
+ return e;
+
+ }
+
+ public Enumeration findCertificates(String filter)
+ throws EBaseException {
+ Enumeration e = findCertRecords(filter);
+ Vector v = new Vector();
+
+ while (e.hasMoreElements()) {
+ CertRecord rec = (CertRecord) 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 findCertRecords(String filter)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration 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 {
+ DBVirtualList vlist = (DBVirtualList) s.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;
+ }
+ }
+
+ DBVirtualList vlist = (DBVirtualList) 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 {
+
+ DBVirtualList vlist = (DBVirtualList) 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();
+ }
+ }
+
+ /**
+ * temp solution...
+ */
+ public class RenewableCertificateCollection {
+ Vector mToRenew = null;
+ Vector mToNotify = null;
+ public RenewableCertificateCollection() {
+ }
+
+ public Vector getRenewable() {
+ return mToRenew;
+ }
+
+ public Vector getNotifiable() {
+ return mToNotify;
+ }
+
+ public void addCertificate(String renewalFlag, Object o) {
+ if (renewalFlag.equals(CertRecord.AUTO_RENEWAL_ENABLED)) {
+ if (mToRenew == null)
+ mToRenew = new Vector();
+ mToRenew.addElement(o);
+ }
+ if (renewalFlag.equals(CertRecord.AUTO_RENEWAL_DISABLED)) {
+ if (mToNotify == null)
+ mToNotify = new Vector();
+ mToNotify.addElement(o);
+ }
+ }
+ }
+
+ public Hashtable getRenewableCertificates(String renewalTime)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+
+ Hashtable 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 e = list.getCertRecords(0, size - 1);
+
+ tab = new Hashtable();
+ 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 e = list.getCertRecords(0, size - 1);
+
+ Vector v = new Vector();
+
+ 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 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 v = new Vector();
+
+ 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 getValidCertificates(String from, String to)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Vector v = new Vector();
+
+ try {
+
+ // 'from' determines 'jumpto' value
+ // 'to' determines where to stop looking
+
+ String ldapfilter = "(certstatus=VALID)";
+
+ String fromVal = "0";
+ try {
+ if (from != null) {
+ int fv = Integer.parseInt(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 getAllValidCertificates()
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration 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 getValidNotPublishedCertificates(String from, String to)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration 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 getAllValidNotPublishedCertificates()
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration 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 getExpiredCertificates(String from, String to)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration 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 getAllExpiredCertificates()
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration 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 getExpiredPublishedCertificates(String from, String to)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration 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 getAllExpiredPublishedCertificates()
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration 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 {
+
+ String now = null;
+
+ Date rightNow = CMS.getCurrentDate();
+
+ 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 {
+
+ String now = null;
+
+ 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 getRevokedCertificates(String from, String to)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration 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 getAllRevokedCertificates()
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration e = null;
+ String ldapfilter = "(|(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED + ")(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED_EXPIRED + "))"; // 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;
+ }
+
+ /**
+ * 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 getRevokedPublishedCertificates(String from, String to)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration 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 getAllRevokedPublishedCertificates()
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration e = null;
+ String ldapfilter = "(&(|(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED + ")(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED_EXPIRED + "))"; // index is setup for this filter
+
+ 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 getRevokedCertificates(Date asOfDate)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration 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 getAllRevokedNonExpiredCertificates()
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration 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;
+ }
+
+ private LDAPSearchResults startSearchForModifiedCertificateRecords()
+ throws EBaseException {
+ CMS.debug("startSearchForModifiedCertificateRecords");
+ LDAPSearchResults r = null;
+ IDBSSession s = mDBService.createSession();
+
+ String filter = "(" + CertRecord.ATTR_CERT_STATUS + "=*)";
+ try {
+ r = s.persistentSearch(getDN(), filter, null);
+ CMS.debug("startSearchForModifiedCertificateRecords persistentSearch started");
+ } catch (Exception e) {
+ CMS.debug("startSearchForModifiedCertificateRecords persistentSearch Exception="+e);
+ r = null;
+ if (s != null)
+ s.close();
+ }
+ return r;
+ }
+
+ 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 eIPs = mCRLIssuingPoints.elements();
+
+ while (eIPs.hasMoreElements()) {
+ ICRLIssuingPoint ip = (ICRLIssuingPoint) 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 (mCertStatusUpdateThread != null)
+ mCertStatusUpdateThread.destroy();
+
+ if (mRetrieveModificationsThread != null)
+ mRetrieveModificationsThread.destroy();
+ }
+}
+
+
+class CertStatusUpdateThread extends Thread {
+ CertificateRepository _cr = null;
+ IRepository _rr = null;
+ int _interval;
+
+ CertStatusUpdateThread(CertificateRepository cr, IRepository rr, String name) {
+ super(name);
+ CMS.debug("new CertStatusUpdateThread");
+ //setName(name);
+
+ _cr = cr;
+ _rr = rr;
+ }
+
+ public void setInterval(int interval) {
+ _interval = interval;
+ }
+
+ public void run() {
+ CMS.debug("Inside run method of CertStatusUpdateThread");
+
+ while (true) {
+ try {
+ // block the update while another thread
+ // (such as the CRL Update) is running
+ CMS.debug("About to start updateCertStatus");
+ synchronized (_cr.mCertStatusUpdateThread) {
+ CMS.debug("Starting updateCertStatus (entered lock)");
+ _cr.updateCertStatus();
+ CMS.debug("updateCertStatus done");
+
+ CMS.debug("Starting cert checkRanges");
+ _cr.checkRanges();
+ CMS.debug("cert checkRanges done");
+
+ CMS.debug("Starting request checkRanges");
+ _rr.checkRanges();
+ CMS.debug("request checkRanges done");
+ }
+
+ } catch (Exception e) {
+ CMS.debug("updateCertStatus done: " + e.toString());
+ }
+ try {
+ sleep(_interval * 1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+}
+
+
+class RetrieveModificationsThread extends Thread {
+ CertificateRepository _cr = null;
+ LDAPSearchResults _results = null;
+
+ RetrieveModificationsThread(CertificateRepository cr, String name) {
+ super(name);
+ CMS.debug("new RetrieveModificationsThread");
+ //setName(name);
+
+ _cr = cr;
+ }
+
+ public void setResults(LDAPSearchResults results) {
+ _results = results;
+ }
+
+ public void run() {
+ CMS.debug("Inside run method of RetrieveModificationsThread");
+
+ if (_results != null) {
+ try {
+ while (_results.hasMoreElements()) {
+ LDAPEntry entry = _results.next();
+ _cr.getModifications(entry);
+ }
+ } catch (LDAPException e) {
+ CMS.debug("LDAPException: "+e.toString());
+ }
+ } else {
+ CMS.debug("_results are null");
+ }
+ CMS.debug("Done with run method of RetrieveModificationsThread");
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/DBRegistry.java b/pki/base/common/src/com/netscape/cmscore/dbs/DBRegistry.java
new file mode 100644
index 000000000..660e385fe
--- /dev/null
+++ b/pki/base/common/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.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.dbs.*;
+
+
+/**
+ * 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 mOCclassNames = new Hashtable();
+ private Hashtable mOCldapNames = new Hashtable();
+ private Hashtable mAttrufNames = new Hashtable();
+ private IFilterConverter mConverter = null;
+ private Vector mDynAttrMappers = new Vector();
+
+ 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();
+ mOCclassNames = null;
+ mOCldapNames.clear();
+ mOCldapNames = null;
+ mAttrufNames.clear();
+ mAttrufNames = null;
+ mConverter = null;
+ }
+
+ /**
+ * 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 v = new Vector();
+
+ 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);
+ }
+ }
+ }
+ String result = "";
+
+ for (int i = 0; i < v.size(); i++) {
+ result += (String) v.elementAt(i);
+ }
+ return result;
+ }
+
+ /**
+ * 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[] = (String[])
+ mOCclassNames.get(value);
+
+ if (ldapNames == null)
+ throw new EDBException(
+ CMS.getUserMessage("CMS_DBS_INVALID_FILTER_ITEM", f));
+ String filter = "";
+
+ for (int g = 0; g < ldapNames.length; g++) {
+ filter += "(objectclass=" +
+ ldapNames[g] + ")";
+ }
+ return "&" + filter;
+ } 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 = (IDBAttrMapper) 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 v = new Vector();
+
+ for (int i = 0; i < attrs.length; i++) {
+
+ if (attrs[i].equals("objectclass")) {
+ v.addElement("objectclass");
+ continue;
+ }
+
+ if (isAttributeRegistered(attrs[i])) {
+ mapper = (IDBAttrMapper)
+ mAttrufNames.get(attrs[i].toLowerCase());
+ if (mapper == null) {
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_INVALID_ATTRS"));
+ }
+ Enumeration e = mapper.getSupportedLDAPAttributeNames();
+
+ while (e.hasMoreElements()) {
+ String s = (String) e.nextElement();
+
+ if (!v.contains(s)) {
+ v.addElement(s);
+ }
+ }
+ } else {
+ IDBDynAttrMapper matchingDynAttrMapper = null;
+ // check if a dynamic mapper can handle the attribute
+ for (Iterator dynMapperIter = mDynAttrMappers.iterator();
+ dynMapperIter.hasNext();) {
+ IDBDynAttrMapper dynAttrMapper =
+ (IDBDynAttrMapper)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 e = obj.getSerializableAttrNames();
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+
+ // add object class to attribute set
+ String className = ((Object) obj).getClass().getName();
+ String vals[] = (String[]) 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 = (String) 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 EBaseException {
+ // map object class attribute to object
+ LDAPAttribute attr = attrs.getAttribute("objectclass");
+
+ //CMS.debug("createObject: attrs " + attrs.toString());
+
+ attrs.remove("objectclass");
+
+ // sort the object class values
+ Enumeration vals = attr.getStringValues();
+ Vector v = new Vector();
+
+ while (vals.hasMoreElements()) {
+ v.addElement(vals.nextElement());
+ }
+ String s[] = new String[v.size()];
+
+ v.copyInto(s);
+ String sorted = sortAndConcate(s).toLowerCase();
+ NameAndObject no = (NameAndObject) 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 ee = obj.getSerializableAttrNames();
+
+ while (ee.hasMoreElements()) {
+ String oname = (String) ee.nextElement();
+ IDBAttrMapper mapper = (IDBAttrMapper)
+ 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 v = new Vector();
+
+ // sort it first
+ for (int i = 0; i < s.length; i++) {
+ for (int j = 0; j < v.size(); j++) {
+ String t = (String) v.elementAt(j);
+
+ if (s[i].compareTo(t) < 0) {
+ v.insertElementAt(s[i], j);
+ break;
+ }
+ }
+ if (i != (v.size() - 1))
+ v.addElement(s[i]);
+ }
+
+ // concate them
+ String result = "";
+
+ for (int i = 0; i < v.size(); i++) {
+ result += ((String) v.elementAt(i) + "+");
+ }
+ return result;
+ }
+}
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/dbs/DBSSession.java b/pki/base/common/src/com/netscape/cmscore/dbs/DBSSession.java
new file mode 100644
index 000000000..03c86a219
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/DBSSession.java
@@ -0,0 +1,447 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import netscape.ldap.*;
+import netscape.ldap.controls.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * 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("cn=123459,o=certificate repository,o=airius.com",
+ * 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);
+ }
+
+ 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()));
+ }
+ }
+
+ 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.
+ */
+ 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()));
+ }
+ }
+
+ /**
+ * Retrieves a list of objects.
+ */
+ public IDBVirtualList createVirtualList(String base, String filter,
+ String attrs[]) throws EBaseException {
+ return new DBVirtualList(mDBSystem.getRegistry(), mConn, base,
+ filter, attrs);
+ }
+
+ /**
+ * Retrieves a list of objects.
+ */
+ public IDBVirtualList createVirtualList(String base, String filter,
+ String attrs[], String sortKey[]) throws EBaseException {
+ return new DBVirtualList(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(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(mDBSystem.getRegistry(), mConn, base,
+ filter, attrs, sortKey, pageSize);
+ }
+
+ /**
+ * Retrieves a list of objects.
+ */
+ public IDBVirtualList createVirtualList(String base, String filter,
+ String attrs[], String sortKey, int pageSize) throws EBaseException {
+ return new DBVirtualList(mDBSystem.getRegistry(), mConn, base,
+ filter, attrs, sortKey, pageSize);
+ }
+
+ public IDBVirtualList createVirtualList(String base, String filter,
+ String attrs[], String startFrom, String sortKey, int pageSize) throws EBaseException {
+ return new DBVirtualList(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/pki/base/common/src/com/netscape/cmscore/dbs/DBSUtil.java b/pki/base/common/src/com/netscape/cmscore/dbs/DBSUtil.java
new file mode 100644
index 000000000..475a77dcb
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/DBSUtil.java
@@ -0,0 +1,56 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.math.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/dbs/DBSearchResults.java b/pki/base/common/src/com/netscape/cmscore/dbs/DBSearchResults.java
new file mode 100644
index 000000000..b7f6cd616
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/DBSearchResults.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.cmscore.dbs;
+
+
+import java.util.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * 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 mRes = null;
+ private ILogger mLogger = CMS.getLogger();
+
+ /**
+ * Constructs search results.
+ */
+ public DBSearchResults(IDBRegistry registry, Enumeration 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/pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java b/pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java
new file mode 100644
index 000000000..797dd8324
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java
@@ -0,0 +1,951 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.io.*;
+import java.util.*;
+import netscape.ldap.*;
+import netscape.ldap.util.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.keydb.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.dbs.crldb.*;
+import com.netscape.certsrv.dbs.repository.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.cmscore.base.*;
+import com.netscape.cmscore.ldapconn.*;
+import com.netscape.cmscore.cert.*;
+
+
+/**
+ * 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[] mRepos = null;
+
+ private BigInteger mNextSerialConfig = null;
+ private boolean mEnableSerialMgmt = false;
+
+ private static final String PEOPLE_DN = "ou=people";
+ private static final String GROUPS_DN = "ou=groups";
+ private static final String REQUESTS_DN = "ou=requests";
+ private static final String XCERTS_DN = "cn=crossCerts";
+ private static final String BASEDN = "o=netscapeCertificateServer";
+ private static final String DEFAULT_DATABASE = "userRoot";
+ private static final String AT_OC = "objectclass";
+ private static final String AT_O = "o";
+ private static final String AT_OU = "ou";
+ private static final String CA_DN = "ou=ca";
+ private static final String CR_DN = "ou=certificateRepository, ou=ca";
+ private static final String CRL_DN = "ou=crlIssuingPoints, ou=ca";
+ private static final String CA_REQUESTS_DN = "ou=ca, ou=requests";
+ private static final String KRA_DN = "ou=kra";
+ private static final String KR_DN = "ou=keyRepository, ou=kra";
+ private static final String KRA_REQUESTS_DN = "ou=kra, ou=requests";
+ private static final String REPLICA_DN = "ou=replica";
+ 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 static final BigInteger BI_ONE = new BigInteger("1");
+
+ 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 (String) (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 (String) (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 = (String) (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 = (String) (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 (String) (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 (String) (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 h = mRepos[repo];
+ CMS.debug("DBSubsystem: Setting max serial number for " + h.get(NAME) + ": " + serial);
+
+ //persist to file
+ mDBConfig.putString((String) 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 h = mRepos[repo];
+ CMS.debug("DBSubsystem: Setting min serial number for " + h.get(NAME) + ": " + serial);
+
+ //persist to file
+ mDBConfig.putString((String) 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 h = mRepos[repo];
+ if (serial == null) {
+ CMS.debug("DBSubsystem: Removing next max " + h.get(NAME) + " number");
+ mDBConfig.remove((String) h.get(PROP_NEXT_MAX_NAME));
+ } else {
+ CMS.debug("DBSubsystem: Setting next max " + h.get(NAME) + " number: " + serial);
+ mDBConfig.putString((String) h.get(PROP_NEXT_MAX_NAME), serial);
+ }
+ IConfigStore rootStore = getOwner().getConfigStore();
+ rootStore.commit(false);
+ if (serial == null) {
+ Object o2 = 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 h = mRepos[repo];
+ if (serial == null) {
+ CMS.debug("DBSubsystem: Removing next min " + h.get(NAME) + " number");
+ mDBConfig.remove((String) h.get(PROP_NEXT_MIN_NAME));
+ } else {
+ CMS.debug("DBSubsystem: Setting next min " + h.get(NAME) + " number: " + serial);
+ mDBConfig.putString((String) h.get(PROP_NEXT_MIN_NAME), serial);
+ }
+ IConfigStore rootStore = getOwner().getConfigStore();
+ rootStore.commit(false);
+ if (serial == null) {
+ Object o2 = 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 h = mRepos[repo];
+ conn = mLdapConnFactory.getConn();
+ String dn = (String) h.get(PROP_BASEDN) + "," + mBaseDN;
+ String rangeDN = (String) h.get(PROP_RANGE_DN) + "," + mBaseDN;
+
+ LDAPEntry entry = conn.read(dn);
+ LDAPAttribute attr = entry.getAttribute(PROP_NEXT_RANGE);
+ nextRange = (String) attr.getStringValues().nextElement();
+
+ BigInteger nextRangeNo = new BigInteger(nextRange);
+ if (nextRangeNo == null) {
+ throw new EBaseException("nextRangeNo is null!");
+ }
+
+ BigInteger incrementNo = new BigInteger((String) h.get(PROP_INCREMENT));
+ if (incrementNo == null) {
+ throw new EBaseException("incrementNo is null!");
+ }
+
+ // 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(BI_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);
+ } 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 h = mRepos[repo];
+ conn = mLdapConnFactory.getConn();
+ String rangedn = (String) 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.
+ */
+ 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);
+
+ // populate the certs hash entry
+ Hashtable certs = new Hashtable();
+ 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 requests = new Hashtable();
+ 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 replicaID = new Hashtable();
+ 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));
+ }
+
+ } catch (EBaseException e) {
+ if (CMS.isPreOpMode())
+ return;
+ throw e;
+ }
+ }
+
+ /**
+ * Starts up this service.
+ */
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Retrieves configuration store.
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * 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();
+ mLdapConnFactory = null;
+ }
+ } 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/pki/base/common/src/com/netscape/cmscore/dbs/DBVirtualList.java b/pki/base/common/src/com/netscape/cmscore/dbs/DBVirtualList.java
new file mode 100644
index 000000000..8a3b3cba7
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/DBVirtualList.java
@@ -0,0 +1,769 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import netscape.ldap.*;
+import netscape.ldap.controls.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * 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 implements IDBVirtualList {
+
+ 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 mEntries = new Vector();
+ // 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[] = 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
+ Object o = 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 =
+ LDAPVirtualListResponse.parseResponse(c);
+
+ 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 =
+ LDAPVirtualListResponse.parseResponse(c);
+
+ 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 Object 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
+ */
+ int baseJumpTo = 0;
+
+ 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 ("No entry at " + index);
+ else
+ return mEntries.elementAt(offset);
+ }
+
+ public Object 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/pki/base/common/src/com/netscape/cmscore/dbs/DateArrayMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/DateArrayMapper.java
new file mode 100644
index 000000000..e073fe633
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/DateArrayMapper.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.dbs;
+
+
+import java.util.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+
+
+/**
+ * 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 v = new Vector();
+
+ /**
+ * Constructs a date array mapper.
+ */
+ public DateArrayMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Retrieves a list of support ldap attributes.
+ */
+ public Enumeration getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps object to a set of attributes.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ Date dates[] = (Date[]) obj;
+
+ if (dates == null)
+ return;
+ 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;
+ Enumeration e = attr.getStringValues();
+ Vector v = new Vector();
+
+ while (e.hasMoreElements()) {
+ v.addElement(DateMapper.dateFromDB((String)
+ 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/pki/base/common/src/com/netscape/cmscore/dbs/DateMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/DateMapper.java
new file mode 100644
index 000000000..8b0009479
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/DateMapper.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.cmscore.dbs;
+
+
+import java.util.*;
+import java.text.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+
+
+/**
+ * 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 v = new Vector();
+ 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 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,
+ 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/pki/base/common/src/com/netscape/cmscore/dbs/IntegerMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/IntegerMapper.java
new file mode 100644
index 000000000..2293bea26
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/IntegerMapper.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.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+
+
+/**
+ * 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 v = new Vector();
+
+ /**
+ * Constructs mapper to deal with Integer.
+ */
+ public IntegerMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Retrieves a list of supported ldap attributes.
+ */
+ public Enumeration 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,
+ ((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/pki/base/common/src/com/netscape/cmscore/dbs/KeyDBSchema.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyDBSchema.java
new file mode 100644
index 000000000..7a5e02a04
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyDBSchema.java
@@ -0,0 +1,58 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.io.*;
+import java.math.*;
+import netscape.ldap.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.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";
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecord.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecord.java
new file mode 100644
index 000000000..7b6fcdb8d
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecord.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.dbs;
+
+
+import java.math.*;
+import java.io.*;
+import java.util.*;
+import java.security.*;
+import java.security.cert.*;
+//import netscape.security.provider.*;
+import netscape.security.x509.*;
+import netscape.security.pkcs.*;
+import netscape.ldap.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.dbs.keydb.*;
+
+
+/**
+ * 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 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;
+
+ protected static Vector mNames = new Vector();
+ 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);
+ }
+
+ /**
+ * 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 {
+ 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 {
+ 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 getElements() {
+ return mNames.elements();
+ }
+
+ /**
+ * Retrieves serializable attribute names.
+ */
+ public Enumeration 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;
+ }
+
+ /**
+ * 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;
+ }
+
+ public MetaInfo getMetaInfo() {
+ return mMetaInfo;
+ }
+
+ /**
+ * 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;
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordList.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordList.java
new file mode 100644
index 000000000..250e66e6c
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordList.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.*;
+import java.io.*;
+import java.math.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.keydb.*;
+import com.netscape.cmscore.dbs.*;
+
+
+/**
+ * A class represents a list of key records.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class KeyRecordList implements IKeyRecordList {
+
+ private IDBVirtualList mVlist = null;
+
+ /**
+ * Constructs a key list.
+ */
+ public KeyRecordList(IDBVirtualList 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) {
+ KeyRecord record = (KeyRecord) mVlist.getElementAt(i);
+
+ if (record == null) return null;
+
+ return record;
+ }
+ /**
+ * Retrieves requests.
+ */
+ public Enumeration getKeyRecords(int startidx, int endidx)
+ throws EBaseException {
+ Vector entries = new Vector();
+
+ for (int i = startidx; i <= endidx; i++) {
+ Object element = mVlist.getElementAt(i);
+
+ if (element != null) {
+ entries.addElement(element);
+ }
+ }
+ if (entries != null) {
+ return entries.elements();
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordMapper.java
new file mode 100644
index 000000000..eaaf3779f
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordMapper.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.cmscore.dbs;
+
+
+import java.math.*;
+import java.io.*;
+import java.util.*;
+import java.security.cert.*;
+import netscape.ldap.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.keydb.*;
+import com.netscape.certsrv.kra.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * 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 getSupportedLDAPAttributeNames() {
+ Vector v = new Vector();
+
+ v.addElement(KeyDBSchema.LDAP_ATTR_KEY_RECORD_ID);
+ return v.elements();
+ }
+
+ public void mapObjectToLDAPAttributeSet(IDBObj parent, String name,
+ Object obj, LDAPAttributeSet attrs) throws EBaseException {
+ 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/pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java
new file mode 100644
index 000000000..06b5f2614
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.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.math.*;
+import java.io.*;
+import java.util.*;
+import java.security.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.keydb.*;
+import com.netscape.certsrv.dbs.repository.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.cmscore.dbs.*;
+
+
+/**
+ * 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 KeyStatusUpdateThread mKeyStatusUpdateThread = null;
+ protected IDBSubsystem mDBService = null;
+
+ /**
+ * 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));
+ }
+ }
+
+ public void setKeyStatusUpdateInterval(IRepository requestRepo, int interval) {
+ CMS.debug("In setKeyStatusUpdateInterval " + interval);
+ // don't run the thread if serial management is disabled.
+ if ((interval == 0) || (!mDBService.getEnableSerialMgmt())) {
+ CMS.debug("In setKeyStatusUpdateInterval interval = 0" + interval);
+ if (mKeyStatusUpdateThread != null) {
+ mKeyStatusUpdateThread.stop();
+ }
+ return;
+ }
+
+ CMS.debug("In setKeyStatusUpdateInterval mKeyStatusUpdateThread " + mKeyStatusUpdateThread);
+ if (mKeyStatusUpdateThread == null) {
+ CMS.debug("In setKeyStatusUpdateInterval about to create KeyStatusUpdateThread ");
+ mKeyStatusUpdateThread = new KeyStatusUpdateThread(this, requestRepo, "KeyStatusUpdateThread");
+ mKeyStatusUpdateThread.setInterval(interval);
+ mKeyStatusUpdateThread.start();
+ } else {
+ CMS.debug("In setKeyStatusUpdateInterval it thinks the thread is up already ");
+ mKeyStatusUpdateThread.setInterval(interval);
+ // dont do anything if we have a thread running already
+ }
+ }
+
+ 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 e = list.getKeyRecords(0, size - 1);
+ while (e.hasMoreElements()) {
+ KeyRecord rec = (KeyRecord) 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 {
+ 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();
+ }
+ 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[]) {
+ String result = "";
+
+ for (int i = 0; i < data.length; i++) {
+ result = result + "\\" + Integer.toHexString((int) data[i]);
+ }
+ return result;
+ }
+
+ public Enumeration searchKeys(String filter, int maxSize)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration e = null;
+
+ try {
+ e = s.search(getDN(), filter, maxSize);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ public Enumeration searchKeys(String filter, int maxSize, int timeLimit)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ Enumeration e = null;
+
+ try {
+ e = s.search(getDN(), filter, maxSize, timeLimit);
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return e;
+ }
+
+ /**
+ * 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.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.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 = 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();
+
+ Vector cList = new Vector(ltSize);
+
+ 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 (mKeyStatusUpdateThread != null)
+ mKeyStatusUpdateThread.destroy();
+ }
+
+}
+
+class KeyStatusUpdateThread extends Thread {
+ KeyRepository _kr = null;
+ IRepository _rr = null;
+ int _interval;
+
+ KeyStatusUpdateThread(KeyRepository kr, IRepository rr, String name) {
+ super(name);
+ CMS.debug("new KeyStatusUpdateThread");
+
+ _kr = kr;
+ _rr = rr;
+ }
+
+ public void setInterval(int interval) {
+ _interval = interval;
+ }
+
+ public void run() {
+ CMS.debug("Inside run method of KeyStatusUpdateThread");
+
+ while (true) {
+ try {
+ // block the update while another thread
+ // (such as the CRL Update) is running
+ CMS.debug("About to start checkRanges");
+ synchronized (_kr.mKeyStatusUpdateThread) {
+ CMS.debug("Starting key checkRanges");
+ _kr.checkRanges();
+ CMS.debug("key checkRanges done");
+
+ CMS.debug("Starting request checkRanges");
+ _rr.checkRanges();
+ CMS.debug("request checkRanges done");
+ }
+ } catch (Exception e) {
+ CMS.debug("key checkRanges done");
+ }
+ try {
+ sleep(_interval * 1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+}
+
+
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/KeyStateMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyStateMapper.java
new file mode 100644
index 000000000..0630efa7c
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyStateMapper.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.dbs;
+
+
+import java.util.*;
+import java.math.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.keydb.*;
+
+
+/**
+ * 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 getSupportedLDAPAttributeNames() {
+ Vector v = new Vector();
+
+ v.addElement(mLdapName);
+ return v.elements();
+ }
+
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ 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/pki/base/common/src/com/netscape/cmscore/dbs/LdapFilterConverter.java b/pki/base/common/src/com/netscape/cmscore/dbs/LdapFilterConverter.java
new file mode 100644
index 000000000..db5db02c9
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/LdapFilterConverter.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.dbs;
+
+
+import java.util.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+
+
+/**
+ * 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 mReg = null;
+
+ /**
+ * Constructs filter convertor.
+ */
+ public LdapFilterConverter(Hashtable 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 = (IDBAttrMapper) 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/pki/base/common/src/com/netscape/cmscore/dbs/LongMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/LongMapper.java
new file mode 100644
index 000000000..9006081f5
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/LongMapper.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.util.*;
+import java.math.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+
+
+/**
+ * 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 v = new Vector();
+
+ /**
+ * Constructs Long mapper.
+ */
+ public LongMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Returns a list of supported ldap attribute names.
+ */
+ public Enumeration getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps object into ldap attribute set.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ 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/pki/base/common/src/com/netscape/cmscore/dbs/MetaInfoMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/MetaInfoMapper.java
new file mode 100644
index 000000000..c3248ec12
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/MetaInfoMapper.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.dbs;
+
+
+import java.util.*;
+import java.math.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+
+
+/**
+ * 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 v = new Vector();
+
+ /**
+ * Constructs a metainfo object.
+ */
+ public MetaInfoMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Returns a list of supported ldap attribute names.
+ */
+ public Enumeration getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps object into ldap attribute set.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ MetaInfo info = (MetaInfo) obj;
+ Enumeration e = info.getElements();
+
+ if (!e.hasMoreElements())
+ return; // dont add anything
+ LDAPAttribute attr = new LDAPAttribute(mLdapName);
+
+ while (e.hasMoreElements()) {
+ String s = null;
+ String attrName = (String) 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;
+ Enumeration values = attr.getStringValues();
+ MetaInfo info = new MetaInfo();
+
+ while (values.hasMoreElements()) {
+ String s = (String) 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/pki/base/common/src/com/netscape/cmscore/dbs/ObjectStreamMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/ObjectStreamMapper.java
new file mode 100644
index 000000000..5c02b4014
--- /dev/null
+++ b/pki/base/common/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.*;
+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 v = new Vector();
+ 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 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/pki/base/common/src/com/netscape/cmscore/dbs/PublicKeyMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/PublicKeyMapper.java
new file mode 100644
index 000000000..4d93f843a
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/PublicKeyMapper.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.cmscore.dbs;
+
+
+import java.util.*;
+import netscape.ldap.*;
+import java.security.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.cmscore.cert.*;
+
+
+/**
+ * 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 v = new Vector();
+
+ 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 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, (byte[]) 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;
+ }
+
+ private String normalize(String s) {
+ String val = "";
+
+ 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;
+ }
+ val += s.charAt(i);
+ }
+ return val;
+ }
+
+ public static String escapeBinaryData(byte data[]) {
+ String result = "";
+
+ for (int i = 0; i < data.length; i++) {
+ int v = 0xff & data[i];
+
+ result = result + "\\" + (v < 16 ? "0" : "") +
+ Integer.toHexString(v);
+ }
+ return result;
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/ReplicaIDRepository.java b/pki/base/common/src/com/netscape/cmscore/dbs/ReplicaIDRepository.java
new file mode 100644
index 000000000..ddf292b12
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/ReplicaIDRepository.java
@@ -0,0 +1,82 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.dbs.*;
+import com.netscape.certsrv.dbs.replicadb.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.CMS;
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/dbs/Repository.java b/pki/base/common/src/com/netscape/cmscore/dbs/Repository.java
new file mode 100644
index 000000000..df84b1156
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/Repository.java
@@ -0,0 +1,504 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.io.*;
+import java.math.*;
+import netscape.ldap.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.repository.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.dbs.keydb.*;
+import com.netscape.certsrv.dbs.replicadb.*;
+
+/**
+ * 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 static final BigInteger BI_ONE = new BigInteger("1");
+ private BigInteger BI_INCREMENT = null;
+ private static final BigInteger BI_ZERO = new BigInteger("0");
+ // (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;
+
+ private BigInteger mMinSerialNo = null;
+ private 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();
+
+ 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(BI_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;
+ }
+
+
+ /**
+ * init serial number cache
+ */
+ private void initCache() throws EBaseException {
+ mNext = getSerialNumber();
+ BigInteger serialConfig = new BigInteger("0");
+ 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);
+
+ 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!");
+
+ }
+
+ }
+
+ /**
+ * get the next serial number in cache
+ */
+ public BigInteger getTheSerialNumber() throws EBaseException {
+
+ CMS.debug("Repository:In getTheSerialNumber " );
+ if (mLastSerialNo == null)
+ initCache();
+ BigInteger serial = new BigInteger((mLastSerialNo.add(BI_ONE)).toString());
+
+ 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(BI_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();
+
+ mLastSerialNo = mLastSerialNo.add(BI_ONE);
+
+
+ } else {
+ mLastSerialNo = mLastSerialNo.add(BI_ONE);
+ }
+
+ if( mLastSerialNo == null ) {
+ CMS.debug( "Repository::getNextSerialNumber() " +
+ "- mLastSerialNo is null!" );
+ throw new EBaseException( "mLastSerialNo is null" );
+ }
+
+ // check if we have reached the end of the range
+ // if so, move to next range
+ if (mLastSerialNo.compareTo( mMaxSerialNo ) > 0 ) {
+ if (mDB.getEnableSerialMgmt()) {
+ CMS.debug("Reached the end of the range. Attempting to move to next range");
+ mMinSerialNo = mNextMinSerialNo;
+ mMaxSerialNo = mNextMaxSerialNo;
+ mLastSerialNo = mMinSerialNo;
+ mNextMinSerialNo = null;
+ mNextMaxSerialNo = null;
+ if ((mMaxSerialNo == null) || (mMinSerialNo == null)) {
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_LIMIT_REACHED",
+ mLastSerialNo.toString()));
+ }
+
+ // persist the changes
+ mDB.setMinSerialConfig(mRepo, mMinSerialNo.toString());
+ mDB.setMaxSerialConfig(mRepo, mMaxSerialNo.toString());
+ mDB.setNextMinSerialConfig(mRepo, null);
+ mDB.setNextMaxSerialConfig(mRepo, null);
+ } else {
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_LIMIT_REACHED",
+ mLastSerialNo.toString()));
+ }
+ }
+
+ BigInteger retSerial = new BigInteger(mLastSerialNo.toString());
+
+ CMS.debug("Repository: getNextSerialNumber: returning retSerial " + retSerial);
+ return retSerial;
+ }
+
+ /**
+ * 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 = 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);
+ 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);
+ 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/pki/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java b/pki/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java
new file mode 100644
index 000000000..7aa63fa1d
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java
@@ -0,0 +1,112 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.io.*;
+import java.math.*;
+import netscape.ldap.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.dbs.repository.*;
+
+
+/**
+ * A class represents a repository record.
+ * <P>
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class RepositoryRecord implements IRepositoryRecord {
+
+ private BigInteger mSerialNo = null;
+ private String mPublishingStatus = null;
+
+ protected static Vector mNames = new Vector();
+ static {
+ mNames.addElement(IRepositoryRecord.ATTR_SERIALNO);
+ mNames.addElement(IRepositoryRecord.ATTR_PUB_STATUS);
+ }
+
+ /**
+ * 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 {
+ 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 {
+ 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 getElements() {
+ return mNames.elements();
+ }
+
+ public Enumeration getSerializableAttrNames() {
+ return mNames.elements();
+ }
+
+ /**
+ * Retrieves serial number.
+ */
+ public BigInteger getSerialNumber() {
+ return mSerialNo;
+ }
+
+ public String getPublishingStatus() {
+ return mPublishingStatus;
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java b/pki/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java
new file mode 100644
index 000000000..436c8633e
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.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.cmscore.dbs;
+
+
+import java.util.*;
+import java.io.*;
+import java.math.*;
+import netscape.ldap.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.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";
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfo.java b/pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfo.java
new file mode 100644
index 000000000..81ae72053
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfo.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.dbs;
+
+
+import java.util.*;
+import java.io.*;
+import java.math.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import netscape.security.pkcs.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.certdb.*;
+
+import com.netscape.cmscore.dbs.*;
+import com.netscape.cmscore.util.*;
+
+
+/**
+ * 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 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/pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfoMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfoMapper.java
new file mode 100644
index 000000000..6ee2c7bb2
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfoMapper.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.dbs;
+
+
+import java.math.*;
+import java.io.*;
+import java.util.*;
+import netscape.ldap.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.cmscore.dbs.*;
+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 mNames = new Vector();
+ static {
+ mNames.addElement(CertDBSchema.LDAP_ATTR_REVO_INFO);
+ }
+
+ /**
+ * Constructs revocation information mapper.
+ */
+ public RevocationInfoMapper() {
+ }
+
+ public Enumeration getSupportedLDAPAttributeNames() {
+ return mNames.elements();
+ }
+
+ public void mapObjectToLDAPAttributeSet(IDBObj parent, String name,
+ Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ try {
+ // in format of <date>;<extensions>
+ String value = "";
+ RevocationInfo info = (RevocationInfo) obj;
+ Date d = info.getRevocationDate();
+
+ value = 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 e = exts.getElements();
+
+ while (e.hasMoreElements()) {
+ Extension ext = (Extension) e.nextElement();
+
+ if (ext instanceof CRLReasonExtension) {
+ RevocationReason reason =
+ ((CRLReasonExtension) ext).getReason();
+
+ value = value + ";CRLReasonExtension=" +
+ Integer.toString(reason.toInt());
+ } else if (ext instanceof InvalidityDateExtension) {
+ Date invalidityDate =
+ ((InvalidityDateExtension) ext).getInvalidityDate();
+
+ value = value + ";InvalidityDateExtension=" +
+ DateMapper.dateToDB(invalidityDate);
+ } else {
+ Debug.trace("XXX skipped extension");
+ }
+ }
+ attrs.add(new LDAPAttribute(CertDBSchema.LDAP_ATTR_REVO_INFO,
+ value));
+ } 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/pki/base/common/src/com/netscape/cmscore/dbs/StringMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/StringMapper.java
new file mode 100644
index 000000000..e9fbd64e7
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/StringMapper.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.dbs;
+
+
+import java.util.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+
+
+/**
+ * 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 v = new Vector();
+
+ /**
+ * Constructs string mapper.
+ */
+ public StringMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Retrieves a list of supported ldap attributes.
+ */
+ public Enumeration 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, (String)
+ 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/pki/base/common/src/com/netscape/cmscore/dbs/StringVectorMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/StringVectorMapper.java
new file mode 100644
index 000000000..2ec203eb6
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/StringVectorMapper.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.cmscore.dbs;
+
+
+import java.util.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+
+
+/**
+ * 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 v = new Vector();
+
+ /**
+ * Constructs string vector mapper.
+ */
+ public StringVectorMapper(String ldapName) {
+ mLdapName = ldapName;
+ v.addElement(mLdapName);
+ }
+
+ /**
+ * Retrieves a list of supported ldap attributes.
+ */
+ public Enumeration getSupportedLDAPAttributeNames() {
+ return v.elements();
+ }
+
+ /**
+ * Maps attribute value to ldap attributes.
+ */
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs)
+ throws EBaseException {
+ Vector v = (Vector) obj;
+ int s = v.size();
+
+ if (s == 0) {
+ return;
+ }
+ String m[] = new String[s];
+
+ for (int i = 0; i < s; i++) {
+ m[i] = (String) 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;
+ Enumeration e = attr.getStringValues();
+ Vector v = new Vector();
+
+ while (e.hasMoreElements()) {
+ v.addElement((String) 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/pki/base/common/src/com/netscape/cmscore/dbs/X500NameMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/X500NameMapper.java
new file mode 100644
index 000000000..b7e386f77
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/X500NameMapper.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.dbs;
+
+
+import java.io.*;
+import java.util.*;
+import netscape.security.x509.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * 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 v = new Vector();
+
+ 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 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,
+ ((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/pki/base/common/src/com/netscape/cmscore/dbs/X509CertImplMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/X509CertImplMapper.java
new file mode 100644
index 000000000..29e1db849
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/X509CertImplMapper.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.cmscore.dbs;
+
+
+import java.io.*;
+import java.util.*;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import netscape.ldap.*;
+import netscape.security.x509.*;
+import netscape.security.extensions.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.cmscore.dbs.*;
+import com.netscape.cmscore.cert.*;
+import com.netscape.cmscore.util.Debug;
+
+
+/**
+ * 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 getSupportedLDAPAttributeNames() {
+ Vector v = new Vector();
+
+ 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 {
+ 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 nonCritSet = cert.getNonCriticalExtensionOIDs();
+
+ if (nonCritSet != null) {
+ for (Iterator i = nonCritSet.iterator(); i.hasNext();) {
+ String oid = (String) 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 critSet = cert.getCriticalExtensionOIDs();
+
+ if (critSet != null) {
+ for (Iterator i = critSet.iterator(); i.hasNext();) {
+ String oid = (String) 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);
+
+ X509CertInfo certinfo = new X509CertInfo();
+ 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/pki/base/common/src/com/netscape/cmscore/extensions/CMSExtensionsMap.java b/pki/base/common/src/com/netscape/cmscore/extensions/CMSExtensionsMap.java
new file mode 100644
index 000000000..aceb6f1bf
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/extensions/CMSExtensionsMap.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.extensions;
+
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+import netscape.security.x509.Extension;
+import netscape.security.util.ObjectIdentifier;
+
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.extensions.*;
+
+
+/**
+ * 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 mName2Ext = new Hashtable();
+ private Hashtable mOID2Ext = new Hashtable();
+ private ISubsystem mOwner = null;
+ 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 sstores = mConfig.getSubStoreNames();
+
+ while (sstores.hasMoreElements()) {
+ String name = (String) 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 (ICMSExtension) 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 (ICMSExtension) mOID2Ext.get(oid.toString());
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/extensions/KeyUsage.java b/pki/base/common/src/com/netscape/cmscore/extensions/KeyUsage.java
new file mode 100644
index 000000000..db618f6f0
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/extensions/KeyUsage.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.cmscore.extensions;
+
+
+import java.io.IOException;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.extensions.*;
+
+import netscape.security.x509.Extension;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.util.DerOutputStream;
+
+import com.netscape.cmscore.util.*;
+
+
+public class KeyUsage implements ICMSExtension {
+ private final static String NAME = "KeyUsageExtension";
+ private final static ObjectIdentifier OID = PKIXExtensions.KeyUsage_Id;
+
+ private IConfigStore mConfig = null;
+ private boolean mSetDefault = false;
+
+ private ILogger mLogger;
+
+ public KeyUsage(boolean setDefault) {
+ mSetDefault = setDefault;
+ mLogger = CMS.getLogger();
+ }
+
+ 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 {
+ DerOutputStream der = new DerOutputStream();
+ byte[] value = extension.getExtensionValue();
+
+ ext = new KeyUsageExtension(new Boolean(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;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, level, msg);
+ }
+
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/jobs/CronItem.java b/pki/base/common/src/com/netscape/cmscore/jobs/CronItem.java
new file mode 100644
index 000000000..b97168163
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/jobs/CronItem.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.jobs;
+
+
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.*;
+
+import java.util.*;
+
+
+/**
+ * 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 mElements = new Vector();
+
+ 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 = (String) 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 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/pki/base/common/src/com/netscape/cmscore/jobs/CronRange.java b/pki/base/common/src/com/netscape/cmscore/jobs/CronRange.java
new file mode 100644
index 000000000..e8923eef8
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/jobs/CronRange.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.cmscore.jobs;
+
+
+import java.util.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/jobs/JobCron.java b/pki/base/common/src/com/netscape/cmscore/jobs/JobCron.java
new file mode 100644
index 000000000..a52f37526
--- /dev/null
+++ b/pki/base/common/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 com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.jobs.*;
+import com.netscape.certsrv.apps.*;
+
+import java.util.*;
+import java.lang.*;
+
+
+/**
+ * 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 item) {
+ // loop through all of the elements of an item
+ for (Enumeration e = item.elements(); e.hasMoreElements();) {
+ CronRange cElement = (CronRange) 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/pki/base/common/src/com/netscape/cmscore/jobs/JobsScheduler.java b/pki/base/common/src/com/netscape/cmscore/jobs/JobsScheduler.java
new file mode 100644
index 000000000..f0b8c49c2
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/jobs/JobsScheduler.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.cmscore.jobs;
+
+
+import java.util.*;
+import java.io.*;
+import java.lang.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.jobs.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import netscape.security.x509.*;
+
+
+/**
+ * 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 mJobPlugins = new Hashtable();
+ public Hashtable mJobs = new Hashtable();
+ private Hashtable mJobThreads = new Hashtable();
+
+ 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 mImpls = c.getSubStoreNames();
+
+ // register all job plugins
+ while (mImpls.hasMoreElements()) {
+ String id = (String) 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 jobs = c.getSubStoreNames();
+
+ while (jobs.hasMoreElements()) {
+ String jobName = (String) jobs.nextElement();
+ String implName = c.getString(jobName + "." + PROP_PLUGIN);
+ JobPlugin plugin =
+ (JobPlugin) 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
+ IJob job = null;
+
+ try {
+ 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) {
+ String errMsg = "JobsScheduler:: init()-" + e.toString();
+
+ 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) {
+ String errMsg = "JobsScheduler:: init()-" + e.toString();
+
+ 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) {
+ String errMsg = "JobsScheduler: init()-" + e.toString();
+
+ 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 getPlugins() {
+ return mJobPlugins;
+ }
+
+ public Hashtable 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 = 0;
+ 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.toString());
+ }
+ }
+ // 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();
+
+ IJob job = null;
+
+ for (Enumeration e = mJobs.elements(); e.hasMoreElements();) {
+ job = (IJob) 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 = (Thread) 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 moy =
+ jcron.getItem(jcron.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 dow = jcron.getItem(jcron.CRON_DAY_OF_WEEK).getElements();
+ Vector dom = jcron.getItem(jcron.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 hour = jcron.getItem(jcron.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 minute = jcron.getItem(jcron.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() {
+ mJobPlugins.clear();
+ mJobPlugins = null;
+ mJobs.clear();
+ mJobs = null;
+
+ Enumeration enums = mJobThreads.keys();
+ while (enums.hasMoreElements()) {
+ String id = (String)enums.nextElement();
+ Thread currthread = (Thread)mJobThreads.get(id);
+ if (currthread != null) {
+ currthread.destroy();
+ }
+ }
+
+ mJobThreads.clear();
+ mJobThreads = null;
+
+ if (mScheduleThread != null) {
+ mScheduleThread.destroy();
+ }
+ }
+
+ /**
+ * 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 = (JobPlugin) 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
+ IJob jobInst = null;
+ String className = plugin.getClassPath();
+
+ if (Debug.ON)
+ Debug.trace("className = " + className);
+ try {
+ 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.toString());
+ 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.toString());
+ 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.toString());
+ 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 getJobPlugins() {
+ return mJobPlugins;
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/ldap/LdapAndExpression.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapAndExpression.java
new file mode 100644
index 000000000..598ae198b
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapAndExpression.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.ldap;
+
+
+import com.netscape.certsrv.base.IAttrSet;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.publish.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/ldap/LdapConnModule.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapConnModule.java
new file mode 100644
index 000000000..273a21c96
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapConnModule.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.cmscore.ldap;
+
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.math.BigInteger;
+
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.authority.*;
+import java.security.*;
+import java.security.cert.*;
+import java.io.IOException;
+import netscape.ldap.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.publish.*;
+
+import com.netscape.cmscore.ldapconn.*;
+import com.netscape.cmscore.util.Debug;
+
+
+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/pki/base/common/src/com/netscape/cmscore/ldap/LdapOrExpression.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapOrExpression.java
new file mode 100644
index 000000000..ae0e1a310
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapOrExpression.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.cmscore.ldap;
+
+
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.publish.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/ldap/LdapPredicateParser.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapPredicateParser.java
new file mode 100644
index 000000000..b8e62d896
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapPredicateParser.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.cmscore.ldap;
+
+
+import java.util.*;
+import java.io.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.publish.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * 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();
+ boolean opANDSeen;
+ boolean opORSeen;
+
+ 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 expSet = new Vector();
+ 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((ILdapExpression) expSet.elementAt(0), null);
+
+ for (int i = 1; i < size; i++)
+ orExp = new LdapOrExpression(orExp,
+ (ILdapExpression) 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 expVector = new Vector();
+
+ 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 = (LdapSimpleExpression) expVector.elementAt(0);
+ LdapSimpleExpression exp2 = (LdapSimpleExpression) expVector.elementAt(1);
+ LdapAndExpression andExp = new LdapAndExpression(exp1, exp2);
+
+ for (int i = 2; i < size; i++) {
+ andExp = new LdapAndExpression(andExp, (LdapSimpleExpression) 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;
+ int endOfString;
+ String nextToken;
+ boolean first;
+
+ public PredicateTokenizer(String predString) {
+ input = predString;
+ currentIndex = 0;
+ nextToken = null;
+ }
+
+ public boolean hasMoreTokens() {
+ return (currentIndex != -1);
+ }
+
+ public String nextToken() {
+ 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.
+ toReturn = null;
+ System.out.println("We shouldn't be here!");
+ }
+ if (toReturn == null)
+ return null;
+ else {
+ String trimmed = toReturn.trim();
+
+ if (trimmed == null || trimmed.length() == 0)
+ return nextToken();
+ else
+ return trimmed;
+ }
+ }
+}
+
+
+class AttributeSet implements IAttrSet {
+ Hashtable ht = new Hashtable();
+ public AttributeSet() {
+ }
+
+ public void delete(String name)
+ throws EBaseException {
+ Object ob = ht.get(name);
+
+ ht.remove(ob);
+ }
+
+ public Object get(String name)
+ throws EBaseException {
+ return ht.get(name);
+ }
+
+ public void set(String name, Object ob)
+ throws EBaseException {
+ ht.put(name, ob);
+ }
+
+ public Enumeration getElements() {
+ return ht.elements();
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/ldap/LdapPublishModule.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapPublishModule.java
new file mode 100644
index 000000000..0afd0ed43
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapPublishModule.java
@@ -0,0 +1,796 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.Hashtable;
+import java.util.Enumeration;
+import java.math.BigInteger;
+
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.cmscore.util.Debug;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.cmscore.ldapconn.*;
+import com.netscape.certsrv.publish.*;
+import com.netscape.certsrv.authority.*;
+import java.security.*;
+import java.security.cert.*;
+import java.io.IOException;
+import netscape.ldap.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.cmscore.dbs.*;
+import com.netscape.certsrv.apps.*;
+
+
+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 mMappers = new Hashtable();
+
+ /**
+ * handlers for request types (events)
+ * values implement IRequestListener
+ */
+ protected Hashtable mEventHandlers = new Hashtable();
+
+ /**
+ * 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 = (LdapMappers) mMappers.get(PROP_TYPE_CLIENT);
+ } else {
+ mappers = (LdapMappers) 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 substores = types.getSubStoreNames();
+
+ while (substores.hasMoreElements()) {
+ String certType = (String) 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();
+ boolean error = false;
+
+ IRequestListener handler = (IRequestListener) 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 = (ICertificateRepository) ca.getCertificateRepository();
+ ICertRecord certRec = (ICertRecord) 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 {
+ ILdapCrlMapper mapper = null;
+ ILdapPublisher publisher = null;
+
+ 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", (String) ""));
+ } 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];
+ X509CertImpl cert;
+
+ 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 = (X509CertImpl) 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()));
+ } catch (EBaseException e) {
+ error = true;
+ mModule.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_FIND",
+ 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()));
+ } catch (EBaseException e) {
+ error = true;
+ mModule.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_FIND",
+ 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/pki/base/common/src/com/netscape/cmscore/ldap/LdapRequestListener.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapRequestListener.java
new file mode 100644
index 000000000..d467bd957
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapRequestListener.java
@@ -0,0 +1,531 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.Hashtable;
+import java.util.Enumeration;
+import java.math.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.authority.*;
+import com.netscape.certsrv.profile.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.publish.*;
+import java.security.cert.*;
+import java.io.IOException;
+import netscape.security.x509.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.cmscore.dbs.*;
+import com.netscape.cmscore.util.*;
+
+
+public class LdapRequestListener implements IRequestListener {
+ private boolean mInited = false;
+
+ /**
+ * handlers for request types (events)
+ * each handler implement IRequestListener
+ */
+ private Hashtable mRequestListeners = new Hashtable();
+
+ 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 = (IRequestListener) 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;
+ }
+
+ if (certs[0] instanceof X509CertImpl)
+ 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;
+ }
+
+ if (certs[0] instanceof X509CertImpl)
+ 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 =
+ (ICertificateRepository) ((ICertificateAuthority) auth).getCertificateRepository();
+
+ if (certdb == null) {
+ mProcessor.log(ILogger.LL_WARN, "Cert DB is null for " + auth);
+ } else {
+ try {
+ certRecord = (ICertRecord) 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;
+ }
+
+ if (certs[0] instanceof X509CertImpl)
+ 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 = (ICertificateRepository)
+ ((ICertificateAuthority) auth).getCertificateRepository();
+
+ if (certdb == null) {
+ mProcessor.log(ILogger.LL_WARN, "Cert DB is null for " + auth);
+ } else {
+ try {
+ certRecord = (ICertRecord) 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/pki/base/common/src/com/netscape/cmscore/ldap/LdapRule.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapRule.java
new file mode 100644
index 000000000..d3872740e
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapRule.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.cmscore.ldap;
+
+
+import java.util.*;
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.publish.*;
+import com.netscape.cmscore.util.*;
+
+
+/**
+ * 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 mappers = mProcessor.getMapperInsts().keys();
+ Enumeration publishers = mProcessor.getPublisherInsts().keys();
+
+ String map = NOMAPPER;
+
+ for (; mappers.hasMoreElements();) {
+ String name = (String) mappers.nextElement();
+
+ map = map + "," + name;
+ }
+ String publish = "";
+
+ for (; publishers.hasMoreElements();) {
+ String name = (String) publishers.nextElement();
+
+ publish = publish + "," + name;
+ }
+
+ epi_params = new String[] {
+ "type;choice(cacert,crl, certs);The publishing object type",
+ "mapper;choice(" + map + ");Use the mapper to find the ldap dn \nto publish the certificate or crl",
+ "publisher;choice(" + publish + ");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 getInstanceParams() {
+ //if (mProcessor == null) System.out.println("xxxxnull");
+ //dont know why the processor was null in getExtendedPluginInfo()
+ Enumeration mappers = mProcessor.getMapperInsts().keys();
+ Enumeration publishers = mProcessor.getPublisherInsts().keys();
+ String map = NOMAPPER;
+
+ for (; mappers.hasMoreElements();) {
+ String name = (String) mappers.nextElement();
+
+ map = map + "," + name;
+ }
+ String publish = "";
+
+ for (; publishers.hasMoreElements();) {
+ String name = (String) publishers.nextElement();
+
+ publish = publish + "," + 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 v = new Vector();
+
+ 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 getDefaultParams() {
+ Vector v = new Vector();
+
+ 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/pki/base/common/src/com/netscape/cmscore/ldap/LdapSimpleExpression.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapSimpleExpression.java
new file mode 100644
index 000000000..d3646c7b8
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapSimpleExpression.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.ldap;
+
+
+import java.util.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.publish.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.cmscore.util.*;
+
+
+/**
+ * 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 = (String) sc.get(mVar);
+ }catch (Exception e) {
+ givenVal = (String) 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 = (String) sc.get(mVar.toLowerCase());
+ }catch (Exception e) {
+ givenVal = (String) null;
+ }
+ }
+
+ if (givenVal == null) {
+ try {
+ givenVal = (String) sc.get(mVar.toUpperCase());
+ }catch (Exception e) {
+ givenVal = (String) 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 value)
+ throws ELdapException {
+ boolean result = false;
+ Enumeration e = (Enumeration) 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((Object) value[i]);
+ if (result)
+ break;
+ }
+ return result;
+ }
+
+ 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) 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 = new Boolean(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/pki/base/common/src/com/netscape/cmscore/ldap/PublishObject.java b/pki/base/common/src/com/netscape/cmscore/ldap/PublishObject.java
new file mode 100644
index 000000000..6818a48bf
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldap/PublishObject.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.cmscore.ldap;
+
+
+import java.security.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.ldap.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/ldap/PublisherProcessor.java b/pki/base/common/src/com/netscape/cmscore/ldap/PublisherProcessor.java
new file mode 100644
index 000000000..7d7b8e9b5
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldap/PublisherProcessor.java
@@ -0,0 +1,1504 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.util.*;
+import java.net.*;
+import java.util.*;
+import java.text.*;
+import java.math.*;
+import java.security.*;
+import java.security.cert.X509Certificate;
+import javax.servlet.*;
+import javax.servlet.http.*;
+import java.security.cert.*;
+import netscape.ldap.*;
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.authority.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.publish.*;
+
+import com.netscape.cmscore.util.*;
+import com.netscape.cmscore.cert.*;
+import com.netscape.cmscore.dbs.*;
+import com.netscape.cmscore.util.Debug;
+
+
+public class PublisherProcessor implements
+ IPublisherProcessor, IXcertPublisherProcessor {
+
+ public Hashtable mPublisherPlugins = new Hashtable();
+ public Hashtable mPublisherInsts = new Hashtable();
+ public Hashtable mMapperPlugins = new Hashtable();
+ public Hashtable mMapperInsts = new Hashtable();
+ public Hashtable mRulePlugins = new Hashtable();
+ public Hashtable mRuleInsts = new Hashtable();
+
+ /**
+ 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 mImpls = c.getSubStoreNames();
+
+ while (mImpls.hasMoreElements()) {
+ String id = (String) 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 instances = c.getSubStoreNames();
+
+ while (instances.hasMoreElements()) {
+ String insName = (String) instances.nextElement();
+ String implName = c.getString(insName + "." +
+ PROP_PLUGIN);
+ PublisherPlugin plugin =
+ (PublisherPlugin) 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) {
+ String errMsg = "PublisherProcessor:: init()-" + e.toString();
+
+ 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) {
+ String errMsg = "PublisherProcessor:: init()-" + e.toString();
+
+ 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) {
+ String errMsg = "PublisherProcessor: init()-" + e.toString();
+
+ 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 = (String) 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 = (String) instances.nextElement();
+ String implName = c.getString(insName + "." +
+ PROP_PLUGIN);
+ MapperPlugin plugin =
+ (MapperPlugin) 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) {
+ String errMsg = "PublisherProcessor:: init()-" + e.toString();
+
+ 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) {
+ String errMsg = "PublisherProcessor:: init()-" + e.toString();
+
+ 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) {
+ String errMsg = "PublisherProcessor: init()-" + e.toString();
+
+ 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 = (String) 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 = (String) instances.nextElement();
+ String implName = c.getString(insName + "." +
+ PROP_PLUGIN);
+ RulePlugin plugin =
+ (RulePlugin) 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) {
+ String errMsg = "PublisherProcessor:: init()-" + e.toString();
+
+ 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) {
+ String errMsg = "PublisherProcessor:: init()-" + e.toString();
+
+ 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) {
+ String errMsg = "PublisherProcessor: init()-" + e.toString();
+
+ 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");
+ }
+
+ if (mConfig.getBoolean(PROP_ENABLE, false)) {
+ mLdapRequestListener = new LdapRequestListener();
+ mLdapRequestListener.init(this, mLdapConfig);
+ mAuthority.registerRequestListener(mLdapRequestListener);
+ 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);
+ }
+ }
+ }
+
+ public void shutdown() {
+ CMS.debug("Shuting down publishing.");
+ try {
+ if (mLdapConnModule != null) {
+ mLdapConnModule.getLdapConnFactory().reset();
+ }
+ if (mLdapRequestListener != null) {
+ //mLdapRequestListener.shutdown();
+ mAuthority.removeRequestListener(mLdapRequestListener);
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ public Hashtable getRulePlugins() {
+ return mRulePlugins;
+ }
+
+ public Hashtable getRuleInsts() {
+ return mRuleInsts;
+ }
+
+ public Hashtable getMapperPlugins() {
+ return mMapperPlugins;
+ }
+
+ public Hashtable getPublisherPlugins() {
+ return mPublisherPlugins;
+ }
+
+ public Hashtable getMapperInsts() {
+ return mMapperInsts;
+ }
+
+ public Hashtable getPublisherInsts() {
+ return mPublisherInsts;
+ }
+
+ //certType can be client,server,ca,crl,smime
+ //XXXshould make it static to make it faster
+ public Enumeration getRules(String publishingType) {
+ Vector rules = new Vector();
+ Enumeration e = mRuleInsts.keys();
+
+ while (e.hasMoreElements()) {
+ String name = (String) 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() && rule.getType().equals(publishingType)) {
+ // 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 getRules(String publishingType, IRequest req) {
+ if (req == null) {
+ return getRules(publishingType);
+ }
+
+ Vector rules = new Vector();
+ Enumeration e = mRuleInsts.keys();
+
+ while (e.hasMoreElements()) {
+ String name = (String) 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() && rule.getType().equals(publishingType)) {
+ // 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 " + name + " for " + publishingType +
+ " request: " + req.getRequestId());
+ }
+ }
+ return rules.elements();
+ }
+
+ /**
+ public PublishRuleSet getPublishRuleSet()
+ {
+ return mRuleSet;
+ }
+ **/
+
+ public Vector getMapperDefaultParams(String implName) throws
+ ELdapException {
+ // is this a registered implname?
+ MapperPlugin plugin = (MapperPlugin)
+ 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 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 getMapperInstanceParams(String insName) throws
+ ELdapException {
+ ILdapMapper mapperInst = null;
+ MapperProxy proxy = (MapperProxy) mMapperInsts.get(insName);
+
+ if (proxy == null) {
+ return null;
+ }
+ mapperInst = proxy.getMapper();
+ if (mapperInst == null) {
+ return null;
+ }
+ Vector v = mapperInst.getInstanceParams();
+
+ return v;
+ }
+
+ public Vector getPublisherDefaultParams(String implName) throws
+ ELdapException {
+ // is this a registered implname?
+ PublisherPlugin plugin = (PublisherPlugin)
+ 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 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 = (MapperProxy)
+ mMapperInsts.get(insName);
+
+ if (proxy == null) {
+ return false;
+ }
+ return proxy.isEnable();
+ }
+
+ public ILdapMapper getActiveMapperInstance(String insName) {
+ MapperProxy proxy = (MapperProxy) mMapperInsts.get(insName);
+
+ if (proxy == null)
+ return null;
+ if (proxy.isEnable())
+ return proxy.getMapper();
+ else
+ return null;
+ }
+
+ public ILdapMapper getMapperInstance(String insName) {
+ MapperProxy proxy = (MapperProxy) mMapperInsts.get(insName);
+
+ if (proxy == null)
+ return null;
+ return proxy.getMapper();
+ }
+
+ public boolean isPublisherInstanceEnable(String insName) {
+ PublisherProxy proxy = (PublisherProxy)
+ mPublisherInsts.get(insName);
+
+ if (proxy == null) {
+ return false;
+ }
+ return proxy.isEnable();
+ }
+
+ public ILdapPublisher getActivePublisherInstance(String insName) {
+ PublisherProxy proxy = (PublisherProxy)
+ mPublisherInsts.get(insName);
+
+ if (proxy == null) {
+ return null;
+ }
+ if (proxy.isEnable())
+ return proxy.getPublisher();
+ else
+ return null;
+ }
+
+ public ILdapPublisher getPublisherInstance(String insName) {
+ PublisherProxy proxy = (PublisherProxy)
+ mPublisherInsts.get(insName);
+
+ if (proxy == null) {
+ return null;
+ }
+ return proxy.getPublisher();
+ }
+
+ public Vector getPublisherInstanceParams(String insName) throws
+ ELdapException {
+ ILdapPublisher publisherInst = getPublisherInstance(insName);
+
+ if (publisherInst == null) {
+ return null;
+ }
+ Vector v = publisherInst.getInstanceParams();
+
+ return v;
+ }
+
+ public Vector getRuleDefaultParams(String implName) throws
+ ELdapException {
+ // is this a registered implname?
+ RulePlugin plugin = (RulePlugin)
+ 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 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 getRuleInstanceParams(String implName) throws
+ ELdapException {
+ // is this a registered implname?
+ RulePlugin plugin = (RulePlugin)
+ 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 v = ruleInst.getInstanceParams();
+ IConfigStore rc = ruleInst.getConfigStore();
+
+ 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 = (ICertificateRepository) ca.getCertificateRepository();
+ ICertRecord certRec = (ICertRecord) 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.toString() +
+ " 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;
+ String errorRule = "";
+
+ if (!enabled())
+ return;
+
+ CMS.debug("PublishProcessor::publishCACert");
+
+ // get mapper and publisher for cert type.
+ Enumeration 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.toString());
+ error = true;
+ errorRule = errorRule + " " + rule.getInstanceName() +
+ " error:" + e.toString();
+ }
+ }
+ // set the ldap published flag.
+ if (!error) {
+ setPublishedFlag(cert.getSerialNumber(), true);
+ } else {
+ throw new
+ ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_FAILED", errorRule));
+ }
+ }
+
+ /**
+ * This function is never called. CMS does not unpublish
+ * CA certificate.
+ */
+ public void unpublishCACert(X509Certificate cert)
+ throws ELdapException {
+ boolean error = false;
+ String errorRule = "";
+
+ if (!enabled())
+ return;
+
+ // get mapper and publisher for cert type.
+ Enumeration 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 = errorRule + " " + rule.getInstanceName();
+ }
+ }
+
+ // set the ldap published flag.
+ if (!error) {
+ setPublishedFlag(cert.getSerialNumber(), false);
+ } else {
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_UNPUBLISH_FAILED", errorRule));
+ }
+ }
+
+ /**
+ * Publish crossCertificatePair
+ */
+ public void publishXCertPair(byte[] pair)
+ throws ELdapException {
+ boolean error = false;
+ String errorRule = "";
+
+ if (!enabled())
+ return;
+ CMS.debug("PublisherProcessor: in publishXCertPair()");
+
+ // get mapper and publisher for cert type.
+ Enumeration 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());
+ error = true;
+ errorRule = errorRule + " " + rule.getInstanceName() +
+ " error:" + e.toString();
+
+ CMS.debug("PublisherProcessor::publishXCertPair: error: " + e.toString());
+ }
+ }
+ }
+
+ /**
+ * Publishs regular user certificate based on the criteria
+ * set in the request.
+ */
+ public void publishCert(X509Certificate cert, IRequest req)
+ throws ELdapException {
+ boolean error = false;
+ String errorRule = "";
+
+ CMS.debug("In PublisherProcessor::publishCert");
+ if (!enabled())
+ return;
+
+ // get mapper and publisher for cert type.
+ Enumeration 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,bailing.");
+ return;
+ }
+
+ while (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 = errorRule + " " + 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));
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_FAILED", errorRule));
+ }
+ }
+
+ /**
+ * Unpublish user certificate. This is used by
+ * UnpublishExpiredJob.
+ */
+ public void unpublishCert(X509Certificate cert, IRequest req)
+ throws ELdapException {
+ boolean error = false;
+ String errorRule = "";
+
+ if (!enabled())
+ return;
+
+ // get mapper and publisher for cert type.
+ Enumeration 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 = errorRule + " " + rule.getInstanceName();
+ }
+ }
+
+ // set the ldap published flag.
+ if (!error) {
+ setPublishedFlag(cert.getSerialNumber(), false);
+ } else {
+ throw new ELdapException(CMS.getUserMessage("CMS_LDAP_UNPUBLISH_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.
+ * 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 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 = ((ILdapMapper) 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.toString());
+ }
+ }
+ }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 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.toString());
+ error = true;
+ errorRule = errorRule + " " + rule.getInstanceName();
+ CMS.debug("PublisherProcessor::publishCRL: error: " + e.toString());
+ }
+ }
+ } catch (ELdapException e) {
+ CMS.debug(
+ "Error publishing CRL to " + dn + ": " + e.toString());
+ 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) {
+ LdapCertMapResult result = 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) {
+ int n = ((Vector)dirdn).size();
+ for (int i = 0; i < n; i++) {
+ publisher.publish(conn, (String)(((Vector)dirdn).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 = (X509Certificate) ca.getCACert();
+
+ LDAPConnection conn = null;
+
+ try {
+ String dirdn = null;
+
+ if (mapper != null) {
+ LdapCertMapResult result = null;
+
+ if (mLdapConnModule != null) {
+ conn = mLdapConnModule.getConn();
+ }
+ try {
+ dirdn = mapper.map(conn, r, (Object) 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) {
+ LdapCertMapResult result = 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/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapAnonConnFactory.java b/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapAnonConnFactory.java
new file mode 100644
index 000000000..fbc99608a
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapAnonConnFactory.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.ldapconn;
+
+
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.ldap.*;
+
+
+/**
+ * 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;
+ }
+ // check if conn is valid and from this factory.
+ AnonConnection anon = (AnonConnection) conn;
+
+ if (anon.getFacId() != mConns) {
+ // returning a connection not from this factory.
+ log(ILogger.LL_WARN, "returnConn: unknown connection.");
+
+ /* swallow this error but see who's doing it. */
+ ELdapException e =
+ new ELdapException(CMS.getUserMessage("CMS_LDAP_UNKNOWN_RETURNED_CONN"));
+ }
+ // 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.");
+ ELdapException e =
+ new ELdapException(CMS.getUserMessage("CMS_LDAP_BAD_RETURNED_CONN"));
+ }
+ }
+
+ // this returned connection might authenticate as someone other than
+ // anonymonus. Reset it to anonymous first before it returns
+ // to the pool.
+ try {
+ anon.authenticate(null, null);
+
+ // 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 {
+ 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/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapAnonConnection.java b/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapAnonConnection.java
new file mode 100644
index 000000000..4be6bc33b
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapAnonConnection.java
@@ -0,0 +1,87 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.ldapconn;
+
+
+import netscape.ldap.*;
+import com.netscape.certsrv.ldap.*;
+
+
+/**
+ * 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 {
+
+ /**
+ * 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, new Boolean(followReferrals));
+
+ super.connect(connInfo.getVersion(),
+ connInfo.getHost(), connInfo.getPort(), null, null);
+ }
+
+ /**
+ * instantiates a connection to a ldap server
+ */
+ public LdapAnonConnection(String host, int port, int version,
+ LDAPSocketFactory fac)
+ throws LDAPException {
+ super(fac);
+ super.connect(version, host, port, null, null);
+ }
+
+ /**
+ * instantiates a non-secure connection to a ldap server
+ */
+ public LdapAnonConnection(String host, int port, int version)
+ throws LDAPException {
+ super();
+ super.connect(version, host, port, null, null);
+ }
+
+ /**
+ * overrides superclass connect.
+ * does not allow reconnect.
+ */
+ public void connect(String host, int port) throws LDAPException {
+ throw new RuntimeException(
+ "this LdapAnonConnection already connected: connect(h,p)");
+ }
+
+ /**
+ * 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/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapAuthInfo.java b/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapAuthInfo.java
new file mode 100644
index 000000000..667e68a85
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapAuthInfo.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.ldapconn;
+
+
+import java.util.Hashtable;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPException;
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.util.PasswordCallback;
+import org.mozilla.jss.util.PasswordCallbackInfo;
+import org.mozilla.jss.util.ConsolePasswordCallback;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.cmscore.base.*;
+import com.netscape.cmsutil.password.*;
+
+
+/**
+ * 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 passwords = new Hashtable();
+
+ /**
+ * 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] = (String) 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 (String[]) 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/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapBoundConnFactory.java b/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapBoundConnFactory.java
new file mode 100644
index 000000000..31e3dca1c
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapBoundConnFactory.java
@@ -0,0 +1,530 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.ldap.*;
+
+
+/**
+ * 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 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 = (BoundConnection) conn;
+
+ if (boundconn.getFacId() != mConns) {
+ log(ILogger.LL_WARN, "returnConn: unknown connection.");
+
+ /* swallow this exception but see who's doing it. */
+ ELdapException e =
+ new ELdapException(CMS.getUserMessage("CMS_LDAP_UNKNOWN_RETURNED_CONN"));
+ }
+ for (int i = 0; i < mNumConns; i++) {
+ if (mConns[i] == conn) {
+ CMS.debug(
+ "returnConn: previously returned connection.");
+
+ /* swallow this exception but see who's doing it */
+ ELdapException e =
+ new ELdapException(CMS.getUserMessage("CMS_LDAP_BAD_RETURNED_CONN"));
+ }
+ }
+ 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 {
+ 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/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapBoundConnection.java b/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapBoundConnection.java
new file mode 100644
index 000000000..8a6b98fc3
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapBoundConnection.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.cmscore.ldapconn;
+
+
+import netscape.ldap.*;
+import java.util.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.ldap.*;
+
+
+/**
+ * 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 {
+ // LDAPConnection calls authenticate so must set this for first
+ // authenticate call.
+ private boolean mAuthenticated = false;
+
+ /**
+ * 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, new Boolean(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 mech, String packageName,
+ Properties props, Object getter)
+ throws LDAPException {
+
+ /**
+ if (mAuthenticated) {
+ throw new RuntimeException(
+ "this LdapBoundConnection already authenticated: auth(mech)");
+ }
+ **/
+ super.authenticate(dn, mech, packageName, props, getter);
+ mAuthenticated = true;
+ }
+
+ /**
+ * Overrides same method in LDAPConnection to do prevent re-authentication.
+ */
+ public void authenticate(String dn, String mechs[], String packageName,
+ Properties props, Object getter)
+ throws LDAPException {
+
+ /**
+ if (mAuthenticated) {
+ throw new RuntimeException(
+ "this LdapBoundConnection is already authenticated: auth(mechs)");
+ }
+ **/
+ super.authenticate(dn, mechs, packageName, 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/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapConnInfo.java b/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapConnInfo.java
new file mode 100644
index 000000000..ba037d854
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapConnInfo.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.ldapconn;
+
+
+import netscape.ldap.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.ldap.*;
+
+
+/**
+ * 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 = (String) 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/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.java b/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.java
new file mode 100644
index 000000000..b9f7d78eb
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.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.cmscore.ldapconn;
+
+
+import java.net.*;
+import java.io.*;
+import netscape.ldap.*;
+import org.mozilla.jss.ssl.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.ldap.*;
+
+
+/**
+ * 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);
+ s.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) {
+ 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) {
+ }
+
+ 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/pki/base/common/src/com/netscape/cmscore/listeners/ListenerPlugin.java b/pki/base/common/src/com/netscape/cmscore/listeners/ListenerPlugin.java
new file mode 100644
index 000000000..a7961e207
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/listeners/ListenerPlugin.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.listeners;
+
+
+import com.netscape.certsrv.base.*;
+import java.util.*;
+import java.lang.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/logging/AuditEventFactory.java b/pki/base/common/src/com/netscape/cmscore/logging/AuditEventFactory.java
new file mode 100644
index 000000000..e8c7032d1
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/logging/AuditEventFactory.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.logging;
+
+
+import java.util.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/logging/AuditFormat.java b/pki/base/common/src/com/netscape/cmscore/logging/AuditFormat.java
new file mode 100644
index 000000000..0af38f168
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/logging/AuditFormat.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.logging;
+
+
+import com.netscape.certsrv.logging.*;
+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}";
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/logging/LogQueue.java b/pki/base/common/src/com/netscape/cmscore/logging/LogQueue.java
new file mode 100644
index 000000000..24336d308
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/logging/LogQueue.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.cmscore.logging;
+
+
+import java.io.*;
+import java.util.*;
+import java.text.MessageFormat;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.CMS;
+
+
+/**
+ * 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 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();
+
+ }
+
+ /**
+ * 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++) {
+ ((ILogEventListener) mListeners.elementAt(i)).shutdown();
+ }
+ mListeners = null;
+ }
+
+ /**
+ * 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 {
+ ((ILogEventListener) 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((ILogEventListener)
+ mListeners.elementAt(i));
+ }
+ }
+ }
+
+ /**
+ * Flushes the log buffers (if any)
+ */
+ public void flush() {
+ for (int i = 0; i < mListeners.size(); i++) {
+ ((ILogEventListener) mListeners.elementAt(i)).flush();
+ }
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/logging/LogSubsystem.java b/pki/base/common/src/com/netscape/cmscore/logging/LogSubsystem.java
new file mode 100644
index 000000000..9a9d4bd4f
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/logging/LogSubsystem.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.logging;
+
+
+import java.io.*;
+import java.util.*;
+import java.text.MessageFormat;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.CMS;
+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 mLogPlugins = new Hashtable();
+ public Hashtable mLogInsts = new Hashtable();
+
+ /**
+ * 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 mImpls = c.getSubStoreNames();
+
+ while (mImpls.hasMoreElements()) {
+ String id = (String) 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 instances = c.getSubStoreNames();
+
+ while (instances.hasMoreElements()) {
+ String insName = (String) instances.nextElement();
+ String implName = c.getString(insName + "." +
+ PROP_PLUGIN);
+ LogPlugin plugin =
+ (LogPlugin) 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) {
+ String errMsg = "LogSubsystem:: init()-" + e.toString();
+
+ throw new EBaseException(insName + ":Failed to instantiate class " + className);
+ } catch (IllegalAccessException e) {
+ String errMsg = "LogSubsystem:: init()-" + e.toString();
+
+ throw new EBaseException(insName + ":Failed to instantiate class " + className);
+ } catch (InstantiationException e) {
+ String errMsg = "LogSubsystem:: init()-" + e.toString();
+
+ 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 (logInst == null) {
+ throw new EBaseException("Failed to instantiate class " + className);
+ }
+
+ 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 enum1 = mLogInsts.keys();
+
+ while (enum1.hasMoreElements()) {
+ String instName = (String) enum1.nextElement();
+
+ Debug.trace("about to call inst=" + instName + " in LogSubsystem.startup()");
+ ILogEventListener inst = (ILogEventListener)
+ 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();
+
+ try {
+ return cs.getString("pluginName", "");
+ } catch (EBaseException e) {
+ return "";
+ }
+ }
+
+ /**
+ * Retrieve log instance by it's name
+ */
+ public ILogEventListener getLogInstance(String insName) {
+ return (ILogEventListener) mLogInsts.get(insName);
+ }
+
+ public Hashtable getLogPlugins() {
+ return mLogPlugins;
+ }
+
+ public Hashtable getLogInsts() {
+ return mLogInsts;
+ }
+
+ public Vector getLogDefaultParams(String implName) throws
+ ELogException {
+ // is this a registered implname?
+ LogPlugin plugin = (LogPlugin)
+ 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 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 getLogInstanceParams(String insName) throws
+ ELogException {
+ ILogEventListener logInst = getLogInstance(insName);
+
+ if (logInst == null) {
+ return null;
+ }
+ Vector v = logInst.getInstanceParams();
+
+ return v;
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/logging/Logger.java b/pki/base/common/src/com/netscape/cmscore/logging/Logger.java
new file mode 100644
index 000000000..b15717ca4
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/logging/Logger.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.cmscore.logging;
+
+
+import java.io.*;
+import java.util.*;
+import com.netscape.certsrv.logging.*;
+
+import com.netscape.cmscore.util.*;
+
+
+/**
+ * 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 mFactories = new Hashtable();
+
+ /**
+ * 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(Integer.toString(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[]) {
+ mLogQueue.log(create(evtClass, prop, source, level, msg, params, ILogger.L_SINGLELINE));
+ }
+
+ //******************** 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) {
+ mLogQueue.log(create(evtClass, prop, source, level, msg, params, multiline));
+ }
+
+ //******************** 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 = (ILogEventFactory) mFactories.get(
+ Integer.toString(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/pki/base/common/src/com/netscape/cmscore/logging/SignedAuditEventFactory.java b/pki/base/common/src/com/netscape/cmscore/logging/SignedAuditEventFactory.java
new file mode 100644
index 000000000..5faa0baba
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/logging/SignedAuditEventFactory.java
@@ -0,0 +1,124 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.logging;
+
+
+import java.util.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+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/pki/base/common/src/com/netscape/cmscore/logging/SignedAuditLogger.java b/pki/base/common/src/com/netscape/cmscore/logging/SignedAuditLogger.java
new file mode 100644
index 000000000..0bb99fb5b
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/logging/SignedAuditLogger.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.logging;
+
+
+import java.io.*;
+import java.util.*;
+import com.netscape.certsrv.logging.*;
+
+import com.netscape.cmscore.util.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/logging/SystemEventFactory.java b/pki/base/common/src/com/netscape/cmscore/logging/SystemEventFactory.java
new file mode 100644
index 000000000..4e5131311
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/logging/SystemEventFactory.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.logging;
+
+
+import java.util.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/notification/EmailFormProcessor.java b/pki/base/common/src/com/netscape/cmscore/notification/EmailFormProcessor.java
new file mode 100644
index 000000000..b04186c3a
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/notification/EmailFormProcessor.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.notification;
+
+
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.notification.*;
+import java.util.*;
+import java.lang.*;
+
+
+/**
+ * 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 mContent = new Vector();
+ Hashtable 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 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 e = mTok2vals.keys(); e.hasMoreElements();) {
+ // get key
+ tok = (String) 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(o);
+ } 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);
+ int tl = token_keys.length;
+
+ 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 vec) {
+ String content = null;
+
+ Enumeration e = vec.elements();
+
+ // initialize content with first element
+ if (e.hasMoreElements()) {
+ content = (String) e.nextElement();
+ }
+
+ while (e.hasMoreElements()) {
+ String v = (String) e.nextElement();
+
+ content += v;
+ }
+
+ return content;
+ }
+
+ /**
+ * 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/pki/base/common/src/com/netscape/cmscore/notification/EmailResolverKeys.java b/pki/base/common/src/com/netscape/cmscore/notification/EmailResolverKeys.java
new file mode 100644
index 000000000..5f053c297
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/notification/EmailResolverKeys.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.notification;
+
+
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.notification.*;
+import java.util.*;
+
+
+/**
+ * Email resolver keys as input to email resolvers
+ * <P>
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class EmailResolverKeys implements IEmailResolverKeys {
+ private Hashtable mKeys = null;
+
+ public EmailResolverKeys() {
+ mKeys = new Hashtable();
+ }
+
+ /**
+ * 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 ((Object) 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 keys 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 getElements() {
+ return (mKeys.elements());
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/notification/EmailTemplate.java b/pki/base/common/src/com/netscape/cmscore/notification/EmailTemplate.java
new file mode 100644
index 000000000..483426414
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/notification/EmailTemplate.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.cmscore.notification;
+
+
+import java.lang.*;
+import java.io.*;
+import java.util.*;
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.notification.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.cmscore.util.*;
+
+
+/**
+ * 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 = new String();
+ 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())) {
+ String error = "Template: " + mTemplateFile + " does not exist or invalid";
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_NOTIFY_TEMPLATE_NOT_EXIST"));
+ return false;
+ }
+
+ /* create input stream */
+ FileReader input;
+
+ try {
+ input = new FileReader(template);
+ } catch (FileNotFoundException e) {
+ String error = "Template: " + mTemplateFile + " not found";
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_NOTIFY_TEMPLATE_NOT_FOUND"));
+
+ return false;
+ }
+
+ /* load template */
+ mFileContents = loadFile(input);
+ if (mFileContents == null) {
+ String error = "Template: Error loading file into string";
+
+ 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) {
+ String error = "Template: Error loading file";
+
+ 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/pki/base/common/src/com/netscape/cmscore/notification/ReqCertEmailResolver.java b/pki/base/common/src/com/netscape/cmscore/notification/ReqCertEmailResolver.java
new file mode 100644
index 000000000..28f0e364c
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/notification/ReqCertEmailResolver.java
@@ -0,0 +1,151 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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 com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.notification.*;
+import com.netscape.certsrv.apps.*;
+import java.security.*;
+import java.security.cert.*;
+import java.io.IOException;
+import netscape.security.x509.*;
+import com.netscape.certsrv.common.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/notification/ReqCertSANameEmailResolver.java b/pki/base/common/src/com/netscape/cmscore/notification/ReqCertSANameEmailResolver.java
new file mode 100644
index 000000000..440e62e85
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/notification/ReqCertSANameEmailResolver.java
@@ -0,0 +1,268 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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 com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.notification.*;
+import java.util.Enumeration;
+import java.security.*;
+import java.security.cert.*;
+import java.io.IOException;
+import netscape.security.x509.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+
+
+/**
+ * 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 e = gn.elements();
+
+ while (e.hasMoreElements()) {
+ Object g = (Object) e.nextElement();
+
+ GeneralName gni =
+ (GeneralName) g;
+
+ if (gni.getType() ==
+ GeneralNameInterface.NAME_RFC822) {
+ CMS.debug("got an subjectalternatename email");
+
+ String nameString = g.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/pki/base/common/src/com/netscape/cmscore/policy/AndExpression.java b/pki/base/common/src/com/netscape/cmscore/policy/AndExpression.java
new file mode 100644
index 000000000..fb3134ffa
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/AndExpression.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.policy;
+
+
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.policy.*;
+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.
+ *
+ * @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/pki/base/common/src/com/netscape/cmscore/policy/GeneralNameUtil.java b/pki/base/common/src/com/netscape/cmscore/policy/GeneralNameUtil.java
new file mode 100644
index 000000000..7a8ab4342
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/GeneralNameUtil.java
@@ -0,0 +1,672 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.io.*;
+import java.util.Vector;
+import java.util.Enumeration;
+
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.policy.*;
+import com.netscape.cmscore.util.Debug;
+
+
+/**
+ * Class that can be used to form general names from configuration file.
+ * Used by policies and extension commands.
+ */
+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 = com.netscape.osutil.OSUtil.AtoB(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 (GeneralNameConfig[]) 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 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 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 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 formGeneralNames(Object value)
+ throws EBaseException {
+ Vector gns = new Vector();
+ 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 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 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 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 params) {
+ params.addElement(mNameDot + PROP_REQUEST_ATTR + "=" + mRequestAttr);
+ super.getInstanceParams(params);
+ }
+
+ public static void getDefaultParams(String name, Vector 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 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/pki/base/common/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java b/pki/base/common/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java
new file mode 100644
index 000000000..63b28d995
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java
@@ -0,0 +1,1552 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.text.*;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IPolicy;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.policy.*;
+import com.netscape.certsrv.authority.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.cmscore.base.*;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.cmscore.util.*;
+import com.netscape.cmscore.request.ARequestQueue;
+
+
+/**
+ * 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.
+ *
+ * @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 DEF_UNDELETABLE_POLICIES =
+ new Hashtable();
+
+ private String mId = "Policy";
+ private Vector mPolicyOrder = new Vector();
+ private Hashtable mImplTable = new Hashtable();
+ private Hashtable mInstanceTable = new Hashtable();
+ 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 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 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 mImpls = c.getSubStoreNames();
+
+ while (mImpls.hasMoreElements()) {
+ String id = (String) 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 = (String) 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 =
+ (RegisteredPolicy) 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();
+ if (rule instanceof IPolicyRule)
+ ((IPolicyRule) 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 = (String) 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";
+ }
+
+ private void setError(IRequest req, String format, String arg) {
+ if (format == null)
+ return;
+ EPolicyException ex = new EPolicyException(format, arg);
+
+ Vector ev = req.getExtDataInStringVector(IRequest.ERRORS);
+ if (ev == null) {
+ ev = new Vector();
+ }
+ ev.addElement(ex.toString());
+ req.setExtData(IRequest.ERRORS, ev);
+ }
+
+ public Enumeration getPolicyImpls() {
+ Vector impls = new Vector();
+ Enumeration enum1 = mImplTable.elements();
+ Enumeration ret = null;
+
+ try {
+ while (enum1.hasMoreElements()) {
+ RegisteredPolicy regPolicy =
+ (RegisteredPolicy) 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 getPolicyImplsInfo() {
+ Vector impls = new Vector();
+ Enumeration enum1 = mImplTable.elements();
+ Enumeration ret = null;
+
+ try {
+ while (enum1.hasMoreElements()) {
+ RegisteredPolicy regPolicy =
+ (RegisteredPolicy) enum1.nextElement();
+
+ impls.addElement(regPolicy.getId());
+
+ }
+ ret = impls.elements();
+ } catch (Exception e) {
+ Debug.printStackTrace(e);
+ }
+ return ret;
+ }
+
+ public IPolicyRule getPolicyImpl(String id) {
+ RegisteredPolicy regImpl = (RegisteredPolicy)
+ 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 getPolicyImplConfig(String id) {
+ IPolicyRule rp = getPolicyImpl(id);
+
+ if (rp == null)
+ return null;
+ Vector v = rp.getDefaultParams();
+
+ if (v == null)
+ v = new Vector();
+ 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 =
+ (RegisteredPolicy) 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 e = mInstanceTable.elements();
+
+ for (; e.hasMoreElements();) {
+ PolicyInstance inst = (PolicyInstance) 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 getPolicyInstances() {
+ Vector rules = new Vector();
+ Enumeration enum1 = mPolicyOrder.elements();
+ Enumeration ret = null;
+
+ try {
+ while (enum1.hasMoreElements()) {
+ PolicyInstance instance =
+ (PolicyInstance) mInstanceTable.get((String) enum1.nextElement());
+
+ rules.addElement(instance.getRule());
+
+ }
+ ret = rules.elements();
+ } catch (Exception e) {
+ Debug.printStackTrace(e);
+ }
+ return ret;
+ }
+
+ public Enumeration getPolicyInstancesInfo() {
+ Vector rules = new Vector();
+ Enumeration enum1 = mPolicyOrder.elements();
+ Enumeration ret = null;
+
+ try {
+ while (enum1.hasMoreElements()) {
+ String ruleName = (String) enum1.nextElement();
+ PolicyInstance instance =
+ (PolicyInstance) 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 = (PolicyInstance)
+ mInstanceTable.get(id);
+
+ return (policyInstance == null) ? null : policyInstance.getRule();
+ }
+
+ public Vector getPolicyInstanceConfig(String id) {
+ PolicyInstance policyInstance = (PolicyInstance)
+ mInstanceTable.get(id);
+
+ if (policyInstance == null)
+ return null;
+ Vector v = policyInstance.getRule().getInstanceParams();
+
+ if (v == null)
+ v = new Vector();
+ 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 =
+ (PolicyInstance) 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 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 = (String) 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 keys = ht.keys(); keys.hasMoreElements();) {
+ String key = (String) keys.nextElement();
+ String val = (String) 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 = (String) 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 = ((String) 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 ht)
+ throws EBaseException {
+ // The instance id should be there already
+ PolicyInstance 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 = (String) 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 = (String) 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 = ((String) 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 = (IExpression)
+ 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 oldkeys = oldStore.keys();
+ oldkeys.hasMoreElements();) {
+ String k = (String) oldkeys.nextElement();
+ String v = (String) oldStore.getString(k);
+
+ newStore.put(k, v);
+ }
+
+ // put modified params.
+ for (Enumeration newkeys = ht.keys();
+ newkeys.hasMoreElements();) {
+ String k = (String) newkeys.nextElement();
+ String v = (String) 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 e = newStore.keys(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+
+ if (key != null) {
+ Debug.trace(
+ "oldstore.put(" + key + "," +
+ (String) newStore.getString(key) + ")");
+ oldStore.put(key, (String) 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 policyOrder = new Vector();
+ 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 enum1 = policyOrder.elements();
+ enum1.hasMoreElements();) {
+ String instanceName = (String) enum1.nextElement();
+ PolicyInstance pInstance = (PolicyInstance)
+ 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 v1, Vector 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 rules) {
+ StringBuffer sb = new StringBuffer();
+
+ for (Enumeration e = rules.elements(); e.hasMoreElements();) {
+ sb.append((String) e.nextElement());
+ sb.append(",");
+ }
+ if (sb.length() > 0)
+ sb.setLength(sb.length() - 1);
+ return new String(sb);
+ }
+
+ private String getRuleOrderString(Vector 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 rules = new Vector();
+ 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 rules = new Vector();
+ 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();
+ for (Enumeration e = rules.elements(); e.hasMoreElements();) {
+ String urn = (String) 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 e = mUndeletablePolicies.keys();
+ e.hasMoreElements();) {
+ String urn = (String) e.nextElement();
+
+ // See if the rule is in the instance table.
+ PolicyInstance inst = (PolicyInstance) 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 = (IExpression)
+ 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;
+ }
+}
+
+
+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/pki/base/common/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java b/pki/base/common/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java
new file mode 100644
index 000000000..3f421fca4
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java
@@ -0,0 +1,46 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.request.*;
+import com.netscape.certsrv.policy.*;
+
+import com.netscape.cmscore.util.Debug;
+
+
+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/pki/base/common/src/com/netscape/cmscore/policy/OrExpression.java b/pki/base/common/src/com/netscape/cmscore/policy/OrExpression.java
new file mode 100644
index 000000000..dfbcb0ef6
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/OrExpression.java
@@ -0,0 +1,65 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.policy;
+
+
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.policy.*;
+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.
+ *
+ * @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/pki/base/common/src/com/netscape/cmscore/policy/PolicyPredicateParser.java b/pki/base/common/src/com/netscape/cmscore/policy/PolicyPredicateParser.java
new file mode 100644
index 000000000..46a874291
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/PolicyPredicateParser.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.cmscore.policy;
+
+
+import java.util.*;
+import java.io.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.policy.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.apps.CMS;
+
+
+/**
+ * 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 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();
+ boolean opANDSeen;
+ boolean opORSeen;
+
+ 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 expSet = new Vector();
+ 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((IExpression) expSet.elementAt(0), null);
+
+ for (int i = 1; i < size; i++)
+ orExp = new OrExpression(orExp,
+ (IExpression) 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 expVector = new Vector();
+
+ 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 = (SimpleExpression) expVector.elementAt(0);
+ SimpleExpression exp2 = (SimpleExpression) expVector.elementAt(1);
+ AndExpression andExp = new AndExpression(exp1, exp2);
+
+ for (int i = 2; i < size; i++) {
+ andExp = new AndExpression(andExp, (SimpleExpression) 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;
+ int endOfString;
+ String nextToken;
+ boolean first;
+
+ public PredicateTokenizer(String predString) {
+ input = predString;
+ currentIndex = 0;
+ nextToken = null;
+ }
+
+ public boolean hasMoreTokens() {
+ return (currentIndex != -1);
+ }
+
+ public String nextToken() {
+ 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.
+ toReturn = null;
+ System.out.println("We shouldn't be here!");
+ }
+ if (toReturn == null)
+ return null;
+ else {
+ String trimmed = toReturn.trim();
+
+ if (trimmed == null || trimmed.length() == 0)
+ return nextToken();
+ else
+ return trimmed;
+ }
+ }
+}
+
+
+class AttributeSet implements IAttrSet {
+ Hashtable ht = new Hashtable();
+ public AttributeSet() {
+ }
+
+ public void delete(String name)
+ throws EBaseException {
+ Object ob = ht.get(name);
+
+ ht.remove(ob);
+ }
+
+ public Object get(String name)
+ throws EBaseException {
+ return ht.get(name);
+ }
+
+ public void set(String name, Object ob)
+ throws EBaseException {
+ ht.put(name, ob);
+ }
+
+ public Enumeration getElements() {
+ return ht.elements();
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/policy/PolicySet.java b/pki/base/common/src/com/netscape/cmscore/policy/PolicySet.java
new file mode 100644
index 000000000..6ec1fa5c2
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/PolicySet.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.cmscore.policy;
+
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+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.
+ *
+ * @author kanda
+ * @version $Revision$, $Date$
+ */
+public class PolicySet implements IPolicySet {
+ private String mName;
+ private Vector mRuleNames = new Vector();
+ private Vector mRules = new Vector();
+ 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 name 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 name 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 name 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 (IPolicyRule) mRules.elementAt(index);
+ }
+
+ /**
+ * Returns an enumeration of rules.
+ * <P>
+ *
+ * @return An enumeration of rules.
+ */
+ public Enumeration 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.
+ int cnt;
+
+ if ((cnt = 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 = (String) mRuleNames.elementAt(index);
+ IPolicyRule rule = (IPolicyRule) 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;
+ ((IPolicyRule) 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 = (String) 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/pki/base/common/src/com/netscape/cmscore/policy/SimpleExpression.java b/pki/base/common/src/com/netscape/cmscore/policy/SimpleExpression.java
new file mode 100644
index 000000000..7b771442c
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/SimpleExpression.java
@@ -0,0 +1,435 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.policy.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.apps.CMS;
+
+
+/**
+ * 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.
+ *
+ * @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 = (Enumeration) 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((Object) 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 = new Boolean(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/pki/base/common/src/com/netscape/cmscore/profile/ProfileSubsystem.java b/pki/base/common/src/com/netscape/cmscore/profile/ProfileSubsystem.java
new file mode 100644
index 000000000..25635e901
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/profile/ProfileSubsystem.java
@@ -0,0 +1,319 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.util.*;
+import java.io.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.registry.*;
+import com.netscape.certsrv.profile.*;
+
+
+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;
+ private ISubsystem mOwner = null;
+ private Vector mProfileIds = new Vector();
+ private Hashtable mProfiles = new Hashtable();
+ private Hashtable mProfileClassIds = new Hashtable();
+
+ /**
+ * 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 = (String) st.nextToken();
+ IConfigStore subStore = config.getSubStore(id);
+ String classid = subStore.getString(PROP_CLASS_ID);
+ IPluginInfo info = registry.getPluginInfo("profile", classid);
+ String configPath = subStore.getString(PROP_CONFIG);
+
+ CMS.debug("Start Profile Creation - " + id + " " + classid + " " + info.getClassName());
+ IProfile profile = createProfile(id, classid, info.getClassName(),
+ configPath);
+
+ CMS.debug("Done Profile Creation - " + id);
+ }
+
+ Enumeration ee = getProfileIds();
+
+ while (ee.hasMoreElements()) {
+ String id = (String) 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, ",");
+ String list = "";
+
+ while (tokenizer.hasMoreTokens()) {
+ String element = (String) tokenizer.nextToken();
+
+ if (!element.equals(id)) {
+ list = list + element + ",";
+ }
+ }
+ if (!list.equals(""))
+ list = list.substring(0, list.length() - 1);
+
+ mConfig.putString(PROP_LIST, list);
+ mConfig.removeSubStore(id);
+ File file1 = new File(configPath);
+
+ file1.delete();
+ 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.removeAllElements();
+ mProfiles.clear();
+ mProfiles = null;
+ mProfileClassIds.clear();
+ mProfileClassIds = null;
+ }
+
+ /**
+ * 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 = (IProfile) 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 = (IProfile) 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 = (IProfile) 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 = (IProfile) 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 (IProfile) mProfiles.get(id);
+ }
+
+ public String getProfileClassId(String id) {
+ return (String) mProfileClassIds.get(id);
+ }
+
+ /**
+ * Retrieves a list of profile ids. The return
+ * list is of type String.
+ */
+ public Enumeration 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/pki/base/common/src/com/netscape/cmscore/registry/PluginInfo.java b/pki/base/common/src/com/netscape/cmscore/registry/PluginInfo.java
new file mode 100644
index 000000000..d0ed9324e
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/registry/PluginInfo.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.registry;
+
+
+import java.util.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.registry.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/registry/PluginRegistry.java b/pki/base/common/src/com/netscape/cmscore/registry/PluginRegistry.java
new file mode 100644
index 000000000..a424d8b73
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/registry/PluginRegistry.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.cmscore.registry;
+
+
+import java.util.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.registry.*;
+
+
+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;
+ private ISubsystem mOwner = null;
+ private Hashtable mTypes = new Hashtable();
+
+ 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 plugins = (Hashtable)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 plugins = (Hashtable) mTypes.get(type);
+
+ if (plugins == null) {
+ plugins = new Hashtable();
+ 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 types = mTypes.keys();
+ StringBuffer typesBuf = new StringBuffer();
+
+ while (types.hasMoreElements()) {
+ String type = (String) types.nextElement();
+
+ typesBuf.append(type);
+ if (types.hasMoreElements()) {
+ typesBuf.append(",");
+ }
+ Hashtable mPlugins = (Hashtable) mTypes.get(type);
+ StringBuffer idsBuf = new StringBuffer();
+ Enumeration plugins = mPlugins.keys();
+
+ while (plugins.hasMoreElements()) {
+ String id = (String) plugins.nextElement();
+
+ idsBuf.append(id);
+ if (plugins.hasMoreElements()) {
+ idsBuf.append(",");
+ }
+ IPluginInfo plugin = (IPluginInfo) 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();
+ mTypes = null;
+ }
+
+ /**
+ * 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 getTypeNames() {
+ return mTypes.keys();
+ }
+
+ /**
+ * Returns a list of identifiers of the given type.
+ */
+ public Enumeration getIds(String type) {
+ Hashtable plugins = (Hashtable) mTypes.get(type);
+
+ if (plugins == null)
+ return null;
+ return plugins.keys();
+ }
+
+ /**
+ * Retrieves the plugin information.
+ */
+ public IPluginInfo getPluginInfo(String type, String id) {
+ Hashtable plugins = (Hashtable) mTypes.get(type);
+
+ if (plugins == null)
+ return null;
+ return (IPluginInfo) plugins.get(id);
+ }
+
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/request/ARequestQueue.java b/pki/base/common/src/com/netscape/cmscore/request/ARequestQueue.java
new file mode 100644
index 000000000..f6d23497a
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/request/ARequestQueue.java
@@ -0,0 +1,1540 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CRLException;
+import java.math.BigInteger;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ByteArrayInputStream;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.base.IAttrSet;
+
+import com.netscape.certsrv.logging.ILogger;
+
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authentication.AuthToken;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.X509ExtensionException;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.util.DerInputStream;
+
+
+/**
+ * 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 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 {
+ // 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 e = req.getExtDataKeys();
+ while (e.hasMoreElements()) {
+ String key = (String) 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 hash) {
+ if (hash == null) {
+ return false;
+ }
+ Enumeration keys = hash.keys();
+ while (keys.hasMoreElements()) {
+ Object key = keys.nextElement();
+ if (! ((key instanceof String) &&
+ isValidExtDataKey((String)key)) ) {
+ return false;
+ }
+
+ 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 value) {
+ if ( !(isValidExtDataKey(key) && isValidExtDataHashtableValue(value)) ) {
+ return false;
+ }
+
+ mExtData.put(key, new ExtDataHashtable(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;
+ }
+
+ public Hashtable getExtDataInHashtable(String key) {
+ Object value = mExtData.get(key);
+ if (value == null) {
+ return null;
+ }
+ if (! (value instanceof Hashtable)) {
+ return null;
+ }
+ return new ExtDataHashtable((Hashtable)value);
+ }
+
+ public Enumeration 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;
+ }
+
+ Hashtable existingValue = (Hashtable)mExtData.get(key);
+ if (existingValue == null) {
+ existingValue = new ExtDataHashtable();
+ mExtData.put(key, existingValue);
+ }
+ existingValue.put(subkey, value);
+ return true;
+ }
+
+ public String getExtDataInString(String key, String subkey) {
+ Hashtable value = getExtDataInHashtable(key);
+ if (value == null) {
+ return null;
+ }
+ return (String)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 = (String[])stringVector.toArray(new String[0]);
+ } catch (ArrayStoreException e) {
+ return false;
+ }
+ return setExtData(key, stringArray);
+ }
+
+ public Vector getExtDataInStringVector(String key) {
+ String[] stringArray = getExtDataInStringArray(key);
+ if (stringArray == null) {
+ return null;
+ }
+ return new Vector(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 hash = new Hashtable();
+ Enumeration keys = data.getElements();
+ while (keys.hasMoreElements()) {
+ try {
+ String authKey = (String) keys.nextElement();
+ hash.put(authKey, data.getInString(authKey));
+ } catch (ClassCastException e) {
+ return false;
+ }
+ }
+ return setExtData(key, hash);
+ }
+
+ public IAuthToken getExtDataInAuthToken(String key) {
+ Hashtable hash = getExtDataInHashtable(key);
+ if (hash == null) {
+ return null;
+ }
+ AuthToken authToken = new AuthToken(null);
+ Enumeration keys = hash.keys();
+ while (keys.hasMoreElements()) {
+ try {
+ String hashKey = (String) keys.nextElement();
+ authToken.set(hashKey, (String) 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 hashValue = new Hashtable();
+ 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 hashValue = getExtDataInHashtable(key);
+ if (hashValue == null) {
+ return null;
+ }
+ Set arrayKeys = hashValue.keySet();
+ Vector listValue = new Vector(arrayKeys.size());
+ for (Iterator iter = arrayKeys.iterator(); iter.hasNext();) {
+ String arrayKey = (String)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 (String[])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 mExtData = new ExtDataHashtable();
+
+ Date mCreationTime = CMS.getCurrentDate();
+ Date mModificationTime = CMS.getCurrentDate();
+}
+
+class RequestIAttrSetWrapper implements IAttrSet {
+ 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 getElements() {
+ return mRequest.getExtDataKeys();
+ }
+}
+
+
+/**
+ * Example of a specialized request class.
+ */
+class EnrollmentRequest
+ extends Request
+ implements IEnrollmentRequest {
+ 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 Object nextElement() {
+ RequestId next = mNext;
+
+ update();
+
+ return next;
+ }
+
+ public RequestId nextRequestId() {
+ RequestId next = mNext;
+
+ update();
+
+ return next;
+ }
+
+ public RequestListByStatus(Enumeration 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 = (RequestId) 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 mEnumeration;
+ protected RequestId mNext;
+}
+
+
+class RequestList
+ implements IRequestList {
+ public boolean hasMoreElements() {
+ return mEnumeration.hasMoreElements();
+ }
+
+ public Object nextElement() {
+ return mEnumeration.nextElement();
+ }
+
+ public RequestId nextRequestId() {
+ return (RequestId) mEnumeration.nextElement();
+ }
+
+ public Object nextRequest() {
+ return null;
+ }
+
+ public IRequest nextRequestObject() {
+ return null;
+ }
+
+ public RequestList(Enumeration e) {
+ mEnumeration = e;
+ }
+
+ protected Enumeration 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/pki/base/common/src/com/netscape/cmscore/request/ARequestRecord.java b/pki/base/common/src/com/netscape/cmscore/request/ARequestRecord.java
new file mode 100644
index 000000000..b81d5d211
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/request/ARequestRecord.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.cmscore.request;
+
+
+import java.util.Hashtable;
+import java.util.Date;
+
+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 mExtData;
+};
diff --git a/pki/base/common/src/com/netscape/cmscore/request/CertRequestConstants.java b/pki/base/common/src/com/netscape/cmscore/request/CertRequestConstants.java
new file mode 100644
index 000000000..7494b5e48
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/request/CertRequestConstants.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.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/pki/base/common/src/com/netscape/cmscore/request/ExtDataHashtable.java b/pki/base/common/src/com/netscape/cmscore/request/ExtDataHashtable.java
new file mode 100644
index 000000000..cdc5a7eea
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/request/ExtDataHashtable.java
@@ -0,0 +1,71 @@
+package com.netscape.cmscore.request;
+
+import java.util.*;
+
+/**
+ * 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 extends Hashtable {
+
+ public ExtDataHashtable() {
+ super();
+ }
+
+ public ExtDataHashtable(int i) {
+ super(i);
+ }
+
+ public ExtDataHashtable(int i, float v) {
+ super(i, v);
+ }
+
+ public ExtDataHashtable(Map 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 Object get(Object o) {
+ if (o instanceof String) {
+ String key = (String)o;
+ return super.get(key.toLowerCase());
+ }
+ return super.get(o);
+ }
+
+ public Object put(Object oKey, Object val) {
+ if (oKey instanceof String) {
+ String key = (String)oKey;
+ return super.put(key.toLowerCase(), val);
+ }
+ return super.put(oKey, val);
+ }
+
+ public void putAll(Map map) {
+ Set keys = map.keySet();
+ for (Iterator i = keys.iterator();
+ i.hasNext();) {
+ Object key = i.next();
+ put(key, map.get(key));
+ }
+ }
+
+ public Object remove(Object o) {
+ if (o instanceof String) {
+ String key = (String)o;
+ return super.remove(key.toLowerCase());
+ }
+ return super.remove(o);
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/request/RequestAttr.java b/pki/base/common/src/com/netscape/cmscore/request/RequestAttr.java
new file mode 100644
index 000000000..ea60dc470
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/request/RequestAttr.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.cmscore.request;
+
+
+import com.netscape.certsrv.dbs.Modification;
+import com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.dbs.IDBAttrMapper;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.request.ldap.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/request/RequestQueue.java b/pki/base/common/src/com/netscape/cmscore/request/RequestQueue.java
new file mode 100644
index 000000000..f390d436d
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/request/RequestQueue.java
@@ -0,0 +1,708 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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 com.netscape.certsrv.dbs.ModificationSet;
+import com.netscape.certsrv.dbs.IDBSearchResults;
+import com.netscape.certsrv.dbs.IDBVirtualList;
+import com.netscape.certsrv.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.cmscore.dbs.DBSubsystem;
+
+import com.netscape.certsrv.base.EBaseException;
+
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.request.ldap.*;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestRecord;
+import com.netscape.certsrv.request.IPolicy;
+import com.netscape.certsrv.request.INotify;
+import com.netscape.certsrv.request.IService;
+import com.netscape.certsrv.request.IRequestList;
+import com.netscape.certsrv.request.IRequestVirtualList;
+import com.netscape.cmscore.request.ARequestQueue;
+import com.netscape.certsrv.dbs.repository.IRepository;
+
+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.toString());
+
+ 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.toString(10));
+
+ 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 attrs[] = { IRequestRecord.ATTR_REQUEST_ID };
+ 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 getRawList() {
+ IDBSearchResults results = null;
+ IDBSSession dbs = null;
+ String attrs[] = { IRequestRecord.ATTR_REQUEST_ID };
+
+ 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;
+ String attrs[] = { IRequestRecord.ATTR_REQUEST_ID };
+
+ 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;
+ String attrs[] = { IRequestRecord.ATTR_REQUEST_ID };
+
+ 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;
+ String attrs[] = { IRequestRecord.ATTR_REQUEST_ID };
+
+ 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;
+ String attrs[] = { IRequestRecord.ATTR_REQUEST_ID };
+
+ 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 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, java.util.Hashtable h) {
+ System.err.println(s);
+ java.util.Enumeration e = h.keys();
+
+ while (e.hasMoreElements()) {
+ String name = (String) e.nextElement();
+
+ System.err.println("Attr: " + name + " Value: " + h.get(name));
+ }
+ }
+
+ /*
+ * return request repository
+ */
+ public IRepository getRequestRepository() {
+ return (IRepository) 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 Object 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 list) {
+ mQueue = queue;
+ mList = list;
+ }
+
+ protected RequestQueue mQueue;
+ protected IDBVirtualList mList;
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/request/RequestRecord.java b/pki/base/common/src/com/netscape/cmscore/request/RequestRecord.java
new file mode 100644
index 000000000..85995aaa3
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/request/RequestRecord.java
@@ -0,0 +1,870 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectInputStream;
+import java.math.BigInteger;
+
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.Hashtable;
+
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+
+import com.netscape.certsrv.base.EBaseException;
+
+import com.netscape.certsrv.dbs.*;
+import com.netscape.cmscore.dbs.StringMapper;
+import com.netscape.cmscore.dbs.DateMapper;
+import com.netscape.cmscore.dbs.BigIntegerMapper;
+
+import com.netscape.certsrv.request.ldap.*;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestRecord;
+
+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 {
+ public RequestId getRequestId() {
+ return mRequestId;
+ }
+
+ public Enumeration 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 = (RequestAttr) mAttrTable.get(name);
+
+ if (ra != null) return ra.get(this);
+ }
+
+ return null;
+ }
+
+ // IDBObj.set
+ 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)o;
+ else {
+ RequestAttr ra = (RequestAttr) 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 getElements() {
+ return mAttrs.elements();
+ }
+
+ // IDBObj.getSerializableAttrNames
+ public Enumeration 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 loadExtDataFromRequest(IRequest r) throws EBaseException {
+ Hashtable h = new Hashtable();
+
+ Enumeration e = r.getExtDataKeys();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ if (r.isSimpleExtDataValue(key)) {
+ h.put(key, r.getExtDataInString(key));
+ } else {
+ h.put(key, r.getExtDataInHashtable(key));
+ }
+ }
+
+ return h;
+ }
+
+ protected void storeExtDataIntoRequest(IRequest r) throws EBaseException {
+ Enumeration e = mExtData.keys();
+ while (e.hasMoreElements()) {
+ String key = (String) 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)value);
+ } else {
+ throw new EDBException("Illegal data value in RequestRecord: " +
+ r.toString());
+ }
+ }
+ }
+
+ protected static Vector mAttrs = new Vector();
+
+ static Hashtable mAttrTable = new Hashtable();
+
+ /*
+ * 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 getSupportedLDAPAttributeNames() {
+ return mAttrs.elements();
+ }
+
+ //
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs) {
+ 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 mAttrs = new Vector();
+
+ 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 getSupportedLDAPAttributeNames() {
+ return mAttrs.elements();
+ }
+
+ //
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs) {
+ 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) {
+ 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 mAttrs = new Vector();
+
+ 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 getSupportedLDAPAttributeNames() {
+ return mAttrs.elements();
+ }
+
+ //
+ public void mapObjectToLDAPAttributeSet(IDBObj parent,
+ String name, Object obj, LDAPAttributeSet attrs) {
+ Hashtable ht = (Hashtable) obj;
+ Enumeration e = ht.keys();
+
+ try {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream os = new ObjectOutputStream(bos);
+
+ String key = null;
+ Object value = null;
+
+ while (e.hasMoreElements()) {
+ key = (String) 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);
+ os.close();
+
+ attrs.add(new LDAPAttribute(Schema.LDAP_ATTR_REQUEST_ATTRS,
+ bos.toByteArray()));
+ } catch (Exception x) {
+ Debug.trace("Output Mapping Error in requeset ID " +
+ ((RequestRecord) parent).getRequestId().toString() + " : " + x);
+ //if (Debug.ON) {
+ Debug.printStackTrace(x);
+ //}
+ }
+ }
+
+ 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 decodeHashtable(byte[] data)
+ throws ObjectStreamException, IOException, ClassNotFoundException {
+ Hashtable ht = new Hashtable();
+ 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 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) {
+ Enumeration values = attr.getByteValues();
+
+ value = (byte[]) 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 mAttrs = new Vector();
+
+ 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 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 {
+ Hashtable ht = (Hashtable) obj;
+ Enumeration e = ht.keys();
+
+ try {
+ while (e.hasMoreElements()) {
+ String key = (String) 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) {
+ Hashtable innerHash = (Hashtable)value;
+ Enumeration innerHashEnum = innerHash.keys();
+ while (innerHashEnum.hasMoreElements()){
+ String innerKey = (String)innerHashEnum.nextElement();
+ String innerValue = (String)innerHash.get(innerKey);
+ attrs.add(new LDAPAttribute(
+ extAttrPrefix + encodeKey(key) + ";" + encodeKey(innerKey),
+ innerValue));
+ }
+ }
+ }
+ } catch (Exception x) {
+ Debug.trace("Output Mapping Error in requeset ID " +
+ ((IRequestRecord) parent).getRequestId().toString() + " : " + x);
+ //if (Debug.ON) {
+ Debug.printStackTrace(x);
+ //}
+ }
+ }
+
+ public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, String name,
+ IDBObj parent)
+ throws EBaseException {
+ Hashtable ht = new Hashtable();
+ Hashtable valueHashtable;
+
+ Enumeration attrEnum = attrs.getAttributes();
+ while (attrEnum.hasMoreElements()) {
+ LDAPAttribute attr = (LDAPAttribute)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)value;
+ if (valueHashtable == null) {
+ valueHashtable = new Hashtable();
+ 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 mAttrs = new Vector();
+
+ static {
+ mAttrs.add(Schema.LDAP_ATTR_EXT_ATTR);
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/request/RequestRepository.java b/pki/base/common/src/com/netscape/cmscore/request/RequestRepository.java
new file mode 100644
index 000000000..c6ab7129e
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/request/RequestRepository.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.cmscore.request;
+
+import java.util.*;
+import java.io.*;
+import java.math.*;
+import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.repository.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.cmscore.dbs.*;
+
+
+/**
+ * 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 {
+ Enumeration e = s.search(getBaseDN(),
+ "(" + RequestRecord.ATTR_REQUEST_ID + "=*)");
+ while (e.hasMoreElements()) {
+ RequestRecord r = (RequestRecord)e.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/pki/base/common/src/com/netscape/cmscore/request/RequestSubsystem.java b/pki/base/common/src/com/netscape/cmscore/request/RequestSubsystem.java
new file mode 100644
index 000000000..2e05e54eb
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/request/RequestSubsystem.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.cmscore.request;
+
+
+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.dbs.IDBSSession;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.cmscore.dbs.DBSubsystem;
+
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.request.*;
+
+
+/**
+ * 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() {
+ mRequestQueue = null;
+
+ 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;
+ private ISubsystem mParent;
+ private String mId = IRequestSubsystem.SUB_ID;
+ private IRequestQueue mRequestQueue;
+
+ protected ILogger mLogger;
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/request/Schema.java b/pki/base/common/src/com/netscape/cmscore/request/Schema.java
new file mode 100644
index 000000000..182e3470e
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/request/Schema.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.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/pki/base/common/src/com/netscape/cmscore/security/CASigningCert.java b/pki/base/common/src/com/netscape/cmscore/security/CASigningCert.java
new file mode 100644
index 000000000..22d0b8c17
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/security/CASigningCert.java
@@ -0,0 +1,169 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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 netscape.security.x509.*;
+import netscape.security.util.*;
+import java.util.*;
+import java.io.*;
+import java.math.*;
+import java.security.PrivateKey;
+import java.security.InvalidKeyException;
+import java.security.SignatureException;
+import java.security.cert.*;
+import java.security.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.security.*;
+import com.netscape.certsrv.apps.CMS;
+import org.mozilla.jss.crypto.Signature;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.CryptoManager.*;
+import org.mozilla.jss.*;
+
+
+/**
+ * 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 static 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, new Boolean(true));
+ extension.set(KeyUsageExtension.NON_REPUDIATION, new Boolean(true));
+ extension.set(KeyUsageExtension.KEY_CERTSIGN, new Boolean(true));
+ extension.set(KeyUsageExtension.CRL_SIGN, new Boolean(true));
+ return extension;
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/security/CertificateInfo.java b/pki/base/common/src/com/netscape/cmscore/security/CertificateInfo.java
new file mode 100644
index 000000000..f702f2e87
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/security/CertificateInfo.java
@@ -0,0 +1,255 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.util.*;
+import java.math.*;
+import java.security.*;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateParsingException;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.security.*;
+import org.mozilla.jss.*;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.CryptoManager.*;
+import org.mozilla.jss.crypto.Signature;
+
+
+/**
+ * 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 static 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());
+
+ notBeforeDate = new Date(beginYear, beginMonth, beginDate,
+ beginHour, beginMin, beginSec);
+ notAfterDate = new Date(afterYear, afterMonth, afterDate,
+ afterHour, afterMin, afterSec);
+ }
+ 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);
+
+ algm = KeyCertUtil.getSigningAlgorithm(getKeyAlgorithm(), 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", ""));
+ }
+
+ 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);
+ KeyPair caKeyPair = (KeyPair) mProperties.get(Constants.PR_CA_KEYPAIR);
+ 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/pki/base/common/src/com/netscape/cmscore/security/JssSubsystem.java b/pki/base/common/src/com/netscape/cmscore/security/JssSubsystem.java
new file mode 100644
index 000000000..cf63a770b
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/security/JssSubsystem.java
@@ -0,0 +1,2153 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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 com.netscape.certsrv.base.*;
+import com.netscape.certsrv.dbs.*;
+import org.mozilla.jss.*;
+import org.mozilla.jss.crypto.KeyPairGenerator;
+import org.mozilla.jss.crypto.PrivateKey;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.pkix.cert.Certificate;
+import org.mozilla.jss.ssl.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.pkcs7.*;
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.util.PasswordCallback;
+import org.mozilla.jss.util.ConsolePasswordCallback;
+import org.mozilla.jss.util.IncorrectPasswordException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.security.*;
+import java.util.*;
+import java.net.*;
+import java.io.*;
+import java.text.*;
+import java.math.*;
+import java.security.*;
+import java.security.cert.CertificateEncodingException;
+import netscape.security.x509.*;
+import java.security.cert.CertificateException;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.CryptoManager.NicknameConflictException;
+import org.mozilla.jss.CryptoManager.UserCertConflictException;
+import org.mozilla.jss.pkcs11.PK11SecureRandom;
+import com.netscape.cmscore.cert.*;
+import com.netscape.cmscore.util.Debug;
+import netscape.ldap.util.*;
+import com.netscape.cmsutil.crypto.*;
+
+
+/**
+ * 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 CERTPREFIX_ALIAS = "certPrefix";
+ private static final String KEYPREFIX_ALIAS = "keyPrefix";
+ private static final String CONFIGDIR_ALIAS = "configDir";
+ private static final String SECMODNAME_ALIAS = "secmodName";
+ private static final String PROP_ENABLE = "enable";
+ private static final String PROP_OCSP_ENABLE = "ocspcheck.enable";
+ private static final String PASSWORD_ALIAS = "password";
+ private static final String mId = ID;
+ private IConfigStore mSSLSubStore;
+ 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 mNicknameMapCertsTable = new Hashtable();
+ private Hashtable mNicknameMapUserCertsTable = new Hashtable();
+
+ 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 mCipherNames = new Hashtable();
+
+ /* default sslv2 and sslv3 cipher suites(all), set if no prefs in config.*/
+ private static final String DEFAULT_CIPHERPREF =
+ "rc4export,rc2export,rc4,rc2,des,desede3," +
+ "rsa_rc4_40_md5,rsa_rc2_40_md5,rsa_des_sha," +
+ "rsa_rc4_128_md5,rsa_3des_sha,rsa_fips_des_sha," +
+ "rsa_fips_3des_sha,fortezza,fortezza_rc4_128_sha," +
+ "fortezza_null,rsa_null_md5";
+
+ /* 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 = (Integer) 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 {
+ String tokenList = "";
+ Enumeration tokens = mCryptoManager.getExternalTokens();
+ int num = 0;
+
+ try {
+ while (tokens.hasMoreElements()) {
+ CryptoToken c = (CryptoToken) tokens.nextElement();
+
+ // skip builtin object token
+ if (c.getName() != null && c.getName().equals("Builtin Object Token")) {
+ continue;
+ }
+
+ if (num++ == 0)
+ tokenList = tokenList + c.getName();
+ else
+ tokenList = tokenList + "," + 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.equals(""))
+ return Constants.PR_INTERNAL_TOKEN;
+ else
+ return (tokenList + "," + Constants.PR_INTERNAL_TOKEN);
+ }
+
+ 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 {
+ String certNames = "";
+
+ try {
+ Enumeration enums = mCryptoManager.getAllTokens();
+
+ while (enums.hasMoreElements()) {
+ CryptoToken token = (CryptoToken) 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.equals(""))
+ certNames = certNames + nickname;
+ else
+ certNames = certNames + "," + 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;
+ }
+
+ public String getCertListWithoutTokenName(String name) throws EBaseException {
+
+ CryptoToken c = null;
+ String certNames = "";
+
+ 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 = certNames + nickname;
+ else
+ certNames = certNames + "," + nickname;
+ }
+ return certNames;
+ } 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;
+ String certNames = "";
+
+ 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 = certNames + nickname;
+ else
+ certNames = certNames + "," + nickname;
+ }
+ return certNames;
+ } 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.getAlgorithmId(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 {
+ X500Name name = new X500Name(dn);
+ } 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) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString()));
+ 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 keyType = "ECC";
+ 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.add(Constants.PR_CERT_SUBJECT_NAME, impl.getSubjectDN().getName());
+ results.add(Constants.PR_ISSUER_NAME, impl.getIssuerDN().getName());
+ results.add(Constants.PR_SERIAL_NUMBER, impl.getSerialNumber().toString());
+ results.add(Constants.PR_BEFORE_VALIDDATE, impl.getNotBefore().toString());
+ results.add(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;
+ CryptoStore store = tcert.getOwningToken().getCryptoStore();
+
+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 = (X509Certificate[]) 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;
+ CryptoStore store = tcert.getOwningToken().getCryptoStore();
+
+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 {
+ Enumeration enums = mCryptoManager.getAllTokens();
+ if (mNicknameMapCertsTable != null)
+ mNicknameMapCertsTable.clear();
+
+ // a temp hashtable with vectors
+ Hashtable vecTable = new Hashtable();
+
+ while (enums.hasMoreElements()) {
+ CryptoToken token = (CryptoToken) enums.nextElement();
+ String tokenName = token.getName();
+
+ CryptoStore store = token.getCryptoStore();
+ X509Certificate[] list = store.getCertificates();
+
+ for (int i = 0; i < list.length; i++) {
+ try {
+ PrivateKey key =
+ CryptoManager.getInstance().findPrivKeyByCert(list[i]);
+ 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 v;
+ if (vecTable.containsKey((Object) nickname) == true) {
+ v = (Vector) vecTable.get(nickname);
+ } else {
+ v = new Vector();
+ }
+ 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.add(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 elms = vecTable.keys();
+
+ while (elms.hasMoreElements()) {
+ String key = (String) elms.nextElement();
+ Vector v = (Vector) vecTable.get((Object) key);
+ X509Certificate[] a = new X509Certificate[v.size()];
+
+ v.copyInto((Object[]) 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 {
+ Enumeration enums = mCryptoManager.getAllTokens();
+
+ while (enums.hasMoreElements()) {
+ CryptoToken token = (CryptoToken) enums.nextElement();
+ String tokenName = token.getName();
+
+ CryptoStore store = token.getCryptoStore();
+ X509Certificate[] list = store.getCertificates();
+
+ for (int i = 0; i < list.length; i++) {
+ try {
+ PrivateKey key =
+ CryptoManager.getInstance().findPrivKeyByCert(list[i]);
+ 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.add(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();
+
+ try {
+ Enumeration enums = mCryptoManager.getAllTokens();
+
+ while (enums.hasMoreElements()) {
+ CryptoToken token = (CryptoToken) enums.nextElement();
+ String tokenName = token.getName();
+
+ 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);
+ NameValuePair pair = pairs.getPair(nickname);
+
+ /* always user cert here*/
+ String certValue = dateStr + "," + "u";
+
+ if (pair == null)
+ pairs.add(nickname, certValue);
+ else {
+ String vvalue = pair.getValue();
+
+ if (vvalue.endsWith(",u")) {
+ pair.setValue(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( "mNicknameMapCertsTable is null" );
+ } else {
+ mNicknameMapCertsTable.clear();
+ }
+
+ // a temp hashtable with vectors
+ Hashtable vecTable = new Hashtable();
+
+ for (int i = 0; i < certs.length; i++) {
+ String nickname = certs[i].getNickname();
+
+ /* build a table of our own */
+ Vector v;
+
+ if (vecTable.containsKey((Object) nickname) == true) {
+ v = (Vector) vecTable.get(nickname);
+ } else {
+ v = new Vector();
+ }
+ v.addElement(certs[i]);
+ vecTable.put(nickname, v);
+ }
+
+ // convert hashtable of vectors to hashtable of arrays
+ Enumeration elms = vecTable.keys();
+
+ while (elms.hasMoreElements()) {
+ String key = (String) elms.nextElement();
+ Vector v = (Vector) vecTable.get((Object) key);
+ X509Certificate[] a = new X509Certificate[v.size()];
+
+ v.copyInto((Object[]) a);
+ mNicknameMapCertsTable.put(key, a);
+ }
+
+ Enumeration keys = mNicknameMapCertsTable.keys();
+
+ while (keys.hasMoreElements()) {
+ String nickname = (String) keys.nextElement();
+ X509Certificate[] value = (X509Certificate[]) 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);
+ NameValuePair pair = pairs.getPair(nickname);
+ String certValue = dateStr + "," + trust;
+
+ if (pair == null)
+ pairs.add(nickname, certValue);
+ else {
+ String vvalue = pair.getValue();
+
+ pair.setValue(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 = (X509Certificate[]) 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 = (X509Certificate[]) 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;
+ CryptoStore store = tcert.getOwningToken().getCryptoStore();
+
+ 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 =
+ (X509Certificate[]) mNicknameMapCertsTable.get(nickname);
+ }
+
+ if (certs == null) {
+ if (mNicknameMapUserCertsTable != null) {
+ certs =
+ (X509Certificate[]) 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;
+ CryptoStore store = tcert.getOwningToken().getCryptoStore();
+
+ 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);
+ String issuerName = cert.getSubjectDN().getName();
+ Principal principal = cert.getSubjectDN();
+ DN dn = new DN(principal.getName());
+ BigInteger serialno = cert.getSerialNumber();
+ String suffix = "." + System.currentTimeMillis();
+ String b64E = com.netscape.osutil.OSUtil.BtoA(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;
+ CryptoStore store = tcert.getOwningToken().getCryptoStore();
+
+ 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());
+ String certIssuerName = certImpl.getSubjectDN().getName();
+ 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()));
+ } 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 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 = (X509Certificate[]) 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
+ String content = "";
+ String noHeader = CertUtils.stripCertBrackets(b64E);
+ String normalized = CertUtils.normalizeCertStr(noHeader);
+ byte data[] = com.netscape.osutil.OSUtil.AtoB(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 += print.toString(Locale.getDefault());
+ }
+
+ return content;
+ }
+ } 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/pki/base/common/src/com/netscape/cmscore/security/KRATransportCert.java b/pki/base/common/src/com/netscape/cmscore/security/KRATransportCert.java
new file mode 100644
index 000000000..35b7cdf2b
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/security/KRATransportCert.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.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";
+ private String mTokenname = Constants.PR_INTERNAL_TOKEN_NAME;
+
+ public KRATransportCert(KeyCertData properties) {
+ this(properties, null);
+ }
+
+ public KRATransportCert(KeyCertData properties, KeyPair pair) {
+ super(properties, pair);
+ String tmp = (String) mProperties.get(Constants.PR_TOKEN_NAME);
+
+ if ((tmp != null) &&
+ (!tmp.equals(Constants.PR_INTERNAL_TOKEN)))
+ mTokenname = tmp;
+ 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, new Boolean(true));
+ return extension;
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/security/KeyCertUtil.java b/pki/base/common/src/com/netscape/cmscore/security/KeyCertUtil.java
new file mode 100644
index 000000000..4f551cd26
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/security/KeyCertUtil.java
@@ -0,0 +1,1088 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.asn1.*;
+
+import java.security.PrivateKey;
+import java.security.*;
+import java.util.*;
+import java.security.interfaces.*;
+import java.io.IOException;
+import java.io.*;
+import java.security.cert.CertificateException;
+import org.mozilla.jss.crypto.KeyPairGenerator;
+import org.mozilla.jss.crypto.*;
+import java.math.*;
+//import java.security.cert.*;
+import org.mozilla.jss.crypto.X509Certificate;
+//import netscape.security.provider.DSAPublicKey;
+// ADDED next line by MLH on 1/9/99
+// REMOVED the line added by MLH on 1/10/99
+//import netscape.security.provider.RSAPublicKey;
+import netscape.security.x509.*;
+import netscape.security.extensions.*;
+import netscape.security.util.*;
+import netscape.security.pkcs.*;
+import org.mozilla.jss.*;
+import org.mozilla.jss.pkcs11.*;
+import org.mozilla.jss.util.*;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.crypto.Signature;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.CryptoManager.NicknameConflictException;
+import org.mozilla.jss.CryptoManager.UserCertConflictException;
+import java.security.cert.CertificateEncodingException;
+import netscape.ldap.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.security.*;
+import com.netscape.cmscore.cert.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.cmscore.dbs.*;
+import com.netscape.cmsutil.crypto.*;
+
+
+/**
+ * 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";
+ private static final int MAX_DOMESTIC_SSL_KEY_LEN = 4096;
+ private static final int MAX_EXPORT_SSL_KEY_LEN = 512;
+ private static final int MIN_DSA_KEY_LEN = 512;
+ private static final int MAX_DSA_KEY_LEN = 1024;
+
+ public static void checkCertificateExt(String ext) throws EBaseException {
+ byte[] b = null;
+
+ if (ext != null) {
+ try {
+
+ b = (byte[]) (com.netscape.osutil.OSUtil.AtoB(ext));
+ // this b can be "Extension" Or "SEQUENCE OF Extension"
+ DerValue b_der = new DerValue(b);
+
+ while (b_der.data.available() != 0) {
+ Extension de = new Extension(b_der.data.getDerValue());
+ }
+ } catch (IOException e) {
+ try {
+ Extension de = new Extension(new DerValue(b));
+ } catch (IOException ex) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_CERT_EXTENSION"));
+ }
+ }
+ }
+ }
+
+ public static String getTokenNames(CryptoManager manager)
+ throws TokenException {
+ String tokenList = "";
+ Enumeration tokens = manager.getExternalTokens();
+ int num = 0;
+
+ while (tokens.hasMoreElements()) {
+ CryptoToken c = (CryptoToken) tokens.nextElement();
+
+ if (num++ == 0)
+ tokenList = tokenList + c.getName();
+ else
+ tokenList = tokenList + "," + c.getName();
+ }
+
+ if (tokenList.equals(""))
+ return Constants.PR_INTERNAL_TOKEN;
+ else
+ return (tokenList + "," + 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();
+ 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 {
+
+ // 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
+ DerOutputStream sequence = new DerOutputStream();
+
+ 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 {
+ 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();
+ DerOutputStream out = 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.getAlgorithmId(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);
+ byte[] bits = bs.getBits();
+ 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,
+ (CertAttrSet) 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[] = (byte[]) (com.netscape.osutil.OSUtil.AtoB(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 = (byte[]) (com.netscape.osutil.OSUtil.AtoB(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
+ if ((isCA == null) && (certLen == null))
+ return;
+ 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, new Boolean(true));
+ anyExt = true;
+ }
+
+ String sslServer = properties.getSSLServerBit();
+
+ if ((sslServer != null) && (sslServer.equals(Constants.TRUE))) {
+ ns.set(NSCertTypeExtension.SSL_SERVER, new Boolean(true));
+ anyExt = true;
+ }
+
+ String sslMail = properties.getSSLMailBit();
+
+ if ((sslMail != null) && (sslMail.equals(Constants.TRUE))) {
+ ns.set(NSCertTypeExtension.EMAIL, new Boolean(true));
+ anyExt = true;
+ }
+
+ String sslCA = properties.getSSLCABit();
+
+ if ((sslCA != null) && (sslCA.equals(Constants.TRUE))) {
+ ns.set(NSCertTypeExtension.SSL_CA, new Boolean(true));
+ anyExt = true;
+ }
+
+ String objectSigning = properties.getObjectSigningBit();
+
+ if ((objectSigning != null) && (objectSigning.equals(Constants.TRUE))) {
+ ns.set(NSCertTypeExtension.OBJECT_SIGNING, new Boolean(true));
+ anyExt = true;
+ }
+
+ String mailCA = properties.getMailCABit();
+
+ if ((mailCA != null) && (mailCA.equals(Constants.TRUE))) {
+ ns.set(NSCertTypeExtension.EMAIL_CA, new Boolean(true));
+ anyExt = true;
+ }
+
+ String objectSigningCA = properties.getObjectSigningCABit();
+
+ if ((objectSigningCA != null) && (objectSigningCA.equals(Constants.TRUE))) {
+ ns.set(NSCertTypeExtension.OBJECT_SIGNING_CA, new Boolean(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 oidSet = new Vector();
+ 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 {
+ String dn = "ou=certificateRepository,ou=ca," + baseDN;
+ BigInteger serialno = null;
+ LDAPEntry entry = conn.read(dn);
+ String serialnoStr = (String) entry.getAttribute(
+ "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 {
+ 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/pki/base/common/src/com/netscape/cmscore/security/OCSPSigningCert.java b/pki/base/common/src/com/netscape/cmscore/security/OCSPSigningCert.java
new file mode 100644
index 000000000..279a62347
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/security/OCSPSigningCert.java
@@ -0,0 +1,147 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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 netscape.security.x509.*;
+import netscape.security.util.*;
+import java.util.*;
+import java.io.*;
+import java.math.*;
+import java.security.PrivateKey;
+import java.security.InvalidKeyException;
+import java.security.SignatureException;
+import java.security.cert.*;
+import java.security.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.security.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.*;
+import org.mozilla.jss.crypto.Signature;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.CryptoManager.*;
+import org.mozilla.jss.*;
+
+
+/**
+ * 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 static 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, new Boolean(true));
+ extension.set(KeyUsageExtension.NON_REPUDIATION, new Boolean(true));
+ extension.set(KeyUsageExtension.KEY_CERTSIGN, new Boolean(true));
+ extension.set(KeyUsageExtension.CRL_SIGN, new Boolean(true));
+ return extension;
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/security/PWCBsdr.java b/pki/base/common/src/com/netscape/cmscore/security/PWCBsdr.java
new file mode 100644
index 000000000..299b9f6e6
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/security/PWCBsdr.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.security;
+
+
+import org.mozilla.jss.*;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.crypto.SecretDecoderRing;
+import org.mozilla.jss.crypto.TokenException;
+import java.io.*;
+import java.lang.*;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.util.PasswordCallback;
+import org.mozilla.jss.util.PasswordCallbackInfo;
+import com.netscape.cmscore.base.*;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.logging.ILogger;
+
+
+/*
+ * A class to retrieve passwords from the SDR password cache
+ *
+ * @author Christina Fu
+ * @version $Revision$, $Date$
+ */
+
+public class PWCBsdr implements PasswordCallback {
+ InputStream in = null;
+ OutputStream out = null;
+ 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) {
+ in = System.in;
+ out = System.out;
+ 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");
+ if (File.separator.equals("/")) {
+ // Unix
+ mCB = new PWsdrConsolePasswordCallback(prompt);
+ } else {
+ 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");
+ String tmp = new String(pw.getCharCopy());
+
+ 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/pki/base/common/src/com/netscape/cmscore/security/PWUtil.java b/pki/base/common/src/com/netscape/cmscore/security/PWUtil.java
new file mode 100644
index 000000000..afba0a4db
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/security/PWUtil.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.security;
+
+
+import java.lang.*;
+import java.io.*;
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.util.PasswordCallback;
+import org.mozilla.jss.util.PasswordCallbackInfo;
+
+
+public class
+PWUtil {
+ public static Password
+ readPasswordFromStream()
+ throws PasswordCallback.GiveUpException {
+ BufferedReader in;
+
+ in = new BufferedReader(new InputStreamReader(System.in));
+
+ StringBuffer buf = new StringBuffer();
+ String passwordString = new String();
+ int c;
+
+ try {
+ // 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()));
+ } catch (Exception e) {
+ throw new PasswordCallback.GiveUpException();
+ }
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/security/PWsdrCache.java b/pki/base/common/src/com/netscape/cmscore/security/PWsdrCache.java
new file mode 100644
index 000000000..309978f28
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/security/PWsdrCache.java
@@ -0,0 +1,639 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.SecretDecoderRing.KeyManager;
+import org.mozilla.jss.SecretDecoderRing.Encryptor;
+import org.mozilla.jss.SecretDecoderRing.Decryptor;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.*;
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.util.Base64OutputStream;
+import java.io.*;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import com.netscape.cmscore.base.*;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.apps.CMS;
+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);
+ mToken = cm.getInternalKeyStorageToken();
+ 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 = com.netscape.osutil.OSUtil.AtoB(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();
+ 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) null);
+ }
+
+ /*
+ * Store passwd in pwcache.
+ */
+ public void addEntry(Hashtable ht) throws EBaseException {
+ addEntry((String) null, (String) null, ht);
+ }
+
+ /*
+ * add passwd in pwcache.
+ */
+ public void addEntry(String tag, String pwd, Hashtable tagPwds) throws EBaseException {
+
+ String stringToAdd = null;
+ String bufs = null;
+
+ if (tagPwds == null) {
+ stringToAdd = tag + ":" + pwd + "\n";
+ } else {
+ Enumeration enum1 = tagPwds.keys();
+
+ while (enum1.hasMoreElements()) {
+ tag = (String) enum1.nextElement();
+ pwd = (String) tagPwds.get(tag);
+ debug("password tag: " + tag + " stored in " + mPWcachedb);
+
+ if (stringToAdd == null) {
+ stringToAdd = tag + ":" + pwd + "\n";
+ } else {
+ stringToAdd += tag + ":" + pwd + "\n";
+ }
+ }
+ }
+
+ String dcrypts = readPWcache();
+
+ if (dcrypts != null) {
+ // converts to Hashtable, replace if tag exists, add
+ // if tag doesn't exist
+ Hashtable 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;
+ }
+
+ // 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 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;
+ }
+ inputs.close();
+ } 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);
+ }
+
+ 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 {
+ 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?
+ tmpPWcache.delete();
+ tmpPWcache = new File(mPWcachedb + ".tmp");
+ }
+ FileOutputStream outstream = new FileOutputStream(mPWcachedb + ".tmp");
+
+ outstream.write(writebuf);
+ outstream.close();
+
+ 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() );
+ }
+ }
+ tmpPWcache.delete();
+ 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);
+ }
+ }
+
+ public String hashtable2String(Hashtable ht) {
+ Enumeration enum1 = ht.keys();
+ String returnString = null;
+
+ while (enum1.hasMoreElements()) {
+ String tag = (String) enum1.nextElement();
+ String pwd = (String) ht.get(tag);
+
+ if (returnString == null) {
+ returnString = tag + ":" + pwd + "\n";
+ } else {
+ returnString += tag + ":" + pwd + "\n";
+ }
+ }
+ return returnString;
+ }
+
+ public Hashtable string2Hashtable(String cache) {
+ Hashtable ht = new Hashtable();
+
+ // first, break into lines
+ StringTokenizer st = new StringTokenizer(cache, "\n");
+
+ while (st.hasMoreTokens()) {
+ String line = (String) 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 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 = (String) 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 EBaseException {
+ try {
+ 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 = Runtime.getRuntime().exec(cmds);
+
+ process.waitFor();
+ BufferedReader pOut = null;
+ String l = null;
+
+ if (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;
+ }
+ } catch (Exception e) {
+ 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 bufs = null;
+ 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 = (String) 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/pki/base/common/src/com/netscape/cmscore/security/Provider.java b/pki/base/common/src/com/netscape/cmscore/security/Provider.java
new file mode 100644
index 000000000..3e343c78c
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/security/Provider.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.cmscore.security;
+
+
+public class Provider extends java.security.Provider {
+
+ 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/pki/base/common/src/com/netscape/cmscore/security/RASigningCert.java b/pki/base/common/src/com/netscape/cmscore/security/RASigningCert.java
new file mode 100644
index 000000000..c6f2f7cbc
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/security/RASigningCert.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.security;
+
+
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import java.util.*;
+import java.security.PrivateKey;
+import java.security.InvalidKeyException;
+import java.security.SignatureException;
+import java.security.*;
+import java.io.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.security.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.base.*;
+import org.mozilla.jss.*;
+import org.mozilla.jss.crypto.Signature;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.CryptoManager.*;
+import org.mozilla.jss.crypto.*;
+import java.security.cert.*;
+
+
+/**
+ * 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";
+ private String mTokenname = Constants.PR_INTERNAL_TOKEN_NAME;
+
+ public RASigningCert(KeyCertData properties) {
+ this(properties, null);
+ }
+
+ public RASigningCert(KeyCertData properties, KeyPair pair) {
+ super(properties, pair);
+ String tmp = (String) mProperties.get(Constants.PR_TOKEN_NAME);
+
+ if ((tmp != null) &&
+ (!tmp.equals(Constants.PR_INTERNAL_TOKEN)))
+ mTokenname = tmp;
+ 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, new Boolean(true));
+ return extension;
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/security/SSLCert.java b/pki/base/common/src/com/netscape/cmscore/security/SSLCert.java
new file mode 100644
index 000000000..0967b0930
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/security/SSLCert.java
@@ -0,0 +1,137 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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 netscape.security.x509.*;
+import netscape.security.util.*;
+import java.util.*;
+import java.security.PrivateKey;
+import java.security.InvalidKeyException;
+import java.security.SignatureException;
+import java.security.*;
+import java.io.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.security.*;
+import com.netscape.certsrv.base.*;
+import org.mozilla.jss.*;
+import org.mozilla.jss.crypto.Signature;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.CryptoManager.*;
+import org.mozilla.jss.crypto.*;
+import java.security.cert.*;
+
+
+/**
+ * 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";
+ private String mTokenname = Constants.PR_INTERNAL_TOKEN_NAME;
+
+ public SSLCert(KeyCertData properties) {
+ this(properties, null);
+ }
+
+ public SSLCert(KeyCertData properties, KeyPair pair) {
+ super(properties, pair);
+ String tmp = (String) mProperties.get(Constants.PR_TOKEN_NAME);
+
+ if ((tmp != null) &&
+ (!tmp.equals(Constants.PR_INTERNAL_TOKEN)))
+ mTokenname = tmp;
+ 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, new Boolean(true));
+ extension.set(KeyUsageExtension.NON_REPUDIATION, new Boolean(true));
+ extension.set(KeyUsageExtension.KEY_ENCIPHERMENT, new Boolean(true));
+ extension.set(KeyUsageExtension.DATA_ENCIPHERMENT, new Boolean(true));
+ return extension;
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/security/SSLSelfSignedCert.java b/pki/base/common/src/com/netscape/cmscore/security/SSLSelfSignedCert.java
new file mode 100644
index 000000000..d38b35b44
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/security/SSLSelfSignedCert.java
@@ -0,0 +1,131 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.security;
+
+
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import java.util.*;
+import java.security.PrivateKey;
+import java.security.InvalidKeyException;
+import java.security.SignatureException;
+import java.security.*;
+import java.io.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.security.*;
+import com.netscape.certsrv.base.*;
+import org.mozilla.jss.*;
+import org.mozilla.jss.crypto.Signature;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.CryptoManager.*;
+import org.mozilla.jss.crypto.*;
+import java.security.cert.*;
+
+
+/**
+ * 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";
+ private String mTokenname = Constants.PR_INTERNAL_TOKEN_NAME;
+
+ public SSLSelfSignedCert(KeyCertData properties) {
+ this(properties, null);
+ }
+
+ public SSLSelfSignedCert(KeyCertData properties, KeyPair pair) {
+ super(properties, pair);
+ String tmp = (String) mProperties.get(Constants.PR_TOKEN_NAME);
+
+ if ((tmp != null) &&
+ (!tmp.equals(Constants.PR_INTERNAL_TOKEN)))
+ mTokenname = tmp;
+ 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, new Boolean(true));
+ //extension.set(KeyUsageExtension.NON_REPUDIATION, new Boolean(true));
+ extension.set(KeyUsageExtension.KEY_ENCIPHERMENT, new Boolean(true));
+ return extension;
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/security/SubsystemCert.java b/pki/base/common/src/com/netscape/cmscore/security/SubsystemCert.java
new file mode 100644
index 000000000..4244d0212
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/security/SubsystemCert.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.security;
+
+
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import java.util.*;
+import java.io.*;
+import java.math.*;
+import java.security.PrivateKey;
+import java.security.InvalidKeyException;
+import java.security.SignatureException;
+import java.security.cert.*;
+import java.security.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.security.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.*;
+import org.mozilla.jss.crypto.Signature;
+import org.mozilla.jss.crypto.TokenException;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.CryptoManager.*;
+import org.mozilla.jss.*;
+
+
+/**
+ * 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, new Boolean(true));
+ extension.set(KeyUsageExtension.NON_REPUDIATION, new Boolean(true));
+ extension.set(KeyUsageExtension.KEY_ENCIPHERMENT, new Boolean(true));
+ return extension;
+ }
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/selftests/SelfTestOrderedInstance.java b/pki/base/common/src/com/netscape/cmscore/selftests/SelfTestOrderedInstance.java
new file mode 100644
index 000000000..22e4044ac
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/selftests/SelfTestOrderedInstance.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 statement //
+///////////////////////
+
+package com.netscape.cmscore.selftests;
+
+
+///////////////////////
+// import statements //
+///////////////////////
+
+import java.util.*;
+
+
+//////////////////////
+// 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/pki/base/common/src/com/netscape/cmscore/selftests/SelfTestSubsystem.java b/pki/base/common/src/com/netscape/cmscore/selftests/SelfTestSubsystem.java
new file mode 100644
index 000000000..5c75d8fd5
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/selftests/SelfTestSubsystem.java
@@ -0,0 +1,1907 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software 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.io.*;
+import java.util.*;
+import java.text.MessageFormat;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.selftests.*;
+
+
+//////////////////////
+// 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 //
+ //////////////////////////////////
+
+ private ISubsystem mOwner = null;
+ 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 mSelfTestInstances = new Hashtable();
+ public Vector mOnDemandOrder = new Vector();
+ public Vector mStartupOrder = new Vector();
+
+ ///////////////////////////
+ // 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 instances = mOnDemandOrder.elements();
+
+ int i = 0;
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = (SelfTestOrderedInstance)
+ 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 instances = mOnDemandOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = (SelfTestOrderedInstance)
+ 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 instances = mOnDemandOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = (SelfTestOrderedInstance)
+ 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 instances = mOnDemandOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = (SelfTestOrderedInstance)
+ 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 instances = mOnDemandOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = (SelfTestOrderedInstance)
+ 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 instances = mOnDemandOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = (SelfTestOrderedInstance)
+ 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 = (ISelfTest)
+ 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 instances = mStartupOrder.elements();
+
+ int i = 0;
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = (SelfTestOrderedInstance)
+ 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 instances = mStartupOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = (SelfTestOrderedInstance)
+ 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 instances = mStartupOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = (SelfTestOrderedInstance)
+ 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 instances = mStartupOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = (SelfTestOrderedInstance)
+ 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 instances = mStartupOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = (SelfTestOrderedInstance)
+ 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 instances = mStartupOrder.elements();
+
+ while (instances.hasMoreElements()) {
+ SelfTestOrderedInstance instance = (SelfTestOrderedInstance)
+ 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 = (ISelfTest)
+ 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;
+ } catch (ESelfTestException eAudit2) {
+ // 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 eAudit2;
+ }
+ }
+
+ 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 instances = mSelfTestInstances.elements();
+
+ while (instances.hasMoreElements()) {
+ ISelfTest instance = (ISelfTest) 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 {
+ // strip preceding/trailing whitespace
+ // from passed-in String parameters
+ if (id != null) {
+ id = id.trim();
+ } else {
+ 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 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 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 = (String) 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 instances = mSelfTestInstances.elements();
+
+ while (instances.hasMoreElements()) {
+ ISelfTest instance = (ISelfTest) instances.nextElement();
+
+ instance.startupSelfTest();
+ }
+
+ if (!CMS.isPreOpMode()) {
+ // run all self test plugin instances (designated at startup)
+ Enumeration 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 collection = mSelfTestInstances.values();
+ Vector list = new Vector(collection);
+
+ Collections.reverse(list);
+
+ // loop through all self test plugin instances
+ ListIterator instances = list.listIterator();
+
+ while (instances.hasNext()) {
+ ISelfTest instance = (ISelfTest) 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/pki/base/common/src/com/netscape/cmscore/time/SimpleTimeSource.java b/pki/base/common/src/com/netscape/cmscore/time/SimpleTimeSource.java
new file mode 100644
index 000000000..0427d82d7
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/time/SimpleTimeSource.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.time;
+
+
+import java.util.*;
+import com.netscape.certsrv.base.*;
+
+
+public class SimpleTimeSource implements ITimeSource {
+
+ public Date getCurrentDate() {
+ return new Date();
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/usrgrp/CertDNCertUserLocator.java b/pki/base/common/src/com/netscape/cmscore/usrgrp/CertDNCertUserLocator.java
new file mode 100644
index 000000000..f9312c1c4
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/usrgrp/CertDNCertUserLocator.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.usrgrp;
+
+
+import netscape.ldap.*;
+import java.util.*;
+import java.security.*;
+import java.security.cert.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.usrgrp.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/usrgrp/ExactMatchCertUserLocator.java b/pki/base/common/src/com/netscape/cmscore/usrgrp/ExactMatchCertUserLocator.java
new file mode 100644
index 000000000..0fb4d0d98
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/usrgrp/ExactMatchCertUserLocator.java
@@ -0,0 +1,82 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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 netscape.ldap.*;
+import java.util.*;
+import java.security.*;
+import java.security.cert.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.usrgrp.*;
+
+
+/**
+ * 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/pki/base/common/src/com/netscape/cmscore/usrgrp/Group.java b/pki/base/common/src/com/netscape/cmscore/usrgrp/Group.java
new file mode 100644
index 000000000..05aec23dc
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/usrgrp/Group.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.usrgrp;
+
+
+import java.util.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.usrgrp.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * A class represents a group.
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class Group implements IGroup {
+ private IUsrGrp mBase = null;
+ private String mName = null;
+ private Vector mMembers = new Vector();
+ private String mDescription = null;
+
+ private static final Vector mNames = new Vector();
+ 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 getMemberNames() {
+ return mMembers.elements();
+ }
+
+ public boolean isMember(String name) {
+ for (int i = 0; i < mMembers.size(); i++) {
+ String id = (String) mMembers.elementAt(i);
+
+ if (name.equals(id)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ 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) 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 getElements() {
+ return mNames.elements();
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/usrgrp/UGSubsystem.java b/pki/base/common/src/com/netscape/cmscore/usrgrp/UGSubsystem.java
new file mode 100644
index 000000000..d19cbf2d3
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/usrgrp/UGSubsystem.java
@@ -0,0 +1,1747 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.lang.*;
+import netscape.ldap.*;
+import java.security.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.usrgrp.*;
+
+import com.netscape.cmscore.ldapconn.*;
+import com.netscape.cmscore.ldap.*;
+import com.netscape.cmscore.util.*;
+
+
+/**
+ * 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 {
+
+ public static final String ID = "usrgrp";
+ private ICertUserLocator mCertUserLocator = null;
+ 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 PROP_BASEDN = "basedn";
+
+ protected IConfigStore mConfig = null;
+ protected LdapBoundConnFactory mLdapConnFactory = null;
+ protected String mBaseDN = null;
+ protected static UGSubsystem mUG = null;
+ private static final String PROP_IMPL = "impl";
+ private static final String PROP_CLASS = "class";
+ private static final String PROP_PASSWORD_CHECKER = "PasswordChecker";
+
+ private 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);
+ IConfigStore c = config.getSubStore(PROP_IMPL);
+ } 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();
+ mLdapConnFactory = null;
+ }
+ } 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 e = findUsers(userid);
+
+ if (e != null && e.hasMoreElements()) {
+ IUser u = (IUser) 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 e = buildUsers(res);
+
+ if (e.hasMoreElements()) {
+ return (IUser) 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 + "=" + getCertificateString(cert);
+ LDAPSearchResults res =
+ ldapconn.search(getUserBaseDN(),
+ LDAPConnection.SCOPE_SUB, filter, null, false);
+ Enumeration e = buildUsers(res);
+
+ return (User) e.nextElement();
+ } catch (LDAPException e) {
+ String errMsg = "findUser()" + e.toString();
+
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ errMsg = "findUser: " + "Internal DB is unavailable";
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_FIND_USER", e.toString()));
+ } catch (ELdapException e) {
+ String errMsg =
+ "find User: Could not get connection to internaldb. Error " + 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;
+ String stripped = "";
+
+ hasSlash = up.indexOf('\\');
+ while (hasSlash != -1) {
+ stripped += up.substring(0, hasSlash) +
+ "\\5c";;
+ up = up.substring(hasSlash + 1);
+ hasSlash = up.indexOf('\\');
+ }
+ filter = stripped + up;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ LDAPSearchResults res = ldapconn.search(getUserBaseDN(),
+ LDAPv2.SCOPE_SUB, "(" + filter + ")",
+ null, false);
+
+ Enumeration e = buildUsers(res);
+
+ return (User) e.nextElement();
+ } catch (LDAPException e) {
+ String errMsg = "findUsersByCert()" + e.toString();
+
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ errMsg = "findUsersByCert: " + "Internal DB is unavailable";
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_FIND_USER_BY_CERT", e.toString()));
+ } catch (ELdapException e) {
+ String errMsg =
+ "find Users By Cert: " +
+ "Could not get connection to internaldb. Error " + 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 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 e = buildUsers(res);
+
+ return e;
+ } catch (LDAPException e) {
+ String errMsg = "findUsers()" + e.toString();
+
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ errMsg = "findUsersByCert: " + "Internal DB is unavailable";
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_FIND_USERS", e.toString()));
+ } catch (ELdapException e) {
+ String errMsg =
+ "find Users: Could not get connection to internaldb. Error " + 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 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 e = lbuildUsers(res);
+
+ return e;
+ } catch (LDAPException e) {
+ String errMsg = "listUsers()" + e.toString();
+
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ errMsg = "findUsersByCert: " + "Internal DB is unavailable";
+ }
+ 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 lbuildUsers(LDAPSearchResults res) throws
+ EUsrGrpException {
+ Vector v = new Vector();
+
+ while (res.hasMoreElements()) {
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+ IUser user = lbuildUser(entry);
+
+ v.addElement(user);
+ }
+ return v.elements();
+ }
+
+ protected Enumeration buildUsers(LDAPSearchResults res) throws
+ EUsrGrpException {
+ Vector v = new Vector();
+
+ 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 {
+ IUser id = createUser(this, (String)
+ entry.getAttribute("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 certVector = new Vector();
+ Enumeration e = certAttr.getByteValues();
+
+ try {
+ for (; e != null && e.hasMoreElements();) {
+ X509Certificate cert = new X509CertImpl(
+ (byte[]) 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 en = certVector.elements();
+ int i = 0;
+
+ while (en.hasMoreElements()) {
+ certArray[i++] = (X509Certificate)
+ 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 {
+ IUser id = createUser(this, (String)
+ entry.getAttribute("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
+ String errMsg = "buildUser(): user DN not found: " +
+ userdn;
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_BUILD_USER"));
+
+ 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) {
+ Enumeration en = mailAttr.getStringValues();
+
+ if (en != null && en.hasMoreElements()) {
+ String mail = (String) 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) {
+ Enumeration en = phoneAttr.getStringValues();
+
+ if (en != null && en.hasMoreElements()) {
+ String phone = (String) 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 {
+ Enumeration en = userTypeAttr.getStringValues();
+
+ if (en != null && en.hasMoreElements()) {
+ String userType = (String) 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 {
+ Enumeration en = userStateAttr.getStringValues();
+
+ if (en != null && en.hasMoreElements()) {
+ String userState = (String) en.nextElement();
+
+ if (userState != null)
+ id.setState(userState);
+ else
+ id.setState("");
+
+ }
+ }
+
+ LDAPAttribute certAttr =
+ entry.getAttribute(LDAP_ATTR_USER_CERT);
+
+ if (certAttr != null) {
+ Vector certVector = new Vector();
+ Enumeration e = certAttr.getByteValues();
+
+ try {
+ for (; e != null && e.hasMoreElements();) {
+ X509Certificate cert = new X509CertImpl(
+ (byte[]) 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 en = certVector.elements();
+ int i = 0;
+
+ while (en.hasMoreElements()) {
+ certArray[i++] = (X509Certificate)
+ en.nextElement();
+ }
+
+ id.setX509Certificates(certArray);
+ }
+ }
+
+ 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();
+ String oc[] = {"top", "person", "organizationalPerson",
+ "inetOrgPerson", "cmsuser" };
+
+ attrs.add(new LDAPAttribute("objectclass", 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()));
+ }
+ }
+
+ LDAPEntry entry = new LDAPEntry("uid=" + 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) {
+ String errMsg =
+ "add User: Could not get connection to internaldb. Error " + 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 attrCertDNStr = new
+ LDAPAttribute(LDAP_ATTR_CERTDN);
+ */
+ LDAPAttribute attrCertBin = new
+ LDAPAttribute(LDAP_ATTR_USER_CERT);
+
+ try {
+ attrCertBin.addValue(cert[0].getEncoded());
+ attrCertStr.addValue(getCertificateString(cert[0]));
+ // attrCertDNStr.addValue(cert[0].getSubjectDN().toString());
+ } 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, attrCertDNStr);
+ addCert.add(LDAPModification.ADD, attrCertBin);
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ ldapconn.modify("uid=" + 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();
+ }
+ String errMsg = "addUserCert():" + e.toString();
+
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ errMsg = "findUsersByCert: " + "Internal DB is unavailable";
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_ADD_USER", e.toString()));
+ throw e;
+ } catch (ELdapException e) {
+ String errMsg =
+ "add User Cert: " +
+ "Could not get connection to internaldb. Error " + 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"));
+ }
+
+ LDAPAttribute certAttr = new
+ LDAPAttribute(LDAP_ATTR_USER_CERT);
+ LDAPAttribute certAttrS = new
+ LDAPAttribute(LDAP_ATTR_USER_CERT_STRING);
+
+ //LDAPAttribute certDNAttrS = new LDAPAttribute(LDAP_ATTR_CERTDN);
+
+ int certCount = 0;
+
+ for (int i = 0; i < certs.length; i++) {
+ LDAPModificationSet attrs = new LDAPModificationSet();
+
+ String certStr = null;
+
+ if (delCertdn.startsWith("-1;")) {
+ certStr = getCertificateStringWithoutVersion(certs[i]);
+ } else {
+ certStr = getCertificateString(certs[i]);
+ }
+ if (delCertdn.equalsIgnoreCase(certStr)) {
+ try {
+ certAttr.addValue(certs[i].getEncoded());
+ certAttrS.addValue(getCertificateString(certs[i]));
+ // certDNAttrS.addValue(certs[i].getSubjectDN().toString());
+ } catch (CertificateEncodingException e) {
+ throw new EUsrGrpException(CMS.getUserMessage("CMS_USRGRP_USR_CERT_ERROR"));
+ }
+
+ attrs.add(LDAPModification.DELETE, certAttr);
+ attrs.add(LDAPModification.DELETE, certAttrS);
+ //attrs.add(LDAPModification.DELETE, certDNAttrS);
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ ldapconn.modify("uid=" + user.getUserID() +
+ "," + getUserBaseDN(), 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 (LDAPException e) {
+ String errMsg = "removeUserCert():" + e;
+
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ errMsg =
+ "removeUserCert: " + "Internal DB is unavailable";
+ }
+ 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) {
+ String errMsg =
+ "remove User Cert: " +
+ "Could not get connection to internaldb. Error " + 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"));
+ }
+
+ return;
+ }
+
+ public void removeUserFromGroup(IGroup grp, String userid)
+ throws EUsrGrpException {
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ String groupDN = "cn=" + grp.getGroupID() +
+ "," + getGroupBaseDN();
+ LDAPAttribute memberAttr = new LDAPAttribute(
+ "uniquemember", "uid=" + userid + "," + getUserBaseDN());
+ LDAPModification singleChange = new LDAPModification(
+ LDAPModification.DELETE, memberAttr);
+
+ ldapconn.modify(groupDN, singleChange);
+ } catch (LDAPException e) {
+ String errMsg = "removeUserFromGroup()" + e.toString();
+
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ errMsg = "removeUser: " + "Internal DB is unavailable";
+ }
+ 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) {
+ String errMsg =
+ "removeUserFromGroup: Could not get connection to internaldb. Error " + 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=" + 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) {
+ String errMsg = "removeUser()" + e.toString();
+
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ errMsg = "removeUser: " + "Internal DB is unavailable";
+ }
+ 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) {
+ String errMsg =
+ "remove User: Could not get connection to internaldb. Error " + 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=" + 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=" + user.getUserID() +
+ "," + getUserBaseDN(), singleChange);
+ } catch (LDAPException e) {
+ if (e.getLDAPResultCode() != LDAPException.NO_SUCH_ATTRIBUTE) {
+ CMS.debug("modifyUser: Error in deleting userstate");
+ throw e;
+ }
+ }
+ }
+ }
+
+ /**
+ 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=" + 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 buildGroups(LDAPSearchResults res) {
+ Vector v = new Vector();
+
+ while (res.hasMoreElements()) {
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+
+ v.addElement(buildGroup(entry));
+ }
+ return v.elements();
+ }
+
+ /**
+ * Finds groups.
+ */
+ public Enumeration findGroups(String filter) {
+ 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) {
+ String errMsg =
+ "findGroups: could not find group " + filter + ". Error " + e;
+
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ errMsg = "findGroups: " + "Internal DB is unavailable";
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_FIND_GROUPS", e.toString()));
+ return null;
+ } catch (ELdapException e) {
+ String errMsg =
+ "find Groups: Could not get connection to internaldb. Error " + 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) {
+ Enumeration groups = findGroups(filter);
+
+ if (groups == null || !groups.hasMoreElements())
+ return null;
+ return (Group) groups.nextElement();
+ }
+
+ /**
+ * List groups. more efficient than find Groups. only retrieves
+ * group names and description.
+ */
+ public Enumeration 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) {
+ String errMsg = "listGroups()" + e.toString();
+
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ errMsg = "listGroups: " + "Internal DB is unavailable";
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_USRGRP_LIST_GROUPS", e.toString()));
+ } catch (ELdapException e) {
+ String errMsg =
+ "list Groups: Could not get connection to internaldb. Error " + 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
+ */
+ protected IGroup buildGroup(LDAPEntry entry) {
+ String groupName = (String)entry.getAttribute("cn").getStringValues().nextElement();
+ IGroup grp = createGroup(this, groupName);
+
+ LDAPAttribute grpDesc = entry.getAttribute("description");
+
+ if (grpDesc != null) {
+ Enumeration en = grpDesc.getStringValues();
+
+ if (en != null && en.hasMoreElements()) {
+ String desc = (String) 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;
+ }
+
+ Enumeration e = attr.getStringValues();
+
+ while (e.hasMoreElements()) {
+ String v = (String) 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=" + name + "," + getGroupBaseDN());
+ }
+
+ /**
+ * Retrieves a group from LDAP
+ * NOTE - LH This takes a full LDAP DN.
+ */
+ public IGroup getGroup(String name) {
+ if (name == null) {
+ return null;
+ }
+
+ LDAPConnection ldapconn = null;
+
+ try {
+ ldapconn = getConn();
+ // read the group object
+ LDAPSearchResults res = ldapconn.search(name,
+ LDAPConnection.SCOPE_BASE, "(objectclass=*)", null, false);
+ Enumeration e = buildGroups(res);
+
+ if (e == null || e.hasMoreElements() == false)
+ return null;
+ return (IGroup) 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;
+ }
+ Enumeration en = attr.getStringValues();
+
+ for (; en.hasMoreElements();) {
+ String v = (String) 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);
+ 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="+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="+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()) {
+ // actually read the entry
+ LDAPEntry entry = (LDAPEntry)res.nextElement();
+ 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 e = grp.getMemberNames();
+
+ if (e.hasMoreElements() == true) {
+ LDAPAttribute attrMembers = new LDAPAttribute("uniquemember");
+
+ while (e.hasMoreElements()) {
+ String name = (String) e.nextElement();
+
+ // DOES NOT SUPPORT NESTED GROUPS...
+ attrMembers.addValue("uid=" + name + "," +
+ getUserBaseDN());
+ }
+ attrs.add(attrMembers);
+ }
+ LDAPEntry entry = new LDAPEntry("cn=" + grp.getGroupID() +
+ "," + getGroupBaseDN(), attrs);
+
+ ldapconn = getConn();
+ ldapconn.add(entry);
+ } catch (LDAPException e) {
+ String errMsg = "addGroup()" + e.toString();
+
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ errMsg = "addGroup: " + "Internal DB is unavailable";
+ }
+ 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) {
+ String errMsg =
+ "add Group: Could not get connection to internaldb. Error " + 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=" + name + "," + getGroupBaseDN());
+ } catch (LDAPException e) {
+ String errMsg = "removeGroup()" + e.toString();
+
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ errMsg = "removeGroup: " + "Internal DB is unavailable";
+ }
+ 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) {
+ String errMsg =
+ "remove Group: Could not get connection to internaldb. " +
+ "Error " + 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 st = null;
+
+ String desc = grp.getDescription();
+
+ if (desc != null) {
+ mod.add(LDAPModification.REPLACE,
+ new LDAPAttribute("description", desc));
+ }
+
+ Enumeration e = grp.getMemberNames();
+
+ if (e.hasMoreElements() == true) {
+ while (e.hasMoreElements()) {
+ String name = (String) e.nextElement();
+
+ // DOES NOT SUPPORT NESTED GROUPS...
+ attrMembers.addValue("uid=" + 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=" + grp.getGroupID() +
+ "," + getGroupBaseDN(), mod);
+ } catch (LDAPException e) {
+ String errMsg = " modifyGroup()" + e.toString();
+
+ if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) {
+ errMsg = "modifyGroup: " + "Internal DB is unavailable";
+ }
+ 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=" + u + ")", null, false);
+
+ if (res.hasMoreElements()) {
+ LDAPEntry entry = (LDAPEntry) res.nextElement();
+
+ return entry.getDN();
+ }
+ } catch (ELdapException e) {
+ String errMsg =
+ "convertUIDtoDN: Could not get connection to internaldb. " +
+ "Error " + 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.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)
+ return null;
+ return mLdapConnFactory.getConn();
+ }
+
+ 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/pki/base/common/src/com/netscape/cmscore/usrgrp/User.java b/pki/base/common/src/com/netscape/cmscore/usrgrp/User.java
new file mode 100644
index 000000000..5ecb4f169
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/usrgrp/User.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.cmscore.usrgrp;
+
+
+import java.util.*;
+import java.security.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.usrgrp.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * A class represents a user.
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class User implements IUser {
+
+ public static final String ATTR_X509_CERTIFICATES = "userCertificates";
+ private IUsrGrp mBase = null;
+ 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 static final Vector mNames = new Vector();
+ 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);
+ }
+
+ /**
+ * 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;
+ }
+
+ 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 {
+ 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 {
+ 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 getElements() {
+ return mNames.elements();
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/util/Assert.java b/pki/base/common/src/com/netscape/cmscore/util/Assert.java
new file mode 100644
index 000000000..afc38f49b
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/Assert.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.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/pki/base/common/src/com/netscape/cmscore/util/AssertionException.java b/pki/base/common/src/com/netscape/cmscore/util/AssertionException.java
new file mode 100644
index 000000000..7b0675b12
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/AssertionException.java
@@ -0,0 +1,32 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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 {
+ public AssertionException() {
+ }
+
+ public AssertionException(String msg) {
+ super(msg);
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/util/Debug.java b/pki/base/common/src/com/netscape/cmscore/util/Debug.java
new file mode 100644
index 000000000..b9b794e9c
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/Debug.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.cmscore.util;
+
+
+import com.netscape.certsrv.base.*;
+import com.netscape.cmsutil.util.*;
+
+import java.lang.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+
+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 mFormatObject = new ThreadLocal() {
+ protected synchronized Object initialValue() {
+ return new SimpleDateFormat(DATE_PATTERN);
+ }
+ };
+
+ /* the dateformatter should be accessed with this function */
+ private static SimpleDateFormat getDateFormatter() {
+ return ((SimpleDateFormat)(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 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("obj is: "+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();
+ 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/pki/base/common/src/com/netscape/cmscore/util/ExceptionFormatter.java b/pki/base/common/src/com/netscape/cmscore/util/ExceptionFormatter.java
new file mode 100644
index 000000000..61f6f49ec
--- /dev/null
+++ b/pki/base/common/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.*;
+
+
+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();
+
+ try {
+ PipedOutputStream po = new PipedOutputStream();
+ 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 {
+
+ public TestException() {
+ }
+
+ public TestException(String s) {
+ super(s);
+ }
+
+}
+
diff --git a/pki/base/common/src/com/netscape/cmscore/util/FileAsString.java b/pki/base/common/src/com/netscape/cmscore/util/FileAsString.java
new file mode 100644
index 000000000..968f9cb80
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/FileAsString.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.util;
+
+
+import java.io.*;
+import java.lang.StringBuffer;
+
+
+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;
+
+ do {
+ char cbuf[] = new char[16];
+
+ bytesread = br.read(cbuf, 0, cbuf.length);
+ if (bytesread > 0) {
+ buf.append(cbuf, 0, bytesread);
+ }
+ String s = new String(buf);
+ }
+ while (bytesread != -1);
+ 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) {
+ try {
+ if (fr != null) {
+ fr.close();
+ }
+ } catch (Exception f) {
+ }
+ 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/pki/base/common/src/com/netscape/cmscore/util/FileDialogFilter.java b/pki/base/common/src/com/netscape/cmscore/util/FileDialogFilter.java
new file mode 100644
index 000000000..98a2e8422
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/FileDialogFilter.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.cmscore.util;
+
+
+import java.io.*;
+
+
+/**
+ * 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 fileNameCursor = 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/pki/base/common/src/com/netscape/cmscore/util/OsSubsystem.java b/pki/base/common/src/com/netscape/cmscore/util/OsSubsystem.java
new file mode 100644
index 000000000..a3cdcbdef
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/OsSubsystem.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.cmscore.util;
+
+
+import java.io.*;
+import java.util.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.apps.*;
+import com.netscape.cmscore.base.*;
+import com.netscape.osutil.*;
+
+
+/**
+ * This object contains the OS independent interfaces. It's currently
+ * used for Unix signal and user handling, but could eventually be extended
+ * for NT interfaces.
+ * <P>
+ *
+ * @author mikep
+ * @version $Revision$, $Date$
+ */
+public final class OsSubsystem implements ISubsystem {
+
+ public static final String ID = "os";
+ protected IConfigStore mConfig;
+ protected String mInstanceDir;
+ protected ISubsystem mOwner;
+ protected ILogger mLogger = null;
+ protected static SignalThread mSignalThread = null;
+
+ private static final String PROP_OS = "os";
+ private static final String PROP_USERID = "userid";
+
+ // singleton enforcement
+
+ private static OsSubsystem mInstance = new OsSubsystem();
+
+ public static OsSubsystem getInstance() {
+ return mInstance;
+ }
+
+ // end singleton enforcement.
+
+ /**
+ * Constructor for an OS subsystem
+ */
+ private OsSubsystem() {
+ }
+
+ /**
+ * Retrieves subsystem name.
+ */
+ public String getId() {
+ return ID;
+ }
+
+ public void setId(String id) throws EBaseException {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION"));
+ }
+
+ /**
+ * 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 {
+
+ mOwner = owner;
+ mConfig = config;
+ mLogger = CMS.getLogger();
+
+ mInstanceDir = CMS.getConfigStore().getString("instanceRoot");
+
+ // We currently only deal with Unix and NT
+ if (isUnix()) {
+ //initUnix();
+ } else {
+ initNT();
+ }
+ try {
+ //System.out.println(" The dir I'm seeing is " + mInstanceDir);
+ String pidName = mInstanceDir + File.separator + "config" + File.separator + "cert-pid";
+ BufferedWriter pidOut = new BufferedWriter(new FileWriter(pidName));
+ int pid = OsSubsystem.getpid();
+
+ pidOut.write(Integer.toString(pid));
+ pidOut.close();
+ OSUtil.getFileWriteLock(pidName);
+ } catch (Exception e) {
+ //XX to stderr XXXXXX
+ //e.printStackTrace();
+ }
+ }
+
+ /**
+ * Starts up OS
+ */
+ public void startup() throws EBaseException {
+ if (isUnix()) {
+ String pf = mConfig.getString("pidFile", null);
+
+ if (pf == null) {
+ return; // development environment does not rely on this
+ }
+ // dont ever call detach in Java environment,
+ // it does a fork()
+ // LibC.detach();
+
+ // need to do pid here, pid will be changed after detach
+ int pid = LibC.getpid();
+ String pidStr = Integer.toString(pid);
+
+ try {
+ FileOutputStream fos = new FileOutputStream(pf);
+
+ fos.write(pidStr.getBytes());
+ fos.close();
+ } catch (IOException e) {
+
+ /*LogDoc
+ *
+ * @phase start OS subsystem
+ * @message OS: <exception thrown>
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE, "OS: " + e.toString());
+ }
+ }
+ }
+
+ /**
+ * Returns the process ID of the Certificate Server process. Works
+ * on Unix and NT.
+ */
+ public static int getpid() {
+ if (isUnix()) {
+ return LibC.getpid();
+ } else {
+ return OSUtil.getNTpid();
+ }
+ }
+
+ /**
+ * Hooks up unix signals.
+ */
+ private void initUnix() throws EBaseException {
+ // Set up signal handling. We pretty much exit on anything
+ // Signal.watch(Signal.SIGHUP);
+ // Signal.watch(Signal.SIGTERM);
+ // Signal.watch(Signal.SIGINT);
+ // mSignalThread = new SignalThread();
+ // mSignalThread.setDaemon(true);
+ // mSignalThread.start();
+
+ Signal.addSignalListener(Signal.SIGHUP, new SIGHUPListener(this));
+ Signal.addSignalListener(Signal.SIGTERM, new SIGTERMListener(this));
+ Signal.addSignalListener(Signal.SIGINT, new SIGINTListener(this));
+
+ /* Increase the maximum number of file descriptors */
+ int i = mConfig.getInteger("maxFiles",
+ ResourceLimit.getHardLimit(ResourceLimit.RLIMIT_NOFILE));
+
+ ResourceLimit.setLimits(ResourceLimit.RLIMIT_NOFILE,
+ i, ResourceLimit.getHardLimit(ResourceLimit.RLIMIT_NOFILE));
+
+ // write current pid to specified file
+ String pf = mConfig.getString("pidFile", null);
+
+ if (pf == null) {
+ return; // development environment does not rely on this
+ }
+ File pidFile = new File(pf);
+
+ if (pidFile.exists()) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_PID_EXIST"));
+ }
+ }
+
+ /**
+ * Used to change the process user id usually called after the appropriate
+ * network ports have been opened.
+ */
+ public void setUserId() throws EBaseException {
+ if (!isUnix())
+ return;
+
+ String userid;
+
+ userid = mConfig.getString(PROP_USERID, null);
+ String id = String.valueOf(UserID.get());
+
+ // Change the userid to the prefered Unix user
+ if (userid == null) {
+
+ /*LogDoc
+ *
+ * @phase set user id
+ * @arg0 default user id
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE,
+ "OS: No user id in config file. Running as {0}", id);
+ } else {
+ Object[] params = {userid, id};
+
+ try {
+ UserID.set(userid);
+ } catch (IllegalArgumentException e) {
+
+ /*LogDoc
+ *
+ * @phase set user id
+ * @arg0 supplied user id in config
+ * @arg1 default user id
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE,
+ "OS: No such user as {0}. Running as {1}", params);
+ } catch (SecurityException e) {
+
+ /*LogDoc
+ *
+ * @phase set user id
+ * @arg0 supplied user id in config
+ * @arg1 default user id
+ */
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_FAILURE,
+ "OS: Can't change process uid to {0}. Running as {1}",
+ params);
+ }
+ }
+ }
+
+ private void initNT() {
+ }
+
+ /**
+ * Stops the watchdog. You need to call this if you want the
+ * server to really shutdown, otherwise the watchdog will just
+ * restart us.
+ * <P>
+ */
+ public static void stop() {
+ if (isUnix()) {
+ shutdownUnix();
+ Signal.send(LibC.getppid(), Signal.SIGTERM);
+ } else {
+
+ /*LogDoc
+ *
+ * @phase stop watchdog
+ */
+ CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
+ ILogger.LL_INFO,
+ "OS: stop the NT watchdog!");
+ }
+ }
+
+ /**
+ * Stops this system.
+ * <P>
+ */
+ public void shutdown() {
+ if (isUnix()) {
+ shutdownUnix();
+ } else {
+ shutdownNT();
+ }
+ }
+
+ /**
+ * Shutdown the unix system handlers
+ * <P>
+ */
+ private static void shutdownUnix() {
+
+ // Don't accidentally stop this thread
+ //if (Thread.currentThread() != mSignalThread && mSignalThread != null) {
+ // mSignalThread.stop();
+ // mSignalThread = null;
+ //}
+
+ /* Don't release this signals to protect the process
+ Signal.release(Signal.SIGHUP);
+ Signal.release(Signal.SIGTERM);
+ Signal.release(Signal.SIGINT);
+ */
+ }
+
+ /**
+ * Shutdown the NT system handlers
+ * <P>
+ */
+ private void shutdownNT() {
+ }
+
+ /**
+ * Restart the server
+ * <P>
+ */
+ public void restart() {
+
+ /**
+ if (isUnix()) {
+ restartUnix();
+ } else {
+ restartNT();
+ }
+ **/
+ }
+
+ /**
+ * Unix restart
+ * <P>
+ */
+ private void restartUnix() {
+ // Tell watch dog to restart us
+ int ppid = LibC.getppid();
+
+ Signal.send(ppid, Signal.SIGHUP);
+ }
+
+ /**
+ * NT restart
+ * <P>
+ */
+ private void restartNT() {
+ }
+
+ /**
+ * Returns the root configuration storage of this system.
+ * <P>
+ *
+ * @return configuration store of this subsystem
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * A universal routine to decide if we are Unix or something else.
+ * This is mostly used for signal handling and uids.
+ *
+ * <P>
+ * @return true if these OS the JavaVM is running on is some Unix varient
+ */
+ public static boolean isUnix() {
+ // XXX What about MacOS?
+ return (File.separatorChar == '/');
+ }
+
+ /**
+ * Unix signal thread. Sleep for a second and then check on the
+ * signals we're interested in. If one is set, do the right stuff
+ */
+ final class SignalThread extends Thread {
+
+ /**
+ * Signal thread constructor
+ */
+ public SignalThread() {
+ super();
+ super.setName("OsSignal-" + (Thread.activeCount() + 1));
+ }
+
+ /**
+ * Check for signal changes every second
+ */
+ public void run() {
+ while (true) {
+ // Sleep for the interval and then check for caught signals
+ // synchronized (Thread.this) {
+ synchronized (this) {
+ try {
+ // Thread.this.wait(1000);
+ this.wait(1000);
+ } catch (InterruptedException e) {
+ // Not very interesting...
+ }
+ }
+
+ // wants us to exit?
+ if (Signal.caught(Signal.SIGINT) > 0 ||
+ Signal.caught(Signal.SIGTERM) > 0) {
+
+ /*LogDoc
+ *
+ * @phase watchdog check
+ */
+ mLogger.log(ILogger.EV_SYSTEM,
+ ILogger.S_OTHER,
+ ILogger.LL_INFO,
+ "OS: Received shutdown signal");
+ SubsystemRegistry.getInstance().get("MAIN").shutdown();
+ return;
+ }
+
+ // Tell to restart us
+ if (Signal.caught(Signal.SIGHUP) > 0) {
+
+ /*LogDoc
+ *
+ * @phase watchdog check
+ */
+ mLogger.log(ILogger.EV_SYSTEM,
+ ILogger.S_OTHER,
+ ILogger.LL_INFO,
+ "OS: Received restart signal");
+ restart();
+ return;
+ }
+
+ }
+ }
+
+ }
+}
+
+
+class SIGTERMListener extends SignalListener {
+ private OsSubsystem mOS;
+ public SIGTERMListener(OsSubsystem os) {
+ mOS = os;
+ }
+
+ public void process() {
+ System.out.println("SIGTERMListener process");
+ // XXX - temp, should call shutdown
+ System.exit(0);
+ //PKIServer.getPKIServer().shutdown();
+ }
+}
+
+
+class SIGINTListener extends SignalListener {
+ private OsSubsystem mOS;
+ public SIGINTListener(OsSubsystem os) {
+ mOS = os;
+ }
+
+ public void process() {
+ System.out.println("SIGINTListener process");
+ // XXX - temp, should call shutdown
+ System.exit(0);
+ //PKIServer.getPKIServer().shutdown();
+ }
+}
+
+
+class SIGHUPListener extends SignalListener {
+ private OsSubsystem mOS;
+ public SIGHUPListener(OsSubsystem os) {
+ mOS = os;
+ }
+
+ public void process() {
+ System.out.println("SIGHUPListener process");
+ // XXX - temp, should call shutdown
+ // System.exit(0);
+ //PKIServer.getPKIServer().shutdown();
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/util/PFXUtils.java b/pki/base/common/src/com/netscape/cmscore/util/PFXUtils.java
new file mode 100644
index 000000000..ed268df46
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/PFXUtils.java
@@ -0,0 +1,162 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.util.*;
+import java.text.*;
+
+import java.security.*;
+import java.security.cert.*;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.crypto.PBEAlgorithm;
+import org.mozilla.jss.pkcs12.*;
+import org.mozilla.jss.pkix.primitive.*;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.*;
+
+
+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/pki/base/common/src/com/netscape/cmscore/util/ProfileSubsystem.java b/pki/base/common/src/com/netscape/cmscore/util/ProfileSubsystem.java
new file mode 100644
index 000000000..d7ba11c02
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/ProfileSubsystem.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.util;
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.table.*;
+import com.netscape.certsrv.base.*;
+
+
+/**
+ * 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 String mId = null;
+ private Thread mMonitoring = new Thread(this);
+ private TextArea mTextArea = null;
+ private JScrollPane mThreads = null;
+ private JTable mThreadTable = null;
+ private JButton mGC = 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 = JTable.createScrollPaneForTable(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 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 void updateThreadPanel() {
+ Thread currentThread = Thread.currentThread();
+ Vector data = new Vector();
+ Thread threads[] = new Thread[100];
+ int numThreads = Thread.enumerate(threads);
+
+ for (int i = 0; i < numThreads; i++) {
+ Vector row = new Vector();
+
+ 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 colNames = new Vector();
+
+ 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
+ mMonitoring.sleep(1000);
+ } catch (Exception e) {
+ }
+ }
+ }
+}
+
+
+class ThreadTableModel extends AbstractTableModel {
+ Vector rowData;
+ Vector columnNames;
+
+ public ThreadTableModel() {
+ }
+
+ public void setInfo(Vector _rowData, Vector _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 Object getValueAt(int row, int column) {
+ return ((Vector) rowData.elementAt(row)).elementAt(column);
+ }
+
+ public boolean isCellEditable(int row, int column) {
+ return false;
+ }
+
+ public void setValueAt(Object value, int row, int column) {
+ ((Vector) 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));
+ threads[i].dumpStack(); // not working, print only current thread
+ System.setErr(err);
+ }
+
+ String str = outArray.toString();
+
+ field.setText(str);
+ dialog.setTitle(name);
+ dialog.setSize(500, 400);
+ dialog.setVisible(true);
+
+ dialog.setContentPane(pane);
+ dialog.show();
+ }
+ }
+ }
+
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/util/StatsSubsystem.java b/pki/base/common/src/com/netscape/cmscore/util/StatsSubsystem.java
new file mode 100644
index 000000000..ba07b2ca0
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/StatsSubsystem.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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.util;
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.table.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.util.*;
+import com.netscape.certsrv.apps.*;
+
+/**
+ * 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 mHashtable = new Hashtable();
+
+ /**
+ * 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 milestones = null;
+ if (mHashtable.containsKey(t.toString())) {
+ milestones = (Vector)mHashtable.get(t.toString());
+ } else {
+ milestones = new Vector();
+ mHashtable.put(t.toString(), milestones);
+ }
+ long startTime = CMS.getCurrentDate().getTime();
+ StatsEvent currentST = null;
+ for (int i = 0; i < milestones.size(); i++) {
+ StatsMilestone se = (StatsMilestone)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 milestones = (Vector)mHashtable.get(t.toString());
+ if (milestones.size() == 0) {
+ return; /* error */
+ }
+ StatsMilestone last = (StatsMilestone)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/pki/base/common/src/com/netscape/cmscore/util/UtilMessage.java b/pki/base/common/src/com/netscape/cmscore/util/UtilMessage.java
new file mode 100644
index 000000000..e9b2a6cdd
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/util/UtilMessage.java
@@ -0,0 +1,179 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.util;
+
+
+import com.netscape.certsrv.base.MessageFormatter;
+import java.util.Locale;
+
+
+/**
+ * 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("failed to load {0}", 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/pki/base/common/src/com/netscape/cmscore/util/UtilResources.java b/pki/base/common/src/com/netscape/cmscore/util/UtilResources.java
new file mode 100644
index 000000000..8114413b0
--- /dev/null
+++ b/pki/base/common/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.*;
+
+
+/**
+ * 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"},
+ };
+}