Beispiel #1
0
static void remmina_nx_session_send_command(RemminaNXSession *nx, const gchar *cmdfmt, ...)
{
	va_list args;
	gchar *cmd;

	va_start (args, cmdfmt);
	cmd = g_strdup_vprintf (cmdfmt, args);
	channel_write (nx->channel, cmd, strlen (cmd));
	g_free(cmd);

	ssh_set_fd_towrite (nx->session);
	channel_write (nx->channel, "\n", 1);
}
Beispiel #2
0
static gpointer remmina_nx_session_tunnel_main_thread(gpointer data)
{
	RemminaNXSession *nx = (RemminaNXSession*) data;
	gchar *ptr;
	ssize_t len = 0, lenw = 0;
	fd_set set;
	struct timeval timeout;
	ssh_channel channels[2];
	ssh_channel channels_out[2];
	gint sock;
	gint ret;
	gchar buffer[10240];
	gchar socketbuffer[10240];
	gchar *socketbuffer_ptr = NULL;
	gint socketbuffer_len = 0;

	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

	/* Accept a local connection */
	sock = accept(nx->server_sock, NULL, NULL);
	if (sock < 0)
	{
		remmina_nx_session_set_application_error(nx, "Failed to accept local socket");
		nx->thread = 0;
		return NULL;
	}
	close(nx->server_sock);
	nx->server_sock = -1;

	channels[0] = nx->channel;
	channels[1] = NULL;

	/* Start the tunnel data transmittion */
	while (nx->running)
	{
		timeout.tv_sec = 1;
		timeout.tv_usec = 0;

		FD_ZERO(&set);
		FD_SET(sock, &set);

		ret = ssh_select(channels, channels_out, sock + 1, &set, &timeout);
		if (!nx->running)
			break;
		if (ret == SSH_EINTR)
			continue;
		if (ret == -1)
			break;

		if (FD_ISSET(sock, &set))
		{
			len = read(sock, buffer, sizeof(buffer));
			if (len == 0)
				nx->running = FALSE;
			else
				if (len > 0)
				{
					for (ptr = buffer, lenw = 0; len > 0; len -= lenw, ptr += lenw)
					{
						ssh_set_fd_towrite(nx->session);
						lenw = channel_write(channels[0], (char*) ptr, len);
						if (lenw <= 0)
						{
							nx->running = FALSE;
							break;
						}
					}
				}
		}

		if (!nx->running)
			break;

		if (channels_out[0] && socketbuffer_len <= 0)
		{
			len = channel_read_nonblocking(channels_out[0], socketbuffer, sizeof(socketbuffer), 0);
			if (len == SSH_ERROR || len == SSH_EOF)
			{
				nx->running = FALSE;
				break;
			}
			else
				if (len > 0)
				{
					socketbuffer_ptr = socketbuffer;
					socketbuffer_len = len;
				}
				else
				{
					/* Clean up the stderr buffer in case FreeNX send something there */
					len = channel_read_nonblocking(channels_out[0], buffer, sizeof(buffer), 1);
				}
		}

		if (nx->running && socketbuffer_len > 0)
		{
			for (lenw = 0; socketbuffer_len > 0; socketbuffer_len -= lenw, socketbuffer_ptr += lenw)
			{
				lenw = write(sock, socketbuffer_ptr, socketbuffer_len);
				if (lenw == -1 && errno == EAGAIN && nx->running)
				{
					/* Sometimes we cannot write to a socket (always EAGAIN), probably because it's internal
					 * buffer is full. We need read the pending bytes from the socket first. so here we simply
					 * break, leave the buffer there, and continue with other data */
					break;
				}
				if (lenw <= 0)
				{
					nx->running = FALSE;
					break;
				}
			}
		}
	}

	nx->thread = 0;

	return NULL;
}
Beispiel #3
0
/**
 * @internal
 *
 * @brief A function to be called each time a step has been done in the
 * connection.
 */
