~hww3/caudium

893c613d8e27e39703c22fe47aa9d8fbae62aa81 — William Welliver 2 years ago 93d5a75
support for minimum and maximum SSL/TLS versions (differing versions for SNI configurations not currently supported)
also support for choosing a particular host on a cert for sni and some fixes for pike 8.0 and tls.
M server/base_server/caudium.pike => server/base_server/caudium.pike +6 -5
@@ 3493,22 3493,23 @@ int main(int argc, array(string) argv)
  return -1;
}

// TODO make this timeout 
mapping sni_configs=([]);
object get_configuration_for_sni(string sni) {
  object conf;
  conf = sni_configs[sni];

  if(conf == -1) return 0;
  else if(conf) return conf;
werror("checking configurations\n");

  foreach(configurations;; conf) {
    object x = conf->get_sni_configuration();
    if(!x) continue;
    werror("find %O: %O\n", sni, x->find_cert_domain(sni));
    if(x->find_cert_domain(sni)) {
    if(conf->is_sni_match(sni)) {
       object x = conf->get_sni_configuration();
       sni_configs[sni] = conf;
       return conf;
    }
  }

  sni_configs[sni] = -1;
  return 0;
}

M server/base_server/config/low_describers.pike => server/base_server/config/low_describers.pike +27 -7
@@ 76,12 76,12 @@ string describe_type(int type, mixed flag)

   case TYPE_STRING_LIST:
    if(!flag)
      return "(Commaseparated list of strings)";
      return "(Comma separated list of strings)";
    break;

   case TYPE_DIR_LIST:
    if(!flag)
      return "(Commaseparated list of directories)";
      return "(Comma separated list of directories)";
    break;

   case TYPE_PASSWORD:


@@ 89,12 89,12 @@ string describe_type(int type, mixed flag)

   case TYPE_INT_LIST:
    if(!flag)
      return "(Commaseparated list of integers)";
      return "(Comma separated list of integers)";
    break;

   case TYPE_SSL_CONFIG:
    if(!flag)
       return "This is an SSL configuration.";
       return "(SSL configuration)";
    break;

