Beispiel #1
0
/** \brief connect to the ssh server
 * \param session ssh session
 * \return 0 on success, SSH_ERROR on error
 * \see ssh_new()
 * \see ssh_disconnect()
 */
int ssh_connect(SSH_SESSION *session){
  int fd;
  int ssh1, ssh2;
  SSH_OPTIONS *options=session->options;
  if(!session->options){
      ssh_set_error(session,SSH_FATAL,"Must set options before connect");
      return SSH_ERROR;
  }
  session->alive=0;
  session->client=1;
  ssh_crypto_init();
  if(options->fd==-1 && !options->host){
      ssh_set_error(session,SSH_FATAL,"Hostname required");
      return SSH_ERROR;
  } 
  if(options->fd != -1)
      fd=options->fd;
  else
      fd=ssh_connect_host(session,options->host,options->bindaddr,options->port,
          options->timeout,options->timeout_usec);    
  if(fd<0)
      return -1;
  set_status(options,0.2);
  session->fd=fd;
  session->alive=1;
  if(!(session->serverbanner=ssh_get_banner(session))){
      if(session->fd>=0)
        close(session->fd);
      session->fd=-1;
      session->alive=0;
      return -1;
  }
  set_status(options,0.4);
  ssh_say(2,"banner : %s\n",session->serverbanner);
  /* here we analyse the different protocols the server allows */
  if(ssh_analyze_banner(session,&ssh1,&ssh2)){
      if(session->fd>=0)
          close(session->fd);
      session->fd=-1;
      session->alive=0;
      return -1;
  }
  /* here we decide which version of the protocol to use */
  if(ssh2 && options->ssh2allowed)
      session->version=2;
  else if(ssh1 && options->ssh1allowed)
      session->version=1;
  else {
      ssh_set_error(session,SSH_FATAL,
        "no version of SSH protocol usable (banner: %s)",
        session->serverbanner);
        close(session->fd);
        session->fd=-1;
        session->alive=0;
        return -1;
  }
  ssh_send_banner(session,0);
  set_status(options,0.5);
  switch(session->version){
      case 2:
        if(ssh_get_kex(session,0)){
            if(session->fd>=0)
                close(session->fd);
            session->fd=-1;
            session->alive=0;
            return -1;
        }
        set_status(options,0.6);
        ssh_list_kex(&session->server_kex);
        if(set_kex(session)){
            if(session->fd>=0)
                close(session->fd);
            session->fd=-1;
            session->alive=0;
            return -1;
        }
        ssh_send_kex(session,0);
        set_status(options,0.8);
        if(dh_handshake(session)){
            if(session->fd>=0)
                close(session->fd);
            session->fd=-1;
            session->alive=0;
            return -1;
        } 
        set_status(options,1.0);
        session->connected=1;
        break;
    case 1:
        if(ssh_get_kex1(session)){
            if(session->fd>=0)
                close(session->fd);
            session->fd=-1;
            session->alive=0;
            return -1;
        }
        set_status(options,0.6);
        session->connected=1;
        break;  
  }
  return 0;
}
Beispiel #2
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:
		case SSH_SESSION_STATE_SOCKET_CONNECTED:
			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)
		    session->socket_callbacks.data=ssh_packet_socket_callback;
#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;
		  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 (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 #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 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;

}