示例#1
0
static void channel_rcv_change_window(SSH_SESSION *session) {
  CHANNEL *channel;
  u32 bytes;
  int rc;

  enter_function();

  channel = channel_from_msg(session);
  if (channel == NULL) {
    ssh_log(session, SSH_LOG_FUNCTIONS, ssh_get_error(session));
  }

  rc = buffer_get_u32(session->in_buffer, &bytes);
  if (channel == NULL || rc != sizeof(u32)) {
    ssh_log(session, SSH_LOG_PACKET,
        "Error getting a window adjust message: invalid packet");
    leave_function();
    return;
  }

  bytes = ntohl(bytes);
  ssh_log(session, SSH_LOG_PROTOCOL,
      "Adding %d bytes to channel (%d:%d) (from %d bytes)",
      bytes,
      channel->local_channel,
      channel->remote_channel,
      channel->remote_window);

  channel->remote_window += bytes;

  leave_function();
}
示例#2
0
static int kbdauth_info_get(SSH_SESSION *session){
    STRING *name; /* name of the "asking" window showed to client */
    STRING *instruction;
    STRING *tmp;
    u32 nprompts;
    u32 i;
    enter_function();
    name=buffer_get_ssh_string(session->in_buffer);
    instruction=buffer_get_ssh_string(session->in_buffer);
    tmp=buffer_get_ssh_string(session->in_buffer);
    buffer_get_u32(session->in_buffer,&nprompts);
    if(!name || !instruction || !tmp){
        if(name)
            free(name);
        if(instruction)
            free(instruction);
        // tmp must be empty if we got here
        ssh_set_error(session,SSH_FATAL,"Invalid USERAUTH_INFO_REQUEST msg");
        leave_function();
        return SSH_AUTH_ERROR;
    }
    if(tmp)
        free(tmp); // no use
    if(!session->kbdint)
        session->kbdint=kbdint_new();
    else
        kbdint_clean(session->kbdint);
    session->kbdint->name=string_to_char(name);
    free(name);
    session->kbdint->instruction=string_to_char(instruction);
    free(instruction);
    nprompts=ntohl(nprompts);
    if(nprompts>KBDINT_MAX_PROMPT){
        ssh_set_error(session,SSH_FATAL,"Too much prompt asked from server: %lu(0x%.8lx)",nprompts,nprompts);
        leave_function();
        return SSH_AUTH_ERROR;
    }
    session->kbdint->nprompts=nprompts;
    session->kbdint->prompts=malloc(nprompts*sizeof(char *));
    memset(session->kbdint->prompts,0,nprompts*sizeof(char *));
    session->kbdint->echo=malloc(nprompts);
    memset(session->kbdint->echo,0,nprompts);
    for(i=0;i<nprompts;++i){
        tmp=buffer_get_ssh_string(session->in_buffer);
        buffer_get_u8(session->in_buffer,&session->kbdint->echo[i]);
        if(!tmp){
            ssh_set_error(session,SSH_FATAL,"Short INFO_REQUEST packet");
            leave_function();
            return SSH_AUTH_ERROR;
        }
        session->kbdint->prompts[i]=string_to_char(tmp);
        free(tmp);
    }
    leave_function();
    return SSH_AUTH_INFO; /* we are not auth. but we parsed the packet */
}
示例#3
0
/*
 * Test the behavior of buffer_prepend_data
 */
