Compare commits

...

33 Commits

Author SHA1 Message Date
Andreas Schneider
232aca8969 Update ChangeLog. 2009-08-04 15:24:06 +02:00
Andreas Schneider
48deb0ca46 Update version number of the package. 2009-08-04 15:17:46 +02:00
Andreas Schneider
59889da5a5 Update version numbers. 2009-08-01 11:22:09 +02:00
Andreas Schneider
a958f6498b Cleanup the libssh.map file and order it alphabetically. 2009-07-30 12:25:27 +02:00
Andreas Schneider
3ec11b46e9 Add gitignore file to branch. 2009-07-29 22:52:21 +02:00
Andreas Schneider
c17ce2697b Add ssh_init to the map file. 2009-07-29 17:50:53 +02:00
Aris Adamantiadis
7fa1804cf1 ssh_init()
fixes in client.c and server.c for this

git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@778 7dcaeef0-15fb-0310-b436-a5af3365683c
2009-07-29 17:50:04 +02:00
Andreas Schneider
ad86a378d9 moved try_publickey_from_file in priv.h
Had nothing to do in libssh.h. 100% sure nobody
used it since one of the structure declaration
was not public.
2009-07-29 17:40:17 +02:00
Andreas Schneider
ed660c29c3 Check for OpenSSH and implement sftp_symlink correct.
When OpenSSH's sftp-server was implemented, the order of the arguments
to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately,
the reversal was not noticed until the server was widely deployed.
Since fixing this to follow the specification would cause
incompatibility, the current order was retained.
2009-07-29 16:05:45 +02:00
Andreas Schneider
6f47401173 Fix SSH1 compilation. 2009-07-29 16:02:52 +02:00
Andreas Schneider
d247b86202 Update map file. 2009-07-25 12:34:49 +02:00
Andreas Schneider
a1c7dd99be Add sftp_readlink function. 2009-07-25 12:34:25 +02:00
Andreas Schneider
11a6ed907d Add sftp_symlink function. 2009-07-25 12:32:51 +02:00
Andreas Schneider
a8ce546f69 Fix a segfault if a NULL pointer is passed to ssh_disconnect(). 2009-07-23 09:07:49 +02:00
Andreas Schneider
6e56d1dfb2 Don't segfault if the session or the answer is NULL. 2009-07-23 09:07:36 +02:00
Andreas Schneider
b07ec7a3d1 Fix ssh_write_knownhost() which always returned -1.
fwrite() return the the number of items written not the size of the
buffer.
2009-07-23 09:07:26 +02:00
Andreas Schneider
09d4029ac1 Add compile flags and test for compiler options only if we use gcc. 2009-07-23 09:07:12 +02:00
Andreas Schneider
b62d0732d2 Only add additional warnings if we have a GNU compiler. 2009-07-23 09:07:00 +02:00
Andreas Schneider
90a6d431a7 Make the ssh_userauth_kbdint functions to get the prompts const.
They shouldn't be modified or free'd by a user.
2009-07-23 09:06:47 +02:00
Andreas Schneider
f7448eeb1c Fix sol8 + ss11 compile errors.
Thanks to tysonite@gmail.com.
2009-07-23 09:06:22 +02:00
Andreas Schneider
d411260a68 Fix build on windows, missing include. 2009-07-14 10:52:18 +02:00
Aris Adamantiadis
f8f0663eb9 Fix doxygen to match SSH_SERVER_FILE_NOT_FOUND fix 2009-07-14 10:22:17 +02:00
Andreas Schneider
cedc635ed0 Add changelog entries for 0.3.1. 2009-07-14 09:51:49 +02:00
Andreas Schneider
ff819489b7 Set version to 0.3.1. 2009-07-14 09:51:36 +02:00
Aris Adamantiadis
37dc2a5279 Reflect the SSH_SERVER_NOT_KNOWN add-on in sample 2009-07-13 12:07:31 +02:00
Aris Adamantiadis
50ebbe636e Added return code SSH_SERVER_FILE_NOT_FOUND
This error is returned by ssh_is_server_known when known_hosts
file does not exist and gives more action to the developer.
2009-07-13 12:07:19 +02:00
Aris Adamantiadis
101bf21d41 Fixed Could not write as much data as expected msg
Bug caused by verifying the size of the buffer in the wrong place
2009-07-02 10:37:32 +02:00
Aris Adamantiadis
ae3bb42da5 Fixed memory leak in ssh_is_server_known() 2009-06-23 09:13:26 +02:00
Aris Adamantiadis
918a912cd5 Fixed yet another read-after-free bug
read of a buffer len after free in sftp_write()
2009-06-23 09:13:15 +02:00
Aris Adamantiadis
7ba81b974e Fixed a use-after-free in match_hashed_host() 2009-06-21 22:18:43 +02:00
Aris Adamantiadis
b5e868fb8b Fix doublefree bug found by Cyril 2009-06-21 22:18:38 +02:00
Andreas Schneider
693c041ba9 Fix a memory leak in ssh_message_free(). 2009-06-20 11:30:09 +02:00
Aris Adamantiadis
39c7e3c7dd Fixed potential format string attacks
Potential format string attacks on error reporting in channels.c
2009-06-20 11:25:23 +02:00
23 changed files with 611 additions and 175 deletions

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
.*
*.swp
*~$
build
cscope.*
tags

View File

@@ -6,13 +6,13 @@ cmake_minimum_required(VERSION 2.6.0)
# global needed variables
set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION "0.3.0")
set(APPLICATION_VERSION "0.3.2")
set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "3")
set(APPLICATION_VERSION_PATCH "0")
set(APPLICATION_VERSION_PATCH "2")
set(LIBRARY_VERSION "3.0.0")
set(LIBRARY_VERSION "3.2.0")
set(LIBRARY_SOVERSION "3")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked

View File

@@ -15,7 +15,7 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
### versions
set(CPACK_PACKAGE_VERSION_MAJOR "0")
set(CPACK_PACKAGE_VERSION_MINOR "3")
set(CPACK_PACKAGE_VERSION_PATCH "0")
set(CPACK_PACKAGE_VERSION_PATCH "2")
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")

