From dfc4ece4083bbbb98f55291d05e7d2b1513464b7 Mon Sep 17 00:00:00 2001 From: Thomas Pummer <dev@nullpointer.at> Date: Fri, 22 Feb 2013 11:10:11 -0500 Subject: [PATCH] the display-name in web.xml now shows the actual version of Gitblit --- src/com/gitblit/utils/X509Utils.java | 98 +++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 87 insertions(+), 11 deletions(-) diff --git a/src/com/gitblit/utils/X509Utils.java b/src/com/gitblit/utils/X509Utils.java index 1510b2c..237c8da 100644 --- a/src/com/gitblit/utils/X509Utils.java +++ b/src/com/gitblit/utils/X509Utils.java @@ -46,11 +46,13 @@ import java.security.cert.X509Certificate; import java.text.MessageFormat; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.TimeZone; @@ -110,6 +112,12 @@ public static final String CA_ALIAS = CA_CN; private static final String BC = org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME; + + private static final int KEY_LENGTH = 2048; + + private static final String KEY_ALGORITHM = "RSA"; + + private static final String SIGNING_ALGORITHM = "SHA512withRSA"; public static final boolean unlimitedStrength; @@ -182,6 +190,9 @@ // displayname of user for README in bundle public String userDisplayname; + + // serialnumber of generated or read certificate + public String serialNumber; public X509Metadata(String cn, String pwd) { if (StringUtils.isEmpty(cn)) { @@ -472,8 +483,8 @@ * @throws Exception */ private static KeyPair newKeyPair() throws Exception { - KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", BC); - kpGen.initialize(2048, new SecureRandom()); + KeyPairGenerator kpGen = KeyPairGenerator.getInstance(KEY_ALGORITHM, BC); + kpGen.initialize(KEY_LENGTH, new SecureRandom()); return kpGen.generateKeyPair(); } @@ -547,7 +558,17 @@ certBuilder.addExtension(X509Extension.basicConstraints, false, new BasicConstraints(false)); certBuilder.addExtension(X509Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(caCert.getPublicKey())); - ContentSigner caSigner = new JcaContentSignerBuilder("SHA256WithRSAEncryption") + // support alternateSubjectNames for SSL certificates + List<GeneralName> altNames = new ArrayList<GeneralName>(); + if (HttpUtils.isIpAddress(sslMetadata.commonName)) { + altNames.add(new GeneralName(GeneralName.iPAddress, sslMetadata.commonName)); + } + if (altNames.size() > 0) { + GeneralNames subjectAltName = new GeneralNames(altNames.toArray(new GeneralName [altNames.size()])); + certBuilder.addExtension(X509Extension.subjectAlternativeName, false, subjectAltName); + } + + ContentSigner caSigner = new JcaContentSignerBuilder(SIGNING_ALGORITHM) .setProvider(BC).build(caPrivateKey); X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC) .getCertificate(certBuilder.build(caSigner)); @@ -561,7 +582,11 @@ new Certificate[] { cert, caCert }); saveKeyStore(targetStoreFile, serverStore, sslMetadata.password); - x509log.log(MessageFormat.format("New web certificate {0,number,0} [{1}]", cert.getSerialNumber(), cert.getSubjectDN().getName())); + x509log.log(MessageFormat.format("New SSL certificate {0,number,0} [{1}]", cert.getSerialNumber(), cert.getSubjectDN().getName())); + + // update serial number in metadata object + sslMetadata.serialNumber = cert.getSerialNumber().toString(); + return cert; } catch (Throwable t) { throw new RuntimeException("Failed to generate SSL certificate!", t); @@ -582,7 +607,7 @@ try { KeyPair caPair = newKeyPair(); - ContentSigner caSigner = new JcaContentSignerBuilder("SHA1WithRSA").setProvider(BC).build(caPair.getPrivate()); + ContentSigner caSigner = new JcaContentSignerBuilder(SIGNING_ALGORITHM).setProvider(BC).build(caPair.getPrivate()); // clone metadata X509Metadata caMetadata = metadata.clone(CA_CN, metadata.password); @@ -623,6 +648,9 @@ x509log.log(MessageFormat.format("New CA certificate {0,number,0} [{1}]", cert.getSerialNumber(), cert.getIssuerDN().getName())); + // update serial number in metadata object + caMetadata.serialNumber = cert.getSerialNumber().toString(); + return cert; } catch (Throwable t) { throw new RuntimeException("Failed to generate Gitblit CA certificate!", t); @@ -649,7 +677,7 @@ X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(issuerDN, new Date()); // build and sign CRL with CA private key - ContentSigner signer = new JcaContentSignerBuilder("SHA1WithRSA").setProvider(BC).build(caPrivateKey); + ContentSigner signer = new JcaContentSignerBuilder(SIGNING_ALGORITHM).setProvider(BC).build(caPrivateKey); X509CRLHolder crl = crlBuilder.build(signer); File tmpFile = new File(caRevocationList.getParentFile(), Long.toHexString(System.currentTimeMillis()) + ".tmp"); @@ -743,6 +771,17 @@ zos.write(FileUtils.readContent(pemFile)); zos.closeEntry(); } + + // include user's public certificate + zos.putNextEntry(new ZipEntry(clientMetadata.commonName + ".cer")); + zos.write(cert.getEncoded()); + zos.closeEntry(); + + // include CA public certificate + zos.putNextEntry(new ZipEntry("ca.cer")); + zos.write(caCert.getEncoded()); + zos.closeEntry(); + if (readme != null) { zos.putNextEntry(new ZipEntry("README.TXT")); zos.write(readme.getBytes("UTF-8")); @@ -799,7 +838,7 @@ certBuilder.addExtension(X509Extension.subjectAlternativeName, false, subjectAltName); } - ContentSigner signer = new JcaContentSignerBuilder("SHA1WithRSA").setProvider(BC).build(caPrivateKey); + ContentSigner signer = new JcaContentSignerBuilder(SIGNING_ALGORITHM).setProvider(BC).build(caPrivateKey); X509Certificate userCert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certBuilder.build(signer)); PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)pair.getPrivate(); @@ -851,6 +890,9 @@ // save certificate after successfully creating the key stores saveCertificate(userCert, certFile); + + // update serial number in metadata object + clientMetadata.serialNumber = userCert.getSerialNumber().toString(); return userCert; } catch (Throwable t) { @@ -935,10 +977,18 @@ String message = FileUtils.readContent(template, "\n"); if (!StringUtils.isEmpty(message)) { content = message; - content = content.replace("$serverHostname", metadata.serverHostname); - content = content.replace("$username", metadata.commonName); - content = content.replace("$userDisplayname", metadata.userDisplayname); - content = content.replace("$storePasswordHint", metadata.passwordHint); + if (!StringUtils.isEmpty(metadata.serverHostname)) { + content = content.replace("$serverHostname", metadata.serverHostname); + } + if (!StringUtils.isEmpty(metadata.commonName)) { + content = content.replace("$username", metadata.commonName); + } + if (!StringUtils.isEmpty(metadata.userDisplayname)) { + content = content.replace("$userDisplayname", metadata.userDisplayname); + } + if (!StringUtils.isEmpty(metadata.passwordHint)) { + content = content.replace("$storePasswordHint", metadata.passwordHint); + } } } return content; @@ -1057,4 +1107,30 @@ } return false; } + + public static X509Metadata getMetadata(X509Certificate cert) { + // manually split DN into OID components + // this is instead of parsing with LdapName which: + // (1) I don't trust the order of values + // (2) it filters out values like EMAILADDRESS + String dn = cert.getSubjectDN().getName(); + Map<String, String> oids = new HashMap<String, String>(); + for (String kvp : dn.split(",")) { + String [] val = kvp.trim().split("="); + String oid = val[0].toUpperCase().trim(); + String data = val[1].trim(); + oids.put(oid, data); + } + + X509Metadata metadata = new X509Metadata(oids.get("CN"), "whocares"); + metadata.oids.putAll(oids); + metadata.serialNumber = cert.getSerialNumber().toString(); + metadata.notAfter = cert.getNotAfter(); + metadata.notBefore = cert.getNotBefore(); + metadata.emailAddress = metadata.getOID("E", null); + if (metadata.emailAddress == null) { + metadata.emailAddress = metadata.getOID("EMAILADDRESS", null); + } + return metadata; + } } -- Gitblit v1.9.1