Add more error checks to ssh_connect().

git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@487 7dcaeef0-15fb-0310-b436-a5af3365683c
This commit is contained in:
Andreas Schneider
2009-04-16 08:42:46 +00:00
parent 10dedee3ef
commit a565f255f0

View File

@@ -406,113 +406,152 @@ int ssh_service_request(SSH_SESSION *session, const char *service) {
} }
/** \addtogroup ssh_session /** \addtogroup ssh_session
* * @{ */ * @{
*/
/** \brief connect to the ssh server /** \brief connect to the ssh server
* \param session ssh session * \param session ssh session
* \return 0 on success, SSH_ERROR on error * \return SSH_OK on success, SSH_ERROR on error
* \see ssh_new() * \see ssh_new()
* \see ssh_disconnect() * \see ssh_disconnect()
*/ */
int ssh_connect(SSH_SESSION *session){ int ssh_connect(SSH_SESSION *session) {
int fd; SSH_OPTIONS *options = session->options;
int ssh1, ssh2; int ssh1 = 0;
SSH_OPTIONS *options=session->options; int ssh2 = 0;
if(!session->options){ int fd = -1;
ssh_set_error(session,SSH_FATAL,"Must set options before connect");
return SSH_ERROR; if (session == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid session pointer");
return SSH_ERROR;
} }
if (session->options == NULL) {
ssh_set_error(session, SSH_FATAL, "No options set");
return SSH_ERROR;
}
options = session->options;
enter_function(); enter_function();
session->alive=0;
session->client=1; session->alive = 0;
session->client = 1;
ssh_crypto_init(); ssh_crypto_init();
ssh_socket_init(); ssh_socket_init();
if(options->fd==-1 && !options->host){
ssh_set_error(session,SSH_FATAL,"Hostname required"); if (options->fd == -1 && options->host == NULL) {
leave_function(); ssh_set_error(session, SSH_FATAL, "Hostname required");
return SSH_ERROR; leave_function();
return SSH_ERROR;
} }
if(options->fd != -1) if (options->fd != -1) {
fd=options->fd; fd = options->fd;
else } else {
fd=ssh_connect_host(session,options->host,options->bindaddr,options->port, fd = ssh_connect_host(session, options->host, options->bindaddr,
options->timeout,options->timeout_usec); options->port, options->timeout, options->timeout_usec);
if(fd<0){
leave_function();
return -1;
} }
set_status(options,0.2); if (fd < 0) {
ssh_socket_set_fd(session->socket,fd); leave_function();
session->alive=1; return SSH_ERROR;
if(!(session->serverbanner=ssh_get_banner(session))){
ssh_socket_close(session->socket);
session->alive=0;
leave_function();
return -1;
} }
set_status(options,0.4); set_status(options, 0.2);
ssh_log(session, SSH_LOG_RARE, "banner: %s\n", session->serverbanner);
/* here we analyse the different protocols the server allows */ ssh_socket_set_fd(session->socket, fd);
if(ssh_analyze_banner(session,&ssh1,&ssh2)){
ssh_socket_close(session->socket); session->alive = 1;
session->alive=0; session->serverbanner = ssh_get_banner(session);
leave_function(); if (session->serverbanner == NULL) {
return -1; ssh_socket_close(session->socket);
session->alive = 0;
leave_function();
return SSH_ERROR;
} }
/* here we decide which version of the protocol to use */ set_status(options, 0.4);
if(ssh2 && options->ssh2allowed)
session->version=2; ssh_log(session, SSH_LOG_RARE,
else if(ssh1 && options->ssh1allowed) "SSH server banner: %s", session->serverbanner);
session->version=1;
else { /* Here we analyse the different protocols the server allows. */
ssh_set_error(session,SSH_FATAL, if (ssh_analyze_banner(session, &ssh1, &ssh2) < 0) {
"no version of SSH protocol usable (banner: %s)", ssh_socket_close(session->socket);
session->alive = 0;
leave_function();
return SSH_ERROR;
}
/* 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); session->serverbanner);
ssh_socket_close(session->socket);
session->alive = 0;
leave_function();
return SSH_ERROR;
}
if (ssh_send_banner(session, 0) < 0) {
ssh_set_error(session, SSH_FATAL, "Sending the banner failed");
ssh_socket_close(session->socket);
session->alive = 0;
leave_function();
return SSH_ERROR;
}
set_status(options, 0.5);
switch (session->version) {
case 2:
if (ssh_get_kex(session,0) < 0) {
ssh_socket_close(session->socket); ssh_socket_close(session->socket);
session->alive=0; session->alive = 0;
leave_function(); leave_function();
return -1; return SSH_ERROR;
} }
ssh_send_banner(session,0); set_status(options,0.6);
set_status(options,0.5);
switch(session->version){ ssh_list_kex(session, &session->server_kex);
case 2: if (set_kex(session) < 0) {
if(ssh_get_kex(session,0) < 0) { ssh_socket_close(session->socket);
ssh_socket_close(session->socket); session->alive = 0;
session->alive=0; leave_function();
leave_function(); return SSH_ERROR;
return -1; }
} if (ssh_send_kex(session, 0) < 0) {
set_status(options,0.6); ssh_socket_close(session->socket);
ssh_list_kex(session, &session->server_kex); session->alive = 0;
if(set_kex(session)){ leave_function();
ssh_socket_close(session->socket); return SSH_ERROR;
session->alive=0; }
leave_function(); set_status(options,0.8);
return -1;
} if (dh_handshake(session) < 0) {
ssh_send_kex(session,0); ssh_socket_close(session->socket);
set_status(options,0.8); session->alive = 0;
if(dh_handshake(session)){ leave_function();
ssh_socket_close(session->socket); return SSH_ERROR;
session->alive=0; }
leave_function(); set_status(options,1.0);
return -1;
} session->connected = 1;
set_status(options,1.0); break;
session->connected=1;
break;
case 1: case 1:
if(ssh_get_kex1(session)){ if (ssh_get_kex1(session) < 0) {
ssh_socket_close(session->socket); ssh_socket_close(session->socket);
session->alive=0; session->alive = 0;
leave_function(); leave_function();
return -1; return SSH_ERROR;
} }
set_status(options,0.6); set_status(options,0.6);
session->connected=1;
break; session->connected = 1;
break;
} }
leave_function(); leave_function();
return 0; return 0;
} }