Roxen.git / server / base_server / roxen.pike

version» Context lines:

Roxen.git/server/base_server/roxen.pike:2009:    //! Save all port options    {    set_port_options( get_key(),    mkmapping( indices(variables),    map(indices(variables),query)));    }       void restore()    //! Restore all port options from saved values    { -  foreach( (array)get_port_options( get_key() ), array kv ) -  set( kv[0], kv[1] ); +  setvars(get_port_options( get_key() ));    }       protected int retries;    protected void bind (void|int ignore_eaddrinuse)    {    if (bound) return;    if (!port_obj) port_obj = Stdio.Port();    Privs privs = Privs (sprintf ("Binding %s", get_url()));    if (port_obj->bind(port, got_connection, ip))    {
Roxen.git/server/base_server/roxen.pike:2267:    array args = ({ARGS}); \    if (sizeof (args)) msg = sprintf (msg, @args); \    report_error ("TLS port %s: %s", get_url(), msg); \    (VAR)->add_warning (msg); \    cert_err_unbind(); \    cert_failure = 1; \    return; \    } while (0)      #if constant(SSL.Constants.PROTOCOL_TLS_MAX) -  protected void set_version() +  protected void set_version(SSLContext|void ctx)    { -  +  if (!ctx) ctx = this_program::ctx;    ctx->min_version = query("ssl_min_version");    }   #endif    -  protected void filter_preferred_suites() +  protected void filter_preferred_suites(SSLContext|void ctx)    { -  +  if (!ctx) ctx = this_program::ctx;   #if constant(SSL.ServerConnection)    int mode = query("ssl_suite_filter");    int bits = query("ssl_key_bits");       /* Suite filter encoding:    *    * Bit Mask Meaning    * 0 1 Strict suite B    * 1 2 Transitional suite B    * 2 4 Ephemeral only
Roxen.git/server/base_server/roxen.pike:2331: Inside #if constant(SSL.ServerConnection)
   // Transitional mode.    ctx->configure_suite_b(bits, 1);    break;    default:    ctx->configure_suite_b(bits);    break;    }    suites = ctx->preferred_suites;       if (ctx->min_version < query("ssl_min_version")) { -  set_version(); +  set_version(ctx);    }    } else {    suites = ctx->get_suites(bits, 1);       // Make sure the min version is restored in case we've    // switched from Suite B. -  set_version(); +  set_version(ctx);    }    if (mode & 4) {    // Ephemeral suites only.    suites = filter(suites,    lambda(int suite) {    return (<    SSL.Constants.KE_dhe_dss,    SSL.Constants.KE_dhe_rsa,    SSL.Constants.KE_ecdhe_ecdsa,    SSL.Constants.KE_ecdhe_rsa,
