Revision 6627
Added by ben leinfelder about 13 years ago
src/edu/ucsb/nceas/metacat/replication/ReplicationServlet.java | ||
---|---|---|
26 | 26 |
|
27 | 27 |
package edu.ucsb.nceas.metacat.replication; |
28 | 28 |
|
29 |
import java.io.FileInputStream; |
|
30 | 29 |
import java.io.IOException; |
31 |
import java.io.InputStream; |
|
32 | 30 |
import java.io.OutputStream; |
33 | 31 |
import java.io.PrintWriter; |
34 |
import java.security.KeyStore; |
|
35 |
import java.security.KeyStoreException; |
|
36 |
import java.security.NoSuchAlgorithmException; |
|
37 |
import java.security.cert.Certificate; |
|
38 |
import java.security.cert.CertificateException; |
|
32 |
import java.net.URI; |
|
33 |
import java.net.URISyntaxException; |
|
39 | 34 |
import java.security.cert.X509Certificate; |
40 | 35 |
import java.util.Enumeration; |
41 | 36 |
import java.util.Hashtable; |
42 | 37 |
|
38 |
import javax.naming.InvalidNameException; |
|
39 |
import javax.naming.ldap.LdapName; |
|
40 |
import javax.naming.ldap.Rdn; |
|
43 | 41 |
import javax.servlet.ServletConfig; |
44 | 42 |
import javax.servlet.ServletException; |
45 | 43 |
import javax.servlet.http.HttpServlet; |
... | ... | |
50 | 48 |
import org.apache.log4j.Logger; |
51 | 49 |
import org.dataone.client.auth.CertificateManager; |
52 | 50 |
|
53 |
import edu.ucsb.nceas.metacat.properties.PropertyService; |
|
54 | 51 |
import edu.ucsb.nceas.metacat.service.ServiceService; |
55 | 52 |
import edu.ucsb.nceas.metacat.service.SessionService; |
56 | 53 |
import edu.ucsb.nceas.metacat.shared.MetacatUtilException; |
57 | 54 |
import edu.ucsb.nceas.metacat.shared.ServiceException; |
58 | 55 |
import edu.ucsb.nceas.metacat.util.AuthUtil; |
59 | 56 |
import edu.ucsb.nceas.metacat.util.SessionData; |
60 |
import edu.ucsb.nceas.utilities.PropertyNotFoundException; |
|
61 | 57 |
|
62 | 58 |
public class ReplicationServlet extends HttpServlet { |
63 | 59 |
|
... | ... | |
121 | 117 |
|
122 | 118 |
try { |
123 | 119 |
// check if the server is included in the list of replicated servers |
120 |
server = ((String[]) params.get("server"))[0]; |
|
124 | 121 |
if (!action.equals("servercontrol") && !action.equals("stop") |
125 | 122 |
&& !action.equals("start") && !action.equals("getall")) { |
126 | 123 |
|
... | ... | |
128 | 125 |
boolean isValid = false; |
129 | 126 |
String msg = "Client certificate is invalid"; |
130 | 127 |
try { |
131 |
isValid = hasValidCertificate(request); |
|
128 |
isValid = hasValidCertificate(request, server);
|
|
132 | 129 |
} catch (Exception e) { |
133 | 130 |
msg = "Could not verify client certificate: " + e.getMessage(); |
134 | 131 |
logMetacat.error(msg, e); |
... | ... | |
144 | 141 |
return; |
145 | 142 |
} |
146 | 143 |
|
147 |
server = ((String[]) params.get("server"))[0]; |
|
148 | 144 |
if (ReplicationService.getServerCodeForServerName(server) == 0) { |
149 | 145 |
logReplication.debug("ReplicationServlet.handleGetOrPost - Action \"" + action + "\" rejected for server: " |
150 | 146 |
+ server); |
... | ... | |
270 | 266 |
} |
271 | 267 |
} |
272 | 268 |
|
273 |
private boolean hasValidCertificate(HttpServletRequest request) throws KeyStoreException, PropertyNotFoundException, NoSuchAlgorithmException, CertificateException, IOException {
|
|
269 |
private boolean hasValidCertificate(HttpServletRequest request, String server) throws InvalidNameException, URISyntaxException, ServiceException {
|
|
274 | 270 |
// get the certificate from the request |
275 | 271 |
X509Certificate certificate = CertificateManager.getInstance().getCertificate(request); |
276 | 272 |
if (certificate != null) { |
277 | 273 |
String givenSubject = CertificateManager.getInstance().getSubjectDN(certificate); |
278 | 274 |
logMetacat.debug("Given certificate subject: " + givenSubject); |
279 | 275 |
|
280 |
// load the keystore |
|
281 |
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); |
|
282 |
InputStream is = new FileInputStream(PropertyService.getProperty("replication.keystore.file")); |
|
283 |
String password = PropertyService.getProperty("replication.keystore.password"); |
|
284 |
keyStore.load(is, password.toCharArray()); |
|
276 |
// get the CN from the DN: |
|
277 |
String givenServerCN = null; |
|
278 |
LdapName ldapName = new LdapName(givenSubject); |
|
279 |
for (Rdn rdn: ldapName.getRdns()) { |
|
280 |
if (rdn.getType().equalsIgnoreCase("CN")) { |
|
281 |
givenServerCN = (String) rdn.getValue(); |
|
282 |
logMetacat.debug("Given server CN: " + givenServerCN); |
|
283 |
break; |
|
284 |
} |
|
285 |
} |
|
285 | 286 |
|
286 |
// this is expensive |
|
287 |
Enumeration<String> aliases = keyStore.aliases(); |
|
288 |
while (aliases.hasMoreElements()) { |
|
289 |
// check that it contains our client's entry |
|
290 |
String alias = aliases.nextElement(); |
|
291 |
logMetacat.debug("checking keyStore alias: " + alias); |
|
292 |
Certificate entryCertificate = keyStore.getCertificate(alias); |
|
293 |
if (entryCertificate instanceof X509Certificate) { |
|
294 |
// check the subject matches |
|
295 |
String entrySubject = CertificateManager.getInstance().getSubjectDN((X509Certificate) entryCertificate); |
|
296 |
logMetacat.debug("Entry certificate subject: " + entrySubject); |
|
297 |
if (entrySubject.equals(givenSubject)) { |
|
298 |
// TODO: additional verification |
|
299 |
// try { |
|
300 |
// certificate.verify(entryCertificate.getPublicKey()); |
|
301 |
// } catch (Exception e) { |
|
302 |
// logMetacat.warn("Certificate not verifiable: " + e.getMessage(), e); |
|
303 |
// continue; |
|
304 |
// } |
|
305 |
// if we pass verification, we did it! |
|
306 |
return true; |
|
307 |
} |
|
308 |
} |
|
287 |
// check the replication table for this server |
|
288 |
int serverCode = ReplicationService.getServerCodeForServerName(server); |
|
289 |
if (serverCode != 0) { |
|
290 |
// does it match (roughly) the certificate |
|
291 |
URI serverURI = new URI("https://" + server); |
|
292 |
String serverHost = serverURI.getHost(); |
|
293 |
logMetacat.debug("Checking against registerd replication server host name: " + serverHost); |
|
294 |
// remove wildcard from certificate CN if it is a wildcard certificate |
|
295 |
givenServerCN = givenServerCN.replace("*", ""); |
|
296 |
// match (ends with) same certificate name (domain)? |
|
297 |
return serverHost.endsWith(givenServerCN); |
|
309 | 298 |
} |
310 | 299 |
} |
311 | 300 |
return false; |
Also available in: Unified diff
check replication table (not keystore) for trusted server host name match