From 621d9e5c413e561293d7484b93882d985b3fe15f Mon Sep 17 00:00:00 2001 From: Endi Sukma Dewata Date: Sat, 24 Mar 2012 02:27:47 -0500 Subject: Removed unnecessary pki folder. Previously the source code was located inside a pki folder. This folder was created during svn migration and is no longer needed. This folder has now been removed and the contents have been moved up one level. Ticket #131 --- .../netscape/cmscore/security/CASigningCert.java | 162 ++ .../netscape/cmscore/security/CertificateInfo.java | 277 +++ .../netscape/cmscore/security/JssSubsystem.java | 2203 ++++++++++++++++++++ .../cmscore/security/KRATransportCert.java | 107 + .../com/netscape/cmscore/security/KeyCertUtil.java | 1139 ++++++++++ .../netscape/cmscore/security/OCSPSigningCert.java | 140 ++ .../src/com/netscape/cmscore/security/PWCBsdr.java | 266 +++ .../src/com/netscape/cmscore/security/PWUtil.java | 73 + .../com/netscape/cmscore/security/PWsdrCache.java | 639 ++++++ .../com/netscape/cmscore/security/Provider.java | 57 + .../netscape/cmscore/security/RASigningCert.java | 113 + .../src/com/netscape/cmscore/security/SSLCert.java | 125 ++ .../cmscore/security/SSLSelfSignedCert.java | 119 ++ .../netscape/cmscore/security/SubsystemCert.java | 81 + 14 files changed, 5501 insertions(+) create mode 100644 base/common/src/com/netscape/cmscore/security/CASigningCert.java create mode 100644 base/common/src/com/netscape/cmscore/security/CertificateInfo.java create mode 100644 base/common/src/com/netscape/cmscore/security/JssSubsystem.java create mode 100644 base/common/src/com/netscape/cmscore/security/KRATransportCert.java create mode 100644 base/common/src/com/netscape/cmscore/security/KeyCertUtil.java create mode 100644 base/common/src/com/netscape/cmscore/security/OCSPSigningCert.java create mode 100644 base/common/src/com/netscape/cmscore/security/PWCBsdr.java create mode 100644 base/common/src/com/netscape/cmscore/security/PWUtil.java create mode 100644 base/common/src/com/netscape/cmscore/security/PWsdrCache.java create mode 100644 base/common/src/com/netscape/cmscore/security/Provider.java create mode 100644 base/common/src/com/netscape/cmscore/security/RASigningCert.java create mode 100644 base/common/src/com/netscape/cmscore/security/SSLCert.java create mode 100644 base/common/src/com/netscape/cmscore/security/SSLSelfSignedCert.java create mode 100644 base/common/src/com/netscape/cmscore/security/SubsystemCert.java (limited to 'base/common/src/com/netscape/cmscore/security') diff --git a/base/common/src/com/netscape/cmscore/security/CASigningCert.java b/base/common/src/com/netscape/cmscore/security/CASigningCert.java new file mode 100644 index 000000000..bba12561f --- /dev/null +++ b/base/common/src/com/netscape/cmscore/security/CASigningCert.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.security; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.KeyPair; + +import netscape.security.x509.KeyUsageExtension; + +import org.mozilla.jss.crypto.PQGParamGenException; +import org.mozilla.jss.crypto.PQGParams; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.common.ConfigConstants; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.security.KeyCertData; + +/** + * CA signing certificate. + * + * @author Christine Ho + * @version $Revision$, $Date$ + */ +public class CASigningCert extends CertificateInfo { + + public static final String SUBJECT_NAME = + "CN=Certificate Authority, O=Netscape Communications, C=US"; + + public CASigningCert(KeyCertData properties) { + this(properties, null); + } + + public CASigningCert(KeyCertData properties, KeyPair pair) { + super(properties, pair); + /* included in console UI + try { + if (mProperties.get(Constants.PR_AKI) == null) { + mProperties.put(Constants.PR_AKI, Constants.FALSE); + } + } catch (Exception e) { + mProperties.put(Constants.PR_AKI, Constants.FALSE); + } + */ + try { + if (mProperties.get(Constants.PR_CERT_LEN) == null) { + mProperties.put(Constants.PR_CERT_LEN, "-1"); + } + } catch (Exception e) { + mProperties.put(Constants.PR_CERT_LEN, "-1"); + } + try { + if (mProperties.get(Constants.PR_IS_CA) == null) { + // "null" mean no BasicConstriant + mProperties.put(Constants.PR_IS_CA, "null"); + } + } catch (Exception e) { + // "null" mean no BasicConstriant + mProperties.put(Constants.PR_IS_CA, "null"); + } + /* included in console UI + try { + if (mProperties.get(Constants.PR_SKI) == null) { + mProperties.put(Constants.PR_SKI, Constants.FALSE); + } + } catch (Exception e) { + mProperties.put(Constants.PR_SKI, Constants.FALSE); + } + */ + } + + public String getSubjectName() { + return (String) mProperties.get(Constants.PR_SUBJECT_NAME); + } + + // get PQG params from the configuration file + public 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/base/common/src/com/netscape/cmscore/security/CertificateInfo.java b/base/common/src/com/netscape/cmscore/security/CertificateInfo.java new file mode 100644 index 000000000..fc7fb9087 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/security/CertificateInfo.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.security; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateParsingException; +import java.util.Calendar; +import java.util.Date; + +import netscape.security.util.DerInputStream; +import netscape.security.util.ObjectIdentifier; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.AuthorityKeyIdentifierExtension; +import netscape.security.x509.CertificateAlgorithmId; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateIssuerName; +import netscape.security.x509.CertificateSerialNumber; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.CertificateVersion; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.KeyIdentifier; +import netscape.security.x509.KeyUsageExtension; +import netscape.security.x509.SubjectKeyIdentifierExtension; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.crypto.PQGParamGenException; +import org.mozilla.jss.crypto.SignatureAlgorithm; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.common.ConfigConstants; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.security.KeyCertData; + +/** + * This base class provides methods to import CA signing cert or get certificate + * request. + * + * @author Christine Ho + * @version $Revision$, $Date$ + */ +public abstract class CertificateInfo { + + protected KeyCertData mProperties; + protected KeyPair mKeyPair; + protected 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()); + + Calendar calendar = Calendar.getInstance(); + calendar.set(beginYear, beginMonth, beginDate, + beginHour, beginMin, beginSec); + notBeforeDate = calendar.getTime(); + calendar.set(afterYear, afterMonth, afterDate, + afterHour, afterMin, afterSec); + notAfterDate = calendar.getTime(); + } + return new CertificateValidity(notBeforeDate, notAfterDate); + } + + public X509CertInfo getCertInfo() throws EBaseException, PQGParamGenException { + X509CertInfo certInfo = new X509CertInfo(); + + try { + certInfo.set(X509CertInfo.VERSION, + new CertificateVersion(CertificateVersion.V3)); + BigInteger serialNumber = mProperties.getSerialNumber(); + + certInfo.set(X509CertInfo.SERIAL_NUMBER, + new CertificateSerialNumber(serialNumber)); + certInfo.set(X509CertInfo.EXTENSIONS, getExtensions()); + certInfo.set(X509CertInfo.VALIDITY, getCertificateValidity()); + String issuerName = mProperties.getIssuerName(); + + if (issuerName == null) { + issuerName = getSubjectName(); + } + + certInfo.set(X509CertInfo.ISSUER, + new CertificateIssuerName(new X500Name(issuerName))); + certInfo.set(X509CertInfo.SUBJECT, + new CertificateSubjectName(new X500Name(getSubjectName()))); + certInfo.set(X509CertInfo.VERSION, + new CertificateVersion(CertificateVersion.V3)); + + PublicKey pubk = mKeyPair.getPublic(); + X509Key xKey = KeyCertUtil.convertPublicKeyToX509Key(pubk); + + certInfo.set(X509CertInfo.KEY, new CertificateX509Key(xKey)); + //SignatureAlgorithm algm = getSigningAlgorithm(); + SignatureAlgorithm algm = + (SignatureAlgorithm) mProperties.get(Constants.PR_SIGNATURE_ALGORITHM); + + if (algm == null) { + String hashtype = (String) mProperties.get(ConfigConstants.PR_HASH_TYPE); + + 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); + String aki = mProperties.getAKI(); + + if ((aki != null) && (aki.equals(Constants.TRUE))) { + CertificateExtensions caexts = null; + + // if (this instanceof CASigningCert) { + if (this.getClass().getName().indexOf("CASigningCert") != -1) { + caexts = exts; + } else { + caexts = mProperties.getCAExtensions(); + } + setAuthorityKeyIdExt(caexts, exts); + } + boolean isKeyUsageEnabled = mProperties.getKeyUsageExtension(); + + if (isKeyUsageEnabled) { + KeyCertUtil.setKeyUsageExtension( + exts, getKeyUsageExtension()); + } + return exts; + } + + public AlgorithmId getAlgorithmId() { + return (AlgorithmId) (mProperties.get(Constants.PR_ALGORITHM_ID)); + } + + public void setAuthorityKeyIdExt(CertificateExtensions caexts, CertificateExtensions ext) + throws IOException, CertificateException, CertificateEncodingException, + CertificateParsingException { + SubjectKeyIdentifierExtension subjKeyExt = null; + + try { + subjKeyExt = + (SubjectKeyIdentifierExtension) caexts.get(SubjectKeyIdentifierExtension.NAME); + } catch (IOException e) { + } + + if (subjKeyExt == null) + return; + else { + KeyIdentifier keyId = (KeyIdentifier) subjKeyExt.get( + SubjectKeyIdentifierExtension.KEY_ID); + AuthorityKeyIdentifierExtension authExt = + new AuthorityKeyIdentifierExtension(false, keyId, null, null); + + ext.set(AuthorityKeyIdentifierExtension.NAME, authExt); + } + } +} diff --git a/base/common/src/com/netscape/cmscore/security/JssSubsystem.java b/base/common/src/com/netscape/cmscore/security/JssSubsystem.java new file mode 100644 index 000000000..42768060c --- /dev/null +++ b/base/common/src/com/netscape/cmscore/security/JssSubsystem.java @@ -0,0 +1,2203 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.security; + +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.math.BigInteger; +import java.net.SocketException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.InvalidParameterException; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Principal; +import java.security.PublicKey; +import java.security.SignatureException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.StringTokenizer; +import java.util.Vector; + +import netscape.ldap.util.DN; +import netscape.security.x509.AlgIdDSA; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.BasicConstraintsExtension; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.CryptoManager.NicknameConflictException; +import org.mozilla.jss.CryptoManager.NotInitializedException; +import org.mozilla.jss.CryptoManager.UserCertConflictException; +import org.mozilla.jss.NoSuchTokenException; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.crypto.AlreadyInitializedException; +import org.mozilla.jss.crypto.CryptoStore; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.InternalCertificate; +import org.mozilla.jss.crypto.KeyPairAlgorithm; +import org.mozilla.jss.crypto.NoSuchItemOnTokenException; +import org.mozilla.jss.crypto.ObjectNotFoundException; +import org.mozilla.jss.crypto.PQGParamGenException; +import org.mozilla.jss.crypto.PQGParams; +import org.mozilla.jss.crypto.PrivateKey; +import org.mozilla.jss.crypto.SignatureAlgorithm; +import org.mozilla.jss.crypto.TokenCertificate; +import org.mozilla.jss.crypto.TokenException; +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.pkcs11.PK11SecureRandom; +import org.mozilla.jss.pkcs7.ContentInfo; +import org.mozilla.jss.pkcs7.SignedData; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.ssl.SSLServerSocket; +import org.mozilla.jss.ssl.SSLSocket; +import org.mozilla.jss.util.IncorrectPasswordException; +import org.mozilla.jss.util.Password; +import org.mozilla.jss.util.PasswordCallback; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.security.ICryptoSubsystem; +import com.netscape.certsrv.security.KeyCertData; +import com.netscape.cmscore.cert.CertPrettyPrint; +import com.netscape.cmscore.cert.CertUtils; +import com.netscape.cmscore.util.Debug; +import com.netscape.cmsutil.crypto.CryptoUtil; +import com.netscape.cmsutil.util.Utils; + +/** + * Subsystem for initializing JSS> + *

