]> WPIA git - gigi.git/blob - src/org/cacert/gigi/ping/SSLPinger.java
Remove mains from "Domain pingers"
[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
31                                         .parseInt(parts[0])));
32                         if (parts.length == 2) {
33                                 switch (parts[1]) {
34                                         case "xmpp" :
35                                                 startXMPP(sch, false, domain);
36                                                 break;
37                                         case "server-xmpp" :
38                                                 startXMPP(sch, true, domain);
39                                                 break;
40                                         case "smtp" :
41                                                 startSMTP(sch);
42                                                 break;
43                                         case "imap" :
44                                                 startIMAP(sch);
45                                                 break;
46
47                                 }
48                         }
49                         test(sch, domain);
50                 } catch (IOException e) {
51                         e.printStackTrace();
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         private void startXMPP(SocketChannel sch, boolean server, String domain)
65                         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:"
70                                 + (server ? "server" : "client") + "\"" + " xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">")
71                                 .getBytes());
72                 os.flush();
73                 os.write("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>"
74                                 .getBytes());
75                 os.flush();
76                 scanFor(is, "<proceed");
77                 scanFor(is, ">");
78
79         }
80         private void scanFor(InputStream is, String scanFor) throws IOException {
81                 int pos = 0;
82                 while (pos < scanFor.length()) {
83                         if (is.read() == scanFor.charAt(pos)) {
84                                 pos++;
85                         } else {
86                                 pos = 0;
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         private void readSMTP(InputStream is) throws IOException {
105                 int counter = 0;
106                 boolean finish = true;
107                 while (true) {
108                         char c = (char) is.read();
109                         if (counter == 3) {
110                                 if (c == ' ') {
111                                         finish = true;
112                                 } else if (c == '-') {
113                                         finish = false;
114                                 } else {
115                                         throw new Error("Invalid smtp: " + c);
116                                 }
117                         }
118                         if (c == '\n') {
119                                 if (finish) {
120                                         return;
121                                 }
122                                 counter = 0;
123                         } else {
124                                 counter++;
125                         }
126                 }
127         }
128         private void test(SocketChannel sch, String domain) {
129                 try {
130                         SSLContext sc = SSLContext.getDefault();
131                         SSLEngine se = sc.createSSLEngine();
132                         ByteBuffer enc_in = ByteBuffer.allocate(se.getSession()
133                                         .getPacketBufferSize());
134                         ByteBuffer enc_out = ByteBuffer.allocate(se.getSession()
135                                         .getPacketBufferSize());
136                         ByteBuffer dec_in = ByteBuffer.allocate(se.getSession()
137                                         .getApplicationBufferSize());
138                         ByteBuffer dec_out = ByteBuffer.allocate(se.getSession()
139                                         .getApplicationBufferSize());
140                         se.setUseClientMode(true);
141                         SSLParameters sp = se.getSSLParameters();
142                         sp.setServerNames(Arrays.<SNIServerName> asList(new SNIHostName(
143                                         domain)));
144                         se.setSSLParameters(sp);
145                         se.beginHandshake();
146                         enc_in.limit(0);
147                         while (se.getHandshakeStatus() != HandshakeStatus.FINISHED
148                                         && se.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING) {
149                                 switch (se.getHandshakeStatus()) {
150                                         case NEED_WRAP :
151                                                 dec_out.limit(0);
152                                                 se.wrap(dec_out, enc_out);
153                                                 enc_out.flip();
154                                                 while (enc_out.remaining() > 0) {
155                                                         sch.write(enc_out);
156                                                 }
157                                                 enc_out.clear();
158                                                 break;
159                                         case NEED_UNWRAP :
160                                                 if (enc_in.remaining() == 0) {
161                                                         enc_in.clear();
162                                                         sch.read(enc_in);
163                                                         enc_in.flip();
164                                                 }
165                                                 while (se.unwrap(enc_in, dec_in).getStatus() == Status.BUFFER_UNDERFLOW) {
166                                                         enc_in.position(enc_in.limit());
167                                                         enc_in.limit(enc_in.capacity());
168                                                         sch.read(enc_in);
169                                                         enc_in.flip();
170                                                 }
171                                                 enc_in.compact();
172                                                 enc_in.flip();
173                                                 break;
174                                         case NEED_TASK :
175                                                 se.getDelegatedTask().run();
176                                                 break;
177                                         case NOT_HANDSHAKING :
178                                         case FINISHED :
179
180                                 }
181
182                         }
183                         System.out.println("completed");
184                         System.out.println(se.getSession().getCipherSuite());
185                         X509Certificate[] peerCertificateChain = se.getSession()
186                                         .getPeerCertificateChain();
187                         for (X509Certificate x509Certificate : peerCertificateChain) {
188                                 System.out.println(x509Certificate.getSubjectDN().getName());
189                         }
190                 } catch (NoSuchAlgorithmException e) {
191                         e.printStackTrace();
192                 } catch (SSLException e) {
193                         e.printStackTrace();
194                 } catch (IOException e) {
195                         e.printStackTrace();
196                 }
197         }
198 }