1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.newsclub.net.unix.demo.ssl;
19
20 import java.io.File;
21 import java.io.FileDescriptor;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.io.PrintStream;
26 import java.nio.charset.Charset;
27 import java.nio.charset.StandardCharsets;
28 import java.security.GeneralSecurityException;
29 import java.util.Arrays;
30 import java.util.concurrent.TimeUnit;
31
32 import javax.net.ssl.SNIMatcher;
33 import javax.net.ssl.SSLSocket;
34 import javax.net.ssl.SSLSocketFactory;
35 import javax.security.auth.DestroyFailedException;
36
37 import org.newsclub.net.unix.AFSocket;
38 import org.newsclub.net.unix.AFUNIXSocket;
39 import org.newsclub.net.unix.AFUNIXSocketAddress;
40 import org.newsclub.net.unix.FileDescriptorCast;
41 import org.newsclub.net.unix.server.AFSocketServer;
42 import org.newsclub.net.unix.ssl.SNIHostnameCapture;
43 import org.newsclub.net.unix.ssl.SSLContextBuilder;
44
45
46
47
48
49
50
51
52 @SuppressWarnings("CatchAndPrintStackTrace" )
53 public class SSLDemoServer {
54 public static void main(String[] args) throws InterruptedException, IOException,
55 GeneralSecurityException, DestroyFailedException {
56
57
58
59
60 AFUNIXSocketAddress addr = AFUNIXSocketAddress.of(new File("/tmp/ssldemo"));
61
62 SSLSocketFactory serverSocketFactory = SSLContextBuilder.forServer()
63 .withKeyStore(new File("juxserver.p12"), () -> "serverpass".toCharArray())
64 .withTrustStore(new File("juxserver.truststore"), () -> "servertrustpass".toCharArray())
65 .withDefaultSSLParameters((p) -> {
66
67
68
69
70
71
72
73
74
75 })
76 .buildAndDestroyBuilder().getSocketFactory();
77
78 AFSocketServer<AFUNIXSocketAddress> server = new AFSocketServer<AFUNIXSocketAddress>(addr) {
79
80
81 final SNIMatcher sniHostnameMatcher = SNIHostnameCapture.ACCEPT_ANY_HOSTNAME;
82
83
84
85
86
87 @Override
88 protected void doServeSocket(AFSocket<? extends AFUNIXSocketAddress> plainSocket)
89 throws IOException {
90 try (SSLSocket sslSocket = (SSLSocket) serverSocketFactory.createSocket(plainSocket,
91
92 "localhost.junixsocket", plainSocket.getPort(),
93
94
95 false)) {
96
97
98
99
100 SNIHostnameCapture sniHostname = SNIHostnameCapture.configure(sslSocket,
101 sniHostnameMatcher);
102
103
104 plainSocket.setAncillaryReceiveBufferSize(1);
105
106 sslSocket.startHandshake();
107
108
109 try {
110 if (sniHostname.isComplete(1, TimeUnit.SECONDS)) {
111 System.out.println("Requested SNI hostname: " + sniHostname.getHostname());
112 }
113 } catch (InterruptedException e) {
114 e.printStackTrace();
115 }
116
117 try (InputStream in = sslSocket.getInputStream();
118 OutputStream out = sslSocket.getOutputStream();) {
119 System.out.println("Received byte: " + Integer.toHexString(in.read()));
120
121 System.out.println("Sending hello...");
122 out.write("Hello World".getBytes(StandardCharsets.UTF_8));
123
124 FileDescriptor[] fds = ((AFUNIXSocket) plainSocket).getReceivedFileDescriptors();
125 if (fds.length > 0) {
126 System.out.println("File descriptor received: " + Arrays.asList(fds));
127 System.out.println(
128 "Sending an extra message directly to a FileDescriptor of the other process...");
129 try (PrintStream ps = new PrintStream(FileDescriptorCast.using(fds[0]).as(
130 OutputStream.class), true, Charset.defaultCharset().name())) {
131 ps.println("Greetings from the server, right to your stderr");
132 }
133 }
134 }
135 }
136 }
137
138 @Override
139 protected void onServingException(AFSocket<? extends AFUNIXSocketAddress> socket,
140 Exception e) {
141 e.printStackTrace();
142 }
143 };
144 server.startAndWaitToBecomeReady();
145 }
146 }