+ * + * @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 = + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA," + + "TLS_RSA_WITH_AES_128_CBC_SHA," + + "TLS_RSA_WITH_AES_256_CBC_SHA," + + "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA," + + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA," + + // "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA," + + // "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA," + + // "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA," + + "TLS_DHE_DSS_WITH_AES_128_CBC_SHA," + + "TLS_DHE_DSS_WITH_AES_256_CBC_SHA," + + "TLS_DHE_RSA_WITH_AES_128_CBC_SHA," + + "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; + + /* list of all ciphers JSS supports */ + private static final int mJSSCipherSuites[] = { + SSLSocket.SSL2_RC4_128_WITH_MD5, + SSLSocket.SSL2_RC4_128_EXPORT40_WITH_MD5, + SSLSocket.SSL2_RC2_128_CBC_WITH_MD5, + SSLSocket.SSL2_RC2_128_CBC_EXPORT40_WITH_MD5, + SSLSocket.SSL2_DES_64_CBC_WITH_MD5, + SSLSocket.SSL2_DES_192_EDE3_CBC_WITH_MD5, + SSLSocket.SSL3_RSA_EXPORT_WITH_RC4_40_MD5, + SSLSocket.SSL3_RSA_WITH_RC4_128_MD5, + SSLSocket.SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5, + SSLSocket.SSL3_RSA_WITH_DES_CBC_SHA, + SSLSocket.SSL3_RSA_WITH_3DES_EDE_CBC_SHA, + SSLSocket.SSL3_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, + SSLSocket.SSL3_FORTEZZA_DMS_WITH_RC4_128_SHA, + SSLSocket.TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, + SSLSocket.TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, + }; + + static { + + /* set ssl cipher string names. */ + /* disallowing SSL2 ciphers to be turned on + mCipherNames.put(Constants.PR_SSL2_RC4_128_WITH_MD5, + Integer.valueOf(SSLSocket.SSL2_RC4_128_WITH_MD5)); + mCipherNames.put(Constants.PR_SSL2_RC4_128_EXPORT40_WITH_MD5, + Integer.valueOf(SSLSocket.SSL2_RC4_128_EXPORT40_WITH_MD5)); + mCipherNames.put(Constants.PR_SSL2_RC2_128_CBC_WITH_MD5, + Integer.valueOf(SSLSocket.SSL2_RC2_128_CBC_WITH_MD5)); + mCipherNames.put(Constants.PR_SSL2_RC2_128_CBC_EXPORT40_WITH_MD5, + Integer.valueOf(SSLSocket.SSL2_RC2_128_CBC_EXPORT40_WITH_MD5)); + mCipherNames.put(Constants.PR_SSL2_DES_64_CBC_WITH_MD5, + Integer.valueOf(SSLSocket.SSL2_DES_64_CBC_WITH_MD5)); + mCipherNames.put(Constants.PR_SSL2_DES_192_EDE3_CBC_WITH_MD5, + Integer.valueOf(SSLSocket.SSL2_DES_192_EDE3_CBC_WITH_MD5)); + */ + mCipherNames.put(Constants.PR_SSL3_RSA_WITH_NULL_MD5, + Integer.valueOf(SSLSocket.SSL3_RSA_WITH_NULL_MD5)); + mCipherNames.put(Constants.PR_SSL3_RSA_EXPORT_WITH_RC4_40_MD5, + Integer.valueOf(SSLSocket.SSL3_RSA_EXPORT_WITH_RC4_40_MD5)); + mCipherNames.put(Constants.PR_SSL3_RSA_WITH_RC4_128_MD5, + Integer.valueOf(SSLSocket.SSL3_RSA_WITH_RC4_128_MD5)); + mCipherNames.put(Constants.PR_SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5, + Integer.valueOf(SSLSocket.SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5)); + mCipherNames.put(Constants.PR_SSL3_RSA_WITH_DES_CBC_SHA, + Integer.valueOf(SSLSocket.SSL3_RSA_WITH_DES_CBC_SHA)); + mCipherNames.put(Constants.PR_SSL3_RSA_WITH_3DES_EDE_CBC_SHA, + Integer.valueOf(SSLSocket.SSL3_RSA_WITH_3DES_EDE_CBC_SHA)); + mCipherNames.put(Constants.PR_SSL3_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, + Integer.valueOf(SSLSocket.SSL3_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA)); + mCipherNames.put(Constants.PR_SSL3_FORTEZZA_DMS_WITH_RC4_128_SHA, + Integer.valueOf(SSLSocket.SSL3_FORTEZZA_DMS_WITH_RC4_128_SHA)); + mCipherNames.put(Constants.PR_SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, + Integer.valueOf(SSLSocket.SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA)); + mCipherNames.put(Constants.PR_SSL_RSA_FIPS_WITH_DES_CBC_SHA, + Integer.valueOf(SSLSocket.SSL_RSA_FIPS_WITH_DES_CBC_SHA)); + mCipherNames.put(Constants.PR_TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, + Integer.valueOf(SSLSocket.TLS_RSA_EXPORT1024_WITH_RC4_56_SHA)); + mCipherNames.put(Constants.PR_TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, + Integer.valueOf(SSLSocket.TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA)); + } + + public static JssSubsystem getInstance() { + return mInstance; + } + + /** + * Constructs a Security service subsystem. + */ + private JssSubsystem() { + } + + public String getId() { + return mId; + } + + public void setId(String id) throws EBaseException { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION")); + + } + + // Add entropy to the 'default' RNG token + public void addEntropy(int bits) + throws org.mozilla.jss.util.NotImplementedException, + IOException, + TokenException { + int read = 0; + int bytes = (7 + bits) / 8; + byte[] b = new byte[bytes]; + if (devRandomInputStream == null) { + throw new IOException(CMS.getLogMessage("CMSCORE_SECURITY_NO_ENTROPY_STREAM")); + } + do { + int c = devRandomInputStream.read(b, read, bytes - read); + read += c; + } while (read < bytes); + + CMS.debug("JssSubsystem adding " + bits + " bits (" + bytes + " bytes) of entropy to default RNG token"); + CMS.debug(b); + PK11SecureRandom sr = new PK11SecureRandom(); + sr.setSeed(b); + } + + /** + * Initializes the Jss security subsystem. + *