static void torture_buffer_prepend(void **state) {
    ssh_buffer buffer = *state;
    uint32_t v;
    buffer_add_data(buffer,"abcdef",6);
    buffer_prepend_data(buffer,"xyz",3);
    assert_int_equal(buffer_get_rest_len(buffer),9);
    assert_int_equal(memcmp(buffer_get_rest(buffer), "xyzabcdef", 9), 0);
// Now remove 4 bytes and see if we can replace them
    buffer_get_u32(buffer,&v);
    assert_int_equal(buffer_get_rest_len(buffer),5);
    assert_int_equal(memcmp(buffer_get_rest(buffer), "bcdef", 5), 0);
    buffer_prepend_data(buffer,"aris",4);
    assert_int_equal(buffer_get_rest_len(buffer),9);
    assert_int_equal(memcmp(buffer_get_rest(buffer), "arisbcdef", 9), 0);
    /* same thing but we add 5 bytes now */
    buffer_get_u32(buffer,&v);
    assert_int_equal(buffer_get_rest_len(buffer),5);
    assert_int_equal(memcmp(buffer_get_rest(buffer), "bcdef", 5), 0);
    buffer_prepend_data(buffer,"12345",5);
    assert_int_equal(buffer_get_rest_len(buffer),10);
    assert_int_equal(memcmp(buffer_get_rest(buffer), "12345bcdef", 10), 0);

}
示例#4
0
static CHANNEL *channel_from_msg(SSH_SESSION *session) {
  CHANNEL *channel;
  u32 chan;

  if (buffer_get_u32(session->in_buffer, &chan) != sizeof(u32)) {
    ssh_set_error(session, SSH_FATAL,
        "Getting channel from message: short read");
    return NULL;
  }

  channel = ssh_channel_from_local(session, ntohl(chan));
  if (channel == NULL) {
    ssh_set_error(session, SSH_FATAL,
        "Server specified invalid channel %lu",
        (long unsigned int) ntohl(chan));
  }

  return channel;
}
示例#5
0
static int channel_rcv_close1(ssh_session session) {
  ssh_channel channel = session->channels;
  uint32_t status;

  buffer_get_u32(session->in_buffer, &status);
  /*
   * It's much more than a channel closing. spec says it's the last
   * message sent by server (strange)
   */

  /* actually status is lost somewhere */
  channel->open = 0;
  channel->remote_eof = 1;

  if (buffer_add_u8(session->out_buffer, SSH_CMSG_EXIT_CONFIRMATION) < 0) {
    return -1;
  }

  if (packet_send(session) != SSH_OK) {
    return -1;
  }

  return 0;
}
示例#6
0
int ssh_agent_get_ident_count(struct ssh_session_struct *session) {
  ssh_buffer request = NULL;
  ssh_buffer reply = NULL;
  unsigned int type = 0;
  unsigned int c1 = 0, c2 = 0;
  uint32_t buf = 0;

  switch (session->version) {
    case 1:
      c1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
      c2 = SSH_AGENT_RSA_IDENTITIES_ANSWER;
      break;
    case 2:
      c1 = SSH2_AGENTC_REQUEST_IDENTITIES;
      c2 = SSH2_AGENT_IDENTITIES_ANSWER;
      break;
    default:
      return 0;
  }

  /* send message to the agent requesting the list of identities */
  request = ssh_buffer_new();
  if (buffer_add_u8(request, c1) < 0) {
    ssh_set_error(session, SSH_FATAL, "Not enough space");
    return -1;
  }

  reply = ssh_buffer_new();
  if (reply == NULL) {
    ssh_set_error(session, SSH_FATAL, "Not enough space");
    return -1;
  }

  if (agent_talk(session, request, reply) < 0) {
    ssh_buffer_free(request);
    return 0;
  }
  ssh_buffer_free(request);

  /* get message type and verify the answer */
  buffer_get_u8(reply, (uint8_t *) &type);
  SSH_LOG(session, SSH_LOG_WARN,
      "Answer type: %d, expected answer: %d",
      type, c2);
  if (agent_failed(type)) {
    return 0;
  } else if (type != c2) {
    ssh_set_error(session, SSH_FATAL,
        "Bad authentication reply message type: %d", type);
    return -1;
  }

  buffer_get_u32(reply, &buf);
  session->agent->count = agent_get_u32((uint8_t*)&buf);
  SSH_LOG(session, SSH_LOG_DEBUG, "Agent count: %d",
      session->agent->count);
  if (session->agent->count > 1024) {
    ssh_set_error(session, SSH_FATAL,
        "Too many identities in authentication reply: %d",
        session->agent->count);
    ssh_buffer_free(reply);
    return -1;
  }

  if (session->agent->ident) {
    buffer_reinit(session->agent->ident);
  }
  session->agent->ident = reply;

  return session->agent->count;
}
示例#7
0
/**
 * @internal
 *
 * @brief This function parses the last end of a channel request packet.
 *
 * This is normally converted to a SSH message and placed in the queue.
 *
 * @param[in]  session  The SSH session.
 *
 * @param[in]  channel  The channel the request is made on.
 *
 * @param[in]  packet   The rest of the packet to be parsed.
 *
 * @param[in]  request  The type of request.
 *
 * @param[in]  want_reply The want_reply field from the request.
 *
 * @returns             SSH_OK on success, SSH_ERROR if an error occured.
 */