Roxen.git/server/base_server/roxen.pike:2389:    }       void certificates_changed(Variable.Variable|void ignored,    void|int ignore_eaddrinuse)    {    int old_cert_failure = cert_failure;    cert_failure = 0;       Variable.Variable Keys = getvar("ssl_keys");    -  array(int) keypairs = Keys->query(); -  if (!sizeof(keypairs)) { +  array(string) keypair_names = Keys->query(); +  if (!sizeof(keypair_names)) {    // No new-style certificates configured.       // Check if there are old-style certificates; in case of which    // this is probably an upgrade.    Variable.Variable Certificates = getvar("ssl_cert_file");    Variable.Variable KeyFile = getvar("ssl_key_file");    -  keypairs = +  keypair_names =    CertDB.register_pem_files(Certificates->query() + ({ KeyFile->query() }),    query("ssl_password"));    -  if (!sizeof(keypairs)) { +  if (!sizeof(keypair_names)) {    // No Old-style certificate configuration found.    // Fall back to using all known certs. -  keypairs = Keys->get_choice_list(); +  keypair_names = Keys->get_choice_list();    }    -  if (sizeof(keypairs)) { +  if (sizeof(keypair_names)) {    // Certificates found. -  Keys->set(keypairs); +  Keys->set(keypair_names);       save();    } else {    // No certs known to the server.    // Not reached except in very special circumstances.    // FIXME: Use anonymous suites?    report_error ("TLS port %s: %s", get_url(),    LOC_M(63,"No certificates found.\n"));    cert_err_unbind();    cert_failure = 1;    return;    }    }    -  +  array(int) keypairs = +  map(keypair_names, CertDB.get_keypairs_by_name) * ({}); +     // FIXME: Only do this if there are certs loaded?    // We must reset the set of certificates. -  // NB: Race condition here where the new SSLContext is -  // live before it has been configured completely. -  ctx = SSLContext(); -  set_version(); -  filter_preferred_suites(); +  SSLContext ctx = SSLContext(); +  ctx->random = Crypto.Random.random_string; +  set_version(ctx); +  filter_preferred_suites(ctx);       foreach(keypairs, int keypair_id) {    array(Crypto.Sign.State|array(string)) keypair =    CertDB.get_keypair(keypair_id);    if (!keypair) continue;       [Crypto.Sign.State private_key, array(string) certs] = keypair;    ctx->add_cert(private_key, certs, ({ name, "*" }));    }   
Roxen.git/server/base_server/roxen.pike:2455: Inside #if 0
   CERT_ERROR(Certificates,    LOC_M(71,"No matching keys and certificates found.\n"));    report_error ("TLS port %s: %s", get_url(),    LOC_M(71,"No matching keys and certificates found.\n"));    cert_err_unbind();    cert_failure = 1;    return;    }   #endif    +  this_program::ctx = ctx; +     if (!bound) {    bind (ignore_eaddrinuse);    if (old_cert_failure && bound)    report_notice (LOC_M(64, "TLS port %s opened.\n"), get_url());    if (!bound)    report_notice("Failed to bind port %s.\n", get_url());    }    }       class CertificateKeyChoiceVariable    { -  inherit Variable.IntChoice; +  inherit Variable.StringChoice;    -  mapping(int:string) get_translation_table() +  array(string) get_choice_list()    { -  array(mapping(string:int|string)) keypairs = CertDB.list_keypairs(); -  return mkmapping(keypairs->id, keypairs->name); +  return Array.uniq(sort(CertDB.list_keypairs()->name));    }    -  array(int) get_choice_list() -  { -  return CertDB.list_keypairs()->id; -  } -  +     array(string|mixed) verify_set(array(int) new_value)    {    if (!sizeof(new_value)) {    // The list of certificates should never be empty.    return ({ "Selection reset to all selected.", get_choice_list() });    }    return ::verify_set(new_value);    }       protected mapping(Standards.ASN1.Types.Identifier:string)
Roxen.git/server/base_server/roxen.pike:2505:    pair = pair[0];    if(pair->type_name!="SEQUENCE" || sizeof(pair)!=2)    continue;    if(pair[0]->type_name=="OBJECT IDENTIFIER" &&    pair[1]->value && !ids[pair[0]])    ids[pair[0]] = pair[1]->value;    }    return ids;    }    -  protected array(string) render_element(int keypair_id) +  protected array(string) render_keypair(int keypair_id)    {    array(Crypto.Sign.State|array(string)) keypair =    CertDB.get_keypair(keypair_id);    if (!keypair) {    return ({ "<td colspan='2'>" +    LOC_C(1129, "Lost certificate") +    "</td>" });    }    [Crypto.Sign.State private_key, array(string) certs] = keypair;   
Roxen.git/server/base_server/roxen.pike:2649:    "<font color='&usr.warncolor;'>" +    LOC_C(1139, "Lost file") +    "</font>";    }) * "<br/>")    });    }       return res;    }    +  protected array(string) render_element(string keypair_name) +  { +  return map(CertDB.get_keypairs_by_name(keypair_name), render_keypair) * +  ({}); +  } +     string render_form(RequestID id, void|mapping additional_args) { -  array(string) current = map(query(), _name); +  array(string) current = Array.uniq(sort(map(query(), _name)));    string res = "<table width='100%'>\n";    foreach( get_choice_list(); int i; mixed elem ) {    if (i != 0) {    res += "<tr><td colspan='3'><hr/></td></tr>\n";    }    mapping m = ([    "type": "checkbox",    "name": path(),    "value": _name(elem),    ]);
Roxen.git/server/base_server/roxen.pike:2694:    "checked": "checked",    ]);    string title = sprintf(LOC_C(1121,"(stale value %s)"), value);    res += sprintf("<tr><td>%s</td><td>%s</td></tr>\n",    Roxen.make_tag( "input", m),    Roxen.html_encode_string(title));    }    return res + "</table>";    }    +  string low_decode_keypair_id(mixed val) { +  if (intp(val)) { +  // Convert from cert keypair id to cert keypair name. +  mapping md = CertDB.get_keypair_metadata(val); +  if (md) return md->name; +  } +  return val; +  } +  +  int decode(mixed encoded) +  { +  // Convert from cert keypair ids to cert keypair names. +  if (arrayp(encoded)) { +  encoded = map(encoded, low_decode_keypair_id); +  } +  return ::decode(encoded); +  } +     protected void create( void|int _flags, void|LocaleString std_name,    void|LocaleString std_doc )    {    ::create(({}), UNDEFINED, _flags, std_name, std_doc);    }    }      #if 1    // Old-style SSL Certificate variables.    // FIXME: Keep these around for at least a few major versions (10 years?).
Roxen.git/server/base_server/roxen.pike:2740:    {    ctx->random = Crypto.Random.random_string;       set_up_ssl_variables( this_object() );       // NB: setup() calls restore() which initializes the variables    // created above.    ::setup(pn, i);      #if constant(SSL.Constants.PROTOCOL_TLS_MAX) -  set_version(); +  set_version(ctx);   #endif    -  filter_preferred_suites(); +  filter_preferred_suites(ctx);       certificates_changed (0, ignore_eaddrinuse);       // Install the change callbacks here to avoid duplicate calls    // above.    // FIXME: Both variables ought to be updated on save before the    // changed callback is called. Currently you can get warnings    // that the files don't match if you update both variables    // at the same time.    getvar ("ssl_keys")->set_changed_callback(certificates_changed);
Roxen.git/server/base_server/roxen.pike:6380: Inside #if defined(SSL3_DEBUG)
   foreach(glob(base, paths), string fname) {   #ifdef SSL3_DEBUG    werror("Found PEM file %O, matching %O.\n",    Stdio.append_path(dir, fname), glob_pattern);   #endif    CertDB.register_pem_file(Stdio.append_path(dir, fname));    }    }    }    } -  CertDB.refresh_all_pem_files(force); +  +  if (CertDB.refresh_all_pem_files(force)) { +  +  // Update all open SSL/TLS ports with the new certificates. +  foreach(open_ports || ([]); ; mapping(string:mapping(int:Protocol)) ips) { +  foreach(ips || ([]); ; mapping(int:Protocol) ports) { +  foreach(ports || ([]); ; Protocol prot) { +  if (prot->certificates_changed) { +  prot->certificates_changed(UNDEFINED, !prot->bound);    } -  +  } +  } +  } +  } + }      protected BackgroundProcess scan_certs_process;      // Start a background process that scan for new certs every 10 minutes.   protected void start_scan_certs()   {    if (scan_certs_process) return;       scan_certs_process = BackgroundProcess(600, scan_certs);   }