]> WPIA git - gigi.git/blobdiff - src/org/cacert/gigi/email/EmailProvider.java
upd: cleanup SQL statements to make them statically verifiable.
[gigi.git] / src / org / cacert / gigi / email / EmailProvider.java
index ea6679cd1a98e0c878173c13c35d770999eea427..a55a1c205259cb0a592e8c57446bda6edec4fa07 100644 (file)
@@ -22,6 +22,7 @@ import javax.net.ssl.SSLSocketFactory;
 import org.cacert.gigi.crypto.SMIME;
 import org.cacert.gigi.database.GigiPreparedStatement;
 import org.cacert.gigi.util.DNSUtil;
+import org.cacert.gigi.util.DomainAssessment;
 
 public abstract class EmailProvider {
 
@@ -40,8 +41,7 @@ public abstract class EmailProvider {
 
     protected final void sendSigned(String contents, PrintWriter output) throws IOException, GeneralSecurityException {
         if (k == null || c == null) {
-            output.println("Content-Transfer-Encoding: base64");
-            output.println();
+            output.print("Content-Transfer-Encoding: base64\r\n\r\n");
             output.print(contents);
         } else {
             SMIME.smime(contents, k, c, output);
@@ -71,10 +71,20 @@ public abstract class EmailProvider {
 
     public static final String FAIL = "FAIL";
 
-    public static final Pattern MAIL = Pattern.compile("^([a-zA-Z0-9])+([a-zA-Z0-9\\+\\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\\._-]+)+$");
+    private static final String MAIL_P_RFC_WORD = "[A-Za-z0-9\\+\\.!#$%&'*/=?^_`|~{}-]+";
+
+    private static final String MAIL_P_RFC_LOCAL = MAIL_P_RFC_WORD + "(?:\\." + MAIL_P_RFC_WORD + ")*";
+
+    private static final String MAIL_P_RFC_LABEL = "(?!(?!xn)..--|-)(?:[A-Za-z0-9-]+)(?<!-)";
+
+    private static final String MAIL_P_RFC_ADDRESS = MAIL_P_RFC_LOCAL + "@(?:" + MAIL_P_RFC_LABEL + "\\.)+" + MAIL_P_RFC_LABEL + "\\.?";
+
+    private static final Pattern MAIL_LOCAL = Pattern.compile("^" + MAIL_P_RFC_LOCAL + "$");
+
+    private static final Pattern MAIL_ADDRESS = Pattern.compile("^" + MAIL_P_RFC_ADDRESS + "$");
 
     public String checkEmailServer(int forUid, String address) throws IOException {
-        if (MAIL.matcher(address).matches()) {
+        if (isValidMailAddress(address)) {
             String[] parts = address.split("@", 2);
             String domain = parts[1];
 
@@ -151,11 +161,10 @@ public abstract class EmailProvider {
                         continue;
                     }
 
-                    try (GigiPreparedStatement statmt = new GigiPreparedStatement("INSERT INTO `emailPinglog` SET `when`=NOW(), `email`=?, `result`=?, `uid`=?, `type`='fast', `status`=?::`pingState`")) {
+                    try (GigiPreparedStatement statmt = new GigiPreparedStatement("INSERT INTO `emailPinglog` SET `when`=NOW(), `email`=?, `result`=?, `uid`=?, `type`='fast', `status`='success'::`pingState`")) {
                         statmt.setString(1, address);
                         statmt.setString(2, line);
                         statmt.setInt(3, forUid);
-                        statmt.setString(4, "success");
                         statmt.execute();
                     }
 
@@ -168,11 +177,10 @@ public abstract class EmailProvider {
 
             }
         }
-        try (GigiPreparedStatement statmt = new GigiPreparedStatement("INSERT INTO `emailPinglog` SET `when`=NOW(), `email`=?, `result`=?, `uid`=?, `type`='fast', `status`=?::`pingState`")) {
+        try (GigiPreparedStatement statmt = new GigiPreparedStatement("INSERT INTO `emailPinglog` SET `when`=NOW(), `email`=?, `result`=?, `uid`=?, `type`='fast'::`emailPingType`, `status`='failed'::`pingState`")) {
             statmt.setString(1, address);
             statmt.setString(2, "Failed to make a connection to the mail server");
             statmt.setInt(3, forUid);
-            statmt.setString(4, "failed");
             statmt.execute();
         }
         return FAIL;
@@ -190,4 +198,27 @@ public abstract class EmailProvider {
         });
     }
 
+    public static boolean isValidMailAddress(String address) {
+        if ( !MAIL_ADDRESS.matcher(address).matches()) {
+            return false;
+        }
+
+        String[] parts = address.split("@", 2);
+
+        String local = parts[0];
+        String domain = parts[1];
+
+        if ( !MAIL_LOCAL.matcher(local).matches()) {
+            return false;
+        }
+
+        for (String domainPart : domain.split("\\.", -1)) {
+            if ( !DomainAssessment.isValidDomainPart(domainPart)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
 }