mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-04 20:30:38 +09:00
Compare commits
41 Commits
release-0-
...
release-0-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
3873489688 | ||
|
|
d14a492019 | ||
|
|
848984f25f | ||
|
|
5a755a8219 | ||
|
|
910689126a | ||
|
|
87995db8fe | ||
|
|
70c9da4fb0 | ||
|
|
1ac654ec6c |
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.2")
|
||||
|
||||
set(APPLICATION_VERSION_MAJOR "0")
|
||||
set(APPLICATION_VERSION_MINOR "3")
|
||||
set(APPLICATION_VERSION_PATCH "0")
|
||||
set(APPLICATION_VERSION_PATCH "2")
|
||||
|
||||
set(LIBRARY_VERSION "3.0.0")
|
||||
set(LIBRARY_VERSION "3.2.0")
|
||||
set(LIBRARY_SOVERSION "3")
|
||||
|
||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||
|
||||
@@ -15,7 +15,7 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
|
||||
### versions
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "3")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "0")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "2")
|
||||
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||
|
||||
|
||||
|
||||
17
ChangeLog
17
ChangeLog
@@ -1,6 +1,23 @@
|
||||
ChangeLog
|
||||
==========
|
||||
|
||||
version 0.3.2 (released 2009-08-05)
|
||||
* Added ssh_init() function.
|
||||
* Added sftp_readlink() function.
|
||||
* Added sftp_symlink() function.
|
||||
* Fixed ssh_write_knownhost().
|
||||
* Fixed compilation on Solaris.
|
||||
* Fixed SSHv1 compilation.
|
||||
|
||||
version 0.3.1 (released 2009-07-14)
|
||||
* Added return code SSH_SERVER_FILE_NOT_FOUND.
|
||||
* Fixed compilation of SSHv1.
|
||||
* Fixed several memory leaks.
|
||||
* Fixed possible infinite loops.
|
||||
* Fixed a possible crash bug.
|
||||
* Fixed build warnings.
|
||||
* Fixed cmake on BSD.
|
||||
|
||||
version 0.3 (released 2009-05-21)
|
||||
* Added support for ssh-agent authentication.
|
||||
* Added POSIX like sftp implementation.
|
||||
|
||||
@@ -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
|
||||
)
|
||||
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
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}}")
|
||||
|
||||
string(REGEX REPLACE "[\r\n]" " " ${_lfs_CFLAGS} "${${_lfs_CFLAGS}}")
|
||||
add_definitions(${_lfs_CFLAGS})
|
||||
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
|
||||
add_definitions(${_lfs_CFLAGS})
|
||||
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)
|
||||
|
||||
7
debian/README.Debian
vendored
7
debian/README.Debian
vendored
@@ -1,7 +0,0 @@
|
||||
libssh for Debian
|
||||
----------------------
|
||||
|
||||
This is a package for the library libssh with the soname 2.
|
||||
There are some other projects which have nearly the same name, so be careful.
|
||||
|
||||
-- Laurent Bigonville <bigon@bigon.be> Fri, 27 Jul 2007 14:59:00 +0200
|
||||
55
debian/changelog
vendored
55
debian/changelog
vendored
@@ -1,55 +0,0 @@
|
||||
libssh (0.2+svn20070321-5) UNRELEASED; urgency=low
|
||||
|
||||
* NOT RELEASED YET
|
||||
* debian/control:
|
||||
- Use my debian.org address in Uploaders and takeover the package
|
||||
with Jean-Philippe permission
|
||||
- Use now official Vcs-* field
|
||||
- Use new Homepage field instead of old pseudo-field
|
||||
- Bump Standards-Version to 3.8.1 (no further changes)
|
||||
- Use debug section for -dbg package
|
||||
- Add ${misc:Depends} to please lintian
|
||||
* debian/libssh-2-doc.doc-base: Fix doc-base-uses-applications-section
|
||||
|
||||
-- Laurent Bigonville <bigon@debian.org> Thu, 08 Nov 2007 05:59:18 +0100
|
||||
|
||||
libssh (0.2+svn20070321-4) unstable; urgency=low
|
||||
|
||||
* debian/control:
|
||||
- Add XS-Vcs-Svn and XS-Vcs-Browser fields.
|
||||
- Change to ${binary:Version} for versionized dependencies.
|
||||
* Add debian/README.Debian to disambiguate the package name
|
||||
|
||||
-- Laurent Bigonville <bigon@bigon.be> Fri, 27 Jul 2007 15:00:06 +0200
|
||||
|
||||
libssh (0.2+svn20070321-3) unstable; urgency=low
|
||||
|
||||
* Fix wrong versionized Replaces for -doc package
|
||||
|
||||
-- Laurent Bigonville <bigon@bigon.be> Thu, 5 Apr 2007 17:58:27 +0200
|
||||
|
||||
libssh (0.2+svn20070321-2) unstable; urgency=low
|
||||
|
||||
* Split devel package into devel and documentation packages
|
||||
|
||||
-- Laurent Bigonville <bigon@bigon.be> Mon, 26 Mar 2007 15:29:51 +0200
|
||||
|
||||
libssh (0.2+svn20070321-1) unstable; urgency=low
|
||||
|
||||
* New svn snapshot:
|
||||
- Fix broken include in include/libssh/server.h (Closes: #410020)
|
||||
- Fix nasty bug in server side code
|
||||
|
||||
-- Laurent Bigonville <bigon@bigon.be> Mon, 26 Mar 2007 15:06:40 +0200
|
||||
|
||||
libssh (0.2-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Laurent Bigonville <bigon@bigon.be> Fri, 29 Dec 2006 07:40:20 +0100
|
||||
|
||||
libssh (0.2~rc-1) unstable; urgency=low
|
||||
|
||||
* Initial release (Closes: #316872)
|
||||
|
||||
-- Jean-Philippe Garcia Ballester <giga@le-pec.org> Wed, 20 Dec 2006 23:56:50 +0100
|
||||
1
debian/compat
vendored
1
debian/compat
vendored
@@ -1 +0,0 @@
|
||||
5
|
||||
65
debian/control
vendored
65
debian/control
vendored
@@ -1,65 +0,0 @@
|
||||
Source: libssh
|
||||
Section: libs
|
||||
Priority: optional
|
||||
Maintainer: Laurent Bigonville <bigon@debian.org>
|
||||
Build-Depends: cdbs, debhelper (>= 5), libgcrypt11-dev, libz-dev, doxygen
|
||||
Standards-Version: 3.8.1
|
||||
Vcs-Svn: svn://svn.berlios.de/libssh/trunk
|
||||
Vcs-Browser: http://svn.berlios.de/wsvn/libssh/trunk/
|
||||
Homepage: http://0xbadc0de.be/wiki/doku.php?id=libssh:libssh
|
||||
|
||||
Package: libssh-2
|
||||
Section: libs
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: A tiny C SSH library
|
||||
The ssh library was designed to be used by programmers needing a working SSH
|
||||
implementation by the mean of a library. The complete control of the client
|
||||
is made by the programmer. With libssh, you can remotely execute programs,
|
||||
transfer files, use a secure and transparent tunnel for your remote programs.
|
||||
With its SFTP implementation, you can play with remote files easily.
|
||||
|
||||
Package: libssh-2-dev
|
||||
Provides: libssh-dev
|
||||
Section: libdevel
|
||||
Architecture: any
|
||||
Depends: libssh-2 (= ${binary:Version}), ${misc:Depends}, libgcrypt11-dev, zlib1g-dev
|
||||
Suggests: libssh-2-doc
|
||||
Conflicts: libssh-dev
|
||||
Description: A tiny C SSH library. Development files
|
||||
The ssh library was designed to be used by programmers needing a working SSH
|
||||
implementation by the mean of a library. The complete control of the client
|
||||
is made by the programmer. With libssh, you can remotely execute programs,
|
||||
transfer files, use a secure and transparent tunnel for your remote programs.
|
||||
With its SFTP implementation, you can play with remote files easily.
|
||||
.
|
||||
This package contains development files.
|
||||
|
||||
Package: libssh-2-dbg
|
||||
Priority: extra
|
||||
Section: debug
|
||||
Architecture: any
|
||||
Depends: libssh-2 (= ${binary:Version}), ${misc:Depends}
|
||||
Description: A tiny C SSH library. Debug symbols
|
||||
The ssh library was designed to be used by programmers needing a working SSH
|
||||
implementation by the mean of a library. The complete control of the client
|
||||
is made by the programmer. With libssh, you can remotely execute programs,
|
||||
transfer files, use a secure and transparent tunnel for your remote programs.
|
||||
With its SFTP implementation, you can play with remote files easily.
|
||||
.
|
||||
This package contains debug symbols.
|
||||
|
||||
Package: libssh-2-doc
|
||||
Section: doc
|
||||
Architecture: all
|
||||
Suggests: doc-base
|
||||
Depends: ${misc:Depends}
|
||||
Replaces: libssh-2-dev (<< 0.2+svn20070321-2)
|
||||
Description: A tiny C SSH library. Documentation files
|
||||
The ssh library was designed to be used by programmers needing a working SSH
|
||||
implementation by the mean of a library. The complete control of the client
|
||||
is made by the programmer. With libssh, you can remotely execute programs,
|
||||
transfer files, use a secure and transparent tunnel for your remote programs.
|
||||
With its SFTP implementation, you can play with remote files easily.
|
||||
.
|
||||
This package contains documentation files.
|
||||
33
debian/copyright
vendored
33
debian/copyright
vendored
@@ -1,33 +0,0 @@
|
||||
This package was debianized by Laurent Bigonville <bigon@bigon.be> on
|
||||
Thu, 16 Nov 2006 20:34:01 +0100.
|
||||
|
||||
It was downloaded from http://www.0xbadc0de.be/
|
||||
|
||||
Upstream Author: Aris Adamantiadis (aka spacewalker) <aris@0xbadc0de.be>
|
||||
|
||||
Copyright: 2003 Aris Adamantiadis
|
||||
|
||||
License:
|
||||
|
||||
This package is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This package is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this package; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
On Debian systems, the complete text of the GNU Lesser General
|
||||
Public License can be found in `/usr/share/common-licenses/LGPL'.
|
||||
|
||||
|
||||
The Debian packaging is
|
||||
(C) 2005-2006, Jean-Philippe Garcia Ballester <giga@le-pec.org>,
|
||||
(C) 2006-2007, Laurent Bigonville <bigon@bigon.be> and
|
||||
is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
|
||||
2
debian/libssh-2-dev.install
vendored
2
debian/libssh-2-dev.install
vendored
@@ -1,2 +0,0 @@
|
||||
debian/tmp/usr/include/*
|
||||
debian/tmp/usr/lib/libssh.{a,la,so}
|
||||
9
debian/libssh-2-doc.doc-base
vendored
9
debian/libssh-2-doc.doc-base
vendored
@@ -1,9 +0,0 @@
|
||||
Document: libssh
|
||||
Title: Debian libssh Manual
|
||||
Author: Aris Adamantiadis <aris@0xbadc0de.be>
|
||||
Abstract: This manual describes libssh API.
|
||||
Section: Programming/C
|
||||
|
||||
Format: HTML
|
||||
Index: /usr/share/doc/libssh-2-doc/html/index.html
|
||||
Files: /usr/share/doc/libssh-2-doc/html/*
|
||||
1
debian/libssh-2-doc.docs
vendored
1
debian/libssh-2-doc.docs
vendored
@@ -1 +0,0 @@
|
||||
debian/tmp/usr/share/doc/libssh/html
|
||||
1
debian/libssh-2-doc.examples
vendored
1
debian/libssh-2-doc.examples
vendored
@@ -1 +0,0 @@
|
||||
debian/tmp/usr/share/doc/libssh/examples/*
|
||||
1
debian/libssh-2-doc.manpages
vendored
1
debian/libssh-2-doc.manpages
vendored
@@ -1 +0,0 @@
|
||||
doxygen/man/man3/ssh_*
|
||||
1
debian/libssh-2.install
vendored
1
debian/libssh-2.install
vendored
@@ -1 +0,0 @@
|
||||
debian/tmp/usr/lib/libssh.so.*
|
||||
2
debian/libssh-2.lintian-overrides
vendored
2
debian/libssh-2.lintian-overrides
vendored
@@ -1,2 +0,0 @@
|
||||
# We use libssh-2 name to avoid name clash with libssh2 package.
|
||||
libssh-2: package-name-doesnt-match-sonames libssh2
|
||||
21
debian/rules
vendored
21
debian/rules
vendored
@@ -1,21 +0,0 @@
|
||||
#!/usr/bin/make -f
|
||||
# Sample debian/rules that uses cdbs. Originaly written by Robert Millan.
|
||||
# This file is public domain.
|
||||
|
||||
DEB_AUTO_CLEANUP_RCS := yes
|
||||
|
||||
# Add here any variable or target overrides you need
|
||||
|
||||
|
||||
include /usr/share/cdbs/1/class/autotools.mk
|
||||
include /usr/share/cdbs/1/rules/debhelper.mk
|
||||
#include /usr/share/cdbs/1/rules/simple-patchsys.mk
|
||||
|
||||
DEB_CONFIGURE_EXTRA_FLAGS = --with-libgcrypt --enable-ssh1
|
||||
DEB_DBG_PACKAGE_libssh-2 = libssh-2-dbg
|
||||
|
||||
install/libssh-2::
|
||||
install -D -m 644 debian/libssh-2.lintian-overrides debian/libssh-2/usr/share/lintian/overrides/libssh-2
|
||||
|
||||
install/libssh-2-doc::
|
||||
make install-doc DESTDIR=debian/tmp
|
||||
2
debian/watch
vendored
2
debian/watch
vendored
@@ -1,2 +0,0 @@
|
||||
version=3
|
||||
http://0xbadc0de.be/libssh/libssh-(.*)\.tgz
|
||||
@@ -51,7 +51,7 @@ typedef unsigned long long uint64_t;
|
||||
/* libssh version */
|
||||
#define LIBSSH_VERSION_MAJOR 0
|
||||
#define LIBSSH_VERSION_MINOR 3
|
||||
#define LIBSSH_VERSION_MICRO 0
|
||||
#define LIBSSH_VERSION_MICRO 1
|
||||
|
||||
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
||||
LIBSSH_VERSION_MINOR, \
|
||||
@@ -80,7 +80,6 @@ typedef struct channel_struct CHANNEL;
|
||||
typedef struct agent_struct AGENT;
|
||||
typedef struct ssh_session SSH_SESSION;
|
||||
typedef struct ssh_kbdint SSH_KBDINT;
|
||||
struct keys_struct;
|
||||
|
||||
/* integer values */
|
||||
typedef uint32_t u32;
|
||||
@@ -134,6 +133,7 @@ typedef int socket_t;
|
||||
#define SSH_SERVER_KNOWN_OK 1
|
||||
#define SSH_SERVER_KNOWN_CHANGED 2
|
||||
#define SSH_SERVER_FOUND_OTHER 3
|
||||
#define SSH_SERVER_FILE_NOT_FOUND 4
|
||||
|
||||
#ifndef MD5_DIGEST_LEN
|
||||
#define MD5_DIGEST_LEN 16
|
||||
@@ -210,6 +210,7 @@ int ssh_connect(SSH_SESSION *session);
|
||||
void ssh_disconnect(SSH_SESSION *session);
|
||||
int ssh_service_request(SSH_SESSION *session, const char *service);
|
||||
char *ssh_get_issue_banner(SSH_SESSION *session);
|
||||
int ssh_get_openssh_version(SSH_SESSION *session);
|
||||
/* get copyright informations */
|
||||
const char *ssh_copyright(void);
|
||||
|
||||
@@ -256,9 +257,6 @@ PUBLIC_KEY *publickey_from_privatekey(PRIVATE_KEY *prv);
|
||||
void privatekey_free(PRIVATE_KEY *prv);
|
||||
STRING *publickey_from_file(SSH_SESSION *session, const char *filename,
|
||||
int *type);
|
||||
STRING *try_publickey_from_file(SSH_SESSION *session,
|
||||
struct keys_struct keytab,
|
||||
char **privkeyfile, int *type);
|
||||
int ssh_is_server_known(SSH_SESSION *session);
|
||||
int ssh_write_knownhost(SSH_SESSION *session);
|
||||
|
||||
@@ -369,14 +367,15 @@ int ssh_userauth_agent_pubkey(SSH_SESSION *session, const char *username,
|
||||
int ssh_userauth_autopubkey(SSH_SESSION *session, const char *passphrase);
|
||||
int ssh_userauth_kbdint(SSH_SESSION *session, const char *user, const char *submethods);
|
||||
int ssh_userauth_kbdint_getnprompts(SSH_SESSION *session);
|
||||
char *ssh_userauth_kbdint_getname(SSH_SESSION *session);
|
||||
char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session);
|
||||
char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session, unsigned int i, char *echo);
|
||||
const char *ssh_userauth_kbdint_getname(SSH_SESSION *session);
|
||||
const char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session);
|
||||
const char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session, unsigned int i, char *echo);
|
||||
int ssh_userauth_kbdint_setanswer(SSH_SESSION *session, unsigned int i,
|
||||
const char *answer);
|
||||
|
||||
|
||||
/* init.c */
|
||||
int ssh_init(void);
|
||||
int ssh_finalize(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -133,6 +133,28 @@ typedef BN_CTX* bignum_CTX;
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* poll support */
|
||||
#ifdef HAVE_POLL
|
||||
#include <poll.h>
|
||||
typedef struct pollfd pollfd_t;
|
||||
#else /* HAVE_POLL */
|
||||
typedef struct pollfd_s {
|
||||
socket_t fd; /* file descriptor */
|
||||
short events; /* requested events */
|
||||
short revents; /* returned events */
|
||||
} pollfd_t;
|
||||
|
||||
#define POLLIN 0x001 /* There is data to read. */
|
||||
#define POLLPRI 0x002 /* There is urgent data to read. */
|
||||
#define POLLOUT 0x004 /* Writing now will not block. */
|
||||
|
||||
#define POLLERR 0x008 /* Error condition. */
|
||||
#define POLLHUP 0x010 /* Hung up. */
|
||||
#define POLLNVAL 0x020 /* Invalid polling request. */
|
||||
|
||||
typedef unsigned long int nfds_t;
|
||||
#endif /* HAVE_POLL */
|
||||
|
||||
/* wrapper.c */
|
||||
MD5CTX md5_init(void);
|
||||
void md5_update(MD5CTX c, const void *data, unsigned long len);
|
||||
@@ -152,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
|
||||
*/
|
||||
@@ -311,6 +337,7 @@ struct ssh_session {
|
||||
int protoversion;
|
||||
int server;
|
||||
int client;
|
||||
int openssh;
|
||||
u32 send_seq;
|
||||
u32 recv_seq;
|
||||
/* status flags */
|
||||
@@ -474,6 +501,9 @@ STRING *agent_sign_data(struct ssh_session *session,
|
||||
struct public_key_struct *pubkey);
|
||||
#endif
|
||||
|
||||
/* poll.c */
|
||||
int ssh_poll(pollfd_t *fds, nfds_t nfds, int timeout);
|
||||
|
||||
/* socket.c */
|
||||
|
||||
struct socket;
|
||||
@@ -578,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);
|
||||
@@ -694,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){ \
|
||||
|
||||
@@ -592,6 +592,30 @@ int sftp_chmod(SFTP_SESSION *sftp, const char *file, mode_t mode);
|
||||
*/
|
||||
int sftp_utimes(SFTP_SESSION *sftp, const char *file, const struct timeval *times);
|
||||
|
||||
/**
|
||||
* @brief Create a symbolic link.
|
||||
*
|
||||
* @param sftp The sftp session handle.
|
||||
*
|
||||
* @param target Specifies the target of the symlink.
|
||||
*
|
||||
* @param dest Specifies the path name of the symlink to be created.
|
||||
*
|
||||
* @return 0 on success, < 0 on error with ssh and sftp error set.
|
||||
*/
|
||||
int sftp_symlink(SFTP_SESSION *sftp, const char *target, const char *dest);
|
||||
|
||||
/**
|
||||
* @brief Read the value of a symbolic link.
|
||||
*
|
||||
* @param sftp The sftp session handle.
|
||||
*
|
||||
* @param path Specifies the path name of the symlink to be read.
|
||||
*
|
||||
* @return The target of the link, NULL on error.
|
||||
*/
|
||||
char *sftp_readlink(SFTP_SESSION *sftp, const char *path);
|
||||
|
||||
/**
|
||||
* @brief Canonicalize a sftp path.
|
||||
*
|
||||
|
||||
@@ -84,6 +84,7 @@ set(libssh_SRCS
|
||||
misc.c
|
||||
options.c
|
||||
packet.c
|
||||
poll.c
|
||||
session.c
|
||||
socket.c
|
||||
string.c
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/agent.h"
|
||||
#include "libssh/priv.h"
|
||||
|
||||
|
||||
@@ -22,12 +22,17 @@
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/ssh2.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/ssh2.h"
|
||||
|
||||
/** \defgroup ssh_auth SSH Authentication functions
|
||||
* \brief functions to authenticate to servers
|
||||
*/
|
||||
@@ -203,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();
|
||||
@@ -309,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();
|
||||
@@ -666,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();
|
||||
@@ -1070,10 +1075,10 @@ static void kbdint_clean(struct ssh_kbdint *kbd) {
|
||||
* of the draft */
|
||||
static int kbdauth_init(SSH_SESSION *session, const char *user,
|
||||
const char *submethods) {
|
||||
STRING *usr;
|
||||
STRING *sub;
|
||||
STRING *service;
|
||||
STRING *method;
|
||||
STRING *usr = NULL;
|
||||
STRING *sub = NULL;
|
||||
STRING *service = NULL;
|
||||
STRING *method = NULL;
|
||||
int rc = SSH_AUTH_ERROR;
|
||||
|
||||
enter_function();
|
||||
@@ -1412,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;
|
||||
}
|
||||
|
||||
@@ -1427,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;
|
||||
}
|
||||
|
||||
@@ -1447,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;
|
||||
@@ -1470,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: */
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/priv.h"
|
||||
|
||||
/** \defgroup ssh_buffer SSH Buffers
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/ssh2.h"
|
||||
|
||||
@@ -311,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);
|
||||
@@ -409,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;
|
||||
}
|
||||
@@ -431,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;
|
||||
}
|
||||
@@ -473,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;
|
||||
}
|
||||
@@ -637,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);
|
||||
}
|
||||
@@ -881,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();
|
||||
@@ -900,7 +904,10 @@ int channel_write(CHANNEL *channel, const void *data, u32 len) {
|
||||
/* What happens when the channel window is zero? */
|
||||
while(channel->remote_window == 0) {
|
||||
/* parse every incoming packet */
|
||||
packet_wait(channel->session, 0, 0);
|
||||
if (packet_wait(channel->session, 0, 0) == SSH_ERROR) {
|
||||
leave_function();
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
effectivelen = len > channel->remote_window ? channel->remote_window : len;
|
||||
} else {
|
||||
@@ -1081,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();
|
||||
@@ -1150,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();
|
||||
@@ -1186,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);
|
||||
}
|
||||
@@ -1305,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);
|
||||
}
|
||||
|
||||
@@ -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: */
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/ssh2.h"
|
||||
|
||||
@@ -93,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);
|
||||
@@ -124,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;
|
||||
}
|
||||
|
||||
@@ -216,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) {
|
||||
@@ -256,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");
|
||||
@@ -327,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 */
|
||||
@@ -359,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;
|
||||
@@ -462,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();
|
||||
@@ -605,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).
|
||||
*
|
||||
@@ -613,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;
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_CRYPTO
|
||||
#include <openssl/blowfish.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/crypto.h"
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -25,6 +25,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/ssh2.h"
|
||||
|
||||
@@ -29,6 +29,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/priv.h"
|
||||
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
@@ -1275,9 +1280,9 @@ static int match_hashed_host(SSH_SESSION *session, const char *host,
|
||||
leave_function();
|
||||
return 0;
|
||||
}
|
||||
SAFE_FREE(source);
|
||||
|
||||
hash = base64_to_bin(b64hash);
|
||||
SAFE_FREE(source);
|
||||
if (hash == NULL) {
|
||||
buffer_free(salt);
|
||||
leave_function();
|
||||
@@ -1337,6 +1342,9 @@ static int match_hashed_host(SSH_SESSION *session, const char *host,
|
||||
* possible attack \n
|
||||
* SSH_SERVER_NOT_KNOWN: The server is unknown. User should confirm
|
||||
* the MD5 is correct\n
|
||||
* SSH_SERVER_FILE_NOT_FOUND:The known host file does not exist. The
|
||||
* host is thus unknown. File will be created
|
||||
* if host key is accepted\n
|
||||
* SSH_SERVER_ERROR: Some error happened
|
||||
*
|
||||
* \see ssh_options_set_wanted_algo()
|
||||
@@ -1356,10 +1364,10 @@ int ssh_is_server_known(SSH_SESSION *session) {
|
||||
enter_function();
|
||||
|
||||
if (ssh_options_default_known_hosts_file(session->options) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Can't find a known_hosts file");
|
||||
leave_function();
|
||||
return SSH_SERVER_ERROR;
|
||||
return SSH_SERVER_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (session->options->host == NULL) {
|
||||
@@ -1413,6 +1421,8 @@ int ssh_is_server_known(SSH_SESSION *session) {
|
||||
/* We override the status with the wrong key state */
|
||||
ret = SSH_SERVER_KNOWN_CHANGED;
|
||||
}
|
||||
} else {
|
||||
tokens_free(tokens);
|
||||
}
|
||||
} while (1);
|
||||
|
||||
@@ -1427,7 +1437,7 @@ int ssh_is_server_known(SSH_SESSION *session) {
|
||||
}
|
||||
|
||||
/** You generaly use it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN
|
||||
* \brief write the current server as known in the known hosts file
|
||||
* \brief write the current server as known in the known hosts file. This will create the known hosts file if it does not exist.
|
||||
* \param session ssh session
|
||||
* \return 0 on success, -1 on error
|
||||
*/
|
||||
@@ -1566,7 +1576,7 @@ int ssh_write_knownhost(SSH_SESSION *session) {
|
||||
}
|
||||
|
||||
len = strlen(buffer);
|
||||
if (fwrite(buffer, len, 1, file) != len || ferror(file)) {
|
||||
if (fwrite(buffer, len, 1, file) != 1 || ferror(file)) {
|
||||
fclose(file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,61 +1,185 @@
|
||||
SSH_0.3 {
|
||||
global:
|
||||
ssh_get_error; ssh_get_error_code;
|
||||
ssh_new; ssh_set_options; ssh_get_fd; ssh_silent_disconnect;
|
||||
ssh_connect; ssh_disconnect; ssh_service_request; ssh_get_issue_banner;
|
||||
ssh_copyright; ssh_get_version; ssh_finalize;
|
||||
ssh_set_fd_toread; ssh_set_fd_towrite; ssh_set_fd_except;
|
||||
string_from_char; string_len; string_new; string_fill; string_to_char;
|
||||
string_copy; string_burn; string_data;
|
||||
ssh_crypto_init;
|
||||
ssh_get_hexa; ssh_print_hexa; ssh_get_random;
|
||||
ssh_get_pubkey_hash; ssh_get_pubkey;
|
||||
ssh_fd_poll; ssh_select; publickey_free;
|
||||
privatekey_from_file; publickey_to_string; publickey_from_privatekey;
|
||||
private_key_free; publickey_from_file; try_publickey_from_file;
|
||||
ssh_is_server_known; ssh_write_knownhost;
|
||||
channel_new; channel_open_forward; channel_open_session; channel_free;
|
||||
channel_request_pty; channel_request_pty_size; channel_change_pty_size;
|
||||
channel_request_shell; channel_request_subsystem; channel_request_env;
|
||||
channel_request_exec; channel_request_sftp; channel_write;
|
||||
channel_send_eof; channel_read_buffer; channel_read; channel_read_nonblocking;
|
||||
channel_poll; channel_close; channel_is_open;
|
||||
channel_is_closed; channel_is_eof; channel_select;
|
||||
ssh_options_new; ssh_options_copy; ssh_options_free; ssh_options_set_wanted_algos;
|
||||
ssh_options_set_username; ssh_options_set_port; ssh_options_getopt;
|
||||
ssh_options_set_host; ssh_options_set_fd; ssh_options_set_bind;
|
||||
ssh_options_set_identity; ssh_options_set_status_callback;
|
||||
ssh_options_set_timeout; ssh_options_set_ssh_dir;
|
||||
ssh_options_set_known_hosts_file; ssh_options_allow_ssh1;
|
||||
ssh_options_allow_ssh2; ssh_options_set_dsa_server_key;
|
||||
ssh_options_set_rsa_server_key;
|
||||
buffer_new; buffer_free; buffer_get; buffer_get_len;
|
||||
ssh_userauth_none; ssh_userauth_password; ssh_userauth_offer_pubkey;
|
||||
ssh_userauth_pubkey; ssh_userauth_autopubkey; ssh_userauth_kbdint;
|
||||
ssh_userauth_kbdint_getnprompts; ssh_userauth_kbdint_getname;
|
||||
ssh_userauth_kbdint_getinstruction; ssh_userauth_kbdint_getprompt;
|
||||
ssh_userauth_kbdint_setanswer;
|
||||
sftp_new; sftp_free; sftp_init; sftp_opendir; sftp_readdir; sftp_dir_eof;
|
||||
sftp_stat; sftp_lstat; sftp_fstat; sftp_attributes_free; sftp_dir_close;
|
||||
sftp_file_close; sftp_open; sftp_read; sftp_write; sftp_seek; sftp_tell;
|
||||
sftp_rewind; sftp_rm; sftp_rmdir; sftp_mkdir; sftp_rename; sftp_setstat;
|
||||
sftp_canonicalize_path; sftp_server_new; sftp_server_init;
|
||||
sftp_get_client_message; sftp_client_message_free; sftp_reply_name;
|
||||
sftp_reply_handle; sftp_handle_alloc; sftp_reply_attr; sftp_handle;
|
||||
sftp_reply_status; sftp_reply_names_add; sftp_reply_names;
|
||||
sftp_reply_data; sftp_handle_remove;
|
||||
ssh_bind_new; ssh_bind_set_options; ssh_bind_listen; ssh_bind_set_blocking;
|
||||
ssh_bind_get_fd; ssh_bind_set_toaccept; ssh_bind_accept; ssh_bind_free;
|
||||
buffer_free;
|
||||
buffer_get;
|
||||
buffer_get_len;
|
||||
buffer_new;
|
||||
channel_change_pty_size;
|
||||
channel_close;
|
||||
channel_free;
|
||||
channel_get_exit_status;
|
||||
channel_get_session;
|
||||
channel_is_closed;
|
||||
channel_is_eof;
|
||||
channel_is_open;
|
||||
channel_new;
|
||||
channel_open_forward;
|
||||
channel_open_session;
|
||||
channel_poll;
|
||||
channel_read;
|
||||
channel_read_buffer;
|
||||
channel_read_nonblocking;
|
||||
channel_request_env;
|
||||
channel_request_exec;
|
||||
channel_request_pty;
|
||||
channel_request_pty_size;
|
||||
channel_request_sftp;
|
||||
channel_request_shell;
|
||||
channel_request_subsystem;
|
||||
channel_select;
|
||||
channel_send_eof;
|
||||
channel_set_blocking;
|
||||
channel_write;
|
||||
privatekey_free;
|
||||
privatekey_from_file;
|
||||
publickey_free;
|
||||
publickey_from_file;
|
||||
publickey_from_privatekey;
|
||||
publickey_to_string;
|
||||
sftp_async_read;
|
||||
sftp_async_read_begin;
|
||||
sftp_attributes_free;
|
||||
sftp_canonicalize_path;
|
||||
sftp_chmod;
|
||||
sftp_chown;
|
||||
sftp_close;
|
||||
sftp_closedir;
|
||||
sftp_dir_eof;
|
||||
sftp_file_set_blocking;
|
||||
sftp_file_set_nonblocking;
|
||||
sftp_free;
|
||||
sftp_fstat;
|
||||
sftp_get_error;
|
||||
sftp_init;
|
||||
sftp_lstat;
|
||||
sftp_mkdir;
|
||||
sftp_new;
|
||||
sftp_open;
|
||||
sftp_opendir;
|
||||
sftp_read;
|
||||
sftp_readdir;
|
||||
sftp_readlink;
|
||||
sftp_rename;
|
||||
sftp_rewind;
|
||||
sftp_rmdir;
|
||||
sftp_seek;
|
||||
sftp_seek64;
|
||||
sftp_server_init;
|
||||
sftp_server_new;
|
||||
sftp_server_version;
|
||||
sftp_setstat;
|
||||
sftp_stat;
|
||||
sftp_symlink;
|
||||
sftp_tell;
|
||||
sftp_tell64;
|
||||
sftp_unlink;
|
||||
sftp_utimes;
|
||||
sftp_write;
|
||||
ssh_accept;
|
||||
ssh_message_get; ssh_message_type; ssh_message_subtype;
|
||||
ssh_message_reply_default; ssh_message_free; ssh_message_auth_user;
|
||||
ssh_message_auth_password; ssh_message_auth_reply_success;
|
||||
ssh_auth_list;
|
||||
ssh_bind_accept;
|
||||
ssh_bind_fd_toaccept;
|
||||
ssh_bind_free;
|
||||
ssh_bind_get_fd;
|
||||
ssh_bind_listen;
|
||||
ssh_bind_new;
|
||||
ssh_bind_set_blocking;
|
||||
ssh_bind_set_fd;
|
||||
ssh_bind_set_options;
|
||||
ssh_clean_pubkey_hash;
|
||||
ssh_connect;
|
||||
ssh_copyright;
|
||||
ssh_disconnect;
|
||||
ssh_fd_poll;
|
||||
ssh_finalize;
|
||||
ssh_get_disconnect_message;
|
||||
ssh_get_error;
|
||||
ssh_get_error_code;
|
||||
ssh_get_fd;
|
||||
ssh_get_hexa;
|
||||
ssh_get_issue_banner;
|
||||
ssh_get_openssh_version;
|
||||
ssh_get_pubkey;
|
||||
ssh_get_pubkey_hash;
|
||||
ssh_get_random;
|
||||
ssh_get_status;
|
||||
ssh_get_version;
|
||||
ssh_init;
|
||||
ssh_is_server_known;
|
||||
ssh_log;
|
||||
ssh_message_auth_password;
|
||||
ssh_message_auth_publickey;
|
||||
ssh_message_auth_reply_pk_ok;
|
||||
ssh_message_auth_reply_success;
|
||||
ssh_message_auth_set_methods;
|
||||
ssh_message_auth_user;
|
||||
ssh_message_channel_request_open_reply_accept;
|
||||
ssh_message_channel_request_channel; ssh_message_channel_request_pty_term;
|
||||
ssh_message_channel_request_subsystem;
|
||||
ssh_message_channel_request_reply_success;
|
||||
set_encrypt_key; set_decrypt_key; cbc_encrypt; cbc_decrypt;
|
||||
ssh_message_free;
|
||||
ssh_message_get;
|
||||
ssh_message_reply_default;
|
||||
ssh_message_retrieve;
|
||||
ssh_message_service_reply_success;
|
||||
ssh_message_service_service;
|
||||
ssh_message_subtype;
|
||||
ssh_message_type;
|
||||
ssh_new;
|
||||
ssh_options_allow_ssh1;
|
||||
ssh_options_allow_ssh2;
|
||||
ssh_options_copy;
|
||||
ssh_options_free;
|
||||
ssh_options_getopt;
|
||||
ssh_options_new;
|
||||
ssh_options_set_auth_callback;
|
||||
ssh_options_set_banner;
|
||||
ssh_options_set_bind;
|
||||
ssh_options_set_dsa_server_key;
|
||||
ssh_options_set_fd;
|
||||
ssh_options_set_host;
|
||||
ssh_options_set_identity;
|
||||
ssh_options_set_known_hosts_file;
|
||||
ssh_options_set_log_function;
|
||||
ssh_options_set_log_verbosity;
|
||||
ssh_options_set_port;
|
||||
ssh_options_set_rsa_server_key;
|
||||
ssh_options_set_ssh_dir;
|
||||
ssh_options_set_status_callback;
|
||||
ssh_options_set_timeout;
|
||||
ssh_options_set_username;
|
||||
ssh_options_set_wanted_algos;
|
||||
ssh_print_hexa;
|
||||
ssh_select;
|
||||
ssh_service_request;
|
||||
ssh_set_blocking;
|
||||
ssh_set_fd_except;
|
||||
ssh_set_fd_toread;
|
||||
ssh_set_fd_towrite;
|
||||
ssh_set_options;
|
||||
ssh_silent_disconnect;
|
||||
ssh_userauth_agent_pubkey;
|
||||
ssh_userauth_autopubkey;
|
||||
ssh_userauth_kbdint;
|
||||
ssh_userauth_kbdint_getinstruction;
|
||||
ssh_userauth_kbdint_getname;
|
||||
ssh_userauth_kbdint_getnprompts;
|
||||
ssh_userauth_kbdint_getprompt;
|
||||
ssh_userauth_kbdint_setanswer;
|
||||
ssh_userauth_list;
|
||||
ssh_userauth_none;
|
||||
ssh_userauth_offer_pubkey;
|
||||
ssh_userauth_password;
|
||||
ssh_userauth_pubkey;
|
||||
ssh_version;
|
||||
ssh_write_knownhost;
|
||||
string_burn;
|
||||
string_copy;
|
||||
string_data;
|
||||
string_fill;
|
||||
string_free;
|
||||
string_from_char;
|
||||
string_len;
|
||||
string_new;
|
||||
string_to_char;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
@@ -34,6 +34,11 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/server.h"
|
||||
@@ -778,7 +783,9 @@ void ssh_message_free(SSH_MESSAGE *msg){
|
||||
SAFE_FREE(msg->channel_request.subsystem);
|
||||
break;
|
||||
}
|
||||
|
||||
ZERO_STRUCTP(msg);
|
||||
SAFE_FREE(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <pwd.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/priv.h"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/ssh2.h"
|
||||
@@ -210,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;
|
||||
@@ -359,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);
|
||||
}
|
||||
@@ -534,7 +538,7 @@ static int packet_send1(SSH_SESSION *session) {
|
||||
"%d bytes after comp + %d padding bytes = %d bytes packet",
|
||||
currentlen, padding, ntohl(finallen));
|
||||
|
||||
if (buffer_prepend_data(session->out_buffer,i &padstring, padding) < 0) {
|
||||
if (buffer_prepend_data(session->out_buffer, &padstring, padding) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (buffer_prepend_data(session->out_buffer, &finallen, sizeof(u32)) < 0) {
|
||||
@@ -576,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
|
||||
@@ -593,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) {
|
||||
@@ -607,7 +611,7 @@ void packet_parse(SSH_SESSION *session) {
|
||||
case SSH_SMSG_STDOUT_DATA:
|
||||
case SSH_SMSG_STDERR_DATA:
|
||||
case SSH_SMSG_EXITSTATUS:
|
||||
channel_handle1(session,type)
|
||||
channel_handle1(session,type);
|
||||
return;
|
||||
case SSH_MSG_DEBUG:
|
||||
case SSH_MSG_IGNORE:
|
||||
@@ -618,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);
|
||||
@@ -654,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();
|
||||
@@ -715,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;
|
||||
@@ -769,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);
|
||||
}
|
||||
|
||||
206
libssh/poll.c
Normal file
206
libssh/poll.c
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* poll.c - poll wrapper
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2003-2008 by Aris Adamantiadis
|
||||
*
|
||||
* The SSH Library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* The SSH Library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
* vim: ts=2 sw=2 et cindent
|
||||
*/
|
||||
|
||||
/* This code is based on glib's gpoll */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/priv.h"
|
||||
|
||||
#ifdef HAVE_POLL
|
||||
#include <poll.h>
|
||||
|
||||
int ssh_poll(pollfd_t *fds, nfds_t nfds, int timeout) {
|
||||
return poll((struct pollfd *) fds, nfds, timeout);
|
||||
}
|
||||
|
||||
#else /* HAVE_POLL */
|
||||
#ifdef _WIN32
|
||||
|
||||
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
|
||||
|
||||
#include <winsock2.h>
|
||||
|
||||
int ssh_poll(pollfd_t *fds, nfds_t nfds, int timeout) {
|
||||
return WSAPoll(fds, nfds, timeout);
|
||||
}
|
||||
|
||||
#else /* _WIN32_WINNT */
|
||||
|
||||
#ifndef STRICT
|
||||
#define STRICT
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
static int poll_rest (HANDLE *handles, int nhandles,
|
||||
pollfd_t *fds, nfds_t nfds, int timeout) {
|
||||
DWORD ready;
|
||||
pollfd_t *f;
|
||||
int recursed_result;
|
||||
|
||||
if (nhandles == 0) {
|
||||
/* No handles to wait for, just the timeout */
|
||||
if (timeout == INFINITE) {
|
||||
ready = WAIT_FAILED;
|
||||
} else {
|
||||
SleepEx(timeout, 1);
|
||||
ready = WAIT_TIMEOUT;
|
||||
}
|
||||
} else {
|
||||
/* Wait for just handles */
|
||||
ready = WaitForMultipleObjectsEx(nhandles, handles, FALSE, timeout, TRUE);
|
||||
#if 0
|
||||
if (ready == WAIT_FAILED) {
|
||||
fprintf(stderr, "WaitForMultipleObjectsEx failed: %d\n", GetLastError());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ready == WAIT_FAILED) {
|
||||
return -1;
|
||||
} else if (ready == WAIT_TIMEOUT || ready == WAIT_IO_COMPLETION) {
|
||||
return 0;
|
||||
} else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles) {
|
||||
for (f = fds; f < &fds[nfds]; f++) {
|
||||
if ((HANDLE) f->fd == handles[ready - WAIT_OBJECT_0]) {
|
||||
f->revents = f->events;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If no timeout and polling several handles, recurse to poll
|
||||
* the rest of them.
|
||||
*/
|
||||
if (timeout == 0 && nhandles > 1) {
|
||||
/* Remove the handle that fired */
|
||||
int i;
|
||||
if (ready < nhandles - 1) {
|
||||
for (i = ready - WAIT_OBJECT_0 + 1; i < nhandles; i++) {
|
||||
handles[i-1] = handles[i];
|
||||
}
|
||||
}
|
||||
nhandles--;
|
||||
recursed_result = poll_rest(handles, nhandles, fds, nfds, 0);
|
||||
if (recursed_result < 0) {
|
||||
return -1;
|
||||
}
|
||||
return recursed_result + 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ssh_poll(pollfd_t *fds, nfds_t nfds, int timeout) {
|
||||
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
|
||||
pollfd_t *f;
|
||||
int nhandles = 0;
|
||||
int rc = -1;
|
||||
|
||||
if (fds == NULL) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nfds >= MAXIMUM_WAIT_OBJECTS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (f = fds; f < &fds[nfds]; f++) {
|
||||
if (f->fd > 0) {
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Don't add the same handle several times into the array, as
|
||||
* docs say that is not allowed, even if it actually does seem
|
||||
* to work.
|
||||
*/
|
||||
for (i = 0; i < nhandles; i++) {
|
||||
if (handles[i] == (HANDLE) f->fd) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == nhandles) {
|
||||
if (nhandles == MAXIMUM_WAIT_OBJECTS) {
|
||||
break;
|
||||
} else {
|
||||
handles[nhandles++] = (HANDLE) f->fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (timeout == -1) {
|
||||
timeout = INFINITE;
|
||||
}
|
||||
|
||||
if (nhandles > 1) {
|
||||
/*
|
||||
* First check if one or several of them are immediately
|
||||
* available.
|
||||
*/
|
||||
rc = poll_rest(handles, nhandles, fds, nfds, 0);
|
||||
|
||||
/*
|
||||
* If not, and we have a significant timeout, poll again with
|
||||
* timeout then. Note that this will return indication for only
|
||||
* one event, or only for messages. We ignore timeouts less than
|
||||
* ten milliseconds as they are mostly pointless on Windows, the
|
||||
* MsgWaitForMultipleObjectsEx() call will timeout right away
|
||||
* anyway.
|
||||
*/
|
||||
if (rc == 0 && (timeout == INFINITE || timeout >= 10)) {
|
||||
rc = poll_rest(handles, nhandles, fds, nfds, timeout);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Just polling for one thing, so no need to check first if
|
||||
* available immediately
|
||||
*/
|
||||
rc = poll_rest(handles, nhandles, fds, nfds, timeout);
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
for (f = fds; f < &fds[nfds]; f++) {
|
||||
f->revents = 0;
|
||||
}
|
||||
errno = EBADF;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif /* _WIN32_WINNT */
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#endif /* HAVE_POLL */
|
||||
|
||||
@@ -135,7 +135,7 @@ int ssh_bind_listen(SSH_BIND *ssh_bind) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ssh_socket_init() < 0) {
|
||||
if (ssh_init() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -479,10 +479,6 @@ int ssh_accept(SSH_SESSION *session) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ssh_crypto_init() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
session->alive = 1;
|
||||
|
||||
session->clientbanner = ssh_get_banner(session);
|
||||
|
||||
188
libssh/sftp.c
188
libssh/sftp.c
@@ -31,6 +31,10 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/ssh2.h"
|
||||
#include "libssh/sftp.h"
|
||||
@@ -1677,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) {
|
||||
@@ -1700,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");
|
||||
}
|
||||
@@ -2207,6 +2212,185 @@ int sftp_utimes(SFTP_SESSION *sftp, const char *file,
|
||||
return sftp_setstat(sftp, file, &attr);
|
||||
}
|
||||
|
||||
int sftp_symlink(SFTP_SESSION *sftp, const char *target, const char *dest) {
|
||||
STATUS_MESSAGE *status = NULL;
|
||||
SFTP_MESSAGE *msg = NULL;
|
||||
STRING *target_s;
|
||||
STRING *dest_s;
|
||||
BUFFER *buffer;
|
||||
u32 id;
|
||||
|
||||
if (sftp == NULL || target == NULL || dest == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer = buffer_new();
|
||||
if (buffer == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
target_s = string_from_char(target);
|
||||
if (target_s == NULL) {
|
||||
buffer_free(buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dest_s = string_from_char(dest);
|
||||
if (dest_s == NULL) {
|
||||
string_free(target_s);
|
||||
buffer_free(buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
id = sftp_get_new_id(sftp);
|
||||
if (buffer_add_u32(buffer, id) < 0) {
|
||||
buffer_free(buffer);
|
||||
string_free(dest_s);
|
||||
string_free(target_s);
|
||||
return -1;
|
||||
}
|
||||
if (ssh_get_openssh_version(sftp->session)) {
|
||||
/* TODO check for version number if they ever fix it. */
|
||||
if (buffer_add_ssh_string(buffer, target_s) < 0 ||
|
||||
buffer_add_ssh_string(buffer, dest_s) < 0) {
|
||||
buffer_free(buffer);
|
||||
string_free(dest_s);
|
||||
string_free(target_s);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (buffer_add_ssh_string(buffer, dest_s) < 0 ||
|
||||
buffer_add_ssh_string(buffer, target_s) < 0) {
|
||||
buffer_free(buffer);
|
||||
string_free(dest_s);
|
||||
string_free(target_s);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (sftp_packet_write(sftp, SSH_FXP_SYMLINK, buffer) < 0) {
|
||||
buffer_free(buffer);
|
||||
string_free(dest_s);
|
||||
string_free(target_s);
|
||||
return -1;
|
||||
}
|
||||
buffer_free(buffer);
|
||||
string_free(dest_s);
|
||||
string_free(target_s);
|
||||
|
||||
while (msg == NULL) {
|
||||
if (sftp_read_and_dispatch(sftp) < 0) {
|
||||
return -1;
|
||||
}
|
||||
msg = sftp_dequeue(sftp, id);
|
||||
}
|
||||
|
||||
/* By specification, this command only returns SSH_FXP_STATUS */
|
||||
if (msg->packet_type == SSH_FXP_STATUS) {
|
||||
status = parse_status_msg(msg);
|
||||
sftp_message_free(msg);
|
||||
if (status == NULL) {
|
||||
return -1;
|
||||
}
|
||||
sftp_set_error(sftp, status->status);
|
||||
switch (status->status) {
|
||||
case SSH_FX_OK:
|
||||
status_msg_free(status);
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* The status should be SSH_FX_OK if the command was successful, if it
|
||||
* didn't, then there was an error
|
||||
*/
|
||||
ssh_set_error(sftp->session, SSH_REQUEST_DENIED,
|
||||
"SFTP server: %s", status->errormsg);
|
||||
status_msg_free(status);
|
||||
return -1;
|
||||
} else {
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received message %d when attempting to set stats", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *sftp_readlink(SFTP_SESSION *sftp, const char *path) {
|
||||
STATUS_MESSAGE *status = NULL;
|
||||
SFTP_MESSAGE *msg = NULL;
|
||||
STRING *path_s = NULL;
|
||||
STRING *link_s = NULL;
|
||||
BUFFER *buffer;
|
||||
char *link;
|
||||
u32 ignored;
|
||||
u32 id;
|
||||
|
||||
if (sftp == NULL || path == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = buffer_new();
|
||||
if (buffer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path_s = string_from_char(path);
|
||||
if (path_s == NULL) {
|
||||
buffer_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
id = sftp_get_new_id(sftp);
|
||||
if (buffer_add_u32(buffer, id) < 0 ||
|
||||
buffer_add_ssh_string(buffer, path_s) < 0 ||
|
||||
sftp_packet_write(sftp, SSH_FXP_READLINK, buffer) < 0) {
|
||||
buffer_free(buffer);
|
||||
string_free(path_s);
|
||||
return NULL;
|
||||
}
|
||||
buffer_free(buffer);
|
||||
string_free(path_s);
|
||||
|
||||
while (msg == NULL) {
|
||||
if (sftp_read_and_dispatch(sftp) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
msg = sftp_dequeue(sftp, id);
|
||||
}
|
||||
|
||||
if (msg->packet_type == SSH_FXP_NAME) {
|
||||
/* we don't care about "count" */
|
||||
buffer_get_u32(msg->payload, &ignored);
|
||||
/* we only care about the file name string */
|
||||
link_s = buffer_get_ssh_string(msg->payload);
|
||||
sftp_message_free(msg);
|
||||
if (link_s == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
link = string_to_char(link_s);
|
||||
string_free(link_s);
|
||||
|
||||
return link;
|
||||
} else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) */
|
||||
status = parse_status_msg(msg);
|
||||
sftp_message_free(msg);
|
||||
if (status == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ssh_set_error(sftp->session, SSH_REQUEST_DENIED,
|
||||
"SFTP server: %s", status->errormsg);
|
||||
status_msg_free(status);
|
||||
} else { /* this shouldn't happen */
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received message %d when attempting to set stats", msg->packet_type);
|
||||
sftp_message_free(msg);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* another code written by Nick */
|
||||
char *sftp_canonicalize_path(SFTP_SESSION *sftp, const char *path) {
|
||||
STATUS_MESSAGE *status = NULL;
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/sftp.h"
|
||||
#include "libssh/ssh2.h"
|
||||
|
||||
@@ -36,22 +36,6 @@
|
||||
#endif
|
||||
#include "libssh/priv.h"
|
||||
|
||||
#if !defined(HAVE_SELECT) && !defined(HAVE_POLL)
|
||||
#error Your system must have either select() or poll()
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_POLL) && !defined(_WIN32)
|
||||
#warning your system does not have poll. Select has known limitations
|
||||
#define SELECT_LIMIT_CHECK
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_POLL
|
||||
#define USE_POLL
|
||||
#include <poll.h>
|
||||
#else
|
||||
#define USE_SELECT
|
||||
#endif
|
||||
|
||||
/** \defgroup ssh_socket SSH Sockets
|
||||
* \addtogroup ssh_socket
|
||||
* @{
|
||||
@@ -472,86 +456,10 @@ int ssh_socket_wait_for_data(struct socket *s, SSH_SESSION *session, u32 len) {
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
#ifdef USE_SELECT
|
||||
/* ssh_socket_poll, select() version */
|
||||
|
||||
/* \internal
|
||||
* \brief polls the socket for data
|
||||
* \param session ssh session
|
||||
* \param writeable value pointed to set to 1 if it is possible to write
|
||||
* \param except value pointed to set to 1 if there is an exception
|
||||
* \return 1 if it is possible to read, 0 otherwise, -1 on error
|
||||
*/
|
||||
/* ssh_socket_poll */
|
||||
int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
|
||||
SSH_SESSION *session = s->session;
|
||||
struct timeval sometime;
|
||||
fd_set rdes; // read set
|
||||
fd_set wdes; // writing set
|
||||
fd_set edes; // exception set
|
||||
int fdmax =- 1;
|
||||
|
||||
enter_function();
|
||||
|
||||
FD_ZERO(&rdes);
|
||||
FD_ZERO(&wdes);
|
||||
FD_ZERO(&edes);
|
||||
|
||||
if (!ssh_socket_is_open(s)) {
|
||||
*except = 1;
|
||||
*writeable = 0;
|
||||
return 0;
|
||||
}
|
||||
#ifdef SELECT_LIMIT_CHECK
|
||||
// some systems don't handle the fds > FD_SETSIZE
|
||||
if(s->fd > FD_SETSIZE){
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"File descriptor out of range for select: %d", s->fd);
|
||||
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if (!s->data_to_read) {
|
||||
ssh_socket_fd_set(s, &rdes, &fdmax);
|
||||
}
|
||||
if (!s->data_to_write) {
|
||||
ssh_socket_fd_set(s, &wdes, &fdmax);
|
||||
}
|
||||
ssh_socket_fd_set(s, &edes, &fdmax);
|
||||
|
||||
/* Set to return immediately (no blocking) */
|
||||
sometime.tv_sec = 0;
|
||||
sometime.tv_usec = 0;
|
||||
|
||||
/* Make the call, and listen for errors */
|
||||
if (select(fdmax, &rdes, &wdes, &edes, &sometime) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "select(): %s", strerror(errno));
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!s->data_to_read) {
|
||||
s->data_to_read = ssh_socket_fd_isset(s, &rdes);
|
||||
}
|
||||
if (!s->data_to_write) {
|
||||
s->data_to_write = ssh_socket_fd_isset(s, &wdes);
|
||||
}
|
||||
if (!s->data_except) {
|
||||
s->data_except = ssh_socket_fd_isset(s, &edes);
|
||||
}
|
||||
*except = s->data_except;
|
||||
*writeable = s->data_to_write;
|
||||
|
||||
leave_function();
|
||||
return (s->data_to_read || (buffer_get_rest_len(s->in_buffer) > 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_POLL
|
||||
/* ssh_socket_poll, poll() version */
|
||||
int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
|
||||
SSH_SESSION *session = s->session;
|
||||
struct pollfd fd[1];
|
||||
pollfd_t fd[1];
|
||||
int rc = -1;
|
||||
|
||||
enter_function();
|
||||
@@ -573,7 +481,7 @@ int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
|
||||
}
|
||||
|
||||
/* Make the call, and listen for errors */
|
||||
rc = poll(fd, 1, 0);
|
||||
rc = ssh_poll(fd, 1, 0);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "poll(): %s", strerror(errno));
|
||||
leave_function();
|
||||
@@ -596,7 +504,6 @@ int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
|
||||
leave_function();
|
||||
return (s->data_to_read || (buffer_get_rest_len(s->in_buffer) > 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \internal
|
||||
* \brief nonblocking flush of the output buffer
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/priv.h"
|
||||
|
||||
/** \defgroup ssh_string SSH Strings
|
||||
|
||||
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