Exemple #1
0
bud_error_t bud_config_init(bud_config_t* config) {
  bud_error_t err;
  int i;
  int r;

  /* Get addresses of frontend and backend */
  r = bud_config_str_to_addr(config->frontend.host,
                             config->frontend.port,
                             &config->frontend.addr);
  if (r != 0)
    return bud_error_num(kBudErrPton, r);

  for (i = 0; i < config->frontend.interface.count; i++) {
    bud_config_addr_t* addr;

    addr = &config->frontend.interface.list[i];
    r = bud_config_str_to_addr(addr->host, addr->port, &addr->addr);
    if (r != 0)
      return bud_error_num(kBudErrPton, r);
  }

  err = bud_config_format_proxyline(config);
  if (!bud_is_ok(err))
    return err;

  i = 0;

  config->balance_e = bud_config_balance_to_enum(config->balance);

  /* At least one backend should be present for non-SNI balancing */
  if (config->contexts[0].backend.count == 0 &&
      config->balance_e != kBudBalanceSNI) {
    err = bud_error(kBudErrNoBackend);
    goto fatal;
  }

  /* Get indexes for SSL_set_ex_data()/SSL_get_ex_data() */
  if (kBudSSLClientIndex == -1) {
    kBudSSLConfigIndex = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
    kBudSSLClientIndex = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
    kBudSSLSNIIndex = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
    kBudSSLTicketKeyIndex = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
    if (kBudSSLConfigIndex == -1 ||
        kBudSSLClientIndex == -1 ||
        kBudSSLSNIIndex == -1 ||
        kBudSSLTicketKeyIndex == -1) {
      err = bud_error(kBudErrNoSSLIndex);
      goto fatal;
    }
  }

#ifndef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
  if (config->context_count != 0) {
    err = bud_error(kBudErrSNINotSupported);
    goto fatal;
  }
#endif  /* !SSL_CTRL_SET_TLSEXT_SERVERNAME_CB */

  /* Allocate workers */
  if (!config->is_worker && config->worker_count != 0) {
    config->workers = calloc(config->worker_count, sizeof(*config->workers));
    if (config->workers == NULL) {
      err = bud_error_str(kBudErrNoMem, "workers");
      goto fatal;
    }
  }

  /* Initialize logger */
  config->logger = bud_logger_new(config, &err);
  if (!bud_is_ok(err))
    goto fatal;

  err = bud_config_init_tracing(&config->trace);
  if (!bud_is_ok(err))
    goto fatal;

  if (config->is_worker || config->worker_count == 0) {
    /* Connect to SNI server */
    if (config->sni.enabled) {
      config->sni.pool = bud_http_pool_new(config,
                                           config->sni.host,
                                           config->sni.port,
                                           &err);
      if (config->sni.pool == NULL)
        goto fatal;
    }

    /* Connect to OCSP Stapling server */
    if (config->stapling.enabled) {
      config->stapling.pool = bud_http_pool_new(config,
                                                config->stapling.host,
                                                config->stapling.port,
                                                &err);
      if (config->stapling.pool == NULL)
        goto fatal;
    }
  }

  /* Init all contexts */
  for (i = 0; i < config->context_count + 1; i++) {
    err = bud_context_init(config, &config->contexts[i]);
    if (!bud_is_ok(err))
      goto fatal;
  }

  return bud_ok();

fatal:
  /* Free all allocated contexts */
  do
    bud_context_free(&config->contexts[i--]);
  while (i >= 0);

  return err;
}
Exemple #2
0
bud_error_t bud_sni_from_json(bud_config_t* config,
                              struct json_value_t* json,
                              bud_context_t* ctx) {
  JSON_Object* obj;
  JSON_Value* val;
  const char* cert_str;
  const char* key_str;
  const char* pass_str;
  JSON_Array* cert_strs;
  JSON_Array* key_strs;
  JSON_Array* pass_strs;
  bud_error_t err;

  cert_str = NULL;
  key_str = NULL;
  pass_str = NULL;
  cert_strs = NULL;
  key_strs = NULL;
  pass_strs = NULL;

  obj = json_value_get_object(json);
  val = json_object_get_value(obj, "cert");
  if (json_value_get_type(val) == JSONString)
    cert_str = json_value_get_string(val);
  else
    cert_strs = json_value_get_array(val);
  val = json_object_get_value(obj, "key");
  if (json_value_get_type(val) == JSONString)
    key_str = json_value_get_string(val);
  else
    key_strs = json_value_get_array(val);
  val = json_object_get_value(obj, "passphrase");
  if (json_value_get_type(val) == JSONString)
    pass_str = json_value_get_string(val);
  else
    pass_strs = json_value_get_array(val);

  if (obj == NULL ||
      !((cert_str != NULL && key_str != NULL) ||
        (cert_strs != NULL && key_strs != NULL))) {
    err = bud_error_str(kBudErrJSONParse, "<SNI Response>");
    goto fatal;
  }

  /* Load NPN from response */
  memset(ctx, 0, sizeof(*ctx));
  ctx->cert_file = cert_str;
  ctx->key_file = key_str;
  ctx->key_pass = pass_str;
  ctx->cert_files = cert_strs;
  ctx->key_files = key_strs;
  ctx->key_passes = pass_strs;
  ctx->ciphers = json_object_get_string(obj, "ciphers");
  ctx->ecdh = json_object_get_string(obj, "ecdh");
  ctx->ticket_key = json_object_get_string(obj, "ticket_key");
  ctx->npn = json_object_get_array(obj, "npn");
  ctx->ca_array = json_object_get_array(obj, "ca");
  val = json_object_get_value(obj, "request_cert");
  if (val != NULL)
    ctx->request_cert = json_value_get_boolean(val);
  err = bud_config_load_backend_list(config, obj, &ctx->backend);
  if (!bud_is_ok(err))
    goto fatal;

  err = bud_context_init(config, ctx);

  /* Make sure that deallocated values won't be used */
  ctx->cert_file = NULL;
  ctx->key_file = NULL;
  ctx->key_pass = NULL;
  ctx->cert_files = NULL;
  ctx->key_files = NULL;
  ctx->key_passes = NULL;
  if (!bud_is_ok(err))
    goto fatal;

  return bud_ok();

fatal:
  if (!bud_is_ok(err)) {
    SSL_CTX_free(ctx->ctx);
    ctx->ctx = NULL;
  }
  free(ctx->backend.list);
  ctx->backend.list = NULL;
  return err;
}