mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-04 12:20:42 +09:00
Compare commits
56 Commits
08cbbea461
...
release-0-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82eb0427f7 | ||
|
|
7cd327a795 | ||
|
|
77a757c728 | ||
|
|
9ef0837c80 | ||
|
|
2f66b3be13 | ||
|
|
32d5293318 | ||
|
|
e0c969bb41 | ||
|
|
cecd5f0f78 | ||
|
|
9bef81c769 | ||
|
|
1093fb43ca | ||
|
|
add2aa5f45 | ||
|
|
26cdf0d994 | ||
|
|
3cf2c3639e | ||
|
|
a501d63c8a | ||
|
|
160053bc39 | ||
|
|
d672dde342 | ||
|
|
86f983962c | ||
|
|
b0d6307d41 | ||
|
|
10920fc678 | ||
|
|
c87b247e01 | ||
|
|
9abdc5ae2a | ||
|
|
e8e874909f | ||
|
|
74eff86a6b | ||
|
|
232aca8969 | ||
|
|
48deb0ca46 | ||
|
|
59889da5a5 | ||
|
|
a958f6498b | ||
|
|
3ec11b46e9 | ||
|
|
c17ce2697b | ||
|
|
7fa1804cf1 | ||
|
|
ad86a378d9 | ||
|
|
ed660c29c3 | ||
|
|
6f47401173 | ||
|
|
d247b86202 | ||
|
|
a1c7dd99be | ||
|
|
11a6ed907d | ||
|
|
a8ce546f69 | ||
|
|
6e56d1dfb2 | ||
|
|
b07ec7a3d1 | ||
|
|
09d4029ac1 | ||
|
|
b62d0732d2 | ||
|
|
90a6d431a7 | ||
|
|
f7448eeb1c | ||
|
|
d411260a68 | ||
|
|
f8f0663eb9 | ||
|
|
cedc635ed0 | ||
|
|
ff819489b7 | ||
|
|
37dc2a5279 | ||
|
|
50ebbe636e | ||
|
|
101bf21d41 | ||
|
|
ae3bb42da5 | ||
|
|
918a912cd5 | ||
|
|
7ba81b974e | ||
|
|
b5e868fb8b | ||
|
|
693c041ba9 | ||
|
|
39c7e3c7dd |
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
.*
|
||||
*.swp
|
||||
*~$
|
||||
build
|
||||
cscope.*
|
||||
tags
|
||||
@@ -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
|
||||
|
||||
@@ -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}")
|
||||
|
||||
|
||||
|
||||
36
ChangeLog
36
ChangeLog
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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){ \
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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: */
|
||||
|
||||
@@ -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 ?? ) */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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: */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
11
libssh/dh.c
11
libssh/dh.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
*;
|
||||
};
|
||||
|
||||
@@ -783,7 +783,9 @@ void ssh_message_free(SSH_MESSAGE *msg){
|
||||
SAFE_FREE(msg->channel_request.subsystem);
|
||||
break;
|
||||
}
|
||||
|
||||
ZERO_STRUCTP(msg);
|
||||
SAFE_FREE(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
134
libssh/misc.c
134
libssh/misc.c
@@ -27,6 +27,7 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "config.h"
|
||||
@@ -35,6 +36,7 @@
|
||||
#define _WIN32_IE 0x0400 //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: */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
/* This code is based on glib's gpoll */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/priv.h"
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
190
libssh/sftp.c
190
libssh/sftp.c
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
19
sample.c
19
sample.c
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user