static void ssh_client_connection_callback(ssh_session session){
	int ssh1,ssh2;

	switch(session->session_state){
		case SSH_SESSION_STATE_NONE:
		case SSH_SESSION_STATE_CONNECTING:
			break;
		case SSH_SESSION_STATE_SOCKET_CONNECTED:
            /* If SSHv1 is disabled, we can send the banner immedietly */
            if (session->opts.ssh1 == 0) {
                ssh_set_fd_towrite(session);
                ssh_send_banner(session, 0);
            }
			break;
		case SSH_SESSION_STATE_BANNER_RECEIVED:
		  if (session->serverbanner == NULL) {
		    goto error;
		  }
		  set_status(session, 0.4f);
		  SSH_LOG(SSH_LOG_RARE,
		      "SSH server banner: %s", session->serverbanner);

		  /* Here we analyze the different protocols the server allows. */
		  if (ssh_analyze_banner(session, 0, &ssh1, &ssh2) < 0) {
		    goto error;
		  }
		  /* Here we decide which version of the protocol to use. */
		  if (ssh2 && session->opts.ssh2) {
		    session->version = 2;
#ifdef WITH_SSH1
		    } else if(ssh1 && session->opts.ssh1) {
		    session->version = 1;
#endif
		    } else if(ssh1 && !session->opts.ssh1){
#ifdef WITH_SSH1
		    ssh_set_error(session, SSH_FATAL,
		        "SSH-1 protocol not available (configure session to allow SSH-1)");
		    goto error;
#else
		    ssh_set_error(session, SSH_FATAL,
		        "SSH-1 protocol not available (libssh compiled without SSH-1 support)");
		    goto error;
#endif
		  } else {
		    ssh_set_error(session, SSH_FATAL,
		        "No version of SSH protocol usable (banner: %s)",
		        session->serverbanner);
		    goto error;
		  }
		  /* from now, the packet layer is handling incoming packets */
		  if (session->version == 2) {
		      ssh_packet_register_socket_callback(session, session->socket);
		  }
#ifdef WITH_SSH1
		  else
		    session->socket_callbacks.data=ssh_packet_socket_callback1;
#endif
		  ssh_packet_set_default_callbacks(session);
		  session->session_state=SSH_SESSION_STATE_INITIAL_KEX;
          if (session->opts.ssh1 == 1) {
              ssh_send_banner(session, 0);
          }
		  set_status(session, 0.5f);
		  break;
		case SSH_SESSION_STATE_INITIAL_KEX:
		/* TODO: This state should disappear in favor of get_key handle */
#ifdef WITH_SSH1
			if(session->version==1){
				if (ssh_get_kex1(session) < 0)
					goto error;
				set_status(session,0.6f);
				session->connected = 1;
				break;
			}
#endif
			break;
		case SSH_SESSION_STATE_KEXINIT_RECEIVED:
			set_status(session,0.6f);
			ssh_list_kex(&session->next_crypto->server_kex);
			if (ssh_set_client_kex(session) < 0) {
				goto error;
			}
			if (ssh_kex_select_methods(session) == SSH_ERROR)
			    goto error;
			if (ssh_send_kex(session, 0) < 0) {
				goto error;
			}
			set_status(session,0.8f);
			session->session_state=SSH_SESSION_STATE_DH;
			if (dh_handshake(session) == SSH_ERROR) {
				goto error;
			}
            /* FALL THROUGH */
		case SSH_SESSION_STATE_DH:
			if(session->dh_handshake_state==DH_STATE_FINISHED){
				set_status(session,1.0f);
				session->connected = 1;
				if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
				    session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
				else
				    session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
			}
			break;
		case SSH_SESSION_STATE_AUTHENTICATING:
			break;
		case SSH_SESSION_STATE_ERROR:
			goto error;
		default:
			ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state);
	}

	return;
error:
	ssh_socket_close(session->socket);
	session->alive = 0;
	session->session_state=SSH_SESSION_STATE_ERROR;

}
Beispiel #4
0
/**
 * @internal
 *
 * @brief A function to be called each time a step has been done in the
 * connection.
 */
static void ssh_client_connection_callback(ssh_session session)
{
    int rc;

    switch(session->session_state) {
        case SSH_SESSION_STATE_NONE:
        case SSH_SESSION_STATE_CONNECTING:
            break;
        case SSH_SESSION_STATE_SOCKET_CONNECTED:
            ssh_set_fd_towrite(session);
            ssh_send_banner(session, 0);

            break;
        case SSH_SESSION_STATE_BANNER_RECEIVED:
            if (session->serverbanner == NULL) {
                goto error;
            }
            set_status(session, 0.4f);
            SSH_LOG(SSH_LOG_RARE,
                    "SSH server banner: %s", session->serverbanner);

            /* Here we analyze the different protocols the server allows. */
            rc = ssh_analyze_banner(session, 0);
            if (rc < 0) {
                ssh_set_error(session, SSH_FATAL,
                        "No version of SSH protocol usable (banner: %s)",
                        session->serverbanner);
                goto error;
            }

            ssh_packet_register_socket_callback(session, session->socket);

            ssh_packet_set_default_callbacks(session);
            session->session_state = SSH_SESSION_STATE_INITIAL_KEX;
            rc = ssh_set_client_kex(session);
            if (rc != SSH_OK) {
                goto error;
            }
            rc = ssh_send_kex(session, 0);
            if (rc < 0) {
                goto error;
            }
            set_status(session, 0.5f);

            break;
        case SSH_SESSION_STATE_INITIAL_KEX:
            /* TODO: This state should disappear in favor of get_key handle */
            break;
        case SSH_SESSION_STATE_KEXINIT_RECEIVED:
            set_status(session,0.6f);
            ssh_list_kex(&session->next_crypto->server_kex);
            if (session->next_crypto->client_kex.methods[0] == NULL) {
                /* in rekeying state if next_crypto client_kex is empty */
                rc = ssh_set_client_kex(session);
                if (rc != SSH_OK) {
                    goto error;
                }
                rc = ssh_send_kex(session, 0);
                if (rc < 0) {
                    goto error;
                }
            }
            if (ssh_kex_select_methods(session) == SSH_ERROR)
                goto error;
            set_status(session,0.8f);
            session->session_state=SSH_SESSION_STATE_DH;
            if (dh_handshake(session) == SSH_ERROR) {
                goto error;
            }
            /* FALL THROUGH */
        case SSH_SESSION_STATE_DH:
            if(session->dh_handshake_state==DH_STATE_FINISHED){
                set_status(session,1.0f);
                session->connected = 1;
                if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
                    session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
                else
                    session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
            }
            break;
        case SSH_SESSION_STATE_AUTHENTICATING:
            break;
        case SSH_SESSION_STATE_ERROR:
            goto error;
        default:
            ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state);
    }

    return;
error:
    ssh_socket_close(session->socket);
    session->alive = 0;
    session->session_state=SSH_SESSION_STATE_ERROR;

}