Exemple #1
3
/**
 * @brief Connect to the ssh server.
 *
 * @param[in]  session  The ssh session to connect.
 *
 * @returns             SSH_OK on success, SSH_ERROR on error.
 * @returns 						SSH_AGAIN, if the session is in nonblocking mode,
 * 											and call must be done again.
 *
 * @see ssh_new()
 * @see ssh_disconnect()
 */
int ssh_connect(ssh_session session) {
  int ret;

  if (session == NULL) {
    ssh_set_error(session, SSH_FATAL, "Invalid session pointer");
    return SSH_ERROR;
  }

  enter_function();
  switch(session->pending_call_state){
  case SSH_PENDING_CALL_NONE:
  	break;
  case SSH_PENDING_CALL_CONNECT:
  	goto pending;
  default:
  	ssh_set_error(session,SSH_FATAL,"Bad call during pending SSH call in ssh_connect");
  	leave_function();
  	return SSH_ERROR;
  }
  session->alive = 0;
  session->client = 1;

  if (ssh_init() < 0) {
    leave_function();
    return SSH_ERROR;
  }
  if (session->fd == SSH_INVALID_SOCKET && session->host == NULL && session->ProxyCommand == NULL) {
    ssh_set_error(session, SSH_FATAL, "Hostname required");
    leave_function();
    return SSH_ERROR;
  }

  ret = ssh_options_apply(session);
  if (ret < 0) {
      ssh_set_error(session, SSH_FATAL, "Couldn't apply options");
      leave_function();
      return SSH_ERROR;
  }
  ssh_log(session,SSH_LOG_RARE,"libssh %s, using threading %s", ssh_copyright(), ssh_threads_get_type());
  session->ssh_connection_callback = ssh_client_connection_callback;
  session->session_state=SSH_SESSION_STATE_CONNECTING;
  ssh_socket_set_callbacks(session->socket,&session->socket_callbacks);
  session->socket_callbacks.connected=socket_callback_connected;
  session->socket_callbacks.data=callback_receive_banner;
  session->socket_callbacks.exception=ssh_socket_exception_callback;
  session->socket_callbacks.userdata=session;
  if (session->fd != SSH_INVALID_SOCKET) {
    ssh_socket_set_fd(session->socket, session->fd);
    ret=SSH_OK;
#ifndef _WIN32
  } else if (session->ProxyCommand != NULL){
    ret=ssh_socket_connect_proxycommand(session->socket, session->ProxyCommand);
#endif
  } else {
    ret=ssh_socket_connect(session->socket, session->host, session->port,
    		session->bindaddr);

    /*, session->timeout * 1000 + session->timeout_usec); */
  }
  if (ret == SSH_ERROR) {
    leave_function();
    return SSH_ERROR;
  }

  set_status(session, 0.2f);

  session->alive = 1;
  ssh_log(session,SSH_LOG_PROTOCOL,"Socket connecting, now waiting for the callbacks to work");
pending:
	session->pending_call_state=SSH_PENDING_CALL_CONNECT;
  if(ssh_is_blocking(session))
    ssh_handle_packets_termination(session,-1,ssh_connect_termination,session);
  else
    ssh_handle_packets_termination(session,0,ssh_connect_termination, session);
  ssh_log(session,SSH_LOG_PACKET,"ssh_connect: Actual state : %d",session->session_state);
  if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){
    leave_function();
    return SSH_AGAIN;
  }
  leave_function();
  session->pending_call_state=SSH_PENDING_CALL_NONE;
  if(session->session_state == SSH_SESSION_STATE_ERROR || session->session_state == SSH_SESSION_STATE_DISCONNECTED)
  	return SSH_ERROR;
  return SSH_OK;
}
Exemple #2
0
/**
 * @internal
 *
 * @brief Request a service from the SSH server.
 *
 * Service requests are for example: ssh-userauth, ssh-connection, etc.
 *
 * @param  session      The session to use to ask for a service request.
 * @param  service      The service request.
 *
 * @return SSH_OK on success
 * @return SSH_ERROR on error
 * @return SSH_AGAIN No response received yet
 * @bug actually only works with ssh-userauth
 */
int ssh_service_request(ssh_session session, const char *service) {
  ssh_string service_s = NULL;
  int rc=SSH_ERROR;

  if(session->auth_service_state != SSH_AUTH_SERVICE_NONE)
    goto pending;
  if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_REQUEST) < 0) {
      return SSH_ERROR;
  }
  service_s = ssh_string_from_char(service);
  if (service_s == NULL) {
      return SSH_ERROR;
  }

  if (buffer_add_ssh_string(session->out_buffer,service_s) < 0) {
    ssh_string_free(service_s);
      return SSH_ERROR;
  }
  ssh_string_free(service_s);
  session->auth_service_state=SSH_AUTH_SERVICE_SENT;
  if (packet_send(session) == SSH_ERROR) {
    ssh_set_error(session, SSH_FATAL,
        "Sending SSH2_MSG_SERVICE_REQUEST failed.");
      return SSH_ERROR;
  }

  SSH_LOG(SSH_LOG_PACKET,
      "Sent SSH_MSG_SERVICE_REQUEST (service %s)", service);
