]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - org.argeo.cms/src/org/argeo/cms/internal/runtime/PkiUtils.java
Improve SSH server. Rename node directory to private.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / runtime / PkiUtils.java
index 474a8995061040ca824a0b54fd8d373af54403db..f47e544218456968cfeb7982031c9649589a3849 100644 (file)
@@ -5,12 +5,14 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Reader;
 import java.math.BigInteger;
+import java.net.InetAddress;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.security.GeneralSecurityException;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.KeyStore;
+import java.security.KeyStore.TrustedCertificateEntry;
 import java.security.KeyStoreException;
 import java.security.PrivateKey;
 import java.security.SecureRandom;
@@ -18,10 +20,14 @@ import java.security.Security;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
+import java.util.Arrays;
 import java.util.Date;
+import java.util.Objects;
 
 import javax.security.auth.x500.X500Principal;
 
+import org.argeo.api.cms.CmsConstants;
+import org.argeo.api.cms.CmsLog;
 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
 import org.bouncycastle.cert.X509CertificateHolder;
 import org.bouncycastle.cert.X509v3CertificateBuilder;
@@ -43,18 +49,39 @@ import org.bouncycastle.pkcs.PKCSException;
  * implementations.
  */
 class PkiUtils {
+       private final static CmsLog log = CmsLog.getLog(PkiUtils.class);
+
        final static String PKCS12 = "PKCS12";
+       final static String JKS = "JKS";
+
+       static final String DEFAULT_KEYSTORE_PATH = KernelConstants.DIR_PRIVATE + '/' + CmsConstants.NODE + ".p12";
+
+       static final String DEFAULT_TRUSTSTORE_PATH = KernelConstants.DIR_PRIVATE + "/trusted.p12";
+
+       static final String DEFAULT_PEM_KEY_PATH = KernelConstants.DIR_PRIVATE + '/' + CmsConstants.NODE + ".key";
+
+       static final String DEFAULT_PEM_CERT_PATH = KernelConstants.DIR_PRIVATE + '/' + CmsConstants.NODE + ".crt";
 
-       private final static String SECURITY_PROVIDER;
+       static final String IPA_PEM_CA_CERT_PATH = "/etc/ipa/ca.crt";
+
+       static final String DEFAULT_KEYSTORE_PASSWORD = "changeit";
+
+       private final static String SUN_SECURITY_PROVIDER;
+       private final static String SUN_JSSE_SECURITY_PROVIDER;
+       private final static String BC_SECURITY_PROVIDER;
        static {
                Security.addProvider(new BouncyCastleProvider());
-               SECURITY_PROVIDER = "BC";
+               // BouncyCastle does not store trusted certificates properly
+               // TODO report it
+               BC_SECURITY_PROVIDER = "BC";
+               SUN_SECURITY_PROVIDER = "SUN";
+               SUN_JSSE_SECURITY_PROVIDER = "SunJSSE";
        }
 
        public static X509Certificate generateSelfSignedCertificate(KeyStore keyStore, X500Principal x500Principal,
                        int keySize, char[] keyPassword) {
                try {
-                       KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", SECURITY_PROVIDER);
+                       KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", BC_SECURITY_PROVIDER);
                        kpGen.initialize(keySize, new SecureRandom());
                        KeyPair pair = kpGen.generateKeyPair();
                        Date notBefore = new Date(System.currentTimeMillis() - 10000);
@@ -62,9 +89,9 @@ class PkiUtils {
                        BigInteger serial = BigInteger.valueOf(System.currentTimeMillis());
                        X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(x500Principal, serial, notBefore,
                                        notAfter, x500Principal, pair.getPublic());
-                       ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider(SECURITY_PROVIDER)
-                                       .build(pair.getPrivate());
-                       X509Certificate cert = new JcaX509CertificateConverter().setProvider(SECURITY_PROVIDER)
+                       ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption")
+                                       .setProvider(BC_SECURITY_PROVIDER).build(pair.getPrivate());
+                       X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC_SECURITY_PROVIDER)
                                        .getCertificate(certGen.build(sigGen));
                        cert.checkValidity(new Date());
                        cert.verify(cert.getPublicKey());
@@ -78,7 +105,7 @@ class PkiUtils {
 
        public static KeyStore getKeyStore(Path keyStoreFile, char[] keyStorePassword, String keyStoreType) {
                try {
-                       KeyStore store = KeyStore.getInstance(keyStoreType, SECURITY_PROVIDER);
+                       KeyStore store = KeyStore.getInstance(keyStoreType, SUN_JSSE_SECURITY_PROVIDER);
                        if (Files.exists(keyStoreFile)) {
                                try (InputStream fis = Files.newInputStream(keyStoreFile)) {
                                        store.load(fis, keyStorePassword);
@@ -138,12 +165,24 @@ class PkiUtils {
 //             return bos.toByteArray();
 //     }
 
-       public static void loadPem(KeyStore keyStore, Reader key, char[] keyPassword, Reader cert) {
-               PrivateKey privateKey = loadPemPrivateKey(key, keyPassword);
-               X509Certificate certificate = loadPemCertificate(cert);
+       public static void loadPrivateCertificatePem(KeyStore keyStore, String alias, Reader key, char[] keyPassword,
+                       Reader cert) {
+               Objects.requireNonNull(keyStore);
+               Objects.requireNonNull(key);
+               try {
+                       X509Certificate certificate = loadPemCertificate(cert);
+                       PrivateKey privateKey = loadPemPrivateKey(key, keyPassword);
+                       keyStore.setKeyEntry(alias, privateKey, keyPassword, new java.security.cert.Certificate[] { certificate });
+               } catch (KeyStoreException e) {
+                       throw new RuntimeException("Cannot store PEM certificate", e);
+               }
+       }
+
+       public static void loadTrustedCertificatePem(KeyStore keyStore,char[] keyStorePassword, Reader cert) {
                try {
-                       keyStore.setKeyEntry(certificate.getSubjectX500Principal().getName(), privateKey, keyPassword,
-                                       new java.security.cert.Certificate[] { certificate });
+                       X509Certificate certificate = loadPemCertificate(cert);
+                       TrustedCertificateEntry trustedCertificateEntry = new TrustedCertificateEntry(certificate);
+                       keyStore.setEntry(certificate.getSubjectX500Principal().getName(), trustedCertificateEntry, null);
                } catch (KeyStoreException e) {
                        throw new RuntimeException("Cannot store PEM certificate", e);
                }
@@ -151,7 +190,7 @@ class PkiUtils {
 
        public static PrivateKey loadPemPrivateKey(Reader reader, char[] keyPassword) {
                try (PEMParser pemParser = new PEMParser(reader)) {
-                       JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
+                       JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(BC_SECURITY_PROVIDER);
                        Object object = pemParser.readObject();
                        PrivateKeyInfo privateKeyInfo;
                        if (object instanceof PKCS8EncryptedPrivateKeyInfo) {
@@ -173,7 +212,7 @@ class PkiUtils {
        public static X509Certificate loadPemCertificate(Reader reader) {
                try (PEMParser pemParser = new PEMParser(reader)) {
                        X509CertificateHolder certHolder = (X509CertificateHolder) pemParser.readObject();
-                       X509Certificate cert = new JcaX509CertificateConverter().setProvider(SECURITY_PROVIDER)
+                       X509Certificate cert = new JcaX509CertificateConverter().setProvider(SUN_SECURITY_PROVIDER)
                                        .getCertificate(certHolder);
                        return cert;
                } catch (IOException | CertificateException e) {
@@ -256,4 +295,33 @@ class PkiUtils {
 
        }
 
+       public static void createSelfSignedKeyStore(Path keyStorePath, char[] keyStorePassword, String keyStoreType) {
+               // for (Provider provider : Security.getProviders())
+               // System.out.println(provider.getName());
+               // File keyStoreFile = keyStorePath.toFile();
+               char[] keyPwd = Arrays.copyOf(keyStorePassword, keyStorePassword.length);
+               if (!Files.exists(keyStorePath)) {
+                       try {
+                               Files.createDirectories(keyStorePath.getParent());
+                               KeyStore keyStore = getKeyStore(keyStorePath, keyStorePassword, keyStoreType);
+                               generateSelfSignedCertificate(keyStore,
+                                               new X500Principal("CN=" + InetAddress.getLocalHost().getHostName() + ",OU=UNSECURE,O=UNSECURE"),
+                                               1024, keyPwd);
+                               saveKeyStore(keyStorePath, keyStorePassword, keyStore);
+                               if (log.isDebugEnabled())
+                                       log.debug("Created self-signed unsecure keystore " + keyStorePath);
+                       } catch (Exception e) {
+                               try {
+                                       if (Files.size(keyStorePath) == 0)
+                                               Files.delete(keyStorePath);
+                               } catch (IOException e1) {
+                                       // silent
+                               }
+                               log.error("Cannot create keystore " + keyStorePath, e);
+                       }
+               } else {
+                       throw new IllegalStateException("Keystore " + keyStorePath + " already exists");
+               }
+       }
+
 }