Exemplo n.º 1
0
/**
 * @brief  Free an event context.
 *
 * @param  event        The ssh_event object to free.
 *                      Note: you have to manually remove sessions and socket
 *                      fds before freeing the event object.
 *
 */
void ssh_event_free(ssh_event event) {
    int used, i;
    ssh_poll_handle p;
    if(event == NULL) {
        return;
    }
    if(event->ctx != NULL) {
        used = event->ctx->polls_used;
        for(i = 0; i < used; i++) {
            p = event->ctx->pollptrs[i];
            if(p->session != NULL) {
                ssh_poll_ctx_remove(event->ctx, p);
                ssh_poll_ctx_add(p->session->default_poll_ctx, p);
                p->session = NULL;
                used = 0;
            }
        }

        ssh_poll_ctx_free(event->ctx);
    }
#ifdef WITH_SERVER
    if(event->sessions != NULL) {
        ssh_list_free(event->sessions);
    }
#endif
    free(event);
}
Exemplo n.º 2
0
/**
 * @brief  Free an event context.
 *
 * @param  event        The ssh_event object to free.
 *                      Note: you have to manually remove sessions and socket
 *                      fds before freeing the event object.
 *
 */
void ssh_event_free(ssh_event event) {
    if(event == NULL) {
        return;
    }
    if(event->ctx != NULL) {
        ssh_poll_ctx_free(event->ctx);
    }
#ifdef WITH_SERVER
    if(event->sessions != NULL) {
        ssh_list_free(event->sessions);
    }
#endif
    free(event);
}
Exemplo n.º 3
0
/**
 * @brief Disconnect from a session (client or server).
 * The session can then be reused to open a new session.
 *
 * @param[in]  session  The SSH session to use.
 */
void ssh_disconnect(ssh_session session) {
  ssh_string str = NULL;
  struct ssh_iterator *it;

  if (session == NULL) {
    return;
  }

  if (session->socket != NULL && ssh_socket_is_open(session->socket)) {
    if (buffer_add_u8(session->out_buffer, SSH2_MSG_DISCONNECT) < 0) {
      goto error;
    }
    if (buffer_add_u32(session->out_buffer,
          htonl(SSH2_DISCONNECT_BY_APPLICATION)) < 0) {
      goto error;
    }

    str = ssh_string_from_char("Bye Bye");
    if (str == NULL) {
      goto error;
    }

    if (buffer_add_ssh_string(session->out_buffer,str) < 0) {
      ssh_string_free(str);
      goto error;
    }
    ssh_string_free(str);

    packet_send(session);
    ssh_socket_close(session->socket);
  }
error:
  session->alive = 0;
  if (session->socket != NULL){
    ssh_socket_reset(session->socket);
  }
  session->opts.fd = SSH_INVALID_SOCKET;
  session->session_state=SSH_SESSION_STATE_DISCONNECTED;

  while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
    ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
    ssh_list_remove(session->channels, it);
  }
  if(session->current_crypto){
    crypto_free(session->current_crypto);
    session->current_crypto=NULL;
  }
  if (session->in_buffer) {
    ssh_buffer_reinit(session->in_buffer);
  }
  if (session->out_buffer) {
    ssh_buffer_reinit(session->out_buffer);
  }
  if (session->in_hashbuf) {
    ssh_buffer_reinit(session->in_hashbuf);
  }
  if (session->out_hashbuf) {
    ssh_buffer_reinit(session->out_hashbuf);
  }
  session->auth_methods = 0;
  SAFE_FREE(session->serverbanner);
  SAFE_FREE(session->clientbanner);

  if(session->ssh_message_list){
    ssh_message msg;
    while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list))
        != NULL){
      ssh_message_free(msg);
    }
    ssh_list_free(session->ssh_message_list);
    session->ssh_message_list=NULL;
  }

  if (session->packet_callbacks){
    ssh_list_free(session->packet_callbacks);
    session->packet_callbacks=NULL;
  }
}
Exemplo n.º 4
0
/**
 * @brief Deallocate a SSH session handle.
 *
 * @param[in] session   The SSH session to free.
 *
 * @see ssh_disconnect()
 * @see ssh_new()
 */