pending:
  rc=ssh_handle_packets_termination(session,SSH_TIMEOUT_USER,
      ssh_service_request_termination, session);
  if (rc == SSH_ERROR) {
      return SSH_ERROR;
  }
  switch(session->auth_service_state){
  case SSH_AUTH_SERVICE_DENIED:
    ssh_set_error(session,SSH_FATAL,"ssh_auth_service request denied");
    break;
  case SSH_AUTH_SERVICE_ACCEPTED:
    rc=SSH_OK;
    break;
  case SSH_AUTH_SERVICE_SENT:
    rc=SSH_AGAIN;
    break;
  case SSH_AUTH_SERVICE_NONE:
  case SSH_AUTH_SERVICE_USER_SENT:
    /* Invalid state, SSH1 specific */
    rc=SSH_ERROR;
    break;
  }

  return rc;
}
Exemple #3
0
/**
 * @internal
 *
 * @brief Request a service from the SSH server.
 *
 * Service requests are for example: ssh-userauth, ssh-connection, etc.
 *
 * @param  session      The session to use to ask for a service request.
 * @param  service      The service request.
 *
 * @return SSH_OK on success
 * @return SSH_ERROR on error
 * @return SSH_AGAIN No response received yet
 * @bug actually only works with ssh-userauth
 */
int ssh_service_request(ssh_session session, const char *service) {
  int rc=SSH_ERROR;

  if(session->auth.service_state != SSH_AUTH_SERVICE_NONE)
    goto pending;

  rc = ssh_buffer_pack(session->out_buffer,
                       "bs",
                       SSH2_MSG_SERVICE_REQUEST,
                       service);
  if (rc != SSH_OK){
      ssh_set_error_oom(session);
      return SSH_ERROR;
  }
  session->auth.service_state = SSH_AUTH_SERVICE_SENT;
  if (ssh_packet_send(session) == SSH_ERROR) {
    ssh_set_error(session, SSH_FATAL,
        "Sending SSH2_MSG_SERVICE_REQUEST failed.");
      return SSH_ERROR;
  }

  SSH_LOG(SSH_LOG_PACKET,
      "Sent SSH_MSG_SERVICE_REQUEST (service %s)", service);
pending:
  rc=ssh_handle_packets_termination(session,SSH_TIMEOUT_USER,
      ssh_service_request_termination, session);
  if (rc == SSH_ERROR) {
      return SSH_ERROR;
  }
  switch(session->auth.service_state) {
  case SSH_AUTH_SERVICE_DENIED:
    ssh_set_error(session,SSH_FATAL,"ssh_auth_service request denied");
    break;
  case SSH_AUTH_SERVICE_ACCEPTED:
    rc=SSH_OK;
    break;
  case SSH_AUTH_SERVICE_SENT:
    rc=SSH_AGAIN;
    break;
  case SSH_AUTH_SERVICE_NONE:
    rc=SSH_ERROR;
    break;
  }

  return rc;
}
Exemple #4
0
static int wait_auth1_status(ssh_session session) {
  /* wait for a packet */
  if (ssh_handle_packets_termination(session,SSH_TIMEOUT_USER,
          ssh_auth_status_termination, session) != SSH_OK){

      return SSH_AUTH_ERROR;
  }
  SSH_LOG(SSH_LOG_PROTOCOL,"Auth state : %d",session->auth_state);

  switch(session->auth_state) {
    case SSH_AUTH_STATE_SUCCESS:
      return SSH_AUTH_SUCCESS;
    case SSH_AUTH_STATE_FAILED:
      return SSH_AUTH_DENIED;
    default:
      return SSH_AUTH_AGAIN;
  }
  return SSH_AUTH_ERROR;
}
Exemple #5
0
/**
 * @brief Retrieve a SSH message from a SSH session.
 *
 * @param[in]  session  The SSH session to get the message.
 *
 * @returns             The SSH message received, NULL in case of error, or timeout
 *                      elapsed.
 *
 * @warning This function blocks until a message has been received. Betterset up
 *          a callback if this behavior is unwanted.
 */
