3709192002-03-20Martin Nilsson #pike __REAL_VERSION__
576edc2014-02-14Martin Nilsson #require constant(SSL.Cipher)
33ef431997-03-13Niels Möller 
d0efae2013-10-26Henrik Grubbström (Grubba) //! Dummy HTTPS server/client
f5bb032001-09-17Martin Nilsson 
bf3f972013-12-06Henrik Grubbström (Grubba) #ifndef PORT
33ef431997-03-13Niels Möller #define PORT 25678
bf3f972013-12-06Henrik Grubbström (Grubba) #endif
33ef431997-03-13Niels Möller 
d35d322014-04-15Henrik Grubbström (Grubba) #ifndef CIPHER_BITS #define CIPHER_BITS 128 #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 "127.0.0.1" #endif
b06b5d2013-08-01Martin Nilsson #ifdef SSL3_DEBUG #define SSL3_DEBUG_MSG(X ...) werror(X) #else /*! SSL3_DEBUG */ #define SSL3_DEBUG_MSG(X ...) #endif /* SSL3_DEBUG */
33ef431997-03-13Niels Möller import Stdio;
7948952014-04-12Henrik Grubbström (Grubba) class MyContext { inherit SSL.context; SSL.alert alert_factory(SSL.connection con, int level, int description, SSL.Constants.ProtocolVersion version, string|void message, mixed|void trace) { if (message) { werror("ALERT [%s: %d:%d]: %s", SSL.Constants.fmt_version(version), level, description, message); } return ::alert_factory(con, level, description, version, message, trace); } }
d0efae2013-10-26Henrik Grubbström (Grubba) #ifndef HTTPS_CLIENT
b807c02014-04-12Henrik Grubbström (Grubba) SSL.sslport port;
d0efae2013-10-26Henrik Grubbström (Grubba)  void my_accept_callback(object f) {
b807c02014-04-12Henrik Grubbström (Grubba)  conn(port->accept());
d0efae2013-10-26Henrik Grubbström (Grubba) } #endif
33ef431997-03-13Niels Möller class conn { import Stdio; object sslfile;
da4f8b2013-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(); } void read_callback(mixed id, string data) {
b06b5d2013-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  }
b55e172010-12-26Henrik Grubbström (Grubba)  protected void create(object f)
33ef431997-03-13Niels Möller  { sslfile = f;
5f22e31997-03-17Niels Möller  sslfile->set_nonblocking(read_callback, 0, 0);
33ef431997-03-13Niels Möller  } } class no_random {
34adca2004-02-03Martin Nilsson  object arcfour = Crypto.Arcfour();
33ef431997-03-13Niels Möller 
b55e172010-12-26Henrik Grubbström (Grubba)  protected void create(string|void secret)
33ef431997-03-13Niels Möller  { if (!secret)
e3bc622014-04-02Martin Nilsson  secret = sprintf("%s%4c", random_string(32), time()); arcfour->set_encrypt_key(Crypto.SHA256.hash(secret)); read(1000);
33ef431997-03-13Niels Möller  } string read(int size) {
e3bc622014-04-02Martin Nilsson  return arcfour->crypt( "\021"*size );
33ef431997-03-13Niels Möller  } } /* PKCS#1 Private key structure: RSAPrivateKey ::= SEQUENCE { version Version, modulus INTEGER, -- n publicExponent INTEGER, -- e privateExponent INTEGER, -- d prime1 INTEGER, -- p prime2 INTEGER, -- q exponent1 INTEGER, -- d mod (p-1) exponent2 INTEGER, -- d mod (q-1) coefficient INTEGER -- (inverse of q) mod p } Version ::= INTEGER */
d0efae2013-10-26Henrik Grubbström (Grubba) class client
33ef431997-03-13Niels Möller {
d0efae2013-10-26Henrik Grubbström (Grubba)  constant request = "HEAD / HTTP/1.0\r\n" "Host: localhost:" + PORT + "\r\n" "\r\n"; SSL.sslfile ssl; int sent; void write_cb() { int bytes = ssl->write(request[sent..]); if (bytes > 0) { sent += bytes; } else if (sent < 0) { werror("Failed to write data: %s\n", strerror(ssl->errno())); exit(17); } if (sent == sizeof(request)) { ssl->set_write_callback(UNDEFINED); } } void got_data(mixed ignored, string data) { werror("Data: %O\n", data); } void con_closed() { werror("Connection closed.\n"); exit(0); } protected void create(Stdio.File con) {
7948952014-04-12Henrik Grubbström (Grubba)  SSL.context ctx = MyContext();
d0efae2013-10-26Henrik Grubbström (Grubba)  ctx->random = no_random()->read;
9c39422014-03-25Henrik Grubbström (Grubba)  // Make sure all cipher suites are available.
915d772014-03-25Henrik Grubbström (Grubba)  ctx->preferred_suites = ctx->get_suites(-1, 2);
d0efae2013-10-26Henrik Grubbström (Grubba)  werror("Starting\n"); ssl = SSL.sslfile(con, ctx, 1); ssl->set_nonblocking(got_data, write_cb, con_closed); }
33ef431997-03-13Niels Möller } int main() {
d0efae2013-10-26Henrik Grubbström (Grubba) #ifdef HTTPS_CLIENT Stdio.File con = Stdio.File();
d35d322014-04-15Henrik Grubbström (Grubba)  if (!con->connect(HOST, PORT)) {
d0efae2013-10-26Henrik Grubbström (Grubba)  werror("Failed to connect to server: %s\n", strerror(con->errno())); return 17; } client(con); return -17; #else
7948952014-04-12Henrik Grubbström (Grubba)  SSL.context ctx = MyContext();
b807c02014-04-12Henrik Grubbström (Grubba) 
557b462014-03-08Henrik Grubbström (Grubba)  Crypto.Sign key;
935b342014-04-01Martin Nilsson  string certificate;
557b462014-03-08Henrik Grubbström (Grubba) 
d35d322014-04-15Henrik Grubbström (Grubba)  string common_name = gethostname(); 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);
935b342014-04-01Martin Nilsson  certificate =
9c39422014-03-25Henrik Grubbström (Grubba)  Standards.X509.make_selfsigned_certificate(key, 3600*4, ([ "organizationName" : "Test",
d35d322014-04-15Henrik Grubbström (Grubba)  "commonName" : common_name,
9c39422014-03-25Henrik Grubbström (Grubba)  ]));
d35d322014-04-15Henrik Grubbström (Grubba)  ctx->add_cert(key, ({ certificate }), ({ "*" }));
935b342014-04-01Martin Nilsson 
d35d322014-04-15Henrik Grubbström (Grubba)  // Compat with OLD clients. certificate = Standards.X509.make_selfsigned_certificate(key, 3600*4, ([ "organizationName" : "Test", "commonName" : common_name, ]), UNDEFINED, Crypto.SHA1);
b807c02014-04-12Henrik Grubbström (Grubba)  ctx->add_cert(key, ({ certificate }), ({ "*" }));
9c39422014-03-25Henrik Grubbström (Grubba) 
d35d322014-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); certificate = Standards.X509.make_selfsigned_certificate(key, 3600*4, ([ "organizationName" : "Test", "commonName" : common_name, ]), UNDEFINED, Crypto.SHA256); ctx->add_cert(key, ({ certificate, ({ "*" }) })); }; // Compat with OLD clients. // // The old FIPS standard maxed out at 1024 & 160 bits with SHA-1.
e3bc622014-04-02Martin Nilsson  key = Crypto.DSA()->generate_key(1024, 160);
935b342014-04-01Martin Nilsson  certificate =
9c39422014-03-25Henrik Grubbström (Grubba)  Standards.X509.make_selfsigned_certificate(key, 3600*4, ([ "organizationName" : "Test",
d35d322014-04-15Henrik Grubbström (Grubba)  "commonName" : common_name, ]), UNDEFINED, Crypto.SHA1); ctx->add_cert(key, ({ certificate }), ({ "*" }));
9c39422014-03-25Henrik Grubbström (Grubba)  #if constant(Crypto.ECC.Curve)
d35d322014-04-15Henrik Grubbström (Grubba)  werror("Generating ECDSA certificate (%d bits)...\n", 521);
0f12b12014-04-02Martin Nilsson  key = Crypto.ECC.SECP_521R1.ECDSA()->generate_key();
935b342014-04-01Martin Nilsson  certificate =
9c39422014-03-25Henrik Grubbström (Grubba)  Standards.X509.make_selfsigned_certificate(key, 3600*4, ([ "organizationName" : "Test",
d35d322014-04-15Henrik Grubbström (Grubba)  "commonName" : common_name,
9c39422014-03-25Henrik Grubbström (Grubba)  ]));
d35d322014-04-15Henrik Grubbström (Grubba)  ctx->add_cert(key, ({ certificate }), ({ "*" })); // Compat with OLD clients. // // Unlikely to be needed, but the cost is minimal. certificate = Standards.X509.make_selfsigned_certificate(key, 3600*4, ([ "organizationName" : "Test", "commonName" : common_name, ]), UNDEFINED, Crypto.SHA1); ctx->add_cert(key, ({ certificate }), ({ "*" }));
9c39422014-03-25Henrik Grubbström (Grubba) #endif
915d772014-03-25Henrik Grubbström (Grubba)  // Make sure all cipher suites are available.
d35d322014-04-15Henrik Grubbström (Grubba)  ctx->preferred_suites = ctx->get_suites(CIPHER_BITS, KE_MODE);
bd7c0f2014-04-01Martin Nilsson  SSL3_DEBUG_MSG("Cipher suites:\n%s",
b807c02014-04-12Henrik Grubbström (Grubba)  .Constants.fmt_cipher_suites(ctx->preferred_suites)); SSL3_DEBUG_MSG("Certs:\n%O\n", ctx->cert_pairs); ctx->random = no_random()->read;
915d772014-03-25Henrik Grubbström (Grubba) 
b807c02014-04-12Henrik Grubbström (Grubba)  port = SSL.sslport(ctx);
9c39422014-03-25Henrik Grubbström (Grubba) 
33ef431997-03-13Niels Möller  werror("Starting\n");
b807c02014-04-12Henrik Grubbström (Grubba)  if (!port->bind(PORT, my_accept_callback))
cfc83a1997-03-15Niels Möller  { perror(""); return 17; }
4652a22013-11-24Henrik Grubbström (Grubba)  else { werror("Listening on port %d.\n", PORT);
cfc83a1997-03-15Niels Möller  return -17;
4652a22013-11-24Henrik Grubbström (Grubba)  }
d0efae2013-10-26Henrik Grubbström (Grubba) #endif
6ecec91997-03-15Niels Möller }