427 lines
15 KiB
HTML
427 lines
15 KiB
HTML
<html>
|
|
<head>
|
|
<link type="text/css" rel="stylesheet" media="all" href="screen.css" />
|
|
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
|
|
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
|
|
<script type="text/javascript" src="forge/debug.js"></script>
|
|
<script type="text/javascript" src="forge/util.js"></script>
|
|
<script type="text/javascript" src="forge/log.js"></script>
|
|
<script type="text/javascript" src="forge/socket.js"></script>
|
|
<script type="text/javascript" src="forge/md5.js"></script>
|
|
<script type="text/javascript" src="forge/sha1.js"></script>
|
|
<script type="text/javascript" src="forge/hmac.js"></script>
|
|
<script type="text/javascript" src="forge/aes.js"></script>
|
|
<script type="text/javascript" src="forge/pem.js"></script>
|
|
<script type="text/javascript" src="forge/asn1.js"></script>
|
|
<script type="text/javascript" src="forge/jsbn.js"></script>
|
|
<script type="text/javascript" src="forge/prng.js"></script>
|
|
<script type="text/javascript" src="forge/random.js"></script>
|
|
<script type="text/javascript" src="forge/oids.js"></script>
|
|
<script type="text/javascript" src="forge/rsa.js"></script>
|
|
<script type="text/javascript" src="forge/pbe.js"></script>
|
|
<script type="text/javascript" src="forge/x509.js"></script>
|
|
<script type="text/javascript" src="forge/pki.js"></script>
|
|
<script type="text/javascript" src="forge/tls.js"></script>
|
|
<script type="text/javascript" src="forge/aesCipherSuites.js"></script>
|
|
<script type="text/javascript" src="forge/tlssocket.js"></script>
|
|
<script type="text/javascript" src="forge/http.js"></script>
|
|
<script type="text/javascript" src="ws-webid.js"></script>
|
|
|
|
<script type="text/javascript">
|
|
//<![CDATA[
|
|
// logging category
|
|
var cat = 'forge.tests.tls';
|
|
|
|
swfobject.embedSWF(
|
|
'forge/SocketPool.swf', 'socketPool', '0', '0', '9.0.0',
|
|
false, {}, {allowscriptaccess: 'always'}, {});
|
|
|
|
// CA certificate for test server
|
|
var certificatePem =
|
|
'-----BEGIN CERTIFICATE-----\r\n' +
|
|
'MIIEaDCCA1CgAwIBAgIJAJuj0AjEWncuMA0GCSqGSIb3DQEBBQUAMH8xCzAJBgNV\r\n' +
|
|
'BAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEd\r\n' +
|
|
'MBsGA1UEChMURGlnaXRhbCBCYXphYXIsIEluYy4xGjAYBgNVBAsTEUZvcmdlIFRl\r\n' +
|
|
'c3QgU2VydmVyMQ0wCwYDVQQDEwR0ZXN0MB4XDTEwMDcxMzE3MjAzN1oXDTMwMDcw\r\n' +
|
|
'ODE3MjAzN1owfzELMAkGA1UEBhMCVVMxETAPBgNVBAgTCFZpcmdpbmlhMRMwEQYD\r\n' +
|
|
'VQQHEwpCbGFja3NidXJnMR0wGwYDVQQKExREaWdpdGFsIEJhemFhciwgSW5jLjEa\r\n' +
|
|
'MBgGA1UECxMRRm9yZ2UgVGVzdCBTZXJ2ZXIxDTALBgNVBAMTBHRlc3QwggEiMA0G\r\n' +
|
|
'CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCm/FobjqK8CVP/Xbnpyhf1tpoyaiFf\r\n' +
|
|
'ShUOmlWqL5rLe0Q0dDR/Zur+sLMUv/1T4wOfFkjjxvZ0Sk5NIjK3Wy2UA41a+M3J\r\n' +
|
|
'RTbCFrg4ujsovFaD4CDmV7Rek0qJB3m5Gp7hgu5vfL/v+WrwxnQObNq+IrTMSA15\r\n' +
|
|
'cO4LzNIPj9K1LN2dB+ucT7xTQFHAfvLLgLlCLiberoabF4rEhgTMTbmMtFVKSt+P\r\n' +
|
|
'xgQIYPnhw1WuAvE9hFesRQFdfARLqIZk92FeHkgtHv9BAunktJemcidbowTCTBaM\r\n' +
|
|
'/njcgi1Tei/LFkph/FCVyGER0pekJNHX626bAQSLo/srsWfmcll9rK6bAgMBAAGj\r\n' +
|
|
'geYwgeMwHQYDVR0OBBYEFCau5k6jxezjULlLuo/liswJlBF8MIGzBgNVHSMEgasw\r\n' +
|
|
'gaiAFCau5k6jxezjULlLuo/liswJlBF8oYGEpIGBMH8xCzAJBgNVBAYTAlVTMREw\r\n' +
|
|
'DwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEdMBsGA1UEChMU\r\n' +
|
|
'RGlnaXRhbCBCYXphYXIsIEluYy4xGjAYBgNVBAsTEUZvcmdlIFRlc3QgU2VydmVy\r\n' +
|
|
'MQ0wCwYDVQQDEwR0ZXN0ggkAm6PQCMRady4wDAYDVR0TBAUwAwEB/zANBgkqhkiG\r\n' +
|
|
'9w0BAQUFAAOCAQEAnP/2mzFWaoGx6+KAfY8pcgnF48IoyKPx5cAQyzpMo+uRwrln\r\n' +
|
|
'INcDGwNx6p6rkjFbK27TME9ReCk+xQuVGaKOtqErKECXWDtD+0M35noyaOwWIFu2\r\n' +
|
|
'7gPZ0uGJ1n9ZMe/S9yZmmusaIrc66rX4o+fslUlH0g3SrH7yf83M8aOC2pEyCsG0\r\n' +
|
|
'mNNfwSFWfmu+1GMRHXJQ/qT8qBX8ZPhzRY2BAS6vr+eh3gwXR6yXLA8Xm1+e+iDU\r\n' +
|
|
'gGTQoYkixDIL2nhvd4AFFlE977BiE+0sMS1eJKUUbQ36MLAWb5oOZKHrphEvqMKA\r\n' +
|
|
'eGDO3qoDqB5TkZC3x38DXBDvAZ01d9s0fvveag==\r\n' +
|
|
'-----END CERTIFICATE-----';
|
|
|
|
// local aliases
|
|
var net = window.forge.net;
|
|
var tls = window.forge.tls;
|
|
var http = window.forge.http;
|
|
var util = window.forge.util;
|
|
|
|
var client;
|
|
|
|
function client_init(primed)
|
|
{
|
|
try
|
|
{
|
|
var sp = net.createSocketPool({
|
|
flashId: 'socketPool',
|
|
policyPort: 19945,
|
|
msie: false
|
|
});
|
|
client = http.createClient({
|
|
//url: 'https://localhost:4433',
|
|
url: 'https://' + window.location.host,
|
|
socketPool: sp,
|
|
connections: 10,
|
|
caCerts: [certificatePem],
|
|
// optional cipher suites in order of preference
|
|
cipherSuites: [
|
|
tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],
|
|
verify: function(c, verified, depth, certs)
|
|
{
|
|
forge.log.debug(cat,
|
|
'TLS certificate ' + depth + ' verified', verified);
|
|
// Note: change to always true to test verifying without cert
|
|
//return verified;
|
|
// FIXME: temporarily accept any cert to allow hitting any bpe
|
|
if(verified !== true)
|
|
{
|
|
forge.log.warning(cat,
|
|
'Certificate NOT verified. Ignored for test.');
|
|
}
|
|
return true;
|
|
},
|
|
primeTlsSockets: primed
|
|
});
|
|
document.getElementById('feedback').innerHTML =
|
|
'http client created';
|
|
}
|
|
catch(ex)
|
|
{
|
|
forge.log.error(cat, ex);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function client_cleanup()
|
|
{
|
|
var sp = client.socketPool;
|
|
client.destroy();
|
|
sp.destroy();
|
|
document.getElementById('feedback').innerHTML =
|
|
'http client cleaned up';
|
|
return false;
|
|
}
|
|
|
|
function client_send()
|
|
{
|
|
/*
|
|
var request = http.createRequest({
|
|
method: 'POST',
|
|
path: '/',
|
|
body: 'echo=foo',
|
|
headers: [{'Content-Type': 'application/x-www-form-urlencoded'}]
|
|
});
|
|
*/
|
|
var request = http.createRequest({
|
|
method: 'GET',
|
|
path: '/'
|
|
});
|
|
|
|
client.send({
|
|
request: request,
|
|
connected: function(e)
|
|
{
|
|
forge.log.debug(cat, 'connected', e);
|
|
},
|
|
headerReady: function(e)
|
|
{
|
|
forge.log.debug(cat, 'header ready', e);
|
|
},
|
|
bodyReady: function(e)
|
|
{
|
|
forge.log.debug(cat, 'body ready', e);
|
|
|
|
// FIXME: current test server doesn't seem to handle keep-alive
|
|
// correctly, so close connection
|
|
e.socket.close();
|
|
},
|
|
error: function(e)
|
|
{
|
|
forge.log.error(cat, 'error', e);
|
|
}
|
|
});
|
|
document.getElementById('feedback').innerHTML =
|
|
'http request sent';
|
|
return false;
|
|
}
|
|
|
|
function client_send_10()
|
|
{
|
|
for(var i = 0; i < 10; ++i)
|
|
{
|
|
client_send();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function client_stress()
|
|
{
|
|
for(var i = 0; i < 10; ++i)
|
|
{
|
|
setTimeout(function()
|
|
{
|
|
for(var i = 0; i < 10; ++i)
|
|
{
|
|
client_send();
|
|
}
|
|
}, 0);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function client_cookies()
|
|
{
|
|
var cookie =
|
|
{
|
|
name: 'test-cookie',
|
|
value: 'test-value',
|
|
maxAge: -1,
|
|
secure: true,
|
|
path: '/'
|
|
};
|
|
client.setCookie(cookie);
|
|
forge.log.debug(cat, 'cookie', client.getCookie('test-cookie'));
|
|
}
|
|
|
|
function client_clear_cookies()
|
|
{
|
|
client.clearCookies();
|
|
}
|
|
|
|
function websocket_test()
|
|
{
|
|
// create certificate
|
|
var cn = 'client';
|
|
console.log(
|
|
'Generating 512-bit key-pair and certificate for \"' + cn + '\".');
|
|
var keys = forge.pki.rsa.generateKeyPair(512);
|
|
console.log('key-pair created.');
|
|
|
|
var cert = forge.pki.createCertificate();
|
|
cert.serialNumber = '01';
|
|
cert.validity.notBefore = new Date();
|
|
cert.validity.notAfter = new Date();
|
|
cert.validity.notAfter.setFullYear(
|
|
cert.validity.notBefore.getFullYear() + 1);
|
|
var attrs = [{
|
|
name: 'commonName',
|
|
value: cn
|
|
}, {
|
|
name: 'countryName',
|
|
value: 'US'
|
|
}, {
|
|
shortName: 'ST',
|
|
value: 'Virginia'
|
|
}, {
|
|
name: 'localityName',
|
|
value: 'Blacksburg'
|
|
}, {
|
|
name: 'organizationName',
|
|
value: 'Test'
|
|
}, {
|
|
shortName: 'OU',
|
|
value: 'Test'
|
|
}];
|
|
cert.setSubject(attrs);
|
|
cert.setIssuer(attrs);
|
|
cert.setExtensions([{
|
|
name: 'basicConstraints',
|
|
cA: true
|
|
}, {
|
|
name: 'keyUsage',
|
|
keyCertSign: true,
|
|
digitalSignature: true,
|
|
nonRepudiation: true,
|
|
keyEncipherment: true,
|
|
dataEncipherment: true
|
|
}, {
|
|
name: 'subjectAltName',
|
|
altNames: [{
|
|
type: 6, // URI
|
|
value: 'http://myuri.com/webid#me'
|
|
}]
|
|
}]);
|
|
// FIXME: add subjectKeyIdentifier extension
|
|
// FIXME: add authorityKeyIdentifier extension
|
|
cert.publicKey = keys.publicKey;
|
|
|
|
// self-sign certificate
|
|
cert.sign(keys.privateKey);
|
|
|
|
// save cert and private key in PEM format
|
|
cert = forge.pki.certificateToPem(cert);
|
|
privateKey = forge.pki.privateKeyToPem(keys.privateKey);
|
|
console.log('certificate created for \"' + cn + '\": \n' + cert);
|
|
|
|
// create websocket
|
|
var ws = new WebSocket('ws://localhost:8080');
|
|
console.log('created websocket', ws);
|
|
|
|
// create TLS client
|
|
var success = false;
|
|
var tls = forge.tls.createConnection(
|
|
{
|
|
server: false,
|
|
caStore: [],
|
|
sessionCache: {},
|
|
// supported cipher suites in order of preference
|
|
cipherSuites: [
|
|
forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],
|
|
virtualHost: 'server',
|
|
verify: function(c, verified, depth, certs)
|
|
{
|
|
console.log(
|
|
'TLS Client verifying certificate w/CN: \"' +
|
|
certs[0].subject.getField('CN').value +
|
|
'\", verified: ' + verified + '...');
|
|
// accept any certificate from the server for this test
|
|
return true;
|
|
},
|
|
connected: function(c)
|
|
{
|
|
console.log('Client connected...');
|
|
|
|
// send message to server
|
|
setTimeout(function()
|
|
{
|
|
c.prepare('Hello Server');
|
|
}, 1);
|
|
},
|
|
getCertificate: function(c, hint)
|
|
{
|
|
console.log('Client getting certificate ...');
|
|
return cert;
|
|
},
|
|
getPrivateKey: function(c, cert)
|
|
{
|
|
return privateKey;
|
|
},
|
|
tlsDataReady: function(c)
|
|
{
|
|
// send base64-encoded TLS data to server
|
|
ws.send(forge.util.encode64(c.tlsData.getBytes()));
|
|
},
|
|
dataReady: function(c)
|
|
{
|
|
var response = c.data.getBytes();
|
|
console.log('Client received \"' + response + '\"');
|
|
success = (response === 'Hello Client');
|
|
c.close();
|
|
},
|
|
closed: function(c)
|
|
{
|
|
console.log('Client disconnected.');
|
|
if(success)
|
|
{
|
|
console.log('PASS');
|
|
}
|
|
else
|
|
{
|
|
console.log('FAIL');
|
|
}
|
|
},
|
|
error: function(c, error)
|
|
{
|
|
console.log('Client error: ' + error.message);
|
|
}
|
|
});
|
|
|
|
ws.onopen = function(evt)
|
|
{
|
|
console.log('websocket connected');
|
|
|
|
// do TLS handshake
|
|
tls.handshake();
|
|
};
|
|
ws.onmessage = function(evt)
|
|
{
|
|
// base64-decode data and process it
|
|
tls.process(forge.util.decode64(evt.data));
|
|
};
|
|
ws.onclose = function(evt)
|
|
{
|
|
console.log('websocket closed');
|
|
};
|
|
}
|
|
|
|
//]]>
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<div class="nav"><a href="index.html">Forge Tests</a> / TLS</div>
|
|
|
|
<div class="header">
|
|
<h1>TLS Test</h1>
|
|
</div>
|
|
|
|
<div class="content">
|
|
|
|
<!-- div used to hold the flash socket pool implemenation -->
|
|
<div id="socketPool">
|
|
<p>Could not load the flash SocketPool.</p>
|
|
</div>
|
|
|
|
<fieldset class="section">
|
|
<ul>
|
|
<li>Use the controls below to test the HTTP client over TLS.</li>
|
|
<li>You currently need a JavaScript console to view the output.</li>
|
|
<li>This test connects to a TLS server so you must have one running. The easiest way to run this test is to start the test server with --tls and load this page over HTTPS.</li>
|
|
</ul>
|
|
</fieldset>
|
|
|
|
<fieldset class="section">
|
|
<legend>Controls</legend>
|
|
<div id="controls">
|
|
<button id="init" onclick="javascript:return client_init(false);">init</button>
|
|
<button id="init_primed" onclick="javascript:return client_init(true);">init primed</button>
|
|
<button id="cleanup" onclick="javascript:return client_cleanup();">cleanup</button>
|
|
<button id="send" onclick="javascript:return client_send();">send</button>
|
|
<button id="send10" onclick="javascript:return client_send_10();">send 10</button>
|
|
<button id="stress" onclick="javascript:return client_stress();">stress</button>
|
|
<button id="client_cookies" onclick="javascript:return client_cookies();">cookies</button>
|
|
<button id="clear_cookies" onclick="javascript:return client_clear_cookies();">clear cookies</button>
|
|
<button id="websocket" onclick="javascript:return websocket_test();">websocket test</button>
|
|
<button id="websocket-webid" onclick="javascript:return websocket_webid('localhost', 8080);">websocket webid test</button>
|
|
</div>
|
|
</fieldset>
|
|
|
|
<fieldset class="section">
|
|
<legend>Feedback</legend>
|
|
<p>Feedback from the flash SocketPool:</p>
|
|
<div id="feedback">
|
|
None
|
|
</div>
|
|
</fieldset>
|
|
|
|
</div>
|
|
</body>
|
|
</html>
|