1
1

Trying to adapt client.c to use callbacks

Этот коммит содержится в:
Aris Adamantiadis 2009-12-03 23:55:46 +01:00
родитель 4924ac8099
Коммит 2f6fbbd706
2 изменённых файлов: 84 добавлений и 47 удалений

Просмотреть файл

@ -27,6 +27,17 @@
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 error_struct error;
struct socket *socket;
@ -63,6 +74,7 @@ struct ssh_session_struct {
/* the states are used by the nonblocking stuff to remember */
/* where it was before being interrupted */
enum ssh_session_state_e session_state;
int packet_state;
int dh_handshake_state;
ssh_string dh_server_signature; //information used by dh_handshake.

Просмотреть файл

@ -44,52 +44,71 @@
/**
* @internal
*
* @brief Get a banner from a socket.
*
* The caller has to free memroy.
*
* @param session The session to get the banner from.
*
* @return A newly allocated string with the banner or NULL on error.
* @brief Callback to be called when the socket is connected or had a
* connection error. Changes the state of the session and updates the error
* message.
* @param code one of SSH_SOCKET_CONNECTED_OK or SSH_SOCKET_CONNECTED_ERROR
* @param user is a pointer to session
*/
char *ssh_get_banner(ssh_session session) {
char buffer[128] = {0};
static void socket_callback_connected(int code, int errno, void *user){
ssh_session session=(ssh_session)user;
enter_function();
ssh_log(session,SSH_LOG_RARE,"Socket connection callback: %d (%d)",code, errno);
if(code == SSH_SOCKET_CONNECTED_OK)
session->session_state=SSH_SESSION_STATE_SOCKET_CONNECTED;
else {
session->session_state=SSH_SESSION_STATE_ERROR;
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;
int i;
size_t i;
int ret=0;
enter_function();
for (i = 0; i < 127; i++) {
if (ssh_socket_read(session->socket, &buffer[i], 1) != SSH_OK) {
ssh_set_error(session, SSH_FATAL, "Remote host closed connection");
leave_function();
return NULL;
}
for(i=0;i<len;++i){
#ifdef WITH_PCAP
if(session->pcap_ctx && buffer[i] == '\n'){
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_IN,buffer,i+1,i+1);
}
if(session->pcap_ctx && buffer[i] == '\n'){
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_IN,buffer,i+1,i+1);
}
#endif
if (buffer[i] == '\r') {
buffer[i] = '\0';
}
if (buffer[i] == '\n') {
buffer[i] = '\0';
str = strdup(buffer);
if (str == NULL) {
leave_function();
return NULL;
}
leave_function();
return str;
}
if(buffer[i]=='\r')
buffer[i]='\0';
if(buffer[i]=='\n'){
buffer[i]='\0';
str=strdup(buffer);
/* number of bytes read */
ret=i+1;
session->remotebanner=str;
session->session_state=SSH_SESSION_STATE_BANNER_RECEIVED;
leave_function();
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;
}
}
ssh_set_error(session, SSH_FATAL, "Too large banner");
leave_function();
return NULL;
return ret;
}
/**
@ -484,7 +503,7 @@ int ssh_service_request(ssh_session session, const char *service) {
int ssh_connect(ssh_session session) {
int ssh1 = 0;
int ssh2 = 0;
int fd = -1;
int ret;
if (session == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid session pointer");
@ -505,20 +524,26 @@ int ssh_connect(ssh_session session) {
leave_function();
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) {
fd = session->fd;
ssh_socket_set_fd(session->socket, session->fd);
ret=SSH_OK;
} else {
fd = ssh_connect_host(session, session->host, session->bindaddr,
session->port, session->timeout, session->timeout_usec);
ret=ssh_socket_connect(session->socket, session->host, session->port,
session->bindaddr);
//, session->timeout * 1000 + session->timeout_usec);
}
if (fd < 0) {
if (ret != SSH_OK) {
leave_function();
return SSH_ERROR;
}
set_status(session, 0.2);
ssh_socket_set_fd(session->socket, fd);
session->alive = 1;
session->serverbanner = ssh_get_banner(session);
if (session->serverbanner == NULL) {
@ -697,7 +722,7 @@ error:
}
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"
"file for informations about your rights";
}