You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GitblitTrustManager.java 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*
  2. * Copyright 2012 gitblit.com.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.gitblit;
  17. import java.io.File;
  18. import java.io.FileInputStream;
  19. import java.io.InputStream;
  20. import java.security.cert.CertificateException;
  21. import java.security.cert.CertificateFactory;
  22. import java.security.cert.X509CRL;
  23. import java.security.cert.X509CRLEntry;
  24. import java.security.cert.X509Certificate;
  25. import java.text.MessageFormat;
  26. import java.util.concurrent.atomic.AtomicLong;
  27. import javax.net.ssl.X509TrustManager;
  28. import org.slf4j.Logger;
  29. import org.slf4j.LoggerFactory;
  30. /**
  31. * GitblitTrustManager is a wrapper trust manager that hot-reloads a local file
  32. * CRL and enforces client certificate revocations. The GitblitTrustManager
  33. * also implements fuzzy revocation enforcement in case of issuer mismatch BUT
  34. * serial number match. These rejecions are specially noted in the log.
  35. *
  36. * @author James Moger
  37. */
  38. public class GitblitTrustManager implements X509TrustManager {
  39. private static final Logger logger = LoggerFactory.getLogger(GitblitTrustManager.class);
  40. private final X509TrustManager delegate;
  41. private final File caRevocationList;
  42. private final AtomicLong lastModified = new AtomicLong(0);
  43. private volatile X509CRL crl;
  44. public GitblitTrustManager(X509TrustManager delegate, File crlFile) {
  45. this.delegate = delegate;
  46. this.caRevocationList = crlFile;
  47. }
  48. @Override
  49. public void checkClientTrusted(X509Certificate[] chain, String authType)
  50. throws CertificateException {
  51. X509Certificate cert = chain[0];
  52. if (isRevoked(cert)) {
  53. String message = MessageFormat.format("Rejecting revoked certificate {0,number,0} for {1}",
  54. cert.getSerialNumber(), cert.getSubjectDN().getName());
  55. logger.warn(message);
  56. throw new CertificateException(message);
  57. }
  58. delegate.checkClientTrusted(chain, authType);
  59. }
  60. @Override
  61. public void checkServerTrusted(X509Certificate[] chain, String authType)
  62. throws CertificateException {
  63. delegate.checkServerTrusted(chain, authType);
  64. }
  65. @Override
  66. public X509Certificate[] getAcceptedIssuers() {
  67. return delegate.getAcceptedIssuers();
  68. }
  69. protected boolean isRevoked(X509Certificate cert) {
  70. if (!caRevocationList.exists()) {
  71. return false;
  72. }
  73. read();
  74. if (crl.isRevoked(cert)) {
  75. // exact cert is revoked
  76. return true;
  77. }
  78. X509CRLEntry entry = crl.getRevokedCertificate(cert.getSerialNumber());
  79. if (entry != null) {
  80. logger.warn("Certificate issuer does not match CRL issuer, but serial number has been revoked!");
  81. logger.warn(" cert issuer = " + cert.getIssuerX500Principal());
  82. logger.warn(" crl issuer = " + crl.getIssuerX500Principal());
  83. return true;
  84. }
  85. return false;
  86. }
  87. protected synchronized void read() {
  88. if (lastModified.get() == caRevocationList.lastModified()) {
  89. return;
  90. }
  91. logger.info("Reloading CRL from " + caRevocationList.getAbsolutePath());
  92. InputStream inStream = null;
  93. try {
  94. inStream = new FileInputStream(caRevocationList);
  95. CertificateFactory cf = CertificateFactory.getInstance("X.509");
  96. X509CRL list = (X509CRL)cf.generateCRL(inStream);
  97. crl = list;
  98. lastModified.set(caRevocationList.lastModified());
  99. } catch (Exception e) {
  100. } finally {
  101. if (inStream != null) {
  102. try {
  103. inStream.close();
  104. } catch (Exception e) {
  105. }
  106. }
  107. }
  108. }
  109. }