1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
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 (StringUtils.isEmpty(forwardedContext)) {
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;
}
}
|