From d3c18925529690716ce1b9038169d7a07e53b287 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Mon, 03 Dec 2012 17:03:31 -0500
Subject: [PATCH] Set subjectAlternativeName on SSL cert if CN=IPAddress (issue-170)

---
 src/com/gitblit/utils/HttpUtils.java |   22 ++++++++++++++++++++++
 docs/04_releases.mkd                 |    1 +
 src/com/gitblit/utils/X509Utils.java |   12 ++++++++++++
 3 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/docs/04_releases.mkd b/docs/04_releases.mkd
index bf57d11..2f35182 100644
--- a/docs/04_releases.mkd
+++ b/docs/04_releases.mkd
@@ -12,6 +12,7 @@
 
 #### fixes
 
+- Set subjectAlternativeName on generated SSL cert if CN is an ip address (issue 170)
 - Fixed incorrect links on history page for files not in the current/active commit (issue 166)
 - Empty repository page failed to handle missing repository (issue 160)
 - Fixed broken ticgit urls (issue 157)
diff --git a/src/com/gitblit/utils/HttpUtils.java b/src/com/gitblit/utils/HttpUtils.java
index b40088c..56c8bd2 100644
--- a/src/com/gitblit/utils/HttpUtils.java
+++ b/src/com/gitblit/utils/HttpUtils.java
@@ -178,4 +178,26 @@
 		}
 		return null;
 	}
+	
+	public static boolean isIpAddress(String address) {
+		if (StringUtils.isEmpty(address)) {
+			return false;
+		}
+		String [] fields = address.split("\\.");
+		if (fields.length == 4) {
+			// IPV4
+			for (String field : fields) {
+				try {
+					int value = Integer.parseInt(field);
+					if (value < 0 || value > 255) {
+						return false;
+					}
+				} catch (Exception e) {
+					return false;
+				}
+			}
+		}
+		// TODO IPV6?
+		return false;
+	}
 }
diff --git a/src/com/gitblit/utils/X509Utils.java b/src/com/gitblit/utils/X509Utils.java
index cfad9ec..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;
@@ -556,6 +558,16 @@
 			certBuilder.addExtension(X509Extension.basicConstraints, false, new BasicConstraints(false));
 			certBuilder.addExtension(X509Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(caCert.getPublicKey()));
 
+			// 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)

--
Gitblit v1.9.1