mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-12-02 01:17:52 +03:00
Trying to adapt client.c to use callbacks
This commit is contained in:
@@ -27,6 +27,17 @@
|
|||||||
|
|
||||||
typedef struct ssh_kbdint_struct* ssh_kbdint;
|
typedef struct ssh_kbdint_struct* ssh_kbdint;
|
||||||
|
|
||||||
|
/* These are the different states a SSH session can be into its life */
|
||||||
|
enum ssh_session_state_e {
|
||||||
|
SSH_SESSION_STATE_NONE,
|
||||||
|
SSH_SESSION_STATE_CONNECTING,
|
||||||
|
SSH_SESSION_STATE_SOCKET_CONNECTED,
|
||||||
|
SSH_SESSION_STATE_BANNER_RECEIVED,
|
||||||
|
SSH_SESSION_STATE_INITIAL_KEX,
|
||||||
|
SSH_SESSION_STATE_AUTHENTICATED,
|
||||||
|
SSH_SESSION_STATE_ERROR
|
||||||
|
};
|
||||||
|
|
||||||
struct ssh_session_struct {
|
struct ssh_session_struct {
|
||||||
struct error_struct error;
|
struct error_struct error;
|
||||||
struct socket *socket;
|
struct socket *socket;
|
||||||
@@ -63,6 +74,7 @@ struct ssh_session_struct {
|
|||||||
|
|
||||||
/* the states are used by the nonblocking stuff to remember */
|
/* the states are used by the nonblocking stuff to remember */
|
||||||
/* where it was before being interrupted */
|
/* where it was before being interrupted */
|
||||||
|
enum ssh_session_state_e session_state;
|
||||||
int packet_state;
|
int packet_state;
|
||||||
int dh_handshake_state;
|
int dh_handshake_state;
|
||||||
ssh_string dh_server_signature; //information used by dh_handshake.
|
ssh_string dh_server_signature; //information used by dh_handshake.
|
||||||
|
|||||||
111
libssh/client.c
111
libssh/client.c
@@ -44,52 +44,71 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*
|
* @brief Callback to be called when the socket is connected or had a
|
||||||
* @brief Get a banner from a socket.
|
* connection error. Changes the state of the session and updates the error
|
||||||
*
|
* message.
|
||||||
* The caller has to free memroy.
|
* @param code one of SSH_SOCKET_CONNECTED_OK or SSH_SOCKET_CONNECTED_ERROR
|
||||||
*
|
* @param user is a pointer to session
|
||||||
* @param session The session to get the banner from.
|
|
||||||
*
|
|
||||||
* @return A newly allocated string with the banner or NULL on error.
|
|
||||||
*/
|
*/
|
||||||
char *ssh_get_banner(ssh_session session) {
|
static void socket_callback_connected(int code, int errno, void *user){
|
||||||
char buffer[128] = {0};
|
ssh_session session=(ssh_session)user;
|
||||||
char *str = NULL;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
enter_function();
|
enter_function();
|
||||||
|
ssh_log(session,SSH_LOG_RARE,"Socket connection callback: %d (%d)",code, errno);
|
||||||
for (i = 0; i < 127; i++) {
|
if(code == SSH_SOCKET_CONNECTED_OK)
|
||||||
if (ssh_socket_read(session->socket, &buffer[i], 1) != SSH_OK) {
|
session->session_state=SSH_SESSION_STATE_SOCKET_CONNECTED;
|
||||||
ssh_set_error(session, SSH_FATAL, "Remote host closed connection");
|
else {
|
||||||
leave_function();
|
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||||
return NULL;
|
ssh_set_error(session,SSH_FATAL,"Connection failed: %s",strerror(errno));
|
||||||
}
|
}
|
||||||
|
leave_function();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @brief Gets the banner from socket and saves it in session.
|
||||||
|
* Updates the session state
|
||||||
|
*
|
||||||
|
* @param data pointer to the begining of header
|
||||||
|
* @param len size of the banner
|
||||||
|
* @param user is a pointer to session
|
||||||
|
* @returns Number of bytes processed, or zero if the banner is not complete.
|
||||||
|
*/
|
||||||
|
static int callback_receive_banner(const void *data, size_t len, void *user) {
|
||||||
|
char *buffer = (char *)data;
|
||||||
|
ssh_session session=(ssh_session) user;
|
||||||
|
char *str = NULL;
|
||||||
|
size_t i;
|
||||||
|
int ret=0;
|
||||||
|
enter_function();
|
||||||
|
for(i=0;i<len;++i){
|
||||||
#ifdef WITH_PCAP
|
#ifdef WITH_PCAP
|
||||||
if(session->pcap_ctx && buffer[i] == '\n'){
|
if(session->pcap_ctx && buffer[i] == '\n'){
|
||||||
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_IN,buffer,i+1,i+1);
|
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_IN,buffer,i+1,i+1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (buffer[i] == '\r') {
|
if(buffer[i]=='\r')
|
||||||
buffer[i] = '\0';
|
buffer[i]='\0';
|
||||||
}
|
if(buffer[i]=='\n'){
|
||||||
if (buffer[i] == '\n') {
|
buffer[i]='\0';
|
||||||
buffer[i] = '\0';
|
str=strdup(buffer);
|
||||||
str = strdup(buffer);
|
/* number of bytes read */
|
||||||
if (str == NULL) {
|
ret=i+1;
|
||||||
|
session->remotebanner=str;
|
||||||
|
session->session_state=SSH_SESSION_STATE_BANNER_RECEIVED;
|
||||||
leave_function();
|
leave_function();
|
||||||
return NULL;
|
return ret;
|
||||||
|
}
|
||||||
|
if(i>127){
|
||||||
|
/* Too big banner */
|
||||||
|
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||||
|
ssh_set_error(session,SSH_FATAL,"Receiving banner: too large banner");
|
||||||
|
leave_function();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
leave_function();
|
leave_function();
|
||||||
return str;
|
return ret;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_set_error(session, SSH_FATAL, "Too large banner");
|
|
||||||
|
|
||||||
leave_function();
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -484,7 +503,7 @@ int ssh_service_request(ssh_session session, const char *service) {
|
|||||||
int ssh_connect(ssh_session session) {
|
int ssh_connect(ssh_session session) {
|
||||||
int ssh1 = 0;
|
int ssh1 = 0;
|
||||||
int ssh2 = 0;
|
int ssh2 = 0;
|
||||||
int fd = -1;
|
int ret;
|
||||||
|
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
ssh_set_error(session, SSH_FATAL, "Invalid session pointer");
|
ssh_set_error(session, SSH_FATAL, "Invalid session pointer");
|
||||||
@@ -505,20 +524,26 @@ int ssh_connect(ssh_session session) {
|
|||||||
leave_function();
|
leave_function();
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
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.user=session;
|
||||||
if (session->fd != -1) {
|
if (session->fd != -1) {
|
||||||
fd = session->fd;
|
ssh_socket_set_fd(session->socket, session->fd);
|
||||||
|
ret=SSH_OK;
|
||||||
} else {
|
} else {
|
||||||
fd = ssh_connect_host(session, session->host, session->bindaddr,
|
ret=ssh_socket_connect(session->socket, session->host, session->port,
|
||||||
session->port, session->timeout, session->timeout_usec);
|
session->bindaddr);
|
||||||
|
|
||||||
|
//, session->timeout * 1000 + session->timeout_usec);
|
||||||
}
|
}
|
||||||
if (fd < 0) {
|
if (ret != SSH_OK) {
|
||||||
leave_function();
|
leave_function();
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
set_status(session, 0.2);
|
set_status(session, 0.2);
|
||||||
|
|
||||||
ssh_socket_set_fd(session->socket, fd);
|
|
||||||
|
|
||||||
session->alive = 1;
|
session->alive = 1;
|
||||||
session->serverbanner = ssh_get_banner(session);
|
session->serverbanner = ssh_get_banner(session);
|
||||||
if (session->serverbanner == NULL) {
|
if (session->serverbanner == NULL) {
|
||||||
@@ -697,7 +722,7 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *ssh_copyright(void) {
|
const char *ssh_copyright(void) {
|
||||||
return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2008 Aris Adamantiadis "
|
return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2010 Aris Adamantiadis "
|
||||||
"(aris@0xbadc0de.be) Distributed under the LGPL, please refer to COPYING"
|
"(aris@0xbadc0de.be) Distributed under the LGPL, please refer to COPYING"
|
||||||
"file for informations about your rights";
|
"file for informations about your rights";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user