void ssh_free(ssh_session session) {
  int i;
  struct ssh_iterator *it;

  if (session == NULL) {
    return;
  }

  /*
   * Delete all channels
   *
   * This needs the first thing we clean up cause if there is still an open
   * channel we call ssh_channel_close() first. So we need a working socket
   * and poll context for it.
   */
  for (it = ssh_list_get_iterator(session->channels);
       it != NULL;
       it = ssh_list_get_iterator(session->channels)) {
      ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
      ssh_list_remove(session->channels, it);
  }
  ssh_list_free(session->channels);
  session->channels = NULL;

#ifdef WITH_PCAP
  if (session->pcap_ctx) {
      ssh_pcap_context_free(session->pcap_ctx);
      session->pcap_ctx = NULL;
  }
#endif

  ssh_socket_free(session->socket);
  session->socket = NULL;

  if (session->default_poll_ctx) {
      ssh_poll_ctx_free(session->default_poll_ctx);
  }

  ssh_buffer_free(session->in_buffer);
  ssh_buffer_free(session->out_buffer);
  session->in_buffer = session->out_buffer = NULL;

  if (session->in_hashbuf != NULL) {
      ssh_buffer_free(session->in_hashbuf);
  }
  if (session->out_hashbuf != NULL) {
      ssh_buffer_free(session->out_hashbuf);
  }

  crypto_free(session->current_crypto);
  crypto_free(session->next_crypto);

#ifndef _WIN32
  agent_free(session->agent);
#endif /* _WIN32 */

  ssh_key_free(session->srv.dsa_key);
  ssh_key_free(session->srv.rsa_key);

  if (session->ssh_message_list) {
      ssh_message msg;

      for (msg = ssh_list_pop_head(ssh_message, session->ssh_message_list);
           msg != NULL;
           msg = ssh_list_pop_head(ssh_message, session->ssh_message_list)) {
          ssh_message_free(msg);
      }
      ssh_list_free(session->ssh_message_list);
  }

  if (session->packet_callbacks) {
    ssh_list_free(session->packet_callbacks);
  }

  /* options */
  if (session->opts.identity) {
      char *id;

      for (id = ssh_list_pop_head(char *, session->opts.identity);
           id != NULL;
           id = ssh_list_pop_head(char *, session->opts.identity)) {
          SAFE_FREE(id);
      }
      ssh_list_free(session->opts.identity);
  }
Exemplo n.º 5
0
static void torture_knownhosts_precheck(void **state)
{
    struct torture_state *s = *state;
    ssh_session session = s->ssh.session;
    struct ssh_list *algo_list = NULL;
    struct ssh_iterator *it = NULL;
    size_t algo_count;
    const char *algo = NULL;
    char known_hosts_file[1024] = {0};
    FILE *file;
    int rc;

    snprintf(known_hosts_file,
             sizeof(known_hosts_file),
             "%s/%s",
             s->socket_dir,
             TORTURE_KNOWN_HOSTS_FILE);

    file = fopen(known_hosts_file, "w");
    assert_non_null(file);
    fprintf(file,
            "127.0.0.10 %s\n",
            torture_get_testkey_pub(SSH_KEYTYPE_RSA));

    fprintf(file,
            "127.0.0.10 %s\n",
            torture_get_testkey_pub(SSH_KEYTYPE_ED25519));

    fprintf(file,
            "127.0.0.10 %s\n",
            torture_get_testkey_pub(SSH_KEYTYPE_ECDSA_P521));

    fclose(file);

    rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file);
    assert_ssh_return_code(session, rc);

    algo_list = ssh_known_hosts_get_algorithms(session);
    assert_non_null(algo_list);

    algo_count = ssh_list_count(algo_list);
    assert_int_equal(algo_count, 3);

    it = ssh_list_get_iterator(algo_list);
    assert_non_null(it);
    algo = ssh_iterator_value(const char *, it);
    assert_string_equal(algo, "ssh-rsa");

    ssh_list_remove(algo_list, it);

    it = ssh_list_get_iterator(algo_list);
    assert_non_null(it);
    algo = ssh_iterator_value(const char *, it);
    assert_string_equal(algo, "ssh-ed25519");

    ssh_list_remove(algo_list, it);

    it = ssh_list_get_iterator(algo_list);
    assert_non_null(it);
    algo = ssh_iterator_value(const char *, it);
    assert_string_equal(algo, "ecdsa-sha2-nistp521");

    ssh_list_free(algo_list);
}
Exemplo n.º 6
0
/**
 * @brief Disconnect from a session (client or server).
 * The session can then be reused to open a new session.
 *
 * @param[in]  session  The SSH session to use.
 */
