Roxen.git / server / base_server / roxen.pike

version» Context lines:

Roxen.git/server/base_server/roxen.pike:1:   // This file is part of Roxen WebServer.   // Copyright © 1996 - 2004, Roxen IS.   //   // The Roxen WebServer main program.   //   // Per Hedbor, Henrik Grubbström, Pontus Hagland, David Hedbor and others.   // ABS and suicide systems contributed freely by Francesco Chemolli    - constant cvs_version="$Id: roxen.pike,v 1.878 2004/08/18 17:01:31 mast Exp $"; + constant cvs_version="$Id: roxen.pike,v 1.879 2004/08/19 14:19:27 grubba Exp $";      //! @appears roxen   //!   //! The Roxen WebServer main program.      // The argument cache. Used by the image cache.   ArgCache argcache;      // Some headerfiles   #define IN_ROXEN
Roxen.git/server/base_server/roxen.pike:1606:    }   }      #if constant(SSL.sslfile)   class SSLProtocol   //! Base protocol for SSL ports. Exactly like Port, but uses SSL.   {    inherit Protocol;       // SSL context -  SSL.context ctx; +  SSL.context ctx = SSL.context();    -  RoxenSSLFile accept() +  void certificates_changed(Variable|void ignored)    { -  Stdio.File q = ::accept(); -  if (q) -  return RoxenSSLFile (q, ctx); -  return 0; -  } +  string raw_keydata; +  array(string) certificates = ({}); +  Variable Certificates = getvar("ssl_cert_file");    -  void create(int pn, string i) +  object privs = Privs("Reading cert file"); +  +  foreach(map(Certificates->query(), String.trim_whites), string cert_file) { +  string raw_cert; +  if( catch{ raw_cert = lopen(cert_file, "r")->read(); } )    { -  ctx = SSL.context(); -  set_up_ssl_variables( this_object() ); -  port = pn; -  ip = i; +  Certificates->add_warning(sprintf(LOC_M(8,"SSL3: Reading cert-file '%s' failed!"), +  cert_file)); +  continue; +  }    -  restore(); +  object msg = Tools.PEM.pem_msg()->init( raw_cert ); +  object part = msg->parts["CERTIFICATE"] || +  msg->parts["X509 CERTIFICATE"]; +  string cert;    -  object privs = Privs("Reading cert file"); -  int key_matches; -  string f, f2; -  ctx->certificates = ({}); +  if (msg->parts["RSA PRIVATE KEY"] || +  msg->parts["DSA PRIVATE KEY"]) { +  raw_keydata = raw_cert; +  }    -  foreach( map(query_option("ssl_cert_file"), String.trim_whites), -  string cert_file ) +  if (!part || !(cert = part->decoded_body()))    { -  if( catch{ f = lopen(cert_file, "r")->read(); } ) -  { -  report_error(LOC_M(8,"SSL3: Reading cert-file '%s' failed!")+"\n", -  cert_file); -  return; +  Certificates->add_warning(LOC_M(10, "SSL3: No certificate found.")+"\n"); +  continue;    } -  +  certificates += ({ cert }); +  }    -  if( strlen(query_option("ssl_key_file")) && -  catch{ f2 = lopen(query_option("ssl_key_file"),"r")->read(); } ) +  Variable KeyFile = getvar("ssl_key_file"); +  +  if( strlen(KeyFile->query()) && +  catch{ raw_keydata = lopen(KeyFile->query(), "r")->read(); } )    { -  report_error(LOC_M(9, "SSL3: Reading key-file '%s' failed!")+"\n", -  query_option("ssl_key_file")); +  KeyFile->add_warning(sprintf(LOC_M(9, "SSL3: Reading key-file '%s' failed!")+"\n", +  query_option("ssl_key_file")));    return;    }    -  object msg = Tools.PEM.pem_msg()->init( f ); -  object part = msg->parts["CERTIFICATE"] || msg->parts["X509 CERTIFICATE"]; -  string cert; +  privs = 0;    -  if (!part || !(cert = part->decoded_body())) -  { -  report_error(LOC_M(10, "SSL3: No certificate found.")+"\n"); +  if (!raw_keydata) { +  Certificates->add_warning(LOC_M(17,"SSL3: No private key found."));    return;    }    -  if( f2 ) -  msg = Tools.PEM.pem_msg()->init( f2 ); +  if (!sizeof(certificates)) return;    -  function r = Crypto.randomness.reasonably_random()->read; +  object msg = Tools.PEM.pem_msg()->init( raw_keydata );       SSL3_WERR(sprintf("key file contains: %O", indices(msg->parts)));    -  +  object part;    if (part = msg->parts["RSA PRIVATE KEY"])    {    string key;       if (!(key = part->decoded_body()))    { -  report_error(LOC_M(11,"SSL3: Private rsa key not valid")+" (PEM).\n"); +  KeyFile->add_warning(LOC_M(11,"SSL3: Private rsa key not valid")+" (PEM).\n");    return;    }       object rsa = Standards.PKCS.RSA.parse_private_key(key);    if (!rsa)    { -  report_error(LOC_M(11, "SSL3: Private rsa key not valid")+" (DER).\n"); +  KeyFile->add_warning(LOC_M(11, "SSL3: Private rsa key not valid")+" (DER).\n");    return;    }       ctx->rsa = rsa;       SSL3_WERR(sprintf("RSA key size: %d bits", rsa->rsa_size()));       if (rsa->rsa_size() > 512)    {    /* Too large for export */ -  ctx->short_rsa = Crypto.rsa()->generate_key(512, r); + #if constant(Crypto.RSA) +  ctx->short_rsa = Crypto.RSA()->generate_key(512, ctx->random); + #else +  ctx->short_rsa = Crypto.rsa()->generate_key(512, ctx->random); + #endif    -  // ctx->long_rsa = Crypto.rsa()->generate_key(rsa->rsa_size(), r); +  // ctx->long_rsa = Crypto.rsa()->generate_key(rsa->rsa_size(), ctx->random);    }    ctx->rsa_mode();    -  +  array(int) key_matches = +  map(certificates, +  lambda(string cert, Variable Certificates) {    // FIXME: Support PKCS7    object tbs = Tools.X509.decode_certificate (cert);    if (!tbs)    { -  report_error(LOC_M(13,"SSL3: Certificate not valid (DER).")+"\n"); -  return; +  Certificates->add_warning(LOC_M(13,"SSL3: Certificate not valid (DER).")); +  return 0;    } -  if (tbs->public_key->rsa->public_key_equal (rsa)) { -  key_matches++; -  // DWIM: Make sure the main cert comes first in the cert list. -  ctx->certificates = ({ cert }) + ctx->certificates; -  } else { -  ctx->certificates += ({ cert }); -  continue; +  return tbs->public_key->rsa->public_key_equal (rsa); +  }, Certificates); +  +  int num_key_matches; +  // DWIM: Make sure the main cert comes first. +  array(string) new_certificates = allocate(sizeof(certificates)); +  int i,j; +  for (i=0; i < sizeof(certificates); i++) { +  if (key_matches[i]) { +  new_certificates[j++] = certificates[i]; +  num_key_matches++;    }    } -  +  for (i=0; i < sizeof(certificates); i++) { +  if (!key_matches[i]) { +  new_certificates[j++] = certificates[i]; +  } +  } +  if( !num_key_matches ) +  { +  KeyFile->add_warning(LOC_M(14, "SSL3: Certificate and private key " +  "do not match.")); +  return; +  } +  ctx->certificates = new_certificates; +  }    else if (part = msg->parts["DSA PRIVATE KEY"])    {    string key;       if (!(key = part->decoded_body()))    {    report_error(LOC_M(15,"SSL3: Private dsa key not valid")+" (PEM).\n");    return;    }       object dsa = Standards.PKCS.DSA.parse_private_key(key);    if (!dsa)    {    report_error(LOC_M(15,"SSL3: Private dsa key not valid")+" (DER).\n");    return;    }       SSL3_WERR(sprintf("Using DSA key."));    -  dsa->use_random(r); +  //dsa->use_random(ctx->random);    ctx->dsa = dsa;    /* Use default DH parameters */   #if constant(SSL.Cipher)    ctx->dh_params = SSL.Cipher.DHParameters();   #else    ctx->dh_params = SSL.cipher()->dh_parameters();   #endif       ctx->dhe_dss_mode();       // FIXME: Add cert <-> private key check.    -  ctx->certificates = ({ cert }) + ctx->certificates; +  ctx->certificates = certificates;    }    else    { -  report_error(LOC_M(17,"SSL3: No private key found.")+"\n"); +  KeyFile->add_warning(LOC_M(17,"SSL3: No private key found."));    return;    }    -  ctx->random = r; + #if EXPORT +  ctx->export_mode(); + #endif    } -  if( !key_matches ) +  +  class CertificateListVariable    { -  report_error(LOC_M(14, "SSL3: Certificate and private key do not " -  "match.")+"\n"); -  return; +  inherit Variable.FileList; +  +  string doc() +  { +  return sprintf(::doc() + "\n", +  combine_path(getcwd(), "../local"), +  getcwd());    } - #if EXPORT -  ctx->export_mode(); +  +  static void create(mixed default_value, void|int flags, +  void|LocaleString std_name, void|LocaleString std_doc) +  { +  ::create(default_value, flags, std_name, std_doc); +  set_changed_callback(certificates_changed); +  } +  } +  +  class KeyFileVariable +  { +  inherit Variable.String; +  +  string doc() +  { +  return sprintf(::doc() + "\n", +  combine_path(getcwd(), "../local"), +  getcwd()); +  } +  +  static void create(mixed default_value, void|int flags, +  void|LocaleString std_name, void|LocaleString std_doc) +  { +  ::create(default_value, flags, std_name, std_doc); +  set_changed_callback(certificates_changed); +  } +  } +  +  RoxenSSLFile accept() +  { +  Stdio.File q = ::accept(); +  if (q) +  return RoxenSSLFile (q, ctx); +  return 0; +  } +  +  void create(int pn, string i) +  { + #if constant(Crypto.Random.random_string) +  ctx->random = Crypto.Random.random_string; + #else +  ctx->random = Crypto.randomness.reasonably_random()->read;   #endif -  +  +  set_up_ssl_variables( this_object() ); +     ::create(pn, i); -  +  +  certificates_changed();    }       string _sprintf( )    {    return "SSLProtocol("+name+"://"+ip+":"+port+")";    }   }   #endif      mapping(string:Protocol) build_protocols_mapping()