]> WPIA git - gigi.git/blobdiff - src/org/cacert/gigi/pages/LoginPage.java
Merge "Update notes about password security"
[gigi.git] / src / org / cacert / gigi / pages / LoginPage.java
index d25eacfb43bc0036aa4a8ae7c6fe9070a980b55f..141c6ca18cc6466ffae0248458347b10511228f7 100644 (file)
@@ -13,18 +13,24 @@ 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.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) {
@@ -33,6 +39,10 @@ public class LoginPage extends Page {
 
         @Override
         public boolean submit(PrintWriter out, HttpServletRequest req) throws GigiApiException {
+            if (RegisterPage.RATE_LIMIT.isLimitExceeded(req.getRemoteAddr())) {
+                outputError(out, req, "Rate Limit Exceeded");
+                return false;
+            }
             tryAuthWithUnpw(req);
             return false;
         }
@@ -46,13 +56,17 @@ 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<String, Object>());
+        if (req.getHeader("Host").equals(ServerConstants.getSecureHostNamePort())) {
+            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<String, Object>());
+        }
     }
 
     @Override
@@ -94,24 +108,25 @@ public class LoginPage extends Page {
     private void tryAuthWithUnpw(HttpServletRequest req) {
         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"));
                 }
-                loginSession(req, User.getById(rs.getInt(2)));
-                req.getSession().setAttribute(LOGIN_METHOD, "Password");
             }
         }
-        rs.close();
     }
 
     public static User getUser(HttpServletRequest req) {
@@ -135,7 +150,7 @@ 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) {
@@ -146,17 +161,12 @@ public class LoginPage extends Page {
         if ( !serial.matches("[A-Fa-f0-9]+")) {
             throw new Error("serial malformed.");
         }
-        GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT `memid` FROM `certs` WHERE `serial`=? AND `disablelogin`='0' AND `revoked` is NULL");
-        ps.setString(1, serial.toLowerCase());
-        GigiResultSet rs = ps.executeQuery();
-        User user = null;
-        if (rs.next()) {
-            user = User.getById(rs.getInt(1));
-        } else {
-            System.out.println("User with serial " + serial + " not found.");
+
+        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) {
@@ -182,7 +192,7 @@ public class LoginPage extends Page {
     }
 
     @Override
-    public boolean isPermitted(User u) {
-        return u == null;
+    public boolean isPermitted(AuthorizationContext ac) {
+        return ac == null;
     }
 }