void ssh_disconnect(ssh_session session) {
  ssh_string str = NULL;
  int i;

  if (session == NULL) {
    return;
  }

  enter_function();

  if (ssh_socket_is_open(session->socket)) {
    if (buffer_add_u8(session->out_buffer, SSH2_MSG_DISCONNECT) < 0) {
      goto error;
    }
    if (buffer_add_u32(session->out_buffer,
          htonl(SSH2_DISCONNECT_BY_APPLICATION)) < 0) {
      goto error;
    }

    str = ssh_string_from_char("Bye Bye");
    if (str == NULL) {
      goto error;
    }

    if (buffer_add_ssh_string(session->out_buffer,str) < 0) {
      ssh_string_free(str);
      goto error;
    }
    ssh_string_free(str);

    packet_send(session);
    ssh_socket_close(session->socket);
  }
error:
  session->alive = 0;
  if(session->socket){
    ssh_socket_reset(session->socket);
  }
  session->fd = SSH_INVALID_SOCKET;
  session->session_state=SSH_SESSION_STATE_DISCONNECTED;
  while (session->channels) {
    ssh_channel_free(session->channels);
  }
  if(session->current_crypto){
    crypto_free(session->current_crypto);
    session->current_crypto=NULL;
  }
  if(session->in_buffer)
    buffer_reinit(session->in_buffer);
  if(session->out_buffer)
    buffer_reinit(session->out_buffer);
  if(session->in_hashbuf)
    buffer_reinit(session->in_hashbuf);
  if(session->out_hashbuf)
    buffer_reinit(session->out_hashbuf);
  session->auth_methods = 0;
  SAFE_FREE(session->serverbanner);
  SAFE_FREE(session->clientbanner);
  if (session->client_kex.methods) {
    for (i = 0; i < 10; i++) {
      SAFE_FREE(session->client_kex.methods[i]);
    }
  }

  if (session->server_kex.methods) {
    for (i = 0; i < 10; i++) {
      SAFE_FREE(session->server_kex.methods[i]);
    }
  }
  SAFE_FREE(session->client_kex.methods);
  SAFE_FREE(session->server_kex.methods);
  if(session->ssh_message_list){
    ssh_message msg;
    while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list))
        != NULL){
      ssh_message_free(msg);
    }
    ssh_list_free(session->ssh_message_list);
    session->ssh_message_list=NULL;
  }

  if (session->packet_callbacks){
    ssh_list_free(session->packet_callbacks);
    session->packet_callbacks=NULL;
  }

  leave_function();
}
Exemplo n.º 7
0
/**
 * @brief Disconnect from a session (client or server).
 * The session can then be reused to open a new session.
 *
 * @param[in]  session  The SSH session to use.
 */
