summaryrefslogtreecommitdiff
path: root/src/org/noreply/fancydress/type3/mmtp/MMTP.java
blob: 63f1f6f14d9c615bc9ad5fe16386281ed0c57b78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/* $Id$ */
package org.noreply.fancydress.type3.mmtp;

import org.noreply.fancydress.type3.routing.*;
import org.noreply.fancydress.type3.*;
import org.noreply.fancydress.crypto.*;
import org.noreply.fancydress.misc.*;
import org.noreply.fancydress.status.*;
import javax.net.ssl.*;
import java.net.*;
import java.io.*;
import java.util.*;
import java.security.*;

public class MMTP {
	static final String TLS_PROTO = "TLSv1";
	static final String SSL_PROTO = "SSLv3";
	static final String TLS_DHE_RSA_WITH_AES_128_CBC_SHA = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
	static final String SSL3_RSA_DES_192_CBC3_SHA = "SSL_RSA_WITH_3DES_EDE_CBC_SHA";

	public static void send(Packet packet) throws Exception {
		byte[] hash = CryptoPrimitives.hash(packet.asOctets(), Util.toOctets("SEND"));
		byte[] ackExpected = Util.concat( Util.toOctets("RECEIVED\r\n"),
				                  CryptoPrimitives.hash(packet.asOctets(), Util.toOctets("RECEIVED")));
		byte[] ackRead = new byte[30];
		MMTPTrustManager trustManager = new MMTPTrustManager(packet.getRoute().getKeyID());
		TrustManager[] trustManagers = { trustManager };
		SSLContext context = SSLContext.getInstance("TLS");
		context.init(null, trustManagers, null);

		SSLSocketFactory socketFactory = context.getSocketFactory();
		SSLSocket socket = (SSLSocket) socketFactory.createSocket("127.0.0.1", 48099);


		String[] supportedProtocols = socket.getSupportedProtocols();
		boolean haveTLSv1 = false;
		boolean haveSSLv3 = false;
		for (int i=0; i<supportedProtocols.length; i++) {
			if (supportedProtocols[i].equals(TLS_PROTO))
				haveTLSv1 = true;
			else if (supportedProtocols[i].equals(SSL_PROTO))
				haveSSLv3 = true;
		}

		String[] supportedCipherSuits = socket.getSupportedCipherSuites();
		boolean acceptableFound = false;
		for (int i=0; i<supportedCipherSuits.length; i++) {
			if (haveTLSv1 && supportedCipherSuits[i].equals(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)) {
				socket.setEnabledProtocols( new String[] { TLS_PROTO } );
				socket.setEnabledCipherSuites( new String[] { TLS_DHE_RSA_WITH_AES_128_CBC_SHA } );
				acceptableFound = true;
				break;
			} else if (haveSSLv3 && supportedCipherSuits[i].equals(SSL3_RSA_DES_192_CBC3_SHA)) {
				socket.setEnabledProtocols( new String[] { SSL_PROTO } );
				socket.setEnabledCipherSuites( new String[] { SSL3_RSA_DES_192_CBC3_SHA } );
				acceptableFound = true;
				break;
			}
		}

		if (!acceptableFound)
			throw new Mix3Exception("Did not found an acceptable Cipher Suit.");

		socket.startHandshake();
		OutputStream out = socket.getOutputStream();
		InputStream in = socket.getInputStream();

		out.write(Util.toOctets("MMTP 0.3\r\n"));
		out.flush();
		byte[] foo = new byte[10];
		int got = in.read(foo, 0, foo.length);
		if ((got != 10) || (!Util.equal(foo, Util.toOctets("MMTP 0.3\r\n")))) { // FIXME
			in.close();
			socket.close();
			throw new IOException("Do not agree on MMTP version.");
		}
		out.write(Util.toOctets("SEND\r\n"));
		out.write(packet.asOctets());
		out.write(hash);
		out.flush();
		got = in.read(ackRead, 0, ackRead.length);
		in.close();
		out.close();
		socket.close();

		if ((got != ackExpected.length) ||
		    (!Util.equal(ackRead, ackExpected)))
			throw new Mix3Exception("got no valid ACK from server.");
	}
}