   case TYPE_PORTS:


@@ 454,12 454,14 @@ string encode_ssl_field(mixed id, string field) {
string encode_ssl_config(string from, mixed id) 
{
    string res = "";
    string cf, kf, cc, cca, cci;
    string cf, kf, cc, cca, cci, min_ver, max_ver;
    sscanf(from, "%*scert-file %s\n", cf);
    sscanf(from, "%*skey-file %s\n", kf);
    sscanf(from, "%*sclient-cert-request %s\n", cc);
    sscanf(from, "%*sclient-cert-authorities %s\n", cca);
   sscanf(from, "%*sclient-cert-issuers %s\n", cci);
    sscanf(from, "%*sclient-cert-issuers %s\n", cci);
    sscanf(from, "%*smin-protocol-version %s\n", min_ver);
    sscanf(from, "%*smax-protocol-version %s\n", max_ver);

    res += ("<tr><td colspan=3>"
            "<table width=100% cellspacing=0  border=0 bgcolor=#f0f0ff>\n"


@@ 470,6 472,24 @@ string encode_ssl_config(string from, mixed id)
            "<tr><td>Key file: (OPTIONAL)<br>(A comma-separated list of files)</td><td><input size=30,1 "
            "name=\"" + encode_ssl_field(id, "key") +"\" value="+Caudium.html_encode_tag_value(kf||"")+
            "></td></tr>\n");
    
    string minv = "";
    array versions = ({"default"}) + sort(map(glob("PROTOCOL_*", indices(SSL.Constants)), lambda(mixed a){return a[sizeof("PROTOCOL_")..];}));
    foreach(versions;; string ver) {
       minv +=("<option value=\"" + ver + "\" " + ((min_ver == ver)?"SELECTED=\"1\"":"") + ">" + ver + "</option>");     
    }
   
   res += ("<tr><td>Minimum Supported Version: (OPTIONAL)</td><td><select "
            "name=\"" + encode_ssl_field(id, "min") + "\">" + minv + "</select></td></tr>\n");

    string maxv = "";
    foreach(versions;; string ver) {
       maxv +=("<option value=\"" + ver + "\" " + ((max_ver == ver)?"SELECTED=\"1\"":"") + ">" + ver + "</option>");
    }
   
   res += ("<tr><td>Maximum Supported Version: (OPTIONAL)</td><td><select "
            "name=\"" + encode_ssl_field(id, "max") + "\">" + maxv + "</select></td></tr>\n");

    string ccrw = "";
    foreach(({"no", "request", "require"});; string opt)
      ccrw +=("<option value=\"" + opt + "\" " + ((cc == opt)?"SELECTED=\"1\"":"") + ">" + opt + "</option>");


@@ 623,7 643,7 @@ string describe_variable_low(array var, mixed path, int really_short,
      
      tmp="<select name="+path+">  ";
      misc=var[VAR_MISC];
      
      if(functionp(misc)) misc = misc(); 
      for(i=0; i<sizeof(misc); i++)
      {
	if(misc[i]==var[VAR_VALUE])

M server/base_server/configuration.pike => server/base_server/configuration.pike +36 -4
@@ 2487,6 2487,19 @@ object get_sni_configuration() {
  return ctx;
}

array(string) get_sni_selection_hosts() {
  object c = get_sni_configuration();
  if(!c) return ({});
  else return ({"All", "None"}) + c->get_certificates()[0]->globs;
}

int(0..1) is_sni_match(string sni) {
  object c = get_sni_configuration();
  if(!c) return 0;
  string m = QUERY(sni_host_match);
  if(!m || (m == "None") || (m != "All" && m != sni)) return 0;
  return (c->find_cert_domain(sni)?1:0);
}
mapping parse_ssl_args(string options)
{
#ifdef SSL3_DEBUG


@@ 2642,13 2655,30 @@ void load_ssl_configuration(mapping options, mixed ctx,
                ctx->auth_level = SSL.Constants.AUTHLEVEL_require;
  }

werror("additional hostnames: %O\n", additional_hostnames);
if(stringp(additional_hostnames)){
  if(!sizeof(additional_hostnames)) additional_hostnames = 0;
}
  if(stringp(additional_hostnames)){
    if(!sizeof(additional_hostnames)) additional_hostnames = 0;
  }

  // we need the certificates to be in the opposite order (my cert first) for ssl to work.
  ctx->add_cert(rsa, reverse(certificates), additional_hostnames||({}));
  if(options["min-protocol-version"])
  {
     if(options["min-protocol-version"] != "default") {
       if(!SSL.Constants["PROTOCOL_" + options["min-protocol-version"]]) {
         ({ report_error, throw }) ("ssl3: min protocol " + options["min-protocol-version"] + " is not valid\n");
       }
       ctx->min_version = SSL.Constants["PROTOCOL_" + options["min-protocol-version"]];
     }
  }
  if(options["max-protocol-version"])
  {
     if(options["max-protocol-version"] != "default") {
       if(!SSL.Constants["PROTOCOL_" + options["max-protocol-version"]]) {
         ({ report_error, throw }) ("ssl3: max protocol " + options["max-protocol-version"] + " is not valid\n");
       }
       ctx->max_version = SSL.Constants["PROTOCOL_" + options["max-protocol-version"]];
    }
  }
}
//!
string MKPORTKEY(array(string) p)


@@ 4069,6 4099,8 @@ void create(string config)
         TYPE_STRING_LIST,
         "Additional host names to accept. Can be used to specify "
         "host names when a wildcard certificate is employed.");
  defvar("sni_host_match", "All", "SNI: Hostnames to handle",
        TYPE_MULTIPLE_STRING,  "Select the hostnames which will be handled by this virtual server.", get_sni_selection_hosts);
  defvar("name", "", "Virtual server name",
         TYPE_STRING|VAR_MORE,
         "This is the name that will be used in the configuration "

M server/base_server/mainconfig.pike => server/base_server/mainconfig.pike +6 -1
@@ 496,7 496,12 @@ string parse_ssl_config(mixed path, mapping allvars) {
   k = encode_ssl_field(path, "cci");
   if(allvars[k] && strlen(allvars[k]))
     args += "client-cert-issuers "+allvars[k]+"\n";

   k = encode_ssl_field(path, "min");
   if(allvars[k] && strlen(allvars[k]))
     args += "min-protocol-version "+allvars[k]+"\n";
   k = encode_ssl_field(path, "max");
   if(allvars[k] && strlen(allvars[k]))
     args += "max-protocol-version "+allvars[k]+"\n";
   return args;
}


M server/protocols/ssl3.pike => server/protocols/ssl3.pike +5 -3
@@ 137,7 137,7 @@ array|void real_port(array port, object cfg)
#ifdef SSL3_DEBUG
  werror(sprintf("options = %O\n", options));
#endif
  cfg->load_ssl_configuration(options, ctx);
  cfg->load_ssl_configuration(options, ctx, ({"*"}));

}



@@ 367,7 367,10 @@ protected int parse_got()
  string server_name = my_fd->get_server_name();
  if(server_name) {
    object c = caudium->get_configuration_for_sni(server_name);
    if(c) { werror("got sni config: %O\n", c); 
    if(c) { 
#ifdef SSL3_DEBUG
      roxen_perror(sprintf("got sni config %O for server name %O\n", c, server_name));
#endif /*SSL3_DEBUG*/
      conf = c;
    }
  }


@@ 385,7 388,6 @@ protected int parse_got()
          Standards.PKCS.Certificate.get_certificate_subject(der)));
      }
  }

  // let's slide our client certificate info in...
//  if()
//  {