X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=src%2Fclub%2Fwpia%2Fgigi%2FGigi.java;h=e76c51710e6c1c664d19c72c176d238f9f05c2ee;hp=2c61c0717d38492a81101b9ba834a532bb2eab23;hb=8bb6a6f9dd49888a07b0588ae9773cc52d51cdb5;hpb=0cc15355aef045e9e608b06454d77c6415cd6446 diff --git a/src/club/wpia/gigi/Gigi.java b/src/club/wpia/gigi/Gigi.java index 2c61c071..e76c5171 100644 --- a/src/club/wpia/gigi/Gigi.java +++ b/src/club/wpia/gigi/Gigi.java @@ -3,7 +3,13 @@ package club.wpia.gigi; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.nio.channels.FileChannel; +import java.nio.file.FileSystems; +import java.nio.file.NoSuchFileException; import java.security.KeyStore; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.security.cert.X509Certificate; import java.util.Calendar; import java.util.Collections; @@ -63,17 +69,24 @@ import club.wpia.gigi.pages.admin.support.FindCertPage; import club.wpia.gigi.pages.admin.support.FindUserByDomainPage; import club.wpia.gigi.pages.admin.support.FindUserByEmailPage; import club.wpia.gigi.pages.admin.support.SupportEnterTicketPage; +import club.wpia.gigi.pages.admin.support.SupportOrgDomainPage; import club.wpia.gigi.pages.admin.support.SupportUserDetailsPage; import club.wpia.gigi.pages.error.AccessDenied; import club.wpia.gigi.pages.error.PageNotFound; +import club.wpia.gigi.pages.main.CertStatusRequestPage; import club.wpia.gigi.pages.main.KeyCompromisePage; import club.wpia.gigi.pages.main.RegisterPage; import club.wpia.gigi.pages.orga.CreateOrgPage; +import club.wpia.gigi.pages.orga.SwitchOrganisation; import club.wpia.gigi.pages.orga.ViewOrgPage; import club.wpia.gigi.pages.statistics.StatisticsRoles; import club.wpia.gigi.pages.wot.Points; import club.wpia.gigi.pages.wot.RequestTTPPage; import club.wpia.gigi.pages.wot.VerifyPage; +import club.wpia.gigi.passwords.DelegatingPasswordChecker; +import club.wpia.gigi.passwords.PasswordChecker; +import club.wpia.gigi.passwords.PasswordHashChecker; +import club.wpia.gigi.passwords.PasswordStrengthChecker; import club.wpia.gigi.ping.PingerDaemon; import club.wpia.gigi.util.AuthorizationContext; import club.wpia.gigi.util.DomainAssessment; @@ -141,17 +154,18 @@ public final class Gigi extends HttpServlet { putPage(StatisticsRoles.PATH, new StatisticsRoles(), mainMenu); putPage("/about", new AboutPage(), mainMenu); putPage(RegisterPage.PATH, new RegisterPage(), mainMenu); + putPage(CertStatusRequestPage.PATH, new CertStatusRequestPage(), mainMenu); putPage(KeyCompromisePage.PATH, new KeyCompromisePage(), mainMenu); putPage(Verify.PATH, new Verify(), null); Menu certificates = createMenu("Certificates"); putPage(Certificates.PATH + "/*", new Certificates(false), certificates); putPage(CertificateAdd.PATH, new CertificateAdd(), certificates); - putPage(MailOverview.DEFAULT_PATH, new MailOverview(), certificates); - putPage(DomainOverview.PATH, new DomainOverview(), certificates); - putPage(EditDomain.PATH + "*", new EditDomain(), null); Menu wot = createMenu("Verification"); + putPage(MailOverview.DEFAULT_PATH, new MailOverview(), wot); + putPage(DomainOverview.PATH, new DomainOverview(), wot); + putPage(EditDomain.PATH + "*", new EditDomain(), null); putPage(VerifyPage.PATH + "/*", new VerifyPage(), wot); putPage(Points.PATH, new Points(false), wot); putPage(RequestTTPPage.PATH, new RequestTTPPage(), wot); @@ -161,6 +175,7 @@ public final class Gigi extends HttpServlet { putPage(TTPAdminPage.PATH + "/*", new TTPAdminPage(), admMenu); putPage(CreateOrgPage.DEFAULT_PATH, new CreateOrgPage(), orgAdm); putPage(ViewOrgPage.DEFAULT_PATH + "/*", new ViewOrgPage(), orgAdm); + putPage(SwitchOrganisation.PATH, new SwitchOrganisation(), orgAdm); Menu support = createMenu("Support Console"); putPage(SupportEnterTicketPage.PATH, new SupportEnterTicketPage(), support); @@ -170,6 +185,7 @@ public final class Gigi extends HttpServlet { Menu account = createMenu("My Account"); putPage(SupportUserDetailsPage.PATH + "*", new SupportUserDetailsPage(), null); + putPage(SupportOrgDomainPage.PATH + "*", new SupportOrgDomainPage(), null); putPage(ChangePasswordPage.PATH, new ChangePasswordPage(), account); putPage(History.PATH, new History(false), account); putPage(FindAgentAccess.PATH, new OneFormPage("Access to Find Agent", FindAgentAccess.class), account); @@ -238,6 +254,8 @@ public final class Gigi extends HttpServlet { private static Gigi instance; + private static PasswordChecker passwordChecker; + private static final Template baseTemplate = new Template(Gigi.class.getResource("Gigi.templ")); private PingerDaemon pinger; @@ -266,6 +284,46 @@ public final class Gigi extends HttpServlet { this.truststore = truststore; pinger = new PingerDaemon(truststore); pinger.start(); + Gigi.passwordChecker = getPasswordChecker(conf); + } + } + + private PasswordChecker getPasswordChecker(Properties conf) { + final String knownPasswordHashesPath; + final boolean knownPasswordHashesRequired; + String knownPasswordHashesConfig = conf.getProperty("knownPasswordHashes"); + if (knownPasswordHashesConfig != null) { + knownPasswordHashesPath = knownPasswordHashesConfig; + knownPasswordHashesRequired = true; + } else { + knownPasswordHashesPath = "/usr/share/pwned-passwords/pwned-passwords.bin"; + knownPasswordHashesRequired = false; + } + + final MessageDigest sha1; + try { + sha1 = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + + try { + final FileChannel knownPasswordHashesFile = FileChannel.open( + FileSystems.getDefault().getPath(knownPasswordHashesPath)); + return new DelegatingPasswordChecker(new PasswordChecker[] { + new PasswordStrengthChecker(), + new PasswordHashChecker(knownPasswordHashesFile, sha1) + }); + } catch (IOException e) { + if (knownPasswordHashesRequired) { + throw new RuntimeException("Error while opening password hash database, refusing startup", e); + } else { + System.err.println("Warning: A problem was encountered while opening the password hash database, passwords will be checked only by strength."); + if ( !(e instanceof NoSuchFileException)) { + e.printStackTrace(); + } + return new PasswordStrengthChecker(); + } } } @@ -357,11 +415,11 @@ public final class Gigi extends HttpServlet { return; } HttpSession hs = req.getSession(); - String clientSerial = (String) hs.getAttribute(CERT_SERIAL); + BigInteger clientSerial = (BigInteger) hs.getAttribute(CERT_SERIAL); if (clientSerial != null) { X509Certificate[] cert = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate"); if (cert == null || cert[0] == null// - || !cert[0].getSerialNumber().toString(16).toLowerCase().equals(clientSerial) // + || !cert[0].getSerialNumber().equals(clientSerial) // || !cert[0].getIssuerDN().equals(hs.getAttribute(CERT_ISSUER))) { hs.invalidate(); resp.sendError(403, "Certificate mismatch."); @@ -514,4 +572,15 @@ public final class Gigi extends HttpServlet { instance.pinger.interrupt(); } + public static PasswordChecker getPasswordChecker() { + if (passwordChecker == null) { + throw new IllegalStateException("Not yet initialized!"); + } + return passwordChecker; + } + + public static void setPasswordChecker(PasswordChecker passwordChecker) { + Gigi.passwordChecker = passwordChecker; + } + }