Compare commits

...

59 Commits
v0-5 ... v0-3

Author SHA1 Message Date
Aris Adamantiadis
ce9be6dfca Fix underflow when leave_function() are unbalanced 2010-01-26 14:42:49 +01:00
Andreas Schneider
5c3ea09e02 Fixed SSH1 support. 2009-09-24 12:58:35 +02:00
Andreas Schneider
9a571d0f25 Fixed build with mingw. 2009-09-15 10:41:36 +02:00
Andreas Schneider
82eb0427f7 Update ChangeLog. 2009-09-15 00:21:00 +02:00
Andreas Schneider
7cd327a795 Fix a possible stack overflow in agent code. 2009-09-14 19:00:28 +02:00
Andreas Schneider
77a757c728 Update ChangeLog. 2009-09-14 10:18:20 +02:00
Aris Adamantiadis
9ef0837c80 Fix the security bug found by Orange Labs
Verify the length of decrypt operation is a multiple of blocksize
2009-09-13 22:44:31 +02:00
Andreas Schneider
2f66b3be13 Update ChangeLog. 2009-09-09 14:01:56 +02:00
Andreas Schneider
32d5293318 Add a portable ssh_mkdir function for Windows. 2009-09-09 14:01:20 +02:00
Andreas Schneider
e0c969bb41 Add a sftp_tell64() function. 2009-09-08 12:02:25 +02:00
Andreas Schneider
cecd5f0f78 Update ChangeLog. 2009-09-08 11:38:28 +02:00
Andreas Schneider
9bef81c769 Fix the free calls and use the safe free macro. 2009-09-08 11:36:38 +02:00
Andreas Schneider
1093fb43ca Add missing NULL pointer checks to crypt_set_algorithms_server.
Thanks to Orange Labs for the report.
2009-09-08 11:36:28 +02:00
Andreas Schneider
add2aa5f45 Fix an integer overflow in buffer_get_data().
Thanks to Orange Labs for the report.
2009-09-08 11:36:06 +02:00
Andreas Schneider
26cdf0d994 Add ChangeLog entries. 2009-08-26 09:51:32 +02:00
Andreas Schneider
3cf2c3639e Increase version number. 2009-08-26 09:50:18 +02:00
Andreas Schneider
a501d63c8a Fix ssh_write_knownhost() if ~/.ssh doesn't exist. 2009-08-26 09:48:35 +02:00
Andreas Schneider
160053bc39 Added ssh_basename() and ssh_dirname(). 2009-08-26 09:47:20 +02:00
Andreas Schneider
d672dde342 Increase version number and update Changelog. 2009-08-18 10:06:02 +02:00
Vic Lee
86f983962c Fix double free pointer crash in dsa_public_to_string
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2009-08-16 14:41:41 +02:00
Aris Adamantiadis
b0d6307d41 Fix channel_get_exit_status bug reported by VicLee
It would return -1 if the channel received the exit status
and the close message at same time.
2009-08-16 14:41:22 +02:00
Aris Adamantiadis
10920fc678 fix ssh_finalize which didn't clear the flag 2009-08-13 23:30:02 +02:00
Aris Adamantiadis
c87b247e01 Fix memory leak introduced by previous bugfix 2009-08-12 22:12:18 +02:00
Aris Adamantiadis
9abdc5ae2a Fixed channel_poll broken when delayed EOF recvd
Previous code returned SSH_EOF even if data was left in buffer
2009-08-10 23:37:53 +02:00
Aris Adamantiadis
e8e874909f Fixed stupid "can't parse known host key" bug
due to a dangling \n in the base64 ...
2009-08-10 22:53:27 +02:00
milo
74eff86a6b Fix possible memory corruption (#14)
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2009-08-07 11:38:18 +02:00
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
33 changed files with 871 additions and 226 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.4")
set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "3")
set(APPLICATION_VERSION_PATCH "0")
set(APPLICATION_VERSION_PATCH "4")
set(LIBRARY_VERSION "3.0.0")
set(LIBRARY_VERSION "3.4.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 "4")
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")

View File

@@ -1,6 +1,42 @@
ChangeLog
==========
version 0.3.4 (released 2009-09-14)
* Added ssh_basename and ssh_dirname.
* Added a portable ssh_mkdir function.
* Added a sftp_tell64() function.
* Added missing NULL pointer checks to crypt_set_algorithms_server.
* Fixed ssh_write_knownhost if ~/.ssh doesn't exist.
* Fixed a possible integer overflow in buffer_get_data().
* Fixed possible security bug in packet_decrypt().
* Fixed a possible stack overflow in agent code.
version 0.3.3 (released 2009-08-18)
* Fixed double free pointer crash in dsa_public_to_string.
* Fixed channel_get_exit_status bug.
* Fixed ssh_finalize which didn't clear the flag.
* Fixed memory leak introduced by previous bugfix.
* Fixed channel_poll broken when delayed EOF recvd.
* Fixed stupid "can't parse known host key" bug.
* Fixed possible memory corruption (ticket #14).
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 4
#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,19 @@ 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);
/* misc.c */
int ssh_mkdir (const char *pathname, mode_t mode);
char *ssh_dirname (const char *path);
char *ssh_basename (const char *path);
/* 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
*/
@@ -234,7 +238,7 @@ typedef struct signature_struct {
struct error_struct {
/* error handling */
int error_code;
unsigned int error_code;
char error_buffer[ERROR_BUFFERLEN];
};
@@ -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

@@ -469,6 +469,17 @@ int sftp_seek64(SFTP_FILE *file, u64 new_offset);
*/
unsigned long sftp_tell(SFTP_FILE *file);
/**
* @brief Report current byte position in file.
*
* @param file Open sftp file handle.
*
* @return The offset of the current byte relative to the beginning
* of the file associated with the file descriptor. < 0 on
* error.
*/
u64 sftp_tell64(SFTP_FILE *file);
/**
* @brief Rewinds the position of the file pointer to the beginning of the
* file.
@@ -592,6 +603,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

@@ -210,10 +210,7 @@ static int agent_talk(struct ssh_session *session,
/* send length and then the request packet */
if (atomicio(session->agent->sock, payload, 4, 0) == 4) {
buffer_get_data(request, payload, len);
ssh_log(session, SSH_LOG_PACKET,
"agent_talk - sending request, payload[0] = %u", payload[0]);
if (atomicio(session->agent->sock, payload, len, 0)
if (atomicio(session->agent->sock, buffer_get_rest(request), len, 0)
!= len) {
ssh_log(session, SSH_LOG_PACKET, "atomicio sending request failed: %s",
strerror(errno));
@@ -327,7 +324,7 @@ int agent_get_ident_count(struct ssh_session *session) {
}
if (session->agent->ident) {
buffer_free(session->agent->ident);
buffer_reinit(session->agent->ident);
}
session->agent->ident = reply;

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();
@@ -268,7 +268,7 @@ int ssh_userauth_none(SSH_SESSION *session, const char *username) {
leave_function();
return rc;
error:
buffer_free(session->out_buffer);
buffer_reinit(session->out_buffer);
string_free(service);
string_free(method);
string_free(user);
@@ -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();
@@ -382,7 +382,7 @@ int ssh_userauth_offer_pubkey(SSH_SESSION *session, const char *username,
leave_function();
return rc;
error:
buffer_free(session->out_buffer);
buffer_reinit(session->out_buffer);
string_free(user);
string_free(method);
string_free(service);
@@ -503,7 +503,7 @@ int ssh_userauth_pubkey(SSH_SESSION *session, const char *username,
leave_function();
return rc;
error:
buffer_free(session->out_buffer);
buffer_reinit(session->out_buffer);
string_free(user);
string_free(service);
string_free(method);
@@ -627,7 +627,7 @@ int ssh_userauth_agent_pubkey(SSH_SESSION *session, const char *username,
return rc;
error:
buffer_free(session->out_buffer);
buffer_reinit(session->out_buffer);
string_free(sign);
string_free(user);
string_free(service);
@@ -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();
@@ -739,7 +739,7 @@ int ssh_userauth_password(SSH_SESSION *session, const char *username,
leave_function();
return rc;
error:
buffer_free(session->out_buffer);
buffer_reinit(session->out_buffer);
string_free(user);
string_free(service);
string_free(method);
@@ -1123,7 +1123,7 @@ static int kbdauth_init(SSH_SESSION *session, const char *user,
leave_function();
return rc;
error:
buffer_free(session->out_buffer);
buffer_reinit(session->out_buffer);
string_free(usr);
string_free(service);
string_free(method);
@@ -1290,7 +1290,7 @@ static int kbdauth_send(SSH_SESSION *session) {
leave_function();
return rc;
error:
buffer_free(session->out_buffer);
buffer_reinit(session->out_buffer);
string_burn(answer);
string_free(answer);
@@ -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

@@ -298,8 +298,13 @@ u32 buffer_pass_bytes_end(struct buffer_struct *buffer, u32 len){
* \returns len otherwise.
*/
u32 buffer_get_data(struct buffer_struct *buffer, void *data, u32 len){
if(buffer->pos+len>buffer->used)
return 0; /*no enough data in buffer */
/*
* Check for a integer overflow first, then check if not enough data is in
* the buffer.
*/
if (buffer->pos + len < len || buffer->pos + len > buffer->used) {
return 0;
}
memcpy(data,buffer->data+buffer->pos,len);
buffer->pos+=len;
return len; /* no yet support for partial reads (is it really needed ?? ) */

View File

@@ -280,7 +280,7 @@ static int grow_window(SSH_SESSION *session, CHANNEL *channel, int minimumsize)
leave_function();
return 0;
error:
buffer_free(session->out_buffer);
buffer_reinit(session->out_buffer);
leave_function();
return -1;
@@ -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);
}
@@ -791,7 +791,7 @@ int channel_send_eof(CHANNEL *channel){
leave_function();
return rc;
error:
buffer_free(session->out_buffer);
buffer_reinit(session->out_buffer);
leave_function();
return rc;
@@ -844,7 +844,7 @@ int channel_close(CHANNEL *channel){
leave_function();
return rc;
error:
buffer_free(session->out_buffer);
buffer_reinit(session->out_buffer);
leave_function();
return rc;
@@ -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();
@@ -938,7 +938,7 @@ int channel_write(CHANNEL *channel, const void *data, u32 len) {
leave_function();
return origlen;
error:
buffer_free(session->out_buffer);
buffer_reinit(session->out_buffer);
leave_function();
return SSH_ERROR;
@@ -1060,7 +1060,7 @@ static int channel_request(CHANNEL *channel, const char *request,
leave_function();
return rc;
error:
buffer_free(session->out_buffer);
buffer_reinit(session->out_buffer);
string_free(req);
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);
}
@@ -1618,6 +1618,9 @@ int channel_poll(CHANNEL *channel, int is_stderr){
}
}
if (buffer_get_rest_len(stdbuf) > 0)
return buffer_get_rest_len(stdbuf);
if (channel->remote_eof) {
leave_function();
return SSH_EOF;
@@ -1658,7 +1661,9 @@ int channel_get_exit_status(CHANNEL *channel) {
return -1;
}
if (channel->open == 0) {
return -1;
/* When a channel is closed, no exit status message can
* come anymore */
break;
}
}

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

@@ -246,7 +246,6 @@ socket_t ssh_connect_host(SSH_SESSION *session, const char *host,
ssh_set_error(session, SSH_FATAL, "Connect failed: %s", strerror(errno));
close(s);
s = -1;
leave_function();
continue;
} else {
/* We are connected */

View File

@@ -60,7 +60,10 @@ u32 packet_decrypt_len(SSH_SESSION *session, char *crypted){
int packet_decrypt(SSH_SESSION *session, void *data,u32 len) {
struct crypto_struct *crypto = session->current_crypto->in_cipher;
char *out = NULL;
if(len % session->current_crypto->in_cipher->blocksize != 0){
ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set on at least one blocksize (received %d)",len);
return SSH_ERROR;
}
out = malloc(len);
if (out == NULL) {
return -1;
@@ -100,7 +103,10 @@ unsigned char *packet_encrypt(SSH_SESSION *session, void *data, u32 len) {
if (!session->current_crypto) {
return NULL; /* nothing to do here */
}
if(len % session->current_crypto->in_cipher->blocksize != 0){
ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set on at least one blocksize (received %d)",len);
return NULL;
}
out = malloc(len);
if (out == NULL) {
return NULL;

View File

@@ -149,6 +149,7 @@ void ssh_crypto_finalize(void) {
g = NULL;
bignum_free(p);
p = NULL;
ssh_crypto_initialized=0;
}
}
@@ -626,20 +627,20 @@ int hashbufout_add_cookie(SSH_SESSION *session) {
}
if (buffer_add_u8(session->out_hashbuf, 20) < 0) {
buffer_free(session->out_hashbuf);
buffer_reinit(session->out_hashbuf);
return -1;
}
if (session->server) {
if (buffer_add_data(session->out_hashbuf,
session->server_kex.cookie, 16) < 0) {
buffer_free(session->out_hashbuf);
buffer_reinit(session->out_hashbuf);
return -1;
}
} else {
if (buffer_add_data(session->out_hashbuf,
session->client_kex.cookie, 16) < 0) {
buffer_free(session->out_hashbuf);
buffer_reinit(session->out_hashbuf);
return -1;
}
}
@@ -654,11 +655,11 @@ int hashbufin_add_cookie(SSH_SESSION *session, unsigned char *cookie) {
}
if (buffer_add_u8(session->in_hashbuf, 20) < 0) {
buffer_free(session->in_hashbuf);
buffer_reinit(session->in_hashbuf);
return -1;
}
if (buffer_add_data(session->in_hashbuf,cookie, 16) < 0) {
buffer_free(session->in_hashbuf);
buffer_reinit(session->in_hashbuf);
return -1;
}

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

@@ -421,8 +421,8 @@ int ssh_send_kex(SSH_SESSION *session, int server_kex) {
leave_function();
return 0;
error:
buffer_free(session->out_buffer);
buffer_free(session->out_hashbuf);
buffer_reinit(session->out_buffer);
buffer_reinit(session->out_hashbuf);
string_free(str);
leave_function();

View File

@@ -22,13 +22,15 @@
* MA 02111-1307, USA.
*/
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <ctype.h>
#ifndef _WIN32
#include <arpa/inet.h>
@@ -1074,6 +1076,7 @@ static char **ssh_get_knownhost_line(SSH_SESSION *session, FILE **file,
while (fgets(buffer, sizeof(buffer), *file)) {
ptr = strchr(buffer, '\n');
if (ptr) {
*ptr = '\0';
}
ptr = strchr(buffer,'\r');
@@ -1280,9 +1283,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 +1345,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 +1367,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 +1424,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 +1440,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
*/
@@ -1441,6 +1449,7 @@ int ssh_write_knownhost(SSH_SESSION *session) {
unsigned char *pubkey_64;
char buffer[4096] = {0};
FILE *file;
char *dir;
size_t len = 0;
if (ssh_options_default_known_hosts_file(session->options) < 0) {
@@ -1454,6 +1463,22 @@ int ssh_write_knownhost(SSH_SESSION *session) {
return -1;
}
/* Check if ~/.ssh exists and create it if not */
dir = ssh_dirname(session->options->known_hosts_file);
if (dir == NULL) {
ssh_set_error(session, SSH_FATAL, "%s", strerror(errno));
return -1;
}
if (! ssh_file_readaccess_ok(dir)) {
if (ssh_mkdir(dir, 0700) < 0) {
ssh_set_error(session, SSH_FATAL,
"Cannot create %s directory.", dir);
SAFE_FREE(dir);
return -1;
}
}
SAFE_FREE(dir);
file = fopen(session->options->known_hosts_file, "a");
if (file == NULL) {
ssh_set_error(session, SSH_FATAL,
@@ -1571,7 +1596,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

@@ -540,7 +540,6 @@ static int dsa_public_to_string(DSA *key, BUFFER *buffer) {
goto error;
}
string_fill(n, (char *) tmp, size);
gcry_sexp_release(sexp);
#elif defined HAVE_LIBCRYPTO
p = make_bignum_string(key->p);

View File

@@ -1,61 +1,188 @@
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_mkdir;
ssh_basename;
ssh_dirname;
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

@@ -27,14 +27,16 @@
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "config.h"
#ifdef _WIN32
#define _WIN32_IE 0x0400 //SHGetSpecialFolderPath
#define _WIN32_IE 0x0501 //SHGetSpecialFolderPath
#include <shlobj.h>
#include <winsock2.h>
#include <direct.h>
#else
#include <pwd.h>
#include <arpa/inet.h>
@@ -149,5 +151,137 @@ const char *ssh_version(int req_version) {
return NULL;
}
/**
* @brief Parse directory component.
*
* dirname breaks a null-terminated pathname string into a directory component.
* In the usual case, ssh_dirname() returns the string up to, but not including,
* the final '/'. Trailing '/' characters are not counted as part of the
* pathname. The caller must free the memory.
*
* @param path The path to parse.
*
* @return The dirname of path or NULL if we can't allocate memory. If path
* does not contain a slash, c_dirname() returns the string ".". If
* path is the string "/", it returns the string "/". If path is
* NULL or an empty string, "." is returned.
*/
char *ssh_dirname (const char *path) {
char *new = NULL;
unsigned int len;
if (path == NULL || *path == '\0') {
return strdup(".");
}
len = strlen(path);
/* Remove trailing slashes */
while(len > 0 && path[len - 1] == '/') --len;
/* We have only slashes */
if (len == 0) {
return strdup("/");
}
/* goto next slash */
while(len > 0 && path[len - 1] != '/') --len;
if (len == 0) {
return strdup(".");
} else if (len == 1) {
return strdup("/");
}
/* Remove slashes again */
while(len > 0 && path[len - 1] == '/') --len;
new = malloc(len + 1);
if (new == NULL) {
return NULL;
}
strncpy(new, path, len);
new[len] = '\0';
return new;
}
/**
* @brief basename - parse filename component.
*
* basename breaks a null-terminated pathname string into a filename component.
* ssh_basename() returns the component following the final '/'. Trailing '/'
* characters are not counted as part of the pathname.
*
* @param path The path to parse.
*
* @return The filename of path or NULL if we can't allocate memory. If path
* is a the string "/", basename returns the string "/". If path is
* NULL or an empty string, "." is returned.
*/
char *ssh_basename (const char *path) {
char *new = NULL;
const char *s;
unsigned int len;
if (path == NULL || *path == '\0') {
return strdup(".");
}
len = strlen(path);
/* Remove trailing slashes */
while(len > 0 && path[len - 1] == '/') --len;
/* We have only slashes */
if (len == 0) {
return strdup("/");
}
while(len > 0 && path[len - 1] != '/') --len;
if (len > 0) {
s = path + len;
len = strlen(s);
while(len > 0 && s[len - 1] == '/') --len;
} else {
return strdup(path);
}
new = malloc(len + 1);
if (new == NULL) {
return NULL;
}
strncpy(new, s, len);
new[len] = '\0';
return new;
}
/**
* @brief Attempts to create a directory with the given pathname.
*
* This is the portable version of mkdir, mode is ignored on Windows systems.
*
* @param pathname The path name to create the directory.
*
* @param mode The permissions to use.
*
* @return 0 on success, < 0 on error with errno set.
*/
int ssh_mkdir(const char *pathname, mode_t mode) {
int r;
#ifdef _WIN32
r = _mkdir(pathname);
#else
r = mkdir(pathname, mode);
#endif
return r;
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */

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);
}
@@ -502,7 +502,7 @@ error:
return rc; /* SSH_OK, AGAIN or ERROR */
}
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
static int packet_send1(SSH_SESSION *session) {
unsigned int blocksize = (session->current_crypto ?
session->current_crypto->out_cipher->blocksize : 8);
@@ -580,10 +580,10 @@ error:
return rc; /* SSH_OK, AGAIN or ERROR */
}
#endif /* HAVE_SSH1 */
#endif /* WITH_SSH1 */
int packet_send(SSH_SESSION *session) {
#ifdef HAVE_SSH1
#ifdef WITH_SSH1
if (session->version == 1) {
return packet_send1(session);
}
@@ -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;
}
@@ -424,7 +424,7 @@ static int dh_handshake_server(SSH_SESSION *session) {
buffer_add_ssh_string(session->out_buffer, f) < 0 ||
buffer_add_ssh_string(session->out_buffer, sign) < 0) {
ssh_set_error(session, SSH_FATAL, "Not enough space");
buffer_free(session->out_buffer);
buffer_reinit(session->out_buffer);
string_free(f);
string_free(sign);
return -1;
@@ -437,7 +437,7 @@ static int dh_handshake_server(SSH_SESSION *session) {
}
if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
buffer_free(session->out_buffer);
buffer_reinit(session->out_buffer);
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

@@ -99,6 +99,7 @@ void ssh_cleanup(SSH_SESSION *session) {
SAFE_FREE(session->banner);
buffer_free(session->in_buffer);
buffer_free(session->out_buffer);
session->in_buffer=session->out_buffer=NULL;
crypto_free(session->current_crypto);
crypto_free(session->next_crypto);
ssh_socket_free(session->socket);

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");
}
@@ -1776,7 +1777,11 @@ int sftp_seek64(SFTP_FILE *file, u64 new_offset) {
/* Report current byte position in file. */
unsigned long sftp_tell(SFTP_FILE *file) {
return file->offset;
return (unsigned long)file->offset;
}
/* Report current byte position in file. */
u64 sftp_tell64(SFTP_FILE *file) {
return (u64)file->offset;
}
/* Rewinds the position of the file pointer to the beginning of the file.*/
@@ -2211,6 +2216,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

@@ -901,7 +901,7 @@ int crypt_set_algorithms_server(SSH_SESSION *session){
/* out */
server = session->server_kex.methods[SSH_CRYPT_S_C];
client = session->client_kex.methods[SSH_CRYPT_S_C];
match = ssh_find_matching(client,server);
match = ssh_find_matching(client, server);
if(!match){
ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server : no matching algorithm function found for %s",server);
@@ -963,8 +963,8 @@ int crypt_set_algorithms_server(SSH_SESSION *session){
ssh_log(session,SSH_LOG_PACKET,"enabling C->S compression");
session->next_crypto->do_compress_in=1;
}
free(match);
SAFE_FREE(match);
client=session->client_kex.methods[SSH_CRYPT_S_C];
server=session->server_kex.methods[SSH_CRYPT_S_C];
match=ssh_find_matching(client,server);
@@ -972,22 +972,23 @@ int crypt_set_algorithms_server(SSH_SESSION *session){
ssh_log(session,SSH_LOG_PACKET,"enabling S->C compression\n");
session->next_crypto->do_compress_out=1;
}
free(match);
SAFE_FREE(match);
server=session->server_kex.methods[SSH_HOSTKEYS];
client=session->client_kex.methods[SSH_HOSTKEYS];
match=ssh_find_matching(client,server);
if(!strcmp(match,"ssh-dss"))
if(match && !strcmp(match,"ssh-dss"))
session->hostkeys=TYPE_DSS;
else if(!strcmp(match,"ssh-rsa"))
else if(match && !strcmp(match,"ssh-rsa"))
session->hostkeys=TYPE_RSA;
else {
ssh_set_error(session,SSH_FATAL,"cannot know what %s is into %s",match,server);
free(match);
ssh_set_error(session, SSH_FATAL, "Cannot know what %s is into %s",
match ? match : NULL, server);
SAFE_FREE(match);
leave_function();
return SSH_ERROR;
}
free(match);
SAFE_FREE(match);
leave_function();
return SSH_OK;
}

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);