/* SimpleThreadedServer.java * * Copyright (C) 2006-2025 wolfSSL Inc. * * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * wolfSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ import java.io.*; import java.net.*; import java.nio.*; import java.util.*; import com.wolfssl.WolfSSL; import com.wolfssl.WolfSSLSession; import com.wolfssl.WolfSSLContext; import com.wolfssl.WolfSSLCertificate; import com.wolfssl.WolfSSLException; import com.wolfssl.WolfSSLJNIException; /** * Simple SSL/TLS server that uses wolfSSL JNI (not JSSE). * The server listens for client connections at localhost:11111 and * handles each client in a separate thread as they come in. * * This is meant to be a very simple example and does not currently offer * much customization. It uses the hard-coded certs and keys found below, * and creates the WolfSSLContext using SSLv23_ServerMethod(). */ public class SimpleThreadedServer { public static void main(String[] args) { new SimpleThreadedServer().run(args); } public void run(String[] args) { int ret = 0; int serverPort = 11111; Socket clientSocket = null; ServerSocket serverSocket = null; /* Cert and Key info */ String serverCert = "../certs/server-cert.pem"; String serverKey = "../certs/server-key.pem"; String caCert = "../certs/client-cert.pem"; String crlPemDir = "../certs/crl"; String dhParam = "../certs/dh2048.pem"; try { /* Load JNI library */ WolfSSL.loadLibrary(); /* Init library */ WolfSSL sslLib = new WolfSSL(); /* Create context */ WolfSSLContext sslCtx = new WolfSSLContext( WolfSSL.SSLv23_ServerMethod()); /* Load certificate/key files */ ret = sslCtx.useCertificateChainFile(serverCert); if (ret != WolfSSL.SSL_SUCCESS) { System.out.println("failed to load server certificate!"); System.exit(1); } ret = sslCtx.usePrivateKeyFile(serverKey, WolfSSL.SSL_FILETYPE_PEM); if (ret != WolfSSL.SSL_SUCCESS) { System.out.println("failed to load server private key!"); System.exit(1); } /* Set verify callback */ ret = sslCtx.loadVerifyLocations(caCert, null); if (ret != WolfSSL.SSL_SUCCESS) { System.out.println("failed to load CA certificates!"); System.exit(1); } /* Create server socket */ serverSocket = new ServerSocket(serverPort); System.out.println("Started server at " + InetAddress.getLocalHost() + ", port " + serverPort); /* Wait for new client connections, process each in new thread */ while (true) { clientSocket = serverSocket.accept(); System.out.println("client connection received from " + clientSocket.getInetAddress().getHostAddress() + " at port " + clientSocket.getLocalPort() + "\n"); ClientHandler client = new ClientHandler(clientSocket, sslCtx); client.start(); } } catch (UnsatisfiedLinkError | WolfSSLException | IOException e) { e.printStackTrace(); } finally { try { if (serverSocket != null) { serverSocket.close(); } } catch (IOException e) { e.printStackTrace(); } } } /* end run() */ class ClientHandler extends Thread { int ret = 0; int insz = 0; int err = 0; Socket clientSocket; WolfSSLContext sslCtx; String msg = "I hear you fa shizzle, from Java!"; byte[] input = new byte[80]; public ClientHandler(Socket s, WolfSSLContext ctx) { clientSocket = s; sslCtx = ctx; } public void run() { WolfSSLSession ssl = null; DataOutputStream outstream = null; DataInputStream instream = null; try { /* Get input and output streams */ outstream = new DataOutputStream( clientSocket.getOutputStream()); instream = new DataInputStream( clientSocket.getInputStream()); /* Create SSL object */ ssl = new WolfSSLSession(sslCtx); /* Pass socket fd to wolfSSL */ ret = ssl.setFd(clientSocket); if (ret != WolfSSL.SSL_SUCCESS) { throw new RuntimeException("Failed to set file descriptor"); } do { ret = ssl.accept(); err = ssl.getError(ret); } while (ret != WolfSSL.SSL_SUCCESS && (err == WolfSSL.SSL_ERROR_WANT_READ || err == WolfSSL.SSL_ERROR_WANT_WRITE)); if (ret != WolfSSL.SSL_SUCCESS) { err = ssl.getError(ret); String errString = WolfSSL.getErrorString(err); throw new RuntimeException( "wolfSSL_accept failed. err = " + err + ", " + errString); } /* Show peer info */ showPeer(ssl); /* Read client response, and echo */ do { insz = ssl.read(input, input.length); err = ssl.getError(0); } while (insz < 0 && (err == WolfSSL.SSL_ERROR_WANT_READ || err == WolfSSL.SSL_ERROR_WANT_WRITE)); if (input.length > 0) { String cliMsg = new String(input, 0, insz); System.out.println("client says: " + cliMsg); } else { throw new RuntimeException("read failed"); } do { ret = ssl.write(msg.getBytes(), msg.length()); err = ssl.getError(0); } while (ret < 0 && (err == WolfSSL.SSL_ERROR_WANT_READ || err == WolfSSL.SSL_ERROR_WANT_WRITE)); if (ret != msg.length()) { throw new RuntimeException("ssl.write() failed"); } ssl.shutdownSSL(); } catch (WolfSSLException | IOException e) { e.printStackTrace(); } finally { if (ssl != null) { try { ssl.freeSSL(); } catch (WolfSSLJNIException e) { e.printStackTrace(); } } } } } void showPeer(WolfSSLSession ssl) { String altname; long peerCrtPtr = 0; try { System.out.println("TLS version is " + ssl.getVersion()); System.out.println("TLS cipher suite is " + ssl.cipherGetName()); peerCrtPtr = ssl.getPeerCertificate(); if (peerCrtPtr != 0) { System.out.println( "issuer : " + ssl.getPeerX509Issuer(peerCrtPtr)); System.out.println( "subject : " + ssl.getPeerX509Subject(peerCrtPtr)); while((altname = ssl.getPeerX509AltName(peerCrtPtr)) != null) { System.out.println("altname = " + altname); } } } catch (WolfSSLJNIException e) { e.printStackTrace(); } finally { if (WolfSSL.getLibVersionHex() >= 0x05003000) { if (peerCrtPtr != 0) { WolfSSLCertificate.freeX509(peerCrtPtr); } } } } } /* end Server */