3709192002-03-20Martin Nilsson #pike __REAL_VERSION__
e1fb092014-02-14Martin Nilsson #require constant(SSL.Cipher)
33ef431997-03-13Niels Möller 
8de1612013-10-26Henrik Grubbström (Grubba) //! Dummy HTTPS server/client
f5bb032001-09-17Martin Nilsson 
3c859d2015-02-25Martin Nilsson #include "tls.h"
52b26e2013-12-06Henrik Grubbström (Grubba) #ifndef PORT
33ef431997-03-13Niels Möller #define PORT 25678
52b26e2013-12-06Henrik Grubbström (Grubba) #endif
33ef431997-03-13Niels Möller 
fbd1a52014-04-15Henrik Grubbström (Grubba) #ifndef CIPHER_BITS
ee22502014-04-15Henrik Grubbström (Grubba) #define CIPHER_BITS 112
fbd1a52014-04-15Henrik Grubbström (Grubba) #endif #ifndef RSA_BITS #define RSA_BITS 4096 #endif #ifndef DSA_BITS #define DSA_BITS 2048 #endif #ifndef KE_MODE #define KE_MODE 1 #endif #ifndef HOST #define HOST "" #endif
1a48372014-04-12Henrik Grubbström (Grubba) class MyContext {
dc90a52014-05-15Martin Nilsson  inherit SSL.Context;
1a48372014-04-12Henrik Grubbström (Grubba) 
6a83642014-05-04Martin Nilsson  SSL.Alert alert_factory(.Connection con,
1a48372014-04-12Henrik Grubbström (Grubba)  int level, int description, SSL.Constants.ProtocolVersion version,
74b5eb2014-04-24Martin Nilsson  string|void message)
1a48372014-04-12Henrik Grubbström (Grubba)  {
bc3a3d2014-09-24Martin Nilsson  if (message && description) {
1a48372014-04-12Henrik Grubbström (Grubba)  werror("ALERT [%s: %d:%d]: %s", SSL.Constants.fmt_version(version), level, description, message); }
74b5eb2014-04-24Martin Nilsson  return ::alert_factory(con, level, description, version, message);
1a48372014-04-12Henrik Grubbström (Grubba)  } }
8de1612013-10-26Henrik Grubbström (Grubba) #ifndef HTTPS_CLIENT
fc7f092014-06-01Martin Nilsson SSL.Port port;
8de1612013-10-26Henrik Grubbström (Grubba) 
d518a32015-09-02Martin Nilsson void my_accept_callback(SSL.File f)
8de1612013-10-26Henrik Grubbström (Grubba) {
bda15a2014-04-24Martin Nilsson  Conn(port->accept());
8de1612013-10-26Henrik Grubbström (Grubba) } #endif
d518a32015-09-02Martin Nilsson class Conn (SSL.File sslfile) {
b7a48e2013-11-27Henrik Grubbström (Grubba)  string message = "HTTP/1.0 200 Ok\r\n" "Connection: close\r\n" "Content-Length: 132\r\n" "Content-Type: text/html; charset=ISO-8859-1\r\n" "Date: Thu, 01 Jan 1970 00:00:01 GMT\r\n" "Server: Bare-Bones\r\n" "\r\n" "<html><head><title>SSL-3 server</title></head>\n" "<body><h1>This is a minimal SSL-3 http server</h1>\n" "<hr><it>/nisse</it></body></html>\n";
33ef431997-03-13Niels Möller  int index = 0;
5f22e31997-03-17Niels Möller  void write_callback()
33ef431997-03-13Niels Möller  {
ead9722003-01-20Martin Nilsson  if (index < sizeof(message))
33ef431997-03-13Niels Möller  { int written = sslfile->write(message[index..]); if (written > 0) index += written; else sslfile->close(); }
ead9722003-01-20Martin Nilsson  if (index == sizeof(message))
33ef431997-03-13Niels Möller  sslfile->close(); }
d67d3e2015-02-27Martin Nilsson 
33ef431997-03-13Niels Möller  void read_callback(mixed id, string data) {
7871142013-08-01Martin Nilsson  SSL3_DEBUG_MSG("Received: '" + data + "'\n");
5f22e31997-03-17Niels Möller  sslfile->set_write_callback(write_callback);
33ef431997-03-13Niels Möller  }
d518a32015-09-02Martin Nilsson  protected void create()
33ef431997-03-13Niels Möller  {
5f22e31997-03-17Niels Möller  sslfile->set_nonblocking(read_callback, 0, 0);
33ef431997-03-13Niels Möller  } }
bda15a2014-04-24Martin Nilsson class Client
33ef431997-03-13Niels Möller {
8de1612013-10-26Henrik Grubbström (Grubba)  constant request = "HEAD / HTTP/1.0\r\n"
6df46f2014-05-20Henrik Grubbström (Grubba)  "Host: " HOST ":" + PORT + "\r\n"
8de1612013-10-26Henrik Grubbström (Grubba)  "\r\n";
fc7f092014-06-01Martin Nilsson  SSL.File ssl;
8de1612013-10-26Henrik Grubbström (Grubba)  int sent;
bda15a2014-04-24Martin Nilsson 
8de1612013-10-26Henrik Grubbström (Grubba)  void write_cb() { int bytes = ssl->write(request[sent..]); if (bytes > 0) { sent += bytes; } else if (sent < 0) {
51f1ce2015-09-06Martin Nilsson  exit(1, "Failed to write data: %s.\n", strerror(ssl->errno()));
8de1612013-10-26Henrik Grubbström (Grubba)  } if (sent == sizeof(request)) { ssl->set_write_callback(UNDEFINED); } }
bda15a2014-04-24Martin Nilsson 
8de1612013-10-26Henrik Grubbström (Grubba)  void got_data(mixed ignored, string data) { werror("Data: %O\n", data); }
bda15a2014-04-24Martin Nilsson 
8de1612013-10-26Henrik Grubbström (Grubba)  void con_closed() {
bda15a2014-04-24Martin Nilsson  exit(0, "Connection closed.\n");
8de1612013-10-26Henrik Grubbström (Grubba)  } protected void create(Stdio.File con) {
dc90a52014-05-15Martin Nilsson  SSL.Context ctx = MyContext();
cba3fe2014-03-25Henrik Grubbström (Grubba)  // Make sure all cipher suites are available.
74cb402014-03-25Henrik Grubbström (Grubba)  ctx->preferred_suites = ctx->get_suites(-1, 2);
8de1612013-10-26Henrik Grubbström (Grubba)  werror("Starting\n");
fc7f092014-06-01Martin Nilsson  ssl = SSL.File(con, ctx);
fd4fd82014-05-17Henrik Grubbström (Grubba)  ssl->connect();
8de1612013-10-26Henrik Grubbström (Grubba)  ssl->set_nonblocking(got_data, write_cb, con_closed); }
33ef431997-03-13Niels Möller }
a19ac22014-05-16Martin Nilsson string common_name; void make_certificate(SSL.Context ctx, Crypto.Sign key, void|Crypto.Hash hash) { mapping attrs = ([ "organizationName" : "Test", "commonName" : common_name, ]); string cert = Standards.X509.make_selfsigned_certificate(key, 3600*24, attrs, 0, hash); ctx->add_cert(key, ({ cert }), ({ "*" })); }
33ef431997-03-13Niels Möller int main() {
8de1612013-10-26Henrik Grubbström (Grubba) #ifdef HTTPS_CLIENT Stdio.File con = Stdio.File();
82a1a12015-02-23Martin Nilsson  if (!con->connect(HOST, PORT))
51f1ce2015-09-06Martin Nilsson  exit(1, "Failed to connect to server: %s.\n", strerror(con->errno()));
82a1a12015-02-23Martin Nilsson 
bda15a2014-04-24Martin Nilsson  Client(con);
82a1a12015-02-23Martin Nilsson  return -1;
8de1612013-10-26Henrik Grubbström (Grubba) #else
dc90a52014-05-15Martin Nilsson  SSL.Context ctx = MyContext();
3697942014-04-12Henrik Grubbström (Grubba) 
11410b2014-03-08Henrik Grubbström (Grubba)  Crypto.Sign key;
a19ac22014-05-16Martin Nilsson  common_name = gethostname();
fbd1a52014-04-15Henrik Grubbström (Grubba)  common_name = (gethostbyname(common_name) || ({ common_name }))[0]; werror("Common name: %O\n", common_name); werror("Generating RSA certificate (%d bits)...\n", RSA_BITS); key = Crypto.RSA()->generate_key(RSA_BITS);
a19ac22014-05-16Martin Nilsson  make_certificate(ctx, key);
87af182014-04-01Martin Nilsson 
fbd1a52014-04-15Henrik Grubbström (Grubba)  // Compat with OLD clients.
a19ac22014-05-16Martin Nilsson  make_certificate(ctx, key, Crypto.SHA1);
cba3fe2014-03-25Henrik Grubbström (Grubba) 
fbd1a52014-04-15Henrik Grubbström (Grubba)  werror("Generating DSA certificate (%d bits)...\n", DSA_BITS); catch { // NB: Not all versions of Nettle support q sizes other than 160. key = Crypto.DSA()->generate_key(DSA_BITS, 256);
a19ac22014-05-16Martin Nilsson  make_certificate(ctx, key);
fbd1a52014-04-15Henrik Grubbström (Grubba)  }; // Compat with OLD clients. // // The old FIPS standard maxed out at 1024 & 160 bits with SHA-1.
2e68752014-04-02Martin Nilsson  key = Crypto.DSA()->generate_key(1024, 160);
a19ac22014-05-16Martin Nilsson  make_certificate(ctx, key, Crypto.SHA1);
cba3fe2014-03-25Henrik Grubbström (Grubba)  #if constant(Crypto.ECC.Curve)
fbd1a52014-04-15Henrik Grubbström (Grubba)  werror("Generating ECDSA certificate (%d bits)...\n", 521);
60afeb2014-04-02Martin Nilsson  key = Crypto.ECC.SECP_521R1.ECDSA()->generate_key();
bd174a2015-11-01Henrik Grubbström (Grubba)  make_certificate(ctx, key, Crypto.SHA512); make_certificate(ctx, key, Crypto.SHA256);
fbd1a52014-04-15Henrik Grubbström (Grubba)  // Compat with OLD clients. // // Unlikely to be needed, but the cost is minimal.
a19ac22014-05-16Martin Nilsson  make_certificate(ctx, key, Crypto.SHA1);
cba3fe2014-03-25Henrik Grubbström (Grubba) #endif
74cb402014-03-25Henrik Grubbström (Grubba)  // Make sure all cipher suites are available.
fbd1a52014-04-15Henrik Grubbström (Grubba)  ctx->preferred_suites = ctx->get_suites(CIPHER_BITS, KE_MODE);
d5d6e22014-04-01Martin Nilsson  SSL3_DEBUG_MSG("Cipher suites:\n%s",
3697942014-04-12Henrik Grubbström (Grubba)  .Constants.fmt_cipher_suites(ctx->preferred_suites));
c8dde02014-09-05Martin Nilsson  SSL3_DEBUG_MSG("Certs:\n%O\n", ctx->get_certificates());
3697942014-04-12Henrik Grubbström (Grubba) 
fc7f092014-06-01Martin Nilsson  port = SSL.Port(ctx);
cba3fe2014-03-25Henrik Grubbström (Grubba) 
33ef431997-03-13Niels Möller  werror("Starting\n");
00c9702015-03-24Martin Nilsson  if (!port->bind(PORT, my_accept_callback, NetUtils.ANY))
82a1a12015-02-23Martin Nilsson  exit(1, "Failed to bind port %d.\n", PORT); werror("Listening on port %d.\n", PORT); return -1;
8de1612013-10-26Henrik Grubbström (Grubba) #endif
6ecec91997-03-15Niels Möller }