X-Git-Url: https://code.wpia.club/?a=blobdiff_plain;f=src%2Forg%2Fcacert%2Fgigi%2Fpages%2FLoginPage.java;h=29b33aa4b2cba169df38412fcb1864794b9a643b;hb=d7271af56f7c4f3381ea079f1be1a52124e1d241;hp=91b6b1b7139383ce20c1d44d61e68b8e19a65406;hpb=ec24cf6925bb3729a644580ad4a9375d05883c62;p=gigi.git diff --git a/src/org/cacert/gigi/pages/LoginPage.java b/src/org/cacert/gigi/pages/LoginPage.java index 91b6b1b7..29b33aa4 100644 --- a/src/org/cacert/gigi/pages/LoginPage.java +++ b/src/org/cacert/gigi/pages/LoginPage.java @@ -13,17 +13,25 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.cacert.gigi.GigiApiException; -import org.cacert.gigi.database.DatabaseConnection; import org.cacert.gigi.database.GigiPreparedStatement; import org.cacert.gigi.database.GigiResultSet; +import org.cacert.gigi.dbObjects.CertificateOwner; import org.cacert.gigi.dbObjects.Group; import org.cacert.gigi.dbObjects.User; import org.cacert.gigi.localisation.Language; import org.cacert.gigi.output.template.Form; +import org.cacert.gigi.output.template.TranslateCommand; +import org.cacert.gigi.pages.main.RegisterPage; +import org.cacert.gigi.util.AuthorizationContext; import org.cacert.gigi.util.PasswordHash; +import org.cacert.gigi.util.RateLimit; +import org.cacert.gigi.util.RateLimit.RateLimitException; +import org.cacert.gigi.util.ServerConstants; public class LoginPage extends Page { + public static final RateLimit RATE_LIMIT = new RateLimit(10, 5 * 60 * 1000); + public class LoginForm extends Form { public LoginForm(HttpServletRequest hsr) { @@ -31,9 +39,12 @@ public class LoginPage extends Page { } @Override - public boolean submit(PrintWriter out, HttpServletRequest req) throws GigiApiException { + public RedirectResult submit(HttpServletRequest req) throws GigiApiException { + if (RegisterPage.RATE_LIMIT.isLimitExceeded(req.getRemoteAddr())) { + throw new RateLimitException(); + } tryAuthWithUnpw(req); - return false; + return new RedirectResult(redirectPath(req)); } @Override @@ -45,76 +56,99 @@ public class LoginPage extends Page { public static final String LOGIN_RETURNPATH = "login-returnpath"; - public LoginPage(String title) { - super(title); + public LoginPage() { + super("Password Login"); } @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { - new LoginForm(req).output(resp.getWriter(), getLanguage(req), new HashMap()); + if (req.getHeader("Host").equals(ServerConstants.getSecureHostNamePortSecure())) { + resp.getWriter().println(getLanguage(req).getTranslation("Authentication with certificate failed. Try another certificate or use a password.")); + } else { + new LoginForm(req).output(resp.getWriter(), getLanguage(req), new HashMap()); + } + } + + @Override + public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { + if (Form.printFormErrors(req, resp.getWriter())) { + Form.getForm(req, LoginForm.class).output(resp.getWriter(), getLanguage(req), new HashMap()); + } } @Override public boolean beforeTemplate(HttpServletRequest req, HttpServletResponse resp) throws IOException { - String redir = (String) req.getSession().getAttribute(LOGIN_RETURNPATH); if (req.getSession().getAttribute("loggedin") == null) { X509Certificate cert = getCertificateFromRequest(req); if (cert != null) { tryAuthWithCertificate(req, cert); } if (req.getMethod().equals("POST")) { - try { - Form.getForm(req, LoginForm.class).submit(resp.getWriter(), req); - } catch (GigiApiException e) { - } + return Form.getForm(req, LoginForm.class).submitExceptionProtected(req, resp); } } if (req.getSession().getAttribute("loggedin") != null) { - String s = redir; - if (s != null) { - if ( !s.startsWith("/")) { - s = "/" + s; - } - resp.sendRedirect(s); - } else { - resp.sendRedirect("/"); - } + resp.sendRedirect(redirectPath(req)); return true; } return false; } + private static String redirectPath(HttpServletRequest req) { + String redir = (String) req.getAttribute(LOGIN_RETURNPATH); + String s = redir; + if (s != null) { + if ( !s.startsWith("/")) { + s = "/" + s; + } + return s; + } else { + return "/"; + } + } + @Override public boolean needsLogin() { return false; } - private void tryAuthWithUnpw(HttpServletRequest req) { + private void tryAuthWithUnpw(HttpServletRequest req) throws GigiApiException { String un = req.getParameter("username"); String pw = req.getParameter("password"); - GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT `password`, `id` FROM `users` WHERE `email`=? AND verified='1'"); - ps.setString(1, un); - GigiResultSet rs = ps.executeQuery(); - if (rs.next()) { - String dbHash = rs.getString(1); - String hash = PasswordHash.verifyHash(pw, dbHash); - if (hash != null) { - if ( !hash.equals(dbHash)) { - GigiPreparedStatement gps = DatabaseConnection.getInstance().prepare("UPDATE `users` SET `password`=? WHERE `email`=?"); - gps.setString(1, hash); - gps.setString(2, un); - gps.executeUpdate(); + try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT `password`, `id` FROM `users` WHERE `email`=? AND verified='1'")) { + ps.setString(1, un); + GigiResultSet rs = ps.executeQuery(); + if (rs.next()) { + String dbHash = rs.getString(1); + String hash = PasswordHash.verifyHash(pw, dbHash); + if (hash != null) { + if ( !hash.equals(dbHash)) { + try (GigiPreparedStatement gps = new GigiPreparedStatement("UPDATE `users` SET `password`=? WHERE `email`=?")) { + gps.setString(1, hash); + gps.setString(2, un); + gps.executeUpdate(); + } + } + loginSession(req, User.getById(rs.getInt(2))); + req.getSession().setAttribute(LOGIN_METHOD, new TranslateCommand("Password")); + return; } - loginSession(req, User.getById(rs.getInt(2))); - req.getSession().setAttribute(LOGIN_METHOD, "Password"); } } - rs.close(); + throw new GigiApiException("Username and password didn't match."); } public static User getUser(HttpServletRequest req) { - return (User) req.getSession().getAttribute(USER); + AuthorizationContext ac = getAuthorizationContext(req); + if (ac == null) { + return null; + } + return ac.getActor(); + } + + public static AuthorizationContext getAuthorizationContext(HttpServletRequest req) { + return ((AuthorizationContext) req.getSession().getAttribute(AUTH_CONTEXT)); } private void tryAuthWithCertificate(HttpServletRequest req, X509Certificate x509Certificate) { @@ -126,23 +160,23 @@ public class LoginPage extends Page { loginSession(req, user); req.getSession().setAttribute(CERT_SERIAL, serial); req.getSession().setAttribute(CERT_ISSUER, x509Certificate.getIssuerDN()); - req.getSession().setAttribute(LOGIN_METHOD, "Certificate"); + req.getSession().setAttribute(LOGIN_METHOD, new TranslateCommand("Certificate")); } public static String extractSerialFormCert(X509Certificate x509Certificate) { - return x509Certificate.getSerialNumber().toString(16).toUpperCase(); + return x509Certificate.getSerialNumber().toString(16).toLowerCase(); } public static User fetchUserBySerial(String serial) { - GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT `memid` FROM `certs` WHERE `serial`=? AND `disablelogin`='0' AND `revoked` is NULL"); - ps.setString(1, serial); - GigiResultSet rs = ps.executeQuery(); - User user = null; - if (rs.next()) { - user = User.getById(rs.getInt(1)); + if ( !serial.matches("[a-f0-9]+")) { + throw new Error("serial malformed."); + } + + CertificateOwner o = CertificateOwner.getByEnabledSerial(serial); + if (o == null || !(o instanceof User)) { + return null; } - rs.close(); - return user; + return (User) o; } public static X509Certificate getCertificateFromRequest(HttpServletRequest req) { @@ -154,21 +188,22 @@ public class LoginPage extends Page { return uc; } - private static final Group LOGIN_BLOCKED = Group.getByString("blockedlogin"); + private static final Group LOGIN_BLOCKED = Group.BLOCKEDLOGIN; private void loginSession(HttpServletRequest req, User user) { if (user.isInGroup(LOGIN_BLOCKED)) { return; } + req.setAttribute(LOGIN_RETURNPATH, req.getSession().getAttribute(LOGIN_RETURNPATH)); req.getSession().invalidate(); HttpSession hs = req.getSession(); hs.setAttribute(LOGGEDIN, true); hs.setAttribute(Language.SESSION_ATTRIB_NAME, user.getPreferredLocale()); - hs.setAttribute(USER, user); + hs.setAttribute(AUTH_CONTEXT, new AuthorizationContext(user, user)); } @Override - public boolean isPermitted(User u) { - return u == null; + public boolean isPermitted(AuthorizationContext ac) { + return ac == null; } }