+ */ + 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. + *

+ */ + public IConfigStore getConfigStore() { + return mConfig; + } + + /** + * Starts up this service. + */ + public void startup() throws EBaseException { + } + + /** + * Shutdowns this subsystem. + *

+ */ + 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 = ""; + @SuppressWarnings("unchecked") + Enumeration tokens = mCryptoManager.getExternalTokens(); + int num = 0; + + try { + while (tokens.hasMoreElements()) { + CryptoToken c = tokens.nextElement(); + + // skip builtin object token + if (c.getName() != null && c.getName().equals("Builtin Object Token")) { + continue; + } + + if (num++ == 0) + tokenList = 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 { + @SuppressWarnings("unchecked") + Enumeration enums = mCryptoManager.getAllTokens(); + + while (enums.hasMoreElements()) { + CryptoToken token = enums.nextElement(); + CryptoStore store = token.getCryptoStore(); + X509Certificate[] list = store.getCertificates(); + + for (int i = 0; i < list.length; i++) { + String nickname = list[i].getNickname(); + + if (certNames.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 { + new X500Name(dn); // check for errors + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_X500_NAME", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_X500_NAME", dn)); + } + } + + public String getCertRequest(String subjectName, KeyPair kp) + throws EBaseException { + try { + netscape.security.pkcs.PKCS10 pkcs = + KeyCertUtil.getCertRequest(subjectName, kp); + ByteArrayOutputStream bs = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(bs); + + pkcs.print(ps); + return bs.toString(); + } catch (NoSuchAlgorithmException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_REQUEST", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED", "")); + } catch (NoSuchProviderException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_REQUEST", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_PROVIDER_NOT_SUPPORTED")); + } catch (InvalidKeyException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_REQUEST", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY")); + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_REQUEST", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_REQ_FAILED")); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_REQUEST", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_CERT", e.toString())); + } catch (SignatureException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_REQUEST", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_SIGNATURE")); + } + } + + public void importCert(String b64E, String nickname, String certType) + throws EBaseException { + try { + KeyCertUtil.importCert(b64E, nickname, certType); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_DECODE_CERT_FAILED")); + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED")); + } catch (TokenException e) { + String eString = e.toString(); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString())); + if (eString.contains("Failed to find certificate that was just imported")) { + throw new EBaseException(eString); + } else { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", "")); + } + } catch (UserCertConflictException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_USERCERT_CONFLICT")); + } catch (NicknameConflictException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_NICKNAME_CONFLICT")); + } catch (NoSuchItemOnTokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN")); + } + } + + public KeyPair getKeyPair(KeyCertData properties) throws EBaseException { + String tokenname = Constants.PR_INTERNAL_TOKEN_NAME; + String keyType = "RSA"; + int keyLength = 512; + + String tmp = (String) properties.get(Constants.PR_TOKEN_NAME); + + if ((tmp != null) && + (!tmp.equals(Constants.PR_INTERNAL_TOKEN))) + tokenname = tmp; + tmp = (String) properties.get(Constants.PR_KEY_TYPE); + if (tmp != null) + keyType = tmp; + tmp = (String) properties.get(Constants.PR_KEY_LENGTH); + if (tmp != null) + keyLength = Integer.parseInt(tmp); + + KeyPair pair = getKeyPair(tokenname, keyType, keyLength); + + return pair; + } + + public KeyPair getECCKeyPair(KeyCertData properties) throws EBaseException { + String token = Constants.PR_INTERNAL_TOKEN_NAME; + String keyCurve = "nistp512"; + String certType = null; + KeyPair pair = null; + + String tmp = (String) properties.get(Constants.PR_TOKEN_NAME); + if (tmp != null) + token = tmp; + + tmp = (String) properties.get(Constants.PR_KEY_CURVENAME); + if (tmp != null) + keyCurve = tmp; + + certType = (String) properties.get(Constants.RS_ID); + + pair = getECCKeyPair(token, keyCurve, certType); + + return pair; + } + + public KeyPair getECCKeyPair(String token, String keyCurve, String certType) throws EBaseException { + KeyPair pair = null; + + if ((token == null) || (token.equals(""))) + token = Constants.PR_INTERNAL_TOKEN_NAME; + + if ((keyCurve == null) || (keyCurve.equals(""))) + keyCurve = "nistp512"; + + String ectype = getECType(certType); + + // ECDHE needs "SIGN" but no "DERIVE" + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage usages_mask[] = { + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.DERIVE + }; + + // ECDH needs "DERIVE" but no any kind of "SIGN" + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage ECDH_usages_mask[] = { + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN, + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN_RECOVER, + }; + + try { + if (ectype.equals("ECDHE")) + pair = CryptoUtil.generateECCKeyPair(token, keyCurve, null, usages_mask); + else + pair = CryptoUtil.generateECCKeyPair(token, keyCurve, null, ECDH_usages_mask); + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ECC_KEY", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED")); + } catch (NoSuchTokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ECC_KEY", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", "")); + } catch (NoSuchAlgorithmException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ECC_KEY", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_NO_SUCH_ALGORITHM", e.toString())); + } catch (TokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ECC_KEY", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", "")); + } + + return pair; + } + + public void importCert(X509CertImpl signedCert, String nickname, + String certType) throws EBaseException { + + try { + KeyCertUtil.importCert(signedCert, nickname, certType); + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED")); + } catch (TokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", "")); + } catch (CertificateEncodingException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_ENCODE_CERT_FAILED")); + } catch (UserCertConflictException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_USERCERT_CONFLICT")); + } catch (NicknameConflictException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_NICKNAME_CONFLICT")); + } catch (NoSuchItemOnTokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN")); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_IMPORT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_ENCODE_CERT_FAILED")); + } + } + + public NameValuePairs getCertInfo(String b64E) throws EBaseException { + try { + byte[] b = KeyCertUtil.convertB64EToByteArray(b64E); + X509CertImpl impl = new X509CertImpl(b); + NameValuePairs results = new NameValuePairs(); + + results.put(Constants.PR_CERT_SUBJECT_NAME, impl.getSubjectDN().getName()); + results.put(Constants.PR_ISSUER_NAME, impl.getIssuerDN().getName()); + results.put(Constants.PR_SERIAL_NUMBER, impl.getSerialNumber().toString()); + results.put(Constants.PR_BEFORE_VALIDDATE, impl.getNotBefore().toString()); + results.put(Constants.PR_AFTER_VALIDDATE, impl.getNotAfter().toString()); + + // fingerprint is using MD5 hash + + return results; + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_INFO", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_DECODE_CERT_FAILED")); + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_CERT_INFO", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_DECODE_CERT_FAILED")); + } + } + + public void deleteUserCert(String nickname, String serialno, String issuername) + throws EBaseException { + try { + X509Certificate cert = getCertificate(nickname, serialno, issuername); + if (cert instanceof TokenCertificate) { + TokenCertificate tcert = (TokenCertificate) cert; + + CMS.debug("*** deleting this token cert"); + tcert.getOwningToken().getCryptoStore().deleteCert(tcert); + CMS.debug("*** finish deleting this token cert"); + } else { + CryptoToken token = CryptoManager.getInstance().getInternalKeyStorageToken(); + CryptoStore store = token.getCryptoStore(); + + CMS.debug("*** deleting this interna cert"); + store.deleteCert(cert); + CMS.debug("*** removing this interna cert"); + } + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED")); + } catch (TokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", "")); + } catch (NoSuchItemOnTokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN")); + } + } + + public void deleteRootCert(String nickname, String serialno, + String issuername) throws EBaseException { + int index = nickname.indexOf(":"); + String tokenname = nickname.substring(0, index); + if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) { + nickname = nickname.substring(index + 1); + } + try { + if (mNicknameMapCertsTable != null) { + X509Certificate[] certs = (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; + + CMS.debug("*** deleting this token cert"); + tcert.getOwningToken().getCryptoStore().deleteCert(tcert); + CMS.debug("*** finish deleting this token cert"); + } else { + CryptoToken token = CryptoManager.getInstance().getInternalKeyStorageToken(); + CryptoStore store = token.getCryptoStore(); + + CMS.debug("*** deleting this interna cert"); + store.deleteCert(cert); + CMS.debug("*** removing this interna cert"); + } + mNicknameMapCertsTable.remove(nickname); + break; + } + } + } + } + + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED")); + } catch (TokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", "")); + } catch (NoSuchItemOnTokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN")); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString())); + } + } + + public NameValuePairs getRootCerts() throws EBaseException { + NameValuePairs nvps = new NameValuePairs(); + try { + @SuppressWarnings("unchecked") + Enumeration 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 { + @SuppressWarnings("unused") + PrivateKey key = + CryptoManager.getInstance().findPrivKeyByCert(list[i]); // check for errors + Debug.trace("JssSubsystem getRootCerts: find private key " + + list[i].getNickname()); + } catch (ObjectNotFoundException e) { + String nickname = list[i].getNickname(); + if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME)) { + nickname = Constants.PR_INTERNAL_TOKEN_NAME + ":" + nickname; + } + X509CertImpl impl = null; + + try { + Vector v; + if (vecTable.containsKey((Object) nickname) == true) { + v = 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.put(nickname + "," + serialno, issuer); + Debug.trace("getRootCerts: nickname=" + nickname + ", serialno=" + + serialno + ", issuer=" + issuer); + continue; + } catch (CryptoManager.NotInitializedException e) { + continue; + } + } + // convert hashtable of vectors to hashtable of arrays + Enumeration elms = vecTable.keys(); + + while (elms.hasMoreElements()) { + String key = (String) elms.nextElement(); + Vector v = 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 { + @SuppressWarnings("unchecked") + 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 { + @SuppressWarnings("unused") + PrivateKey key = + CryptoManager.getInstance().findPrivKeyByCert(list[i]); // check for errors + String nickname = list[i].getNickname(); + if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME) || + tokenName.equals(Constants.PR_FULL_INTERNAL_TOKEN_NAME)) { + nickname = Constants.PR_INTERNAL_TOKEN_NAME + ":" + nickname; + } + X509CertImpl impl = null; + + try { + impl = new X509CertImpl(list[i].getEncoded()); + } catch (CertificateException e) { + // skip bad certificate + CMS.debug("bad certificate - " + nickname); + continue; + } + String serialno = impl.getSerialNumber().toString(); + String issuer = impl.getIssuerDN().toString(); + nvps.put(nickname + "," + serialno, issuer); + Debug.trace("getUserCerts: nickname=" + nickname + ", serialno=" + + serialno + ", issuer=" + issuer); + } catch (ObjectNotFoundException e) { + Debug.trace("JssSubsystem getUserCerts: cant find private key " + + list[i].getNickname()); + continue; + } catch (CryptoManager.NotInitializedException e) { + continue; + } + } + } + } catch (TokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ALL_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", "")); + } + + return nvps; + + } + + /* + * get all certificates on all tokens for Certificate Database Management + */ + public NameValuePairs getAllCertsManage() throws EBaseException { + + /* + * first get all CA certs (internal only), + * then all user certs (both internal and external) + */ + + NameValuePairs pairs = getCACerts(); + + if (mNicknameMapUserCertsTable != null) + mNicknameMapUserCertsTable.clear(); + + try { + @SuppressWarnings("unchecked") + 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(); + X509Certificate[] certificates = + CryptoManager.getInstance().findCertsByNickname(nickname); + + mNicknameMapUserCertsTable.put(nickname, certificates); + + X509CertImpl impl = null; + + try { + impl = new X509CertImpl(list[i].getEncoded()); + } catch (CertificateException e) { + // skip bad certificate + CMS.debug("bad certificate - " + nickname); + continue; + } + Date date = impl.getNotAfter(); + String dateStr = mFormatter.format(date); + String vvalue = pairs.get(nickname); + + /* always user cert here*/ + String certValue = dateStr + "," + "u"; + + if (vvalue == null) + pairs.put(nickname, certValue); + else { + if (vvalue.endsWith(",u")) { + pairs.put(nickname, vvalue + ";" + certValue); + } + } + + } + } /* while */ + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ALL_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED")); + // } catch (CertificateException e) { + // log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ALL_CERT", e.toString())); + // throw new EBaseException(BaseResources.CERT_ERROR); + } catch (TokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_ALL_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", "")); + } + + return pairs; + } + + public NameValuePairs getCACerts() throws EBaseException { + NameValuePairs pairs = new NameValuePairs(); + + //InternalCertificate[] certs; + X509Certificate[] certs; + + try { + certs = + CryptoManager.getInstance().getCACerts(); + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_CA_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED")); + } + + if (mNicknameMapCertsTable == null) { + CMS.debug("JssSubsystem::getCACerts() - " + + "mNicknameMapCertsTable is null!"); + throw new EBaseException("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 = 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 = 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); + String vvalue = pairs.get(nickname); + String certValue = dateStr + "," + trust; + + if (vvalue == null) + pairs.put(nickname, certValue); + else { + pairs.put(nickname, vvalue + ";" + certValue); + } + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_SECURITY_GET_CA_CERT_FOR", nickname, e.toString())); + // allow it to continue with other certs even if one blows + // up + // throw new EBaseException(BaseResources.CERT_ERROR); + } + } + } + return pairs; + } + + public void trustCert(String nickname, String date, String trust) throws + EBaseException { + try { + if (mNicknameMapCertsTable != null) { + X509Certificate[] certs = (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; + + 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; + + tcert.getOwningToken().getCryptoStore().deleteCert(tcert); + } else { + CryptoToken token = CryptoManager.getInstance().getInternalKeyStorageToken(); + CryptoStore store = token.getCryptoStore(); + + store.deleteCert(cert); + } + if (isUserCert == true) { + mNicknameMapUserCertsTable.remove(nickname); + } else { + mNicknameMapCertsTable.remove(nickname); + } + break; + } + } + } + + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED")); + } catch (TokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", "")); + } catch (NoSuchItemOnTokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN")); + } catch (ParseException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString())); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString())); + } + } + + public void deleteTokenCertificate(String nickname, String pathname) throws EBaseException { + try { + X509Certificate cert = CryptoManager.getInstance().findCertByNickname(nickname); + Principal principal = cert.getSubjectDN(); + DN dn = new DN(principal.getName()); + BigInteger serialno = cert.getSerialNumber(); + String suffix = "." + System.currentTimeMillis(); + String b64E = Utils.base64encode(cert.getEncoded()); + PrintStream stream = new PrintStream(new FileOutputStream(pathname + suffix)); + + stream.println("-----BEGIN CERTIFICATE-----"); + stream.print(b64E); + stream.println("-----END CERTIFICATE-----"); + stream.close(); + if (cert instanceof TokenCertificate) { + TokenCertificate tcert = (TokenCertificate) cert; + + tcert.getOwningToken().getCryptoStore().deleteCert(tcert); + } else + throw new EBaseException(CMS.getUserMessage("CMS_BASE_NOT_TOKEN_CERT")); + + int index = nickname.indexOf(":"); + + // the deleted certificate is on the hardware token. We should delete the same one from + // the internal token. + if (index > 0) { + CryptoToken cToken = CryptoManager.getInstance().getInternalKeyStorageToken(); + CryptoStore store = cToken.getCryptoStore(); + X509Certificate[] allcerts = CryptoManager.getInstance().getCACerts(); + + for (int i = 0; i < allcerts.length; i++) { + try { + X509CertImpl certImpl = new X509CertImpl(allcerts[i].getEncoded()); + Principal certPrincipal = certImpl.getSubjectDN(); + DN certdn = new DN(certPrincipal.getName()); + BigInteger certSerialNo = certImpl.getSerialNumber(); + + if (dn.equals(certdn) && certSerialNo.compareTo(serialno) == 0) { + store.deleteCert(allcerts[i]); + break; + } + } catch (Exception ee) { + Debug.trace("JssSubsystem:deleteTokenCertificate: " + ee.toString()); + } + } + } + } catch (TokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", "")); + } catch (NoSuchItemOnTokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN")); + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED")); + } catch (ObjectNotFoundException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_ITEM_NOT_FOUND_ON_TOKEN")); + } catch (CertificateEncodingException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString())); + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_DELETE_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString())); + } + } + + public String getSubjectDN(String nickname) throws EBaseException { + try { + X509Certificate cert = + CryptoManager.getInstance().findCertByNickname(nickname); + X509CertImpl impl = new X509CertImpl(cert.getEncoded()); + + return impl.getSubjectDN().getName(); + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_SUBJECT_NAME", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED")); + } catch (TokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_SUBJECT_NAME", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", "")); + } catch (ObjectNotFoundException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_SUBJECT_NAME", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND")); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_SUBJECT_NAME", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString())); + } + } + + public void setRootCertTrust(String nickname, String serialno, + String issuerName, String trust) throws EBaseException { + + X509Certificate cert = getCertificate(nickname, serialno, issuerName); + if (cert instanceof InternalCertificate) { + if (trust.equals("trust")) { + int trustflag = InternalCertificate.TRUSTED_CA | + InternalCertificate.TRUSTED_CLIENT_CA | + InternalCertificate.VALID_CA; + + ((InternalCertificate) cert).setSSLTrust(trustflag); + } else { + ((InternalCertificate) cert).setSSLTrust(InternalCertificate.VALID_CA); + } + } + } + + public X509Certificate getCertificate(String nickname, String serialno, + String issuerName) throws EBaseException { + + int index = nickname.indexOf(":"); + String tokenname = nickname.substring(0, index); + if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) { + nickname = nickname.substring(index + 1); + } + try { + X509Certificate[] certs = + CryptoManager.getInstance().findCertsByNickname(nickname); + + X509CertImpl impl = null; + int i = 0; + if (certs != null && certs.length > 0) { + for (; i < certs.length; i++) { + impl = new X509CertImpl(certs[i].getEncoded()); + if (impl.getIssuerDN().toString().equals(issuerName) && + impl.getSerialNumber().toString().equals(serialno)) + return certs[i]; + } + } else { + EBaseException e = + new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND")); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw e; + } + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED")); + } catch (TokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", "")); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString())); + } + + return null; + } + + public String getRootCertTrustBit(String nickname, String serialno, + String issuerName) throws EBaseException { + int index = nickname.indexOf(":"); + String tokenname = nickname.substring(0, index); + if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) { + nickname = nickname.substring(index + 1); + } + try { + X509Certificate[] certs = + CryptoManager.getInstance().findCertsByNickname(nickname); + + X509CertImpl impl = null; + int i = 0; + if (certs != null && certs.length > 0) { + for (; i < certs.length; i++) { + impl = new X509CertImpl(certs[i].getEncoded()); + if (impl.getIssuerDN().toString().equals(issuerName) && + impl.getSerialNumber().toString().equals(serialno)) + break; + } + } else { + EBaseException e = + new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND")); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw e; + } + + String trust = "U"; + if (certs[i] instanceof InternalCertificate) { + InternalCertificate icert = (InternalCertificate) certs[i]; + int flag = icert.getSSLTrust(); + if ((InternalCertificate.TRUSTED_CLIENT_CA & flag) == InternalCertificate.TRUSTED_CLIENT_CA) + trust = "T"; + } else + trust = "N/A"; + return trust; + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED")); + } catch (TokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", "")); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString())); + } + } + + public String getCertPrettyPrint(String nickname, String serialno, + String issuerName, Locale locale) throws EBaseException { + int index = nickname.indexOf(":"); + String tokenname = nickname.substring(0, index); + if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) { + nickname = nickname.substring(index + 1); + } + try { + X509Certificate[] certs = + CryptoManager.getInstance().findCertsByNickname(nickname); + + X509CertImpl impl = null; + if (certs != null && certs.length > 0) { + for (int i = 0; i < certs.length; i++) { + impl = new X509CertImpl(certs[i].getEncoded()); + if (impl.getIssuerDN().toString().equals(issuerName) && + impl.getSerialNumber().toString().equals(serialno)) + break; + } + } else { + EBaseException e = + new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND")); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw e; + } + CertPrettyPrint print = null; + + if (impl != null) + print = new CertPrettyPrint(impl); + + if (print != null) + return print.toString(locale); + else + return null; + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED")); + } catch (TokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", "")); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString())); + } + } + + public String getCertPrettyPrintAndFingerPrint(String nickname, String serialno, + String issuerName, Locale locale) throws EBaseException { + int index = nickname.indexOf(":"); + String tokenname = nickname.substring(0, index); + if (tokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) { + nickname = nickname.substring(index + 1); + } + try { + X509Certificate[] certs = + CryptoManager.getInstance().findCertsByNickname(nickname); + + X509CertImpl impl = null; + if (certs != null && certs.length > 0) { + for (int i = 0; i < certs.length; i++) { + impl = new X509CertImpl(certs[i].getEncoded()); + if (impl.getIssuerDN().toString().equals(issuerName) && + impl.getSerialNumber().toString().equals(serialno)) + break; + } + } else { + EBaseException e = + new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_NOT_FOUND")); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw e; + } + CertPrettyPrint print = null; + String fingerPrint = ""; + + if (impl != null) { + print = new CertPrettyPrint(impl); + fingerPrint = CMS.getFingerPrints(impl.getEncoded()); + } + + if ((print != null) && (fingerPrint != "")) { + String pp = print.toString(locale) + "\n" + + "Certificate Fingerprints:" + '\n' + fingerPrint; + return pp; + } else + return null; + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CRYPTOMANAGER_UNINITIALIZED")); + } catch (TokenException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND", "")); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString())); + } catch (NoSuchAlgorithmException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_PRINT_CERT", e.toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_NO_SUCH_ALGORITHM", e.toString())); + } + } + + public String getCertPrettyPrint(String nickname, String date, + Locale locale) throws EBaseException { + try { + X509Certificate[] certs = + CryptoManager.getInstance().findCertsByNickname(nickname); + + if ((certs == null || certs.length == 0) && + mNicknameMapCertsTable != null) { + certs = (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[] = Utils.base64decode(normalized); + + ContentInfo ci = (ContentInfo) + ASN1Util.decode(ContentInfo.getTemplate(), data); + + if (!ci.getContentType().equals(ContentInfo.SIGNED_DATA)) { + throw new CertificateException( + "PKCS #7 structure is not a SignedData"); + } + SignedData sd = (SignedData) ci.getInterpretedContent(); + + if (!sd.hasCertificates()) { + throw new CertificateException( + "No certificates in PKCS #7 structure"); + } + SET certs = sd.getCertificates(); + + for (int i = 0; i < certs.size(); i++) { + Certificate cert = (Certificate) certs.elementAt(i); + X509CertImpl certImpl = new X509CertImpl( + ASN1Util.encode(cert)); + CertPrettyPrint print = new CertPrettyPrint(certImpl); + + content += 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/base/common/src/com/netscape/cmscore/security/KRATransportCert.java b/base/common/src/com/netscape/cmscore/security/KRATransportCert.java new file mode 100644 index 000000000..79988e7d6 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/security/KRATransportCert.java @@ -0,0 +1,107 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.security; + +import java.io.IOException; +import java.security.KeyPair; + +import netscape.security.x509.KeyUsageExtension; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.common.ConfigConstants; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.security.KeyCertData; + +/** + * 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/base/common/src/com/netscape/cmscore/security/KeyCertUtil.java b/base/common/src/com/netscape/cmscore/security/KeyCertUtil.java new file mode 100644 index 000000000..2a9afb868 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/security/KeyCertUtil.java @@ -0,0 +1,1139 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.security; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.math.BigInteger; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.InvalidParameterException; +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SignatureException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.interfaces.DSAParams; +import java.security.interfaces.DSAPublicKey; +import java.security.interfaces.RSAPublicKey; +import java.util.Enumeration; +import java.util.Vector; + +import netscape.ldap.LDAPAttribute; +import netscape.ldap.LDAPAttributeSet; +import netscape.ldap.LDAPConnection; +import netscape.ldap.LDAPEntry; +import netscape.ldap.LDAPException; +import netscape.ldap.LDAPModification; +import netscape.security.extensions.AuthInfoAccessExtension; +import netscape.security.extensions.ExtendedKeyUsageExtension; +import netscape.security.extensions.NSCertTypeExtension; +import netscape.security.extensions.OCSPNoCheckExtension; +import netscape.security.pkcs.PKCS10; +import netscape.security.pkcs.PKCS10Attribute; +import netscape.security.pkcs.PKCS10Attributes; +import netscape.security.pkcs.PKCS9Attribute; +import netscape.security.util.BigInt; +import netscape.security.util.DerOutputStream; +import netscape.security.util.DerValue; +import netscape.security.util.ObjectIdentifier; +import netscape.security.x509.AlgIdDSA; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.AuthorityKeyIdentifierExtension; +import netscape.security.x509.BasicConstraintsExtension; +import netscape.security.x509.CertAttrSet; +import netscape.security.x509.CertificateAlgorithmId; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.Extension; +import netscape.security.x509.Extensions; +import netscape.security.x509.GeneralName; +import netscape.security.x509.KeyIdentifier; +import netscape.security.x509.KeyUsageExtension; +import netscape.security.x509.SubjectKeyIdentifierExtension; +import netscape.security.x509.URIName; +import netscape.security.x509.X500Name; +import netscape.security.x509.X500Signer; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.CryptoManager.NicknameConflictException; +import org.mozilla.jss.CryptoManager.NotInitializedException; +import org.mozilla.jss.CryptoManager.UserCertConflictException; +import org.mozilla.jss.NoSuchTokenException; +import org.mozilla.jss.asn1.ANY; +import org.mozilla.jss.asn1.ASN1Header; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.asn1.BIT_STRING; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.InternalCertificate; +import org.mozilla.jss.crypto.KeyPairAlgorithm; +import org.mozilla.jss.crypto.KeyPairGenerator; +import org.mozilla.jss.crypto.NoSuchItemOnTokenException; +import org.mozilla.jss.crypto.ObjectNotFoundException; +import org.mozilla.jss.crypto.PQGParamGenException; +import org.mozilla.jss.crypto.PQGParams; +import org.mozilla.jss.crypto.Signature; +import org.mozilla.jss.crypto.SignatureAlgorithm; +import org.mozilla.jss.crypto.TokenException; +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.pkcs11.PK11ECPublicKey; +import org.mozilla.jss.util.Base64OutputStream; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.security.KeyCertData; +import com.netscape.cmscore.cert.CertUtils; +import com.netscape.cmscore.dbs.BigIntegerMapper; +import com.netscape.cmscore.dbs.DateMapper; +import com.netscape.cmscore.dbs.X509CertImplMapper; +import com.netscape.cmsutil.crypto.CryptoUtil; +import com.netscape.cmsutil.util.Utils; + +/** + * This class provides all the base methods to generate the key for different + * kinds of certificates. + * + * @author Christine Ho + * @version $Revision$, $Date$ + */ +public class KeyCertUtil { + + public static final String CA_SIGNINGCERT_NICKNAME = "caSigningCert"; + 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 = Utils.base64decode(ext); + // this b can be "Extension" Or "SEQUENCE OF Extension" + DerValue b_der = new DerValue(b); + + while (b_der.data.available() != 0) { + new Extension(b_der.data.getDerValue()); // check for errors + } + } catch (IOException e) { + try { + new Extension(new DerValue(b)); // check for errors + } catch (IOException ex) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_CERT_EXTENSION")); + } + } + } + } + + public static String getTokenNames(CryptoManager manager) + throws TokenException { + String tokenList = ""; + @SuppressWarnings("unchecked") + 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); + 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[] = Utils.base64decode(str); + + /* + java.security.cert.X509Certificate cert = + java.security.cert.X509Certificate.getInstance(bCert); + return cert; + */ + return bCert; + } + + /** + * ASN.1 structure: + * 0 30 142: SEQUENCE { + * 3 30 69: SEQUENCE { + * 5 06 3: OBJECT IDENTIFIER issuerAltName (2 5 29 18) + * 10 04 62: OCTET STRING + * : 30 3C 82 01 61 82 01 61 A4 10 30 0E 31 0C 30 0A + * : 06 03 55 04 03 13 03 64 73 61 87 04 01 01 01 01 + * : 86 01 61 81 14 74 68 6F 6D 61 73 6B 40 6E 65 74 + * : 73 63 61 70 65 2E 63 6F 6D 88 03 29 01 01 + * : } + * 74 30 69: SEQUENCE { + * 76 06 3: OBJECT IDENTIFIER subjectAltName (2 5 29 17) + * 81 04 62: OCTET STRING + * : 30 3C 82 01 61 82 01 61 A4 10 30 0E 31 0C 30 0A + * : 06 03 55 04 03 13 03 64 73 61 87 04 01 01 01 01 + * : 86 01 61 81 14 74 68 6F 6D 61 73 6B 40 6E 65 74 + * : 73 63 61 70 65 2E 63 6F 6D 88 03 29 01 01 + * : } + * : } + * Uses the following to test with configuration wizard: + * MIGOMEUGA1UdEQQ+MDyCAWGCAWGkEDAOMQwwCgYDVQQDEwNkc2GHBAEBAQGGAWGB + * FHRob21hc2tAbmV0c2NhcGUuY29tiAMpAQEwRQYDVR0SBD4wPIIBYYIBYaQQMA4x + * DDAKBgNVBAMTA2RzYYcEAQEBAYYBYYEUdGhvbWFza0BuZXRzY2FwZS5jb22IAykB + * AQ== + */ + public static void setDERExtension( + CertificateExtensions ext, KeyCertData properties) + throws IOException { + + String b64E = properties.getDerExtension(); + + if (b64E != null) { + byte[] b = Utils.base64decode(b64E); + + // this b can be "Extension" Or "SEQUENCE OF Extension" + try { + DerValue b_der = new DerValue(b); + + while (b_der.data.available() != 0) { + Extension de = new Extension(b_der.data.getDerValue()); + + ext.set(de.getExtensionId().toString(), de); + } + } catch (IOException e) { + Extension de = new Extension(new DerValue(b)); + + ext.set(de.getExtensionId().toString(), de); + } + } + } + + public static void setBasicConstraintsExtension( + CertificateExtensions ext, KeyCertData properties) + throws IOException { + String isCA = properties.isCA(); + String certLen = properties.getCertLen(); + + if (isCA == null) + return; // isCA is not optional + if (isCA.equals("null")) + return; // no BasicConstraints requested + int len = 0; + boolean bool = false; + + if ((certLen == null) || (certLen.equals(""))) + len = 0; + else + len = Integer.parseInt(certLen); + + if ((isCA == null) || (isCA.equals("")) || + (isCA.equals(Constants.FALSE))) + bool = false; + else + bool = true; + + BasicConstraintsExtension basic = new BasicConstraintsExtension( + bool, len); + + ext.set(BasicConstraintsExtension.NAME, basic); + } + + public static void setExtendedKeyUsageExtension( + CertificateExtensions ext, KeyCertData properties) throws IOException, + CertificateException { + ExtendedKeyUsageExtension ns = new ExtendedKeyUsageExtension(); + boolean anyExt = false; + + String sslClient = properties.getSSLClientBit(); + + if ((sslClient != null) && (sslClient.equals(Constants.TRUE))) { + ns.addOID(new ObjectIdentifier("1.3.6.1.5.5.7.3.2")); + anyExt = true; + } + + String sslServer = properties.getSSLServerBit(); + + if ((sslServer != null) && (sslServer.equals(Constants.TRUE))) { + ns.addOID(new ObjectIdentifier("1.3.6.1.5.5.7.3.1")); + anyExt = true; + } + + String sslMail = properties.getSSLMailBit(); + + if ((sslMail != null) && (sslMail.equals(Constants.TRUE))) { + ns.addOID(new ObjectIdentifier("1.3.6.1.5.5.7.3.4")); + anyExt = true; + } + + String objectSigning = properties.getObjectSigningBit(); + + if ((objectSigning != null) && (objectSigning.equals(Constants.TRUE))) { + ns.addOID(new ObjectIdentifier("1.3.6.1.5.5.7.3.3")); + anyExt = true; + } + + String timestamping = properties.getTimeStampingBit(); + if ((timestamping != null) && (timestamping.equals(Constants.TRUE))) { + ns.addOID(new ObjectIdentifier("1.3.6.1.5.5.7.3.8")); + anyExt = true; + } + + String ocspSigning = properties.getOCSPSigning(); + + if ((ocspSigning != null) && (ocspSigning.equals(Constants.TRUE))) { + ns.addOID(new ObjectIdentifier("1.3.6.1.5.5.7.3.9")); + anyExt = true; + } + + if (anyExt) + ext.set(ExtendedKeyUsageExtension.NAME, ns); + } + + public static void setNetscapeCertificateExtension( + CertificateExtensions ext, KeyCertData properties) throws IOException, + CertificateException { + + NSCertTypeExtension ns = new NSCertTypeExtension(); + boolean anyExt = false; + + String sslClient = properties.getSSLClientBit(); + + if ((sslClient != null) && (sslClient.equals(Constants.TRUE))) { + ns.set(NSCertTypeExtension.SSL_CLIENT, 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/base/common/src/com/netscape/cmscore/security/OCSPSigningCert.java b/base/common/src/com/netscape/cmscore/security/OCSPSigningCert.java new file mode 100644 index 000000000..762db5e90 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/security/OCSPSigningCert.java @@ -0,0 +1,140 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.security; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.KeyPair; + +import netscape.security.x509.KeyUsageExtension; + +import org.mozilla.jss.crypto.PQGParamGenException; +import org.mozilla.jss.crypto.PQGParams; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.common.ConfigConstants; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.security.KeyCertData; + +/** + * OCSP signing certificate. + * + * @author Christine Ho + * @version $Revision$, $Date$ + */ +public class OCSPSigningCert extends CertificateInfo { + public static final String SUBJECT_NAME = + "CN=Certificate Authority, O=Netscape Communications, C=US"; + + public OCSPSigningCert(KeyCertData properties) { + this(properties, null); + } + + public OCSPSigningCert(KeyCertData properties, KeyPair pair) { + super(properties, pair); + /* included in console UI + try { + if (mProperties.get(Constants.PR_OCSP_SIGNING) == null) { + mProperties.put(Constants.PR_OCSP_SIGNING, Constants.TRUE); + } + if (mProperties.get(Constants.PR_OCSP_NOCHECK) == null) { + mProperties.put(Constants.PR_OCSP_NOCHECK, Constants.TRUE); + } + } catch (Exception e) { + mProperties.put(Constants.PR_OCSP_SIGNING, Constants.TRUE); + mProperties.put(Constants.PR_OCSP_NOCHECK, Constants.TRUE); + } + */ + } + + public String getSubjectName() { + return (String) mProperties.get(Constants.PR_SUBJECT_NAME); + } + + // get PQG params from the configuration file + public 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/base/common/src/com/netscape/cmscore/security/PWCBsdr.java b/base/common/src/com/netscape/cmscore/security/PWCBsdr.java new file mode 100644 index 000000000..32a0e90ed --- /dev/null +++ b/base/common/src/com/netscape/cmscore/security/PWCBsdr.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.security; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; + +import org.mozilla.jss.util.Password; +import org.mozilla.jss.util.PasswordCallback; +import org.mozilla.jss.util.PasswordCallbackInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cmscore.base.JDialogPasswordCallback; + +/* + * A class to retrieve passwords from the SDR password cache + * + * @author Christina Fu + * @version $Revision$, $Date$ + */ + +public class PWCBsdr implements PasswordCallback { + 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"); + return pw; + } else { /* password not found */ + // we don't want caller to do getPasswordAgain, for now + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_THROW_CALLBACK")); + throw new PasswordCallback.GiveUpException(); + } + } + } catch (Throwable e) { + // System.out.println( "BUG HERE!!!!first!!!!!!!!!!!!!!!!!" ); + // e.printStackTrace(); + throw new PasswordCallback.GiveUpException(); + } + } + + /* The password cache has failed to return a password (or a usable password. + * Now we will try and get the password from the user and hopefully add + * the password to the cache pw cache + */ + public Password getPasswordAgain(PasswordCallbackInfo info) + throws PasswordCallback.GiveUpException { + + CMS.debug("in getPasswordAgain"); + try { + Password pw = null; + + try { + if (firsttime) { + try { + firsttime = false; + + pw = mCB.getPasswordFirstAttempt(info); + } catch (PasswordCallback.GiveUpException e) { + throw new PasswordCallback.GiveUpException(); + } + } else { + pw = mCB.getPasswordAgain(info); + } + return (pw); + } catch (PasswordCallback.GiveUpException e) { + throw new PasswordCallback.GiveUpException(); + } + } catch (Throwable e) { + // System.out.println( "BUG HERE!! in the password again!!" + // + "!!!!!!!!!!!" ); + // e.printStackTrace(); + throw new PasswordCallback.GiveUpException(); + } + } + + public void log(int level, String msg) { + if (mLogger == null) { + System.out.println(msg); + } else { + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, level, "PWCBsdr " + msg); + } + } +} + +class PWsdrConsolePasswordCallback implements PasswordCallback { + private String mPrompt = null; + + public PWsdrConsolePasswordCallback(String p) { + mPrompt = p; + } + + public String getPrompt() { + return mPrompt; + } + + public Password getPasswordFirstAttempt(PasswordCallbackInfo info) + throws PasswordCallback.GiveUpException { + if (mPrompt == null) { + System.out.println("Get password " + info.getName()); + } else { + System.out.println(getPrompt()); + } + + Password tmppw = PWUtil.readPasswordFromStream(); + + return (tmppw); + } + + public Password getPasswordAgain(PasswordCallbackInfo info) + throws PasswordCallback.GiveUpException { + System.out.println("Password Incorrect."); + if (mPrompt == null) { + System.out.println("Get password " + info.getName()); + } else { + System.out.println(getPrompt()); + } + + Password tmppw = PWUtil.readPasswordFromStream(); + + return (tmppw); + } +} + +class PWsdrDialogPasswordCallback extends JDialogPasswordCallback { + private String mPrompt = null; + + public PWsdrDialogPasswordCallback(String p) { + super(); + mPrompt = p; + } + + public String getPrompt(PasswordCallbackInfo info) { + if (mPrompt == null) { + return super.getPrompt(info); + } else { + return mPrompt; + } + } +} diff --git a/base/common/src/com/netscape/cmscore/security/PWUtil.java b/base/common/src/com/netscape/cmscore/security/PWUtil.java new file mode 100644 index 000000000..3938bf5d2 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/security/PWUtil.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.security; + +import org.mozilla.jss.util.Password; +import org.mozilla.jss.util.PasswordCallback; + +public class PWUtil { + public static Password + readPasswordFromStream() + throws PasswordCallback.GiveUpException { + + StringBuffer buf = new StringBuffer(); + String passwordString = 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/base/common/src/com/netscape/cmscore/security/PWsdrCache.java b/base/common/src/com/netscape/cmscore/security/PWsdrCache.java new file mode 100644 index 000000000..6c834d0e0 --- /dev/null +++ b/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 java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.StringTokenizer; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.CryptoManager.NotInitializedException; +import org.mozilla.jss.SecretDecoderRing.Decryptor; +import org.mozilla.jss.SecretDecoderRing.Encryptor; +import org.mozilla.jss.SecretDecoderRing.KeyManager; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.TokenException; +import org.mozilla.jss.util.Base64OutputStream; +import org.mozilla.jss.util.Password; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cmsutil.util.Utils; + +/* + * A class for managing passwords in the SDR password cache + * + * @author Christina Fu + * @version $Revision$, $Date$ + */ +public class PWsdrCache { + public static final String PROP_PWC_TOKEN_NAME = "pwcTokenname"; + public static final String PROP_PWC_KEY_ID = "pwcKeyid"; + public static final String PROP_PWC_NICKNAME = "sso_key"; + + private ILogger mLogger = null; + private String mPWcachedb = null; + // mTool tells if this is called from the PasswordCache tool + private boolean mIsTool = false; + private byte[] mKeyID = null; + private String mTokenName = null; + private CryptoToken mToken = null; + + // for CMSEngine + public PWsdrCache() throws EBaseException { + mLogger = CMS.getLogger(); + try { + mPWcachedb = CMS.getConfigStore().getString("pwCache"); + CMS.debug("got pwCache file path from configstore"); + } catch (Exception e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_GET_CONFIG")); + // let it fall through + } + initToken(); + initKey(); + } + + private void initToken() throws EBaseException { + if (mToken == null) { + CryptoManager cm = null; + try { + cm = CryptoManager.getInstance(); + mTokenName = CMS.getConfigStore().getString(PROP_PWC_TOKEN_NAME); + log(ILogger.LL_DEBUG, "pwcTokenname specified. Use token for SDR key. tokenname= " + mTokenName); + mToken = cm.getTokenByName(mTokenName); + } catch (NotInitializedException e) { + log(ILogger.LL_FAILURE, e.toString()); + throw new EBaseException(e.toString()); + } catch (Exception e) { + log(ILogger.LL_DEBUG, "no pwcTokenname specified, use internal token for SDR key"); + mToken = cm.getInternalKeyStorageToken(); + } + } + } + + // called from PWCBsdr or CMSEngine only + private void initKey() throws EBaseException { + if (mKeyID == null) { + try { + String keyID = CMS.getConfigStore().getString(PROP_PWC_KEY_ID); + log(ILogger.LL_DEBUG, "retrieved PWC SDR key"); + mKeyID = base64Decode(keyID); + + } catch (Exception e) { + log(ILogger.LL_DEBUG, "no pwcSDRKey specified"); + throw new EBaseException(e.toString()); + } + } + } + + // for PasswordCache tool (isTool == true) + // and installation wizard (isTool == false) + // Do not use for PWCBsdr, since we don't want to mistakenly + // generate SDR keys in case of configuration errors + public PWsdrCache(String pwCache, String pwcTokenname, byte[] keyId, + boolean isTool) throws Exception { + mPWcachedb = pwCache; + mIsTool = isTool; + mTokenName = pwcTokenname; + CryptoManager cm = null; + + if (keyId != null) { + mKeyID = keyId; + } + + cm = CryptoManager.getInstance(); + if (mTokenName != null) { + mToken = cm.getTokenByName(mTokenName); + 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 = Utils.base64decode(s); + return d; + } + + public static String base64Encode(byte[] bytes) throws IOException { + // All this streaming is lame, but Base64OutputStream needs a + // PrintStream + ByteArrayOutputStream output = new ByteArrayOutputStream(); + 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 = enum1.nextElement(); + pwd = 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 = enum1.nextElement(); + String pwd = 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(); + + 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 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/base/common/src/com/netscape/cmscore/security/Provider.java b/base/common/src/com/netscape/cmscore/security/Provider.java new file mode 100644 index 000000000..540fe2201 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/security/Provider.java @@ -0,0 +1,57 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.security; + +public class Provider extends java.security.Provider { + + /** + * + */ + private static final long serialVersionUID = -8050884788034389693L; + + public Provider() { + super("CMS", 1.4, + "Provides Signature and Message Digesting"); + + ///////////////////////////////////////////////////////////// + // Signature + ///////////////////////////////////////////////////////////// + + put("Signature.SHA1withDSA", "org.mozilla.jss.provider.DSASignature"); + + put("Alg.Alias.Signature.DSA", "SHA1withDSA"); + put("Alg.Alias.Signature.DSS", "SHA1withDSA"); + put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA"); + put("Alg.Alias.Signature.SHA-1/DSA", "SHA1withDSA"); + put("Alg.Alias.Signature.SHA1/DSA", "SHA1withDSA"); + put("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA"); + put("Alg.Alias.Signature.SHAwithDSA", "SHA1withDSA"); + + put("Signature.MD5/RSA", "org.mozilla.jss.provider.MD5RSASignature"); + put("Signature.MD2/RSA", "org.mozilla.jss.provider.MD2RSASignature"); + put("Signature.SHA-1/RSA", + "org.mozilla.jss.provider.SHA1RSASignature"); + + put("Alg.Alias.Signature.SHA1/RSA", "SHA-1/RSA"); + + ///////////////////////////////////////////////////////////// + // Message Digesting + ///////////////////////////////////////////////////////////// + + } +} diff --git a/base/common/src/com/netscape/cmscore/security/RASigningCert.java b/base/common/src/com/netscape/cmscore/security/RASigningCert.java new file mode 100644 index 000000000..581fc8866 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/security/RASigningCert.java @@ -0,0 +1,113 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.security; + +import java.io.IOException; +import java.security.KeyPair; + +import netscape.security.x509.KeyUsageExtension; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.common.ConfigConstants; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.security.KeyCertData; + +/** + * 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/base/common/src/com/netscape/cmscore/security/SSLCert.java b/base/common/src/com/netscape/cmscore/security/SSLCert.java new file mode 100644 index 000000000..b54f24dc7 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/security/SSLCert.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 java.io.IOException; +import java.security.KeyPair; + +import netscape.security.x509.KeyUsageExtension; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.common.ConfigConstants; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.security.KeyCertData; + +/** + * SSL server certificate + * + * @author Christine Ho + * @version $Revision$, $Date$ + */ +public class SSLCert extends CertificateInfo { + public static final String SUBJECT_NAME = + "CN=SSL, O=Netscape Communications, C=US"; + 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/base/common/src/com/netscape/cmscore/security/SSLSelfSignedCert.java b/base/common/src/com/netscape/cmscore/security/SSLSelfSignedCert.java new file mode 100644 index 000000000..1d70e7a1d --- /dev/null +++ b/base/common/src/com/netscape/cmscore/security/SSLSelfSignedCert.java @@ -0,0 +1,119 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.security; + +import java.io.IOException; +import java.security.KeyPair; + +import netscape.security.x509.KeyUsageExtension; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.common.ConfigConstants; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.security.KeyCertData; + +/** + * SSL server certificate + * + * @author Christine Ho + * @version $Revision$, $Date$ + */ +public class 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/base/common/src/com/netscape/cmscore/security/SubsystemCert.java b/base/common/src/com/netscape/cmscore/security/SubsystemCert.java new file mode 100644 index 000000000..aede5e4d9 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/security/SubsystemCert.java @@ -0,0 +1,81 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.security; + +import java.io.IOException; +import java.security.KeyPair; + +import netscape.security.x509.KeyUsageExtension; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.common.ConfigConstants; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.security.KeyCertData; + +/** + * Subsystem certificate. + * + * @author Christine Ho + * @version $Revision$, $Date$ + */ +public class SubsystemCert extends CertificateInfo { + + public SubsystemCert(KeyCertData properties) { + this(properties, null); + } + + public SubsystemCert(KeyCertData properties, KeyPair pair) { + super(properties, pair); + try { + if (mProperties.get(Constants.PR_SSL_CLIENT_BIT) == null) + mProperties.put(Constants.PR_SSL_CLIENT_BIT, Constants.TRUE); + } catch (Exception e) { + mProperties.put(Constants.PR_SSL_CLIENT_BIT, Constants.TRUE); + } + } + + public String getSubjectName() { + return (String) mProperties.get(Constants.PR_SUBJECT_NAME); + } + + public void updateConfig(IConfigStore cmsFileTmp) throws EBaseException { + } + + public String getNickname() { + String name = (String) mProperties.get(Constants.PR_NICKNAME); + String instanceName = (String) mProperties.get(ConfigConstants.PR_CERT_INSTANCE_NAME); + + if (name != null) + return name; + return "subsystemCert " + instanceName; + } + + public String getKeyAlgorithm() { + return (String) mProperties.get(Constants.PR_KEY_TYPE); + } + + protected KeyUsageExtension getKeyUsageExtension() throws IOException { + KeyUsageExtension extension = new KeyUsageExtension(); + + extension.set(KeyUsageExtension.DIGITAL_SIGNATURE, new Boolean(true)); + extension.set(KeyUsageExtension.NON_REPUDIATION, new Boolean(true)); + extension.set(KeyUsageExtension.KEY_ENCIPHERMENT, new Boolean(true)); + return extension; + } +} -- cgit