View File

@@ -1,6 +1,23 @@
ChangeLog
==========
version 0.3.2 (released 2009-08-05)
* Added ssh_init() function.
* Added sftp_readlink() function.
* Added sftp_symlink() function.
* Fixed ssh_write_knownhost().
* Fixed compilation on Solaris.
* Fixed SSHv1 compilation.
version 0.3.1 (released 2009-07-14)
* Added return code SSH_SERVER_FILE_NOT_FOUND.
* Fixed compilation of SSHv1.
* Fixed several memory leaks.
* Fixed possible infinite loops.
* Fixed a possible crash bug.
* Fixed build warnings.
* Fixed cmake on BSD.
version 0.3 (released 2009-05-21)
* Added support for ssh-agent authentication.
* Added POSIX like sftp implementation.

View File

@@ -3,47 +3,48 @@
include(CheckCCompilerFlag)
if (UNIX AND NOT WIN32)
# with -fPIC
check_c_compiler_flag("-fPIC" WITH_FPIC)
if (WITH_FPIC)
add_definitions(-fPIC)
endif (WITH_FPIC)
if (CMAKE_COMPILER_IS_GNUCC)
add_definitions(-Wall -Wextra -Wmissing-prototypes -Wdeclaration-after-statement -Wunused)
if (CMAKE_SIZEOF_VOID_P MATCHES "8")
# with large file support
execute_process(
COMMAND
getconf LFS64_CFLAGS
OUTPUT_VARIABLE
_lfs_CFLAGS
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
else (CMAKE_SIZEOF_VOID_P MATCHES "8")
# with large file support
execute_process(
COMMAND
getconf LFS_CFLAGS
OUTPUT_VARIABLE
_lfs_CFLAGS
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
# with -fPIC
check_c_compiler_flag("-fPIC" WITH_FPIC)
if (WITH_FPIC)
add_definitions(-fPIC)
endif (WITH_FPIC)
if (CMAKE_SIZEOF_VOID_P MATCHES "8")
# with large file support
execute_process(
COMMAND
getconf LFS64_CFLAGS
OUTPUT_VARIABLE
_lfs_CFLAGS
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
else (CMAKE_SIZEOF_VOID_P MATCHES "8")
# with large file support
execute_process(
COMMAND
getconf LFS_CFLAGS
OUTPUT_VARIABLE
_lfs_CFLAGS
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
add_definitions(${_lfs_CFLAGS})
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
add_definitions(${_lfs_CFLAGS})
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
add_definitions(-Wall -Wextra -Wmissing-prototypes -Wdeclaration-after-statement -Wunused)
check_c_compiler_flag("-fstack-protector" WITH_STACK_PROTECTOR)
if (WITH_STACK_PROTECTOR)
add_definitions(-fstack-protector)
endif (WITH_STACK_PROTECTOR)
check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
if (WITH_FORTIFY_SOURCE)
add_definitions(-D_FORTIFY_SOURCE=2)
endif (WITH_FORTIFY_SOURCE)
check_c_compiler_flag("-fstack-protector" WITH_STACK_PROTECTOR)
if (WITH_STACK_PROTECTOR)
add_definitions(-fstack-protector)
endif (WITH_STACK_PROTECTOR)
check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
if (WITH_FORTIFY_SOURCE)
add_definitions(-D_FORTIFY_SOURCE=2)
endif (WITH_FORTIFY_SOURCE)
endif (CMAKE_COMPILER_IS_GNUCC)
endif (UNIX AND NOT WIN32)

View File

@@ -51,7 +51,7 @@ typedef unsigned long long uint64_t;
/* libssh version */
#define LIBSSH_VERSION_MAJOR 0
#define LIBSSH_VERSION_MINOR 3
#define LIBSSH_VERSION_MICRO 0
#define LIBSSH_VERSION_MICRO 1
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
LIBSSH_VERSION_MINOR, \
@@ -80,7 +80,6 @@ typedef struct channel_struct CHANNEL;
typedef struct agent_struct AGENT;
typedef struct ssh_session SSH_SESSION;
typedef struct ssh_kbdint SSH_KBDINT;
struct keys_struct;
/* integer values */
typedef uint32_t u32;
@@ -134,6 +133,7 @@ typedef int socket_t;
#define SSH_SERVER_KNOWN_OK 1
#define SSH_SERVER_KNOWN_CHANGED 2
#define SSH_SERVER_FOUND_OTHER 3
#define SSH_SERVER_FILE_NOT_FOUND 4
#ifndef MD5_DIGEST_LEN
#define MD5_DIGEST_LEN 16
@@ -210,6 +210,7 @@ int ssh_connect(SSH_SESSION *session);
void ssh_disconnect(SSH_SESSION *session);
int ssh_service_request(SSH_SESSION *session, const char *service);
char *ssh_get_issue_banner(SSH_SESSION *session);
int ssh_get_openssh_version(SSH_SESSION *session);
/* get copyright informations */
const char *ssh_copyright(void);
@@ -256,9 +257,6 @@ PUBLIC_KEY *publickey_from_privatekey(PRIVATE_KEY *prv);
void privatekey_free(PRIVATE_KEY *prv);
STRING *publickey_from_file(SSH_SESSION *session, const char *filename,
int *type);
STRING *try_publickey_from_file(SSH_SESSION *session,
struct keys_struct keytab,
char **privkeyfile, int *type);
int ssh_is_server_known(SSH_SESSION *session);
int ssh_write_knownhost(SSH_SESSION *session);
@@ -369,14 +367,15 @@ int ssh_userauth_agent_pubkey(SSH_SESSION *session, const char *username,
int ssh_userauth_autopubkey(SSH_SESSION *session, const char *passphrase);
int ssh_userauth_kbdint(SSH_SESSION *session, const char *user, const char *submethods);
int ssh_userauth_kbdint_getnprompts(SSH_SESSION *session);
char *ssh_userauth_kbdint_getname(SSH_SESSION *session);
char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session);
char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session, unsigned int i, char *echo);
const char *ssh_userauth_kbdint_getname(SSH_SESSION *session);
const char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session);
const char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session, unsigned int i, char *echo);
int ssh_userauth_kbdint_setanswer(SSH_SESSION *session, unsigned int i,
const char *answer);
/* init.c */
int ssh_init(void);
int ssh_finalize(void);
#ifdef __cplusplus

View File

@@ -174,7 +174,11 @@ void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len);
struct string_struct {
u32 size;
unsigned char string[MAX_PACKET_LEN];
} __attribute__ ((packed));
}
#if !defined(__SUNPRO_C)
__attribute__ ((packed))
#endif
;
/** Describes a buffer state at a moment
*/
@@ -333,6 +337,7 @@ struct ssh_session {
int protoversion;
int server;
int client;
int openssh;
u32 send_seq;
u32 recv_seq;
/* status flags */
@@ -603,6 +608,9 @@ char *ssh_find_matching(const char *in_d, const char *what_d);
PRIVATE_KEY *_privatekey_from_file(void *session, const char *filename,
int type);
STRING *try_publickey_from_file(SSH_SESSION *session,
struct keys_struct keytab,
char **privkeyfile, int *type);
/* in keys.c */
const char *ssh_type_to_char(int type);
@@ -719,6 +727,12 @@ int match_hostname(const char *host, const char *pattern, unsigned int len);
/* log.c */
#ifndef __FUNCTION__
#if defined(__SUNPRO_C)
#define __FUNCTION__ __func__
#endif
#endif
#define _enter_function(sess) \
do {\
if((sess)->log_verbosity >= SSH_LOG_FUNCTIONS){ \

View File

@@ -592,6 +592,30 @@ int sftp_chmod(SFTP_SESSION *sftp, const char *file, mode_t mode);
*/
int sftp_utimes(SFTP_SESSION *sftp, const char *file, const struct timeval *times);
/**
* @brief Create a symbolic link.
*
* @param sftp The sftp session handle.
*
* @param target Specifies the target of the symlink.
*
* @param dest Specifies the path name of the symlink to be created.
*
* @return 0 on success, < 0 on error with ssh and sftp error set.
*/
int sftp_symlink(SFTP_SESSION *sftp, const char *target, const char *dest);
/**
* @brief Read the value of a symbolic link.
*
* @param sftp The sftp session handle.
*
* @param path Specifies the path name of the symlink to be read.
*
* @return The target of the link, NULL on error.
*/
char *sftp_readlink(SFTP_SESSION *sftp, const char *path);
/**
* @brief Canonicalize a sftp path.
*

View File

@@ -208,7 +208,7 @@ int ssh_userauth_none(SSH_SESSION *session, const char *username) {
enter_function();
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
if (session->version == 1) {
ssh_userauth1_none(session, username);
leave_function();
@@ -314,7 +314,7 @@ int ssh_userauth_offer_pubkey(SSH_SESSION *session, const char *username,
enter_function();
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
if (session->version == 1) {
ssh_userauth1_offer_pubkey(session, username, type, publickey);
leave_function();
@@ -671,7 +671,7 @@ int ssh_userauth_password(SSH_SESSION *session, const char *username,
enter_function();
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
if (session->version == 1) {
rc = ssh_userauth1_password(session, username, password);
leave_function();
@@ -1417,7 +1417,7 @@ int ssh_userauth_kbdint_getnprompts(SSH_SESSION *session) {
*
* @returns The name of the message block. Do not free it.
*/
char *ssh_userauth_kbdint_getname(SSH_SESSION *session) {
const char *ssh_userauth_kbdint_getname(SSH_SESSION *session) {
return session->kbdint->name;
}
@@ -1432,7 +1432,7 @@ char *ssh_userauth_kbdint_getname(SSH_SESSION *session) {
* @returns The instruction of the message block.
*/
char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session) {
const char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session) {
return session->kbdint->instruction;
}
@@ -1452,7 +1452,7 @@ char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session) {
*
* @returns A pointer to the prompt. Do not free it.
*/
char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session, unsigned int i,
const char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session, unsigned int i,
char *echo) {
if (i > session->kbdint->nprompts) {
return NULL;
@@ -1475,7 +1475,7 @@ char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session, unsigned int i,
*/
int ssh_userauth_kbdint_setanswer(SSH_SESSION *session, unsigned int i,
const char *answer) {
if (i > session->kbdint->nprompts) {
if (session == NULL || answer == NULL || i > session->kbdint->nprompts) {
return -1;
}

View File

@@ -27,7 +27,7 @@
#include "libssh/priv.h"
#include "libssh/ssh1.h"
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
static int wait_auth1_status(SSH_SESSION *session) {
/* wait for a packet */
if (packet_read(session) != SSH_OK) {
@@ -138,7 +138,11 @@ int ssh_userauth_offer_pubkey(SSH_SESSION *session, char *username,int type, STR
*/
int ssh_userauth1_offer_pubkey(SSH_SESSION *session, const char *username,
int type, STRING *pubkey) {
return SSH_AUTH_DENIED;
(void) session;
(void) username;
(void) type;
(void) pubkey;
return SSH_AUTH_DENIED;
}
/*
@@ -247,5 +251,5 @@ int ssh_userauth1_password(SSH_SESSION *session, const char *username,
return wait_auth1_status(session);
}
#endif /* HAVE_SSH1 */
#endif /* WITH_SSH1 */
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -315,7 +315,7 @@ static void channel_rcv_change_window(SSH_SESSION *session) {
channel = channel_from_msg(session);
if (channel == NULL) {
ssh_log(session, SSH_LOG_FUNCTIONS, ssh_get_error(session));
ssh_log(session, SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session));
}
rc = buffer_get_u32(session->in_buffer, &bytes);
@@ -413,7 +413,7 @@ static void channel_rcv_eof(SSH_SESSION *session) {
channel = channel_from_msg(session);
if (channel == NULL) {
ssh_log(session, SSH_LOG_FUNCTIONS, ssh_get_error(session));
ssh_log(session, SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session));
leave_function();
return;
}
@@ -435,7 +435,7 @@ static void channel_rcv_close(SSH_SESSION *session) {
channel = channel_from_msg(session);
if (channel == NULL) {
ssh_log(session, SSH_LOG_FUNCTIONS, ssh_get_error(session));
ssh_log(session, SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session));
leave_function();
return;
}
@@ -477,7 +477,7 @@ static void channel_rcv_request(SSH_SESSION *session) {
channel = channel_from_msg(session);
if (channel == NULL) {
ssh_log(session, SSH_LOG_FUNCTIONS, ssh_get_error(session));
ssh_log(session, SSH_LOG_FUNCTIONS,"%s", ssh_get_error(session));
leave_function();
return;
}
@@ -641,7 +641,7 @@ int channel_default_bufferize(CHANNEL *channel, void *data, int len,
* @see channel_request_exec()
*/
int channel_open_session(CHANNEL *channel) {
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
if (channel->session->version == 1) {
return channel_open_session1(channel);
}
@@ -885,7 +885,7 @@ int channel_write(CHANNEL *channel, const void *data, u32 len) {
return -1;
}
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
if (channel->version == 1) {
int rc = channel_write1(channel, data, len);
leave_function();
@@ -1088,7 +1088,7 @@ int channel_request_pty_size(CHANNEL *channel, const char *terminal,
int rc = SSH_ERROR;
enter_function();
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
if (channel->version==1) {
channel_request_pty_size1(channel,terminal, col, row);
leave_function();
@@ -1157,7 +1157,7 @@ int channel_change_pty_size(CHANNEL *channel, int cols, int rows) {
enter_function();
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
if (channel->version == 1) {
rc = channel_change_pty_size1(channel,cols,rows);
leave_function();
@@ -1193,7 +1193,7 @@ error:
* @returns SSH_SUCCESS on success, SSH_ERROR on error.
*/
int channel_request_shell(CHANNEL *channel) {
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
if (channel->version == 1) {
return channel_request_shell1(channel);
}
@@ -1312,7 +1312,7 @@ int channel_request_exec(CHANNEL *channel, const char *cmd) {
STRING *command = NULL;
int rc = SSH_ERROR;
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
if (channel->version == 1) {
return channel_request_exec1(channel, cmd);
}

View File

@@ -29,7 +29,7 @@
#include "libssh/priv.h"
#include "libssh/ssh1.h"
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
/*
* This is a big hack. In fact, SSH1 doesn't make a clever use of channels.
@@ -301,5 +301,5 @@ int channel_write1(CHANNEL *channel, const void *data, int len) {
return origlen;
}
#endif /* HAVE_SSH1 */
#endif /* WITH_SSH1 */
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -98,7 +98,10 @@ char *ssh_get_banner(SSH_SESSION *session) {
* @see ssh_get_banner()
*/
static int ssh_analyze_banner(SSH_SESSION *session, int *ssh1, int *ssh2) {
char *banner = session->serverbanner;
const char *banner = session->serverbanner;
const char *openssh;
ssh_log(session, SSH_LOG_RARE, "Analyzing banner: %s", banner);
if (strncmp(banner, "SSH-", 4) != 0) {
ssh_set_error(session, SSH_FATAL, "Protocol mismatch: %s", banner);
@@ -129,6 +132,17 @@ static int ssh_analyze_banner(SSH_SESSION *session, int *ssh1, int *ssh2) {
return -1;
}
openssh = strstr(banner, "OpenSSH");
if (openssh != NULL) {
int major, minor;
major = strtol(openssh + 8, (char **) NULL, 10);
minor = strtol(openssh + 10, (char **) NULL, 10);
session->openssh = SSH_VERSION_INT(major, minor, 0);
ssh_log(session, SSH_LOG_RARE,
"We are talking to an OpenSSH server version: %d.%d (%x)",
major, minor, session->openssh);
}
return 0;
}
@@ -221,6 +235,7 @@ static int dh_handshake(SSH_SESSION *session) {
}
string_burn(e);
string_free(e);
e=NULL;
rc = packet_send(session);
if (rc == SSH_ERROR) {
@@ -261,7 +276,7 @@ static int dh_handshake(SSH_SESSION *session) {
}
string_burn(f);
string_free(f);
f=NULL;
signature = buffer_get_ssh_string(session->in_buffer);
if (signature == NULL) {
ssh_set_error(session, SSH_FATAL, "No signature in packet");
@@ -332,13 +347,14 @@ static int dh_handshake(SSH_SESSION *session) {
/* forget it for now ... */
string_burn(signature);
string_free(signature);
signature=NULL;
/*
* Once we got SSH2_MSG_NEWKEYS we can switch next_crypto and
* current_crypto
*/
if (session->current_crypto) {
crypto_free(session->current_crypto);
session->current_crypto=NULL;
}
/* FIXME later, include a function to change keys */
@@ -364,14 +380,22 @@ static int dh_handshake(SSH_SESSION *session) {
/* not reached */
error:
string_burn(e);
string_free(e);
string_burn(f);
string_free(f);
string_burn(pubkey);
string_free(pubkey);
string_burn(signature);
string_free(signature);
if(e != NULL){
string_burn(e);
string_free(e);
}
if(f != NULL){
string_burn(f);
string_free(f);
}
if(pubkey != NULL){
string_burn(pubkey);
string_free(pubkey);
}
if(signature != NULL){
string_burn(signature);
string_free(signature);
}
leave_function();
return rc;
@@ -467,15 +491,10 @@ int ssh_connect(SSH_SESSION *session) {
session->alive = 0;
session->client = 1;
if (ssh_crypto_init() < 0) {
if (ssh_init() < 0) {
leave_function();
return SSH_ERROR;
}
if (ssh_socket_init() < 0) {
leave_function();
return SSH_ERROR;
}
if (options->fd == -1 && options->host == NULL) {
ssh_set_error(session, SSH_FATAL, "Hostname required");
leave_function();
@@ -610,6 +629,24 @@ char *ssh_get_issue_banner(SSH_SESSION *session) {
return string_to_char(session->banner);
}
/**
* @brief Get the version of the OpenSSH server, if it is not an OpenSSH server
* then 0 will be returned.
*
* You can use the SSH_VERSION_INT macro to compare version numbers.
*
* @param session The SSH session to use.
*
* @return The version number if available, 0 otherwise.
*/
int ssh_get_openssh_version(SSH_SESSION *session) {
if (session == NULL) {
return 0;
}
return session->openssh;
}
/**
* @brief Disconnect from a session (client or server).
*
@@ -618,13 +655,12 @@ char *ssh_get_issue_banner(SSH_SESSION *session) {
void ssh_disconnect(SSH_SESSION *session) {
STRING *str = NULL;
enter_function();
if (session == NULL) {
leave_function();
return;
}
enter_function();
if (ssh_socket_is_open(session->socket)) {
if (buffer_add_u8(session->out_buffer, SSH2_MSG_DISCONNECT) < 0) {
goto error;

View File

@@ -31,12 +31,29 @@
* @{
*/
/**
* @brief initialize global cryptographic data structures.
*
* This function should only be called once, at the begining of the program, in the main thread. It may be omitted if your program is not multithreaded.
*
* @returns 0
*/
int ssh_init(void) {
if(ssh_crypto_init())
return -1;
if(ssh_socket_init())
return -1;
return 0;
}
/**
* @brief Finalize and cleanup all libssh and cryptographic data structures.
*
* This function should only be called once, at the end of the program!
*
* @returns 0
* @returns -1 in case of error
@returns 0 otherwise
*/
int ssh_finalize(void) {
ssh_crypto_finalize();

View File

@@ -1280,9 +1280,9 @@ static int match_hashed_host(SSH_SESSION *session, const char *host,
leave_function();
return 0;
}
SAFE_FREE(source);
hash = base64_to_bin(b64hash);
SAFE_FREE(source);
if (hash == NULL) {
buffer_free(salt);
leave_function();
@@ -1342,6 +1342,9 @@ static int match_hashed_host(SSH_SESSION *session, const char *host,
* possible attack \n
* SSH_SERVER_NOT_KNOWN: The server is unknown. User should confirm
* the MD5 is correct\n
* SSH_SERVER_FILE_NOT_FOUND:The known host file does not exist. The
* host is thus unknown. File will be created
* if host key is accepted\n
* SSH_SERVER_ERROR: Some error happened
*
* \see ssh_options_set_wanted_algo()
@@ -1361,10 +1364,10 @@ int ssh_is_server_known(SSH_SESSION *session) {
enter_function();
if (ssh_options_default_known_hosts_file(session->options) < 0) {
ssh_set_error(session, SSH_FATAL,
ssh_set_error(session, SSH_REQUEST_DENIED,
"Can't find a known_hosts file");
leave_function();
return SSH_SERVER_ERROR;
return SSH_SERVER_FILE_NOT_FOUND;
}
if (session->options->host == NULL) {
@@ -1418,6 +1421,8 @@ int ssh_is_server_known(SSH_SESSION *session) {
/* We override the status with the wrong key state */
ret = SSH_SERVER_KNOWN_CHANGED;
}
} else {
tokens_free(tokens);
}
} while (1);
@@ -1432,7 +1437,7 @@ int ssh_is_server_known(SSH_SESSION *session) {
}
/** You generaly use it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN
* \brief write the current server as known in the known hosts file
* \brief write the current server as known in the known hosts file. This will create the known hosts file if it does not exist.
* \param session ssh session
* \return 0 on success, -1 on error
*/
@@ -1571,7 +1576,7 @@ int ssh_write_knownhost(SSH_SESSION *session) {
}
len = strlen(buffer);
if (fwrite(buffer, len, 1, file) != len || ferror(file)) {
if (fwrite(buffer, len, 1, file) != 1 || ferror(file)) {
fclose(file);
return -1;
}

View File

@@ -1,61 +1,185 @@
SSH_0.3 {
global:
ssh_get_error; ssh_get_error_code;
ssh_new; ssh_set_options; ssh_get_fd; ssh_silent_disconnect;
ssh_connect; ssh_disconnect; ssh_service_request; ssh_get_issue_banner;
ssh_copyright; ssh_get_version; ssh_finalize;
ssh_set_fd_toread; ssh_set_fd_towrite; ssh_set_fd_except;
string_from_char; string_len; string_new; string_fill; string_to_char;
string_copy; string_burn; string_data;
ssh_crypto_init;
ssh_get_hexa; ssh_print_hexa; ssh_get_random;
ssh_get_pubkey_hash; ssh_get_pubkey;
ssh_fd_poll; ssh_select; publickey_free;
privatekey_from_file; publickey_to_string; publickey_from_privatekey;
private_key_free; publickey_from_file; try_publickey_from_file;
ssh_is_server_known; ssh_write_knownhost;
channel_new; channel_open_forward; channel_open_session; channel_free;
channel_request_pty; channel_request_pty_size; channel_change_pty_size;
channel_request_shell; channel_request_subsystem; channel_request_env;
channel_request_exec; channel_request_sftp; channel_write;
channel_send_eof; channel_read_buffer; channel_read; channel_read_nonblocking;
channel_poll; channel_close; channel_is_open;
channel_is_closed; channel_is_eof; channel_select;
ssh_options_new; ssh_options_copy; ssh_options_free; ssh_options_set_wanted_algos;
ssh_options_set_username; ssh_options_set_port; ssh_options_getopt;
ssh_options_set_host; ssh_options_set_fd; ssh_options_set_bind;
ssh_options_set_identity; ssh_options_set_status_callback;
ssh_options_set_timeout; ssh_options_set_ssh_dir;
ssh_options_set_known_hosts_file; ssh_options_allow_ssh1;
ssh_options_allow_ssh2; ssh_options_set_dsa_server_key;
ssh_options_set_rsa_server_key;
buffer_new; buffer_free; buffer_get; buffer_get_len;
ssh_userauth_none; ssh_userauth_password; ssh_userauth_offer_pubkey;
ssh_userauth_pubkey; ssh_userauth_autopubkey; ssh_userauth_kbdint;
ssh_userauth_kbdint_getnprompts; ssh_userauth_kbdint_getname;
ssh_userauth_kbdint_getinstruction; ssh_userauth_kbdint_getprompt;
ssh_userauth_kbdint_setanswer;
sftp_new; sftp_free; sftp_init; sftp_opendir; sftp_readdir; sftp_dir_eof;
sftp_stat; sftp_lstat; sftp_fstat; sftp_attributes_free; sftp_dir_close;
sftp_file_close; sftp_open; sftp_read; sftp_write; sftp_seek; sftp_tell;
sftp_rewind; sftp_rm; sftp_rmdir; sftp_mkdir; sftp_rename; sftp_setstat;
sftp_canonicalize_path; sftp_server_new; sftp_server_init;
sftp_get_client_message; sftp_client_message_free; sftp_reply_name;
sftp_reply_handle; sftp_handle_alloc; sftp_reply_attr; sftp_handle;
sftp_reply_status; sftp_reply_names_add; sftp_reply_names;
sftp_reply_data; sftp_handle_remove;
ssh_bind_new; ssh_bind_set_options; ssh_bind_listen; ssh_bind_set_blocking;
ssh_bind_get_fd; ssh_bind_set_toaccept; ssh_bind_accept; ssh_bind_free;
buffer_free;
buffer_get;
buffer_get_len;
buffer_new;
channel_change_pty_size;
channel_close;
channel_free;
channel_get_exit_status;
channel_get_session;
channel_is_closed;
channel_is_eof;
channel_is_open;
channel_new;
channel_open_forward;
channel_open_session;
channel_poll;
channel_read;
channel_read_buffer;
channel_read_nonblocking;
channel_request_env;
channel_request_exec;
channel_request_pty;
channel_request_pty_size;
channel_request_sftp;
channel_request_shell;
channel_request_subsystem;
channel_select;
channel_send_eof;
channel_set_blocking;
channel_write;
privatekey_free;
privatekey_from_file;
publickey_free;
publickey_from_file;
publickey_from_privatekey;
publickey_to_string;
sftp_async_read;
sftp_async_read_begin;
sftp_attributes_free;
sftp_canonicalize_path;
sftp_chmod;
sftp_chown;
sftp_close;
sftp_closedir;
sftp_dir_eof;
sftp_file_set_blocking;
sftp_file_set_nonblocking;
sftp_free;
sftp_fstat;
sftp_get_error;
sftp_init;
sftp_lstat;
sftp_mkdir;
sftp_new;
sftp_open;
sftp_opendir;
sftp_read;
sftp_readdir;
sftp_readlink;
sftp_rename;
sftp_rewind;
sftp_rmdir;
sftp_seek;
sftp_seek64;
sftp_server_init;
sftp_server_new;
sftp_server_version;
sftp_setstat;
sftp_stat;
sftp_symlink;
sftp_tell;
sftp_tell64;
sftp_unlink;
sftp_utimes;
sftp_write;
ssh_accept;
ssh_message_get; ssh_message_type; ssh_message_subtype;
ssh_message_reply_default; ssh_message_free; ssh_message_auth_user;
ssh_message_auth_password; ssh_message_auth_reply_success;
ssh_auth_list;
ssh_bind_accept;
ssh_bind_fd_toaccept;
ssh_bind_free;
ssh_bind_get_fd;
ssh_bind_listen;
ssh_bind_new;
ssh_bind_set_blocking;
ssh_bind_set_fd;
ssh_bind_set_options;
ssh_clean_pubkey_hash;
ssh_connect;
ssh_copyright;
ssh_disconnect;
ssh_fd_poll;
ssh_finalize;
ssh_get_disconnect_message;
ssh_get_error;
ssh_get_error_code;
ssh_get_fd;
ssh_get_hexa;
ssh_get_issue_banner;
ssh_get_openssh_version;
ssh_get_pubkey;
ssh_get_pubkey_hash;
ssh_get_random;
ssh_get_status;
ssh_get_version;
ssh_init;
ssh_is_server_known;
ssh_log;
ssh_message_auth_password;
ssh_message_auth_publickey;
ssh_message_auth_reply_pk_ok;
ssh_message_auth_reply_success;
ssh_message_auth_set_methods;
ssh_message_auth_user;
ssh_message_channel_request_open_reply_accept;
ssh_message_channel_request_channel; ssh_message_channel_request_pty_term;
ssh_message_channel_request_subsystem;
ssh_message_channel_request_reply_success;
set_encrypt_key; set_decrypt_key; cbc_encrypt; cbc_decrypt;
ssh_message_free;
ssh_message_get;
ssh_message_reply_default;
ssh_message_retrieve;
ssh_message_service_reply_success;
ssh_message_service_service;
ssh_message_subtype;
ssh_message_type;
ssh_new;
ssh_options_allow_ssh1;
ssh_options_allow_ssh2;
ssh_options_copy;
ssh_options_free;
ssh_options_getopt;
ssh_options_new;
ssh_options_set_auth_callback;
ssh_options_set_banner;
ssh_options_set_bind;
ssh_options_set_dsa_server_key;
ssh_options_set_fd;
ssh_options_set_host;
ssh_options_set_identity;
ssh_options_set_known_hosts_file;
ssh_options_set_log_function;
ssh_options_set_log_verbosity;
ssh_options_set_port;
ssh_options_set_rsa_server_key;
ssh_options_set_ssh_dir;
ssh_options_set_status_callback;
ssh_options_set_timeout;
ssh_options_set_username;
ssh_options_set_wanted_algos;
ssh_print_hexa;
ssh_select;
ssh_service_request;
ssh_set_blocking;
ssh_set_fd_except;
ssh_set_fd_toread;
ssh_set_fd_towrite;
ssh_set_options;
ssh_silent_disconnect;
ssh_userauth_agent_pubkey;
ssh_userauth_autopubkey;
ssh_userauth_kbdint;
ssh_userauth_kbdint_getinstruction;
ssh_userauth_kbdint_getname;
ssh_userauth_kbdint_getnprompts;
ssh_userauth_kbdint_getprompt;
ssh_userauth_kbdint_setanswer;
ssh_userauth_list;
ssh_userauth_none;
ssh_userauth_offer_pubkey;
ssh_userauth_password;
ssh_userauth_pubkey;
ssh_version;
ssh_write_knownhost;
string_burn;
string_copy;
string_data;
string_fill;
string_free;
string_from_char;
string_len;
string_new;
string_to_char;
local:
*;
};

View File

@@ -783,7 +783,9 @@ void ssh_message_free(SSH_MESSAGE *msg){
SAFE_FREE(msg->channel_request.subsystem);
break;
}
ZERO_STRUCTP(msg);
SAFE_FREE(msg);
}
/**

View File

@@ -60,7 +60,7 @@ SSH_OPTIONS *ssh_options_new(void) {
option->port=22; /* set the default port */
option->fd=-1;
option->ssh2allowed=1;
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
option->ssh1allowed=1;
#else
option->ssh1allowed=0;
@@ -830,7 +830,7 @@ int ssh_options_getopt(SSH_OPTIONS *options, int *argcptr, char **argv) {
int compress = 0;
int cont = 1;
int current = 0;
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
int ssh1 = 1;
#else
int ssh1 = 0;

View File

@@ -214,7 +214,7 @@ error:
return rc;
}
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
/* a slighty modified packet_read2() for SSH-1 protocol */
static int packet_read1(SSH_SESSION *session) {
void *packet = NULL;
@@ -363,11 +363,11 @@ error:
return rc;
}
#endif /* HAVE_SSH1 */
#endif /* WITH_SSH1 */
/* that's where i'd like C to be object ... */
int packet_read(SSH_SESSION *session) {
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
if (session->version == 1) {
return packet_read1(session);
}
@@ -580,7 +580,7 @@ error:
return rc; /* SSH_OK, AGAIN or ERROR */
}
#endif /* HAVE_SSH1 */
#endif /* WITH_SSH1 */
int packet_send(SSH_SESSION *session) {
#ifdef HAVE_SSH1
@@ -597,7 +597,7 @@ void packet_parse(SSH_SESSION *session) {
int type = session->in_packet.type;
u32 tmp;
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
if (session->version == 1) {
/* SSH-1 */
switch(type) {
@@ -622,7 +622,7 @@ void packet_parse(SSH_SESSION *session) {
}
return;
} else {
#endif /* HAVE_SSH1 */
#endif /* WITH_SSH1 */
switch(type) {
case SSH2_MSG_DISCONNECT:
buffer_get_u32(session->in_buffer, &tmp);
@@ -658,12 +658,12 @@ void packet_parse(SSH_SESSION *session) {
default:
ssh_log(session, SSH_LOG_RARE, "Received unhandled packet %d", type);
}
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
}
#endif
}
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
static int packet_wait1(SSH_SESSION *session, int type, int blocking) {
enter_function();
@@ -719,7 +719,7 @@ static int packet_wait1(SSH_SESSION *session, int type, int blocking) {
leave_function();
return SSH_OK;
}
#endif /* HAVE_SSH1 */
#endif /* WITH_SSH1 */
static int packet_wait2(SSH_SESSION *session, int type, int blocking) {
int rc = SSH_ERROR;
@@ -773,7 +773,7 @@ static int packet_wait2(SSH_SESSION *session, int type, int blocking) {
}
int packet_wait(SSH_SESSION *session, int type, int block) {
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
if (session->version == 1) {
return packet_wait1(session, type, block);
}

View File

@@ -25,6 +25,8 @@
/* This code is based on glib's gpoll */
#include <errno.h>
#include "config.h"
#include "libssh/priv.h"

View File

@@ -135,7 +135,7 @@ int ssh_bind_listen(SSH_BIND *ssh_bind) {
return -1;
}
if (ssh_socket_init() < 0) {
if (ssh_init() < 0) {
return -1;
}
@@ -479,10 +479,6 @@ int ssh_accept(SSH_SESSION *session) {
return -1;
}
if (ssh_crypto_init() < 0) {
return -1;
}
session->alive = 1;
session->clientbanner = ssh_get_banner(session);

View File

@@ -1681,6 +1681,7 @@ ssize_t sftp_write(SFTP_FILE *file, const void *buf, size_t count) {
BUFFER *buffer;
u32 id;
int len;
int packetlen;
buffer = buffer_new();
if (buffer == NULL) {
@@ -1704,12 +1705,12 @@ ssize_t sftp_write(SFTP_FILE *file, const void *buf, size_t count) {
return -1;
}
string_free(datastring);
len = sftp_packet_write(file->sftp, SSH_FXP_WRITE, buffer);
packetlen=buffer_get_len(buffer);
buffer_free(buffer);
if (len < 0) {
return -1;
} else if ((u32) len != buffer_get_len(buffer)) {
} else if (len != packetlen) {
ssh_log(sftp->session, SSH_LOG_PACKET,
"Could not write as much data as expected");
}
@@ -2211,6 +2212,185 @@ int sftp_utimes(SFTP_SESSION *sftp, const char *file,
return sftp_setstat(sftp, file, &attr);
}
int sftp_symlink(SFTP_SESSION *sftp, const char *target, const char *dest) {
STATUS_MESSAGE *status = NULL;
SFTP_MESSAGE *msg = NULL;
STRING *target_s;
STRING *dest_s;
BUFFER *buffer;
u32 id;
if (sftp == NULL || target == NULL || dest == NULL) {
return -1;
}
buffer = buffer_new();
if (buffer == NULL) {
return -1;
}
target_s = string_from_char(target);
if (target_s == NULL) {
buffer_free(buffer);
return -1;
}
dest_s = string_from_char(dest);
if (dest_s == NULL) {
string_free(target_s);
buffer_free(buffer);
return -1;
}
id = sftp_get_new_id(sftp);
if (buffer_add_u32(buffer, id) < 0) {
buffer_free(buffer);
string_free(dest_s);
string_free(target_s);
return -1;
}
if (ssh_get_openssh_version(sftp->session)) {
/* TODO check for version number if they ever fix it. */
if (buffer_add_ssh_string(buffer, target_s) < 0 ||
buffer_add_ssh_string(buffer, dest_s) < 0) {
buffer_free(buffer);
string_free(dest_s);
string_free(target_s);
return -1;
}
} else {
if (buffer_add_ssh_string(buffer, dest_s) < 0 ||
buffer_add_ssh_string(buffer, target_s) < 0) {
buffer_free(buffer);
string_free(dest_s);
string_free(target_s);
return -1;
}
}
if (sftp_packet_write(sftp, SSH_FXP_SYMLINK, buffer) < 0) {
buffer_free(buffer);
string_free(dest_s);
string_free(target_s);
return -1;
}
buffer_free(buffer);
string_free(dest_s);
string_free(target_s);
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
return -1;
}
msg = sftp_dequeue(sftp, id);
}
/* By specification, this command only returns SSH_FXP_STATUS */
if (msg->packet_type == SSH_FXP_STATUS) {
status = parse_status_msg(msg);
sftp_message_free(msg);
if (status == NULL) {
return -1;
}
sftp_set_error(sftp, status->status);
switch (status->status) {
case SSH_FX_OK:
status_msg_free(status);
return 0;
default:
break;
}
/*
* The status should be SSH_FX_OK if the command was successful, if it
* didn't, then there was an error
*/
ssh_set_error(sftp->session, SSH_REQUEST_DENIED,
"SFTP server: %s", status->errormsg);
status_msg_free(status);
return -1;
} else {
ssh_set_error(sftp->session, SSH_FATAL,
"Received message %d when attempting to set stats", msg->packet_type);
sftp_message_free(msg);
}
return -1;
}
char *sftp_readlink(SFTP_SESSION *sftp, const char *path) {
STATUS_MESSAGE *status = NULL;
SFTP_MESSAGE *msg = NULL;
STRING *path_s = NULL;
STRING *link_s = NULL;
BUFFER *buffer;
char *link;
u32 ignored;
u32 id;
if (sftp == NULL || path == NULL) {
return NULL;
}
buffer = buffer_new();
if (buffer == NULL) {
return NULL;
}
path_s = string_from_char(path);
if (path_s == NULL) {
buffer_free(buffer);
return NULL;
}
id = sftp_get_new_id(sftp);
if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, path_s) < 0 ||
sftp_packet_write(sftp, SSH_FXP_READLINK, buffer) < 0) {
buffer_free(buffer);
string_free(path_s);
return NULL;
}
buffer_free(buffer);
string_free(path_s);
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
return NULL;
}
msg = sftp_dequeue(sftp, id);
}
if (msg->packet_type == SSH_FXP_NAME) {
/* we don't care about "count" */
buffer_get_u32(msg->payload, &ignored);
/* we only care about the file name string */
link_s = buffer_get_ssh_string(msg->payload);
sftp_message_free(msg);
if (link_s == NULL) {
return NULL;
}
link = string_to_char(link_s);
string_free(link_s);
return link;
} else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) */
status = parse_status_msg(msg);
sftp_message_free(msg);
if (status == NULL) {
return NULL;
}
ssh_set_error(sftp->session, SSH_REQUEST_DENIED,
"SFTP server: %s", status->errormsg);
status_msg_free(status);
} else { /* this shouldn't happen */
ssh_set_error(sftp->session, SSH_FATAL,
"Received message %d when attempting to set stats", msg->packet_type);
sftp_message_free(msg);
}
return NULL;
}
/* another code written by Nick */
char *sftp_canonicalize_path(SFTP_SESSION *sftp, const char *path) {
STATUS_MESSAGE *status = NULL;

View File

@@ -367,7 +367,8 @@ void do_sftp(SSH_SESSION *session){
static int auth_kbdint(SSH_SESSION *session){
int err=ssh_userauth_kbdint(session,NULL,NULL);
char *name,*instruction,*prompt,*ptr;
const char *name, *instruction, *prompt;
char *ptr;
char buffer[128];
int i,n;
char echo;
@@ -469,9 +470,12 @@ int main(int argc, char **argv){
ssh_disconnect(session);
ssh_finalize();
exit(-1);
case SSH_SERVER_FILE_NOT_FOUND:
fprintf(stderr,"Could not find known host file. If you accept the host key here,\n");
fprintf(stderr,"the file will be automatically created.\n");
/* fallback to SSH_SERVER_NOT_KNOWN behaviour */
case SSH_SERVER_NOT_KNOWN:
hexa = ssh_get_hexa(hash, hlen);
free(hash);
fprintf(stderr,"The server is unknown. Do you trust the host key ?\n");
fprintf(stderr, "Public key hash: %s\n", hexa);
free(hexa);
@@ -483,8 +487,11 @@ int main(int argc, char **argv){
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
fgets(buf,sizeof(buf),stdin);
if(strncasecmp(buf,"yes",3)==0){
if(ssh_write_knownhost(session))
fprintf(stderr,"error %s\n",ssh_get_error(session));
if (ssh_write_knownhost(session) < 0) {
free(hash);
fprintf(stderr, "error %s\n", strerror(errno));
exit(-1);
}
}
break;
@@ -552,8 +559,10 @@ int main(int argc, char **argv){
else
batch_shell(session);
}
#ifdef WITH_SFTP
else
do_sftp(session);
do_sftp(session);
#endif
if(!sftp && !cmds[0])
do_cleanup(0);
ssh_disconnect(session);