mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-28 21:28:55 +00:00
385 lines
9.9 KiB
Java
385 lines
9.9 KiB
Java
/*
|
|
* The contents of this file are subject to the Mozilla Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is the Netscape Security Services for Java.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998-2000 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the
|
|
* terms of the GNU General Public License Version 2 or later (the
|
|
* "GPL"), in which case the provisions of the GPL are applicable
|
|
* instead of those above. If you wish to allow use of your
|
|
* version of this file only under the terms of the GPL and not to
|
|
* allow others to use your version of this file under the MPL,
|
|
* indicate your decision by deleting the provisions above and
|
|
* replace them with the notice and other provisions required by
|
|
* the GPL. If you do not delete the provisions above, a recipient
|
|
* may use your version of this file under either the MPL or the
|
|
* GPL.
|
|
*/
|
|
|
|
// THIS FILE NEEDS CLEANING UP
|
|
|
|
// This program demonstrates SSL server-side support. It expects
|
|
// (HTTP) clients to connect to it, and will respond to HTTP
|
|
// GET requests
|
|
//
|
|
|
|
// tabstops: 4
|
|
|
|
import org.mozilla.jss.ssl.*;
|
|
|
|
import java.io.*;
|
|
import java.util.*;
|
|
import org.mozilla.jss.*;
|
|
|
|
/**
|
|
* Parameters supported by this socket test:
|
|
*
|
|
* filename file to be read from https server (default: /index.html)
|
|
* port port to connect to (default: 443)
|
|
* clientauth do client-auth or not (default: no client-auth)
|
|
*
|
|
* The following parameters are used for regression testing, so
|
|
* we can print success or failure of the test.
|
|
*
|
|
* filesize size of file to be read
|
|
* status security status of connection - this has to be an integer
|
|
*
|
|
*/
|
|
|
|
public class SSLServer
|
|
{
|
|
boolean handshakeEventHappened = false;
|
|
boolean doClientAuth = false;
|
|
Hashtable args;
|
|
PrintStream results;
|
|
String versionStr;
|
|
|
|
String argNames[] = {
|
|
"filename",
|
|
"port",
|
|
"filesize",
|
|
"clientauth",
|
|
"nickname"
|
|
};
|
|
|
|
String values[] = {
|
|
"data1k.txt", // filename
|
|
"2929", // port
|
|
"1024", // filesize
|
|
"true", // request client auth
|
|
"Server-Cert cert-meatpie" // nickname of cert to use
|
|
};
|
|
|
|
private static String htmlHeader = "SSL Server Tester";
|
|
private static String htmlTail = "\n";
|
|
|
|
/* simple helper functions */
|
|
private boolean isInvalid(String s) {
|
|
return (s == null) || s.equals("");
|
|
}
|
|
|
|
private String getArgument(String key) {
|
|
return (String) args.get(key);
|
|
}
|
|
|
|
String okay = "okay";
|
|
String failed = "FAILED";
|
|
|
|
/*
|
|
* return "okay" or "FAILED" based on equality of
|
|
* the argument strings
|
|
*/
|
|
private String cmp(String s1, String s2) {
|
|
if(s1 == s2) return okay;
|
|
if(s1 == null) return failed;
|
|
if(s1.equals(s2)) return okay;
|
|
return failed;
|
|
}
|
|
|
|
private String cmp(String s1, int s2) {
|
|
return cmp(s1, new Integer(s2).toString());
|
|
}
|
|
|
|
|
|
public void run()
|
|
{
|
|
try {
|
|
SSLServerSocket l;
|
|
SSLSocket s;
|
|
int port;
|
|
String tmpStr;
|
|
String portStr;
|
|
String nickname;
|
|
|
|
results.println(htmlHeader);
|
|
|
|
portStr = getArgument("port");
|
|
if(isInvalid(portStr)) {
|
|
port = 2929;
|
|
} else {
|
|
port = Integer.valueOf(portStr).intValue();
|
|
}
|
|
|
|
results.println("here");
|
|
tmpStr = getArgument("clientauth");
|
|
if(!isInvalid(tmpStr)) {
|
|
tmpStr = tmpStr.toLowerCase();
|
|
doClientAuth = !(tmpStr.equals("off") ||
|
|
tmpStr.equals("false") ||
|
|
tmpStr.equals("0"));
|
|
}
|
|
|
|
l = new SSLServerSocket(port);
|
|
results.println("Listening " + l.toString());
|
|
|
|
// select the server's cert/key
|
|
nickname = getArgument("nickname");
|
|
results.println("Getting Cert:"+nickname+"");
|
|
l.setServerCertNickname(nickname);
|
|
|
|
if (doClientAuth) {
|
|
l.setNeedClientAuth(true);
|
|
}
|
|
|
|
// wait for and accept a connection.
|
|
s = (SSLSocket)l.accept();
|
|
results.println("Accepted.");
|
|
|
|
handleConnection(s);
|
|
// handleConnection will close s, as appropriate.
|
|
s = null;
|
|
|
|
l.close();
|
|
l = null;
|
|
|
|
} catch(Exception e) {
|
|
results.println("***** TEST FAILED *****");
|
|
e.printStackTrace(results);
|
|
results.println(
|
|
"If there is no stack trace, try disabling the JIT and trying again.");
|
|
}
|
|
results.println("END OF TEST");
|
|
}
|
|
|
|
public void handleConnection(SSLSocket s) throws Exception
|
|
{
|
|
SSLHandshakeCompletedListener listener = null;
|
|
|
|
listener = new ServerHandshakeCB(this);
|
|
s.addHandshakeCompletedListener(listener);
|
|
|
|
results.println("Connected to " + s.toString());
|
|
|
|
InputStream in = s.getInputStream();
|
|
byte[] bytes = new byte[4096];
|
|
int totalBytes = 0;
|
|
int numReads = 0;
|
|
|
|
// now try to read data from the SSL connection
|
|
try {
|
|
boolean endFound = false;
|
|
while(! endFound && totalBytes < bytes.length) {
|
|
results.println("Calling Read.");
|
|
int n = in.read(bytes, totalBytes,
|
|
bytes.length - totalBytes);
|
|
if(n == -1) {
|
|
results.println("EOF found.");
|
|
break;
|
|
}
|
|
|
|
if(n == 0) {
|
|
results.println("Zero bytes read?");
|
|
break;
|
|
}
|
|
numReads++;
|
|
|
|
results.println("Read " + n + " bytes of data");
|
|
totalBytes += n;
|
|
for (int i = 0; i + 3 < bytes.length; ++i) {
|
|
if (bytes[i] == 0x0D &&
|
|
bytes[i+1] == 0x0A &&
|
|
bytes[i+2] == 0x0D &&
|
|
bytes[i+3] == 0x0A )
|
|
{
|
|
results.println("Empty line found.");
|
|
endFound = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} catch (IOException e) {
|
|
results.println(
|
|
"IOException while reading from pipe? Actually got " +
|
|
totalBytes + " bytes total");
|
|
e.printStackTrace(results);
|
|
results.println("");
|
|
throw e;
|
|
}
|
|
|
|
results.println("Number of read() calls: " + numReads );
|
|
results.println("Total bytes read: " + totalBytes );
|
|
String msg = null;
|
|
|
|
if (totalBytes > 0) {
|
|
msg = new String(bytes, 0, totalBytes, "8859_1");
|
|
results.println("Request received:");
|
|
results.println(msg);
|
|
results.println("");
|
|
}
|
|
|
|
|
|
SSLSecurityStatus status = s.getStatus();
|
|
results.println("Security status of session:");
|
|
results.println(status.toString());
|
|
|
|
results.println("Handshake callback event happened: " +
|
|
((handshakeEventHappened) ? okay : failed));
|
|
|
|
OutputStream os = s.getOutputStream();
|
|
PrintOutputStreamWriter out = new PrintOutputStreamWriter(os);
|
|
os = null; // don't keep this reference lying around
|
|
|
|
String reply = "HTTP/1.0 200 OK\r\n" +
|
|
"Server: Netscape-Enterprise/2.0a\r\n" +
|
|
"Date: Tue, 01 Apr 1998 22:10:05 GMT\r\n" +
|
|
"Content-type: text/plain\r\n" +
|
|
"\r\n" +
|
|
msg;
|
|
out.println(reply);
|
|
|
|
// Got here, so no exception thrown above.
|
|
// Try to clean up.
|
|
in.close();
|
|
in = null;
|
|
|
|
if (listener != null) {
|
|
s.removeHandshakeCompletedListener(listener);
|
|
listener = null;
|
|
}
|
|
|
|
out.close();
|
|
out = null;
|
|
|
|
s.close();
|
|
s = null;
|
|
}
|
|
|
|
/**
|
|
* given an input string, convert less-than, greater-than, and ampersand
|
|
* from raw characters to escaped characters
|
|
* (< becomes `&lt;', etc.)
|
|
*/
|
|
private String escapeHTML(String s)
|
|
{
|
|
StringBuffer result = new StringBuffer();
|
|
|
|
// this is inefficient, but I don't care
|
|
for(int i=0; i<s.length(); i++) {
|
|
char c = s.charAt(i);
|
|
switch(c) {
|
|
case '<': result.append("<"); break;
|
|
case '>': result.append(">"); break;
|
|
case '&': result.append("&"); break;
|
|
default: result.append(c); break;
|
|
}
|
|
}
|
|
|
|
return result.toString();
|
|
}
|
|
|
|
public SSLServer( PrintStream ps, String verStr)
|
|
{
|
|
this.args = new Hashtable();
|
|
this.results = ps;
|
|
this.versionStr = verStr;
|
|
|
|
for(int i=0; i<argNames.length; i++) {
|
|
String value = values[i];
|
|
if(value != null)
|
|
this.args.put(argNames[i], value);
|
|
}
|
|
}
|
|
|
|
static final int cipherSuites[] = {
|
|
SSLSocket.SSL3_RSA_WITH_RC4_128_MD5,
|
|
SSLSocket.SSL3_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
SSLSocket.SSL3_RSA_WITH_DES_CBC_SHA,
|
|
SSLSocket.SSL3_RSA_EXPORT_WITH_RC4_40_MD5,
|
|
SSLSocket.SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
|
|
SSLSocket.SSL3_RSA_WITH_NULL_MD5,
|
|
0
|
|
};
|
|
|
|
public static void main(String argv[])
|
|
{
|
|
int i;
|
|
|
|
System.out.println("SSLServer started\n");
|
|
|
|
try {
|
|
NSSInit.initialize("secmod.db", "key3.db", "cert7.db");
|
|
}
|
|
catch (KeyDatabaseException kdbe) {
|
|
System.out.println("Couldn't open the key database\n");
|
|
return;
|
|
}
|
|
catch (CertDatabaseException cdbe) {
|
|
System.out.println("Couldn't open the certificate database");
|
|
return;
|
|
}
|
|
catch (org.mozilla.jss.crypto.AlreadyInitializedException aie) {
|
|
System.out.println("CryptoManager already initialized???");
|
|
return;
|
|
}
|
|
|
|
SSLServerSocket.configServerSessionIDCache(10, 0, 0, null);
|
|
|
|
/* enable all the SSL2 cipher suites */
|
|
for (i = SSLSocket.SSL2_RC4_128_WITH_MD5;
|
|
i <= SSLSocket.SSL2_DES_192_EDE3_CBC_WITH_MD5; ++i) {
|
|
// SSLSocket.setPermittedByPolicy(i, SSLSocket.SSL_ALLOWED);
|
|
SSLSocket.setCipherPreference( i, true);
|
|
}
|
|
|
|
/* enable all the SSL3 cipher suites */
|
|
for (i = 0; cipherSuites[i] != 0; ++i) {
|
|
// SSLSocket.setPermittedByPolicy(cipherSuites[i], SSLSocket.SSL_ALLOWED);
|
|
SSLSocket.setCipherPreference( cipherSuites[i], true);
|
|
}
|
|
|
|
SSLServer x = new SSLServer(System.out, "Stand alone Ver 0.01");
|
|
x.run();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
class ServerHandshakeCB implements SSLHandshakeCompletedListener {
|
|
SSLServer sc;
|
|
|
|
ServerHandshakeCB(SSLServer sc) {
|
|
this.sc = sc;
|
|
}
|
|
|
|
public void handshakeCompleted(SSLHandshakeCompletedEvent event) {
|
|
sc.handshakeEventHappened = true;
|
|
sc.results.println("handshake happened");
|
|
}
|
|
}
|
|
|