Exemplo n.º 1
0
static void
cmd_http_request(
        struct server_framework_state *state,
        struct client_state *p,
        size_t pkt_size,
        const struct new_server_prot_packet *pkt_gen)
{
  enum
  {
    MAX_PARAM_NUM = 10000,
    MAX_PARAM_SIZE = 128 * 1024 * 1024,
  };

  const struct new_server_prot_http_request *pkt;
  size_t in_size;
  const ej_size_t *arg_sizes, *env_sizes, *param_name_sizes, *param_sizes;
  unsigned long bptr;
  const unsigned char ** args;
  const unsigned char ** envs;
  const unsigned char ** param_names;
  const unsigned char ** params;
  size_t *my_param_sizes;
  int i;
  char *out_txt = 0;
  size_t out_size = 0;
  FILE *out_f = 0;
  struct http_request_info hr;
  unsigned char info_buf[1024];
  unsigned char *pbuf = info_buf;

  memset(&hr, 0, sizeof(hr));
  hr.id = p->id;
  hr.client_state = p;
  hr.fw_state = state;
  gettimeofday(&hr.timestamp1, 0);
  hr.current_time = hr.timestamp1.tv_sec;
  hr.locale_id = -1;

  if (pkt_size < sizeof(*pkt))
    return nsf_err_packet_too_small(state, p, pkt_size, sizeof(*pkt));
  pkt = (const struct new_server_prot_http_request *) pkt_gen;

  if (pkt->arg_num < 0 || pkt->arg_num > MAX_PARAM_NUM)
    return nsf_err_protocol_error(state, p);
  if (pkt->env_num < 0 || pkt->env_num > MAX_PARAM_NUM)
    return nsf_err_protocol_error(state, p);
  if (pkt->param_num < 0 || pkt->param_num > MAX_PARAM_NUM)
    return nsf_err_protocol_error(state, p);

  in_size = sizeof(*pkt);
  in_size += pkt->arg_num * sizeof(ej_size_t);
  in_size += pkt->env_num * sizeof(ej_size_t);
  in_size += pkt->param_num * 2 * sizeof(ej_size_t);
  if (pkt_size < in_size)
    return nsf_err_packet_too_small(state, p, pkt_size, in_size);

  XALLOCAZ(args, pkt->arg_num);
  XALLOCAZ(envs, pkt->env_num);
  XALLOCAZ(param_names, pkt->param_num);
  XALLOCAZ(params, pkt->param_num);
  XALLOCAZ(my_param_sizes, pkt->param_num);

  bptr = (unsigned long) pkt;
  bptr += sizeof(*pkt);
  arg_sizes = (const ej_size_t *) bptr;
  bptr += pkt->arg_num * sizeof(ej_size_t);
  env_sizes = (const ej_size_t *) bptr;
  bptr += pkt->env_num * sizeof(ej_size_t);
  param_name_sizes = (const ej_size_t *) bptr;
  bptr += pkt->param_num * sizeof(ej_size_t);
  param_sizes = (const ej_size_t *) bptr;
  bptr += pkt->param_num * sizeof(ej_size_t);

  for (i = 0; i < pkt->arg_num; i++) {
    if (arg_sizes[i] > MAX_PARAM_SIZE) return nsf_err_protocol_error(state, p);
    in_size += arg_sizes[i] + 1;
  }
  for (i = 0; i < pkt->env_num; i++) {
    if (env_sizes[i] > MAX_PARAM_SIZE) return nsf_err_protocol_error(state, p);
    in_size += env_sizes[i] + 1;
  }
  for (i = 0; i < pkt->param_num; i++) {
    if (param_name_sizes[i] > MAX_PARAM_SIZE)
      return nsf_err_protocol_error(state, p);
    if (param_sizes[i] > MAX_PARAM_SIZE)
      return nsf_err_protocol_error(state, p);
    in_size += param_name_sizes[i] + 1;
    in_size += param_sizes[i] + 1;
  }
  if (pkt_size != in_size)
    return nsf_err_bad_packet_length(state, p, pkt_size, in_size);

  for (i = 0; i < pkt->arg_num; i++) {
    args[i] = (const unsigned char*) bptr;
    bptr += arg_sizes[i] + 1;
    if (strlen(args[i]) != arg_sizes[i])
      return nsf_err_protocol_error(state, p);
  }
  for (i = 0; i < pkt->env_num; i++) {
    envs[i] = (const unsigned char*) bptr;
    bptr += env_sizes[i] + 1;
    if (strlen(envs[i]) != env_sizes[i])
      return nsf_err_protocol_error(state, p);
  }
  for (i = 0; i < pkt->param_num; i++) {
    param_names[i] = (const unsigned char*) bptr;
    bptr += param_name_sizes[i] + 1;
    if (strlen(param_names[i]) != param_name_sizes[i])
      return nsf_err_protocol_error(state, p);
    params[i] = (const unsigned char *) bptr;
    my_param_sizes[i] = param_sizes[i];
    bptr += param_sizes[i] + 1;
  }

  hr.arg_num = pkt->arg_num;
  hr.args = args;
  hr.env_num = pkt->env_num;
  hr.envs = envs;
  hr.param_num = pkt->param_num;
  hr.param_names = param_names;
  hr.param_sizes = my_param_sizes;
  hr.params = params;
  hr.config = ejudge_config;

  // ok, generate HTML
  out_f = open_memstream(&out_txt, &out_size);
  ns_handle_http_request(state, p, out_f, &hr);
  close_memstream(out_f); out_f = 0;

  *pbuf = 0;
  // report IP?
  if (hr.ssl_flag) {
    pbuf = stpcpy(pbuf, "HTTPS:");
  } else {
    pbuf = stpcpy(pbuf, "HTTPS:");
  }
  pbuf = stpcpy(pbuf, xml_unparse_ipv6(&hr.ip));
  *pbuf++ = ':';
  if (hr.role_name) {
    pbuf = stpcpy(pbuf, hr.role_name);
  }
  if (hr.action > 0 && hr.action < NEW_SRV_ACTION_LAST && ns_symbolic_action_table[hr.action]) {
    *pbuf++ = '/';
    pbuf = stpcpy(pbuf, ns_symbolic_action_table[hr.action]);
  }
  if (hr.session_id) {
    *pbuf++ = '/';
    *pbuf++ = 'S';
    pbuf += sprintf(pbuf, "%016llx", hr.session_id);
    if (hr.client_key) {
      *pbuf++ = '-';
      pbuf += sprintf(pbuf, "%016llx", hr.client_key);
    }
  }
  if (hr.user_id > 0) {
    *pbuf++ = '/';
    *pbuf++ = 'U';
    pbuf += sprintf(pbuf, "%d", hr.user_id);
  }
  if (hr.contest_id > 0) {
    *pbuf++ = '/';
    *pbuf++ = 'C';
    pbuf += sprintf(pbuf, "%d", hr.contest_id);
  }

  // no reply now
  if (hr.no_reply) goto cleanup;

  if (hr.protocol_reply) {
    xfree(out_txt); out_txt = 0;
    info("%d:%s -> %d", p->id, info_buf, hr.protocol_reply);
    nsf_close_client_fds(p);
    nsf_send_reply(state, p, hr.protocol_reply);
    goto cleanup;
  }

  //
  if (hr.content_type && hr.content_type[0]) {
    // generate header
    char *hdr_t = NULL;
    size_t hdr_z = 0;
    FILE *hdr_f = open_memstream(&hdr_t, &hdr_z);

    fprintf(hdr_f, "Content-Type: %s\n", hr.content_type);
    fprintf(hdr_f, "Cache-Control: no-cache\n");
    fprintf(hdr_f, "Pragma: no-cache\n");
    if (hr.client_key) {
      fprintf(hdr_f, "Set-Cookie: EJSID=%016llx; Path=/\n", hr.client_key);
    }
    putc('\n', hdr_f);
    if (out_size > 0) {
      fwrite(out_txt, 1, out_size, hdr_f);
    }
    fclose(hdr_f); hdr_f = NULL;
    free(out_txt);
    out_txt = hdr_t;
    out_size = hdr_z;
  }

  if (!out_txt || !*out_txt) {
    xfree(out_txt); out_txt = 0;
    if (hr.allow_empty_output) {
      info("%d:%s -> OK", p->id, info_buf);
      nsf_close_client_fds(p);
      nsf_send_reply(state, p, NEW_SRV_RPL_OK);
      goto cleanup;
    }
    out_f = open_memstream(&out_txt, &out_size);
    ns_html_err_internal_error(out_f, &hr, 0, "empty output generated");
    close_memstream(out_f); out_f = 0;
    xfree(out_txt); out_txt = 0;
  }

  nsf_new_autoclose(state, p, out_txt, out_size);
  info("%d:%s -> OK, %zu", p->id, info_buf, out_size);
  nsf_send_reply(state, p, NEW_SRV_RPL_OK);

 cleanup:
  if (hr.log_f) fclose(hr.log_f);
  xfree(hr.log_t);
  xfree(hr.login);
  xfree(hr.name);
  xfree(hr.name_arm);
  xfree(hr.script_part);
  xfree(hr.body_attr);
}
Exemplo n.º 2
0
static void
cmd_http_request(struct server_framework_state *state,
                 struct client_state *p,
                 size_t pkt_size,
                 const struct new_server_prot_packet *pkt_gen)
{
  enum
  {
    MAX_PARAM_NUM = 10000,
    MAX_PARAM_SIZE = 128 * 1024 * 1024,
  };

  const struct new_server_prot_http_request *pkt;
  size_t in_size;
  const ej_size_t *arg_sizes, *env_sizes, *param_name_sizes, *param_sizes;
  unsigned long bptr;
  const unsigned char ** args;
  const unsigned char ** envs;
  const unsigned char ** param_names;
  const unsigned char ** params;
  size_t *my_param_sizes;
  int i;
  char *out_txt = 0;
  size_t out_size = 0;
  FILE *out_f = 0;
  struct http_request_info hr;

  memset(&hr, 0, sizeof(hr));
  hr.id = p->id;
  hr.client_state = p;
  hr.fw_state = state;
  gettimeofday(&hr.timestamp1, 0);

  if (pkt_size < sizeof(*pkt))
    return nsf_err_packet_too_small(state, p, pkt_size, sizeof(*pkt));
  pkt = (const struct new_server_prot_http_request *) pkt_gen;

  if (pkt->arg_num < 0 || pkt->arg_num > MAX_PARAM_NUM)
    return nsf_err_protocol_error(state, p);
  if (pkt->env_num < 0 || pkt->env_num > MAX_PARAM_NUM)
    return nsf_err_protocol_error(state, p);
  if (pkt->param_num < 0 || pkt->param_num > MAX_PARAM_NUM)
    return nsf_err_protocol_error(state, p);

  in_size = sizeof(*pkt);
  in_size += pkt->arg_num * sizeof(ej_size_t);
  in_size += pkt->env_num * sizeof(ej_size_t);
  in_size += pkt->param_num * 2 * sizeof(ej_size_t);
  if (pkt_size < in_size)
    return nsf_err_packet_too_small(state, p, pkt_size, in_size);

  XALLOCAZ(args, pkt->arg_num);
  XALLOCAZ(envs, pkt->env_num);
  XALLOCAZ(param_names, pkt->param_num);
  XALLOCAZ(params, pkt->param_num);
  XALLOCAZ(my_param_sizes, pkt->param_num);

  bptr = (unsigned long) pkt;
  bptr += sizeof(*pkt);
  arg_sizes = (const ej_size_t *) bptr;
  bptr += pkt->arg_num * sizeof(ej_size_t);
  env_sizes = (const ej_size_t *) bptr;
  bptr += pkt->env_num * sizeof(ej_size_t);
  param_name_sizes = (const ej_size_t *) bptr;
  bptr += pkt->param_num * sizeof(ej_size_t);
  param_sizes = (const ej_size_t *) bptr;
  bptr += pkt->param_num * sizeof(ej_size_t);

  for (i = 0; i < pkt->arg_num; i++) {
    if (arg_sizes[i] > MAX_PARAM_SIZE) return nsf_err_protocol_error(state, p);
    in_size += arg_sizes[i] + 1;
  }
  for (i = 0; i < pkt->env_num; i++) {
    if (env_sizes[i] > MAX_PARAM_SIZE) return nsf_err_protocol_error(state, p);
    in_size += env_sizes[i] + 1;
  }
  for (i = 0; i < pkt->param_num; i++) {
    if (param_name_sizes[i] > MAX_PARAM_SIZE)
      return nsf_err_protocol_error(state, p);
    if (param_sizes[i] > MAX_PARAM_SIZE)
      return nsf_err_protocol_error(state, p);
    in_size += param_name_sizes[i] + 1;
    in_size += param_sizes[i] + 1;
  }
  if (pkt_size != in_size)
    return nsf_err_bad_packet_length(state, p, pkt_size, in_size);

  for (i = 0; i < pkt->arg_num; i++) {
    args[i] = (const unsigned char*) bptr;
    bptr += arg_sizes[i] + 1;
    if (strlen(args[i]) != arg_sizes[i])
      return nsf_err_protocol_error(state, p);
  }
  for (i = 0; i < pkt->env_num; i++) {
    envs[i] = (const unsigned char*) bptr;
    bptr += env_sizes[i] + 1;
    if (strlen(envs[i]) != env_sizes[i])
      return nsf_err_protocol_error(state, p);
  }
  for (i = 0; i < pkt->param_num; i++) {
    param_names[i] = (const unsigned char*) bptr;
    bptr += param_name_sizes[i] + 1;
    if (strlen(param_names[i]) != param_name_sizes[i])
      return nsf_err_protocol_error(state, p);
    params[i] = (const unsigned char *) bptr;
    my_param_sizes[i] = param_sizes[i];
    bptr += param_sizes[i] + 1;
  }

  hr.arg_num = pkt->arg_num;
  hr.args = args;
  hr.env_num = pkt->env_num;
  hr.envs = envs;
  hr.param_num = pkt->param_num;
  hr.param_names = param_names;
  hr.param_sizes = my_param_sizes;
  hr.params = params;

  // ok, generate HTML
  out_f = open_memstream(&out_txt, &out_size);
  ns_handle_http_request(state, p, out_f, &hr);
  close_memstream(out_f); out_f = 0;

  // no reply now
  if (hr.no_reply) goto cleanup;

  if (hr.protocol_reply) {
    xfree(out_txt); out_txt = 0;
    info("HTTP_REQUEST -> %d", hr.protocol_reply);
    nsf_close_client_fds(p);
    nsf_send_reply(state, p, hr.protocol_reply);
    goto cleanup;
  }

  if (!out_txt || !*out_txt) {
    xfree(out_txt); out_txt = 0;
    if (hr.allow_empty_output) {
      info("HTTP_REQUEST -> OK");
      nsf_close_client_fds(p);
      nsf_send_reply(state, p, NEW_SRV_RPL_OK);
      goto cleanup;
    }
    out_f = open_memstream(&out_txt, &out_size);
    ns_html_err_internal_error(out_f, &hr, 0, "empty output generated");
    close_memstream(out_f); out_f = 0;
    xfree(out_txt); out_txt = 0;
  }

  nsf_new_autoclose(state, p, out_txt, out_size);
  info("HTTP_REQUEST -> OK, %zu", out_size);
  nsf_send_reply(state, p, NEW_SRV_RPL_OK);

 cleanup:
  xfree(hr.login);
  xfree(hr.name);
  xfree(hr.name_arm);
  xfree(hr.script_part);
  xfree(hr.body_attr);
}