pike.git / lib / modules / SSL.pmod / https.pike

version» Context lines:

pike.git/lib/modules/SSL.pmod/https.pike:1:   #pike __REAL_VERSION__ + #require constant(SSL.Cipher)    - /* -  * dummy https server/client -  */ -  +    //! Dummy HTTPS server/client    -  + #include "tls.h" +    #ifndef PORT   #define PORT 25678   #endif    - #ifdef SSL3_DEBUG - #define SSL3_DEBUG_MSG(X ...) werror(X) - #else /*! SSL3_DEBUG */ - #define SSL3_DEBUG_MSG(X ...) - #endif /* SSL3_DEBUG */ + #ifndef CIPHER_BITS + #define CIPHER_BITS 112 + #endif    - #if constant(SSL.Cipher.CipherAlgorithm) + #ifndef RSA_BITS + #define RSA_BITS 4096 + #endif    - import Stdio; + #ifndef DSA_BITS + #define DSA_BITS 2048 + #endif    - #ifndef HTTPS_CLIENT - inherit SSL.sslport; + #ifndef KE_MODE + #define KE_MODE 1 + #endif    - protected void create() + #ifndef HOST + #define HOST "127.0.0.1" + #endif +  + class MyContext   { -  SSL3_DEBUG_MSG("https->create\n"); -  sslport::create(); - } +  inherit SSL.Context;    - void my_accept_callback(object f) +  SSL.Alert alert_factory(.Connection con, +  int level, int description, +  SSL.Constants.ProtocolVersion version, +  string|void message)    { -  werror("Accept!\n"); -  conn(accept()); +  if (message && description) { +  werror("ALERT [%s: %d:%d]: %s", +  SSL.Constants.fmt_version(version), +  level, description, message);    } -  +  return ::alert_factory(con, level, description, version, message); +  } + }    - protected string fmt_cipher_suites(array(int) s) + #ifndef HTTPS_CLIENT + SSL.Port port; +  + void my_accept_callback(SSL.File f)   { -  String.Buffer b = String.Buffer(); -  mapping(int:string) ciphers = ([]); -  foreach([array(string)]indices(SSL.Constants), string id) -  if( has_prefix(id, "SSL_") || has_prefix(id, "TLS_") || -  has_prefix(id, "SSL2_") ) -  ciphers[SSL.Constants[id]] = id; -  foreach(s, int c) -  b->sprintf(" %-6d: %010x: %s\n", -  c, cipher_suite_sort_key(c), ciphers[c]||"unknown"); -  return (string)b; +  Conn(port->accept());   }   #endif    - string my_certificate = MIME.decode_base64( -  "MIIBxDCCAW4CAQAwDQYJKoZIhvcNAQEEBQAwbTELMAkGA1UEBhMCREUxEzARBgNV\n" -  "BAgTClRodWVyaW5nZW4xEDAOBgNVBAcTB0lsbWVuYXUxEzARBgNVBAoTClRVIEls\n" -  "bWVuYXUxDDAKBgNVBAsTA1BNSTEUMBIGA1UEAxMLZGVtbyBzZXJ2ZXIwHhcNOTYw\n" -  "NDMwMDUzNjU4WhcNOTYwNTMwMDUzNjU5WjBtMQswCQYDVQQGEwJERTETMBEGA1UE\n" -  "CBMKVGh1ZXJpbmdlbjEQMA4GA1UEBxMHSWxtZW5hdTETMBEGA1UEChMKVFUgSWxt\n" -  "ZW5hdTEMMAoGA1UECxMDUE1JMRQwEgYDVQQDEwtkZW1vIHNlcnZlcjBcMA0GCSqG\n" -  "SIb3DQEBAQUAA0sAMEgCQQDBB6T7bGJhRhRSpDESxk6FKh3iKKrpn4KcDtFM0W6s\n" -  "16QSPz6J0Z2a00lDxudwhJfQFkarJ2w44Gdl/8b+de37AgMBAAEwDQYJKoZIhvcN\n" -  "AQEEBQADQQB5O9VOLqt28vjLBuSP1De92uAiLURwg41idH8qXxmylD39UE/YtHnf\n" -  "bC6QS0pqetnZpQj1yEsjRTeVfuRfANGw\n"); -  - string my_key = MIME.decode_base64( -  "MIIBOwIBAAJBAMEHpPtsYmFGFFKkMRLGToUqHeIoqumfgpwO0UzRbqzXpBI/PonR\n" -  "nZrTSUPG53CEl9AWRqsnbDjgZ2X/xv517fsCAwEAAQJBALzUbJmkQm1kL9dUVclH\n" -  "A2MTe15VaDTY3N0rRaZ/LmSXb3laiOgBnrFBCz+VRIi88go3wQ3PKLD8eQ5to+SB\n" -  "oWECIQDrmq//unoW1+/+D3JQMGC1KT4HJprhfxBsEoNrmyIhSwIhANG9c0bdpJse\n" -  "VJA0y6nxLeB9pyoGWNZrAB4636jTOigRAiBhLQlAqhJnT6N+H7LfnkSVFDCwVFz3\n" -  "eygz2yL3hCH8pwIhAKE6vEHuodmoYCMWorT5tGWM0hLpHCN/z3Btm38BGQSxAiAz\n" -  "jwsOclu4b+H8zopfzpAaoB8xMcbs0heN+GNNI0h/dQ==\n"); -  - class conn { -  import Stdio; -  -  object sslfile; -  + class Conn (SSL.File sslfile) + {    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"
pike.git/lib/modules/SSL.pmod/https.pike:102: Inside #if constant(SSL.Cipher.CipherAlgorithm)
   if (index == sizeof(message))    sslfile->close();    }       void read_callback(mixed id, string data)    {    SSL3_DEBUG_MSG("Received: '" + data + "'\n");    sslfile->set_write_callback(write_callback);    }    -  protected void create(object f) +  protected void create()    { -  sslfile = f; +     sslfile->set_nonblocking(read_callback, 0, 0);    }   }    - class no_random { -  object arcfour = Crypto.Arcfour(); -  -  protected void create(string|void secret) + class Client   { -  if (!secret) -  secret = sprintf("Foo!%4c", time()); -  arcfour->set_encrypt_key(Crypto.SHA1->hash(secret)); -  } -  -  string read(int size) -  { -  return arcfour->crypt(replace(allocate(size), 0, "\021") * ""); -  } - } -  - /* 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 -  - */ -  - class client - { -  constant request = +  Stdio.Buffer request = Stdio.Buffer(    "HEAD / HTTP/1.0\r\n" -  "Host: localhost:" + PORT + "\r\n" -  "\r\n"; +  "Host: " HOST ":" + PORT + "\r\n" +  "\r\n");    -  SSL.sslfile ssl; -  int sent; -  void write_cb() +  void write_cb(SSL.File fd)    { -  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( request->output_to(fd) < 0 ) +  exit(1, "Failed to write data: %s.\n", strerror(fd->errno())); +  +  if( sizeof(request) ) return; +  fd->set_write_callback(UNDEFINED);    } -  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); +  exit(0, "Connection closed.\n");    }       protected void create(Stdio.File con)    { -  SSL.context ctx = SSL.context(); -  ctx->random = no_random()->read; +  SSL.Context ctx = MyContext(); +  // Make sure all cipher suites are available. +  ctx->preferred_suites = ctx->get_suites(-1, 2);    werror("Starting\n"); -  ssl = SSL.sslfile(con, ctx, 1); +  SSL.File ssl = SSL.File(con, ctx); +  ssl->connect();    ssl->set_nonblocking(got_data, write_cb, con_closed);    }   }    -  + 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 }), ({ "*" })); + } +    int main()   {   #ifdef HTTPS_CLIENT    Stdio.File con = Stdio.File(); -  if (!con->connect("127.0.0.1", PORT)) { -  werror("Failed to connect to server: %s\n", strerror(con->errno())); -  return 17; -  } -  client(con); -  return -17; +  if (!con->connect(HOST, PORT)) +  exit(1, "Failed to connect to server: %s.\n", strerror(con->errno())); +  +  Client(con); +  return -1;   #else -  SSL3_DEBUG_MSG("Cert: '%s'\n", String.string2hex(my_certificate)); -  SSL3_DEBUG_MSG("Key: '%s'\n", String.string2hex(my_key)); - #if 0 -  array key = SSL.asn1.ber_decode(my_key)->get_asn1()[1]; -  SSL3_DEBUG_MSG("Decoded key: %O\n", key); -  object n = key[1][1]; -  object e = key[2][1]; -  object d = key[3][1]; -  object p = key[4][1]; -  object q = key[5][1]; +  SSL.Context ctx = MyContext();    -  werror("n = %s\np = %s\nq = %s\npq = %s\n", -  n->digits(), p->digits(), q->digits(), (p*q)->digits()); +  Crypto.Sign key;    -  rsa = Crypto.RSA(); -  rsa->set_public_key(n, e); -  rsa->set_private_key(d); - #else /* !0 */ -  // FIXME: Is this correct? -  rsa = Standards.PKCS.RSA.parse_private_key(my_key); - #endif /* 0 */ +  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); +  make_certificate(ctx, key); +  +  // Compat with OLD clients. +  make_certificate(ctx, key, Crypto.SHA1); +  +  +  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); +  make_certificate(ctx, key); +  }; +  +  // Compat with OLD clients. +  // +  // The old FIPS standard maxed out at 1024 & 160 bits with SHA-1. +  key = Crypto.DSA()->generate_key(1024, 160); +  make_certificate(ctx, key, Crypto.SHA1); +  + #if constant(Crypto.ECC.Curve) +  werror("Generating ECDSA certificate (%d bits)...\n", 521); +  +  key = Crypto.ECC.SECP_521R1.ECDSA()->generate_key(); +  make_certificate(ctx, key, Crypto.SHA512); +  make_certificate(ctx, key, Crypto.SHA256); +  +  // Compat with OLD clients. +  // +  // Unlikely to be needed, but the cost is minimal. +  make_certificate(ctx, key, Crypto.SHA1); + #endif +     // Make sure all cipher suites are available. -  rsa_mode(); -  SSL3_DEBUG_MSG("Cipher suites:\n%s", fmt_cipher_suites(preferred_suites)); -  certificates = ({ my_certificate }); -  random = no_random()->read; +  ctx->preferred_suites = ctx->get_suites(CIPHER_BITS, KE_MODE); +  ctx->min_version = SSL.Constants.PROTOCOL_SSL_3_0; +  SSL3_DEBUG_MSG("Cipher suites:\n%s", +  .Constants.fmt_cipher_suites(ctx->preferred_suites)); +  +  SSL3_DEBUG_MSG("Certs:\n%O\n", ctx->get_certificates()); +  +  port = SSL.Port(ctx); +     werror("Starting\n"); -  if (!bind(PORT, my_accept_callback)) -  { -  perror(""); -  return 17; -  } -  else { +  if (!port->bind(PORT, my_accept_callback, NetUtils.ANY)) +  exit(1, "Failed to bind port %d.\n", PORT); +     werror("Listening on port %d.\n", PORT); -  return -17; -  } +  return -1;   #endif   } -  - #else // constant(SSL.Cipher.CipherAlgorithm) - constant this_program_does_not_exist = 1; - #endif +