void ssh_disconnect(ssh_session session) {
  struct ssh_iterator *it;
  int rc;

  if (session == NULL) {
    return;
  }

  if (session->socket != NULL && ssh_socket_is_open(session->socket)) {
    rc = ssh_buffer_pack(session->out_buffer,
                         "bdss",
                         SSH2_MSG_DISCONNECT,
                         SSH2_DISCONNECT_BY_APPLICATION,
                         "Bye Bye",
                         ""); /* language tag */
    if (rc != SSH_OK){
      ssh_set_error_oom(session);
      goto error;
    }

    ssh_packet_send(session);
    ssh_socket_close(session->socket);
  }
error:
  session->recv_seq = 0;
  session->send_seq = 0;
  session->alive = 0;
  if (session->socket != NULL){
    ssh_socket_reset(session->socket);
  }
  session->opts.fd = SSH_INVALID_SOCKET;
  session->session_state=SSH_SESSION_STATE_DISCONNECTED;

  while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
    ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
    ssh_list_remove(session->channels, it);
  }
  if(session->current_crypto){
    crypto_free(session->current_crypto);
    session->current_crypto=NULL;
  }
  if (session->next_crypto) {
    crypto_free(session->next_crypto);
    session->next_crypto = crypto_new();
    if (session->next_crypto == NULL) {
      ssh_set_error_oom(session);
    }
  }
  if (session->in_buffer) {
    ssh_buffer_reinit(session->in_buffer);
  }
  if (session->out_buffer) {
    ssh_buffer_reinit(session->out_buffer);
  }
  if (session->in_hashbuf) {
    ssh_buffer_reinit(session->in_hashbuf);
  }
  if (session->out_hashbuf) {
    ssh_buffer_reinit(session->out_hashbuf);
  }
  session->auth.supported_methods = 0;
  SAFE_FREE(session->serverbanner);
  SAFE_FREE(session->clientbanner);

  if(session->ssh_message_list){
    ssh_message msg;
    while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list))
        != NULL){
      ssh_message_free(msg);
    }
    ssh_list_free(session->ssh_message_list);
    session->ssh_message_list=NULL;
  }

  if (session->packet_callbacks){
    ssh_list_free(session->packet_callbacks);
    session->packet_callbacks=NULL;
  }
}
Exemplo n.º 8
0
static void torture_callbacks_execute_list(void **state){
    struct ssh_list *list = ssh_list_new();
    int v = 0, w = 0;
    struct ssh_channel_callbacks_struct c1 = {
            .channel_eof_function = cb1,
            .userdata = &v
    };
    struct ssh_channel_callbacks_struct c2 = {
            .channel_exit_status_function = cb2,
            .userdata = &v
    };
    struct ssh_channel_callbacks_struct c3 = {
            .channel_eof_function = cb1,
            .channel_exit_status_function = cb2,
            .userdata = &w
    };

    (void)state;
    ssh_callbacks_init(&c1);
    ssh_callbacks_init(&c2);
    ssh_callbacks_init(&c3);

    ssh_list_append(list, &c1);
    ssh_callbacks_execute_list(list,
                               ssh_channel_callbacks,
                               channel_eof_function,
                               NULL,
                               NULL);
    assert_int_equal(v, 1);

    v = 0;
    ssh_list_append(list, &c2);
    ssh_callbacks_execute_list(list,
                               ssh_channel_callbacks,
                               channel_eof_function,
                               NULL,
                               NULL);
    assert_int_equal(v, 1);
    ssh_callbacks_execute_list(list,
                               ssh_channel_callbacks,
                               channel_exit_status_function,
                               NULL,
                               NULL,
                               0);
    assert_int_equal(v, 11);

    v = 0;
    w = 0;
    ssh_list_append(list, &c3);
    ssh_callbacks_execute_list(list,
                               ssh_channel_callbacks,
                               channel_eof_function,
                               NULL,
                               NULL);
    assert_int_equal(v, 1);
    assert_int_equal(w, 1);
    ssh_callbacks_execute_list(list,
                               ssh_channel_callbacks,
                               channel_exit_status_function,
                               NULL,
                               NULL,
                               0);
    assert_int_equal(v, 11);
    assert_int_equal(w, 11);

    ssh_list_free(list);

}
Exemplo n.º 9
0
Arquivo: kex.c Projeto: simonsj/libssh
/**
 * @internal
 * @brief selects the hostkey mechanisms to be chosen for the key exchange,
 * as some hostkey mechanisms may be present in known_hosts file and preferred
 * @returns a cstring containing a comma-separated list of hostkey methods.
 *          NULL if no method matches
 */