ssh_message ssh_message_get(ssh_session session) {
  ssh_message msg = NULL;
  int rc;

  msg=ssh_message_pop_head(session);
  if(msg) {
      return msg;
  }
  if(session->ssh_message_list == NULL) {
      session->ssh_message_list = ssh_list_new();
  }
  rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
      ssh_message_termination, session);
  if(rc || session->session_state == SSH_SESSION_STATE_ERROR)
    return NULL;
  msg=ssh_list_pop_head(ssh_message, session->ssh_message_list);

  return msg;
}
Exemple #6
0
/* Do the banner and key exchange */
int ssh_handle_key_exchange(ssh_session session) {
    int rc;
    if (session->session_state != SSH_SESSION_STATE_NONE)
      goto pending;
    rc = ssh_send_banner(session, 1);
    if (rc < 0) {
        return SSH_ERROR;
    }

    session->alive = 1;

    session->ssh_connection_callback = ssh_server_connection_callback;
    session->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED;
    ssh_socket_set_callbacks(session->socket,&session->socket_callbacks);
    session->socket_callbacks.data=callback_receive_banner;
    session->socket_callbacks.exception=ssh_socket_exception_callback;
    session->socket_callbacks.userdata=session;

    rc = server_set_kex(session);
    if (rc < 0) {
        return SSH_ERROR;
    }
    pending:
    rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
        ssh_server_kex_termination,session);
    SSH_LOG(SSH_LOG_PACKET, "ssh_handle_key_exchange: current state : %d",
        session->session_state);
    if (rc != SSH_OK)
      return rc;
    if (session->session_state == SSH_SESSION_STATE_ERROR ||
        session->session_state == SSH_SESSION_STATE_DISCONNECTED) {
      return SSH_ERROR;
    }

  return SSH_OK;
}
Exemple #7
0
/**
 * @brief Connect to the ssh server.
 *
 * @param[in]  session  The ssh session to connect.
 *
 * @returns             SSH_OK on success, SSH_ERROR on error.
 * @returns 						SSH_AGAIN, if the session is in nonblocking mode,
 * 											and call must be done again.
 *
 * @see ssh_new()
 * @see ssh_disconnect()
 */
int ssh_connect(ssh_session session) {
  int ret;

  if (session == NULL) {
    return SSH_ERROR;
  }

  switch(session->pending_call_state){
  case SSH_PENDING_CALL_NONE:
  	break;
  case SSH_PENDING_CALL_CONNECT:
  	goto pending;
  default:
  	ssh_set_error(session,SSH_FATAL,"Bad call during pending SSH call in ssh_connect");

  	return SSH_ERROR;
  }
  session->alive = 0;
  session->client = 1;

  if (ssh_init() < 0) {
    return SSH_ERROR;
  }
  if (session->opts.fd == SSH_INVALID_SOCKET &&
      session->opts.host == NULL &&
      session->opts.ProxyCommand == NULL) {
    ssh_set_error(session, SSH_FATAL, "Hostname required");
    return SSH_ERROR;
  }

  ret = ssh_options_apply(session);
  if (ret < 0) {
      ssh_set_error(session, SSH_FATAL, "Couldn't apply options");
      return SSH_ERROR;
  }
  SSH_LOG(SSH_LOG_RARE,"libssh %s, using threading %s", ssh_copyright(), ssh_threads_get_type());
  session->ssh_connection_callback = ssh_client_connection_callback;
  session->session_state=SSH_SESSION_STATE_CONNECTING;
  ssh_socket_set_callbacks(session->socket,&session->socket_callbacks);
  session->socket_callbacks.connected=socket_callback_connected;
  session->socket_callbacks.data=callback_receive_banner;
  session->socket_callbacks.exception=ssh_socket_exception_callback;
  session->socket_callbacks.userdata=session;
  if (session->opts.fd != SSH_INVALID_SOCKET) {
    session->session_state=SSH_SESSION_STATE_SOCKET_CONNECTED;
    ssh_socket_set_fd(session->socket, session->opts.fd);
    ret=SSH_OK;
#ifndef _WIN32
  } else if (session->opts.ProxyCommand != NULL){
    ret = ssh_socket_connect_proxycommand(session->socket,
                                          session->opts.ProxyCommand);
#endif
  } else {
    ret=ssh_socket_connect(session->socket,
                           session->opts.host,
                           session->opts.port,
                           session->opts.bindaddr);
  }
  if (ret == SSH_ERROR) {
    return SSH_ERROR;
  }

  set_status(session, 0.2f);

  session->alive = 1;
  SSH_LOG(SSH_LOG_PROTOCOL,"Socket connecting, now waiting for the callbacks to work");
pending:
  session->pending_call_state=SSH_PENDING_CALL_CONNECT;
  if(ssh_is_blocking(session)) {
      int timeout = (session->opts.timeout * 1000) +
                    (session->opts.timeout_usec / 1000);
      if (timeout == 0) {
          timeout = 10 * 1000;
      }
      SSH_LOG(SSH_LOG_PACKET,"Actual timeout : %d", timeout);
      ret = ssh_handle_packets_termination(session, timeout, ssh_connect_termination, session);
      if (session->session_state != SSH_SESSION_STATE_ERROR &&
          (ret == SSH_ERROR || !ssh_connect_termination(session))) {
          ssh_set_error(session, SSH_FATAL,
                        "Timeout connecting to %s", session->opts.host);
          session->session_state = SSH_SESSION_STATE_ERROR;
      }
  }
  else {
      ret = ssh_handle_packets_termination(session,
                                           SSH_TIMEOUT_NONBLOCKING,
                                           ssh_connect_termination,
                                           session);
      if (ret == SSH_ERROR) {
          session->session_state = SSH_SESSION_STATE_ERROR;
      }
  }
  SSH_LOG(SSH_LOG_PACKET,"current state : %d",session->session_state);
  if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){
    return SSH_AGAIN;
  }

  session->pending_call_state=SSH_PENDING_CALL_NONE;
  if(session->session_state == SSH_SESSION_STATE_ERROR || session->session_state == SSH_SESSION_STATE_DISCONNECTED)
  	return SSH_ERROR;
  return SSH_OK;
}