Changeset 3bc9053


Ignore:
Timestamp:
Mar 4, 2018 12:14:05 PM (2 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
c6e401a
Parents:
5a63926
Message:

KeyStore?: Log expiration of self-signed certs

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/SSLClientUtil.java

    r5a63926 r3bc9053  
    200200            fis = new FileInputStream(ks);
    201201            keyStore.load(fis, ksPass.toCharArray());
     202            KeyStoreUtil.logCertExpiration(keyStore, ks.getAbsolutePath(), 180*24*60*60*1000L);
    202203            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    203204            kmf.init(keyStore, keyPass.toCharArray());
  • apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java

    r5a63926 r3bc9053  
    854854    private boolean verifyKeyStore(File ks, Set<String> altNames) {
    855855        if (ks.exists()) {
     856            String ksPW = _context.getProperty(PROP_KEYSTORE_PASSWORD, KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD);
     857            KeyStoreUtil.logCertExpiration(ks, ksPW, 180*24*60*60*1000L);
    856858            boolean rv = _context.getProperty(PROP_KEY_PASSWORD) != null;
    857859            if (!rv)
    858                 System.err.println("Console SSL error, must set " + PROP_KEY_PASSWORD + " in " + (new File(_context.getConfigDir(), "router.config")).getAbsolutePath());
     860                System.err.println("Console SSL error, must set " + PROP_KEY_PASSWORD + " in " +
     861                                   (new File(_context.getConfigDir(), "router.config")).getAbsolutePath());
    859862            return rv;
    860863        }
  • apps/sam/java/src/net/i2p/sam/SSLUtil.java

    r5a63926 r3bc9053  
    164164            fis = new FileInputStream(ks);
    165165            keyStore.load(fis, ksPass.toCharArray());
     166            KeyStoreUtil.logCertExpiration(keyStore, ks.getAbsolutePath(), 180*24*60*60*1000L);
    166167            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    167168            kmf.init(keyStore, keyPass.toCharArray());
  • apps/sam/java/src/net/i2p/sam/client/SSLUtil.java

    r5a63926 r3bc9053  
    165165            fis = new FileInputStream(ks);
    166166            keyStore.load(fis, ksPass.toCharArray());
     167            KeyStoreUtil.logCertExpiration(keyStore, ks.getAbsolutePath(), 180*24*60*60*1000L);
    167168            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    168169            kmf.init(keyStore, keyPass.toCharArray());
  • core/java/src/net/i2p/crypto/KeyStoreUtil.java

    r5a63926 r3bc9053  
    99import java.security.GeneralSecurityException;
    1010import java.security.KeyStore;
     11import java.security.KeyStoreException;
    1112import java.security.MessageDigest;
    1213import java.security.PrivateKey;
     
    3031import net.i2p.crypto.provider.I2PProvider;
    3132import net.i2p.data.Base32;
     33import net.i2p.data.DataHelper;
    3234import net.i2p.util.Log;
    3335import net.i2p.util.SecureDirectory;
     
    280282        } catch (GeneralSecurityException e) {}
    281283        return count;
     284    }
     285
     286    /**
     287     *  Validate expiration for all private key certs in a key store.
     288     *  Use this for keystores containing selfsigned certs where the
     289     *  user will be expected to renew an expiring cert.
     290     *  Use this for Jetty keystores, where we aren't doing the loading ourselves.
     291     *
     292     *  If a cert isn't valid, it will probably cause bigger problems later when it's used.
     293     *
     294     *  @param f keystore file
     295     *  @param ksPW keystore password
     296     *  @param expiresWithin ms if cert expires within this long, we will log a warning, e.g. 180*24*60*60*1000L
     297     *  @return true if all are good, false if we logged something
     298     *  @since 0.9.34
     299     */
     300    public static boolean logCertExpiration(File f, String ksPW, long expiresWithin) {
     301        String location = f.getAbsolutePath();
     302        InputStream fis = null;
     303        try {
     304            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
     305            fis = new FileInputStream(f);
     306            ks.load(fis, ksPW.toCharArray());
     307            return logCertExpiration(ks, location, expiresWithin);
     308        } catch (IOException ioe) {
     309            error("Unable to check certificates in key store " + location, ioe);
     310            return false;
     311        } catch (GeneralSecurityException gse) {
     312            error("Unable to check certificates in key store " + location, gse);
     313            return false;
     314        } finally {
     315            try { if (fis != null) fis.close(); } catch (IOException foo) {}
     316        }
     317    }
     318
     319    /**
     320     *  Validate expiration for all private key certs in a key store.
     321     *  Use this for keystores containing selfsigned certs where the
     322     *  user will be expected to renew an expiring cert.
     323     *  Use this for keystores we are feeding to an SSLContext and ServerSocketFactory.
     324     *
     325     *  We added support for self-signed certs in 0.8.3 2011-01, with a 10-year expiration.
     326     *  We still don't generate them by default. We don't expect anybody's
     327     *  certs to expire until 2021.
     328     *
     329     *  @param location the path or other identifying info, for logging only
     330     *  @param expiresWithin ms if cert expires within this long, we will log a warning, e.g. 180*24*60*60*1000L
     331     *  @return true if all are good, false if we logged something
     332     *  @since 0.9.34
     333     */
     334    public static boolean logCertExpiration(KeyStore ks, String location, long expiresWithin) {
     335        boolean rv = true;
     336        try {
     337            int count = 0;
     338            for(Enumeration<String> e = ks.aliases(); e.hasMoreElements();) {
     339                String alias = e.nextElement();
     340                if (ks.isKeyEntry(alias)) {
     341                    Certificate[] cs;
     342                    try {
     343                        cs = ks.getCertificateChain(alias);
     344                    } catch (KeyStoreException kse) {
     345                        error("Unable to check certificates for \"" + alias + "\" in key store " + location, kse);
     346                        rv = false;
     347                        continue;
     348                    }
     349                    for (Certificate c : cs) {
     350                        if (c != null && (c instanceof X509Certificate)) {
     351                            count++;
     352                            X509Certificate cert = (X509Certificate) c;
     353                            try {
     354                                //System.out.println("checking " + alias + " in " + location);
     355                                cert.checkValidity();
     356                                long expiresIn = cert.getNotAfter().getTime() - System.currentTimeMillis();
     357                                //System.out.println("expiration of " + alias + " is in " + DataHelper.formatDuration(expiresIn));
     358                                if (expiresIn < expiresWithin) {
     359                                    Log l = I2PAppContext.getGlobalContext().logManager().getLog(KeyStoreUtil.class);
     360                                    String subj = cert.getIssuerX500Principal().toString();
     361                                    l.logAlways(Log.WARN, "Certificate \"" + subj + "\" in key store " + location +
     362                                                          " will expire in " + DataHelper.formatDuration2(expiresIn).replace("&nbsp;", " ") +
     363                                                          "\nYou should renew the certificate soon." +
     364                                                          // TODO better help or tools, or autorenew
     365                                                          "\nFor a local self-signed certificate, you may delete the keystore and restart," +
     366                                                          " or ask for help on how to renew.");
     367                                }
     368                            } catch (CertificateExpiredException cee) {
     369                                String subj = cert.getIssuerX500Principal().toString();
     370                                error("Expired certificate \"" + subj + "\" in key store " + location +
     371                                      "\nYou must renew the certificate." +
     372                                      // TODO better help or tools, or autorenew
     373                                      "\nFor a local self-signed certificate, you may simply delete the keystore and restart," +
     374                                      "\nor ask for help on how to renew.",
     375                                      null);
     376                                rv = false;
     377                            } catch (CertificateNotYetValidException cnyve) {
     378                                String subj = cert.getIssuerX500Principal().toString();
     379                                error("Not yet valid certificate \"" + subj + "\" in key store " + location, null);
     380                                rv = false;
     381                            }
     382                        }
     383                    }
     384                }
     385            }
     386            if (count == 0)
     387                error("No certificates found in key store " + location, null);
     388        } catch (GeneralSecurityException e) {
     389            error("Unable to check certificates in key store " + location, e);
     390            rv = false;
     391        }
     392        return rv;
    282393    }
    283394
  • router/java/src/net/i2p/router/client/SSLClientListenerRunner.java

    r5a63926 r3bc9053  
    143143            fis = new FileInputStream(ks);
    144144            keyStore.load(fis, ksPass.toCharArray());
     145            KeyStoreUtil.logCertExpiration(keyStore, ks.getAbsolutePath(), 180*24*60*60*1000L);
    145146            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    146147            kmf.init(keyStore, keyPass.toCharArray());
Note: See TracChangeset for help on using the changeset viewer.