Ejemplo n.º 1
0
static int send_pubkey_ok(const char *algo, const char *pubkey_data,
    uint32_t pubkey_len) {
  struct ssh2_packet *pkt;
  char *buf, *ptr;
  uint32_t buflen, bufsz;
  int res;

  /* Make sure to allocate a buffer large enough to hold the publickey
   * data we're sending back.
   */
  bufsz = buflen = pubkey_len + 1024;

  pkt = sftp_ssh2_packet_create(sftp_pool);

  buflen = bufsz;
  ptr = buf = palloc(pkt->pool, bufsz);

  sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_USER_AUTH_PK_OK);
  sftp_msg_write_string(&buf, &buflen, algo);
  sftp_msg_write_data(&buf, &buflen, pubkey_data, pubkey_len, TRUE);

  pkt->payload = ptr;
  pkt->payload_len = (bufsz - buflen);

  (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "sending publickey OK");

  res = sftp_ssh2_packet_write(sftp_conn->wfd, pkt);
  if (res < 0) {
    destroy_pool(pkt->pool);
    return -1;
  }

  destroy_pool(pkt->pool);
  return 0;
}
Ejemplo n.º 2
0
int sftp_service_handle(struct ssh2_packet *pkt) {
  int res;
  char *service = NULL;

  res = read_service_req(pkt, &service);
  if (res < 0) {
    destroy_pool(pkt->pool);
    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE, NULL);
  }

  destroy_pool(pkt->pool);

  pkt = sftp_ssh2_packet_create(service_pool);
  res = write_service_accept(pkt, service);
  if (res < 0) {
    destroy_pool(pkt->pool);
    return -1;
  }

  res = sftp_ssh2_packet_write(sftp_conn->wfd, pkt);
  if (res < 0) {
    destroy_pool(pkt->pool);
    return -1;
  }

  destroy_pool(pkt->pool);
  return 0;
}
Ejemplo n.º 3
0
int sftp_kbdint_recv_response(pool *p, unsigned int expected_count,
    unsigned int *rcvd_count, const char ***responses) {
  register unsigned int i;
  unsigned char *buf;
  cmd_rec *cmd;
  array_header *list;
  uint32_t buflen, resp_count;
  struct ssh2_packet *pkt;
  char mesg_type;
  int res;

  if (p == NULL ||
      rcvd_count == NULL ||
      responses == NULL) {
    errno = EINVAL;
    return -1;
  }

  pkt = sftp_ssh2_packet_create(kbdint_pool);

  res = sftp_ssh2_packet_read(sftp_conn->rfd, pkt);
  if (res < 0) {
    destroy_pool(pkt->pool);
    return res;
  }

  mesg_type = sftp_ssh2_packet_get_mesg_type(pkt);
  if (mesg_type != SFTP_SSH2_MSG_USER_AUTH_INFO_RESP) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "expecting USER_AUTH_INFO_RESP message, received %s (%d)",
      sftp_ssh2_packet_get_mesg_type_desc(mesg_type), mesg_type);
    destroy_pool(pkt->pool);
    errno = EPERM;
    return -1;
  }

  cmd = pr_cmd_alloc(pkt->pool, 2, pstrdup(pkt->pool, "USER_AUTH_INFO_RESP"));
  cmd->arg = "(data)";

  pr_trace_msg(trace_channel, 9,
    "reading USER_AUTH_INFO_RESP message from client");

  buf = pkt->payload;
  buflen = pkt->payload_len;

  resp_count = sftp_msg_read_int(pkt->pool, &buf, &buflen);

  /* Ensure that the number of responses sent by the client is the same
   * as the number of challenges sent, lest a malicious client attempt to
   * trick us into allocating too much memory (Bug#3973).
   */
  if (resp_count != expected_count) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "sent %lu %s, but received %lu %s", (unsigned long) expected_count,
      expected_count != 1 ? "challenges" : "challenge",
      (unsigned long) resp_count, resp_count != 1 ? "responses" : "response");
    destroy_pool(pkt->pool);
    errno = EPERM;
    return -1;
  }

  if (resp_count > SFTP_KBDINT_MAX_RESPONSES) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "received too many responses (%lu > max %lu), rejecting",
      (unsigned long) resp_count, (unsigned long) SFTP_KBDINT_MAX_RESPONSES);
    destroy_pool(pkt->pool);
    errno = EPERM;
    return -1;
  }

  list = make_array(p, resp_count, sizeof(char *));
  for (i = 0; i < resp_count; i++) {
    char *resp;

    resp = sftp_msg_read_string(pkt->pool, &buf, &buflen);
    *((char **) push_array(list)) = pstrdup(p, sftp_utf8_decode_str(p, resp));
  }

  *rcvd_count = (unsigned int) resp_count;
  *responses = ((const char **) list->elts);
  return 0;
}
Ejemplo n.º 4
0
int sftp_kbdint_send_challenge(const char *user, const char *instruction,
    unsigned int count, sftp_kbdint_challenge_t *challenges) {
  register unsigned int i;
  unsigned char *buf, *ptr;
  uint32_t buflen, bufsz;
  struct ssh2_packet *pkt;
  int res;

  if (count == 0 ||
      challenges == NULL) {
    errno = EINVAL;
    return -1;
  }

  pkt = sftp_ssh2_packet_create(kbdint_pool);

  /* XXX Is this large enough?  Too large? */
  buflen = bufsz = 3072;
  buf = ptr = palloc(pkt->pool, bufsz);

  /* See RFC4256, Section 3.2. */
  sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_USER_AUTH_INFO_REQ);

  if (user) {
    sftp_msg_write_string(&buf, &buflen,
      sftp_utf8_encode_str(pkt->pool, user));

  } else {
    /* Empty user strings are allowed. */
    sftp_msg_write_string(&buf, &buflen, "");
  }

  if (instruction) {
    sftp_msg_write_string(&buf, &buflen,
      sftp_utf8_encode_str(pkt->pool, instruction));

  } else {
    /* Empty instruction strings are allowed. */
    sftp_msg_write_string(&buf, &buflen, "");
  }

  /* Empty language string. */
  sftp_msg_write_string(&buf, &buflen, "");

  sftp_msg_write_int(&buf, &buflen, count);

  for (i = 0; i < count; i++) {
    sftp_msg_write_string(&buf, &buflen, challenges[i].challenge);
    sftp_msg_write_bool(&buf, &buflen, challenges[i].display_response);
  }

  pkt->payload = ptr;
  pkt->payload_len = (bufsz - buflen);

  pr_trace_msg(trace_channel, 9,
    "sending USER_AUTH_INFO_REQ message to client");

  res = sftp_ssh2_packet_write(sftp_conn->wfd, pkt);
  destroy_pool(pkt->pool);

  return res;
}
Ejemplo n.º 5
0
void sftp_disconnect_send(uint32_t reason, const char *explain,
    const char *file, int lineno, const char *func) {
  struct ssh2_packet *pkt;
  const pr_netaddr_t *remote_addr;
  const char *lang = "en-US";
  unsigned char *buf, *ptr;
  uint32_t buflen, bufsz;
  int sockfd;

  /* Send the client a DISCONNECT mesg. */
  pkt = sftp_ssh2_packet_create(sftp_pool);

  remote_addr = pr_netaddr_get_sess_remote_addr();

  buflen = bufsz = 1024;
  ptr = buf = palloc(pkt->pool, bufsz);

  if (explain == NULL) {
    register unsigned int i;

    for (i = 0; explanations[i].explain; i++) {
      if (explanations[i].code == reason) {
        explain = explanations[i].explain;
        lang = explanations[i].lang;
        if (lang == NULL) {
          lang = "en-US";
        }
        break;
      }
    }

    if (explain == NULL) {
      explain = "Unknown reason";
    }

  } else {
    lang = "en-US";
  }

  if (strlen(func) > 0) {
    pr_trace_msg(trace_channel, 9, "disconnecting (%s) [at %s:%d:%s()]",
      explain, file, lineno, func);

  } else {
    pr_trace_msg(trace_channel, 9, "disconnecting (%s) [at %s:%d]", explain,
      file, lineno);
  }

  sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_DISCONNECT);
  sftp_msg_write_int(&buf, &buflen, reason);
  sftp_msg_write_string(&buf, &buflen, explain);
  sftp_msg_write_string(&buf, &buflen, lang);

  pkt->payload = ptr;
  pkt->payload_len = (bufsz - buflen);

  (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
    "disconnecting %s (%s)", pr_netaddr_get_ipstr(remote_addr), explain);

  /* If we are called very early in the connection lifetime, then the
   * sftp_conn variable may not have been set yet, thus the conditional here.
   */
  if (sftp_conn != NULL) {
    sockfd = sftp_conn->wfd;

  } else {
    sockfd = session.c->wfd;
  }

  /* Explicitly set a short poll timeout of 5 secs. */
  sftp_ssh2_packet_set_poll_timeout(5);

  if (sftp_ssh2_packet_write(sockfd, pkt) < 0) {
    int xerrno = errno;

    pr_trace_msg(trace_channel, 12,
      "error writing DISCONNECT message: %s", strerror(xerrno));
  }

  destroy_pool(pkt->pool);
}
Ejemplo n.º 6
0
int sftp_tap_send_packet(void) {
  int chance;

  if (!sftp_interop_supports_feature(SFTP_SSH2_FEAT_IGNORE_MSG)) {
    pr_trace_msg(trace_channel, 3,
      "unable to send TAP packet: IGNORE not supported by client");
    return 0;
  }

  if (curr_policy.chance_max == 0) {
    /* The "none" policy is in effect; nothing to do. */
    return 0;
  }

  /* Calculate our odds of sending a tap packet, based on the configured
   * policy.
   */
  if (curr_policy.chance_max != 1) {
    chance = (int) (rand() / (RAND_MAX / curr_policy.chance_max + 1));

  } else {
    chance = 1;
  }

  if (chance == curr_policy.chance) {
    unsigned char *rand_data;
    char *buf, *ptr;
    uint32_t bufsz, buflen, rand_datalen;
    struct ssh2_packet *pkt;
    unsigned int max_datalen = 8192;

    if (curr_policy.max_datalen) {
      max_datalen = curr_policy.max_datalen;
    }

    rand_datalen = (uint32_t) (curr_policy.min_datalen + rand() /
      (RAND_MAX / (max_datalen - curr_policy.min_datalen) + 1));

    pr_trace_msg(trace_channel, 20,  "sending random SSH2_MSG_IGNORE message "
      "(%lu bytes) based on '%s' TAP policy", (unsigned long) rand_datalen,
      curr_policy.policy);

    pkt = sftp_ssh2_packet_create(tap_pool);
    bufsz = buflen = rand_datalen + 32;
    ptr = buf = palloc(pkt->pool, bufsz);

    rand_data = palloc(pkt->pool, rand_datalen);

    /* We don't need cryptographically secure random bytes here, just
     * pseudo-random data.
     */
    RAND_pseudo_bytes(rand_data, rand_datalen);

    sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_IGNORE);
    sftp_msg_write_data(&buf, &buflen, (char *) rand_data, rand_datalen, TRUE);

    pkt->payload = ptr;
    pkt->payload_len = (bufsz - buflen);

    if (sftp_ssh2_packet_send(sftp_conn->wfd, pkt) < 0) {
      int xerrno = errno;

      pr_trace_msg(trace_channel, 12,
        "error writing TAP packet: %s", strerror(xerrno));
    }

    destroy_pool(pkt->pool);
  }
 
  return 0;
}