int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel, ssh_buffer packet,
    const char *request, uint8_t want_reply) {
  ssh_message msg = NULL;
  enter_function();
  msg = ssh_message_new(session);
  if (msg == NULL) {
    ssh_set_error_oom(session);
    goto error;
  }

  ssh_log(session, SSH_LOG_PACKET,
      "Received a %s channel_request for channel (%d:%d) (want_reply=%hhd)",
      request, channel->local_channel, channel->remote_channel, want_reply);

  msg->type = SSH_REQUEST_CHANNEL;
  msg->channel_request.channel = channel;
  msg->channel_request.want_reply = want_reply;

  if (strcmp(request, "pty-req") == 0) {
    ssh_string term = NULL;
    char *term_c = NULL;
    term = buffer_get_ssh_string(packet);
    if (term == NULL) {
      ssh_set_error_oom(session);
      goto error;
    }
    term_c = ssh_string_to_char(term);
    if (term_c == NULL) {
      ssh_set_error_oom(session);
      ssh_string_free(term);
      goto error;
    }
    ssh_string_free(term);

    msg->channel_request.type = SSH_CHANNEL_REQUEST_PTY;
    msg->channel_request.TERM = term_c;

    buffer_get_u32(packet, &msg->channel_request.width);
    buffer_get_u32(packet, &msg->channel_request.height);
    buffer_get_u32(packet, &msg->channel_request.pxwidth);
    buffer_get_u32(packet, &msg->channel_request.pxheight);

    msg->channel_request.width = ntohl(msg->channel_request.width);
    msg->channel_request.height = ntohl(msg->channel_request.height);
    msg->channel_request.pxwidth = ntohl(msg->channel_request.pxwidth);
    msg->channel_request.pxheight = ntohl(msg->channel_request.pxheight);
    msg->channel_request.modes = buffer_get_ssh_string(packet);
    if (msg->channel_request.modes == NULL) {
      SAFE_FREE(term_c);
      goto error;
    }
    goto end;
  }

  if (strcmp(request, "window-change") == 0) {
    msg->channel_request.type = SSH_CHANNEL_REQUEST_WINDOW_CHANGE;

    buffer_get_u32(packet, &msg->channel_request.width);
    buffer_get_u32(packet, &msg->channel_request.height);
    buffer_get_u32(packet, &msg->channel_request.pxwidth);
    buffer_get_u32(packet, &msg->channel_request.pxheight);

    msg->channel_request.width = ntohl(msg->channel_request.width);
    msg->channel_request.height = ntohl(msg->channel_request.height);
    msg->channel_request.pxwidth = ntohl(msg->channel_request.pxwidth);
    msg->channel_request.pxheight = ntohl(msg->channel_request.pxheight);

    goto end;
  }

  if (strcmp(request, "subsystem") == 0) {
    ssh_string subsys = NULL;
    char *subsys_c = NULL;
    subsys = buffer_get_ssh_string(packet);
    if (subsys == NULL) {
      ssh_set_error_oom(session);
      goto error;
    }
    subsys_c = ssh_string_to_char(subsys);
    if (subsys_c == NULL) {
      ssh_set_error_oom(session);
      ssh_string_free(subsys);
      goto error;
    }
    ssh_string_free(subsys);

    msg->channel_request.type = SSH_CHANNEL_REQUEST_SUBSYSTEM;
    msg->channel_request.subsystem = subsys_c;

    goto end;
  }

  if (strcmp(request, "shell") == 0) {
    msg->channel_request.type = SSH_CHANNEL_REQUEST_SHELL;
    goto end;
  }

  if (strcmp(request, "exec") == 0) {
    ssh_string cmd = NULL;
    cmd = buffer_get_ssh_string(packet);
    if (cmd == NULL) {
      ssh_set_error_oom(session);
      goto error;
    }
    msg->channel_request.type = SSH_CHANNEL_REQUEST_EXEC;
    msg->channel_request.command = ssh_string_to_char(cmd);
    ssh_string_free(cmd);
    if (msg->channel_request.command == NULL) {
      goto error;
    }
    goto end;
  }

  if (strcmp(request, "env") == 0) {
    ssh_string name = NULL;
    ssh_string value = NULL;
    name = buffer_get_ssh_string(packet);
    if (name == NULL) {
      ssh_set_error_oom(session);
      goto error;
    }
    value = buffer_get_ssh_string(packet);
    if (value == NULL) {
      ssh_set_error_oom(session);
      ssh_string_free(name);
      goto error;
    }

    msg->channel_request.type = SSH_CHANNEL_REQUEST_ENV;
    msg->channel_request.var_name = ssh_string_to_char(name);
    msg->channel_request.var_value = ssh_string_to_char(value);
    if (msg->channel_request.var_name == NULL ||
        msg->channel_request.var_value == NULL) {
      ssh_string_free(name);
      ssh_string_free(value);
      goto error;
    }
    ssh_string_free(name);
    ssh_string_free(value);

    goto end;
  }

  if (strcmp(request, "x11-req") == 0) {
    ssh_string auth_protocol = NULL;
    ssh_string auth_cookie = NULL;

    buffer_get_u8(packet, &msg->channel_request.x11_single_connection);

    auth_protocol = buffer_get_ssh_string(packet);
    if (auth_protocol == NULL) {
      ssh_set_error_oom(session);
      goto error;
    }
    auth_cookie = buffer_get_ssh_string(packet);
    if (auth_cookie == NULL) {
      ssh_set_error_oom(session);
      ssh_string_free(auth_protocol);
      goto error;
    }

    msg->channel_request.type = SSH_CHANNEL_REQUEST_X11;
    msg->channel_request.x11_auth_protocol = ssh_string_to_char(auth_protocol);
    msg->channel_request.x11_auth_cookie = ssh_string_to_char(auth_cookie);
    if (msg->channel_request.x11_auth_protocol == NULL ||
        msg->channel_request.x11_auth_cookie == NULL) {
      ssh_string_free(auth_protocol);
      ssh_string_free(auth_cookie);
      goto error;
    }
    ssh_string_free(auth_protocol);
    ssh_string_free(auth_cookie);

    buffer_get_u32(packet, &msg->channel_request.x11_screen_number);

    goto end;
  }

  msg->channel_request.type = SSH_CHANNEL_UNKNOWN;
end:
  ssh_message_queue(session,msg);
  leave_function();
  return SSH_OK;
error:
  ssh_message_free(msg);

  leave_function();
  return SSH_ERROR;
}
示例#8
0
int ssh_get_kex1(SSH_SESSION *session) {
  STRING *server_exp = NULL;
  STRING *server_mod = NULL;
  STRING *host_exp = NULL;
  STRING *host_mod = NULL;
  STRING *serverkey = NULL;
  STRING *hostkey = NULL;
  STRING *enc_session = NULL;
  PUBLIC_KEY *srv = NULL;
  PUBLIC_KEY *host = NULL;
  u32 server_bits;
  u32 host_bits;
  u32 protocol_flags;
  u32 supported_ciphers_mask;
  u32 supported_authentications_mask;
  u16 bits;
  int rc = -1;
  int ko;

  enter_function();
  ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY");
  if (packet_wait(session, SSH_SMSG_PUBLIC_KEY, 1) != SSH_OK) {
    leave_function();
    return -1;
  }

  ssh_log(session, SSH_LOG_PROTOCOL, "Got a SSH_SMSG_PUBLIC_KEY");
  if (buffer_get_data(session->in_buffer, session->server_kex.cookie, 8) != 8) {
    ssh_set_error(session, SSH_FATAL, "Can't get cookie in buffer");
    leave_function();
    return -1;
  }

  buffer_get_u32(session->in_buffer, &server_bits);
  server_exp = buffer_get_mpint(session->in_buffer);
  if (server_exp == NULL) {
    goto error;
  }
  server_mod = buffer_get_mpint(session->in_buffer);
  if (server_mod == NULL) {
    goto error;
  }
  buffer_get_u32(session->in_buffer, &host_bits);
  host_exp = buffer_get_mpint(session->in_buffer);
  if (host_exp == NULL) {
    goto error;
  }
  host_mod = buffer_get_mpint(session->in_buffer);
  if (host_mod == NULL) {
    goto error;
  }
  buffer_get_u32(session->in_buffer, &protocol_flags);
  buffer_get_u32(session->in_buffer, &supported_ciphers_mask);
  ko = buffer_get_u32(session->in_buffer, &supported_authentications_mask);

  if ((ko != sizeof(u32)) || !host_mod || !host_exp
      || !server_mod || !server_exp) {
    ssh_log(session, SSH_LOG_RARE, "Invalid SSH_SMSG_PUBLIC_KEY packet");
    ssh_set_error(session, SSH_FATAL, "Invalid SSH_SMSG_PUBLIC_KEY packet");
    goto error;
  }

  server_bits = ntohl(server_bits);
  host_bits = ntohl(host_bits);
  protocol_flags = ntohl(protocol_flags);
  supported_ciphers_mask = ntohl(supported_ciphers_mask);
  supported_authentications_mask = ntohl(supported_authentications_mask);
  ssh_log(session, SSH_LOG_PROTOCOL,
      "Server bits: %d; Host bits: %d; Protocol flags: %.8lx; "
      "Cipher mask: %.8lx; Auth mask: %.8lx",
      server_bits,
      host_bits,
      (unsigned long int) protocol_flags,
      (unsigned long int) supported_ciphers_mask,
      (unsigned long int) supported_authentications_mask);

  serverkey = make_rsa1_string(server_exp, server_mod);
  if (serverkey == NULL) {
    goto error;
  }
  hostkey = make_rsa1_string(host_exp,host_mod);
  if (serverkey == NULL) {
    goto error;
  }
  if (build_session_id1(session, server_mod, host_mod) < 0) {
    goto error;
  }

  srv = publickey_from_string(session, serverkey);
  if (srv == NULL) {
    goto error;
  }
  host = publickey_from_string(session, hostkey);
  if (host == NULL) {
    goto error;
  }

  session->next_crypto->server_pubkey = string_copy(hostkey);
  if (session->next_crypto->server_pubkey == NULL) {
    goto error;
  }
  session->next_crypto->server_pubkey_type = "ssh-rsa1";

  /* now, we must choose an encryption algo */
  /* hardcode 3des */
  if (!(supported_ciphers_mask & (1 << SSH_CIPHER_3DES))) {
    ssh_set_error(session, SSH_FATAL, "Remote server doesn't accept 3DES");
    goto error;
  }

  ssh_log(session, SSH_LOG_PROTOCOL, "Sending SSH_CMSG_SESSION_KEY");

  if (buffer_add_u8(session->out_buffer, SSH_CMSG_SESSION_KEY) < 0) {
    goto error;
  }
  if (buffer_add_u8(session->out_buffer, SSH_CIPHER_3DES) < 0) {
    goto error;
  }
  if (buffer_add_data(session->out_buffer, session->server_kex.cookie, 8) < 0) {
    goto error;
  }

  enc_session = encrypt_session_key(session, srv, host, server_bits, host_bits);
  if (enc_session == NULL) {
    goto error;
  }

  bits = string_len(enc_session) * 8 - 7;
  ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %zu bytes encrypted session",
      bits, string_len(enc_session));
  bits = htons(bits);
  /* the encrypted mpint */
  if (buffer_add_data(session->out_buffer, &bits, sizeof(u16)) < 0) {
    goto error;
  }
  if (buffer_add_data(session->out_buffer, enc_session->string,
        string_len(enc_session)) < 0) {
    goto error;
  }
  /* the protocol flags */
  if (buffer_add_u32(session->out_buffer, 0) < 0) {
    goto error;
  }

  if (packet_send(session) != SSH_OK) {
    goto error;
  }

  /* we can set encryption */
  if (crypt_set_algorithms(session)) {
    goto error;
  }

  session->current_crypto = session->next_crypto;
  session->next_crypto = NULL;

  ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_SUCCESS");
  if (packet_wait(session,SSH_SMSG_SUCCESS,1) != SSH_OK) {
    char buffer[1024] = {0};
    snprintf(buffer, sizeof(buffer),
        "Key exchange failed: %s", ssh_get_error(session));
    ssh_set_error(session, SSH_FATAL, "%s",buffer);
    goto error;
  }
  ssh_log(session, SSH_LOG_PROTOCOL, "received SSH_SMSG_SUCCESS\n");

  rc = 0;