char *ssh_client_select_hostkeys(ssh_session session)
{
    char methods_buffer[128]={0};
    char tail_buffer[128]={0};
    char *new_hostkeys = NULL;
    static const char *preferred_hostkeys[] = {
        "ssh-ed25519",
        "ecdsa-sha2-nistp521",
        "ecdsa-sha2-nistp384",
        "ecdsa-sha2-nistp256",
        "rsa-sha2-512",
        "rsa-sha2-256",
        "ssh-rsa",
#ifdef HAVE_DSA
        "ssh-dss",
#endif
        NULL
    };
    struct ssh_list *algo_list = NULL;
    struct ssh_iterator *it = NULL;
    size_t algo_count;
    int needcomma = 0;
    size_t i, len;

    algo_list = ssh_known_hosts_get_algorithms(session);
    if (algo_list == NULL) {
        return NULL;
    }

    algo_count = ssh_list_count(algo_list);
    if (algo_count == 0) {
        ssh_list_free(algo_list);
        return NULL;
    }

    for (i = 0; preferred_hostkeys[i] != NULL; ++i) {
        bool found = false;
        /* This is a signature type: We list also the SHA2 extensions */
        enum ssh_keytypes_e base_preferred =
            ssh_key_type_from_signature_name(preferred_hostkeys[i]);

        for (it = ssh_list_get_iterator(algo_list);
             it != NULL;
             it = it->next) {
            const char *algo = ssh_iterator_value(const char *, it);
            /* This is always key type so we do not have to care for the
             * SHA2 extension */
            enum ssh_keytypes_e base_algo = ssh_key_type_from_name(algo);

            if (base_preferred == base_algo) {
                /* Matching the keys already verified it is a known type */
                if (needcomma) {
                    strncat(methods_buffer,
                            ",",
                            sizeof(methods_buffer) - strlen(methods_buffer) - 1);
                }
                strncat(methods_buffer,
                        preferred_hostkeys[i],
                        sizeof(methods_buffer) - strlen(methods_buffer) - 1);
                needcomma = 1;
                found = true;
            }
        }
        /* Collect the rest of the algorithms in other buffer, that will
         * follow the preferred buffer. This will signalize all the algorithms
         * we are willing to accept.
         */
        if (!found) {
            snprintf(tail_buffer + strlen(tail_buffer),
                     sizeof(tail_buffer) - strlen(tail_buffer),
                     ",%s", preferred_hostkeys[i]);
        }
    }
    ssh_list_free(algo_list);

    if (strlen(methods_buffer) == 0) {
        SSH_LOG(SSH_LOG_DEBUG,
                "No supported kex method for existing key in known_hosts file");
        return NULL;
    }

    /* Append the supported list to the preferred.
     * The length is maximum 128 + 128 + 1, which will not overflow
     */
    len = strlen(methods_buffer) + strlen(tail_buffer) + 1;
    new_hostkeys = malloc(len);
    if (new_hostkeys == NULL) {
        ssh_set_error_oom(session);
        return NULL;
    }
    snprintf(new_hostkeys, len,
             "%s%s", methods_buffer, tail_buffer);

    SSH_LOG(SSH_LOG_DEBUG,
            "Changing host key method to \"%s\"",
            new_hostkeys);

    return new_hostkeys;
}