summaryrefslogtreecommitdiffstats
path: root/src/main/java/com/gitblit/utils/HttpUtils.java
diff options
context:
space:
mode:
authorJames Moger <james.moger@gitblit.com>2013-03-27 12:46:05 -0400
committerJames Moger <james.moger@gitblit.com>2013-03-27 17:22:08 -0400
commitf6b200be4c8b90c26886c6cdd5809abac8c4ac15 (patch)
treea948dbcf6f24bf884ad95a8d6830b4ec4e1706cf /src/main/java/com/gitblit/utils/HttpUtils.java
parentb79ade104858ce6714a7329b7629b331564a2ea5 (diff)
downloadgitblit-f6b200be4c8b90c26886c6cdd5809abac8c4ac15.tar.gz
gitblit-f6b200be4c8b90c26886c6cdd5809abac8c4ac15.zip
Reorganized to Apache Standard Directory Layout & integrated Moxie
This is a massive commit which reorganizes the entire project structure (although it is still monolithic), removes the Build classes, and switches to Moxie, a smarter Ant build tookit based on the original Gitblit Build classes. The Ant build script will likely require additional fine-tuning, but this is big step forward.
Diffstat (limited to 'src/main/java/com/gitblit/utils/HttpUtils.java')
-rw-r--r--src/main/java/com/gitblit/utils/HttpUtils.java204
1 files changed, 204 insertions, 0 deletions
diff --git a/src/main/java/com/gitblit/utils/HttpUtils.java b/src/main/java/com/gitblit/utils/HttpUtils.java
new file mode 100644
index 00000000..86f53cfe
--- /dev/null
+++ b/src/main/java/com/gitblit/utils/HttpUtils.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2011 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.utils;
+
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.text.MessageFormat;
+import java.util.Date;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.LoggerFactory;
+
+import com.gitblit.models.UserModel;
+import com.gitblit.utils.X509Utils.X509Metadata;
+
+/**
+ * Collection of utility methods for http requests.
+ *
+ * @author James Moger
+ *
+ */
+public class HttpUtils {
+
+ /**
+ * Returns the Gitblit URL based on the request.
+ *
+ * @param request
+ * @return the host url
+ */
+ public static String getGitblitURL(HttpServletRequest request) {
+ // default to the request scheme and port
+ String scheme = request.getScheme();
+ int port = request.getServerPort();
+
+ // try to use reverse-proxy server's port
+ String forwardedPort = request.getHeader("X-Forwarded-Port");
+ if (StringUtils.isEmpty(forwardedPort)) {
+ forwardedPort = request.getHeader("X_Forwarded_Port");
+ }
+ if (!StringUtils.isEmpty(forwardedPort)) {
+ // reverse-proxy server has supplied the original port
+ try {
+ port = Integer.parseInt(forwardedPort);
+ } catch (Throwable t) {
+ }
+ }
+
+ // try to use reverse-proxy server's scheme
+ String forwardedScheme = request.getHeader("X-Forwarded-Proto");
+ if (StringUtils.isEmpty(forwardedScheme)) {
+ forwardedScheme = request.getHeader("X_Forwarded_Proto");
+ }
+ if (!StringUtils.isEmpty(forwardedScheme)) {
+ // reverse-proxy server has supplied the original scheme
+ scheme = forwardedScheme;
+
+ if ("https".equals(scheme) && port == 80) {
+ // proxy server is https, inside server is 80
+ // this is likely because the proxy server has not supplied
+ // x-forwarded-port. since 80 is almost definitely wrong,
+ // make an educated guess that 443 is correct.
+ port = 443;
+ }
+ }
+
+ String context = request.getContextPath();
+ String forwardedContext = request.getHeader("X-Forwarded-Context");
+ if (forwardedContext != null) {
+ forwardedContext = request.getHeader("X_Forwarded_Context");
+ }
+ if (!StringUtils.isEmpty(forwardedContext)) {
+ context = forwardedContext;
+ }
+
+ // trim any trailing slash
+ if (context.length() > 0 && context.charAt(context.length() - 1) == '/') {
+ context = context.substring(1);
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(scheme);
+ sb.append("://");
+ sb.append(request.getServerName());
+ if (("http".equals(scheme) && port != 80)
+ || ("https".equals(scheme) && port != 443)) {
+ sb.append(":" + port);
+ }
+ sb.append(context);
+ return sb.toString();
+ }
+
+ /**
+ * Returns a user model object built from attributes in the SSL certificate.
+ * This model is not retrieved from the user service.
+ *
+ * @param httpRequest
+ * @param checkValidity ensure certificate can be used now
+ * @param usernameOIDs if unspecified, CN is used as the username
+ * @return a UserModel, if a valid certificate is in the request, null otherwise
+ */
+ public static UserModel getUserModelFromCertificate(HttpServletRequest httpRequest, boolean checkValidity, String... usernameOIDs) {
+ if (httpRequest.getAttribute("javax.servlet.request.X509Certificate") != null) {
+ X509Certificate[] certChain = (X509Certificate[]) httpRequest
+ .getAttribute("javax.servlet.request.X509Certificate");
+ if (certChain != null) {
+ X509Certificate cert = certChain[0];
+ // ensure certificate is valid
+ if (checkValidity) {
+ try {
+ cert.checkValidity(new Date());
+ } catch (CertificateNotYetValidException e) {
+ LoggerFactory.getLogger(HttpUtils.class).info(MessageFormat.format("X509 certificate {0} is not yet valid", cert.getSubjectDN().getName()));
+ return null;
+ } catch (CertificateExpiredException e) {
+ LoggerFactory.getLogger(HttpUtils.class).info(MessageFormat.format("X509 certificate {0} has expired", cert.getSubjectDN().getName()));
+ return null;
+ }
+ }
+ return getUserModelFromCertificate(cert, usernameOIDs);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Creates a UserModel from a certificate
+ * @param cert
+ * @param usernameOids if unspecified CN is used as the username
+ * @return
+ */
+ public static UserModel getUserModelFromCertificate(X509Certificate cert, String... usernameOIDs) {
+ X509Metadata metadata = X509Utils.getMetadata(cert);
+
+ UserModel user = new UserModel(metadata.commonName);
+ user.emailAddress = metadata.emailAddress;
+ user.isAuthenticated = false;
+
+ if (usernameOIDs == null || usernameOIDs.length == 0) {
+ // use default usename<->CN mapping
+ usernameOIDs = new String [] { "CN" };
+ }
+
+ // determine username from OID fingerprint
+ StringBuilder an = new StringBuilder();
+ for (String oid : usernameOIDs) {
+ String val = metadata.getOID(oid.toUpperCase(), null);
+ if (val != null) {
+ an.append(val).append(' ');
+ }
+ }
+ user.username = an.toString().trim();
+ return user;
+ }
+
+ public static X509Metadata getCertificateMetadata(HttpServletRequest httpRequest) {
+ if (httpRequest.getAttribute("javax.servlet.request.X509Certificate") != null) {
+ X509Certificate[] certChain = (X509Certificate[]) httpRequest
+ .getAttribute("javax.servlet.request.X509Certificate");
+ if (certChain != null) {
+ X509Certificate cert = certChain[0];
+ return X509Utils.getMetadata(cert);
+ }
+ }
+ 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;
+ }
+ }
+ return true;
+ }
+ // TODO IPV6?
+ return false;
+ }
+}