Author: dbkr
Date: 2006-07-17 17:01:38 +0000 (Mon, 17 Jul 2006)
New Revision: 9645
Modified:
trunk/apps/Freemail/src/freemail/RTSFetcher.java
trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java
trunk/apps/Freemail/src/freemail/utils/ChainedAsymmetricBlockCipher.java
Log:
Work on processing RTS messages. Not done yet.
Modified: trunk/apps/Freemail/src/freemail/RTSFetcher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-17 14:44:49 UTC
(rev 9644)
+++ trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-17 17:01:38 UTC
(rev 9645)
@@ -3,8 +3,13 @@
import freemail.fcp.FCPConnection;
import freemail.fcp.HighLevelFCPClient;
import freemail.utils.DateStringFactory;
+import freemail.utils.PropsFile;
+import freemail.utils.ChainedAsymmetricBlockCipher;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.PrintStream;
@@ -17,7 +22,13 @@
import java.security.NoSuchAlgorithmException;
import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.crypto.params.RSAKeyParameters;
+import org.bouncycastle.crypto.AsymmetricBlockCipher;
+import org.bouncycastle.crypto.engines.RSAEngine;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+import freenet.support.io.LineReadingInputStream;
+
public class RTSFetcher {
private String rtskey;
private File contact_dir;
@@ -26,11 +37,16 @@
private static int PASSES_PER_DAY = 3;
private static int MAX_DAYS_BACK = 30;
private static String LOGFILE = "rtslog";
+ private static int RTS_MAX_SIZE = 2 * 1024 * 1024;
+ private File accdir;
+ private PropsFile accprops;
- RTSFetcher(String key, File ctdir) {
+ RTSFetcher(String key, File ctdir, File ad) {
this.rtskey = key;
this.sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z");
this.contact_dir = ctdir;
+ this.accdir = ad;
+ this.accprops = AccountManager.getAccountFile(this.accdir);
}
public void fetch() {
@@ -72,11 +88,164 @@
if (result != null) {
System.out.println(keybase+i+": got RTS!");
- log.incNextId(date);
- // TODO: handle the RTS!
+ // if we didn't successfully handle (or fatally
fail to handle) the RTS message, don't increment the id, so we'll get it again
in a bit
+ if (this.handle_rts(result)) {
+ log.incNextId(date);
+ }
+ result.delete();
} else {
System.out.println(keybase+i+": no RTS.");
}
}
}
+
+
+
+ private boolean handle_rts(File rtsmessage) {
+ // sanity check!
+ if (!rtsmessage.exists()) return false;
+
+ if (rtsmessage.length() > RTS_MAX_SIZE) {
+ System.out.println("RTS Message is too large -
discarding!");
+ return true;
+ }
+
+ // decrypt
+ byte[] plaintext;
+ try {
+ plaintext = decrypt_rts(rtsmessage);
+ } catch (IOException ioe) {
+ System.out.println("Error reading RTS message!");
+ return false;
+ } catch (InvalidCipherTextException icte) {
+ System.out.println("Could not decrypt RTS message -
discarding.");
+ return true;
+ }
+
+ File rtsfile;
+ byte[] sig;
+ int messagebytes = 0;
+ try {
+ rtsfile = File.createTempFile("rtstmp", "tmp",
Freemail.getTempDir());
+
+ ByteArrayInputStream bis = new
ByteArrayInputStream(plaintext);
+ LineReadingInputStream lis = new
LineReadingInputStream(bis);
+ PrintStream ps = new PrintStream(new
FileOutputStream(rtsfile));
+
+ String line;
+ while (true) {
+ line = lis.readLine(200, 200);
+ messagebytes += lis.getLastBytesRead();
+
+ if (line == null || line.equals("")) break;
+
+ ps.println(line);
+ }
+
+ ps.close();
+
+ if (line == null) {
+ // that's not right, we shouldn't have reached
the end of the file, just the blank line before the signature
+
+ System.out.println("Couldn't find signature on
RTS message - ignoring!");
+ return true;
+ }
+
+ sig = new byte[bis.available()];
+
+ int read = 0;
+ while (true) {
+ read = bis.read(sig, 0, bis.available());
+ if (read == 0) break;
+ }
+ bis.close();
+ } catch (IOException ioe) {
+ System.out.println("IO error whilst handling RTS
message. "+ioe.getMessage());
+ ioe.printStackTrace();
+ return false;
+ }
+
+ PropsFile rtsprops = new PropsFile(rtsfile);
+
+ try {
+ validate_rts(rtsprops);
+ } catch (Exception e) {
+ System.out.println("RTS message does not contain vital
information: "+e.getMessage()+" - discarding");
+ return true;
+ }
+
+ // verify the signature
+ String their_mailsite = rtsprops.get("mailsite");
+
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException alge) {
+ System.out.println("No MD5 implementation available -
sorry, Freemail cannot work!");
+ return false;
+ }
+ md.update(plaintext, 0, messagebytes);
+ byte[] our_hash = md.digest();
+
+ HighLevelFCPClient fcpcli = new HighLevelFCPClient();
+ fcpcli.fetch(their_mailsite);
+
+ // TODO: finish.
+
+ // verify the message is for us
+
+ // create the inbound contact
+
+ // move the props file to the right place
+
+ return true;
+ }
+
+ private byte[] decrypt_rts(File rtsmessage) throws IOException,
InvalidCipherTextException {
+ byte[] ciphertext = new byte[(int)rtsmessage.length()];
+ FileInputStream fis = new FileInputStream(rtsmessage);
+ int read = 0;
+ while (read < rtsmessage.length()) {
+ read += fis.read(ciphertext, read,
(int)rtsmessage.length() - read);
+ }
+
+ RSAKeyParameters ourprivkey =
AccountManager.getPrivateKey(this.accdir);
+
+ // decrypt it
+ AsymmetricBlockCipher deccipher = new RSAEngine();
+ deccipher.init(false, ourprivkey);
+ byte[] plaintext =
ChainedAsymmetricBlockCipher.decrypt(deccipher, ciphertext);
+
+ return plaintext;
+ }
+
+ /*
+ * Make sure an RTS file has all the right properties in it
+ * If any are missing, throw an exception which says which are missing
+ */
+ private void validate_rts(PropsFile rts) throws Exception {
+ StringBuffer missing = new StringBuffer();
+
+ if (rts.get("commssk") == null) {
+ missing.append("commssk");
+ }
+ if (rts.get("ackssk") == null) {
+ missing.append("ackssk");
+ }
+ if (rts.get("messagetype") == null) {
+ missing.append("messagetype");
+ }
+ if (rts.get("to") == null) {
+ missing.append("to");
+ }
+ if (rts.get("mailsite") == null) {
+ missing.append("mailsite");
+ }
+ if (rts.get("ctsssk") == null) {
+ missing.append("ctsssk");
+ }
+
+ if (missing.length() == 0) return;
+ throw new Exception(missing.toString());
+ }
}
Modified: trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java 2006-07-17
14:44:49 UTC (rev 9644)
+++ trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java 2006-07-17
17:01:38 UTC (rev 9645)
@@ -36,7 +36,7 @@
this.nf = null;
}
- this.rtsf = new RTSFetcher("KSK@"+accprops.get("rtskey")+"-",
inbound_dir);
+ this.rtsf = new RTSFetcher("KSK@"+accprops.get("rtskey")+"-",
inbound_dir, accdir);
//this.mf = new MailFetcher(this.mb, inbound_dir,
Freemail.getFCPConnection());
}
Modified:
trunk/apps/Freemail/src/freemail/utils/ChainedAsymmetricBlockCipher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/utils/ChainedAsymmetricBlockCipher.java
2006-07-17 14:44:49 UTC (rev 9644)
+++ trunk/apps/Freemail/src/freemail/utils/ChainedAsymmetricBlockCipher.java
2006-07-17 17:01:38 UTC (rev 9645)
@@ -32,4 +32,8 @@
return bos.toByteArray();
}
+
+ public static byte[] decrypt(AsymmetricBlockCipher cipher, byte[] in)
throws InvalidCipherTextException {
+ return ChainedAsymmetricBlockCipher.encrypt(cipher, in);
+ }
}