]> WPIA git - gigi.git/blob - src/org/cacert/gigi/ping/SSLPinger.java
[EMPTY] Formatting with configured formatter.
[gigi.git] / src / org / cacert / gigi / ping / SSLPinger.java
1 package org.cacert.gigi.ping;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.OutputStream;
6 import java.net.InetSocketAddress;
7 import java.net.Socket;
8 import java.nio.ByteBuffer;
9 import java.nio.channels.SocketChannel;
10 import java.security.NoSuchAlgorithmException;
11 import java.util.Arrays;
12
13 import javax.net.ssl.SNIHostName;
14 import javax.net.ssl.SNIServerName;
15 import javax.net.ssl.SSLContext;
16 import javax.net.ssl.SSLEngine;
17 import javax.net.ssl.SSLEngineResult.Status;
18 import javax.net.ssl.SSLException;
19 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
20 import javax.net.ssl.SSLParameters;
21 import javax.security.cert.X509Certificate;
22
23 public class SSLPinger extends DomainPinger {
24
25         @Override
26         public void ping(String domain, String configuration, String expToken) {
27                 try {
28                         SocketChannel sch = SocketChannel.open();
29                         String[] parts = configuration.split(":", 2);
30                         sch.connect(new InetSocketAddress(domain, Integer.parseInt(parts[0])));
31                         if (parts.length == 2) {
32                                 switch (parts[1]) {
33                                 case "xmpp":
34                                         startXMPP(sch, false, domain);
35                                         break;
36                                 case "server-xmpp":
37                                         startXMPP(sch, true, domain);
38                                         break;
39                                 case "smtp":
40                                         startSMTP(sch);
41                                         break;
42                                 case "imap":
43                                         startIMAP(sch);
44                                         break;
45
46                                 }
47                         }
48                         test(sch, domain);
49                 } catch (IOException e) {
50                         e.printStackTrace();
51                 }
52
53         }
54
55         private void startIMAP(SocketChannel sch) throws IOException {
56                 Socket s = sch.socket();
57                 InputStream is = s.getInputStream();
58                 OutputStream os = s.getOutputStream();
59                 scanFor(is, "\n");
60                 os.write("ENABLE STARTTLS\r\n".getBytes());
61                 os.flush();
62                 scanFor(is, "\n");
63         }
64
65         private void startXMPP(SocketChannel sch, boolean server, String domain) throws IOException {
66                 Socket s = sch.socket();
67                 InputStream is = s.getInputStream();
68                 OutputStream os = s.getOutputStream();
69                 os.write(("<stream:stream to=\"" + domain + "\" xmlns=\"jabber:" + (server ? "server" : "client") + "\"" + " xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">")
70                         .getBytes());
71                 os.flush();
72                 os.write("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>".getBytes());
73                 os.flush();
74                 scanFor(is, "<proceed");
75                 scanFor(is, ">");
76
77         }
78
79         private void scanFor(InputStream is, String scanFor) throws IOException {
80                 int pos = 0;
81                 while (pos < scanFor.length()) {
82                         if (is.read() == scanFor.charAt(pos)) {
83                                 pos++;
84                         } else {
85                                 pos = 0;
86                         }
87                 }
88         }
89
90         private void startSMTP(SocketChannel sch) throws IOException {
91                 Socket s = sch.socket();
92                 InputStream is = s.getInputStream();
93                 readSMTP(is);
94                 s.getOutputStream().write("EHLO ssl.pinger\r\n".getBytes());
95                 s.getOutputStream().flush();
96                 readSMTP(is);
97                 s.getOutputStream().write("HELP\r\n".getBytes());
98                 s.getOutputStream().flush();
99                 readSMTP(is);
100                 s.getOutputStream().write("STARTTLS\r\n".getBytes());
101                 s.getOutputStream().flush();
102                 readSMTP(is);
103         }
104
105         private void readSMTP(InputStream is) throws IOException {
106                 int counter = 0;
107                 boolean finish = true;
108                 while (true) {
109                         char c = (char) is.read();
110                         if (counter == 3) {
111                                 if (c == ' ') {
112                                         finish = true;
113                                 } else if (c == '-') {
114                                         finish = false;
115                                 } else {
116                                         throw new Error("Invalid smtp: " + c);
117                                 }
118                         }
119                         if (c == '\n') {
120                                 if (finish) {
121                                         return;
122                                 }
123                                 counter = 0;
124                         } else {
125                                 counter++;
126                         }
127                 }
128         }
129
130         private void test(SocketChannel sch, String domain) {
131                 try {
132                         SSLContext sc = SSLContext.getDefault();
133                         SSLEngine se = sc.createSSLEngine();
134                         ByteBuffer enc_in = ByteBuffer.allocate(se.getSession().getPacketBufferSize());
135                         ByteBuffer enc_out = ByteBuffer.allocate(se.getSession().getPacketBufferSize());
136                         ByteBuffer dec_in = ByteBuffer.allocate(se.getSession().getApplicationBufferSize());
137                         ByteBuffer dec_out = ByteBuffer.allocate(se.getSession().getApplicationBufferSize());
138                         se.setUseClientMode(true);
139                         SSLParameters sp = se.getSSLParameters();
140                         sp.setServerNames(Arrays.<SNIServerName> asList(new SNIHostName(domain)));
141                         se.setSSLParameters(sp);
142                         se.beginHandshake();
143                         enc_in.limit(0);
144                         while (se.getHandshakeStatus() != HandshakeStatus.FINISHED
145                                 && se.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING) {
146                                 switch (se.getHandshakeStatus()) {
147                                 case NEED_WRAP:
148                                         dec_out.limit(0);
149                                         se.wrap(dec_out, enc_out);
150                                         enc_out.flip();
151                                         while (enc_out.remaining() > 0) {
152                                                 sch.write(enc_out);
153                                         }
154                                         enc_out.clear();
155                                         break;
156                                 case NEED_UNWRAP:
157                                         if (enc_in.remaining() == 0) {
158                                                 enc_in.clear();
159                                                 sch.read(enc_in);
160                                                 enc_in.flip();
161                                         }
162                                         while (se.unwrap(enc_in, dec_in).getStatus() == Status.BUFFER_UNDERFLOW) {
163                                                 enc_in.position(enc_in.limit());
164                                                 enc_in.limit(enc_in.capacity());
165                                                 sch.read(enc_in);
166                                                 enc_in.flip();
167                                         }
168                                         enc_in.compact();
169                                         enc_in.flip();
170                                         break;
171                                 case NEED_TASK:
172                                         se.getDelegatedTask().run();
173                                         break;
174                                 case NOT_HANDSHAKING:
175                                 case FINISHED:
176
177                                 }
178
179                         }
180                         System.out.println("completed");
181                         System.out.println(se.getSession().getCipherSuite());
182                         X509Certificate[] peerCertificateChain = se.getSession().getPeerCertificateChain();
183                         for (X509Certificate x509Certificate : peerCertificateChain) {
184                                 System.out.println(x509Certificate.getSubjectDN().getName());
185                         }
186                 } catch (NoSuchAlgorithmException e) {
187                         e.printStackTrace();
188                 } catch (SSLException e) {
189                         e.printStackTrace();
190                 } catch (IOException e) {
191                         e.printStackTrace();
192                 }
193         }
194 }