error:
  string_free(host_mod);
  string_free(host_exp);
  string_free(server_mod);
  string_free(server_exp);
  string_free(serverkey);
  string_free(hostkey);

  publickey_free(srv);
  publickey_free(host);

  leave_function();
  return rc;
}
示例#9
0
static void channel_rcv_request(SSH_SESSION *session) {
  CHANNEL *channel;
  STRING *request_s;
  char *request;
  u32 status;

  enter_function();

  channel = channel_from_msg(session);
  if (channel == NULL) {
    ssh_log(session, SSH_LOG_FUNCTIONS, ssh_get_error(session));
    leave_function();
    return;
  }

  request_s = buffer_get_ssh_string(session->in_buffer);
  if (request_s == NULL) {
    ssh_log(session, SSH_LOG_PACKET, "Invalid MSG_CHANNEL_REQUEST");
    leave_function();
    return;
  }

  request = string_to_char(request_s);
  string_free(request_s);
  if (request == NULL) {
    leave_function();
    return;
  }

  buffer_get_u8(session->in_buffer, (u8 *) &status);

  if (strcmp(request,"exit-status") == 0) {
    SAFE_FREE(request);
    ssh_log(session, SSH_LOG_PACKET, "received exit-status");
    buffer_get_u32(session->in_buffer, &status);
    channel->exit_status = ntohl(status);

    leave_function();
    return ;
  }

  if (strcmp(request, "exit-signal") == 0) {
    const char *core = "(core dumped)";
    STRING *signal_s;
    char *signal;
    u8 i;

    SAFE_FREE(request);

    signal_s = buffer_get_ssh_string(session->in_buffer);
    if (signal_s == NULL) {
      ssh_log(session, SSH_LOG_PACKET, "Invalid MSG_CHANNEL_REQUEST");
      leave_function();
      return;
    }

    signal = string_to_char(signal_s);
    string_free(signal_s);
    if (signal == NULL) {
      leave_function();
      return;
    }

    buffer_get_u8(session->in_buffer, &i);
    if (i == 0) {
      core = "";
    }

    ssh_log(session, SSH_LOG_PACKET,
        "Remote connection closed by signal SIG %s %s", signal, core);
    SAFE_FREE(signal);

    leave_function();
    return;
  }
  ssh_log(session, SSH_LOG_PACKET, "Unknown request %s", request);
  SAFE_FREE(request);

  leave_function();
}
示例#10
0
/* is_stderr is set to 1 if the data are extended, ie stderr */
static void channel_rcv_data(SSH_SESSION *session,int is_stderr) {
  CHANNEL *channel;
  STRING *str;
  size_t len;

  enter_function();

  channel = channel_from_msg(session);
  if (channel == NULL) {
    ssh_log(session, SSH_LOG_FUNCTIONS,
        "%s", ssh_get_error(session));
    leave_function();
    return;
  }

  if (is_stderr) {
    u32 ignore;
    /* uint32 data type code. we can ignore it */
    buffer_get_u32(session->in_buffer, &ignore);
  }

  str = buffer_get_ssh_string(session->in_buffer);
  if (str == NULL) {
    ssh_log(session, SSH_LOG_PACKET, "Invalid data packet!");
    leave_function();
    return;
  }
  len = string_len(str);

  ssh_log(session, SSH_LOG_PROTOCOL,
      "Channel receiving %zu bytes data in %d (local win=%d remote win=%d)",
      len,
      is_stderr,
      channel->local_window,
      channel->remote_window);

  /* What shall we do in this case? Let's accept it anyway */
  if (len > channel->local_window) {
    ssh_log(session, SSH_LOG_RARE,
        "Data packet too big for our window(%zu vs %d)",
        len,
        channel->local_window);
  }

  if (channel_default_bufferize(channel, str->string, len,
        is_stderr) < 0) {
    string_free(str);
    leave_function();
    return;
  }

  if (len <= channel->local_window) {
    channel->local_window -= len;
  } else {
    channel->local_window = 0; /* buggy remote */
  }

  ssh_log(session, SSH_LOG_PROTOCOL,
      "Channel windows are now (local win=%d remote win=%d)",
      channel->local_window,
      channel->remote_window);

  string_free(str);
  leave_function();
}
示例#11
0
static int channel_open(CHANNEL *channel, const char *type_c, int window,
    int maxpacket, BUFFER *payload) {
  SSH_SESSION *session = channel->session;
  STRING *type = NULL;
  u32 tmp = 0;

  enter_function();

  channel->local_channel = ssh_channel_new_id(session);
  channel->local_maxpacket = maxpacket;
  channel->local_window = window;

  ssh_log(session, SSH_LOG_RARE,
      "Creating a channel %d with %d window and %d max packet",
      channel->local_channel, window, maxpacket);

  type = string_from_char(type_c);
  if (type == NULL) {
    leave_function();
    return -1;
  }

  if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_OPEN) < 0 ||
      buffer_add_ssh_string(session->out_buffer,type) < 0 ||
      buffer_add_u32(session->out_buffer, htonl(channel->local_channel)) < 0 ||
      buffer_add_u32(session->out_buffer, htonl(channel->local_window)) < 0 ||
      buffer_add_u32(session->out_buffer, htonl(channel->local_maxpacket)) < 0) {
    string_free(type);
    leave_function();
    return -1;
  }

  string_free(type);

  if (payload != NULL) {
    if (buffer_add_buffer(session->out_buffer, payload) < 0) {
      leave_function();
      return -1;
    }
  }

  if (packet_send(session) != SSH_OK) {
    leave_function();
    return -1;
  }

  ssh_log(session, SSH_LOG_RARE,
      "Sent a SSH_MSG_CHANNEL_OPEN type %s for channel %d",
      type_c, channel->local_channel);

  if (packet_wait(session, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, 1) != SSH_OK) {
    leave_function();
    return -1;
  }

  switch(session->in_packet.type) {
    case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
      buffer_get_u32(session->in_buffer, &tmp);

      if (channel->local_channel != ntohl(tmp)) {
        ssh_set_error(session, SSH_FATAL,
            "Server answered with sender channel number %lu instead of given %u",
            (long unsigned int) ntohl(tmp),
            channel->local_channel);
        leave_function();
        return -1;
      }
      buffer_get_u32(session->in_buffer, &tmp);
      channel->remote_channel = ntohl(tmp);

      buffer_get_u32(session->in_buffer, &tmp);
      channel->remote_window = ntohl(tmp);

      buffer_get_u32(session->in_buffer,&tmp);
      channel->remote_maxpacket=ntohl(tmp);

      ssh_log(session, SSH_LOG_PROTOCOL,
          "Received a CHANNEL_OPEN_CONFIRMATION for channel %d:%d",
          channel->local_channel,
          channel->remote_channel);
      ssh_log(session, SSH_LOG_PROTOCOL,
          "Remote window : %lu, maxpacket : %lu",
          (long unsigned int) channel->remote_window,
          (long unsigned int) channel->remote_maxpacket);

      channel->open = 1;
      leave_function();
      return 0;
    case SSH2_MSG_CHANNEL_OPEN_FAILURE:
      {
        STRING *error_s;
        char *error;
        u32 code;

        buffer_get_u32(session->in_buffer, &tmp);
        buffer_get_u32(session->in_buffer, &code);

        error_s = buffer_get_ssh_string(session->in_buffer);
        error = string_to_char(error_s);
        string_free(error_s);
        if (error == NULL) {
          leave_function();
          return -1;
        }

        ssh_set_error(session, SSH_REQUEST_DENIED,
            "Channel opening failure: channel %u error (%lu) %s",
            channel->local_channel,
            (long unsigned int) ntohl(code),
            error);
        SAFE_FREE(error);

        leave_function();
        return -1;
      }
    default:
      ssh_set_error(session, SSH_FATAL,
          "Received unknown packet %d\n", session->in_packet.type);
      leave_function();
      return -1;
  }

  leave_function();
  return -1;
}
示例#12
0
SFTP_CLIENT_MESSAGE *sftp_get_client_message(SFTP_SESSION *sftp) {
    SFTP_PACKET *packet=sftp_packet_read(sftp);
    SFTP_CLIENT_MESSAGE *msg=malloc(sizeof (SFTP_CLIENT_MESSAGE));
    BUFFER *payload;
    STRING *tmp;
    memset(msg,0,sizeof(SFTP_CLIENT_MESSAGE));
    if(!packet)
        return NULL;
    payload=packet->payload;
    ssh_say(2,"received sftp packet type %d\n",packet->type);
    msg->type=packet->type;
    msg->sftp=sftp;
    buffer_get_u32(payload,&msg->id);
    switch(msg->type) {
    case SSH_FXP_CLOSE:
    case SSH_FXP_READDIR:
        msg->handle=buffer_get_ssh_string(payload);
        break;
    case SSH_FXP_READ:
        msg->handle=buffer_get_ssh_string(payload);
        buffer_get_u64(payload,&msg->offset);
        buffer_get_u32(payload,&msg->len);
        break;
    case SSH_FXP_WRITE:
        msg->handle=buffer_get_ssh_string(payload);
        buffer_get_u64(payload,&msg->offset);
        msg->data=buffer_get_ssh_string(payload);
        break;
    case SSH_FXP_REMOVE:
    case SSH_FXP_RMDIR:
    case SSH_FXP_OPENDIR:
    case SSH_FXP_READLINK:
    case SSH_FXP_REALPATH:
        tmp=buffer_get_ssh_string(payload);
        msg->filename=string_to_char(tmp);
        free(tmp);
        break;
    case SSH_FXP_RENAME:
    case SSH_FXP_SYMLINK:
        tmp=buffer_get_ssh_string(payload);
        msg->filename=string_to_char(tmp);
        free(tmp);
        msg->data=buffer_get_ssh_string(payload);
        break;
    case SSH_FXP_MKDIR:
    case SSH_FXP_SETSTAT:
        tmp=buffer_get_ssh_string(payload);
        msg->filename=string_to_char(tmp);
        free(tmp);
        msg->attr=sftp_parse_attr(sftp, payload,0);
        break;
    case SSH_FXP_FSETSTAT:
        msg->handle=buffer_get_ssh_string(payload);
        msg->attr=sftp_parse_attr(sftp, payload,0);
        break;
    case SSH_FXP_LSTAT:
    case SSH_FXP_STAT:
        tmp=buffer_get_ssh_string(payload);
        msg->filename=string_to_char(tmp);
        free(tmp);
        if(sftp->version >3)
            buffer_get_u32(payload,&msg->flags);
        break;
    case SSH_FXP_OPEN:
        tmp=buffer_get_ssh_string(payload);
        msg->filename=string_to_char(tmp);
        free(tmp);
        buffer_get_u32(payload,&msg->flags);
        msg->attr=sftp_parse_attr(sftp, payload,0);
    case SSH_FXP_FSTAT:
        msg->handle=buffer_get_ssh_string(payload);
        buffer_get_u32(payload,&msg->flags);
        break;
    default:
        printf("Received handled sftp message %d\n",msg->type);
    }
    msg->flags=ntohl(msg->flags);
    msg->offset=ntohll(msg->offset);
    msg->len=ntohl(msg->len);
    sftp_packet_free(packet);
    return msg;
}
示例#13
0
void packet_parse(SSH_SESSION *session) {
  STRING *error_s = NULL;
  char *error = NULL;
  int type = session->in_packet.type;
  u32 tmp;

#ifdef HAVE_SSH1
  if (session->version == 1) {
    /* SSH-1 */
    switch(type) {
      case SSH_MSG_DISCONNECT:
        ssh_log(session, SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT");
        ssh_set_error(session, SSH_FATAL, "Received SSH_MSG_DISCONNECT");

        ssh_socket_close(session->socket);
        session->alive = 0;
        return;
      case SSH_SMSG_STDOUT_DATA:
      case SSH_SMSG_STDERR_DATA:
      case SSH_SMSG_EXITSTATUS:
        channel_handle1(session,type);
        return;
      case SSH_MSG_DEBUG:
      case SSH_MSG_IGNORE:
        break;
      default:
        ssh_log(session, SSH_LOG_PACKET,
            "Unexpected message code %d", type);
    }
    return;
  } else {
#endif /* HAVE_SSH1 */
    switch(type) {
      case SSH2_MSG_DISCONNECT:
        buffer_get_u32(session->in_buffer, &tmp);
        error_s = buffer_get_ssh_string(session->in_buffer);
        if (error_s == NULL) {
          return;
        }
        error = string_to_char(error_s);
        string_free(error_s);
        if (error == NULL) {
          return;
        }
        ssh_log(session, SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT\n");
        ssh_set_error(session, SSH_FATAL,
            "Received SSH_MSG_DISCONNECT: %s",error);

        SAFE_FREE(error);

        ssh_socket_close(session->socket);
        session->alive = 0;

        return;
      case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
      case SSH2_MSG_CHANNEL_DATA:
      case SSH2_MSG_CHANNEL_EXTENDED_DATA:
      case SSH2_MSG_CHANNEL_REQUEST:
      case SSH2_MSG_CHANNEL_EOF:
      case SSH2_MSG_CHANNEL_CLOSE:
        channel_handle(session,type);
      case SSH2_MSG_IGNORE:
      case SSH2_MSG_DEBUG:
        return;
      default:
        ssh_log(session, SSH_LOG_RARE, "Received unhandled packet %d", type);
    }
#ifdef HAVE_SSH1
  }
#endif
}
示例#14
0
static int kbdauth_info_get(ssh_session session) {
  ssh_string name; /* name of the "asking" window showed to client */
  ssh_string instruction;
  ssh_string tmp;
  uint32_t nprompts;
  uint32_t i;

  enter_function();

  name = buffer_get_ssh_string(session->in_buffer);
  instruction = buffer_get_ssh_string(session->in_buffer);
  tmp = buffer_get_ssh_string(session->in_buffer);
  buffer_get_u32(session->in_buffer, &nprompts);

  if (name == NULL || instruction == NULL || tmp == NULL) {
    string_free(name);
    string_free(instruction);
    /* tmp if empty if we got here */
    ssh_set_error(session, SSH_FATAL, "Invalid USERAUTH_INFO_REQUEST msg");
    leave_function();
    return SSH_AUTH_ERROR;
  }
  string_free(tmp);

  if (session->kbdint == NULL) {
    session->kbdint = kbdint_new();
    if (session->kbdint == NULL) {
      ssh_set_error(session, SSH_FATAL, "Not enough space");
      string_free(name);
      string_free(instruction);

      leave_function();
      return SSH_AUTH_ERROR;
    }
  } else {
    kbdint_clean(session->kbdint);
  }

  session->kbdint->name = string_to_char(name);
  string_free(name);
  if (session->kbdint->name == NULL) {
    ssh_set_error(session, SSH_FATAL, "Not enough space");
    kbdint_free(session->kbdint);
    leave_function();
    return SSH_AUTH_ERROR;
  }

  session->kbdint->instruction = string_to_char(instruction);
  string_free(instruction);
  if (session->kbdint->instruction == NULL) {
    ssh_set_error(session, SSH_FATAL, "Not enough space");
    kbdint_free(session->kbdint);
    session->kbdint = NULL;
    leave_function();
    return SSH_AUTH_ERROR;
  }

  nprompts = ntohl(nprompts);
  if (nprompts > KBDINT_MAX_PROMPT) {
    ssh_set_error(session, SSH_FATAL,
        "Too much prompt asked from server: %u (0x%.4x)",
        nprompts, nprompts);
    kbdint_free(session->kbdint);
    session->kbdint = NULL;
    leave_function();
    return SSH_AUTH_ERROR;
  }

  session->kbdint->nprompts = nprompts;
  session->kbdint->prompts = malloc(nprompts * sizeof(char *));
  if (session->kbdint->prompts == NULL) {
    session->kbdint->nprompts = 0;
    ssh_set_error(session, SSH_FATAL, "No space left");
    kbdint_free(session->kbdint);
    session->kbdint = NULL;
    leave_function();
    return SSH_AUTH_ERROR;
  }
  memset(session->kbdint->prompts, 0, nprompts * sizeof(char *));

  session->kbdint->echo = malloc(nprompts);
  if (session->kbdint->echo == NULL) {
    session->kbdint->nprompts = 0;
    ssh_set_error(session, SSH_FATAL, "No space left");
    kbdint_free(session->kbdint);
    session->kbdint = NULL;
    leave_function();
    return SSH_AUTH_ERROR;
  }
  memset(session->kbdint->echo, 0, nprompts);

  for (i = 0; i < nprompts; i++) {
    tmp = buffer_get_ssh_string(session->in_buffer);
    buffer_get_u8(session->in_buffer, &session->kbdint->echo[i]);
    if (tmp == NULL) {
      ssh_set_error(session, SSH_FATAL, "Short INFO_REQUEST packet");
      kbdint_free(session->kbdint);
      session->kbdint = NULL;
      leave_function();
      return SSH_AUTH_ERROR;
    }
    session->kbdint->prompts[i] = string_to_char(tmp);
    string_free(tmp);
    if (session->kbdint->prompts[i] == NULL) {
      ssh_set_error(session, SSH_FATAL, "Not enough space");
      kbdint_free(session->kbdint);
      session->kbdint = NULL;
      leave_function();
      return SSH_AUTH_ERROR;
    }
  }

  leave_function();
  return SSH_AUTH_INFO; /* we are not auth. but we parsed the packet */
}
示例#15
0
int ssh_get_kex1(SSH_SESSION *session){
    u32 server_bits, host_bits, protocol_flags, 
        supported_ciphers_mask, supported_authentications_mask;
    STRING *server_exp=NULL;
    STRING *server_mod=NULL;
    STRING *host_exp=NULL;
    STRING *host_mod=NULL;
    STRING *serverkey;
    STRING *hostkey;
    STRING *enc_session;
    PUBLIC_KEY *svr,*host;
    int ko;
    u16 bits;
    ssh_say(3,"Waiting for a SSH_SMSG_PUBLIC_KEY\n");
    if(packet_wait(session,SSH_SMSG_PUBLIC_KEY,1)){
        return -1;
    }
    ssh_say(3,"Got a SSH_SMSG_PUBLIC_KEY\n");
    if(buffer_get_data(session->in_buffer,session->server_kex.cookie,8)!=8){
        ssh_set_error(NULL,SSH_FATAL,"Can't get cookie in buffer");
        return -1;
    }
    buffer_get_u32(session->in_buffer,&server_bits);
    server_exp=buffer_get_mpint(session->in_buffer);
    server_mod=buffer_get_mpint(session->in_buffer);
    buffer_get_u32(session->in_buffer,&host_bits);
    host_exp=buffer_get_mpint(session->in_buffer);
    host_mod=buffer_get_mpint(session->in_buffer);
    buffer_get_u32(session->in_buffer,&protocol_flags);
    buffer_get_u32(session->in_buffer,&supported_ciphers_mask);
    ko=buffer_get_u32(session->in_buffer,&supported_authentications_mask);
    if((ko!=sizeof(u32)) || !host_mod || !host_exp || !server_mod || !server_exp){
        ssh_say(2,"Invalid SSH_SMSG_PUBLIC_KEY packet\n");
        ssh_set_error(NULL,SSH_FATAL,"Invalid SSH_SMSG_PUBLIC_KEY packet");
        if(host_mod)
            free(host_mod);
        if(host_exp)
            free(host_exp);
        if(server_mod)
            free(server_mod);
        if(server_exp)
            free(server_exp);
        return -1;
    }
    server_bits=ntohl(server_bits);
    host_bits=ntohl(host_bits);
    protocol_flags=ntohl(protocol_flags);
    supported_ciphers_mask=ntohl(supported_ciphers_mask);
    supported_authentications_mask=ntohl(supported_authentications_mask);
    ssh_say(1,"server bits: %d ; host bits: %d\nProtocol flags : %.8lx ; "
            "cipher mask : %.8lx ; auth mask: %.8lx\n",server_bits,
            host_bits,protocol_flags,supported_ciphers_mask,
            supported_authentications_mask);
    serverkey=make_rsa1_string(server_exp,server_mod);
    hostkey=make_rsa1_string(host_exp,host_mod);
    build_session_id1(session,server_mod,host_mod);
    free(server_exp);
    free(server_mod);
    free(host_exp);
    free(host_mod);
    svr=publickey_from_string(serverkey);
    host=publickey_from_string(hostkey);
    session->next_crypto->server_pubkey=string_copy(hostkey);
    session->next_crypto->server_pubkey_type="ssh-rsa1";

    /* now, we must choose an encryption algo */
    /* hardcode 3des */
    if(!(supported_ciphers_mask & (1<<SSH_CIPHER_3DES))){
        ssh_set_error(NULL,SSH_FATAL,"Remote server doesn't accept 3des");
        return -1;
    }
    packet_clear_out(session);
    buffer_add_u8(session->out_buffer,SSH_CMSG_SESSION_KEY);
    buffer_add_u8(session->out_buffer,SSH_CIPHER_3DES);
    buffer_add_data(session->out_buffer,session->server_kex.cookie,8);
    
    enc_session=encrypt_session_key(session,svr,host,server_bits, host_bits);
    bits=string_len(enc_session)*8 - 7;
    ssh_say(2,"%d bits,%d bytes encrypted session\n",bits,string_len(enc_session));
    bits=htons(bits);
    /* the encrypted mpint */
    buffer_add_data(session->out_buffer,&bits,sizeof(u16));
    buffer_add_data(session->out_buffer,enc_session->string,
            string_len(enc_session));
    /* the protocol flags */
    buffer_add_u32(session->out_buffer,0);

    packet_send(session); 
    /* we can set encryption */
    if(crypt_set_algorithms(session))
        return -1;
    session->current_crypto=session->next_crypto;
    session->next_crypto=NULL;
    if(packet_wait(session,SSH_SMSG_SUCCESS,1)){
        char buffer[1024];
        snprintf(buffer,sizeof(buffer),"Key exchange failed : %s",ssh_get_error(session));
        ssh_set_error(session,SSH_FATAL,"%s",buffer);
        return -1;
    }
    ssh_say(1,"received SSH_SMSG_SUCCESS\n");
    return 0;
    
}