37 Commits
Author SHA1 Message Date
Nicolas Viennot c9a6e2560a Synchronize the list binding pane (bind-key + ?) 2013-06-26 02:05:13 -04:00
Nicolas Viennot 59cab76dd8 Fix copy mode when the buffer size is smaller than 2000 2013-06-26 00:54:27 -04:00
Nicolas Viennot ddf0a9dd55 Fix compile bug
libssh/include/libssh/libssh.h:115: error: previous declaration of 'ssh_session' was here
tmate.h:83: error: redefinition of typedef 'ssh_channel'
libssh/include/libssh/libssh.h:110: error: previous declaration of 'ssh_channel' was here
make: *** [tmate-ssh-client.o] Error 1
2013-06-17 17:34:34 -04:00
Nicolas Viennot edea6cf141 Release 1.8.4 2013-06-14 23:59:26 -04:00
Nicolas Viennot 632553bdc9 SSH log level is tweakable with -v 2013-06-14 23:58:08 -04:00
Nicolas Viennot 7316ed33e1 [libssh] auth: If the agent fails, fall back to regular path
It's causing issues on MacOSX when ssh_agent_get_ident_count()
reports "Agent count: 0".
2013-06-14 23:53:18 -04:00
Nicolas Viennot 8f19552af0 Better error message when SSH keys are not setup 2013-06-14 23:10:24 -04:00
Nicolas Viennot 80f9e84b83 Release 1.8.3 2013-06-14 22:39:28 -04:00
Nicolas Viennot 53355a0b92 Bug fix: $TMUX wasn't being reused properly 2013-06-14 22:39:21 -04:00
Nicolas Viennot 16dd13979e Ubuntu complains without the README 2013-06-14 22:11:13 -04:00
Nicolas Viennot 12d681d8cc Change connection string tmate.io -> master.tmate.io 2013-06-14 22:11:12 -04:00
Nicolas Viennot 5d847fb0aa Random socket path (we don't support multi sessions) 2013-06-14 15:35:39 -04:00
Nicolas Viennot a50dcb09b5 Notification messages 2013-06-13 05:15:08 -04:00
Nicolas Viennot edd194c23c Synchronize copy-mode 2013-06-13 02:34:59 -04:00
Nicolas Viennot fc4eaeb89f TERM defaults to screen-256color 2013-06-13 02:34:58 -04:00
Nicolas Viennot e52312ec3c Report failed commands to slave
which will in turn notify the proper client
2013-06-12 20:33:58 -04:00
Nicolas Viennot 844451c6ce Show tmate messages in the status bar 2013-06-12 19:47:36 -04:00
Nicolas Viennot a1d7bf7dc0 No reconnection for now 2013-06-12 18:02:29 -04:00
Nicolas Viennot 2dca2c0fd5 Synching winlinks idx instead of window ids 2013-06-12 17:58:31 -04:00
Nicolas Viennot e70a5f8b7f Add strack trace debug function 2013-06-12 17:57:53 -04:00
Nicolas Viennot a4e196366e Quick README 2013-06-12 16:30:04 -04:00
Nicolas Viennot 69bc1bfde5 Sync all session windows 2013-06-12 03:19:42 -04:00
Nicolas Viennot bf4edb4056 Authenticating the server 2013-06-12 01:28:01 -04:00
Nicolas Viennot 141428691e Status bar sync 2013-06-11 23:50:16 -04:00
Nicolas Viennot 35daf6d805 Replication of bind/unbind commands 2013-06-11 22:52:21 -04:00
Nicolas Viennot 839c4e3dd9 Replicate remote client commands 2013-06-11 22:32:49 -04:00
Nicolas Viennot b7371802bf Developer Environement setup 2013-06-11 17:00:50 -04:00
Nicolas Viennot f89b98e1c3 Use tmate.io 2013-06-11 13:30:25 -04:00
Nicolas Viennot 6988b99fb4 Enable compression 2013-06-10 05:59:59 -04:00
Nicolas Viennot 56cee30ee8 [libssh] fix server side compression 2013-06-10 05:59:59 -04:00
Nicolas Viennot 7cdb1e2016 [libssh] bug fix in channel_open() 2013-06-10 04:30:12 -04:00
Nicolas Viennot 8131143fa8 gitignore update 2013-06-10 04:30:12 -04:00
Nicolas Viennot a75e70f86b Fix error message 2013-06-10 04:30:12 -04:00
Nicolas Viennot 864124f4c0 Public key auth no longer need to be blocking (libssh 0.6) 2013-06-10 02:50:07 -04:00
Nicolas Viennot 05de59d106 Adding msgpack 2013-06-10 02:50:07 -04:00
Nicolas Viennot 0f7ccda4fb Adding libssh 2013-06-10 02:50:07 -04:00
Nicolas Viennot 220b2afb3c Client side first shot 2013-06-10 01:54:57 -04:00
334 changed files with 74621 additions and 168 deletions
+4
View File
@@ -15,3 +15,7 @@ tmux
Makefile
Makefile.in
configure
tmate
cscope.*
ctags
*.log
+45 -34
View File
@@ -1,8 +1,8 @@
# $Id$
# Obvious program stuff.
bin_PROGRAMS = tmux
dist_man1_MANS = tmux.1
bin_PROGRAMS = tmate
dist_man1_MANS = tmate.1
# Distribution tarball options.
EXTRA_DIST = \
@@ -21,6 +21,13 @@ if IS_GLIBC
CFLAGS += -D_GNU_SOURCE
endif
CFLAGS += -Wno-unused-parameter -Wno-unused-variable
CFLAGS += -Ilibssh/include/ -Imsgpack/src
if IS_DEVENV
CFLAGS += -DDEVENV
endif
# Set flags for gcc. gcc4 whines abouts silly stuff so it needs slightly
# different flags.
if IS_GCC
@@ -30,8 +37,7 @@ CFLAGS += -O0 -g
CFLAGS += -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CFLAGS += -Wundef -Wbad-function-cast -Winline -Wcast-align
CFLAGS += -Wdeclaration-after-statement
CFLAGS += -Wbad-function-cast -Winline -Wcast-align
CPPFLAGS += -DDEBUG
else
CFLAGS += -O2
@@ -57,7 +63,7 @@ CFLAGS += -erroff=E_EMPTY_DECLARATION
endif
# List of sources.
dist_tmux_SOURCES = \
dist_tmate_SOURCES = \
arguments.c \
attributes.c \
cfg.c \
@@ -171,6 +177,12 @@ dist_tmux_SOURCES = \
session.c \
signal.c \
status.c \
tmate-debug.c \
tmate-ssh-client.c \
tmate-encoder.c \
tmate-decoder.c \
tmate-msg.c \
tmate.c \
tmux.c \
tty-acs.c \
tty-keys.c \
@@ -183,66 +195,65 @@ dist_tmux_SOURCES = \
window.c \
xmalloc.c \
xterm-keys.c
nodist_tmux_SOURCES = osdep-@PLATFORM@.c
nodist_tmate_SOURCES = osdep-@PLATFORM@.c
# Pile in all the compat/ stuff that is needed.
if NO_FORKPTY
nodist_tmux_SOURCES += compat/forkpty-@PLATFORM@.c
nodist_tmate_SOURCES += compat/forkpty-@PLATFORM@.c
endif
if NO_IMSG
nodist_tmux_SOURCES += compat/imsg.c compat/imsg-buffer.c
nodist_tmate_SOURCES += compat/imsg.c compat/imsg-buffer.c
endif
if NO_CLOSEFROM
nodist_tmux_SOURCES += compat/closefrom.c
nodist_tmate_SOURCES += compat/closefrom.c
endif
if NO_DAEMON
nodist_tmux_SOURCES += compat/daemon.c
nodist_tmate_SOURCES += compat/daemon.c
endif
if NO_SETENV
nodist_tmux_SOURCES += compat/setenv.c
nodist_tmate_SOURCES += compat/setenv.c
endif
if NO_STRLCAT
nodist_tmux_SOURCES += compat/strlcat.c
nodist_tmate_SOURCES += compat/strlcat.c
endif
if NO_STRLCPY
nodist_tmux_SOURCES += compat/strlcpy.c
nodist_tmate_SOURCES += compat/strlcpy.c
endif
if NO_ASPRINTF
nodist_tmux_SOURCES += compat/asprintf.c
nodist_tmate_SOURCES += compat/asprintf.c
endif
if NO_FGETLN
nodist_tmux_SOURCES += compat/fgetln.c
nodist_tmate_SOURCES += compat/fgetln.c
endif
if NO_GETOPT
nodist_tmux_SOURCES += compat/getopt.c
nodist_tmate_SOURCES += compat/getopt.c
endif
if NO_STRCASESTR
nodist_tmux_SOURCES += compat/strcasestr.c
nodist_tmate_SOURCES += compat/strcasestr.c
endif
if NO_STRSEP
nodist_tmux_SOURCES += compat/strsep.c
nodist_tmate_SOURCES += compat/strsep.c
endif
if NO_VIS
nodist_tmux_SOURCES += compat/vis.c compat/unvis.c
nodist_tmate_SOURCES += compat/vis.c compat/unvis.c
endif
if NO_STRTONUM
nodist_tmux_SOURCES += compat/strtonum.c
nodist_tmate_SOURCES += compat/strtonum.c
endif
if NO_B64_NTOP
nodist_tmux_SOURCES += compat/b64_ntop.c
nodist_tmate_SOURCES += compat/b64_ntop.c
endif
# Update SF web site.
upload-index.html: update-index.html
scp www/index.html www/main.css www/images/*.png \
${USER},tmux@web.sf.net:/home/groups/t/tm/tmux/htdocs
rm -f www/index.html www/images/small-*
tmate_LDADD = \
libssh/build/src/libssh.a \
msgpack/src/.libs/libmsgpackc.a
update-index.html:
(cd www/images && \
rm -f small-* && \
for i in *.png; do \
convert "$$i" -resize 200x150 "small-$$i"; \
done \
)
sed "s/%%VERSION%%/${VERSION}/g" www/index.html.in >www/index.html
*.c: $(tmate_LDADD)
libssh/build/src/libssh.a:
cd libssh/build && cmake .. -DWITH_SFTP=OFF -DWITH_SERVER=OFF -DWITH_PCAP=OFF -DWITH_STATIC_LIB=ON
+make -C libssh/build ssh_static
msgpack/src/.libs/libmsgpackc.a:
cd msgpack && ./bootstrap && ./configure
+make -C msgpack/src libmsgpackc.la
-60
View File
@@ -1,60 +0,0 @@
Welcome to tmux!
tmux is a "terminal multiplexer", it enables a number of terminals (or windows)
to be accessed and controlled from a single terminal. tmux is intended to be a
simple, modern, BSD-licensed alternative to programs such as GNU screen.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux and OS X and may still
run on Solaris and AIX (although they haven't been tested in a while).
Since the 1.2 release tmux depends on libevent. Download it from:
http://www.monkey.org/~provos/libevent/
To build tmux from a release tarball, do:
$ ./configure && make
$ sudo make install
To get and build the latest from version control:
$ git clone git://git.code.sf.net/p/tmux/tmux-code tmux
$ cd tmux
$ sh autogen.sh
$ ./configure && make
For more information see https://sourceforge.net/scm/?type=git&group_id=200378
and http://git-scm.com. Patches should be sent by email to the mailing list at
tmux-users@lists.sourceforge.net.
For documentation on using tmux, see the tmux.1 manpage. It can be viewed from
the source tree with:
$ nroff -mdoc tmux.1|less
Some common questions are answered in the FAQ file and a more extensive (but
slightly out of date) guide is available in the OpenBSD FAQ at
http://www.openbsd.org/faq/faq7.html#tmux. A rough todo list is in the TODO
file and some example configurations and a Vim syntax file are in the examples
directory.
For debugging, running tmux with -v or -vv will generate server and client log
files in the current directory.
tmux mailing lists are available. Visit:
https://sourceforge.net/mail/?group_id=200378
Bug reports, feature suggestions and especially code contributions are most
welcome. Please send by email to:
tmux-users@lists.sourceforge.net
This file and the CHANGES, FAQ and TODO files are licensed under the ISC
license. Files under examples/ remain copyright their authors unless otherwise
stated in the file but permission has been received to distribute them with
tmux. All other files have a license and copyright notice at their start.
-- Nicholas Marriott <nicm@users.sf.net>
$Id$
Symlink
+1
View File
@@ -0,0 +1 @@
README.md
+60
View File
@@ -0,0 +1,60 @@
Welcome to tmux!
tmux is a "terminal multiplexer", it enables a number of terminals (or windows)
to be accessed and controlled from a single terminal. tmux is intended to be a
simple, modern, BSD-licensed alternative to programs such as GNU screen.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux and OS X and may still
run on Solaris and AIX (although they haven't been tested in a while).
Since the 1.2 release tmux depends on libevent. Download it from:
http://www.monkey.org/~provos/libevent/
To build tmux from a release tarball, do:
$ ./configure && make
$ sudo make install
To get and build the latest from version control:
$ git clone git://git.code.sf.net/p/tmux/tmux-code tmux
$ cd tmux
$ sh autogen.sh
$ ./configure && make
For more information see https://sourceforge.net/scm/?type=git&group_id=200378
and http://git-scm.com. Patches should be sent by email to the mailing list at
tmux-users@lists.sourceforge.net.
For documentation on using tmux, see the tmux.1 manpage. It can be viewed from
the source tree with:
$ nroff -mdoc tmux.1|less
Some common questions are answered in the FAQ file and a more extensive (but
slightly out of date) guide is available in the OpenBSD FAQ at
http://www.openbsd.org/faq/faq7.html#tmux. A rough todo list is in the TODO
file and some example configurations and a Vim syntax file are in the examples
directory.
For debugging, running tmux with -v or -vv will generate server and client log
files in the current directory.
tmux mailing lists are available. Visit:
https://sourceforge.net/mail/?group_id=200378
Bug reports, feature suggestions and especially code contributions are most
welcome. Please send by email to:
tmux-users@lists.sourceforge.net
This file and the CHANGES, FAQ and TODO files are licensed under the ISC
license. Files under examples/ remain copyright their authors unless otherwise
stated in the file but permission has been received to distribute them with
tmux. All other files have a license and copyright notice at their start.
-- Nicholas Marriott <nicm@users.sf.net>
$Id$
+33
View File
@@ -0,0 +1,33 @@
tmate
=====
What is it?
-----------
Tmate is a fork of tmux. It provides an instant pairing solution.
License
-------
tmate is built on top of tmux, libssh and msgpack. Their respective licenses are
in the sources. tmate is MIT licensed.
Copyright (c) 2013 Nicolas Viennot
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+5
View File
@@ -41,6 +41,10 @@ const struct cmd_entry cmd_break_pane_entry = {
enum cmd_retval
cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
#ifdef TMATE
cmdq_error(cmdq, "break pane is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
struct winlink *wl;
struct session *s;
@@ -112,4 +116,5 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
format_free(ft);
}
return (CMD_RETURN_NORMAL);
#endif
}
+5
View File
@@ -76,6 +76,10 @@ cmd_join_pane_exec(struct cmd *self, struct cmd_q *cmdq)
enum cmd_retval
join_pane(struct cmd *self, struct cmd_q *cmdq, int not_same_window)
{
#ifdef TMATE
cmdq_error(cmdq, "join pane is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
struct session *dst_s;
struct winlink *src_wl, *dst_wl;
@@ -170,4 +174,5 @@ join_pane(struct cmd *self, struct cmd_q *cmdq, int not_same_window)
notify_window_layout_changed(dst_w);
return (CMD_RETURN_NORMAL);
#endif
}
+5
View File
@@ -41,6 +41,10 @@ const struct cmd_entry cmd_link_window_entry = {
enum cmd_retval
cmd_link_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
#ifdef TMATE
cmdq_error(cmdq, "link window is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
struct session *src, *dst;
struct winlink *wl;
@@ -62,4 +66,5 @@ cmd_link_window_exec(struct cmd *self, struct cmd_q *cmdq)
recalculate_sizes();
return (CMD_RETURN_NORMAL);
#endif
}
+10
View File
@@ -49,6 +49,16 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
size_t used;
int width, keywidth;
#ifdef TMATE
/* XXX TODO Really nasty hack, we really need our own client instance... */
struct client fake_client;
if (!cmdq->client) {
cmdq->client = &fake_client;
cmdq->client->flags = 0;
cmdq->client->session = RB_MIN(sessions, &sessions);
}
#endif
if (args_has(args, 't'))
return (cmd_list_keys_table(self, cmdq));
+5
View File
@@ -41,6 +41,10 @@ const struct cmd_entry cmd_move_window_entry = {
enum cmd_retval
cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
#ifdef TMATE
cmdq_error(cmdq, "move window is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
struct session *src, *dst, *s;
struct winlink *wl;
@@ -73,4 +77,5 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
recalculate_sizes();
return (CMD_RETURN_NORMAL);
#endif
}
+14
View File
@@ -23,6 +23,7 @@
#include <time.h>
#include "tmux.h"
#include "tmate.h"
/* Create new command queue. */
struct cmd_q *
@@ -81,6 +82,7 @@ cmdq_print(struct cmd_q *cmdq, const char *fmt, ...)
window_pane_reset_mode(w->active);
window_pane_set_mode(w->active, &window_copy_mode);
window_copy_init_for_output(w->active);
tmate_sync_copy_mode(w->active);
}
window_copy_vadd(w->active, fmt, ap);
}
@@ -136,7 +138,14 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
va_end(ap);
if (c == NULL) {
#ifdef TMATE
if (cmd->file && cmd->line)
xasprintf(&cause, "%s:%u: %s", cmd->file, cmd->line, msg);
else
xasprintf(&cause, "%s", msg);
#else
xasprintf(&cause, "%s:%u: %s", cmd->file, cmd->line, msg);
#endif
ARRAY_ADD(&cfg_causes, cause);
} else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
evbuffer_add(c->stderr_data, msg, msglen);
@@ -225,6 +234,11 @@ cmdq_continue(struct cmd_q *cmdq)
cmdq->time = time(NULL);
cmdq->number++;
#ifdef TMATE
if (tmate_should_replicate_cmd(cmdq->cmd->entry))
tmate_exec_cmd(s);
#endif
guard = cmdq_guard(cmdq, "begin");
retval = cmdq->cmd->entry->exec(cmdq->cmd, cmdq);
if (guard) {
+7
View File
@@ -85,6 +85,13 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_q *cmdq)
}
server_unzoom_window(src_w);
#ifdef TMATE
if (src_w != dst_w) {
cmdq_error(cmdq, "swap pane on different window is not supported with tmate");
return (CMD_RETURN_ERROR);
}
#endif
if (src_wp == dst_wp)
return (CMD_RETURN_NORMAL);
+5
View File
@@ -41,6 +41,10 @@ const struct cmd_entry cmd_swap_window_entry = {
enum cmd_retval
cmd_swap_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
#ifdef TMATE
cmdq_error(cmdq, "swap window is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
const char *target_src, *target_dst;
struct session *src, *dst;
@@ -84,4 +88,5 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_q *cmdq)
recalculate_sizes();
return (CMD_RETURN_NORMAL);
#endif
}
+5
View File
@@ -39,6 +39,10 @@ const struct cmd_entry cmd_unlink_window_entry = {
enum cmd_retval
cmd_unlink_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
#ifdef TMATE
cmdq_error(cmdq, "unlink window is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
struct winlink *wl;
struct window *w;
@@ -67,4 +71,5 @@ cmd_unlink_window_exec(struct cmd *self, struct cmd_q *cmdq)
recalculate_sizes();
return (CMD_RETURN_NORMAL);
#endif
}
+15 -1
View File
@@ -1,7 +1,7 @@
# $Id$
# Miscellaneous autofoo bullshit.
AC_INIT(tmux, 1.8)
AC_INIT(tmate, 1.8.4)
AC_CONFIG_AUX_DIR(etc)
AM_INIT_AUTOMAKE([foreign])
@@ -40,6 +40,13 @@ AC_CHECK_HEADERS(
]
)
AC_ARG_ENABLE(
devenv,
AC_HELP_STRING(--enable-devenv, "dev env (localhost, port 2200, no auth checks)"),
found_devenv=$enable_devenv
)
AM_CONDITIONAL(IS_DEVENV, test "x$found_devenv" = xyes)
# Is this a debug build?
#found_debug=yes
AC_ARG_ENABLE(
@@ -107,6 +114,13 @@ AC_MSG_RESULT($found_glibc)
# Look for clock_gettime. Must come before event_init.
AC_SEARCH_LIBS(clock_gettime, rt)
AC_CHECK_LIB(z, inflate, [],
[AC_MSG_ERROR([zlib library required])])
AC_CHECK_LIB(crypto,CRYPTO_new_ex_data, [],
[AC_MSG_ERROR([OpenSSL library required])])
AC_CHECK_LIB(ssl, SSL_library_init, [],
[AC_MSG_ERROR([OpenSSL library required])])
# Look for libevent.
PKG_CHECK_MODULES(
LIBEVENT,
+8
View File
@@ -0,0 +1,8 @@
*.a
*.o
.*
*.swp
*~$
build
cscope.*
tags
+15
View File
@@ -0,0 +1,15 @@
Author(s):
Aris Adamantiadis <aris@0xbadc0de.be> (project initiator)
Andreas Schneider <mail@cynapses.org> (developer)
Nick Zitzmann <seiryu (at) comcast (dot) net> (mostly client SFTP stuff)
Norbert Kiesel <nkiesel (at) tbdnetworks (dot) com> (getaddrinfo and other patches)
Jean-Philippe Garcia Ballester <giga (at) le-pec (dot) org> (Port to libgcrypt and configure.in voodoo, debian packaging)
Contributor(s):
Laurent Bigonville <bigon (at) bigon (dot) be> (debian packaging)
+24
View File
@@ -0,0 +1,24 @@
Some parts are under the BSDv2 License :
Copyright (c) 2000 Markus Friedl. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+136
View File
@@ -0,0 +1,136 @@
project(libssh C)
# Required cmake version
cmake_minimum_required(VERSION 2.6.0)
# global needed variables
set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "5")
set(APPLICATION_VERSION_PATCH "90")
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
# SOVERSION scheme: CURRENT.AGE.REVISION
# If there was an incompatible interface change:
# Increment CURRENT. Set AGE and REVISION to 0
# If there was a compatible interface change:
# Increment AGE. Set REVISION to 0
# If the source code was changed, but there were no interface changes:
# Increment REVISION.
set(LIBRARY_VERSION "4.3.0")
set(LIBRARY_SOVERSION "4")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH
${CMAKE_SOURCE_DIR}/cmake/Modules
)
# add definitions
include(DefineCMakeDefaults)
include(DefinePlatformDefaults)
include(DefineCompilerFlags)
include(DefineInstallationPaths)
include(DefineOptions.cmake)
include(CPackConfig.cmake)
# disallow in-source build
include(MacroEnsureOutOfSourceBuild)
macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.")
# add macros
include(MacroAddPlugin)
include(MacroCopyFile)
# search for libraries
if (WITH_ZLIB)
find_package(ZLIB REQUIRED)
endif (WITH_ZLIB)
if (WITH_GCRYPT)
find_package(GCrypt 1.5.0 REQUIRED)
if (NOT GCRYPT_FOUND)
message(FATAL_ERROR "Could not find GCrypt")
endif (NOT GCRYPT_FOUND)
else (WITH_GCRYPT)
find_package(OpenSSL)
if (NOT OPENSSL_FOUND)
find_package(GCrypt)
if (NOT GCRYPT_FOUND)
message(FATAL_ERROR "Could not find OpenSSL or GCrypt")
endif (NOT GCRYPT_FOUND)
endif (NOT OPENSSL_FOUND)
endif(WITH_GCRYPT)
# Find out if we have threading available
set(CMAKE_THREAD_PREFER_PTHREADS ON)
find_package(Threads)
# config.h checks
include(ConfigureChecks.cmake)
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
# check subdirectories
add_subdirectory(doc)
add_subdirectory(include)
add_subdirectory(src)
# pkg-config file
configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc)
configure_file(libssh_threads.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc
DESTINATION
${LIB_INSTALL_DIR}/pkgconfig
COMPONENT
pkgconfig
)
# cmake config files
configure_file(libssh-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-config.cmake @ONLY)
configure_file(libssh-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-config-version.cmake @ONLY)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/libssh-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/libssh-config-version.cmake
DESTINATION
${CMAKE_INSTALL_DIR}
COMPONENT
devel
)
# in tree build settings
configure_file(libssh-build-tree-settings.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-build-tree-settings.cmake @ONLY)
add_subdirectory(examples)
if (WITH_TESTING)
find_package(CMocka REQUIRED)
include(AddCMockaTest)
add_subdirectory(tests)
endif (WITH_TESTING)
message(STATUS "********************************************")
message(STATUS "********** ${PROJECT_NAME} build options : **********")
message(STATUS "zlib support: ${WITH_ZLIB}")
message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
message(STATUS "SSH-1 support: ${WITH_SSH1}")
message(STATUS "SFTP support: ${WITH_SFTP}")
message(STATUS "Server support : ${WITH_SERVER}")
message(STATUS "Pcap debugging support : ${WITH_PCAP}")
message(STATUS "With static library: ${WITH_STATIC_LIB}")
message(STATUS "Unit testing: ${WITH_TESTING}")
message(STATUS "Client code Unit testing: ${WITH_CLIENT_TESTING}")
if (WITH_INTERNAL_DOC)
message(STATUS "Internal documentation generation")
else (WITH_INTERNAL_DOC)
message(STATUS "Public API documentation generation")
endif (WITH_INTERNAL_DOC)
message(STATUS "Benchmarks: ${WITH_BENCHMARKS}")
message(STATUS "********************************************")
+460
View File
@@ -0,0 +1,460 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
Linking with OpenSSL
17. In addition, as a special exception, we give permission to link the code of its release of libssh with the OpenSSL project's "OpenSSL" library (or with modified versions of it that use the same license as the "OpenSSL" library), and distribute the linked executables. You must obey the GNU Lesser General Public License in all respects for all of the code used other than "OpenSSL". If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version.
END OF TERMS AND CONDITIONS
+53
View File
@@ -0,0 +1,53 @@
# For help take a look at:
# http://www.cmake.org/Wiki/CMake:CPackConfiguration
### general settings
set(CPACK_PACKAGE_NAME ${APPLICATION_NAME})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The SSH library")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README")
set(CPACK_PACKAGE_VENDOR "The SSH Library Development Team")
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
### versions
set(CPACK_PACKAGE_VERSION_MAJOR "0")
set(CPACK_PACKAGE_VERSION_MINOR "5")
set(CPACK_PACKAGE_VERSION_PATCH "90")
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
### source generator
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;tags;cscope.*")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
if (WIN32)
set(CPACK_GENERATOR "ZIP")
### nsis generator
find_package(NSIS)
if (NSIS_MAKE)
set(CPACK_GENERATOR "${CPACK_GENERATOR};NSIS")
set(CPACK_NSIS_DISPLAY_NAME "The SSH Library")
set(CPACK_NSIS_COMPRESSOR "/SOLID zlib")
set(CPACK_NSIS_MENU_LINKS "http://www.libssh.org/" "libssh homepage")
endif (NSIS_MAKE)
endif (WIN32)
set(CPACK_PACKAGE_INSTALL_DIRECTORY "libssh")
set(CPACK_PACKAGE_FILE_NAME ${APPLICATION_NAME}-${CPACK_PACKAGE_VERSION})
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")
set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C/C++ Headers")
set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION
"Libraries used to build programs which use libssh")
set(CPACK_COMPONENT_HEADERS_DESCRIPTION
"C/C++ header files for use with libssh")
set(CPACK_COMPONENT_HEADERS_DEPENDS libraries)
#set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime")
set(CPACK_COMPONENT_LIBRARIES_GROUP "Development")
set(CPACK_COMPONENT_HEADERS_GROUP "Development")
include(CPack)
+9
View File
@@ -0,0 +1,9 @@
set(UPDATE_TYPE "true")
set(CTEST_PROJECT_NAME "libssh")
set(CTEST_NIGHTLY_START_TIME "01:00:00 CET")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "test.libssh.org")
set(CTEST_DROP_LOCATION "/submit.php?project=libssh")
set(CTEST_DROP_SITE_CDASH TRUE)
+298
View File
@@ -0,0 +1,298 @@
ChangeLog
==========
version 0.5.x (released 2012-xx-xx)
* Added new PKI infrastructure.
* Added simplified user auth functions.
* Added ECDSA pubkey support.
* Added ECDSA hostkey support.
* Added diffie-hellman-group14-sha1 support.
* Fixed a ton of bugs.
version 0.5.0 (released 2011-06-01)
* Added ssh_ prefix to all functions.
* Added complete Windows support.
* Added improved server support.
* Added unit tests for a lot of functions.
* Added asynchronous service request.
* Added a multiplatform ssh_getpass() function.
* Added a tutorial.
* Added a lot of documentation.
* Fixed a lot of bugs.
* Fixed several memory leaks.
version 0.4.8 (released 2011-01-15)
* Fixed memory leaks in session signing.
* Fixed memory leak in ssh_print_hexa.
* Fixed problem with ssh_connect w/ timeout and fd > 1024.
* Fixed some warnings on OS/2.
* Fixed installation path for OS/2.
version 0.4.7 (released 2010-12-28)
* Fixed a possible memory leak in ssh_get_user_home().
* Fixed a memory leak in sftp_xstat.
* Fixed uninitialized fd->revents member.
* Fixed timout value in ssh_channel_accept().
* Fixed length checks in ssh_analyze_banner().
* Fixed a possible data overread and crash bug.
* Fixed setting max_fd which breaks ssh_select().
* Fixed some pedantic build warnings.
* Fixed a memory leak with session->bindaddr.
version 0.4.6 (released 2010-09-03)
* Added a cleanup function to free the ws2_32 library.
* Fixed build with gcc 3.4.
* Fixed the Windows build on Vista and newer.
* Fixed the usage of WSAPoll() on Windows.
* Fixed "@deprecated" in doxygen
* Fixed some mingw warnings.
* Fixed handling of opened channels.
* Fixed keepalive problem on older openssh servers.
* Fixed testing for big endian on Windows.
* Fixed the Windows preprocessor macros and defines.
version 0.4.5 (released 2010-07-13)
* Added option to bind a client to an ip address.
* Fixed the ssh socket polling function.
* Fixed Windows related bugs in bsd_poll().
* Fixed serveral build warnings.
version 0.4.4 (released 2010-06-01)
* Fixed a bug in the expand function for escape sequences.
* Fixed a bug in the tilde expand function.
* Fixed a bug in setting the options.
version 0.4.3 (released 2010-05-18)
* Added global/keepalive responses.
* Added runtime detection of WSAPoll().
* Added a select(2) based poll-emulation if poll(2) is not available.
* Added a function to expand an escaped string.
* Added a function to expand the tilde from a path.
* Added a proxycommand support.
* Added ssh_privatekey_type public function
* Added the possibility to define _OPENSSL_DIR and _ZLIB_DIR.
* Fixed sftp_chown.
* Fixed sftp_rename on protocol version 3.
* Fixed a blocking bug in channel_poll.
* Fixed config parsing wich has overwritten user specified values.
* Fixed hashed [host]:port format in knownhosts
* Fixed Windows build.
* Fixed doublefree happening after a negociation error.
* Fixed aes*-ctr with <= OpenSSL 0.9.7b.
* Fixed some documentation.
* Fixed exec example which has broken read usage.
* Fixed broken algorithm choice for server.
* Fixed a typo that we don't export all symbols.
* Removed the unneeded dependency to doxygen.
* Build examples only on the Linux plattform.
version 0.4.2 (released 2010-03-15)
* Added owner and group information in sftp attributes.
* Added missing SSH_OPTIONS_FD option.
* Added printout of owner and group in the sftp example.
* Added a prepend function for ssh_list.
* Added send back replies to openssh's keepalives.
* Fixed documentation in scp code
* Fixed longname parsing, this only workings with readdir.
* Fixed and added support for several identity files.
* Fixed sftp_parse_longname() on Windows.
* Fixed a race condition bug in ssh_scp_close()
* Remove config support for SSHv1 Cipher variable.
* Rename ssh_list_add to ssh_list_append.
* Rename ssh_list_get_head to ssh_list_pop_head
version 0.4.1 (released 2010-02-13)
* Added support for aes128-ctr, aes192-ctr and aes256-ctr encryption.
* Added an example for exec.
* Added private key type detection feature in privatekey_from_file().
* Fixed zlib compression fallback.
* Fixed kex bug that client preference should be prioritary
* Fixed known_hosts file set by the user.
* Fixed a memleak in channel_accept().
* Fixed underflow when leave_function() are unbalanced
* Fixed memory corruption in handle_channel_request_open().
* Fixed closing of a file handle case of errors in privatekey_from_file().
* Fixed ssh_get_user_home_dir() to be thread safe.
* Fixed the doxygen documentation.
version 0.4.0 (released 2009-12-10)
* Added scp support.
* Added support for sending signals (RFC 4254, section 6.9).
* Added MSVC support.
* Added support for ~/.ssh/config.
* Added sftp extension support.
* Added X11 forwarding support for client.
* Added forward listening.
* Added support for openssh extensions (statvfs, fstatvfs).
* Added a cleaned up interface for setting options.
* Added a generic way to handle sockets asynchronously.
* Added logging of the sftp flags used to open a file.
* Added full poll() support and poll-emulation for win32.
* Added missing 64bit functions in sftp.
* Added support for ~/ and SSH_DIR/ in filenames instead of %s/.
* Fixed Fix channel_get_exit_status bug.
* Fixed calltrace logging to make it optional.
* Fixed compilation on Solaris.
* Fixed resolving of ip addresses.
* Fixed libssh compilation without server support.
* Fixed possible memory corruptions (ticket #14).
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.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.
* Added error checking to all functions.
* Added const to arguments where it was needed.
* Added a channel_get_exit_status() function.
* Added a channel_read_buffer() function, channel_read() is now
a POSIX like function.
* Added a more generic auth callback function.
* Added printf attribute checking for log and error functions.
* Added runtime function tracer support.
* Added NSIS build support with CPack.
* Added openssh hashed host support.
* Added API documentation for all public functions.
* Added asynchronous SFTP read function.
* Added a ssh_bind_set_fd() function.
* Fixed known_hosts parsing.
* Fixed a lot of build warnings.
* Fixed the Windows build.
* Fixed a lot of memory leaks.
* Fixed a double free corruption in the server support.
* Fixed the "ssh_accept:" bug in server support.
* Fixed important channel bugs.
* Refactored the socket handling.
* Switched to CMake build system.
* Improved performance.
version 0.2 (released 2007-11-29)
* General cleanup
* More comprehensive API
* Up-to-date Doxygen documentation of each public function
* Basic server-based support
* Libgcrypt support (alternative to openssl and its license)
* SSH1 support (disabled by default)
* Added 3des-cbc
* A lot of bugfixes
version 0.11-dev
* Server implementation development.
* Small bug corrected when connecting to sun ssh servers.
* Channel wierdness corrected (writing huge data packets)
* Channel_read_nonblocking added
* Channel bug where stderr wasn't correctly read fixed.
* Added sftp_file_set_nonblocking(), which is nonblocking SFTP IO
* Connect_status callback.
* Priv.h contains the internal functions, libssh.h the public interface
* Options_set_timeout (thx marcelo) really working.
* Tcp tunneling through channel_open_forward.
* Channel_request_exec()
* Channel_request_env()
* Ssh_get_pubkey_hash()
* Ssh_is_server_known()
* Ssh_write_known_host()
* Options_set_ssh_dir
* How could this happen ! there weren't any channel_close !
* Nasty channel_free bug resolved.
* Removed the unsigned long all around the code. use only u8,u32 & u64.
* It now compiles and runs under amd64 !
* Channel_request_pty_size
* Channel_change_pty_size
* Options_copy()
* Ported the doc to an HTML file.
* Small bugfix in packet.c
* Prefixed error constants with SSH_
* Sftp_stat, sftp_lstat, sftp_fstat. thanks Michel Bardiaux for the patch.
* Again channel number mismatch fixed.
* Fixed a bug in ssh_select making the select fail when a signal has been
caught.
* Keyboard-interactive authentication working.
version 0.1 (released 2004-03-05)
* Begining of sftp subsystem implementation.
* Some cleanup into channels implementation
* Now every channel functions is called by its CHANNEL handler.
* Added channel_poll() and channel_read().
* Changed the client so it uses the new channel_poll and channel_read interface
* Small use-after-free bug with channels resolved
* Changed stupidities in lot of function names.
* Removed a debug output file opened by default.
* Added API.txt, the libssh programmer handbook.
* Various bug fixes from Nick Zitzmann.
* Developed a cryptographic structure for handling protocols.
* An autoconf script which took me half of a day to set up.
* A ssh_select wrapper has been written.
version 0.0.4 (released 2003-10-10)
* Some terminal code (eof handling) added
* Channels bugfix (it still needs some tweaking though)
* Zlib support
* Added a wrapper.c file. The goal is to provide a similar API to every
cryptographic functions. bignums and sha/md5 are wrapped now.
* More work than it first looks.
* Support for other crypto libs planed (lighter libs)
* Fixed stupid select() bug.
* Libssh now compiles and links with openssl 0.9.6
* RSA pubkey authentication code now works !
version 0.0.3 (released 2003-09-15)
* Added install target in makefile
* Some cleanup in headers files and source code
* Change default banner and project name to libssh.
* New file auth.c to support more and more authentication ways
* Bugfix(read offbyone) in send_kex
* A base64 parser. don't read the source, it's awful. pure 0xbadc0de.
* Changed the client filename to "ssh". logic isn't it ?
* Dss publickey authentication ! still need to wait for the rsa one
* Bugfix in packet.c
* New misc.c contains misc functions
version 0.0.2 (released 2003-09-03)
* Initial release.
* Client supports both ssh and dss hostkey verification, but doesn't compare them to openssh's files. (~/.ssh/known_hosts)
* The only supported authentication method is password.
* Compiles on linux and openbsd. freebsd and netbsd should work, too
* Lot of work which hasn't been discussed here.
+59
View File
@@ -0,0 +1,59 @@
Coding Style Conventions
========================
Coding style guidelines are about reducing the number of unnecessary
reformatting patches and making things easier for developers to work together.
You don't have to like them or even agree with them, but once put in place we
all have to abide by them (or vote to change them). However, coding style
should never outweigh coding itself and so the guidelines described here are
hopefully easy enough to follow as they are very common and supported by tools
and editors.
The basic style for C code is the Linux kernel coding style [1] with one
excecption, we use 4 spaces instead of tabs. This closely matches what most
libssh developers use already anyways, with a few exceptions as mentioned
below.
To shorthen this here are the highlights:
* Maximum line width is 80 characters
The reason is not about people with low-res screens but rather sticking
to 80 columns prevents you from easily nesting more than one level of
if statements or other code blocks.
* Use 4 spaces to indent
* No trailing whitespaces
* Follow the K&R guidelines. We won't go through all of them here. Do you
have a copy of "The C Programming Language" anyways right?
Editors
========
VIM
----
set ts=4 sw=4 et cindent
For Vim, the following settings in $HOME/.vimrc will also deal with
displaying trailing whitespace:
if has("syntax") && (&t_Co > 2 || has("gui_running"))
syntax on
function! ActivateInvisibleCharIndicator()
syntax match TrailingSpace "[ \t]\+$" display containedin=ALL
highlight TrailingSpace ctermbg=Red
endf
autocmd BufNewFile,BufRead * call ActivateInvisibleCharIndicator()
endif
" Show tabs, trailing whitespace, and continued lines visually
set list listchars=tab:»·,trail:·,extends:…
" highlight overly long lines same as TODOs.
set textwidth=80
autocmd BufNewFile,BufRead *.c,*.h exec 'match Todo /\%>' . &textwidth . 'v.\+/'
[1] https://www.kernel.org/doc/Documentation/CodingStyle
+179
View File
@@ -0,0 +1,179 @@
include(CheckIncludeFile)
include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckTypeSize)
include(CheckCXXSourceCompiles)
include(TestBigEndian)
set(PACKAGE ${APPLICATION_NAME})
set(VERSION ${APPLICATION_VERSION})
set(DATADIR ${DATA_INSTALL_DIR})
set(LIBDIR ${LIB_INSTALL_DIR})
set(PLUGINDIR "${PLUGIN_INSTALL_DIR}-${LIBRARY_SOVERSION}")
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
set(BINARYDIR ${CMAKE_BINARY_DIR})
set(SOURCEDIR ${CMAKE_SOURCE_DIR})
function(COMPILER_DUMPVERSION _OUTPUT_VERSION)
# Remove whitespaces from the argument.
# This is needed for CC="ccache gcc" cmake ..
string(REPLACE " " "" _C_COMPILER_ARG "${CMAKE_C_COMPILER_ARG1}")
execute_process(
COMMAND
${CMAKE_C_COMPILER} ${_C_COMPILER_ARG} -dumpversion
OUTPUT_VARIABLE _COMPILER_VERSION
)
string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2"
_COMPILER_VERSION "${_COMPILER_VERSION}")
set(${_OUTPUT_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE)
endfunction()
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
compiler_dumpversion(GNUCC_VERSION)
if (NOT GNUCC_VERSION EQUAL 34)
set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden")
check_c_source_compiles(
"void __attribute__((visibility(\"default\"))) test() {}
int main(void){ return 0; }
" WITH_VISIBILITY_HIDDEN)
set(CMAKE_REQUIRED_FLAGS "")
endif (NOT GNUCC_VERSION EQUAL 34)
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
# HEADER FILES
check_include_file(argp.h HAVE_ARGP_H)
check_include_file(pty.h HAVE_PTY_H)
check_include_file(termios.h HAVE_TERMIOS_H)
if (WIN32)
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
if (NOT HAVE_WSPIAPI_H)
message(STATUS "WARNING: Without wspiapi.h, this build will only work on Windows XP and newer versions")
endif (NOT HAVE_WSPIAPI_H)
check_include_files("winsock2.h;ws2tcpip.h" HAVE_WS2TCPIP_H)
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
set(HAVE_GETADDRINFO TRUE)
set(HAVE_GETHOSTBYNAME TRUE)
endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
set(HAVE_SELECT TRUE)
endif (WIN32)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
check_include_file(openssl/ecdh.h HAVE_OPENSSL_ECDH_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
check_include_file(openssl/ec.h HAVE_OPENSSL_EC_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
if (CMAKE_HAVE_PTHREAD_H)
set(HAVE_PTHREAD_H 1)
endif (CMAKE_HAVE_PTHREAD_H)
if (NOT WITH_GCRYPT)
if (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H)
set(HAVE_OPENSSL_ECC 1)
endif (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H)
if (HAVE_OPENSSL_ECC)
set(HAVE_ECC 1)
endif (HAVE_OPENSSL_ECC)
endif (NOT WITH_GCRYPT)
# FUNCTIONS
check_function_exists(strncpy HAVE_STRNCPY)
check_function_exists(vsnprintf HAVE_VSNPRINTF)
check_function_exists(snprintf HAVE_SNPRINTF)
if (WIN32)
check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S)
check_function_exists(_vsnprintf HAVE__VSNPRINTF)
check_function_exists(_snprintf HAVE__SNPRINTF)
check_function_exists(_snprintf_s HAVE__SNPRINTF_S)
endif (WIN32)
if (UNIX)
if (NOT LINUX)
# libsocket (Solaris)
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
if (HAVE_LIBSOCKET)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
endif (HAVE_LIBSOCKET)
# libnsl/inet_pton (Solaris)
check_library_exists(nsl inet_pton "" HAVE_LIBNSL)
if (HAVE_LIBNSL)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl)
endif (HAVE_LIBNSL)
# librt
check_library_exists(rt nanosleep "" HAVE_LIBRT)
endif (NOT LINUX)
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
if (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
endif (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
check_library_exists(util forkpty "" HAVE_LIBUTIL)
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
check_function_exists(poll HAVE_POLL)
check_function_exists(select HAVE_SELECT)
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
check_function_exists(ntohll HAVE_NTOHLL)
check_function_exists(htonll HAVE_HTONLL)
check_function_exists(strtoull HAVE_STRTOULL)
check_function_exists(__strtoull HAVE___STRTOULL)
endif (UNIX)
set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
# LIBRARIES
if (OPENSSL_FOUND)
set(HAVE_LIBCRYPTO 1)
endif (OPENSSL_FOUND)
if (GCRYPT_FOUND)
set(HAVE_LIBGCRYPT 1)
if (GCRYPT_VERSION VERSION_GREATER "1.4.6")
#set(HAVE_GCRYPT_ECC 1)
#set(HAVE_ECC 1)
endif (GCRYPT_VERSION VERSION_GREATER "1.4.6")
endif (GCRYPT_FOUND)
if (CMAKE_HAVE_THREADS_LIBRARY)
if (CMAKE_USE_PTHREADS_INIT)
set(HAVE_PTHREAD 1)
endif (CMAKE_USE_PTHREADS_INIT)
endif (CMAKE_HAVE_THREADS_LIBRARY)
# OPTIONS
if (WITH_DEBUG_CRYPTO)
set(DEBUG_CRYPTO 1)
endif (WITH_DEBUG_CRYPTO)
if (WITH_DEBUG_CALLTRACE)
set(DEBUG_CALLTRACE 1)
endif (WITH_DEBUG_CALLTRACE)
# ENDIAN
if (NOT WIN32)
test_big_endian(WORDS_BIGENDIAN)
endif (NOT WIN32)
+27
View File
@@ -0,0 +1,27 @@
option(WITH_ZLIB "Build with ZLIB support" ON)
option(WITH_SSH1 "Build with SSH1 support" OFF)
option(WITH_SFTP "Build with SFTP support" ON)
option(WITH_SERVER "Build with SSH server support" ON)
option(WITH_STATIC_LIB "Build with a static library" OFF)
option(WITH_DEBUG_CRYPTO "Build with cryto debug output" OFF)
option(WITH_DEBUG_CALLTRACE "Build with calltrace debug output" ON)
option(WITH_GCRYPT "Compile against libgcrypt" OFF)
option(WITH_PCAP "Compile with Pcap generation support" ON)
option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
option(WITH_TESTING "Build with unit tests" OFF)
option(WITH_CLIENT_TESTING "Build with client tests; requires a running sshd" OFF)
option(WITH_BENCHMARKS "Build benchmarks tools" OFF)
if (WITH_ZLIB)
set(WITH_LIBZ ON)
else (WITH_ZLIB)
set(WITH_LIBZ OFF)
endif (WITH_ZLIB)
if(WITH_BENCHMARKS)
set(WITH_TESTING ON)
endif(WITH_BENCHMARKS)
if (WITH_TESTING)
set(WITH_STATIC_LIB ON)
endif (WITH_TESTING)
+99
View File
@@ -0,0 +1,99 @@
# How to build from source
## Requirements
### Common requirements
In order to build libssh, you need to install several components:
- A C compiler
- [CMake](http://www.cmake.org) >= 2.6.0.
- [openssl](http://www.openssl.org) >= 0.9.8
or
- [gcrypt](http://www.gnu.org/directory/Security/libgcrypt.html) >= 1.4
optional:
- [libz](http://www.zlib.net) >= 1.2
Note that these version numbers are version we know works correctly. If you
build and run libssh successfully with an older version, please let us know.
Windows binaries known to be working:
- http://www.slproweb.com/products/Win32OpenSSL.html
- http://www.winimage.com/zLibDll/index.html
We installed them in C:\Program Files
## Building
First, you need to configure the compilation, using CMake. Go inside the
`build` dir. Create it if it doesn't exist.
GNU/Linux, MacOS X, MSYS/MinGW:
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
make
On Windows you should choose a makefile gernerator with -G.
### CMake standard options
Here is a list of the most interesting options provided out of the box by
CMake.
- CMAKE_BUILD_TYPE: The type of build (can be Debug Release MinSizeRel
RelWithDebInfo)
- CMAKE_INSTALL_PREFIX: The prefix to use when running make install (Default
to /usr/local on GNU/Linux and MacOS X)
- CMAKE_C_COMPILER: The path to the C compiler
- CMAKE_CXX_COMPILER: The path to the C++ compiler
### CMake options defined for libssh
Options are defined in the following files:
- DefineOptions.cmake
They can be changed with the -D option:
`cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DWITH_ZLIB=OFF ..`
### Browsing/editing CMake options
In addition to passing options on the command line, you can browse and edit
CMake options using `cmakesetup` (Windows), `cmake-gui` or `ccmake` (GNU/Linux
and MacOS X).
- Go to the build dir
- On Windows: run `cmakesetup`
- On GNU/Linux and MacOS X: run `ccmake ..`
### Useful Windows options:
If you have installed OpenSSL or ZLIB in non standard directories, maybe you
want to set:
OPENSSL_ROOT_DIR
and
ZLIB_ROOT_DIR
## Installing
If you want to install libssh after compilation run:
make install
## Running
The libssh binary can be found in the `build/libssh` directory.
You can use `build/examples/samplessh` which is a sample client to
test libssh on UNIX.
## About this document
This document is written using [Markdown][] syntax, making it possible to
provide usable information in both plain text and HTML format. Whenever
modifying this document please use [Markdown][] syntax.
[markdown]: http://www.daringfireball.net/projects/markdown
+163
View File
@@ -0,0 +1,163 @@
_ _ _ _
(_) (_) (_) (_)
(_) _ (_) _ _ _ _ _ (_) _
(_) (_) (_)(_) _ (_)(_) (_)(_) (_)(_) _
(_) (_) (_) (_) _ (_) _ (_) (_) (_)
(_) (_) (_)(_)(_) (_)(_) (_)(_) (_) (_).org
The SSH library
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1* Why ?
-_-_-_-_-_
Why not ? :) I've began to work on my own implementation of the ssh protocol
because i didn't like the currently public ones.
Not any allowed you to import and use the functions as a powerful library,
and so i worked on a library-based SSH implementation which was non-existing
in the free and open source software world.
2* How/Who ?
-_-_-_-_-_-_-_
If you downloaded this file, you must know what it is : a library for
accessing ssh client services through C libraries calls in a simple manner.
Everybody can use this software under the terms of the LGPL - see the COPYING
file
If you ask yourself how to compile libssh, please read INSTALL before anything.
3* Where ?
-_-_-_-_-_-_
http://www.libssh.org
4* API Changes !
-_-_-_-_-_-_-_-_-_
Changes between 0.4 and 0.5
---------------------------
We use the ssh_ prefix as namespace for every function now. There is a legacy.h
which could be used to get the old function names.
Changes between 0.3 and 0.4
---------------------------
We changed libssh to be typesafe now:
SSH_SESSION *session -> ssh_session session
SFTP_SESSION *sftp -> sftp_session sftp
CHANNEL *channel -> ssh_channel channel
STRING *string -> ssh_string string
...
The options structure has been removed and there is a new function. This
function can set all available options now. You can find the enum in the
header file and it is documented. Example:
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
5* Copyright policy
-_-_-_-_-_-_-_-_-_-_
libssh is a project with distributed copyright ownership, which means we prefer
the copyright on parts of libssh to be held by individuals rather than
corporations if possible. There are historical legal reasons for this, but one
of the best ways to explain it is that it’s much easier to work with
individuals who have ownership than corporate legal departments if we ever need
to make reasonable compromises with people using and working with libssh.
We track the ownership of every part of libssh via git, our source code control
system, so we know the provenance of every piece of code that is committed to
libssh.
So if possible, if you’re doing libssh changes on behalf of a company who
normally owns all the work you do please get them to assign personal copyright
ownership of your changes to you as an individual, that makes things very easy
for us to work with and avoids bringing corporate legal departments into the
picture.
If you can’t do this we can still accept patches from you owned by your
employer under a standard employment contract with corporate copyright
ownership. It just requires a simple set-up process first.
We use a process very similar to the way things are done in the Linux Kernel
community, so it should be very easy to get a sign off from your corporate
legal department. The only changes we’ve made are to accommodate the license we
use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2.
The process is called signing.
How to sign your work
----------------------
Once you have permission to contribute to libssh from your employer, simply
email a copy of the following text from your corporate email address to:
contributing@libssh.org
--------------------------------------------------------------------------
libssh Developer's Certificate of Origin. Version 1.0
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the appropriate
version of the GNU General Public License; or
(b) The contribution is based upon previous work that, to the best of
my knowledge, is covered under an appropriate open source license
and I have the right under that license to submit that work with
modifications, whether created in whole or in part by me, under
the GNU General Public License, in the appropriate version; or
(c) The contribution was provided directly to me by some other
person who certified (a) or (b) and I have not modified it.
(d) I understand and agree that this project and the contribution are
public and that a record of the contribution (including all
metadata and personal information I submit with it, including my
sign-off) is maintained indefinitely and may be redistributed
consistent with the libssh Team's policies and the requirements of
the GNU GPL where they are relevant.
(e) I am granting this work to this project 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 the option of the project) any later version.
http://www.gnu.org/licenses/lgpl-2.1.html
--------------------------------------------------------------------------
We will maintain a copy of that email as a record that you have the rights to
contribute code to libssh under the required licenses whilst working for the
company where the email came from.
Then when sending in a patch via the normal mechanisms described above, add a
line that states:
Signed-off-by: Random J Developer <random@developer.example.org>
using your real name and the email address you sent the original email you used
to send the libssh Developer’s Certificate of Origin to us (sorry, no
pseudonyms or anonymous contributions.)
That’s it! Such code can then quite happily contain changes that have copyright
messages such as:
(c) Example Corporation.
and can be merged into the libssh codebase in the same way as patches from any
other individual. You don’t need to send in a copy of the libssh Developer’s
Certificate of Origin for each patch, or inside each patch. Just the sign-off
message is all that is required once we’ve received the initial email.
Have fun and happy libssh hacking!
The libssh Team
+118
View File
@@ -0,0 +1,118 @@
How to contribute a patch to libssh
====================================
Simple, just make the code change, and email it as either a "diff -u"
change, or as a "git format-patch" change against the original source
code to libssh@libssh.org, or attach it to a bug report at
https://red.libssh.org/
For larger code changes, breaking the changes up into a set of simple
patches, each of which does a single thing, are much easier to review.
Patch sets like that will most likely have an easier time being merged
into the libssh code than large single patches that make lots of
changes in one large diff.
Ownership of the contributed code
==================================
libssh is a project with distributed copyright ownership, which means
we prefer the copyright on parts of libssh to be held by individuals
rather than corporations if possible. There are historical legal
reasons for this, but one of the best ways to explain it is that it's
much easier to work with individuals who have ownership than corporate
legal departments if we ever need to make reasonable compromises with
people using and working with libssh.
We track the ownership of every part of libssh via http://git.libssh.org,
our source code control system, so we know the provenance of every piece
of code that is committed to libssh.
So if possible, if you're doing libssh changes on behalf of a company
who normally owns all the work you do please get them to assign
personal copyright ownership of your changes to you as an individual,
that makes things very easy for us to work with and avoids bringing
corporate legal departments into the picture.
If you can't do this we can still accept patches from you owned by
your employer under a standard employment contract with corporate
copyright ownership. It just requires a simple set-up process first.
We use a process very similar to the way things are done in the Linux
Kernel community, so it should be very easy to get a sign off from
your corporate legal department. The only changes we've made are to
accommodate the license we use, which is LGPLv2 (or later) whereas the
Linux kernel uses GPLv2.
The process is called signing.
How to sign your work
----------------------
Once you have permission to contribute to libssh from your employer, simply
email a copy of the following text from your corporate email address to:
contributing@libssh.org
libssh Developer's Certificate of Origin. Version 1.0
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the appropriate
version of the GNU General Public License; or
(b) The contribution is based upon previous work that, to the best of
my knowledge, is covered under an appropriate open source license
and I have the right under that license to submit that work with
modifications, whether created in whole or in part by me, under
the GNU General Public License, in the appropriate version; or
(c) The contribution was provided directly to me by some other
person who certified (a) or (b) and I have not modified it.
(d) I understand and agree that this project and the contribution are
public and that a record of the contribution (including all
metadata and personal information I submit with it, including my
sign-off) is maintained indefinitely and may be redistributed
consistent with the libssh Team's policies and the requirements of
the GNU GPL where they are relevant.
(e) I am granting this work to this project 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 the option of the project) any later version.
http://www.gnu.org/licenses/lgpl-2.1.html
We will maintain a copy of that email as a record that you have the
rights to contribute code to libssh under the required licenses whilst
working for the company where the email came from.
Then when sending in a patch via the normal mechanisms described
above, add a line that states:
Signed-off-by: Random J Developer <random@developer.example.org>
using your real name and the email address you sent the original email
you used to send the libssh Developer's Certificate of Origin to us
(sorry, no pseudonyms or anonymous contributions.)
That's it! Such code can then quite happily contain changes that have
copyright messages such as:
(c) Example Corporation.
and can be merged into the libssh codebase in the same way as patches
from any other individual. You don't need to send in a copy of the
libssh Developer's Certificate of Origin for each patch, or inside each
patch. Just the sign-off message is all that is required once we've
received the initial email.
Have fun and happy libssh hacking !
The libssh Team
+197
View File
@@ -0,0 +1,197 @@
#!/bin/bash
#
# Last Change: 2008-06-18 14:13:46
#
# Script to build libssh on UNIX.
#
# Copyright (c) 2006-2007 Andreas Schneider <mail@cynapses.org>
#
SOURCE_DIR=".."
LANG=C
export LANG
SCRIPT="$0"
COUNT=0
while [ -L "${SCRIPT}" ]
do
SCRIPT=$(readlink ${SCRIPT})
COUNT=$(expr ${COUNT} + 1)
if [ ${COUNT} -gt 100 ]; then
echo "Too many symbolic links"
exit 1
fi
done
BUILDDIR=$(dirname ${SCRIPT})
cleanup_and_exit () {
if test "$1" = 0 -o -z "$1" ; then
exit 0
else
exit $1
fi
}
function configure() {
if [ -n "${CMAKEDIR}" ]; then
${CMAKEDIR}/bin/cmake "$@" ${SOURCE_DIR} || cleanup_and_exit $?
else
cmake "$@" ${SOURCE_DIR} || cleanup_and_exit $?
fi
}
function compile() {
if [ -f /proc/cpuinfo ]; then
CPUCOUNT=$(grep -c processor /proc/cpuinfo)
elif test `uname` = "SunOS" ; then
CPUCOUNT=$(psrinfo -p)
else
CPUCOUNT="1"
fi
if [ "${CPUCOUNT}" -gt "1" ]; then
${MAKE} -j${CPUCOUNT} $1 || cleanup_and_exit $?
else
${MAKE} $1 || exit $?
fi
}
function clean_build_dir() {
find ! -path "*.svn*" ! -name "*.bat" ! -name "*.sh" ! -name "." -print0 | xargs -0 rm -rf
}
function usage () {
echo "Usage: `basename $0` [--prefix /install_prefix|--build [debug|final]|--clean|--verbose|--libsuffix (32|64)|--help|--clang|--cmakedir /directory|--make
(gmake|make)|--ccompiler (gcc|cc)|--withstaticlib|--unittesting|--clientunittesting|--withssh1|--withserver]"
cleanup_and_exit
}
cd ${BUILDDIR}
# the default CMake options:
OPTIONS="--graphviz=${BUILDDIR}/libssh.dot"
# the default 'make' utility:
MAKE="make"
while test -n "$1"; do
PARAM="$1"
ARG="$2"
shift
case ${PARAM} in
*-*=*)
ARG=${PARAM#*=}
PARAM=${PARAM%%=*}
set -- "----noarg=${PARAM}" "$@"
esac
case ${PARAM} in
*-help|-h)
#echo_help
usage
cleanup_and_exit
;;
*-build)
DOMAKE="1"
BUILD_TYPE="${ARG}"
test -n "${BUILD_TYPE}" && shift
;;
*-clean)
clean_build_dir
cleanup_and_exit
;;
*-clang)
OPTIONS="${OPTIONS} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
;;
*-verbose)
DOVERBOSE="1"
;;
*-memtest)
OPTIONS="${OPTIONS} -DMEM_NULL_TESTS=ON"
;;
*-libsuffix)
OPTIONS="${OPTIONS} -DLIB_SUFFIX=${ARG}"
shift
;;
*-prefix)
OPTIONS="${OPTIONS} -DCMAKE_INSTALL_PREFIX=${ARG}"
shift
;;
*-sysconfdir)
OPTIONS="${OPTIONS} -DSYSCONF_INSTALL_DIR=${ARG}"
shift
;;
*-cmakedir)
CMAKEDIR="${ARG}"
shift
;;
*-make)
MAKE="${ARG}"
shift
;;
*-ccompiler)
OPTIONS="${OPTIONS} -DCMAKE_C_COMPILER=${ARG}"
shift
;;
*-withstaticlib)
OPTIONS="${OPTIONS} -DWITH_STATIC_LIB=ON"
;;
*-unittesting)
OPTIONS="${OPTIONS} -DWITH_TESTING=ON"
;;
*-clientunittesting)
OPTIONS="${OPTIONS} -DWITH_CLIENT_TESTING=ON"
;;
*-withssh1)
OPTIONS="${OPTIONS} -DWITH_SSH1=ON"
;;
*-withserver)
OPTIONS="${OPTIONS} -DWITH_SERVER=ON"
;;
----noarg)
echo "$ARG does not take an argument"
cleanup_and_exit
;;
-*)
echo Unknown Option "$PARAM". Exit.
cleanup_and_exit 1
;;
*)
usage
;;
esac
done
if [ "${DOMAKE}" == "1" ]; then
OPTIONS="${OPTIONS} -DCMAKE_BUILD_TYPE=${BUILD_TYPE}"
fi
if [ -n "${DOVERBOSE}" ]; then
OPTIONS="${OPTIONS} -DCMAKE_VERBOSE_MAKEFILE=1"
else
OPTIONS="${OPTIONS} -DCMAKE_VERBOSE_MAKEFILE=0"
fi
test -f "${BUILDDIR}/.build.log" && rm -f ${BUILDDIR}/.build.log
touch ${BUILDDIR}/.build.log
# log everything from here to .build.log
exec 1> >(exec -a 'build logging tee' tee -a ${BUILDDIR}/.build.log) 2>&1
echo "${HOST} started build at $(date)."
echo
configure ${OPTIONS} "$@"
if [ -n "${DOMAKE}" ]; then
test -n "${DOVERBOSE}" && compile VERBOSE=1 || compile
fi
DOT=$(which dot 2>/dev/null)
if [ -n "${DOT}" ]; then
${DOT} -Tpng -o${BUILDDIR}/libssh.png ${BUILDDIR}/libssh.dot
${DOT} -Tsvg -o${BUILDDIR}/libssh.svg ${BUILDDIR}/libssh.dot
fi
exec >&0 2>&0 # so that the logging tee finishes
sleep 1 # wait till tee terminates
cleanup_and_exit 0
+23
View File
@@ -0,0 +1,23 @@
# - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN)
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
# Copyright (c) 2007-2010 Andreas Schneider <asn@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
enable_testing()
include(CTest)
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
set(CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags")
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
set(CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
function (ADD_CMOCKA_TEST _testName _testSource)
add_executable(${_testName} ${_testSource})
target_link_libraries(${_testName} ${ARGN})
add_test(${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName})
endfunction (ADD_CMOCKA_TEST)
@@ -0,0 +1,22 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,26 @@
# - Check whether the C compiler supports a given flag in the
# context of a stack checking compiler option.
# CHECK_C_COMPILER_FLAG_SSP(FLAG VARIABLE)
#
# FLAG - the compiler flag
# VARIABLE - variable to store the result
#
# This actually calls check_c_source_compiles.
# See help for CheckCSourceCompiles for a listing of variables
# that can modify the build.
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
include(CheckCSourceCompiles)
function(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT)
set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT})
set(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
endfunction(CHECK_C_COMPILER_FLAG_SSP)
@@ -0,0 +1,27 @@
# Always include srcdir and builddir in include path
# This saves typing ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY} in
# about every subdir
# since cmake 2.4.0
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Put the include dirs which are in the source or build tree
# before all other include dirs, so the headers in the sources
# are prefered over the already installed ones
# since cmake 2.4.1
set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
# Use colored output
# since cmake 2.4.0
set(CMAKE_COLOR_MAKEFILE ON)
# Define the generic version of the libraries here
set(GENERIC_LIB_VERSION "0.1.0")
set(GENERIC_LIB_SOVERSION "0")
# Set the default build type to release with debug info
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebInfo
CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
)
endif (NOT CMAKE_BUILD_TYPE)
@@ -0,0 +1,77 @@
# define system dependent compiler flags
include(CheckCCompilerFlag)
include(CheckCCompilerFlagSSP)
if (UNIX AND NOT WIN32)
#
# Define GNUCC compiler flags
#
if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
# add -Wconversion ?
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute")
# with -fPIC
check_c_compiler_flag("-fPIC" WITH_FPIC)
if (WITH_FPIC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
endif (WITH_FPIC)
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
if (WITH_STACK_PROTECTOR)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
endif (WITH_STACK_PROTECTOR)
if (CMAKE_BUILD_TYPE)
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
if (NOT CMAKE_BUILD_TYPE_LOWER MATCHES debug)
check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
if (WITH_FORTIFY_SOURCE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2")
endif (WITH_FORTIFY_SOURCE)
endif()
endif()
endif (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
#
# Check for large filesystem support
#
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
)
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
if (_lfs_CFLAGS)
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}")
endif (_lfs_CFLAGS)
endif (UNIX AND NOT WIN32)
if (MSVC)
# Use secure functions by defaualt and suppress warnings about
#"deprecated" functions
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
endif (MSVC)
@@ -0,0 +1,109 @@
if (UNIX OR OS2)
IF (NOT APPLICATION_NAME)
MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME")
SET(APPLICATION_NAME ${PROJECT_NAME})
ENDIF (NOT APPLICATION_NAME)
# Suffix for Linux
SET(LIB_SUFFIX
CACHE STRING "Define suffix of directory name (32/64)"
)
SET(EXEC_INSTALL_PREFIX
"${CMAKE_INSTALL_PREFIX}"
CACHE PATH "Base directory for executables and libraries"
)
SET(SHARE_INSTALL_PREFIX
"${CMAKE_INSTALL_PREFIX}/share"
CACHE PATH "Base directory for files which go to share/"
)
SET(DATA_INSTALL_PREFIX
"${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}"
CACHE PATH "The parent directory where applications can install their data")
# The following are directories where stuff will be installed to
SET(BIN_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/bin"
CACHE PATH "The ${APPLICATION_NAME} binary install dir (default prefix/bin)"
)
SET(SBIN_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/sbin"
CACHE PATH "The ${APPLICATION_NAME} sbin install dir (default prefix/sbin)"
)
SET(LIB_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}"
CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/lib)"
)
SET(LIBEXEC_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/libexec"
CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/libexec)"
)
SET(PLUGIN_INSTALL_DIR
"${LIB_INSTALL_DIR}/${APPLICATION_NAME}"
CACHE PATH "The subdirectory relative to the install prefix where plugins will be installed (default is prefix/lib/${APPLICATION_NAME})"
)
SET(INCLUDE_INSTALL_DIR
"${CMAKE_INSTALL_PREFIX}/include"
CACHE PATH "The subdirectory to the header prefix (default prefix/include)"
)
set(CMAKE_INSTALL_DIR
"${LIB_INSTALL_DIR}/cmake"
CACHE PATH "The subdirectory to install cmake config files")
SET(DATA_INSTALL_DIR
"${DATA_INSTALL_PREFIX}"
CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_NAME})"
)
SET(HTML_INSTALL_DIR
"${DATA_INSTALL_PREFIX}/doc/HTML"
CACHE PATH "The HTML install dir for documentation (default data/doc/html)"
)
SET(ICON_INSTALL_DIR
"${DATA_INSTALL_PREFIX}/icons"
CACHE PATH "The icon install dir (default data/icons/)"
)
SET(SOUND_INSTALL_DIR
"${DATA_INSTALL_PREFIX}/sounds"
CACHE PATH "The install dir for sound files (default data/sounds)"
)
SET(LOCALE_INSTALL_DIR
"${SHARE_INSTALL_PREFIX}/locale"
CACHE PATH "The install dir for translations (default prefix/share/locale)"
)
SET(XDG_APPS_DIR
"${SHARE_INSTALL_PREFIX}/applications/"
CACHE PATH "The XDG apps dir"
)
SET(XDG_DIRECTORY_DIR
"${SHARE_INSTALL_PREFIX}/desktop-directories"
CACHE PATH "The XDG directory"
)
SET(SYSCONF_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/etc"
CACHE PATH "The ${APPLICATION_NAME} sysconfig install dir (default prefix/etc)"
)
SET(MAN_INSTALL_DIR
"${SHARE_INSTALL_PREFIX}/man"
CACHE PATH "The ${APPLICATION_NAME} man install dir (default prefix/man)"
)
SET(INFO_INSTALL_DIR
"${SHARE_INSTALL_PREFIX}/info"
CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)"
)
else()
# Same same
set(BIN_INSTALL_DIR "bin" CACHE PATH "-")
set(SBIN_INSTALL_DIR "sbin" CACHE PATH "-")
set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "-")
set(INCLUDE_INSTALL_DIR "include" CACHE PATH "-")
set(CMAKE_INSTALL_DIR "CMake" CACHE PATH "-")
set(PLUGIN_INSTALL_DIR "plugins" CACHE PATH "-")
set(HTML_INSTALL_DIR "doc/HTML" CACHE PATH "-")
set(ICON_INSTALL_DIR "icons" CACHE PATH "-")
set(SOUND_INSTALL_DIR "soudns" CACHE PATH "-")
set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-")
endif ()
@@ -0,0 +1,28 @@
# Set system vars
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
set(LINUX TRUE)
endif(CMAKE_SYSTEM_NAME MATCHES "Linux")
if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
set(FREEBSD TRUE)
set(BSD TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
set(OPENBSD TRUE)
set(BSD TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
if (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
set(NETBSD TRUE)
set(BSD TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
set(SOLARIS TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
if (CMAKE_SYSTEM_NAME MATCHES "OS2")
set(OS2 TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "OS2")
+60
View File
@@ -0,0 +1,60 @@
# - Try to find Argp
# Once done this will define
#
# ARGP_FOUND - system has Argp
# ARGP_INCLUDE_DIRS - the Argp include directory
# ARGP_LIBRARIES - Link these to use Argp
# ARGP_DEFINITIONS - Compiler switches required for using Argp
#
# Copyright (c) 2010 Andreas Schneider <asn@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
# in cache already
set(ARGP_FOUND TRUE)
else (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
find_path(ARGP_INCLUDE_DIR
NAMES
argp.h
PATHS
/usr/include
/usr/local/include
/opt/local/include
/sw/include
)
find_library(ARGP_LIBRARY
NAMES
argp
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
set(ARGP_INCLUDE_DIRS
${ARGP_INCLUDE_DIR}
)
if (ARGP_LIBRARY)
set(ARGP_LIBRARIES
${ARGP_LIBRARIES}
${ARGP_LIBRARY}
)
endif (ARGP_LIBRARY)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Argp DEFAULT_MSG ARGP_LIBRARIES ARGP_INCLUDE_DIRS)
# show the ARGP_INCLUDE_DIRS and ARGP_LIBRARIES variables only in the advanced view
mark_as_advanced(ARGP_INCLUDE_DIRS ARGP_LIBRARIES)
endif (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
+49
View File
@@ -0,0 +1,49 @@
# - Try to find CMocka
# Once done this will define
#
# CMOCKA_ROOT_DIR - Set this variable to the root installation of CMocka
#
# Read-Only variables:
# CMOCKA_FOUND - system has CMocka
# CMOCKA_INCLUDE_DIR - the CMocka include directory
# CMOCKA_LIBRARIES - Link these to use CMocka
# CMOCKA_DEFINITIONS - Compiler switches required for using CMocka
#
#=============================================================================
# Copyright (c) 2011-2012 Andreas Schneider <asn@cryptomilk.org>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
#
find_path(CMOCKA_INCLUDE_DIR
NAMES
cmocka.h
PATHS
${CMOCKA_ROOT_DIR}/include
)
find_library(CMOCKA_LIBRARY
NAMES
cmocka
PATHS
${CMOCKA_ROOT_DIR}/include
)
if (CMOCKA_LIBRARY)
set(CMOCKA_LIBRARIES
${CMOCKA_LIBRARIES}
${CMOCKA_LIBRARY}
)
endif (CMOCKA_LIBRARY)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CMocka DEFAULT_MSG CMOCKA_LIBRARIES CMOCKA_INCLUDE_DIR)
# show the CMOCKA_INCLUDE_DIR and CMOCKA_LIBRARIES variables only in the advanced view
mark_as_advanced(CMOCKA_INCLUDE_DIR CMOCKA_LIBRARIES)
+75
View File
@@ -0,0 +1,75 @@
# - Try to find GCrypt
# Once done this will define
#
# GCRYPT_FOUND - system has GCrypt
# GCRYPT_INCLUDE_DIRS - the GCrypt include directory
# GCRYPT_LIBRARIES - Link these to use GCrypt
# GCRYPT_DEFINITIONS - Compiler switches required for using GCrypt
#
#=============================================================================
# Copyright (c) 2009-2012 Andreas Schneider <asn@cryptomilk.org>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
#
set(_GCRYPT_ROOT_HINTS
$ENV{GCRYTPT_ROOT_DIR}
${GCRYPT_ROOT_DIR})
set(_GCRYPT_ROOT_PATHS
"$ENV{PROGRAMFILES}/libgcrypt")
set(_GCRYPT_ROOT_HINTS_AND_PATHS
HINTS ${_GCRYPT_ROOT_HINTS}
PATHS ${_GCRYPT_ROOT_PATHS})
find_path(GCRYPT_INCLUDE_DIR
NAMES
gcrypt.h
HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS}
)
find_library(GCRYPT_LIBRARY
NAMES
gcrypt
gcrypt11
libgcrypt-11
HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS}
)
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY})
if (GCRYPT_INCLUDE_DIR)
file(STRINGS "${GCRYPT_INCLUDE_DIR}/gcrypt.h" _gcrypt_version_str REGEX "^#define GCRYPT_VERSION \"[0-9]+.[0-9]+.[0-9]+\"")
string(REGEX REPLACE "^.*GCRYPT_VERSION.*([0-9]+.[0-9]+.[0-9]+).*" "\\1" GCRYPT_VERSION "${_gcrypt_version_str}")
endif (GCRYPT_INCLUDE_DIR)
include(FindPackageHandleStandardArgs)
if (GCRYPT_VERSION)
find_package_handle_standard_args(GCrypt
REQUIRED_VARS
GCRYPT_INCLUDE_DIR
GCRYPT_LIBRARIES
VERSION_VAR
GCRYPT_VERSION
FAIL_MESSAGE
"Could NOT find GCrypt, try to set the path to GCrypt root folder in the system variable GCRYPT_ROOT_DIR"
)
else (GCRYPT_VERSION)
find_package_handle_standard_args(GCrypt
"Could NOT find GCrypt, try to set the path to GCrypt root folder in the system variable GCRYPT_ROOT_DIR"
GCRYPT_INCLUDE_DIR
GCRYPT_LIBRARIES)
endif (GCRYPT_VERSION)
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
mark_as_advanced(GCRYPT_INCLUDE_DIR GCRYPT_LIBRARIES)
+39
View File
@@ -0,0 +1,39 @@
# - Try to find NSIS
# Once done this will define
#
# NSIS_ROOT_DIR - Set this variable to the root installation of ZLIB
#
# Read-Only variables:
# NSIS_FOUND - system has NSIS
# NSIS_MAKE - NSIS creator executable
#
#=============================================================================
# Copyright (c) 2010-2011 Andreas Schneider <asn@cryptomilk.org>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
#
set(_NSIS_ROOT_PATHS
C:/NSIS/Bin
"$ENV{PROGRAMFILES}/NSIS"
)
find_program(NSIS_MAKE
NAMES
makensis
PATHS
${NSIS_ROOT_PATH}
${NSIS_ROOT_PATH}/Bin
${_NSIS_ROOT_PATHS}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NSIS DEFAULT_MSG NSIS_MAKE)
mark_as_advanced(NSIS_MAKE)
+208
View File
@@ -0,0 +1,208 @@
# - Try to find OpenSSL
# Once done this will define
#
# OPENSSL_ROOT_DIR - Set this variable to the root installation of OpenSSL
#
# Read-Only variables:
# OPENSSL_FOUND - system has OpenSSL
# OPENSSL_INCLUDE_DIRS - the OpenSSL include directory
# OPENSSL_LIBRARIES - Link these to use OpenSSL
# OPENSSL_DEFINITIONS - Compiler switches required for using OpenSSL
#
#=============================================================================
# Copyright (c) 2006-2009 Kitware, Inc.
# Copyright (c) 2006 Alexander Neundorf <neundorf@kde.org>
# Copyright (c) 2009-2010 Mathieu Malaterre <mathieu.malaterre@gmail.com>
# Copyright (c) 2011 Andreas Schneider <asn@cryptomilk.org>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
#
if (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
# in cache already
set(OPENSSL_FOUND TRUE)
else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
if (UNIX)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(_OPENSSL openssl)
endif (PKG_CONFIG_FOUND)
endif (UNIX)
# http://www.slproweb.com/products/Win32OpenSSL.html
set(_OPENSSL_ROOT_HINTS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
)
set(_OPENSSL_ROOT_PATHS
"C:/OpenSSL/"
"C:/OpenSSL-Win32/"
"C:/OpenSSL-Win64/"
"$ENV{PROGRAMFILES}/OpenSSL"
"$ENV{PROGRAMFILES}/OpenSSL-Win32"
"$ENV{PROGRAMFILES}/OpenSSL-Win64"
)
find_path(OPENSSL_ROOT_DIR
NAMES
include/openssl/ssl.h
HINTS
${_OPENSSL_ROOT_HINTS}
PATHS
${_OPENSSL_ROOT_PATHS}
)
mark_as_advanced(OPENSSL_ROOT_DIR)
find_path(OPENSSL_INCLUDE_DIR
NAMES
openssl/ssl.h
PATHS
/usr/local/include
/opt/local/include
/sw/include
/usr/lib/sfw/include
${OPENSSL_ROOT_DIR}/include
)
set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
mark_as_advanced(OPENSSL_INCLUDE_DIRS)
if (WIN32 AND NOT CYGWIN)
# MINGW should go here too
if (MSVC)
# /MD and /MDd are the standard values - if someone wants to use
# others, the libnames have to change here too
# use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b
# TODO: handle /MT and static lib
# In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix:
# * MD for dynamic-release
# * MDd for dynamic-debug
# * MT for static-release
# * MTd for static-debug
# Implementation details:
# We are using the libraries located in the VC subdir instead of the parent directory eventhough :
# libeay32MD.lib is identical to ../libeay32.lib, and
# ssleay32MD.lib is identical to ../ssleay32.lib
find_library(LIB_EAY_DEBUG
NAMES
libeay32MDd
libeay32
PATHS
${OPENSSL_ROOT_DIR}/lib/VC
)
find_library(LIB_EAY_RELEASE
NAMES
libeay32MD
libeay32
PATHS
${OPENSSL_ROOT_DIR}/lib/VC
)
find_library(SSL_EAY_DEBUG
NAMES
ssleay32MDd
ssleay32
ssl
PATHS ${OPENSSL_ROOT_DIR}/lib/VC
)
find_library(SSL_EAY_RELEASE
NAMES
ssleay32MD
ssleay32
ssl
PATHS
${OPENSSL_ROOT_DIR}/lib/VC
)
if (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
set(OPENSSL_LIBRARIES
optimized ${SSL_EAY_RELEASE} debug ${SSL_EAY_DEBUG}
optimized ${LIB_EAY_RELEASE} debug ${LIB_EAY_DEBUG}
)
else (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
set( OPENSSL_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} )
endif (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
mark_as_advanced(SSL_EAY_DEBUG SSL_EAY_RELEASE)
mark_as_advanced(LIB_EAY_DEBUG LIB_EAY_RELEASE)
elseif (MINGW)
# same player, for MingW
find_library(LIB_EAY
NAMES
libeay32
PATHS
${OPENSSL_ROOT_DIR}/lib/MinGW
)
find_library(SSL_EAY
NAMES
ssleay32
PATHS
${OPENSSL_ROOT_DIR}/lib/MinGW
)
mark_as_advanced(SSL_EAY LIB_EAY)
set(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY})
else(MSVC)
# Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
find_library(LIB_EAY
NAMES
libeay32
PATHS
${OPENSSL_ROOT_DIR}/lib
)
find_library(SSL_EAY
NAMES
ssleay32
PATHS
${OPENSSL_ROOT_DIR}/lib
)
mark_as_advanced(SSL_EAY LIB_EAY)
set(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY})
endif(MSVC)
else (WIN32 AND NOT CYGWIN)
find_library(OPENSSL_SSL_LIBRARIES
NAMES
ssl
ssleay32
ssleay32MD
PATHS
${_OPENSSL_LIBDIR}
/opt/local/lib
/sw/lib
/usr/sfw/lib/64
/usr/sfw/lib
)
find_library(OPENSSL_CRYPTO_LIBRARIES
NAMES
crypto
PATHS
${_OPENSSL_LIBDIR}
/opt/local/lib
/sw/lib
/usr/sfw/lib/64
/usr/sfw/lib
)
mark_as_advanced(OPENSSL_CRYPTO_LIBRARIES OPENSSL_SSL_LIBRARIES)
set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES})
endif (WIN32 AND NOT CYGWIN)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpenSSL DEFAULT_MSG OPENSSL_LIBRARIES OPENSSL_INCLUDE_DIRS)
endif (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
+120
View File
@@ -0,0 +1,120 @@
# - Try to find ZLIB
# Once done this will define
#
# ZLIB_ROOT_DIR - Set this variable to the root installation of ZLIB
#
# Read-Only variables:
# ZLIB_FOUND - system has ZLIB
# ZLIB_INCLUDE_DIRS - the ZLIB include directory
# ZLIB_LIBRARIES - Link these to use ZLIB
#
# ZLIB_VERSION_STRING - The version of zlib found (x.y.z)
# ZLIB_VERSION_MAJOR - The major version of zlib
# ZLIB_VERSION_MINOR - The minor version of zlib
# ZLIB_VERSION_PATCH - The patch version of zlib
# ZLIB_VERSION_TWEAK - The tweak version of zlib
#
# The following variable are provided for backward compatibility
#
# ZLIB_MAJOR_VERSION - The major version of zlib
# ZLIB_MINOR_VERSION - The minor version of zlib
# ZLIB_PATCH_VERSION - The patch version of zlib
#
#=============================================================================
# Copyright (c) 2001-2009 Kitware, Inc.
# Copyright (c) 2011 Andreas Schneider <asn@cryptomilk.org>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
#
if (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
# in cache already
set(ZLIB_FOUND TRUE)
else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
set(_ZLIB_ROOT_HINTS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Zlib;InstallPath]/include"
)
set(_ZLIB_ROOT_PATHS
"$ENV{PROGRAMFILES}/zlib"
)
find_path(ZLIB_ROOT_DIR
NAMES
include/zlib.h
HINTS
${_ZLIB_ROOT_HINTS}
PATHS
${_ZLIB_ROOT_PATHS}
)
mark_as_advanced(ZLIB_ROOT_DIR)
# check for header file
find_path(ZLIB_INCLUDE_DIR
NAMES
zlib.h
PATHS
/usr/local/include
/opt/local/include
/sw/include
/usr/lib/sfw/include
${ZLIB_ROOT_DIR}/include
)
mark_as_advanced(ZLIB_INCLUDE_DIR)
# check version number
if (ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h")
file(STRINGS "${ZLIB_INCLUDE_DIR}/zlib.h" ZLIB_H REGEX "^#define ZLIB_VERSION \"[^\"]*\"$")
string(REGEX REPLACE "^.*ZLIB_VERSION \"([0-9]+).*$" "\\1" ZLIB_VERSION_MAJOR "${ZLIB_H}")
string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_MINOR "${ZLIB_H}")
string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_PATCH "${ZLIB_H}")
set(ZLIB_VERSION_STRING "${ZLIB_VERSION_MAJOR}.${ZLIB_VERSION_MINOR}.${ZLIB_VERSION_PATCH}")
# only append a TWEAK version if it exists:
set(ZLIB_VERSION_TWEAK "")
if ("${ZLIB_H}" MATCHES "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+).*$")
set(ZLIB_VERSION_TWEAK "${CMAKE_MATCH_1}")
set(ZLIB_VERSION_STRING "${ZLIB_VERSION_STRING}.${ZLIB_VERSION_TWEAK}")
endif ("${ZLIB_H}" MATCHES "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+).*$")
set(ZLIB_MAJOR_VERSION "${ZLIB_VERSION_MAJOR}")
set(ZLIB_MINOR_VERSION "${ZLIB_VERSION_MINOR}")
set(ZLIB_PATCH_VERSION "${ZLIB_VERSION_PATCH}")
endif (ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h")
find_library(ZLIB_LIBRARY
NAMES
z
zdll
zlib
zlib1
zlibd
PATHS
/usr/local/lib
/opt/local/lib
/sw/lib
/usr/sfw/lib/64
/usr/sfw/lib
${ZLIB_ROOT_DIR}/lib
)
mark_as_advanced(ZLIB_LIBRARY)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ZLIB DEFAULT_MSG ZLIB_INCLUDE_DIR ZLIB_LIBRARY)
#find_package_handle_standard_args(ZLIB REQUIRED_VARS ZLIB_INCLUDE_DIR ZLIB_LIBRARY
# VERSION_VAR ZLIB_VERSION_STRING)
if (ZLIB_FOUND)
set(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR})
set(ZLIB_LIBRARIES ${ZLIB_LIBRARY})
endif (ZLIB_FOUND)
endif (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
@@ -0,0 +1,21 @@
# - MACRO_ADD_COMPILE_FLAGS(target_name flag1 ... flagN)
# Copyright (c) 2006, Oswald Buddenhagen, <ossi@kde.org>
# Copyright (c) 2006, Andreas Schneider, <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ADD_COMPILE_FLAGS _target)
get_target_property(_flags ${_target} COMPILE_FLAGS)
if (_flags)
set(_flags ${_flags} ${ARGN})
else (_flags)
set(_flags ${ARGN})
endif (_flags)
set_target_properties(${_target} PROPERTIES COMPILE_FLAGS ${_flags})
endmacro (MACRO_ADD_COMPILE_FLAGS)
@@ -0,0 +1,20 @@
# - MACRO_ADD_LINK_FLAGS(target_name flag1 ... flagN)
# Copyright (c) 2006, Oswald Buddenhagen, <ossi@kde.org>
# Copyright (c) 2006, Andreas Schneider, <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ADD_LINK_FLAGS _target)
get_target_property(_flags ${_target} LINK_FLAGS)
if (_flags)
set(_flags "${_flags} ${ARGN}")
else (_flags)
set(_flags "${ARGN}")
endif (_flags)
set_target_properties(${_target} PROPERTIES LINK_FLAGS "${_flags}")
endmacro (MACRO_ADD_LINK_FLAGS)
+30
View File
@@ -0,0 +1,30 @@
# - MACRO_ADD_PLUGIN(name [WITH_PREFIX] file1 .. fileN)
#
# Create a plugin from the given source files.
# If WITH_PREFIX is given, the resulting plugin will have the
# prefix "lib", otherwise it won't.
#
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
# Copyright (c) 2006, Laurent Montel, <montel@kde.org>
# Copyright (c) 2006, Andreas Schneider, <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ADD_PLUGIN _target_NAME _with_PREFIX)
if (${_with_PREFIX} STREQUAL "WITH_PREFIX")
set(_first_SRC)
else (${_with_PREFIX} STREQUAL "WITH_PREFIX")
set(_first_SRC ${_with_PREFIX})
endif (${_with_PREFIX} STREQUAL "WITH_PREFIX")
add_library(${_target_NAME} MODULE ${_first_SRC} ${ARGN})
if (_first_SRC)
set_target_properties(${_target_NAME} PROPERTIES PREFIX "")
endif (_first_SRC)
endmacro (MACRO_ADD_PLUGIN _name _sources)
+33
View File
@@ -0,0 +1,33 @@
# - macro_copy_file(_src _dst)
# Copies a file to ${_dst} only if ${_src} is different (newer) than ${_dst}
#
# Example:
# macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/icon.png ${CMAKE_CURRENT_BINARY_DIR}/.)
# Copies file icon.png to ${CMAKE_CURRENT_BINARY_DIR} directory
#
# Copyright (c) 2006-2007 Wengo
# Copyright (c) 2006-2008 Andreas Schneider <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING file.
macro (macro_copy_file _src _dst)
# Removes all path containing .svn or CVS or CMakeLists.txt during the copy
if (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*")
if (CMAKE_VERBOSE_MAKEFILE)
message(STATUS "Copy file from ${_src} to ${_dst}")
endif (CMAKE_VERBOSE_MAKEFILE)
# Creates directory if necessary
get_filename_component(_path ${_dst} PATH)
file(MAKE_DIRECTORY ${_path})
execute_process(
COMMAND
${CMAKE_COMMAND} -E copy_if_different ${_src} ${_dst}
OUTPUT_QUIET
)
endif (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*")
endmacro (macro_copy_file)
@@ -0,0 +1,17 @@
# - MACRO_ENSURE_OUT_OF_SOURCE_BUILD(<errorMessage>)
# MACRO_ENSURE_OUT_OF_SOURCE_BUILD(<errorMessage>)
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage)
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _insource)
if (_insource)
message(SEND_ERROR "${_errorMessage}")
message(FATAL_ERROR "Remove the file CMakeCache.txt in ${CMAKE_SOURCE_DIR} first.")
endif (_insource)
endmacro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD)
+100
View File
@@ -0,0 +1,100 @@
# - Run Doxygen
#
# Adds a doxygen target that runs doxygen to generate the html
# and optionally the LaTeX API documentation.
# The doxygen target is added to the doc target as dependency.
# i.e.: the API documentation is built with:
# make doc
#
# USAGE: INCLUDE IN PROJECT
#
# set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
# include(UseDoxygen)
# Add the Doxyfile.in and UseDoxygen.cmake files to the projects source directory.
#
#
# Variables you may define are:
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored. Defaults to "doc".
#
# DOXYFILE_LATEX_DIR - Directory where the Doxygen LaTeX output is stored. Defaults to "latex".
#
# DOXYFILE_HTML_DIR - Directory where the Doxygen html output is stored. Defaults to "html".
#
#
# Copyright (c) 2009-2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
# Copyright (c) 2010 Andreas Schneider <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
macro(usedoxygen_set_default name value)
if(NOT DEFINED "${name}")
set("${name}" "${value}")
endif()
endmacro()
find_package(Doxygen)
if(DOXYGEN_FOUND)
find_file(DOXYFILE_IN
NAMES
doxy.config.in
PATHS
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_ROOT}/Modules/
NO_DEFAULT_PATH)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
endif()
if(DOXYGEN_FOUND AND DOXYFILE_IN_FOUND)
add_custom_target(doxygen ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
usedoxygen_set_default(DOXYFILE_HTML_DIR "html")
set_property(DIRECTORY APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
set(DOXYFILE_LATEX FALSE)
set(DOXYFILE_PDFLATEX FALSE)
set(DOXYFILE_DOT FALSE)
find_package(LATEX)
if(LATEX_COMPILER AND MAKEINDEX_COMPILER)
set(DOXYFILE_LATEX TRUE)
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex")
set_property(DIRECTORY APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
if(PDFLATEX_COMPILER)
set(DOXYFILE_PDFLATEX TRUE)
endif()
if(DOXYGEN_DOT_EXECUTABLE)
set(DOXYFILE_DOT TRUE)
endif()
add_custom_command(TARGET doxygen
POST_BUILD
COMMAND ${CMAKE_MAKE_PROGRAM}
WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
endif()
configure_file(${DOXYFILE_IN} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config ESCAPE_QUOTES IMMEDIATE @ONLY)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac ESCAPE_QUOTES IMMEDIATE @ONLY)
add_custom_target(doxygen-trac ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac)
endif()
get_target_property(DOC_TARGET doc TYPE)
if(NOT DOC_TARGET)
add_custom_target(doc)
endif()
add_dependencies(doc doxygen)
endif()
+148
View File
@@ -0,0 +1,148 @@
/* Name of package */
#cmakedefine PACKAGE "${APPLICATION_NAME}"
/* Version number of package */
#cmakedefine VERSION "${APPLICATION_VERSION}"
#cmakedefine LOCALEDIR "${LOCALE_INSTALL_DIR}"
#cmakedefine DATADIR "${DATADIR}"
#cmakedefine LIBDIR "${LIBDIR}"
#cmakedefine PLUGINDIR "${PLUGINDIR}"
#cmakedefine SYSCONFDIR "${SYSCONFDIR}"
#cmakedefine BINARYDIR "${BINARYDIR}"
#cmakedefine SOURCEDIR "${SOURCEDIR}"
/************************** HEADER FILES *************************/
/* Define to 1 if you have the <argp.h> header file. */
#cmakedefine HAVE_ARGP_H 1
/* Define to 1 if you have the <pty.h> header file. */
#cmakedefine HAVE_PTY_H 1
/* Define to 1 if you have the <termios.h> header file. */
#cmakedefine HAVE_TERMIOS_H 1
/* Define to 1 if you have the <openssl/aes.h> header file. */
#cmakedefine HAVE_OPENSSL_AES_H 1
/* Define to 1 if you have the <wspiapi.h> header file. */
#cmakedefine HAVE_WSPIAPI_H 1
/* Define to 1 if you have the <openssl/blowfish.h> header file. */
#cmakedefine HAVE_OPENSSL_BLOWFISH_H 1
/* Define to 1 if you have the <openssl/des.h> header file. */
#cmakedefine HAVE_OPENSSL_DES_H 1
/* Define to 1 if you have the <openssl/ecdh.h> header file. */
#cmakedefine HAVE_OPENSSL_ECDH_H 1
/* Define to 1 if you have the <openssl/ec.h> header file. */
#cmakedefine HAVE_OPENSSL_EC_H 1
/* Define to 1 if you have the <openssl/ecdsa.h> header file. */
#cmakedefine HAVE_OPENSSL_ECDSA_H 1
/* Define to 1 if you have the <pthread.h> header file. */
#cmakedefine HAVE_PTHREAD_H 1
/* Define to 1 if you have eliptic curve cryptography in openssl */
#cmakedefine HAVE_OPENSSL_ECC 1
/* Define to 1 if you have eliptic curve cryptography in gcrypt */
#cmakedefine HAVE_GCRYPT_ECC 1
/* Define to 1 if you have eliptic curve cryptography */
#cmakedefine HAVE_ECC 1
/*************************** FUNCTIONS ***************************/
/* Define to 1 if you have the `snprintf' function. */
#cmakedefine HAVE_SNPRINTF 1
/* Define to 1 if you have the `_snprintf' function. */
#cmakedefine HAVE__SNPRINTF 1
/* Define to 1 if you have the `_snprintf_s' function. */
#cmakedefine HAVE__SNPRINTF_S 1
/* Define to 1 if you have the `vsnprintf' function. */
#cmakedefine HAVE_VSNPRINTF 1
/* Define to 1 if you have the `_vsnprintf' function. */
#cmakedefine HAVE__VSNPRINTF 1
/* Define to 1 if you have the `_vsnprintf_s' function. */
#cmakedefine HAVE__VSNPRINTF_S 1
/* Define to 1 if you have the `strncpy' function. */
#cmakedefine HAVE_STRNCPY 1
/* Define to 1 if you have the `cfmakeraw' function. */
#cmakedefine HAVE_CFMAKERAW 1
/* Define to 1 if you have the `getaddrinfo' function. */
#cmakedefine HAVE_GETADDRINFO 1
/* Define to 1 if you have the `poll' function. */
#cmakedefine HAVE_POLL 1
/* Define to 1 if you have the `select' function. */
#cmakedefine HAVE_SELECT 1
/* Define to 1 if you have the `clock_gettime' function. */
#cmakedefine HAVE_CLOCK_GETTIME 1
/* Define to 1 if you have the `ntohll' function. */
#cmakedefine HAVE_NTOHLL 1
/* Define to 1 if you have the `htonll' function. */
#cmakedefine HAVE_HTONLL 1
/* Define to 1 if you have the `strtoull' function. */
#cmakedefine HAVE_STRTOULL 1
/* Define to 1 if you have the `__strtoull' function. */
#cmakedefine HAVE___STRTOULL 1
/*************************** LIBRARIES ***************************/
/* Define to 1 if you have the `crypto' library (-lcrypto). */
#cmakedefine HAVE_LIBCRYPTO 1
/* Define to 1 if you have the `gcrypt' library (-lgcrypt). */
#cmakedefine HAVE_LIBGCRYPT 1
/* Define to 1 if you have the `pthread' library (-lpthread). */
#cmakedefine HAVE_PTHREAD 1
/**************************** OPTIONS ****************************/
/* Define to 1 if you want to enable ZLIB */
#cmakedefine WITH_ZLIB 1
/* Define to 1 if you want to enable SFTP */
#cmakedefine WITH_SFTP 1
/* Define to 1 if you want to enable SSH1 */
#cmakedefine WITH_SSH1 1
/* Define to 1 if you want to enable server support */
#cmakedefine WITH_SERVER 1
/* Define to 1 if you want to enable debug output for crypto functions */
#cmakedefine DEBUG_CRYPTO 1
/* Define to 1 if you want to enable pcap output support (experimental) */
#cmakedefine WITH_PCAP 1
/* Define to 1 if you want to enable calltrace debug output */
#cmakedefine DEBUG_CALLTRACE 1
/*************************** ENDIAN *****************************/
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#cmakedefine WORDS_BIGENDIAN 1
+5
View File
@@ -0,0 +1,5 @@
#
# Build the documentation
#
include(UseDoxygen OPTIONAL)
+1
View File
@@ -0,0 +1 @@
<!-- Doxygen TracFooter -->
+4
View File
@@ -0,0 +1,4 @@
<!-- Doxygen TracHeader -->
<style>@import url(/chrome/site/doxygen.css);</style>
<style>@import url(/chrome/site/tabs.css);</style>
<!-- /Doxygen TracHeader -->
+375
View File
@@ -0,0 +1,375 @@
/**
@page libssh_tutor_authentication Chapter 2: A deeper insight on authentication
@section authentication_details A deeper insight on authentication
In our guided tour, we merely mentioned that the user needed to authenticate.
We didn't explain much in detail how that was supposed to happen.
This chapter explains better the four authentication methods: with public keys,
with a password, with challenges and responses (keyboard-interactive), and with
no authentication at all.
If your software is supposed to connect to an arbitrary server, then you
might need to support all authentication methods. If your software will
connect only to a given server, then it might be enough for your software
to support only the authentication methods used by that server. If you are
the administrator of the server, it might be your call to choose those
authentication methods.
It is not the purpose of this document to review in detail the advantages
and drawbacks of each authentication method. You are therefore invited
to read the abundant documentation on this topic to fully understand the
advantages and security risks linked to each method.
@subsection pubkeys Authenticating with public keys
libssh is fully compatible with the openssh public and private keys. You
can either use the automatic public key authentication method provided by
libssh, or roll your own using the public key functions.
The process of authenticating by public key to a server is the following:
- you scan a list of files that contain public keys. each key is sent to
the SSH server, until the server acknowledges a key (a key it knows can be
used to authenticate the user).
- then, you retrieve the private key for this key and send a message
proving that you know that private key.
The function ssh_userauth_autopubkey() does this using the available keys in
"~/.ssh/". The return values are the following:
- SSH_AUTH_ERROR: some serious error happened during authentication
- SSH_AUTH_DENIED: no key matched
- SSH_AUTH_SUCCESS: you are now authenticated
- SSH_AUTH_PARTIAL: some key matched but you still have to provide an other
mean of authentication (like a password).
The ssh_userauth_publickey_auto() function also tries to authenticate using the
SSH agent, if you have one running, or the "none" method otherwise.
If you wish to authenticate with public key by your own, follow these steps:
- Retrieve the public key with ssh_import_pubkey_file().
- Offer the public key to the SSH server using ssh_userauth_try_publickey().
If the return value is SSH_AUTH_SUCCESS, the SSH server accepts to
authenticate using the public key and you can go to the next step.
- Retrieve the private key, using the ssh_pki_import_privkey_file() function.
If a passphrase is needed, either the passphrase specified as argument or
a callback will be used.
- Authenticate using ssh_userauth_publickey() with your private key.
- Do not forget cleaning up memory using ssh_key_free().
Here is a minimalistic example of public key authentication:
@code
int authenticate_pubkey(ssh_session session)
{
int rc;
rc = ssh_userauth_publickey_auto(session, NULL);
if (rc == SSH_AUTH_ERROR)
{
fprintf(stderr, "Authentication failed: %s\n",
ssh_get_error(session));
return SSH_AUTH_ERROR;
}
return rc;
}
@endcode
@see ssh_userauth_publickey_auto()
@see ssh_userauth_try_publickey()
@see ssh_userauth_publickey()
@see ssh_pki_import_pubkey_file()
@see ssh_pki_import_privkey_file()
@see ssh_key_free()
@subsection password Authenticating with a password
The function ssh_userauth_password() serves the purpose of authenticating
using a password. It will return SSH_AUTH_SUCCESS if the password worked,
or one of other constants otherwise. It's your work to ask the password
and to deallocate it in a secure manner.
If your server complains that the password is wrong, but you can still
authenticate using openssh's client (issuing password), it's probably
because openssh only accept keyboard-interactive. Switch to
keyboard-interactive authentication, or try to configure plain text passwords
on the SSH server.
Here is a small example of password authentication:
@code
int authenticate_password(ssh_session session)
{
char *password;
int rc;
password = getpass("Enter your password: ");
rc = ssh_userauth_password(session, NULL, password);
if (rc == SSH_AUTH_ERROR)
{
fprintf(stderr, "Authentication failed: %s\n",
ssh_get_error(session));
return SSH_AUTH_ERROR;
}
return rc;
}
@endcode
@see ssh_userauth_password
@subsection keyb_int The keyboard-interactive authentication method
The keyboard-interactive method is, as its name tells, interactive. The
server will issue one or more challenges that the user has to answer,
until the server takes an authentication decision.
ssh_userauth_kbdint() is the the main keyboard-interactive function.
It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL,
SSH_AUTH_ERROR, or SSH_AUTH_INFO, depending on the result of the request.
The keyboard-interactive authentication method of SSH2 is a feature that
permits the server to ask a certain number of questions in an interactive
manner to the client, until it decides to accept or deny the login.
To begin, you call ssh_userauth_kbdint() (just set user and submethods to
NULL) and store the answer.
If the answer is SSH_AUTH_INFO, it means that the server has sent a few
questions that you should ask the user. You can retrieve these questions
with the following functions: ssh_userauth_kbdint_getnprompts(),
ssh_userauth_kbdint_getname(), ssh_userauth_kbdint_getinstruction(), and
ssh_userauth_kbdint_getprompt().
Set the answer for each question in the challenge using
ssh_userauth_kbdint_setanswer().
Then, call again ssh_userauth_kbdint() and start the process again until
these functions returns something else than SSH_AUTH_INFO.
Here are a few remarks:
- Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS.
- The server can send an empty question set (this is the default behavior
on my system) after you have sent the answers to the first questions.
You must still parse the answer, it might contain some
message from the server saying hello or such things. Just call
ssh_userauth_kbdint() until needed.
- The meaning of "name", "prompt", "instruction" may be a little
confusing. An explanation is given in the RFC section that follows.
Here is a little note about how to use the information from
keyboard-interactive authentication, coming from the RFC itself (rfc4256):
@verbatim
3.3 User Interface Upon receiving a request message, the client SHOULD
prompt the user as follows: A command line interface (CLI) client SHOULD
print the name and instruction (if non-empty), adding newlines. Then for
each prompt in turn, the client SHOULD display the prompt and read the
user input.
A graphical user interface (GUI) client has many choices on how to prompt
the user. One possibility is to use the name field (possibly prefixed
with the application's name) as the title of a dialog window in which
the prompt(s) are presented. In that dialog window, the instruction field
would be a text message, and the prompts would be labels for text entry
fields. All fields SHOULD be presented to the user, for example an
implementation SHOULD NOT discard the name field because its windows lack
titles; it SHOULD instead find another way to display this information. If
prompts are presented in a dialog window, then the client SHOULD NOT
present each prompt in a separate window.
All clients MUST properly handle an instruction field with embedded
newlines. They SHOULD also be able to display at least 30 characters for
the name and prompts. If the server presents names or prompts longer than 30
characters, the client MAY truncate these fields to the length it can
display. If the client does truncate any fields, there MUST be an obvious
indication that such truncation has occured.
The instruction field SHOULD NOT be truncated. Clients SHOULD use control
character filtering as discussed in [SSH-ARCH] to avoid attacks by
including terminal control characters in the fields to be displayed.
For each prompt, the corresponding echo field indicates whether or not
the user input should be echoed as characters are typed. Clients SHOULD
correctly echo/mask user input for each prompt independently of other
prompts in the request message. If a client does not honor the echo field
for whatever reason, then the client MUST err on the side of
masking input. A GUI client might like to have a checkbox toggling
echo/mask. Clients SHOULD NOT add any additional characters to the prompt
such as ": " (colon-space); the server is responsible for supplying all
text to be displayed to the user. Clients MUST also accept empty responses
from the user and pass them on as empty strings.
@endverbatim
The following example shows how to perform keyboard-interactive authentication:
@code
int authenticate_kbdint(ssh_session session)
{
int rc;
rc = ssh_userauth_kbdint(session, NULL, NULL);
while (rc == SSH_AUTH_INFO)
{
const char *name, *instruction;
int nprompts, iprompt;
name = ssh_userauth_kbdint_getname(session);
instruction = ssh_userauth_kbdint_getinstruction(session);
nprompts = ssh_userauth_kbdint_getnprompts(session);
if (strlen(name) > 0)
printf("%s\n", name);
if (strlen(instruction) > 0)
printf("%s\n", instruction);
for (iprompt = 0; iprompt < nprompts; iprompt++)
{
const char *prompt;
char echo;
prompt = ssh_userauth_kbdint_getprompt(session, iprompt, &echo);
if (echo)
{
char buffer[128], *ptr;
printf("%s", prompt);
if (fgets(buffer, sizeof(buffer), stdin) == NULL)
return SSH_AUTH_ERROR;
buffer[sizeof(buffer) - 1] = '\0';
if ((ptr = strchr(buffer, '\n')) != NULL)
*ptr = '\0';
if (ssh_userauth_kbdint_setanswer(session, iprompt, buffer) < 0)
return SSH_AUTH_ERROR;
memset(buffer, 0, strlen(buffer));
}
else
{
char *ptr;
ptr = getpass(prompt);
if (ssh_userauth_kbdint_setanswer(session, iprompt, ptr) < 0)
return SSH_AUTH_ERROR;
}
}
rc = ssh_userauth_kbdint(session, NULL, NULL);
}
return rc;
}
@endcode
@see ssh_userauth_kbdint()
@see ssh_userauth_kbdint_getnprompts()
@see ssh_userauth_kbdint_getname()
@see ssh_userauth_kbdint_getinstruction()
@see ssh_userauth_kbdint_getprompt()
@see ssh_userauth_kbdint_setanswer()
@subsection none Authenticating with "none" method
The primary purpose of the "none" method is to get authenticated **without**
any credential. Don't do that, use one of the other authentication methods,
unless you really want to grant anonymous access.
If the account has no password, and if the server is configured to let you
pass, ssh_userauth_none() might answer SSH_AUTH_SUCCESS.
The following example shows how to perform "none" authentication:
@code
int authenticate_kbdint(ssh_session session)
{
int rc;
rc = ssh_userauth_none(session, NULL, NULL);
return rc;
}
@endcode
@subsection auth_list Getting the list of supported authentications
You are not meant to choose a given authentication method, you can
let the server tell you which methods are available. Once you know them,
you try them one after the other.
The following example shows how to get the list of available authentication
methods with ssh_userauth_list() and how to use the result:
@code
int test_several_auth_methods(ssh_session session)
{
int method, rc;
rc = ssh_userauth_none(session, NULL, NULL);
if (rc != SSH_AUTH_SUCCESS) {
return rc;
}
method = ssh_userauth_list(session, NULL);
if (method & SSH_AUTH_METHOD_NONE)
{ // For the source code of function authenticate_none(),
// refer to the corresponding example
rc = authenticate_none(session);
if (rc == SSH_AUTH_SUCCESS) return rc;
}
if (method & SSH_AUTH_METHOD_PUBLICKEY)
{ // For the source code of function authenticate_pubkey(),
// refer to the corresponding example
rc = authenticate_pubkey(session);
if (rc == SSH_AUTH_SUCCESS) return rc;
}
if (method & SSH_AUTH_METHOD_INTERACTIVE)
{ // For the source code of function authenticate_kbdint(),
// refer to the corresponding example
rc = authenticate_kbdint(session);
if (rc == SSH_AUTH_SUCCESS) return rc;
}
if (method & SSH_AUTH_METHOD_PASSWORD)
{ // For the source code of function authenticate_password(),
// refer to the corresponding example
rc = authenticate_password(session);
if (rc == SSH_AUTH_SUCCESS) return rc;
}
return SSH_AUTH_ERROR;
}
@endcode
@subsection banner Getting the banner
The SSH server might send a banner, which you can retrieve with
ssh_get_issue_banner(), then display to the user.
The following example shows how to retrieve and dispose the issue banner:
@code
int display_banner(ssh_session session)
{
int rc;
char *banner;
/*
*** Does not work without calling ssh_userauth_none() first ***
*** That will be fixed ***
*/
rc = ssh_userauth_none(session, NULL);
if (rc == SSH_AUTH_ERROR)
return rc;
banner = ssh_get_issue_banner(session);
if (banner)
{
printf("%s\n", banner);
free(banner);
}
return rc;
}
@endcode
*/
+94
View File
@@ -0,0 +1,94 @@
/**
@page libssh_tutor_command Chapter 4: Passing a remote command
@section remote_command Passing a remote command
Previous chapter has shown how to open a full shell session, with an attached
terminal or not. If you only need to execute a command on the remote end,
you don't need all that complexity.
The method described here is suited for executing only one remote command.
If you need to issue several commands in a row, you should consider using
a non-interactive remote shell, as explained in previous chapter.
@see shell
@subsection exec_remote Executing a remote command
The first steps for executing a remote command are identical to those
for opening remote shells. You first need a SSH channel, and then
a SSH session that uses this channel:
@code
int show_remote_files(ssh_session session)
{
ssh_channel channel;
int rc;
channel = ssh_channel_new(session);
if (channel == NULL) return SSH_ERROR;
rc = ssh_channel_open_session(channel);
if (rc != SSH_OK)
{
ssh_channel_free(channel);
return rc;
}
@endcode
Once a session is open, you can start the remote command with
ssh_channel_request_exec():
@code
rc = ssh_channel_request_exec(channel, "ls -l");
if (rc != SSH_OK)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return rc;
}
@endcode
If the remote command displays data, you get them with ssh_channel_read().
This function returns the number of bytes read. If there is no more
data to read on the channel, this function returns 0, and you can go to next step.
If an error has been encountered, it returns a negative value:
@code
char buffer[256];
unsigned int nbytes;
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0)
{
if (fwrite(buffer, 1, nbytes, stdout) != nbytes)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if (nbytes < 0)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
@endcode
Once you read the result of the remote command, you send an
end-of-file to the channel, close it, and free the memory
that it used:
@code
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_OK;
}
@endcode
*/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+229
View File
@@ -0,0 +1,229 @@
/**
@page libssh_tutor_forwarding Chapter 7: Forwarding connections (tunnel)
@section forwarding_connections Forwarding connections
Port forwarding comes in SSH protocol in two different flavours:
direct or reverse port forwarding. Direct port forwarding is also
named local port forwardind, and reverse port forwarding is also called
remote port forwarding. SSH also allows X11 tunnels.
@subsection forwarding_direct Direct port forwarding
Direct port forwarding is from client to server. The client opens a tunnel,
and forwards whatever data to the server. Then, the server connects to an
end point. The end point can reside on another machine or on the SSH
server itself.
Example of use of direct port forwarding:
@verbatim
Mail client application Google Mail
| ^
5555 (arbitrary) |
| 143 (IMAP2)
V |
SSH client =====> SSH server
Legend:
--P-->: port connexion through port P
=====>: SSH tunnel
@endverbatim
A mail client connects to port 5555 of a client. An encrypted tunnel is
established to the server. The server connects to port 143 of Google Mail (the
end point). Now the local mail client can retreive mail.
@subsection forwarding_reverse Reverse port forwarding
The reverse forwarding is slightly different. It goes from server to client,
even though the client has the initiative of establishing the tunnel.
Once the tunnel is established, the server will listen on a port. Whenever
a connection to this port is made, the server forwards the data to the client.
Example of use of reverse port forwarding:
@verbatim
Local mail server Mail client application
^ |
| 5555 (arbitrary)
143 (IMAP2) |
| V
SSH client <===== SSH server
Legend:
--P-->: port connexion through port P
=====>: SSH tunnel
@endverbatim
In this example, the SSH client establishes the tunnel,
but it is used to forward the connections established at
the server to the client.
@subsection forwarding_x11 X11 tunnels
X11 tunnels allow a remote application to display locally.
Example of use of X11 tunnels:
@verbatim
Local display Graphical application
(X11 server) (X11 client)
^ |
| V
SSH client <===== SSH server
Legend:
----->: X11 connection through X11 display number
=====>: SSH tunnel
@endverbatim
The SSH tunnel is established by the client.
How to establish X11 tunnels with libssh has already been described in
this tutorial.
@see x11
@subsection libssh_direct Doing direct port forwarding with libssh
To do direct port forwarding, call function ssh_channel_open_forward():
- you need a separate channel for the tunnel as first parameter;
- second and third parameters are the remote endpoint;
- fourth and fifth parameters are sent to the remote server
so that they can be logged on that server.
If you don't plan to forward the data you will receive to any local port,
just put fake values like "localhost" and 5555 as your local host and port.
The example below shows how to open a direct channel that would be
used to retrieve google's home page from the remote SSH server.
@code
int direct_forwarding(ssh_session session)
{
ssh_channel forwarding_channel;
int rc;
char *http_get = "GET / HTTP/1.1\nHost: www.google.com\n\n";
int nbytes, nwritten;
forwarding_channel = ssh_channel_new(session);
if (forwarding_channel == NULL) {
return rc;
}
rc = ssh_channel_open_forward(forwarding_channel,
"www.google.com", 80,
"localhost", 5555);
if (rc != SSH_OK)
{
ssh_channel_free(forwarding_channel);
return rc;
}
nbytes = strlen(http_get);
nwritten = ssh_channel_write(forwarding_channel,
http_get,
nbytes);
if (nbytes != nwritten)
{
ssh_channel_free(forwarding_channel);
return SSH_ERROR;
}
...
ssh_channel_free(forwarding_channel);
return SSH_OK;
}
@endcode
The data sent by Google can be retrieved for example with ssh_select()
and ssh_channel_read(). Goggle's home page can then be displayed on the
local SSH client, saved into a local file, made available on a local port,
or whatever use you have for it.
@subsection libssh_reverse Doing reverse port forwarding with libssh
To do reverse port forwarding, call ssh_forward_listen(),
then ssh_forward_accept().
When you call ssh_forward_listen(), you can let the remote server
chose the non-priviledged port it should listen to. Otherwise, you can chose
your own priviledged or non-priviledged port. Beware that you should have
administrative priviledges on the remote server to open a priviledged port
(port number < 1024).
Below is an example of a very rough web server waiting for connections on port
8080 of remote SSH server. The incoming connections are passed to the
local libssh application, which handles them:
@code
int web_server(ssh_session session)
{
int rc;
ssh_channel channel;
char buffer[256];
int nbytes, nwritten;
char *helloworld = ""
"HTTP/1.1 200 OK\n"
"Content-Type: text/html\n"
"Content-Length: 113\n"
"\n"
"<html>\n"
" <head>\n"
" <title>Hello, World!</title>\n"
" </head>\n"
" <body>\n"
" <h1>Hello, World!</h1>\n"
" </body>\n"
"</html>\n";
rc = ssh_forward_listen(session, NULL, 8080, NULL);
if (rc != SSH_OK)
{
fprintf(stderr, "Error opening remote port: %s\n",
ssh_get_error(session));
return rc;
}
channel = ssh_forward_accept(session, 60000);
if (channel == NULL)
{
fprintf(stderr, "Error waiting for incoming connection: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
while (1)
{
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
if (nbytes < 0)
{
fprintf(stderr, "Error reading incoming data: %s\n",
ssh_get_error(session));
ssh_channel_send_eof(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
if (strncmp(buffer, "GET /", 5)) continue;
nbytes = strlen(helloworld);
nwritten = ssh_channel_write(channel, helloworld, nbytes);
if (nwritten != nbytes)
{
fprintf(stderr, "Error sending answer: %s\n",
ssh_get_error(session));
ssh_channel_send_eof(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
printf("Sent answer\n");
}
ssh_channel_send_eof(channel);
ssh_channel_free(channel);
return SSH_OK;
}
@endcode
*/
+455
View File
@@ -0,0 +1,455 @@
/**
@page libssh_tutor_guided_tour Chapter 1: A typical SSH session
@section ssh_session A typical SSH session
A SSH session goes through the following steps:
- Before connecting to the server, you can set up if you wish one or other
server public key authentication, i.e. DSA or RSA. You can choose
cryptographic algorithms you trust and compression algorithms if any. You
must of course set up the hostname.
- The connection is established. A secure handshake is made, and resulting from
it, a public key from the server is gained. You MUST verify that the public
key is legitimate, using for instance the MD5 fingerprint or the known hosts
file.
- The client must authenticate: the classical ways are password, or
public keys (from dsa and rsa key-pairs generated by openssh).
If a SSH agent is running, it is possible to use it.
- Now that the user has been authenticated, you must open one or several
channels. Channels are different subways for information into a single ssh
connection. Each channel has a standard stream (stdout) and an error stream
(stderr). You can theoretically open an infinity of channels.
- With the channel you opened, you can do several things:
- Execute a single command.
- Open a shell. You may want to request a pseudo-terminal before.
- Invoke the sftp subsystem to transfer files.
- Invoke the scp subsystem to transfer files.
- Invoke your own subsystem. This is outside the scope of this document,
but can be done.
- When everything is finished, just close the channels, and then the connection.
The sftp and scp subsystems use channels, but libssh hides them to
the programmer. If you want to use those subsystems, instead of a channel,
you'll usually open a "sftp session" or a "scp session".
@subsection setup Creating the session and setting options
The most important object in a SSH connection is the SSH session. In order
to allocate a new SSH session, you use ssh_new(). Don't forget to
always verify that the allocation successed.
@code
#include <libssh/libssh.h>
#include <stdlib.h>
int main()
{
ssh_session my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
...
ssh_free(my_ssh_session);
}
@endcode
libssh follows the allocate-it-deallocate-it pattern. Each object that you allocate
using xxxxx_new() must be deallocated using xxxxx_free(). In this case, ssh_new()
does the allocation and ssh_free() does the contrary.
The ssh_options_set() function sets the options of the session. The most important options are:
- SSH_OPTIONS_HOST: the name of the host you want to connect to
- SSH_OPTIONS_PORT: the used port (default is port 22)
- SSH_OPTIONS_USER: the system user under which you want to connect
- SSH_OPTIONS_LOG_VERBOSITY: the quantity of messages that are printed
The complete list of options can be found in the documentation of ssh_options_set().
The only mandatory option is SSH_OPTIONS_HOST. If you don't use SSH_OPTIONS_USER,
the local username of your account will be used.
Here is a small example of how to use it:
@code
#include <libssh/libssh.h>
#include <stdlib.h>
int main()
{
ssh_session my_ssh_session;
int verbosity = SSH_LOG_PROTOCOL;
int port = 22;
my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port);
...
ssh_free(my_ssh_session);
}
@endcode
Please notice that all parameters are passed to ssh_options_set() as pointers,
even if you need to set an integer value.
@see ssh_new
@see ssh_free
@see ssh_options_set
@see ssh_options_parse_config
@see ssh_options_copy
@see ssh_options_getopt
@subsection connect Connecting to the server
Once all settings have been made, you can connect using ssh_connect(). That
function will return SSH_OK if the connection worked, SSH_ERROR otherwise.
You can get the English error string with ssh_get_error() in order to show the
user what went wrong. Then, use ssh_disconnect() when you want to stop
the session.
Here's an example:
@code
#include <libssh/libssh.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
ssh_session my_ssh_session;
int rc;
my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK)
{
fprintf(stderr, "Error connecting to localhost: %s\n",
ssh_get_error(my_ssh_session));
exit(-1);
}
...
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
}
@endcode
@subsection serverauth Authenticating the server
Once you're connected, the following step is mandatory: you must check that the server
you just connected to is known and safe to use (remember, SSH is about security and
authentication).
There are two ways of doing this:
- The first way (recommended) is to use the ssh_is_server_known()
function. This function will look into the known host file
(~/.ssh/known_hosts on UNIX), look for the server hostname's pattern,
and determine whether this host is present or not in the list.
- The second way is to use ssh_get_pubkey_hash() to get a binary version
of the public key hash value. You can then use your own database to check
if this public key is known and secure.
You can also use the ssh_get_pubkey_hash() to show the public key hash
value to the user, in case he knows what the public key hash value is
(some paranoid people write their public key hash values on paper before
going abroad, just in case ...).
If the remote host is being used to for the first time, you can ask the user whether
he/she trusts it. Once he/she concluded that the host is valid and worth being
added in the known hosts file, you use ssh_write_knownhost() to register it in
the known hosts file, or any other way if you use your own database.
The following example is part of the examples suite available in the
examples/ directory:
@code
#include <errno.h>
#include <string.h>
int verify_knownhost(ssh_session session)
{
int state, hlen;
unsigned char *hash = NULL;
char *hexa;
char buf[10];
state = ssh_is_server_known(session);
hlen = ssh_get_pubkey_hash(session, &hash);
if (hlen < 0)
return -1;
switch (state)
{
case SSH_SERVER_KNOWN_OK:
break; /* ok */
case SSH_SERVER_KNOWN_CHANGED:
fprintf(stderr, "Host key for server changed: it is now:\n");
ssh_print_hexa("Public key hash", hash, hlen);
fprintf(stderr, "For security reasons, connection will be stopped\n");
free(hash);
return -1;
case SSH_SERVER_FOUND_OTHER:
fprintf(stderr, "The host key for this server was not found but an other"
"type of key exists.\n");
fprintf(stderr, "An attacker might change the default server key to"
"confuse your client into thinking the key does not exist\n");
free(hash);
return -1;
case SSH_SERVER_FILE_NOT_FOUND:
fprintf(stderr, "Could not find known host file.\n");
fprintf(stderr, "If you accept the host key here, the file will be"
"automatically created.\n");
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
case SSH_SERVER_NOT_KNOWN:
hexa = ssh_get_hexa(hash, hlen);
fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
fprintf(stderr, "Public key hash: %s\n", hexa);
free(hexa);
if (fgets(buf, sizeof(buf), stdin) == NULL)
{
free(hash);
return -1;
}
if (strncasecmp(buf, "yes", 3) != 0)
{
free(hash);
return -1;
}
if (ssh_write_knownhost(session) < 0)
{
fprintf(stderr, "Error %s\n", strerror(errno));
free(hash);
return -1;
}
break;
case SSH_SERVER_ERROR:
fprintf(stderr, "Error %s", ssh_get_error(session));
free(hash);
return -1;
}
free(hash);
return 0;
}
@endcode
@see ssh_connect
@see ssh_disconnect
@see ssh_get_error
@see ssh_get_error_code
@see ssh_get_pubkey_hash
@see ssh_is_server_known
@see ssh_write_knownhost
@subsection auth Authenticating the user
The authentication process is the way a service provider can identify a
user and verify his/her identity. The authorization process is about enabling
the authenticated user the access to ressources. In SSH, the two concepts
are linked. After authentication, the server can grant the user access to
several ressources such as port forwarding, shell, sftp subsystem, and so on.
libssh supports several methods of authentication:
- "none" method. This method allows to get the available authentications
methods. It also gives the server a chance to authenticate the user with
just his/her login. Some very old hardware uses this feature to fallback
the user on a "telnet over SSH" style of login.
- password method. A password is sent to the server, which accepts it or not.
- keyboard-interactive method. The server sends several challenges to the
user, who must answer correctly. This makes possible the authentication
via a codebook for instance ("give code at 23:R on page 3").
- public key method. The host knows the public key of the user, and the
user must prove he knows the associated private key. This can be done
manually, or delegated to the SSH agent as we'll see later.
All these methods can be combined. You can for instance force the user to
authenticate with at least two of the authentication methods. In that case,
one speaks of "Partial authentication". A partial authentication is a
response from authentication functions stating that your credential was
accepted, but yet another one is required to get in.
The example below shows an authentication with password:
@code
#include <libssh/libssh.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
ssh_session my_ssh_session;
int rc;
char *password;
// Open session and set options
my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
// Connect to server
rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK)
{
fprintf(stderr, "Error connecting to localhost: %s\n",
ssh_get_error(my_ssh_session));
ssh_free(my_ssh_session);
exit(-1);
}
// Verify the server's identity
// For the source code of verify_knowhost(), check previous example
if (verify_knownhost(my_ssh_session) < 0)
{
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
exit(-1);
}
// Authenticate ourselves
password = getpass("Password: ");
rc = ssh_userauth_password(my_ssh_session, NULL, password);
if (rc != SSH_AUTH_SUCCESS)
{
fprintf(stderr, "Error authenticating with password: %s\n",
ssh_get_error(my_ssh_session));
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
exit(-1);
}
...
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
}
@endcode
@see @ref authentication_details
@subsection using_ssh Doing something
At this point, the authenticity of both server and client is established.
Time has come to take advantage of the many possibilities offered by the SSH
protocol: execute a remote command, open remote shells, transfer files,
forward ports, etc.
The example below shows how to execute a remote command:
@code
int show_remote_processes(ssh_session session)
{
ssh_channel channel;
int rc;
char buffer[256];
unsigned int nbytes;
channel = ssh_channel_new(session);
if (channel == NULL)
return SSH_ERROR;
rc = ssh_channel_open_session(channel);
if (rc != SSH_OK)
{
ssh_channel_free(channel);
return rc;
}
rc = ssh_channel_request_exec(channel, "ps aux");
if (rc != SSH_OK)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return rc;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0)
{
if (write(1, buffer, nbytes) != nbytes)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if (nbytes < 0)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_OK;
}
@endcode
@see @ref opening_shell
@see @ref remote_command
@see @ref sftp_subsystem
@see @ref scp_subsystem
@subsection errors Handling the errors
All the libssh functions which return an error value also set an English error message
describing the problem.
Error values are typically SSH_ERROR for integer values, or NULL for pointers.
The function ssh_get_error() returns a pointer to the static error message.
ssh_error_code() returns the error code number : SSH_NO_ERROR,
SSH_REQUEST_DENIED, SSH_INVALID_REQUEST, SSH_CONNECTION_LOST, SSH_FATAL,
or SSH_INVALID_DATA. SSH_REQUEST_DENIED means the ssh server refused your
request, but the situation is recoverable. The others mean something happened
to the connection (some encryption problems, server problems, ...).
SSH_INVALID_REQUEST means the library got some garbage from server, but
might be recoverable. SSH_FATAL means the connection has an important
problem and isn't probably recoverable.
Most of time, the error returned are SSH_FATAL, but some functions
(generaly the ssh_request_xxx ones) may fail because of server denying request.
In these cases, SSH_REQUEST_DENIED is returned.
ssh_get_error() and ssh_get_error_code() take a ssh_session as a parameter.
That's for thread safety, error messages that can be attached to a session
aren't static anymore. Any error that happens during ssh_options_xxx()
or ssh_connect() (i.e., outside of any session) can be retrieved by
giving NULL as argument.
The SFTP subsystem has its own error codes, in addition to libssh ones.
*/
+49
View File
@@ -0,0 +1,49 @@
/**
@page libssh_tutorial The Tutorial
@section introduction Introduction
libssh is a C library that enables you to write a program that uses the
SSH protocol. With it, you can remotely execute programs, transfer
files, or use a secure and transparent tunnel for your remote programs.
The SSH protocol is encrypted, ensures data integrity, and provides strong
means of authenticating both the server of the client. The library hides
a lot of technical details from the SSH protocol, but this does not
mean that you should not try to know about and understand these details.
libssh is a Free Software / Open Source project. The libssh library
is distributed under LGPL license. The libssh project has nothing to do with
"libssh2", which is a completly different and independant project.
libssh can run on top of either libgcrypt or libcrypto,
two general-purpose cryptographic libraries.
This tutorial concentrates for its main part on the "client" side of libssh.
To learn how to accept incoming SSH connexions (how to write a SSH server),
you'll have to jump to the end of this document.
This tutorial describes libssh version 0.5.0. This version is a little different
from the 0.4.X series. However, the examples should work with
little changes on versions like 0.4.2 and later.
Table of contents:
@subpage libssh_tutor_guided_tour
@subpage libssh_tutor_authentication
@subpage libssh_tutor_shell
@subpage libssh_tutor_command
@subpage libssh_tutor_sftp
@subpage libssh_tutor_scp
@subpage libssh_tutor_forwarding
@subpage libssh_tutor_threads
@subpage libssh_tutor_todo
*/
+24
View File
@@ -0,0 +1,24 @@
/**
@page libssh_linking The Linking HowTo
@section dynamic Dynamic Linking
On UNIX and Windows systems its the same, you need at least the libssh.h
header file and the libssh shared library.
@section static Static Linking
@warning <b>The libssh library is licensed under the LGPL! Make sure you
understand what this means to your codebase if you want to distribute
binaries and link statically against LGPL code!</b>
On UNIX systems linking against the static version of the library is the
same as linking against the shared library. Both have the same name. Some
build system require to use the full path to the static library.
On Windows you need to define LIBSSH_STATIC in the compiler command
line. This is required cause the dynamic library needs to specify the
dllimport attribute.
*/
+211
View File
@@ -0,0 +1,211 @@
/**
@mainpage
This is the online reference for developing with the libssh library. It
documents the libssh C API and the C++ wrapper.
@section main-linking Linking
We created a small howto how to link libssh against your application, read
@subpage libssh_linking.
@section main-tutorial Tutorial
You should start by reading @subpage libssh_tutorial, then reading the documentation of
the interesting functions as you go.
@section main-features Features
The libssh library provides:
- Full C library functions for manipulating a client-side SSH connection
- SSH2 and SSH1 protocol compliant
- Fully configurable sessions
- Server support
- SSH agent authentication support
- Support for AES-128, AES-192, AES-256, Blowfish, 3DES in CBC mode, and AES in CTR mode
- Supports OpenSSL and GCrypt
- Use multiple SSH connections in a same process, at same time
- Use multiple channels in the same connection
- Thread safety when using different sessions at same time
- POSIX-like SFTP (Secure File Transfer) implementation with openssh extension support
- SCP implementation
- Large file system support (files bigger than 4GB)
- RSA and DSS server public key supported
- Compression support (with zlib)
- Public key (RSA and DSS), password and keyboard-interactive authentication
- Full poll()/WSAPoll() support and a poll-emulation for Win32.
- Runs and tested under x86_64, x86, ARM, Sparc32, PPC under Linux, BSD, MacOSX, Solaris and Windows
@section main-copyright Copyright Policy
libssh is a project with distributed copyright ownership, which means we prefer
the copyright on parts of libssh to be held by individuals rather than
corporations if possible. There are historical legal reasons for this, but one
of the best ways to explain it is that it’s much easier to work with
individuals who have ownership than corporate legal departments if we ever need
to make reasonable compromises with people using and working with libssh.
We track the ownership of every part of libssh via git, our source code control
system, so we know the provenance of every piece of code that is committed to
libssh.
So if possible, if you’re doing libssh changes on behalf of a company who
normally owns all the work you do please get them to assign personal copyright
ownership of your changes to you as an individual, that makes things very easy
for us to work with and avoids bringing corporate legal departments into the
picture.
If you can’t do this we can still accept patches from you owned by your
employer under a standard employment contract with corporate copyright
ownership. It just requires a simple set-up process first.
We use a process very similar to the way things are done in the Linux Kernel
community, so it should be very easy to get a sign off from your corporate
legal department. The only changes we’ve made are to accommodate the license we
use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2.
The process is called signing.
How to sign your work
----------------------
Once you have permission to contribute to libssh from your employer, simply
email a copy of the following text from your corporate email address to:
contributing@libssh.org
@verbatim
libssh Developer's Certificate of Origin. Version 1.0
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the appropriate
version of the GNU General Public License; or
(b) The contribution is based upon previous work that, to the best of
my knowledge, is covered under an appropriate open source license
and I have the right under that license to submit that work with
modifications, whether created in whole or in part by me, under
the GNU General Public License, in the appropriate version; or
(c) The contribution was provided directly to me by some other
person who certified (a) or (b) and I have not modified it.
(d) I understand and agree that this project and the contribution are
public and that a record of the contribution (including all
metadata and personal information I submit with it, including my
sign-off) is maintained indefinitely and may be redistributed
consistent with the libssh Team's policies and the requirements of
the GNU GPL where they are relevant.
(e) I am granting this work to this project 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 the option of the project) any later version.
http://www.gnu.org/licenses/lgpl-2.1.html
@endverbatim
We will maintain a copy of that email as a record that you have the rights to
contribute code to libssh under the required licenses whilst working for the
company where the email came from.
Then when sending in a patch via the normal mechanisms described above, add a
line that states:
@verbatim
Signed-off-by: Random J Developer <random@developer.example.org>
@endverbatim
using your real name and the email address you sent the original email you used
to send the libssh Developer’s Certificate of Origin to us (sorry, no
pseudonyms or anonymous contributions.)
That’s it! Such code can then quite happily contain changes that have copyright
messages such as:
@verbatim
(c) Example Corporation.
@endverbatim
and can be merged into the libssh codebase in the same way as patches from any
other individual. You don’t need to send in a copy of the libssh Developer’s
Certificate of Origin for each patch, or inside each patch. Just the sign-off
message is all that is required once we’ve received the initial email.
Have fun and happy libssh hacking!
The libssh Team
@section main-rfc Internet standard
@subsection main-rfc-secsh Secure Shell (SSH)
The following RFC documents described SSH-2 protcol as an Internet standard.
- <a href="http://tools.ietf.org/html/rfc4250" target="_blank">RFC 4250</a>,
The Secure Shell (SSH) Protocol Assigned Numbers
- <a href="http://tools.ietf.org/html/rfc4251" target="_blank">RFC 4251</a>,
The Secure Shell (SSH) Protocol Architecture
- <a href="http://tools.ietf.org/html/rfc4252" target="_blank">RFC 4252</a>,
The Secure Shell (SSH) Authentication Protocol
- <a href="http://tools.ietf.org/html/rfc4253" target="_blank">RFC 4253</a>,
The Secure Shell (SSH) Transport Layer Protocol
- <a href="http://tools.ietf.org/html/rfc4254" target="_blank">RFC 4254</a>,
The Secure Shell (SSH) Connection Protocol
- <a href="http://tools.ietf.org/html/rfc4255" target="_blank">RFC 4255</a>,
Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints
- <a href="http://tools.ietf.org/html/rfc4256" target="_blank">RFC 4256</a>,
Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)
- <a href="http://tools.ietf.org/html/rfc4335" target="_blank">RFC 4335</a>,
The Secure Shell (SSH) Session Channel Break Extension
- <a href="http://tools.ietf.org/html/rfc4344" target="_blank">RFC 4344</a>,
The Secure Shell (SSH) Transport Layer Encryption Modes
- <a href="http://tools.ietf.org/html/rfc4345" target="_blank">RFC 4345</a>,
Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol
It was later modified and expanded by the following RFCs.
- <a href="http://tools.ietf.org/html/rfc4419" target="_blank">RFC 4419</a>,
Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer
Protocol
- <a href="http://tools.ietf.org/html/rfc4432" target="_blank">RFC 4432</a>,
RSA Key Exchange for the Secure Shell (SSH) Transport Layer Protocol
- <a href="http://tools.ietf.org/html/rfc4462" target="_blank">RFC 4462</a>,
Generic Security Service Application Program Interface (GSS-API)
Authentication and Key Exchange for the Secure Shell (SSH) Protocol
- <a href="http://tools.ietf.org/html/rfc4716" target="_blank">RFC 4716</a>,
The Secure Shell (SSH) Public Key File Format
- <a href="http://tools.ietf.org/html/rfc5656" target="_blank">RFC 5656</a>,
Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer
Interesting cryptography documents:
- <a href="http://www.cryptsoft.com/pkcs11doc/" target="_blank">PKCS #11</a>, PKCS #11 reference documents, describing interface with smartcards.
@subsection main-rfc-sftp Secure Shell File Transfer Protocol (SFTP)
The protocol is not an Internet standard but it is still widely implemented.
OpenSSH and most other implementation implement Version 3 of the protocol. We
do the same in libssh.
- <a href="http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02" target="_blank">
draft-ietf-secsh-filexfer-02.txt</a>,
SSH File Transfer Protocol
@subsection main-rfc-extensions Secure Shell Extensions
The OpenSSH project has defined some extensions to the protocol. We support some of
them like the statvfs calls in SFTP or the ssh-agent.
- <a href="http://api.libssh.org/rfc/PROTOCOL" target="_blank">
OpenSSH's deviations and extensions</a>
- <a href="http://api.libssh.org/rfc/PROTOCOL.agent" target="_blank">
OpenSSH's ssh-agent</a>
- <a href="http://api.libssh.org/rfc/PROTOCOL.certkeys" target="_blank">
OpenSSH's pubkey certificate authentication</a>
*/
+268
View File
@@ -0,0 +1,268 @@
/**
@page libssh_tutor_scp Chapter 6: The SCP subsystem
@section scp_subsystem The SCP subsystem
The SCP subsystem has far less functionnality than the SFTP subsystem.
However, if you only need to copy files from and to the remote system,
it does its job.
@subsection scp_session Opening and closing a SCP session
Like in the SFTP subsystem, you don't handle the SSH channels directly.
Instead, you open a "SCP session".
When you open your SCP session, you have to choose between read or write mode.
You can't do both in the same session. So you specify either SSH_SCP_READ or
SSH_SCP_WRITE as the second parameter of function ssh_scp_new().
Another important mode flag for opening your SCP session is SSH_SCP_RECURSIVE.
When you use SSH_SCP_RECURSIVE, you declare that you are willing to emulate
the behaviour of "scp -r" command in your program, no matter it is for
reading or for writing.
Once your session is created, you initialize it with ssh_scp_init(). When
you have finished transferring files, you terminate the SCP connection with
ssh_scp_close(). Finally, you can dispose the SCP connection with
ssh_scp_free().
The example below does the maintenance work to open a SCP connection for writing in
recursive mode:
@code
int scp_write(ssh_session session)
{
ssh_scp scp;
int rc;
scp = ssh_scp_new
(session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, ".");
if (scp == NULL)
{
fprintf(stderr, "Error allocating scp session: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
rc = ssh_scp_init(scp);
if (rc != SSH_OK)
{
fprintf(stderr, "Error initializing scp session: %s\n",
ssh_get_error(session));
ssh_scp_free(scp);
return rc;
}
...
ssh_scp_close(scp);
ssh_scp_free(scp);
return SSH_OK;
}
@endcode
The example below shows how to open a connection to read a single file:
@code
int scp_read(ssh_session session)
{
ssh_scp scp;
int rc;
scp = ssh_scp_new
(session, SSH_SCP_READ, "helloworld/helloworld.txt");
if (scp == NULL)
{
fprintf(stderr, "Error allocating scp session: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
rc = ssh_scp_init(scp);
if (rc != SSH_OK)
{
fprintf(stderr, "Error initializing scp session: %s\n",
ssh_get_error(session));
ssh_scp_free(scp);
return rc;
}
...
ssh_scp_close(scp);
ssh_scp_free(scp);
return SSH_OK;
}
@endcode
@subsection scp_write Creating files and directories
You create directories with ssh_scp_push_directory(). In recursive mode,
you are placed in this directory once it is created. If the directory
already exists and if you are in recursive mode, you simply enter that
directory.
Creating files is done in two steps. First, you prepare the writing with
ssh_scp_push_file(). Then, you write the data with ssh_scp_write().
The length of the data to write must be identical between both function calls.
There's no need to "open" nor "close" the file, this is done automatically
on the remote end. If the file already exists, it is overwritten and truncated.
The following example creates a new directory named "helloworld/", then creates
a file named "helloworld.txt" in that directory:
@code
int scp_helloworld(ssh_session session, ssh_scp scp)
{
int rc;
const char *helloworld = "Hello, world!\n";
int length = strlen(helloworld);
rc = ssh_scp_push_directory(scp, "helloworld", S_IRWXU);
if (rc != SSH_OK)
{
fprintf(stderr, "Can't create remote directory: %s\n",
ssh_get_error(session));
return rc;
}
rc = ssh_scp_push_file
(scp, "helloworld.txt", length, S_IRUSR | S_IWUSR);
if (rc != SSH_OK)
{
fprintf(stderr, "Can't open remote file: %s\n",
ssh_get_error(session));
return rc;
}
rc = ssh_scp_write(scp, helloworld, length);
if (rc != SSH_OK)
{
fprintf(stderr, "Can't write to remote file: %s\n",
ssh_get_error(session));
return rc;
}
return SSH_OK;
}
@endcode
@subsection scp_recursive_write Copying full directory trees to the remote server
Let's say you want to copy the following tree of files to the remote site:
@verbatim
+-- file1
+-- B --+
| +-- file2
-- A --+
| +-- file3
+-- C --+
+-- file4
@endverbatim
You would do it that way:
- open the session in recursive mode
- enter directory A
- enter its subdirectory B
- create file1 in B
- create file2 in B
- leave directory B
- enter subdirectory C
- create file3 in C
- create file4 in C
- leave directory C
- leave directory A
To leave a directory, call ssh_scp_leave_directory().
@subsection scp_read Reading files and directories
To receive files, you pull requests from the other side with ssh_scp_pull_request().
If this function returns SSH_SCP_REQUEST_NEWFILE, then you must get ready for
the reception. You can get the size of the data to receive with ssh_scp_request_get_size()
and allocate a buffer accordingly. When you are ready, you accept the request with
ssh_scp_accept_request(), then read the data with ssh_scp_read().
The following example receives a single file. The name of the file to
receive has been given earlier, when the scp session was opened:
@code
int scp_receive(ssh_session session, ssh_scp scp)
{
int rc;
int size, mode;
char *filename, *buffer;
rc = ssh_scp_pull_request(scp);
if (rc != SSH_SCP_REQUEST_NEWFILE)
{
fprintf(stderr, "Error receiving information about file: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
size = ssh_scp_request_get_size(scp);
filename = strdup(ssh_scp_request_get_filename(scp));
mode = ssh_scp_request_get_permissions(scp);
printf("Receiving file %s, size %d, permisssions 0%o\n",
filename, size, mode);
free(filename);
buffer = malloc(size);
if (buffer == NULL)
{
fprintf(stderr, "Memory allocation error\n");
return SSH_ERROR;
}
ssh_scp_accept_request(scp);
rc = ssh_scp_read(scp, buffer, size);
if (rc == SSH_ERROR)
{
fprintf(stderr, "Error receiving file data: %s\n",
ssh_get_error(session));
free(buffer);
return rc;
}
printf("Done\n");
write(1, buffer, size);
free(buffer);
rc = ssh_scp_pull_request(scp);
if (rc != SSH_SCP_REQUEST_EOF)
{
fprintf(stderr, "Unexpected request: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
return SSH_OK;
}
@endcode
In this example, since we just requested a single file, we expect ssh_scp_request()
to return SSH_SCP_REQUEST_NEWFILE first, then SSH_SCP_REQUEST_EOF. That's quite a
naive approach; for example, the remote server might send a warning as well
(return code SSH_SCP_REQUEST_WARNING) and the example would fail. A more comprehensive
reception program would receive the requests in a loop and analyze them carefully
until SSH_SCP_REQUEST_EOF has been received.
@subsection scp_recursive_read Receiving full directory trees from the remote server
If you opened the SCP session in recursive mode, the remote end will be
telling you when to change directory.
In that case, when ssh_scp_pull_request() answers
SSH_SCP_REQUEST_NEWDIRECTORY, you should make that local directory (if
it does not exist yet) and enter it. When ssh_scp_pull_request() answers
SSH_SCP_REQUEST_ENDDIRECTORY, you should leave the current directory.
*/
+415
View File
@@ -0,0 +1,415 @@
/**
@page libssh_tutor_sftp Chapter 5: The SFTP subsystem
@section sftp_subsystem The SFTP subsystem
SFTP stands for "Secure File Transfer Protocol". It enables you to safely
transfer files between the local and the remote computer. It reminds a lot
of the old FTP protocol.
SFTP is a rich protocol. It lets you do over the network almost everything
that you can do with local files:
- send files
- modify only a portion of a file
- receive files
- receive only a portion of a file
- get file owner and group
- get file permissions
- set file owner and group
- set file permissions
- remove files
- rename files
- create a directory
- remove a directory
- retrieve the list of files in a directory
- get the target of a symbolic link
- create symbolic links
- get information about mounted filesystems.
The current implemented version of the SFTP protocol is version 3. All functions
aren't implemented yet, but the most important are.
@subsection sftp_session Opening and closing a SFTP session
Unlike with remote shells and remote commands, when you use the SFTP subsystem,
you don't handle directly the SSH channels. Instead, you open a "SFTP session".
The function sftp_new() creates a new SFTP session. The function sftp_init()
initializes it. The function sftp_free() deletes it.
As you see, all the SFTP-related functions start with the "sftp_" prefix
instead of the usual "ssh_" prefix.
The example below shows how to use these functions:
@code
#include <libssh/sftp.h>
int sftp_helloworld(ssh_session session)
{
sftp_session sftp;
int rc;
sftp = sftp_new(session);
if (sftp == NULL)
{
fprintf(stderr, "Error allocating SFTP session: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
rc = sftp_init(sftp);
if (rc != SSH_OK)
{
fprintf(stderr, "Error initializing SFTP session: %s.\n",
sftp_get_error(sftp));
sftp_free(sftp);
return rc;
}
...
sftp_free(sftp);
return SSH_OK;
}
@endcode
@subsection sftp_errors Analyzing SFTP errors
In case of a problem, the function sftp_get_error() returns a SFTP-specific
error number, in addition to the regular SSH error number returned by
ssh_get_error_number().
Possible errors are:
- SSH_FX_OK: no error
- SSH_FX_EOF: end-of-file encountered
- SSH_FX_NO_SUCH_FILE: file does not exist
- SSH_FX_PERMISSION_DENIED: permission denied
- SSH_FX_FAILURE: generic failure
- SSH_FX_BAD_MESSAGE: garbage received from server
- SSH_FX_NO_CONNECTION: no connection has been set up
- SSH_FX_CONNECTION_LOST: there was a connection, but we lost it
- SSH_FX_OP_UNSUPPORTED: operation not supported by libssh yet
- SSH_FX_INVALID_HANDLE: invalid file handle
- SSH_FX_NO_SUCH_PATH: no such file or directory path exists
- SSH_FX_FILE_ALREADY_EXISTS: an attempt to create an already existing file or directory has been made
- SSH_FX_WRITE_PROTECT: write-protected filesystem
- SSH_FX_NO_MEDIA: no media was in remote drive
@subsection sftp_mkdir Creating a directory
The function sftp_mkdir() tahes the "SFTP session" we juste created as
its first argument. It also needs the name of the file to create, and the
desired permissions. The permissions are the same as for the usual mkdir()
function. To get a comprehensive list of the available permissions, use the
"man 2 stat" command. The desired permissions are combined with the remote
user's mask to determine the effective permissions.
The code below creates a directory named "helloworld" in the current directory that
can be read and written only by its owner:
@code
#include <libssh/sftp.h>
#include <sys/stat.h>
int sftp_helloworld(ssh_session session, sftp_session sftp)
{
int rc;
rc = sftp_mkdir(sftp, "helloworld", S_IRWXU);
if (rc != SSH_OK)
{
if (sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS)
{
fprintf(stderr, "Can't create directory: %s\n",
ssh_get_error(session));
return rc;
}
}
...
return SSH_OK;
}
@endcode
Unlike its equivalent in the SCP subsystem, this function does NOT change the
current directory to the newly created subdirectory.
@subsection sftp_write Copying a file to the remote computer
You handle the contents of a remote file just like you would do with a
local file: you open the file in a given mode, move the file pointer in it,
read or write data, and close the file.
The sftp_open() function is very similar to the regular open() function,
excepted that it returns a file handle of type sftp_file. This file handle
is then used by the other file manipulation functions and remains valid
until you close the remote file with sftp_close().
The example below creates a new file named "helloworld.txt" in the
newly created "helloworld" directory. If the file already exists, it will
be truncated. It then writes the famous "Hello, World!" sentence to the
file, followed by a new line character. Finally, the file is closed:
@code
#include <libssh/sftp.h>
#include <sys/stat.h>
#include <fcntl.h>
int sftp_helloworld(ssh_session session, sftp_session sftp)
{
int access_type = O_WRONLY | O_CREAT | O_TRUNC;
sftp_file file;
const char *helloworld = "Hello, World!\n";
int length = strlen(helloworld);
int rc, nwritten;
...
file = sftp_open(sftp, "helloworld/helloworld.txt",
access_type, S_IRWXU);
if (file == NULL)
{
fprintf(stderr, "Can't open file for writing: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
nwritten = sftp_write(file, helloworld, length);
if (nwritten != length)
{
fprintf(stderr, "Can't write data to file: %s\n",
ssh_get_error(session));
sftp_close(file);
return SSH_ERROR;
}
rc = sftp_close(file);
if (rc != SSH_OK)
{
fprintf(stderr, "Can't close the written file: %s\n",
ssh_get_error(session));
return rc;
}
return SSH_OK;
}
@endcode
@subsection sftp_read Reading a file from the remote computer
The nice thing with reading a file over the network through SFTP is that it
can be done both in a synchronous way or an asynchronous way. If you read the file
asynchronously, your program can do something else while it waits for the
results to come.
Synchronous read is done with sftp_read().
The following example prints the contents of remote file "/etc/profile". For
each 1024 bytes of information read, it waits until the end of the read operation:
@code
int sftp_read_sync(ssh_session session, sftp_session sftp)
{
int access_type;
sftp_file file;
char buffer[1024];
int nbytes, rc;
access_type = O_RDONLY;
file = sftp_open(sftp, "/etc/profile",
access_type, 0);
if (file == NULL)
{
fprintf(stderr, "Can't open file for reading: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
nbytes = sftp_read(file, buffer, sizeof(buffer));
while (nbytes > 0)
{
if (write(1, buffer, nbytes) != nbytes)
{
sftp_close(file);
return SSH_ERROR;
}
nbytes = sftp_read(file, buffer, sizeof(buffer));
}
if (nbytes < 0)
{
fprintf(stderr, "Error while reading file: %s\n",
ssh_get_error(session));
sftp_close(file);
return SSH_ERROR;
}
rc = sftp_close(file);
if (rc != SSH_OK)
{
fprintf(stderr, "Can't close the read file: %s\n",
ssh_get_error(session));
return rc;
}
return SSH_OK;
}
@endcode
Asynchronous read is done in two steps, first sftp_async_read_begin(), which
returns a "request handle", and then sftp_async_read(), which uses that request handle.
If the file has been opened in nonblocking mode, then sftp_async_read()
might return SSH_AGAIN, which means that the request hasn't completed yet
and that the function should be called again later on. Otherwise,
sftp_async_read() waits for the data to come. To open a file in nonblocking mode,
call sftp_file_set_nonblocking() right after you opened it. Default is blocking mode.
The example below reads a very big file in asynchronous, nonblocking, mode. Each
time the data are not ready yet, a counter is incrementer.
@code
int sftp_read_async(ssh_session session, sftp_session sftp)
{
int access_type;
sftp_file file;
char buffer[1024];
int async_request;
int nbytes;
long counter;
int rc;
access_type = O_RDONLY;
file = sftp_open(sftp, "some_very_big_file",
access_type, 0);
if (file == NULL)
{
fprintf(stderr, "Can't open file for reading: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
sftp_file_set_nonblocking(file);
async_request = sftp_async_read_begin(file, sizeof(buffer));
counter = 0L;
usleep(10000);
if (async_request >= 0)
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
async_request);
else nbytes = -1;
while (nbytes > 0 || nbytes == SSH_AGAIN)
{
if (nbytes > 0)
{
write(1, buffer, nbytes);
async_request = sftp_async_read_begin(file, sizeof(buffer));
}
else counter++;
usleep(10000);
if (async_request >= 0)
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
async_request);
else nbytes = -1;
}
if (nbytes < 0)
{
fprintf(stderr, "Error while reading file: %s\n",
ssh_get_error(session));
sftp_close(file);
return SSH_ERROR;
}
printf("The counter has reached value: %ld\n", counter);
rc = sftp_close(file);
if (rc != SSH_OK)
{
fprintf(stderr, "Can't close the read file: %s\n",
ssh_get_error(session));
return rc;
}
return SSH_OK;
}
@endcode
@subsection sftp_ls Listing the contents of a directory
The functions sftp_opendir(), sftp_readdir(), sftp_dir_eof(),
and sftp_closedir() enable to list the contents of a directory.
They use a new handle_type, "sftp_dir", which gives access to the
directory being read.
In addition, sftp_readdir() returns a "sftp_attributes" which is a pointer
to a structure with informations about a directory entry:
- name: the name of the file or directory
- size: its size in bytes
- etc.
sftp_readdir() might return NULL under two conditions:
- when the end of the directory has been met
- when an error occured
To tell the difference, call sftp_dir_eof().
The attributes must be freed with sftp_attributes_free() when no longer
needed.
The following example reads the contents of some remote directory:
@code
int sftp_list_dir(ssh_session session, sftp_session sftp)
{
sftp_dir dir;
sftp_attributes attributes;
int rc;
dir = sftp_opendir(sftp, "/var/log");
if (!dir)
{
fprintf(stderr, "Directory not opened: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
printf("Name Size Perms Owner\tGroup\n");
while ((attributes = sftp_readdir(sftp, dir)) != NULL)
{
printf("%-20s %10llu %.8o %s(%d)\t%s(%d)\n",
attributes->name,
(long long unsigned int) attributes->size,
attributes->permissions,
attributes->owner,
attributes->uid,
attributes->group,
attributes->gid);
sftp_attributes_free(attributes);
}
if (!sftp_dir_eof(dir))
{
fprintf(stderr, "Can't list directory: %s\n",
ssh_get_error(session));
sftp_closedir(dir);
return SSH_ERROR;
}
rc = sftp_closedir(dir);
if (rc != SSH_OK)
{
fprintf(stderr, "Can't close directory: %s\n",
ssh_get_error(session));
return rc;
}
}
@endcode
*/
+361
View File
@@ -0,0 +1,361 @@
/**
@page libssh_tutor_shell Chapter 3: Opening a remote shell
@section opening_shell Opening a remote shell
We already mentioned that a single SSH connection can be shared
between several "channels". Channels can be used for different purposes.
This chapter shows how to open one of these channels, and how to use it to
start a command interpreter on a remote computer.
@subsection open_channel Opening and closing a channel
The ssh_channel_new() function creates a channel. It returns the channel as
a variable of type ssh_channel.
Once you have this channel, you open a SSH session that uses it with
ssh_channel_open_session().
Once you don't need the channel anymore, you can send an end-of-file
to it with ssh_channel_close(). At this point, you can destroy the channel
with ssh_channel_free().
The code sample below achieves these tasks:
@code
int shell_session(ssh_session session)
{
ssh_channel channel;
int rc;
channel = ssh_channel_new(session);
if (channel == NULL)
return SSH_ERROR;
rc = ssh_channel_open_session(channel);
if (rc != SSH_OK)
{
ssh_channel_free(channel);
return rc;
}
...
ssh_channel_close(channel);
ssh_channel_send_eof(channel);
ssh_channel_free(channel);
return SSH_OK;
}
@endcode
@subsection interactive Interactive and non-interactive sessions
A "shell" is a command interpreter. It is said to be "interactive"
if there is a human user typing the commands, one after the
other. The contrary, a non-interactive shell, is similar to
the execution of commands in the background: there is no attached
terminal.
If you plan using an interactive shell, you need to create a
pseud-terminal on the remote side. A remote terminal is usually referred
to as a "pty", for "pseudo-teletype". The remote processes won't see the
difference with a real text-oriented terminal.
If needed, you request the pty with the function ssh_channel_request_pty().
Then you define its dimensions (number of rows and columns)
with ssh_channel_change_pty_size().
Be your session interactive or not, the next step is to request a
shell with ssh_channel_request_shell().
@code
int interactive_shell_session(ssh_channel channel)
{
int rc;
rc = ssh_channel_request_pty(channel);
if (rc != SSH_OK) return rc;
rc = ssh_channel_change_pty_size(channel, 80, 24);
if (rc != SSH_OK) return rc;
rc = ssh_channel_request_shell(channel);
if (rc != SSH_OK) return rc;
...
return rc;
}
@endcode
@subsection read_data Displaying the data sent by the remote computer
In your program, you will usually need to receive all the data "displayed"
into the remote pty. You will usually analyse, log, or display this data.
ssh_channel_read() and ssh_channel_read_nonblocking() are the simplest
way to read data from a channel. If you only need to read from a single
channel, they should be enough.
The example below shows how to wait for remote data using ssh_channel_read():
@code
int interactive_shell_session(ssh_channel channel)
{
int rc;
char buffer[256];
int nbytes;
rc = ssh_channel_request_pty(channel);
if (rc != SSH_OK) return rc;
rc = ssh_channel_change_pty_size(channel, 80, 24);
if (rc != SSH_OK) return rc;
rc = ssh_channel_request_shell(channel);
if (rc != SSH_OK) return rc;
while (ssh_channel_is_open(channel) &&
!ssh_channel_is_eof(channel))
{
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
if (nbytes < 0)
return SSH_ERROR;
if (nbytes > 0)
write(1, buffer, nbytes);
}
return rc;
}
@endcode
Unlike ssh_channel_read(), ssh_channel_read_nonblocking() never waits for
remote data to be ready. It returns immediately.
If you plan to use ssh_channel_read_nonblocking() repeatedly in a loop,
you should use a "passive wait" function like usleep(3) in the same
loop. Otherwise, your program will consume all the CPU time, and your
computer might become unresponsive.
@subsection write_data Sending user input to the remote computer
User's input is sent to the remote site with ssh_channel_write().
The following example shows how to combine a nonblocking read from a SSH
channel with a nonblocking read from the keyboard. The local input is then
sent to the remote computer:
@code
/* Under Linux, this function determines whether a key has been pressed.
Under Windows, it is a standard function, so you need not redefine it.
*/
int kbhit()
{
struct timeval tv = { 0L, 0L };
fd_set fds;
FD_ZERO(&fds);
FD_SET(0, &fds);
return select(1, &fds, NULL, NULL, &tv);
}
/* A very simple terminal emulator:
- print data received from the remote computer
- send keyboard input to the remote computer
*/
int interactive_shell_session(ssh_channel channel)
{
/* Session and terminal initialization skipped */
...
char buffer[256];
int nbytes, nwritten;
while (ssh_channel_is_open(channel) &&
!ssh_channel_is_eof(channel))
{
nbytes = ssh_channel_read_nonblocking(channel, buffer, sizeof(buffer), 0);
if (nbytes < 0) return SSH_ERROR;
if (nbytes > 0)
{
nwritten = write(1, buffer, nbytes);
if (nwritten != nbytes) return SSH_ERROR;
if (!kbhit())
{
usleep(50000L); // 0.05 second
continue;
}
nbytes = read(0, buffer, sizeof(buffer));
if (nbytes < 0) return SSH_ERROR;
if (nbytes > 0)
{
nwritten = ssh_channel_write(channel, buffer, nbytes);
if (nwritten != nbytes) return SSH_ERROR;
}
}
return rc;
}
@endcode
Of course, this is a poor terminal emulator, since the echo from the keys
pressed should not be done locally, but should be done by the remote side.
Also, user's input should not be sent once "Enter" key is pressed, but
immediately after each key is pressed. This can be accomplished
by setting the local terminal to "raw" mode with the cfmakeraw(3) function.
cfmakeraw() is a standard function under Linux, on other systems you can
recode it with:
@code
static void cfmakeraw(struct termios *termios_p)
{
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
termios_p->c_cflag &= ~(CSIZE|PARENB);
termios_p->c_cflag |= CS8;
}
@endcode
If you are not using a local terminal, but some kind of graphical
environment, the solution to this kind of "echo" problems will be different.
@subsection select_loop A more elaborate way to get the remote data
*** Warning: ssh_select() and ssh_channel_select() are not relevant anymore,
since libssh is about to provide an easier system for asynchronous
communications. This subsection should be removed then. ***
ssh_channel_read() and ssh_channel_read_nonblocking() functions are simple,
but they are not adapted when you expect data from more than one SSH channel,
or from other file descriptors. Last example showed how getting data from
the standard input (the keyboard) at the same time as data from the SSH
channel was complicated. The functions ssh_select() and ssh_channel_select()
provide a more elegant way to wait for data coming from many sources.
The functions ssh_select() and ssh_channel_select() remind of the standard
UNIX select(2) function. The idea is to wait for "something" to happen:
incoming data to be read, outcoming data to block, or an exception to
occur. Both these functions do a "passive wait", i.e. you can safely use
them repeatedly in a loop, it will not consume exaggerate processor time
and make your computer unresponsive. It is quite common to use these
functions in your application's main loop.
The difference between ssh_select() and ssh_channel_select() is that
ssh_channel_select() is simpler, but allows you only to watch SSH channels.
ssh_select() is more complete and enables watching regular file descriptors
as well, in the same function call.
Below is an example of a function that waits both for remote SSH data to come,
as well as standard input from the keyboard:
@code
int interactive_shell_session(ssh_session session, ssh_channel channel)
{
/* Session and terminal initialization skipped */
...
char buffer[256];
int nbytes, nwritten;
while (ssh_channel_is_open(channel) &&
!ssh_channel_is_eof(channel))
{
struct timeval timeout;
ssh_channel in_channels[2], out_channels[2];
fd_set fds;
int maxfd;
timeout.tv_sec = 30;
timeout.tv_usec = 0;
in_channels[0] = channel;
in_channels[1] = NULL;
FD_ZERO(&fds);
FD_SET(0, &fds);
FD_SET(ssh_get_fd(session), &fds);
maxfd = ssh_get_fd(session) + 1;
ssh_select(in_channels, out_channels, maxfd, &fds, &timeout);
if (out_channels[0] != NULL)
{
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
if (nbytes < 0) return SSH_ERROR;
if (nbytes > 0)
{
nwritten = write(1, buffer, nbytes);
if (nwritten != nbytes) return SSH_ERROR;
}
}
if (FD_ISSET(0, &fds))
{
nbytes = read(0, buffer, sizeof(buffer));
if (nbytes < 0) return SSH_ERROR;
if (nbytes > 0)
{
nwritten = ssh_channel_write(channel, buffer, nbytes);
if (nbytes != nwritten) return SSH_ERROR;
}
}
}
return rc;
}
@endcode
@subsection x11 Using graphical applications on the remote side
If your remote application is graphical, you can forward the X11 protocol to
your local computer.
To do that, you first declare that you accept X11 connections with
ssh_channel_accept_x11(). Then you create the forwarding tunnel for
the X11 protocol with ssh_channel_request_x11().
The following code performs channel initialization and shell session
opening, and handles a parallel X11 connection:
@code
int interactive_shell_session(ssh_channel channel)
{
int rc;
ssh_channel x11channel;
rc = ssh_channel_request_pty(channel);
if (rc != SSH_OK) return rc;
rc = ssh_channel_change_pty_size(channel, 80, 24);
if (rc != SSH_OK) return rc;
rc = ssh_channel_request_x11(channel, 0, NULL, NULL, 0);
if (rc != SSH_OK) return rc;
rc = ssh_channel_request_shell(channel);
if (rc != SSH_OK) return rc;
/* Read the data sent by the remote computer here */
...
}
@endcode
Don't forget to set the $DISPLAY environment variable on the remote
side, or the remote applications won't try using the X11 tunnel:
@code
$ export DISPLAY=:0
$ xclock &
@endcode
*/
+14
View File
@@ -0,0 +1,14 @@
/**
@page libssh_tutor_todo To be done
*** To be written ***
@section sshd Writing a libssh-based server
*** To be written ***
@section cpp The libssh C++ wrapper
*** To be written ***
*/
+65
View File
@@ -0,0 +1,65 @@
/**
@page libssh_tutor_threads Chapter 8: Threads with libssh
@section threads_with_libssh How to use libssh with threads
libssh may be used in multithreaded applications, but under several conditions :
- Threading must be initialized during the initialization of libssh. This
initialization must be done outside of any threading context.
- If pthreads is being used by your application (or your framework's backend),
you must link with libssh_threads dynamic library and initialize
threading with the ssh_threads_pthreads threading object.
- If an other threading library is being used by your application, you must
implement all the methods of the ssh_threads_callbacks_struct structure
and initialize libssh with it.
- At all times, you may use different sessions inside threads, make parallel
connections, read/write on different sessions and so on. You *cannot* use a
single session (or channels for a single session) in several threads at the same
time. This will most likely lead to internal state corruption. This limitation is
being worked out and will maybe disappear later.
@subsection threads_init Initialization of threads
To initialize threading, you must first select the threading model you want to
use, using ssh_threads_set_callbacks(), then call ssh_init().
@code
#include <libssh/callbacks.h>
...
ssh_threads_set_callbacks(ssh_threads_get_noop());
ssh_init();
@endcode
ssh_threads_noop is the threading structure that does nothing. It's the
threading callbacks being used by default when you're not using threading.
@subsection threads_pthread Using libpthread with libssh
If your application is using libpthread, you may simply use the libpthread
threading backend:
@code
#include <libssh/callbacks.h>
...
ssh_threads_set_callbacks(ssh_threads_get_pthread());
ssh_init();
@endcode
However, you must be sure to link with the library ssh_threads. If
you're using gcc, you must use the commandline
@code
gcc -o output input.c -lssh -lssh_threads
@endcode
@subsection threads_other Using another threading library
You must find your way in the ssh_threads_callbacks_struct structure. You must
implement the following methods :
- mutex_lock
- mutex_unlock
- mutex_init
- mutex_destroy
- thread_id
Good luck !
*/
+57
View File
@@ -0,0 +1,57 @@
project(libssh-examples C CXX)
set(examples_SRCS
authentication.c
knownhosts.c
connect_ssh.c
)
include_directories(
${LIBSSH_PUBLIC_INCLUDE_DIRS}
${CMAKE_BINARY_DIR}
)
if (LINUX)
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
add_executable(scp_download scp_download.c ${examples_SRCS})
target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
add_executable(samplessh sample.c ${examples_SRCS})
target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY})
if (WITH_SFTP)
add_executable(samplesftp samplesftp.c ${examples_SRCS})
target_link_libraries(samplesftp ${LIBSSH_SHARED_LIBRARY})
endif (WITH_SFTP)
if (WITH_SERVER)
add_executable(samplesshd samplesshd.c)
target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY})
add_executable(samplesshd-kbdint samplesshd-kbdint.c)
target_link_libraries(samplesshd-kbdint ${LIBSSH_SHARED_LIBRARY})
if (HAVE_LIBUTIL)
add_executable(samplesshd-tty samplesshd-tty.c)
target_link_libraries(samplesshd-tty ${LIBSSH_SHARED_LIBRARY} util)
endif (HAVE_LIBUTIL)
endif (WITH_SERVER)
endif (LINUX)
add_executable(exec exec.c ${examples_SRCS})
target_link_libraries(exec ${LIBSSH_SHARED_LIBRARY})
add_executable(senddata senddata.c ${examples_SRCS})
target_link_libraries(senddata ${LIBSSH_SHARED_LIBRARY})
add_executable(libsshpp libsshpp.cpp)
target_link_libraries(libsshpp ${LIBSSH_SHARED_LIBRARY})
add_executable(libsshpp_noexcept libsshpp_noexcept.cpp)
target_link_libraries(libsshpp_noexcept ${LIBSSH_SHARED_LIBRARY})
+167
View File
@@ -0,0 +1,167 @@
/*
* authentication.c
* This file contains an example of how to do an authentication to a
* SSH server using libssh
*/
/*
Copyright 2003-2009 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libssh/libssh.h>
#include "examples_common.h"
int authenticate_kbdint(ssh_session session, const char *password) {
int err;
err = ssh_userauth_kbdint(session, NULL, NULL);
while (err == SSH_AUTH_INFO) {
const char *instruction;
const char *name;
char buffer[128];
int i, n;
name = ssh_userauth_kbdint_getname(session);
instruction = ssh_userauth_kbdint_getinstruction(session);
n = ssh_userauth_kbdint_getnprompts(session);
if (name && strlen(name) > 0) {
printf("%s\n", name);
}
if (instruction && strlen(instruction) > 0) {
printf("%s\n", instruction);
}
for (i = 0; i < n; i++) {
const char *answer;
const char *prompt;
char echo;
prompt = ssh_userauth_kbdint_getprompt(session, i, &echo);
if (prompt == NULL) {
break;
}
if (echo) {
char *p;
printf("%s", prompt);
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
return SSH_AUTH_ERROR;
}
buffer[sizeof(buffer) - 1] = '\0';
if ((p = strchr(buffer, '\n'))) {
*p = '\0';
}
if (ssh_userauth_kbdint_setanswer(session, i, buffer) < 0) {
return SSH_AUTH_ERROR;
}
memset(buffer, 0, strlen(buffer));
} else {
if (password && strstr(prompt, "Password:")) {
answer = password;
} else {
buffer[0] = '\0';
if (ssh_getpass(prompt, buffer, sizeof(buffer), 0, 0) < 0) {
return SSH_AUTH_ERROR;
}
answer = buffer;
}
err = ssh_userauth_kbdint_setanswer(session, i, answer);
memset(buffer, 0, sizeof(buffer));
if (err < 0) {
return SSH_AUTH_ERROR;
}
}
}
err=ssh_userauth_kbdint(session,NULL,NULL);
}
return err;
}
static void error(ssh_session session){
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
}
int authenticate_console(ssh_session session){
int rc;
int method;
char password[128] = {0};
char *banner;
// Try to authenticate
rc = ssh_userauth_none(session, NULL);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
}
method = ssh_auth_list(session);
while (rc != SSH_AUTH_SUCCESS) {
// Try to authenticate with public key first
if (method & SSH_AUTH_METHOD_PUBLICKEY) {
rc = ssh_userauth_autopubkey(session, NULL);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
// Try to authenticate with keyboard interactive";
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
rc = authenticate_kbdint(session, NULL);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
if (ssh_getpass("Password: ", password, sizeof(password), 0, 0) < 0) {
return SSH_AUTH_ERROR;
}
// Try to authenticate with password
if (method & SSH_AUTH_METHOD_PASSWORD) {
rc = ssh_userauth_password(session, NULL, password);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
memset(password, 0, sizeof(password));
}
banner = ssh_get_issue_banner(session);
if (banner) {
printf("%s\n",banner);
ssh_string_free_char(banner);
}
return rc;
}
+67
View File
@@ -0,0 +1,67 @@
/*
* connect_ssh.c
* This file contains an example of how to connect to a
* SSH server using libssh
*/
/*
Copyright 2009 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
#include <libssh/libssh.h>
#include "examples_common.h"
#include <stdio.h>
ssh_session connect_ssh(const char *host, const char *user,int verbosity){
ssh_session session;
int auth=0;
session=ssh_new();
if (session == NULL) {
return NULL;
}
if(user != NULL){
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
ssh_free(session);
return NULL;
}
}
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
ssh_free(session);
return NULL;
}
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
if(ssh_connect(session)){
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
if(verify_knownhost(session)<0){
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
auth=authenticate_console(session);
if(auth==SSH_AUTH_SUCCESS){
return session;
} else if(auth==SSH_AUTH_DENIED){
fprintf(stderr,"Authentication failed\n");
} else {
fprintf(stderr,"Error while authenticating : %s\n",ssh_get_error(session));
}
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
+22
View File
@@ -0,0 +1,22 @@
/*
Copyright 2009 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
#ifndef EXAMPLES_COMMON_H_
#define EXAMPLES_COMMON_H_
#include <libssh/libssh.h>
int authenticate_console(ssh_session session);
int authenticate_kbdint(ssh_session session, const char *password);
int verify_knownhost(ssh_session session);
ssh_session connect_ssh(const char *hostname, const char *user, int verbosity);
#endif /* EXAMPLES_COMMON_H_ */
+66
View File
@@ -0,0 +1,66 @@
/* simple exec example */
#include <stdio.h>
#include <libssh/libssh.h>
#include "examples_common.h"
int main(void) {
ssh_session session;
ssh_channel channel;
char buffer[256];
int nbytes;
int rc;
session = connect_ssh("localhost", NULL, 0);
if (session == NULL) {
ssh_finalize();
return 1;
}
channel = ssh_channel_new(session);;
if (channel == NULL) {
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 1;
}
rc = ssh_channel_open_session(channel);
if (rc < 0) {
goto failed;
}
rc = ssh_channel_request_exec(channel, "lsof");
if (rc < 0) {
goto failed;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0) {
if (fwrite(buffer, 1, nbytes, stdout) != (unsigned int) nbytes) {
goto failed;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if (nbytes < 0) {
goto failed;
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 0;
failed:
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 1;
}
+98
View File
@@ -0,0 +1,98 @@
/*
* knownhosts.c
* This file contains an example of how verify the identity of a
* SSH server using libssh
*/
/*
Copyright 2003-2009 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libssh/libssh.h>
#include "examples_common.h"
#ifdef _WIN32
#define strncasecmp _strnicmp
#endif
int verify_knownhost(ssh_session session){
char *hexa;
int state;
char buf[10];
unsigned char *hash = NULL;
int hlen;
state=ssh_is_server_known(session);
hlen = ssh_get_pubkey_hash(session, &hash);
if (hlen < 0) {
return -1;
}
switch(state){
case SSH_SERVER_KNOWN_OK:
break; /* ok */
case SSH_SERVER_KNOWN_CHANGED:
fprintf(stderr,"Host key for server changed : server's one is now :\n");
ssh_print_hexa("Public key hash",hash, hlen);
ssh_clean_pubkey_hash(&hash);
fprintf(stderr,"For security reason, connection will be stopped\n");
return -1;
case SSH_SERVER_FOUND_OTHER:
fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n");
fprintf(stderr,"An attacker might change the default server key to confuse your client"
"into thinking the key does not exist\n"
"We advise you to rerun the client with -d or -r for more safety.\n");
return -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 behavior */
case SSH_SERVER_NOT_KNOWN:
hexa = ssh_get_hexa(hash, hlen);
fprintf(stderr,"The server is unknown. Do you trust the host key ?\n");
fprintf(stderr, "Public key hash: %s\n", hexa);
ssh_string_free_char(hexa);
if (fgets(buf, sizeof(buf), stdin) == NULL) {
ssh_clean_pubkey_hash(&hash);
return -1;
}
if(strncasecmp(buf,"yes",3)!=0){
ssh_clean_pubkey_hash(&hash);
return -1;
}
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
if (fgets(buf, sizeof(buf), stdin) == NULL) {
ssh_clean_pubkey_hash(&hash);
return -1;
}
if(strncasecmp(buf,"yes",3)==0){
if (ssh_write_knownhost(session) < 0) {
ssh_clean_pubkey_hash(&hash);
fprintf(stderr, "error %s\n", strerror(errno));
return -1;
}
}
break;
case SSH_SERVER_ERROR:
ssh_clean_pubkey_hash(&hash);
fprintf(stderr,"%s",ssh_get_error(session));
return -1;
}
ssh_clean_pubkey_hash(&hash);
return 0;
}
+304
View File
@@ -0,0 +1,304 @@
/* libssh_scp.c
* Sample implementation of a SCP client
*/
/*
Copyright 2009 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <libssh/libssh.h>
#include "examples_common.h"
static char **sources;
static int nsources;
static char *destination;
static int verbosity=0;
struct location {
int is_ssh;
char *user;
char *host;
char *path;
ssh_session session;
ssh_scp scp;
FILE *file;
};
enum {
READ,
WRITE
};
static void usage(const char *argv0){
fprintf(stderr,"Usage : %s [options] [[user@]host1:]file1 ... \n"
" [[user@]host2:]destination\n"
"sample scp client - libssh-%s\n",
// "Options :\n",
// " -r : use RSA to verify host public key\n",
argv0,
ssh_version(0));
exit(0);
}
static int opts(int argc, char **argv){
int i;
while((i=getopt(argc,argv,"v"))!=-1){
switch(i){
case 'v':
verbosity++;
break;
default:
fprintf(stderr,"unknown option %c\n",optopt);
usage(argv[0]);
return -1;
}
}
nsources=argc-optind-1;
if(nsources < 1){
usage(argv[0]);
return -1;
}
sources=malloc((nsources + 1) * sizeof(char *));
if(sources == NULL)
return -1;
for(i=0;i<nsources;++i){
sources[i] = argv[optind];
optind++;
}
sources[i]=NULL;
destination=argv[optind];
return 0;
}
static struct location *parse_location(char *loc){
struct location *location=malloc(sizeof(struct location));
char *ptr;
location->host=location->user=NULL;
ptr=strchr(loc,':');
if(ptr != NULL){
location->is_ssh=1;
location->path=strdup(ptr+1);
*ptr='\0';
ptr=strchr(loc,'@');
if(ptr != NULL){
location->host=strdup(ptr+1);
*ptr='\0';
location->user=strdup(loc);
} else {
location->host=strdup(loc);
}
} else {
location->is_ssh=0;
location->path=strdup(loc);
}
return location;
}
static int open_location(struct location *loc, int flag){
if(loc->is_ssh && flag==WRITE){
loc->session=connect_ssh(loc->host,loc->user,verbosity);
if(!loc->session){
fprintf(stderr,"Couldn't connect to %s\n",loc->host);
return -1;
}
loc->scp=ssh_scp_new(loc->session,SSH_SCP_WRITE,loc->path);
if(!loc->scp){
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
return -1;
}
if(ssh_scp_init(loc->scp)==SSH_ERROR){
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
ssh_scp_free(loc->scp);
return -1;
}
return 0;
} else if(loc->is_ssh && flag==READ){
loc->session=connect_ssh(loc->host, loc->user,verbosity);
if(!loc->session){
fprintf(stderr,"Couldn't connect to %s\n",loc->host);
return -1;
}
loc->scp=ssh_scp_new(loc->session,SSH_SCP_READ,loc->path);
if(!loc->scp){
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
return -1;
}
if(ssh_scp_init(loc->scp)==SSH_ERROR){
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
ssh_scp_free(loc->scp);
return -1;
}
return 0;
} else {
loc->file=fopen(loc->path,flag==READ ? "r":"w");
if(!loc->file){
if(errno==EISDIR){
if(chdir(loc->path)){
fprintf(stderr,"Error changing directory to %s: %s\n",loc->path,strerror(errno));
return -1;
}
return 0;
}
fprintf(stderr,"Error opening %s: %s\n",loc->path,strerror(errno));
return -1;
}
return 0;
}
return -1;
}
/** @brief copies files from source location to destination
* @param src source location
* @param dest destination location
* @param recursive Copy also directories
*/
static int do_copy(struct location *src, struct location *dest, int recursive){
int size;
socket_t fd;
struct stat s;
int w,r;
char buffer[16384];
int total=0;
int mode;
char *filename;
/* recursive mode doesn't work yet */
(void)recursive;
/* Get the file name and size*/
if(!src->is_ssh){
fd=fileno(src->file);
fstat(fd,&s);
size=s.st_size;
mode = s.st_mode & ~S_IFMT;
filename=ssh_basename(src->path);
} else {
size=0;
do {
r=ssh_scp_pull_request(src->scp);
if(r==SSH_SCP_REQUEST_NEWDIR){
ssh_scp_deny_request(src->scp,"Not in recursive mode");
continue;
}
if(r==SSH_SCP_REQUEST_NEWFILE){
size=ssh_scp_request_get_size(src->scp);
filename=strdup(ssh_scp_request_get_filename(src->scp));
mode=ssh_scp_request_get_permissions(src->scp);
//ssh_scp_accept_request(src->scp);
break;
}
if(r==SSH_ERROR){
fprintf(stderr,"Error: %s\n",ssh_get_error(src->session));
return -1;
}
} while(r != SSH_SCP_REQUEST_NEWFILE);
}
if(dest->is_ssh){
r=ssh_scp_push_file(dest->scp,src->path, size, mode);
// snprintf(buffer,sizeof(buffer),"C0644 %d %s\n",size,src->path);
if(r==SSH_ERROR){
fprintf(stderr,"error: %s\n",ssh_get_error(dest->session));
ssh_scp_free(dest->scp);
return -1;
}
} else {
if(!dest->file){
dest->file=fopen(filename,"w");
if(!dest->file){
fprintf(stderr,"Cannot open %s for writing: %s\n",filename,strerror(errno));
if(src->is_ssh)
ssh_scp_deny_request(src->scp,"Cannot open local file");
return -1;
}
}
if(src->is_ssh){
ssh_scp_accept_request(src->scp);
}
}
do {
if(src->is_ssh){
r=ssh_scp_read(src->scp,buffer,sizeof(buffer));
if(r==SSH_ERROR){
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(src->session));
return -1;
}
if(r==0)
break;
} else {
r=fread(buffer,1,sizeof(buffer),src->file);
if(r==0)
break;
if(r<0){
fprintf(stderr,"Error reading file: %s\n",strerror(errno));
return -1;
}
}
if(dest->is_ssh){
w=ssh_scp_write(dest->scp,buffer,r);
if(w == SSH_ERROR){
fprintf(stderr,"Error writing in scp: %s\n",ssh_get_error(dest->session));
ssh_scp_free(dest->scp);
dest->scp=NULL;
return -1;
}
} else {
w=fwrite(buffer,r,1,dest->file);
if(w<=0){
fprintf(stderr,"Error writing in local file: %s\n",strerror(errno));
return -1;
}
}
total+=r;
} while(total < size);
printf("wrote %d bytes\n",total);
return 0;
}
int main(int argc, char **argv){
struct location *dest, *src;
int i;
int r;
if(opts(argc,argv)<0)
return EXIT_FAILURE;
dest=parse_location(destination);
if(open_location(dest,WRITE)<0)
return EXIT_FAILURE;
for(i=0;i<nsources;++i){
src=parse_location(sources[i]);
if(open_location(src,READ)<0){
return EXIT_FAILURE;
}
if(do_copy(src,dest,0) < 0){
break;
}
}
if(dest->is_ssh){
r=ssh_scp_close(dest->scp);
if(r == SSH_ERROR){
fprintf(stderr,"Error closing scp: %s\n",ssh_get_error(dest->session));
ssh_scp_free(dest->scp);
dest->scp=NULL;
return -1;
}
} else {
fclose(dest->file);
dest->file=NULL;
}
ssh_disconnect(dest->session);
ssh_finalize();
return 0;
}
+33
View File
@@ -0,0 +1,33 @@
/*
Copyright 2010 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
*/
/* This file demonstrates the use of the C++ wrapper to libssh */
#include <iostream>
#include <string>
#include <libssh/libsshpp.hpp>
int main(int argc, const char **argv){
ssh::Session session;
try {
if(argc>1)
session.setOption(SSH_OPTIONS_HOST,argv[1]);
else
session.setOption(SSH_OPTIONS_HOST,"localhost");
session.connect();
session.userauthPublickeyAuto();
session.disconnect();
} catch (ssh::SshException e){
std::cout << "Error during connection : ";
std::cout << e.getError() << std::endl;
}
return 0;
}
+41
View File
@@ -0,0 +1,41 @@
/*
Copyright 2010 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
*/
/* This file demonstrates the use of the C++ wrapper to libssh
* specifically, without C++ exceptions
*/
#include <iostream>
#define SSH_NO_CPP_EXCEPTIONS
#include <libssh/libsshpp.hpp>
int main(int argc, const char **argv){
ssh::Session session,s2;
int err;
if(argc>1)
err=session.setOption(SSH_OPTIONS_HOST,argv[1]);
else
err=session.setOption(SSH_OPTIONS_HOST,"localhost");
if(err==SSH_ERROR)
goto error;
err=session.connect();
if(err==SSH_ERROR)
goto error;
err=session.userauthPublickeyAuto();
if(err==SSH_ERROR)
goto error;
return 0;
error:
std::cout << "Error during connection : ";
std::cout << session.getError() << std::endl;
return 1;
}
+519
View File
@@ -0,0 +1,519 @@
/* client.c */
/*
Copyright 2003-2009 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
#include "config.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <sys/select.h>
#include <sys/time.h>
#ifdef HAVE_PTY_H
#include <pty.h>
#endif
#include <sys/ioctl.h>
#include <signal.h>
#include <errno.h>
#include <libssh/callbacks.h>
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include <fcntl.h>
#include "examples_common.h"
#define MAXCMD 10
static char *host;
static char *user;
static char *cmds[MAXCMD];
static struct termios terminal;
static char *pcap_file=NULL;
static char *proxycommand;
static int auth_callback(const char *prompt, char *buf, size_t len,
int echo, int verify, void *userdata) {
(void) verify;
(void) userdata;
return ssh_getpass(prompt, buf, len, echo, verify);
}
struct ssh_callbacks_struct cb = {
.auth_function=auth_callback,
.userdata=NULL
};
static void add_cmd(char *cmd){
int n;
for(n=0;cmds[n] && (n<MAXCMD);n++);
if(n==MAXCMD)
return;
cmds[n]=strdup(cmd);
}
static void usage(){
fprintf(stderr,"Usage : ssh [options] [login@]hostname\n"
"sample client - libssh-%s\n"
"Options :\n"
" -l user : log in as user\n"
" -p port : connect to port\n"
" -d : use DSS to verify host public key\n"
" -r : use RSA to verify host public key\n"
#ifdef WITH_PCAP
" -P file : create a pcap debugging file\n"
#endif
#ifndef _WIN32
" -T proxycommand : command to execute as a socket proxy\n"
#endif
,
ssh_version(0));
exit(0);
}
static int opts(int argc, char **argv){
int i;
// for(i=0;i<argc;i++)
// printf("%d : %s\n",i,argv[i]);
/* insert your own arguments here */
while((i=getopt(argc,argv,"T:P:"))!=-1){
switch(i){
case 'P':
pcap_file=optarg;
break;
#ifndef _WIN32
case 'T':
proxycommand=optarg;
break;
#endif
default:
fprintf(stderr,"unknown option %c\n",optopt);
usage();
}
}
if(optind < argc)
host=argv[optind++];
while(optind < argc)
add_cmd(argv[optind++]);
if(host==NULL)
usage();
return 0;
}
#ifndef HAVE_CFMAKERAW
static void cfmakeraw(struct termios *termios_p){
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
termios_p->c_cflag &= ~(CSIZE|PARENB);
termios_p->c_cflag |= CS8;
}
#endif
static void do_cleanup(int i) {
/* unused variable */
(void) i;
tcsetattr(0,TCSANOW,&terminal);
}
static void do_exit(int i) {
/* unused variable */
(void) i;
do_cleanup(0);
exit(0);
}
ssh_channel chan;
int signal_delayed=0;
static void sigwindowchanged(int i){
(void) i;
signal_delayed=1;
}
static void setsignal(void){
signal(SIGWINCH, sigwindowchanged);
signal_delayed=0;
}
static void sizechanged(void){
struct winsize win = { 0, 0, 0, 0 };
ioctl(1, TIOCGWINSZ, &win);
ssh_channel_change_pty_size(chan,win.ws_col, win.ws_row);
// printf("Changed pty size\n");
setsignal();
}
/* There are two flavors of select loop: the one based on
* ssh_select and the one based on channel_select.
* The ssh_select one permits you to give your own file descriptors to
* follow. It is thus a complete select loop.
* The second one only selects on channels. It is simplier to use
* but doesn't permit you to fill in your own file descriptor. It is
* more adapted if you can't use ssh_select as a main loop (because
* you already have another main loop system).
*/
#ifdef USE_CHANNEL_SELECT
/* channel_select base main loop, with a standard select(2)
*/
static void select_loop(ssh_session session,ssh_channel channel){
fd_set fds;
struct timeval timeout;
char buffer[4096];
ssh_buffer readbuf=ssh_buffer_new();
ssh_channel channels[2];
int lus;
int eof=0;
int maxfd;
int ret;
while(channel){
/* when a signal is caught, ssh_select will return
* with SSH_EINTR, which means it should be started
* again. It lets you handle the signal the faster you
* can, like in this window changed example. Of course, if
* your signal handler doesn't call libssh at all, you're
* free to handle signals directly in sighandler.
*/
do{
FD_ZERO(&fds);
if(!eof)
FD_SET(0,&fds);
timeout.tv_sec=30;
timeout.tv_usec=0;
FD_SET(ssh_get_fd(session),&fds);
maxfd=ssh_get_fd(session)+1;
ret=select(maxfd,&fds,NULL,NULL,&timeout);
if(ret==EINTR)
continue;
if(FD_ISSET(0,&fds)){
lus=read(0,buffer,sizeof(buffer));
if(lus)
ssh_channel_write(channel,buffer,lus);
else {
eof=1;
ssh_channel_send_eof(channel);
}
}
if(FD_ISSET(ssh_get_fd(session),&fds)){
ssh_set_fd_toread(session);
}
channels[0]=channel; // set the first channel we want to read from
channels[1]=NULL;
ret=ssh_channel_select(channels,NULL,NULL,NULL); // no specific timeout - just poll
if(signal_delayed)
sizechanged();
} while (ret==EINTR || ret==SSH_EINTR);
// we already looked for input from stdin. Now, we are looking for input from the channel
if(channel && ssh_channel_is_closed(channel)){
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
ssh_channel_free(channel);
channel=NULL;
channels[0]=NULL;
}
if(channels[0]){
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)>0){
lus=channel_read_buffer(channel,readbuf,0,0);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
ssh_channel_free(channel);
channel=channels[0]=NULL;
} else
if (write(1,ssh_buffer_get_begin(readbuf),lus) < 0) {
fprintf(stderr, "Error writing to buffer\n");
return;
}
}
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)>0){ /* stderr */
lus=channel_read_buffer(channel,readbuf,0,1);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
ssh_channel_free(channel);
channel=channels[0]=NULL;
} else
if (write(2,ssh_buffer_get_begin(readbuf),lus) < 0) {
fprintf(stderr, "Error writing to buffer\n");
return;
}
}
}
if(channel && ssh_channel_is_closed(channel)){
ssh_channel_free(channel);
channel=NULL;
}
}
ssh_buffer_free(readbuf);
}
#else /* CHANNEL_SELECT */
static void select_loop(ssh_session session,ssh_channel channel){
fd_set fds;
struct timeval timeout;
char buffer[4096];
/* channels will be set to the channels to poll.
* outchannels will contain the result of the poll
*/
ssh_channel channels[2], outchannels[2];
int lus;
int eof=0;
int maxfd;
unsigned int r;
int ret;
while(channel){
do{
FD_ZERO(&fds);
if(!eof)
FD_SET(0,&fds);
timeout.tv_sec=30;
timeout.tv_usec=0;
FD_SET(ssh_get_fd(session),&fds);
maxfd=ssh_get_fd(session)+1;
channels[0]=channel; // set the first channel we want to read from
channels[1]=NULL;
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
if(signal_delayed)
sizechanged();
if(ret==EINTR)
continue;
if(FD_ISSET(0,&fds)){
lus=read(0,buffer,sizeof(buffer));
if(lus)
ssh_channel_write(channel,buffer,lus);
else {
eof=1;
ssh_channel_send_eof(channel);
}
}
if(channel && ssh_channel_is_closed(channel)){
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
ssh_channel_free(channel);
channel=NULL;
channels[0]=NULL;
}
if(outchannels[0]){
while(channel && ssh_channel_is_open(channel) && (r = ssh_channel_poll(channel,0))!=0){
lus=ssh_channel_read(channel,buffer,sizeof(buffer) > r ? r : sizeof(buffer),0);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
ssh_channel_free(channel);
channel=channels[0]=NULL;
} else
if (write(1,buffer,lus) < 0) {
fprintf(stderr, "Error writing to buffer\n");
return;
}
}
while(channel && ssh_channel_is_open(channel) && (r = ssh_channel_poll(channel,1))!=0){ /* stderr */
lus=ssh_channel_read(channel,buffer,sizeof(buffer) > r ? r : sizeof(buffer),1);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
ssh_channel_free(channel);
channel=channels[0]=NULL;
} else
if (write(2,buffer,lus) < 0) {
fprintf(stderr, "Error writing to buffer\n");
return;
}
}
}
if(channel && ssh_channel_is_closed(channel)){
ssh_channel_free(channel);
channel=NULL;
}
} while (ret==EINTR || ret==SSH_EINTR);
}
}
#endif
static void shell(ssh_session session){
ssh_channel channel;
struct termios terminal_local;
int interactive=isatty(0);
channel = ssh_channel_new(session);
if(interactive){
tcgetattr(0,&terminal_local);
memcpy(&terminal,&terminal_local,sizeof(struct termios));
}
if(ssh_channel_open_session(channel)){
printf("error opening channel : %s\n",ssh_get_error(session));
return;
}
chan=channel;
if(interactive){
ssh_channel_request_pty(channel);
sizechanged();
}
if(ssh_channel_request_shell(channel)){
printf("Requesting shell : %s\n",ssh_get_error(session));
return;
}
if(interactive){
cfmakeraw(&terminal_local);
tcsetattr(0,TCSANOW,&terminal_local);
setsignal();
}
signal(SIGTERM,do_cleanup);
select_loop(session,channel);
if(interactive)
do_cleanup(0);
}
static void batch_shell(ssh_session session){
ssh_channel channel;
char buffer[1024];
int i,s=0;
for(i=0;i<MAXCMD && cmds[i];++i) {
s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]);
free(cmds[i]);
cmds[i] = NULL;
}
channel=ssh_channel_new(session);
ssh_channel_open_session(channel);
if(ssh_channel_request_exec(channel,buffer)){
printf("error executing \"%s\" : %s\n",buffer,ssh_get_error(session));
return;
}
select_loop(session,channel);
}
static int client(ssh_session session){
int auth=0;
char *banner;
int state;
if (user)
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0)
return -1;
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
return -1;
if (proxycommand != NULL){
if(ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, proxycommand))
return -1;
}
ssh_options_parse_config(session, NULL);
if(ssh_connect(session)){
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
return -1;
}
state=verify_knownhost(session);
if (state != 0)
return -1;
ssh_userauth_none(session, NULL);
banner=ssh_get_issue_banner(session);
if(banner){
printf("%s\n",banner);
free(banner);
}
auth=authenticate_console(session);
if(auth != SSH_AUTH_SUCCESS){
return -1;
}
ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success");
if(!cmds[0])
shell(session);
else
batch_shell(session);
return 0;
}
ssh_pcap_file pcap;
void set_pcap(ssh_session session);
void set_pcap(ssh_session session){
if(!pcap_file)
return;
pcap=ssh_pcap_file_new();
if(!pcap)
return;
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
printf("Error opening pcap file\n");
ssh_pcap_file_free(pcap);
pcap=NULL;
return;
}
ssh_set_pcap_file(session,pcap);
}
void cleanup_pcap(void);
void cleanup_pcap(){
if(pcap)
ssh_pcap_file_free(pcap);
pcap=NULL;
}
int main(int argc, char **argv){
ssh_session session;
session = ssh_new();
ssh_callbacks_init(&cb);
ssh_set_callbacks(session,&cb);
if(ssh_options_getopt(session, &argc, argv)) {
fprintf(stderr, "error parsing command line :%s\n",
ssh_get_error(session));
usage();
}
opts(argc,argv);
signal(SIGTERM, do_exit);
set_pcap(session);
client(session);
ssh_disconnect(session);
ssh_free(session);
cleanup_pcap();
ssh_finalize();
return 0;
}
+266
View File
@@ -0,0 +1,266 @@
/*
Copyright 2003-2009 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
#include "config.h"
#include <sys/statvfs.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include "examples_common.h"
#ifdef WITH_SFTP
static int verbosity;
static char *destination;
#define DATALEN 65536
static void do_sftp(ssh_session session){
sftp_session sftp=sftp_new(session);
sftp_dir dir;
sftp_attributes file;
sftp_statvfs_t sftpstatvfs;
struct statvfs sysstatvfs;
sftp_file fichier;
sftp_file to;
int len=1;
unsigned int i;
char data[DATALEN]={0};
char *lnk;
unsigned int count;
if(!sftp){
fprintf(stderr, "sftp error initialising channel: %s\n",
ssh_get_error(session));
return;
}
if(sftp_init(sftp)){
fprintf(stderr, "error initialising sftp: %s\n",
ssh_get_error(session));
return;
}
printf("Additional SFTP extensions provided by the server:\n");
count = sftp_extensions_get_count(sftp);
for (i = 0; i < count; i++) {
printf("\t%s, version: %s\n",
sftp_extensions_get_name(sftp, i),
sftp_extensions_get_data(sftp, i));
}
/* test symlink and readlink */
if (sftp_symlink(sftp, "/tmp/this_is_the_link",
"/tmp/sftp_symlink_test") < 0) {
fprintf(stderr, "Could not create link (%s)\n", ssh_get_error(session));
return;
}
lnk = sftp_readlink(sftp, "/tmp/sftp_symlink_test");
if (lnk == NULL) {
fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session));
return;
}
printf("readlink /tmp/sftp_symlink_test: %s\n", lnk);
sftp_unlink(sftp, "/tmp/sftp_symlink_test");
if (sftp_extension_supported(sftp, "statvfs@openssh.com", "2")) {
sftpstatvfs = sftp_statvfs(sftp, "/tmp");
if (sftpstatvfs == NULL) {
fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session));
return;
}
printf("sftp statvfs:\n"
"\tfile system block size: %llu\n"
"\tfundamental fs block size: %llu\n"
"\tnumber of blocks (unit f_frsize): %llu\n"
"\tfree blocks in file system: %llu\n"
"\tfree blocks for non-root: %llu\n"
"\ttotal file inodes: %llu\n"
"\tfree file inodes: %llu\n"
"\tfree file inodes for to non-root: %llu\n"
"\tfile system id: %llu\n"
"\tbit mask of f_flag values: %llu\n"
"\tmaximum filename length: %llu\n",
(unsigned long long) sftpstatvfs->f_bsize,
(unsigned long long) sftpstatvfs->f_frsize,
(unsigned long long) sftpstatvfs->f_blocks,
(unsigned long long) sftpstatvfs->f_bfree,
(unsigned long long) sftpstatvfs->f_bavail,
(unsigned long long) sftpstatvfs->f_files,
(unsigned long long) sftpstatvfs->f_ffree,
(unsigned long long) sftpstatvfs->f_favail,
(unsigned long long) sftpstatvfs->f_fsid,
(unsigned long long) sftpstatvfs->f_flag,
(unsigned long long) sftpstatvfs->f_namemax);
sftp_statvfs_free(sftpstatvfs);
if (statvfs("/tmp", &sysstatvfs) < 0) {
fprintf(stderr, "statvfs failed (%s)\n", strerror(errno));
return;
}
printf("sys statvfs:\n"
"\tfile system block size: %llu\n"
"\tfundamental fs block size: %llu\n"
"\tnumber of blocks (unit f_frsize): %llu\n"
"\tfree blocks in file system: %llu\n"
"\tfree blocks for non-root: %llu\n"
"\ttotal file inodes: %llu\n"
"\tfree file inodes: %llu\n"
"\tfree file inodes for to non-root: %llu\n"
"\tfile system id: %llu\n"
"\tbit mask of f_flag values: %llu\n"
"\tmaximum filename length: %llu\n",
(unsigned long long) sysstatvfs.f_bsize,
(unsigned long long) sysstatvfs.f_frsize,
(unsigned long long) sysstatvfs.f_blocks,
(unsigned long long) sysstatvfs.f_bfree,
(unsigned long long) sysstatvfs.f_bavail,
(unsigned long long) sysstatvfs.f_files,
(unsigned long long) sysstatvfs.f_ffree,
(unsigned long long) sysstatvfs.f_favail,
(unsigned long long) sysstatvfs.f_fsid,
(unsigned long long) sysstatvfs.f_flag,
(unsigned long long) sysstatvfs.f_namemax);
}
/* the connection is made */
/* opening a directory */
dir=sftp_opendir(sftp,"./");
if(!dir) {
fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session));
return ;
}
/* reading the whole directory, file by file */
while((file=sftp_readdir(sftp,dir))){
fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n",
file->name,
file->permissions,
file->owner,
file->uid,
file->group,
file->gid,
(long long unsigned int) file->size);
sftp_attributes_free(file);
}
/* when file=NULL, an error has occured OR the directory listing is end of file */
if(!sftp_dir_eof(dir)){
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
return;
}
if(sftp_closedir(dir)){
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
return;
}
/* this will open a file and copy it into your /home directory */
/* the small buffer size was intended to stress the library. of course, you can use a buffer till 20kbytes without problem */
fichier=sftp_open(sftp,"/usr/bin/ssh",O_RDONLY, 0);
if(!fichier){
fprintf(stderr, "Error opening /usr/bin/ssh: %s\n",
ssh_get_error(session));
return;
}
/* open a file for writing... */
to=sftp_open(sftp,"ssh-copy",O_WRONLY | O_CREAT, 0700);
if(!to){
fprintf(stderr, "Error opening ssh-copy for writing: %s\n",
ssh_get_error(session));
return;
}
while((len=sftp_read(fichier,data,4096)) > 0){
if(sftp_write(to,data,len)!=len){
fprintf(stderr, "Error writing %d bytes: %s\n",
len, ssh_get_error(session));
return;
}
}
printf("finished\n");
if(len<0)
fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session));
sftp_close(fichier);
sftp_close(to);
printf("fichiers ferm\n");
to=sftp_open(sftp,"/tmp/grosfichier",O_WRONLY|O_CREAT, 0644);
for(i=0;i<1000;++i){
len=sftp_write(to,data,DATALEN);
printf("wrote %d bytes\n",len);
if(len != DATALEN){
printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session));
}
}
sftp_close(to);
/* close the sftp session */
sftp_free(sftp);
printf("sftp session terminated\n");
}
static void usage(const char *argv0){
fprintf(stderr,"Usage : %s [-v] remotehost\n"
"sample sftp test client - libssh-%s\n"
"Options :\n"
" -v : increase log verbosity\n",
argv0,
ssh_version(0));
exit(0);
}
static int opts(int argc, char **argv){
int i;
while((i=getopt(argc,argv,"v"))!=-1){
switch(i){
case 'v':
verbosity++;
break;
default:
fprintf(stderr,"unknown option %c\n",optopt);
usage(argv[0]);
return -1;
}
}
destination=argv[optind];
if(destination == NULL){
usage(argv[0]);
return -1;
}
return 0;
}
int main(int argc, char **argv){
ssh_session session;
if(opts(argc,argv)<0)
return EXIT_FAILURE;
session=connect_ssh(destination,NULL,verbosity);
if(session == NULL)
return EXIT_FAILURE;
do_sftp(session);
ssh_disconnect(session);
ssh_free(session);
return 0;
}
#endif
+413
View File
@@ -0,0 +1,413 @@
/* This is a sample implementation of a libssh based SSH server */
/*
Copyright 2003-2011 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
#include "config.h"
#include <libssh/libssh.h>
#include <libssh/server.h>
#ifdef HAVE_ARGP_H
#include <argp.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define SSHD_USER "libssh"
#define SSHD_PASSWORD "libssh"
#ifndef KEYS_FOLDER
#ifdef _WIN32
#define KEYS_FOLDER
#else
#define KEYS_FOLDER "/etc/ssh/"
#endif
#endif
#ifdef WITH_PCAP
static const char *pcap_file = "debug.server.pcap";
static ssh_pcap_file pcap;
static void set_pcap(ssh_session session){
if(!pcap_file)
return;
pcap=ssh_pcap_file_new();
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
printf("Error opening pcap file\n");
ssh_pcap_file_free(pcap);
pcap=NULL;
return;
}
ssh_set_pcap_file(session,pcap);
}
static void cleanup_pcap(void) {
ssh_pcap_file_free(pcap);
pcap=NULL;
}
#endif
static int auth_password(const char *user, const char *password){
if(strcmp(user, SSHD_USER))
return 0;
if(strcmp(password, SSHD_PASSWORD))
return 0;
return 1; // authenticated
}
#ifdef HAVE_ARGP_H
const char *argp_program_version = "libssh server example "
SSH_STRINGIFY(LIBSSH_VERSION);
const char *argp_program_bug_address = "<libssh@libssh.org>";
/* Program documentation. */
static char doc[] = "libssh -- a Secure Shell protocol implementation";
/* A description of the arguments we accept. */
static char args_doc[] = "BINDADDR";
static int port = 22;
/* The options we understand. */
static struct argp_option options[] = {
{
.name = "port",
.key = 'p',
.arg = "PORT",
.flags = 0,
.doc = "Set the port to bind.",
.group = 0
},
{
.name = "hostkey",
.key = 'k',
.arg = "FILE",
.flags = 0,
.doc = "Set the host key.",
.group = 0
},
{
.name = "dsakey",
.key = 'd',
.arg = "FILE",
.flags = 0,
.doc = "Set the dsa key.",
.group = 0
},
{
.name = "rsakey",
.key = 'r',
.arg = "FILE",
.flags = 0,
.doc = "Set the rsa key.",
.group = 0
},
{
.name = "verbose",
.key = 'v',
.arg = NULL,
.flags = 0,
.doc = "Get verbose output.",
.group = 0
},
{NULL, 0, 0, 0, NULL, 0}
};
/* Parse a single option. */
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
/* Get the input argument from argp_parse, which we
* know is a pointer to our arguments structure.
*/
ssh_bind sshbind = state->input;
switch (key) {
case 'p':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
port = atoi(arg);
break;
case 'd':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
break;
case 'k':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
break;
case 'r':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
break;
case 'v':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
break;
case ARGP_KEY_ARG:
if (state->arg_num >= 1) {
/* Too many arguments. */
argp_usage (state);
}
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
break;
case ARGP_KEY_END:
if (state->arg_num < 1) {
/* Not enough arguments. */
argp_usage (state);
}
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
/* Our argp parser. */
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
#endif /* HAVE_ARGP_H */
static const char *name;
static const char *instruction;
static const char *prompts[2];
static char echo[] = { 1, 0 };
static int kbdint_check_response(ssh_session session) {
int count;
count = ssh_userauth_kbdint_getnanswers(session);
if(count != 2) {
instruction = "Something weird happened :(";
return 0;
}
if(strcasecmp("Arthur Dent",
ssh_userauth_kbdint_getanswer(session, 0)) != 0) {
instruction = "OK, this is not YOUR name, "
"but it's a reference to the HGTG...";
prompts[0] = "The main character's full name: ";
return 0;
}
if(strcmp("42", ssh_userauth_kbdint_getanswer(session, 1)) != 0) {
instruction = "Make an effort !!! What is the Answer to the Ultimate "
"Question of Life, the Universe, and Everything ?";
prompts[1] = "Answer to the Ultimate Question of Life, the Universe, "
"and Everything: ";
return 0;
}
return 1;
}
static int authenticate(ssh_session session) {
ssh_message message;
name = "\n\nKeyboard-Interactive Fancy Authentication\n";
instruction = "Please enter your real name and your password";
prompts[0] = "Real name: ";
prompts[1] = "Password: ";
do {
message=ssh_message_get(session);
if(!message)
break;
switch(ssh_message_type(message)){
case SSH_REQUEST_AUTH:
switch(ssh_message_subtype(message)){
case SSH_AUTH_METHOD_PASSWORD:
printf("User %s wants to auth with pass %s\n",
ssh_message_auth_user(message),
ssh_message_auth_password(message));
if(auth_password(ssh_message_auth_user(message),
ssh_message_auth_password(message))){
ssh_message_auth_reply_success(message,0);
ssh_message_free(message);
return 1;
}
ssh_message_auth_set_methods(message,
SSH_AUTH_METHOD_PASSWORD |
SSH_AUTH_METHOD_INTERACTIVE);
// not authenticated, send default message
ssh_message_reply_default(message);
break;
case SSH_AUTH_METHOD_INTERACTIVE:
if(!ssh_message_auth_kbdint_is_response(message)) {
printf("User %s wants to auth with kbdint\n",
ssh_message_auth_user(message));
ssh_message_auth_interactive_request(message, name,
instruction, 2, prompts, echo);
} else {
if(kbdint_check_response(session)) {
ssh_message_auth_reply_success(message,0);
ssh_message_free(message);
return 1;
}
ssh_message_auth_set_methods(message,
SSH_AUTH_METHOD_PASSWORD |
SSH_AUTH_METHOD_INTERACTIVE);
ssh_message_reply_default(message);
}
break;
case SSH_AUTH_METHOD_NONE:
default:
printf("User %s wants to auth with unknown auth %d\n",
ssh_message_auth_user(message),
ssh_message_subtype(message));
ssh_message_auth_set_methods(message,
SSH_AUTH_METHOD_PASSWORD |
SSH_AUTH_METHOD_INTERACTIVE);
ssh_message_reply_default(message);
break;
}
break;
default:
ssh_message_auth_set_methods(message,
SSH_AUTH_METHOD_PASSWORD |
SSH_AUTH_METHOD_INTERACTIVE);
ssh_message_reply_default(message);
}
ssh_message_free(message);
} while (1);
return 0;
}
int main(int argc, char **argv){
ssh_session session;
ssh_bind sshbind;
ssh_message message;
ssh_channel chan=0;
char buf[2048];
int auth=0;
int shell=0;
int i;
int r;
sshbind=ssh_bind_new();
session=ssh_new();
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY,
KEYS_FOLDER "ssh_host_dsa_key");
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY,
KEYS_FOLDER "ssh_host_rsa_key");
#ifdef HAVE_ARGP_H
/*
* Parse our arguments; every option seen by parse_opt will
* be reflected in arguments.
*/
argp_parse (&argp, argc, argv, 0, 0, sshbind);
#else
(void) argc;
(void) argv;
#endif
#ifdef WITH_PCAP
set_pcap(session);
#endif
if(ssh_bind_listen(sshbind)<0){
printf("Error listening to socket: %s\n", ssh_get_error(sshbind));
return 1;
}
printf("Started sample libssh sshd on port %d\n", port);
printf("You can login as the user %s with the password %s\n", SSHD_USER,
SSHD_PASSWORD);
r = ssh_bind_accept(sshbind, session);
if(r==SSH_ERROR){
printf("Error accepting a connection: %s\n", ssh_get_error(sshbind));
return 1;
}
if (ssh_handle_key_exchange(session)) {
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
return 1;
}
/* proceed to authentication */
auth = authenticate(session);
if(!auth){
printf("Authentication error: %s\n", ssh_get_error(session));
ssh_disconnect(session);
return 1;
}
/* wait for a channel session */
do {
message = ssh_message_get(session);
if(message){
if(ssh_message_type(message) == SSH_REQUEST_CHANNEL_OPEN &&
ssh_message_subtype(message) == SSH_CHANNEL_SESSION) {
chan = ssh_message_channel_request_open_reply_accept(message);
ssh_message_free(message);
break;
} else {
ssh_message_reply_default(message);
ssh_message_free(message);
}
} else {
break;
}
} while(!chan);
if(!chan) {
printf("Error: cleint did not ask for a channel session (%s)\n",
ssh_get_error(session));
ssh_finalize();
return 1;
}
/* wait for a shell */
do {
message = ssh_message_get(session);
if(message != NULL) {
if(ssh_message_type(message) == SSH_REQUEST_CHANNEL &&
ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_SHELL) {
shell = 1;
ssh_message_channel_request_reply_success(message);
ssh_message_free(message);
break;
}
ssh_message_reply_default(message);
ssh_message_free(message);
} else {
break;
}
} while(!shell);
if(!shell) {
printf("Error: No shell requested (%s)\n", ssh_get_error(session));
return 1;
}
printf("it works !\n");
do{
i=ssh_channel_read(chan,buf, 2048, 0);
if(i>0) {
if(*buf == '' || *buf == '')
break;
if(i == 1 && *buf == '\r')
ssh_channel_write(chan, "\r\n", 2);
else
ssh_channel_write(chan, buf, i);
if (write(1,buf,i) < 0) {
printf("error writing to buffer\n");
return 1;
}
}
} while (i>0);
ssh_channel_close(chan);
ssh_disconnect(session);
ssh_bind_free(sshbind);
#ifdef WITH_PCAP
cleanup_pcap();
#endif
ssh_finalize();
return 0;
}
+453
View File
@@ -0,0 +1,453 @@
/* This is a sample implementation of a libssh based SSH server */
/*
Copyright 2003-2011 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
#include "config.h"
#include <libssh/libssh.h>
#include <libssh/server.h>
#include <libssh/callbacks.h>
#ifdef HAVE_ARGP_H
#include <argp.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <poll.h>
#include <pty.h>
#define SSHD_USER "libssh"
#define SSHD_PASSWORD "libssh"
#ifndef KEYS_FOLDER
#ifdef _WIN32
#define KEYS_FOLDER
#else
#define KEYS_FOLDER "/etc/ssh/"
#endif
#endif
#ifdef WITH_PCAP
const char *pcap_file="debug.server.pcap";
ssh_pcap_file pcap;
static void set_pcap(ssh_session session){
if(!pcap_file)
return;
pcap=ssh_pcap_file_new();
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
printf("Error opening pcap file\n");
ssh_pcap_file_free(pcap);
pcap=NULL;
return;
}
ssh_set_pcap_file(session,pcap);
}
static void cleanup_pcap(){
ssh_pcap_file_free(pcap);
pcap=NULL;
}
#endif
static int auth_password(const char *user, const char *password){
if(strcmp(user, SSHD_USER))
return 0;
if(strcmp(password, SSHD_PASSWORD))
return 0;
return 1; // authenticated
}
#ifdef HAVE_ARGP_H
const char *argp_program_version = "libssh server example "
SSH_STRINGIFY(LIBSSH_VERSION);
const char *argp_program_bug_address = "<libssh@libssh.org>";
/* Program documentation. */
static char doc[] = "libssh -- a Secure Shell protocol implementation";
/* A description of the arguments we accept. */
static char args_doc[] = "BINDADDR";
static int port = 22;
/* The options we understand. */
static struct argp_option options[] = {
{
.name = "port",
.key = 'p',
.arg = "PORT",
.flags = 0,
.doc = "Set the port to bind.",
.group = 0
},
{
.name = "hostkey",
.key = 'k',
.arg = "FILE",
.flags = 0,
.doc = "Set the host key.",
.group = 0
},
{
.name = "dsakey",
.key = 'd',
.arg = "FILE",
.flags = 0,
.doc = "Set the dsa key.",
.group = 0
},
{
.name = "rsakey",
.key = 'r',
.arg = "FILE",
.flags = 0,
.doc = "Set the rsa key.",
.group = 0
},
{
.name = "verbose",
.key = 'v',
.arg = NULL,
.flags = 0,
.doc = "Get verbose output.",
.group = 0
},
{NULL, 0, 0, 0, NULL, 0}
};
/* Parse a single option. */
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
/* Get the input argument from argp_parse, which we
* know is a pointer to our arguments structure.
*/
ssh_bind sshbind = state->input;
switch (key) {
case 'p':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
port = atoi(arg);
break;
case 'd':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
break;
case 'k':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
break;
case 'r':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
break;
case 'v':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
break;
case ARGP_KEY_ARG:
if (state->arg_num >= 1) {
/* Too many arguments. */
argp_usage (state);
}
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
break;
case ARGP_KEY_END:
if (state->arg_num < 1) {
/* Not enough arguments. */
argp_usage (state);
}
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
/* Our argp parser. */
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
#endif /* HAVE_ARGP_H */
static int authenticate(ssh_session session) {
ssh_message message;
do {
message=ssh_message_get(session);
if(!message)
break;
switch(ssh_message_type(message)){
case SSH_REQUEST_AUTH:
switch(ssh_message_subtype(message)){
case SSH_AUTH_METHOD_PASSWORD:
printf("User %s wants to auth with pass %s\n",
ssh_message_auth_user(message),
ssh_message_auth_password(message));
if(auth_password(ssh_message_auth_user(message),
ssh_message_auth_password(message))){
ssh_message_auth_reply_success(message,0);
ssh_message_free(message);
return 1;
}
ssh_message_auth_set_methods(message,
SSH_AUTH_METHOD_PASSWORD |
SSH_AUTH_METHOD_INTERACTIVE);
// not authenticated, send default message
ssh_message_reply_default(message);
break;
case SSH_AUTH_METHOD_NONE:
default:
printf("User %s wants to auth with unknown auth %d\n",
ssh_message_auth_user(message),
ssh_message_subtype(message));
ssh_message_auth_set_methods(message,
SSH_AUTH_METHOD_PASSWORD |
SSH_AUTH_METHOD_INTERACTIVE);
ssh_message_reply_default(message);
break;
}
break;
default:
ssh_message_auth_set_methods(message,
SSH_AUTH_METHOD_PASSWORD |
SSH_AUTH_METHOD_INTERACTIVE);
ssh_message_reply_default(message);
}
ssh_message_free(message);
} while (1);
return 0;
}
static int copy_fd_to_chan(socket_t fd, int revents, void *userdata) {
ssh_channel chan = (ssh_channel)userdata;
char buf[2048];
int sz = 0;
if(!chan) {
close(fd);
return -1;
}
if(revents & POLLIN) {
sz = read(fd, buf, 2048);
if(sz > 0) {
ssh_channel_write(chan, buf, sz);
}
}
if(revents & POLLHUP) {
ssh_channel_close(chan);
sz = -1;
}
return sz;
}
static int copy_chan_to_fd(ssh_session session,
ssh_channel channel,
void *data,
uint32_t len,
int is_stderr,
void *userdata) {
int fd = *(int*)userdata;
int sz;
(void)session;
(void)channel;
(void)is_stderr;
sz = write(fd, data, len);
return sz;
}
static void chan_close(ssh_session session, ssh_channel channel, void *userdata) {
int fd = *(int*)userdata;
(void)session;
(void)channel;
close(fd);
}
struct ssh_channel_callbacks_struct cb = {
.channel_data_function = copy_chan_to_fd,
.channel_eof_function = chan_close,
.channel_close_function = chan_close,
.userdata = NULL
};
static int main_loop(ssh_channel chan) {
ssh_session session = ssh_channel_get_session(chan);
socket_t fd;
struct termios *term = NULL;
struct winsize *win = NULL;
pid_t childpid;
ssh_event event;
short events;
childpid = forkpty(&fd, NULL, term, win);
if(childpid == 0) {
execl("/bin/bash", "/bin/bash", (char *)NULL);
abort();
}
cb.userdata = &fd;
ssh_callbacks_init(&cb);
ssh_set_channel_callbacks(chan, &cb);
events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
event = ssh_event_new();
if(event == NULL) {
printf("Couldn't get a event\n");
return -1;
}
if(ssh_event_add_fd(event, fd, events, copy_fd_to_chan, chan) != SSH_OK) {
printf("Couldn't add an fd to the event\n");
return -1;
}
if(ssh_event_add_session(event, session) != SSH_OK) {
printf("Couldn't add the session to the event\n");
return -1;
}
do {
ssh_event_dopoll(event, 1000);
} while(!ssh_channel_is_closed(chan));
ssh_event_remove_fd(event, fd);
ssh_event_remove_session(event, session);
ssh_event_free(event);
return 0;
}
int main(int argc, char **argv){
ssh_session session;
ssh_bind sshbind;
ssh_message message;
ssh_channel chan=0;
int auth=0;
int shell=0;
int r;
sshbind=ssh_bind_new();
session=ssh_new();
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY,
KEYS_FOLDER "ssh_host_dsa_key");
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY,
KEYS_FOLDER "ssh_host_rsa_key");
#ifdef HAVE_ARGP_H
/*
* Parse our arguments; every option seen by parse_opt will
* be reflected in arguments.
*/
argp_parse (&argp, argc, argv, 0, 0, sshbind);
#else
(void) argc;
(void) argv;
#endif
#ifdef WITH_PCAP
set_pcap(session);
#endif
if(ssh_bind_listen(sshbind)<0){
printf("Error listening to socket: %s\n", ssh_get_error(sshbind));
return 1;
}
printf("Started sample libssh sshd on port %d\n", port);
printf("You can login as the user %s with the password %s\n", SSHD_USER,
SSHD_PASSWORD);
r = ssh_bind_accept(sshbind, session);
if(r==SSH_ERROR){
printf("Error accepting a connection: %s\n", ssh_get_error(sshbind));
return 1;
}
if (ssh_handle_key_exchange(session)) {
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
return 1;
}
/* proceed to authentication */
auth = authenticate(session);
if(!auth){
printf("Authentication error: %s\n", ssh_get_error(session));
ssh_disconnect(session);
return 1;
}
/* wait for a channel session */
do {
message = ssh_message_get(session);
if(message){
if(ssh_message_type(message) == SSH_REQUEST_CHANNEL_OPEN &&
ssh_message_subtype(message) == SSH_CHANNEL_SESSION) {
chan = ssh_message_channel_request_open_reply_accept(message);
ssh_message_free(message);
break;
} else {
ssh_message_reply_default(message);
ssh_message_free(message);
}
} else {
break;
}
} while(!chan);
if(!chan) {
printf("Error: cleint did not ask for a channel session (%s)\n",
ssh_get_error(session));
ssh_finalize();
return 1;
}
/* wait for a shell */
do {
message = ssh_message_get(session);
if(message != NULL) {
if(ssh_message_type(message) == SSH_REQUEST_CHANNEL) {
if(ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_SHELL) {
shell = 1;
ssh_message_channel_request_reply_success(message);
ssh_message_free(message);
break;
} else if(ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_PTY) {
ssh_message_channel_request_reply_success(message);
ssh_message_free(message);
continue;
}
}
ssh_message_reply_default(message);
ssh_message_free(message);
} else {
break;
}
} while(!shell);
if(!shell) {
printf("Error: No shell requested (%s)\n", ssh_get_error(session));
return 1;
}
printf("it works !\n");
main_loop(chan);
ssh_disconnect(session);
ssh_bind_free(sshbind);
#ifdef WITH_PCAP
cleanup_pcap();
#endif
ssh_finalize();
return 0;
}
+314
View File
@@ -0,0 +1,314 @@
/* This is a sample implementation of a libssh based SSH server */
/*
Copyright 2003-2009 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
#include "config.h"
#include <libssh/libssh.h>
#include <libssh/server.h>
#ifdef HAVE_ARGP_H
#include <argp.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifndef KEYS_FOLDER
#ifdef _WIN32
#define KEYS_FOLDER
#else
#define KEYS_FOLDER "/etc/ssh/"
#endif
#endif
#ifdef WITH_PCAP
static const char *pcap_file="debug.server.pcap";
static ssh_pcap_file pcap;
static void set_pcap(ssh_session session) {
if(!pcap_file)
return;
pcap=ssh_pcap_file_new();
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
printf("Error opening pcap file\n");
ssh_pcap_file_free(pcap);
pcap=NULL;
return;
}
ssh_set_pcap_file(session,pcap);
}
static void cleanup_pcap(void) {
ssh_pcap_file_free(pcap);
pcap=NULL;
}
#endif
static int auth_password(const char *user, const char *password){
if(strcmp(user,"aris"))
return 0;
if(strcmp(password,"lala"))
return 0;
return 1; // authenticated
}
#ifdef HAVE_ARGP_H
const char *argp_program_version = "libssh server example "
SSH_STRINGIFY(LIBSSH_VERSION);
const char *argp_program_bug_address = "<libssh@libssh.org>";
/* Program documentation. */
static char doc[] = "libssh -- a Secure Shell protocol implementation";
/* A description of the arguments we accept. */
static char args_doc[] = "BINDADDR";
/* The options we understand. */
static struct argp_option options[] = {
{
.name = "port",
.key = 'p',
.arg = "PORT",
.flags = 0,
.doc = "Set the port to bind.",
.group = 0
},
{
.name = "hostkey",
.key = 'k',
.arg = "FILE",
.flags = 0,
.doc = "Set the host key.",
.group = 0
},
{
.name = "dsakey",
.key = 'd',
.arg = "FILE",
.flags = 0,
.doc = "Set the dsa key.",
.group = 0
},
{
.name = "rsakey",
.key = 'r',
.arg = "FILE",
.flags = 0,
.doc = "Set the rsa key.",
.group = 0
},
{
.name = "verbose",
.key = 'v',
.arg = NULL,
.flags = 0,
.doc = "Get verbose output.",
.group = 0
},
{NULL, 0, NULL, 0, NULL, 0}
};
/* Parse a single option. */
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
/* Get the input argument from argp_parse, which we
* know is a pointer to our arguments structure.
*/
ssh_bind sshbind = state->input;
switch (key) {
case 'p':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
break;
case 'd':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
break;
case 'k':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
break;
case 'r':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
break;
case 'v':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
break;
case ARGP_KEY_ARG:
if (state->arg_num >= 1) {
/* Too many arguments. */
argp_usage (state);
}
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
break;
case ARGP_KEY_END:
if (state->arg_num < 1) {
/* Not enough arguments. */
argp_usage (state);
}
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
/* Our argp parser. */
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
#endif /* HAVE_ARGP_H */
int main(int argc, char **argv){
ssh_session session;
ssh_bind sshbind;
ssh_message message;
ssh_channel chan=0;
char buf[2048];
int auth=0;
int sftp=0;
int i;
int r;
sshbind=ssh_bind_new();
session=ssh_new();
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");
#ifdef HAVE_ARGP_H
/*
* Parse our arguments; every option seen by parse_opt will
* be reflected in arguments.
*/
argp_parse (&argp, argc, argv, 0, 0, sshbind);
#else
(void) argc;
(void) argv;
#endif
#ifdef WITH_PCAP
set_pcap(session);
#endif
if(ssh_bind_listen(sshbind)<0){
printf("Error listening to socket: %s\n",ssh_get_error(sshbind));
return 1;
}
r=ssh_bind_accept(sshbind,session);
if(r==SSH_ERROR){
printf("error accepting a connection : %s\n",ssh_get_error(sshbind));
return 1;
}
if (ssh_handle_key_exchange(session)) {
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
return 1;
}
do {
message=ssh_message_get(session);
if(!message)
break;
switch(ssh_message_type(message)){
case SSH_REQUEST_AUTH:
switch(ssh_message_subtype(message)){
case SSH_AUTH_METHOD_PASSWORD:
printf("User %s wants to auth with pass %s\n",
ssh_message_auth_user(message),
ssh_message_auth_password(message));
if(auth_password(ssh_message_auth_user(message),
ssh_message_auth_password(message))){
auth=1;
ssh_message_auth_reply_success(message,0);
break;
}
// not authenticated, send default message
case SSH_AUTH_METHOD_NONE:
default:
ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PASSWORD);
ssh_message_reply_default(message);
break;
}
break;
default:
ssh_message_reply_default(message);
}
ssh_message_free(message);
} while (!auth);
if(!auth){
printf("auth error: %s\n",ssh_get_error(session));
ssh_disconnect(session);
return 1;
}
do {
message=ssh_message_get(session);
if(message){
switch(ssh_message_type(message)){
case SSH_REQUEST_CHANNEL_OPEN:
if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){
chan=ssh_message_channel_request_open_reply_accept(message);
break;
}
default:
ssh_message_reply_default(message);
}
ssh_message_free(message);
}
} while(message && !chan);
if(!chan){
printf("error : %s\n",ssh_get_error(session));
ssh_finalize();
return 1;
}
do {
message=ssh_message_get(session);
if(message && ssh_message_type(message)==SSH_REQUEST_CHANNEL &&
(ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SHELL ||
ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_PTY)) {
// if(!strcmp(ssh_message_channel_request_subsystem(message),"sftp")){
sftp=1;
ssh_message_channel_request_reply_success(message);
break;
// }
}
if(!sftp){
ssh_message_reply_default(message);
}
ssh_message_free(message);
} while (message && !sftp);
if(!sftp){
printf("error : %s\n",ssh_get_error(session));
return 1;
}
printf("it works !\n");
do{
i=ssh_channel_read(chan,buf, 2048, 0);
if(i>0) {
ssh_channel_write(chan, buf, i);
if (write(1,buf,i) < 0) {
printf("error writing to buffer\n");
return 1;
}
if (buf[0] == '\x0d') {
if (write(1, "\n", 1) < 0) {
printf("error writing to buffer\n");
return 1;
}
ssh_channel_write(chan, "\n", 1);
}
}
} while (i>0);
ssh_disconnect(session);
ssh_bind_free(sshbind);
#ifdef WITH_PCAP
cleanup_pcap();
#endif
ssh_finalize();
return 0;
}
+165
View File
@@ -0,0 +1,165 @@
/* scp_download.c
* Sample implementation of a tiny SCP downloader client
*/
/*
Copyright 2009 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <libssh/libssh.h>
#include "examples_common.h"
int verbosity=0;
const char *createcommand="rm -fr /tmp/libssh_tests && mkdir /tmp/libssh_tests && cd /tmp/libssh_tests && date > a && date > b && mkdir c && date > d";
char *host=NULL;
static void usage(const char *argv0){
fprintf(stderr,"Usage : %s [options] host\n"
"sample tiny scp downloader client - libssh-%s\n"
"This program will create files in /tmp and try to fetch them\n",
// "Options :\n",
// " -r : use RSA to verify host public key\n",
argv0,
ssh_version(0));
exit(0);
}
static int opts(int argc, char **argv){
int i;
while((i=getopt(argc,argv,"v"))!=-1){
switch(i){
case 'v':
verbosity++;
break;
default:
fprintf(stderr,"unknown option %c\n",optopt);
usage(argv[0]);
return -1;
}
}
host = argv[optind];
if(host == NULL)
usage(argv[0]);
return 0;
}
static void create_files(ssh_session session){
ssh_channel channel=ssh_channel_new(session);
char buffer[1];
if(channel == NULL){
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
exit(EXIT_FAILURE);
}
if(ssh_channel_open_session(channel) != SSH_OK){
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
ssh_channel_free(channel);
exit(EXIT_FAILURE);
}
if(ssh_channel_request_exec(channel,createcommand) != SSH_OK){
fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session));
ssh_channel_close(channel);
ssh_channel_free(channel);
exit(EXIT_FAILURE);
}
while(!ssh_channel_is_eof(channel)){
ssh_channel_read(channel,buffer,1,1);
if (write(1,buffer,1) < 0) {
fprintf(stderr, "Error writing to buffer\n");
ssh_channel_close(channel);
ssh_channel_free(channel);
return;
}
}
ssh_channel_close(channel);
ssh_channel_free(channel);
}
static int fetch_files(ssh_session session){
int size;
char buffer[16384];
int mode;
char *filename;
int r;
ssh_scp scp=ssh_scp_new(session, SSH_SCP_READ | SSH_SCP_RECURSIVE, "/tmp/libssh_tests/*");
if(ssh_scp_init(scp) != SSH_OK){
fprintf(stderr,"error initializing scp: %s\n",ssh_get_error(session));
ssh_scp_free(scp);
return -1;
}
printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n");
do {
r=ssh_scp_pull_request(scp);
switch(r){
case SSH_SCP_REQUEST_NEWFILE:
size=ssh_scp_request_get_size(scp);
filename=strdup(ssh_scp_request_get_filename(scp));
mode=ssh_scp_request_get_permissions(scp);
printf("downloading file %s, size %d, perms 0%o\n",filename,size,mode);
free(filename);
ssh_scp_accept_request(scp);
r=ssh_scp_read(scp,buffer,sizeof(buffer));
if(r==SSH_ERROR){
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(session));
ssh_scp_close(scp);
ssh_scp_free(scp);
return -1;
}
printf("done\n");
break;
case SSH_ERROR:
fprintf(stderr,"Error: %s\n",ssh_get_error(session));
ssh_scp_close(scp);
ssh_scp_free(scp);
return -1;
case SSH_SCP_REQUEST_WARNING:
fprintf(stderr,"Warning: %s\n",ssh_scp_request_get_warning(scp));
break;
case SSH_SCP_REQUEST_NEWDIR:
filename=strdup(ssh_scp_request_get_filename(scp));
mode=ssh_scp_request_get_permissions(scp);
printf("downloading directory %s, perms 0%o\n",filename,mode);
free(filename);
ssh_scp_accept_request(scp);
break;
case SSH_SCP_REQUEST_ENDDIR:
printf("End of directory\n");
break;
case SSH_SCP_REQUEST_EOF:
printf("End of requests\n");
goto end;
}
} while (1);
end:
ssh_scp_close(scp);
ssh_scp_free(scp);
return 0;
}
int main(int argc, char **argv){
ssh_session session;
if(opts(argc,argv)<0)
return EXIT_FAILURE;
session=connect_ssh(host,NULL,verbosity);
if(session == NULL)
return EXIT_FAILURE;
create_files(session);
fetch_files(session);
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 0;
}
+64
View File
@@ -0,0 +1,64 @@
#include <stdio.h>
#include <libssh/libssh.h>
#include "examples_common.h"
#define LIMIT 0x100000000
int main(void) {
ssh_session session;
ssh_channel channel;
char buffer[1024*1024];
int rc;
uint64_t total=0;
uint64_t lastshown=4096;
session = connect_ssh("localhost", NULL, 0);
if (session == NULL) {
return 1;
}
channel = ssh_channel_new(session);;
if (channel == NULL) {
ssh_disconnect(session);
return 1;
}
rc = ssh_channel_open_session(channel);
if (rc < 0) {
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
rc = ssh_channel_request_exec(channel, "cat > /dev/null");
if (rc < 0) {
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
while ((rc = ssh_channel_write(channel, buffer, sizeof(buffer))) > 0) {
total += rc;
if(total/2 >= lastshown){
printf("written %llx\n", (long long unsigned int) total);
lastshown=total;
}
if(total > LIMIT)
break;
}
if (rc < 0) {
printf("error : %s\n",ssh_get_error(session));
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_disconnect(session);
return 0;
}
+258
View File
@@ -0,0 +1,258 @@
/*
Copyright 2010 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
#include "config.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <libssh/callbacks.h>
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include <fcntl.h>
#include "examples_common.h"
char *host;
const char *desthost="localhost";
const char *port="22";
#ifdef WITH_PCAP
#include <libssh/pcap.h>
char *pcap_file=NULL;
#endif
static void usage(){
fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
exit(1);
}
static int opts(int argc, char **argv){
int i;
while((i=getopt(argc,argv,"P:"))!=-1){
switch(i){
#ifdef WITH_PCAP
case 'P':
pcap_file=optarg;
break;
#endif
default:
fprintf(stderr,"unknown option %c\n",optopt);
usage();
}
}
if(optind < argc)
host=argv[optind++];
if(optind < argc)
desthost=argv[optind++];
if(optind < argc)
port=argv[optind++];
if(host==NULL)
usage();
return 0;
}
static void select_loop(ssh_session session,ssh_channel channel){
fd_set fds;
struct timeval timeout;
char buffer[4096];
/* channels will be set to the channels to poll.
* outchannels will contain the result of the poll
*/
ssh_channel channels[2], outchannels[2];
int lus;
int eof=0;
int maxfd;
int ret;
while(channel){
do{
FD_ZERO(&fds);
if(!eof)
FD_SET(0,&fds);
timeout.tv_sec=30;
timeout.tv_usec=0;
FD_SET(ssh_get_fd(session),&fds);
maxfd=ssh_get_fd(session)+1;
channels[0]=channel; // set the first channel we want to read from
channels[1]=NULL;
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
if(ret==EINTR)
continue;
if(FD_ISSET(0,&fds)){
lus=read(0,buffer,sizeof(buffer));
if(lus)
channel_write(channel,buffer,lus);
else {
eof=1;
channel_send_eof(channel);
}
}
if(channel && channel_is_closed(channel)){
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
channel_free(channel);
channel=NULL;
channels[0]=NULL;
}
if(outchannels[0]){
while(channel && channel_is_open(channel) && channel_poll(channel,0)){
lus=channel_read(channel,buffer,sizeof(buffer),0);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
channel_free(channel);
channel=channels[0]=NULL;
} else {
ret = write(1, buffer, lus);
if (ret < 0) {
fprintf(stderr, "Error writing to stdin: %s",
strerror(errno));
return;
}
}
}
while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */
lus=channel_read(channel,buffer,sizeof(buffer),1);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
channel_free(channel);
channel=channels[0]=NULL;
} else
ret = write(2, buffer, lus);
if (ret < 0) {
fprintf(stderr, "Error writing to stderr: %s",
strerror(errno));
return;
}
}
}
if(channel && channel_is_closed(channel)){
channel_free(channel);
channel=NULL;
}
} while (ret==EINTR || ret==SSH_EINTR);
}
}
static void forwarding(ssh_session session){
ssh_channel channel;
int r;
channel=channel_new(session);
r=channel_open_forward(channel,desthost,atoi(port),"localhost",22);
if(r<0) {
printf("error forwarding port : %s\n",ssh_get_error(session));
return;
}
select_loop(session,channel);
}
static int client(ssh_session session){
int auth=0;
char *banner;
int state;
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
return -1;
ssh_options_parse_config(session, NULL);
if(ssh_connect(session)){
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
return -1;
}
state=verify_knownhost(session);
if (state != 0)
return -1;
ssh_userauth_none(session, NULL);
banner=ssh_get_issue_banner(session);
if(banner){
printf("%s\n",banner);
free(banner);
}
auth=authenticate_console(session);
if(auth != SSH_AUTH_SUCCESS){
return -1;
}
ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success");
forwarding(session);
return 0;
}
#ifdef WITH_PCAP
ssh_pcap_file pcap;
void set_pcap(ssh_session session);
void set_pcap(ssh_session session){
if(!pcap_file)
return;
pcap=ssh_pcap_file_new();
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
printf("Error opening pcap file\n");
ssh_pcap_file_free(pcap);
pcap=NULL;
return;
}
ssh_set_pcap_file(session,pcap);
}
void cleanup_pcap(void);
void cleanup_pcap(){
ssh_pcap_file_free(pcap);
pcap=NULL;
}
#endif
int main(int argc, char **argv){
ssh_session session;
session = ssh_new();
if(ssh_options_getopt(session, &argc, argv)) {
fprintf(stderr, "error parsing command line :%s\n",
ssh_get_error(session));
usage();
}
opts(argc,argv);
#ifdef WITH_PCAP
set_pcap(session);
#endif
client(session);
ssh_disconnect(session);
ssh_free(session);
#ifdef WITH_PCAP
cleanup_pcap();
#endif
ssh_finalize();
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
project(headers C)
add_subdirectory(libssh)
+39
View File
@@ -0,0 +1,39 @@
project(libssh-headers C)
set(libssh_HDRS
callbacks.h
libssh.h
ssh2.h
legacy.h
)
if (WITH_SFTP)
set(libssh_HDRS
${libssh_HDRS}
sftp.h
)
endif (WITH_SFTP)
if (WITH_SSH1)
set(libssh_HDRS
${libssh_HDRS}
ssh1.h
)
endif (WITH_SSH1)
if (WITH_SERVER)
set(libssh_HDRS
${libssh_HDRS}
server.h
)
endif (WITH_SERVER)
install(
FILES
${libssh_HDRS}
DESTINATION
${INCLUDE_INSTALL_DIR}/${APPLICATION_NAME}
COMPONENT
headers
)
+117
View File
@@ -0,0 +1,117 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2008-2009 Andreas Schneider <asn@cryptomilk.org>
*
* This 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.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __AGENT_H
#define __AGENT_H
#include "libssh/libssh.h"
/* Messages for the authentication agent connection. */
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
#define SSH_AGENTC_RSA_CHALLENGE 3
#define SSH_AGENT_RSA_RESPONSE 4
#define SSH_AGENT_FAILURE 5
#define SSH_AGENT_SUCCESS 6
#define SSH_AGENTC_ADD_RSA_IDENTITY 7
#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8
#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
/* private OpenSSH extensions for SSH2 */
#define SSH2_AGENTC_REQUEST_IDENTITIES 11
#define SSH2_AGENT_IDENTITIES_ANSWER 12
#define SSH2_AGENTC_SIGN_REQUEST 13
#define SSH2_AGENT_SIGN_RESPONSE 14
#define SSH2_AGENTC_ADD_IDENTITY 17
#define SSH2_AGENTC_REMOVE_IDENTITY 18
#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
/* smartcard */
#define SSH_AGENTC_ADD_SMARTCARD_KEY 20
#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
/* lock/unlock the agent */
#define SSH_AGENTC_LOCK 22
#define SSH_AGENTC_UNLOCK 23
/* add key with constraints */
#define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
#define SSH_AGENT_CONSTRAIN_CONFIRM 2
/* extended failure messages */
#define SSH2_AGENT_FAILURE 30
/* additional error code for ssh.com's ssh-agent2 */
#define SSH_COM_AGENT2_FAILURE 102
#define SSH_AGENT_OLD_SIGNATURE 0x01
struct ssh_agent_struct {
struct ssh_socket_struct *sock;
ssh_buffer ident;
unsigned int count;
};
#ifndef _WIN32
/* agent.c */
/**
* @brief Create a new ssh agent structure.
*
* @return An allocated ssh agent structure or NULL on error.
*/
struct ssh_agent_struct *agent_new(struct ssh_session_struct *session);
void agent_close(struct ssh_agent_struct *agent);
/**
* @brief Free an allocated ssh agent structure.
*
* @param agent The ssh agent structure to free.
*/
void agent_free(struct ssh_agent_struct *agent);
/**
* @brief Check if the ssh agent is running.
*
* @param session The ssh session to check for the agent.
*
* @return 1 if it is running, 0 if not.
*/
int agent_is_running(struct ssh_session_struct *session);
int ssh_agent_get_ident_count(struct ssh_session_struct *session);
ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session,
char **comment);
ssh_key ssh_agent_get_first_ident(struct ssh_session_struct *session,
char **comment);
ssh_string ssh_agent_sign_data(ssh_session session,
const ssh_key pubkey,
struct ssh_buffer_struct *data);
#endif
#endif /* __AGENT_H */
/* vim: set ts=2 sw=2 et cindent: */
+106
View File
@@ -0,0 +1,106 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2009 by Aris Adamantiadis
*
* This 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.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AUTH_H_
#define AUTH_H_
#include "config.h"
#include "libssh/callbacks.h"
SSH_PACKET_CALLBACK(ssh_packet_userauth_banner);
SSH_PACKET_CALLBACK(ssh_packet_userauth_failure);
SSH_PACKET_CALLBACK(ssh_packet_userauth_success);
SSH_PACKET_CALLBACK(ssh_packet_userauth_pk_ok);
SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request);
SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response);
/** @internal
* kdbint structure must be shared with message.c
* and server.c
*/
struct ssh_kbdint_struct {
uint32_t nprompts;
uint32_t nanswers;
char *name;
char *instruction;
char **prompts;
unsigned char *echo; /* bool array */
char **answers;
};
typedef struct ssh_kbdint_struct* ssh_kbdint;
ssh_kbdint ssh_kbdint_new(void);
void ssh_kbdint_clean(ssh_kbdint kbd);
void ssh_kbdint_free(ssh_kbdint kbd);
#ifdef WITH_SSH1
void ssh_auth1_handler(ssh_session session, uint8_t type);
/* auth1.c */
int ssh_userauth1_none(ssh_session session, const char *username);
int ssh_userauth1_offer_pubkey(ssh_session session, const char *username,
int type, ssh_string pubkey);
int ssh_userauth1_password(ssh_session session, const char *username,
const char *password);
#endif
/** @internal
* States of authentication in the client-side. They describe
* what was the last response from the server
*/
enum ssh_auth_state_e {
/** No authentication asked */
SSH_AUTH_STATE_NONE=0,
/** Last authentication response was a partial success */
SSH_AUTH_STATE_PARTIAL,
/** Last authentication response was a success */
SSH_AUTH_STATE_SUCCESS,
/** Last authentication response was failed */
SSH_AUTH_STATE_FAILED,
/** Last authentication was erroneous */
SSH_AUTH_STATE_ERROR,
/** Last state was a keyboard-interactive ask for info */
SSH_AUTH_STATE_INFO,
/** Last state was a public key accepted for authentication */
SSH_AUTH_STATE_PK_OK,
/** We asked for a keyboard-interactive authentication */
SSH_AUTH_STATE_KBDINT_SENT
};
/** @internal
* @brief states of the authentication service request
*/
enum ssh_auth_service_state_e {
/** initial state */
SSH_AUTH_SERVICE_NONE=0,
/** Authentication service request packet sent */
SSH_AUTH_SERVICE_SENT,
/** Service accepted */
SSH_AUTH_SERVICE_ACCEPTED,
/** Access to service denied (fatal) */
SSH_AUTH_SERVICE_DENIED,
/** Specific to SSH1 */
SSH_AUTH_SERVICE_USER_SENT
};
#endif /* AUTH_H_ */
+53
View File
@@ -0,0 +1,53 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2010 by Aris Adamantiadis
*
* This 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.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef BIND_H_
#define BIND_H_
#include "libssh/priv.h"
#include "libssh/session.h"
struct ssh_bind_struct {
struct ssh_common_struct common; /* stuff common to ssh_bind and ssh_session */
struct ssh_bind_callbacks_struct *bind_callbacks;
void *bind_callbacks_userdata;
struct ssh_poll_handle_struct *poll;
/* options */
char *wanted_methods[10];
char *banner;
char *ecdsakey;
char *dsakey;
char *rsakey;
ssh_key ecdsa;
ssh_key dsa;
ssh_key rsa;
char *bindaddr;
socket_t bindfd;
unsigned int bindport;
int blocking;
int toaccept;
};
struct ssh_poll_handle_struct *ssh_bind_get_poll(struct ssh_bind_struct
*sshbind);
#endif /* BIND_H_ */
+72
View File
@@ -0,0 +1,72 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2009 by Aris Adamantiadis
*
* This 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.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef BUFFER_H_
#define BUFFER_H_
#include "libssh/libssh.h"
/*
* Describes a buffer state
* [XXXXXXXXXXXXDATA PAYLOAD XXXXXXXXXXXXXXXXXXXXXXXX]
* ^ ^ ^ ^]
* \_data points\_pos points here \_used points here | /
* here Allocated
*/
struct ssh_buffer_struct {
char *data;
uint32_t used;
uint32_t allocated;
uint32_t pos;
};
LIBSSH_API void ssh_buffer_free(ssh_buffer buffer);
LIBSSH_API void *ssh_buffer_get_begin(ssh_buffer buffer);
LIBSSH_API uint32_t ssh_buffer_get_len(ssh_buffer buffer);
LIBSSH_API ssh_buffer ssh_buffer_new(void);
int buffer_add_ssh_string(ssh_buffer buffer, ssh_string string);
int buffer_add_u8(ssh_buffer buffer, uint8_t data);
int buffer_add_u16(ssh_buffer buffer, uint16_t data);
int buffer_add_u32(ssh_buffer buffer, uint32_t data);
int buffer_add_u64(ssh_buffer buffer, uint64_t data);
int buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len);
int buffer_prepend_data(ssh_buffer buffer, const void *data, uint32_t len);
int buffer_add_buffer(ssh_buffer buffer, ssh_buffer source);
int buffer_reinit(ssh_buffer buffer);
/* buffer_get_rest returns a pointer to the current position into the buffer */
void *buffer_get_rest(ssh_buffer buffer);
/* buffer_get_rest_len returns the number of bytes which can be read */
uint32_t buffer_get_rest_len(ssh_buffer buffer);
/* buffer_read_*() returns the number of bytes read, except for ssh strings */
int buffer_get_u8(ssh_buffer buffer, uint8_t *data);
int buffer_get_u32(ssh_buffer buffer, uint32_t *data);
int buffer_get_u64(ssh_buffer buffer, uint64_t *data);
uint32_t buffer_get_data(ssh_buffer buffer, void *data, uint32_t requestedlen);
/* buffer_get_ssh_string() is an exception. if the String read is too large or invalid, it will answer NULL. */
ssh_string buffer_get_ssh_string(ssh_buffer buffer);
/* gets a string out of a SSH-1 mpint */
ssh_string buffer_get_mpint(ssh_buffer buffer);
/* buffer_pass_bytes acts as if len bytes have been read (used for padding) */
uint32_t buffer_pass_bytes_end(ssh_buffer buffer, uint32_t len);
uint32_t buffer_pass_bytes(ssh_buffer buffer, uint32_t len);
#endif /* BUFFER_H_ */
+447
View File
@@ -0,0 +1,447 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2009 Aris Adamantiadis <aris@0xbadc0de.be>
*
* This 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.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* callback.h
* This file includes the public declarations for the libssh callback mechanism
*/
#ifndef _SSH_CALLBACK_H
#define _SSH_CALLBACK_H
#include <libssh/libssh.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup libssh_callbacks The libssh callbacks
* @ingroup libssh
*
* Callback which can be replaced in libssh.
*
* @{
*/
/** @internal
* @brief callback to process simple codes
* @param code value to transmit
* @param user Userdata to pass in callback
*/
typedef void (*ssh_callback_int) (int code, void *user);
/** @internal
* @brief callback for data received messages.
* @param data data retrieved from the socket or stream
* @param len number of bytes available from this stream
* @param user user-supplied pointer sent along with all callback messages
* @returns number of bytes processed by the callee. The remaining bytes will
* be sent in the next callback message, when more data is available.
*/
typedef int (*ssh_callback_data) (const void *data, size_t len, void *user);
typedef void (*ssh_callback_int_int) (int code, int errno_code, void *user);
typedef int (*ssh_message_callback) (ssh_session, ssh_message message, void *user);
typedef int (*ssh_channel_callback_int) (ssh_channel channel, int code, void *user);
typedef int (*ssh_channel_callback_data) (ssh_channel channel, int code, void *data, size_t len, void *user);
/**
* @brief SSH log callback. All logging messages will go through this callback
* @param session Current session handler
* @param priority Priority of the log, the smaller being the more important
* @param message the actual message
* @param userdata Userdata to be passed to the callback function.
*/
typedef void (*ssh_log_callback) (ssh_session session, int priority,
const char *message, void *userdata);
/**
* @brief SSH Connection status callback.
* @param session Current session handler
* @param status Percentage of connection status, going from 0.0 to 1.0
* once connection is done.
* @param userdata Userdata to be passed to the callback function.
*/
typedef void (*ssh_status_callback) (ssh_session session, float status,
void *userdata);
/**
* @brief SSH global request callback. All global request will go through this
* callback.
* @param session Current session handler
* @param message the actual message
* @param userdata Userdata to be passed to the callback function.
*/
typedef void (*ssh_global_request_callback) (ssh_session session,
ssh_message message, void *userdata);
/**
* The structure to replace libssh functions with appropriate callbacks.
*/
struct ssh_callbacks_struct {
/** DON'T SET THIS use ssh_callbacks_init() instead. */
size_t size;
/**
* User-provided data. User is free to set anything he wants here
*/
void *userdata;
/**
* This functions will be called if e.g. a keyphrase is needed.
*/
ssh_auth_callback auth_function;
/**
* This function will be called each time a loggable event happens.
*/
ssh_log_callback log_function;
/**
* This function gets called during connection time to indicate the
* percentage of connection steps completed.
*/
void (*connect_status_function)(void *userdata, float status);
/**
* This function will be called each time a global request is received.
*/
ssh_global_request_callback global_request_function;
};
typedef struct ssh_callbacks_struct *ssh_callbacks;
/**
* These are the callbacks exported by the socket structure
* They are called by the socket module when a socket event appears
*/
struct ssh_socket_callbacks_struct {
/**
* User-provided data. User is free to set anything he wants here
*/
void *userdata;
/**
* This function will be called each time data appears on socket. The data
* not consumed will appear on the next data event.
*/
ssh_callback_data data;
/** This function will be called each time a controlflow state changes, i.e.
* the socket is available for reading or writing.
*/
ssh_callback_int controlflow;
/** This function will be called each time an exception appears on socket. An
* exception can be a socket problem (timeout, ...) or an end-of-file.
*/
ssh_callback_int_int exception;
/** This function is called when the ssh_socket_connect was used on the socket
* on nonblocking state, and the connection successed.
*/
ssh_callback_int_int connected;
};
typedef struct ssh_socket_callbacks_struct *ssh_socket_callbacks;
#define SSH_SOCKET_FLOW_WRITEWILLBLOCK 1
#define SSH_SOCKET_FLOW_WRITEWONTBLOCK 2
#define SSH_SOCKET_EXCEPTION_EOF 1
#define SSH_SOCKET_EXCEPTION_ERROR 2
#define SSH_SOCKET_CONNECTED_OK 1
#define SSH_SOCKET_CONNECTED_ERROR 2
#define SSH_SOCKET_CONNECTED_TIMEOUT 3
/**
* @brief Initializes an ssh_callbacks_struct
* A call to this macro is mandatory when you have set a new
* ssh_callback_struct structure. Its goal is to maintain the binary
* compatibility with future versions of libssh as the structure
* evolves with time.
*/
#define ssh_callbacks_init(p) do {\
(p)->size=sizeof(*(p)); \
} while(0);
/**
* @internal
* @brief tests if a callback can be called without crash
* verifies that the struct size if big enough
* verifies that the callback pointer exists
* @param p callback pointer
* @param c callback name
* @returns nonzero if callback can be called
*/
#define ssh_callbacks_exists(p,c) (\
(p != NULL) && ( (char *)&((p)-> c) < (char *)(p) + (p)->size ) && \
((p)-> c != NULL) \
)
/** @brief Prototype for a packet callback, to be called when a new packet arrives
* @param session The current session of the packet
* @param type packet type (see ssh2.h)
* @param packet buffer containing the packet, excluding size, type and padding fields
* @param user user argument to the callback
* and are called each time a packet shows up
* @returns SSH_PACKET_USED Packet was parsed and used
* @returns SSH_PACKET_NOT_USED Packet was not used or understood, processing must continue
*/
typedef int (*ssh_packet_callback) (ssh_session session, uint8_t type, ssh_buffer packet, void *user);
/** return values for a ssh_packet_callback */
/** Packet was used and should not be parsed by another callback */
#define SSH_PACKET_USED 1
/** Packet was not used and should be passed to any other callback
* available */
#define SSH_PACKET_NOT_USED 2
/** @brief This macro declares a packet callback handler
* @code
* SSH_PACKET_CALLBACK(mycallback){
* ...
* }
* @endcode
*/
#define SSH_PACKET_CALLBACK(name) \
int name (ssh_session session, uint8_t type, ssh_buffer packet, void *user)
struct ssh_packet_callbacks_struct {
/** Index of the first packet type being handled */
uint8_t start;
/** Number of packets being handled by this callback struct */
uint8_t n_callbacks;
/** A pointer to n_callbacks packet callbacks */
ssh_packet_callback *callbacks;
/**
* User-provided data. User is free to set anything he wants here
*/
void *user;
};
typedef struct ssh_packet_callbacks_struct *ssh_packet_callbacks;
/**
* @brief Set the session callback functions.
*
* This functions sets the callback structure to use your own callback
* functions for auth, logging and status.
*
* @code
* struct ssh_callbacks_struct cb = {
* .userdata = data,
* .auth_function = my_auth_function
* };
* ssh_callbacks_init(&cb);
* ssh_set_callbacks(session, &cb);
* @endcode
*
* @param session The session to set the callback structure.
*
* @param cb The callback structure itself.
*
* @return SSH_OK on success, SSH_ERROR on error.
*/
LIBSSH_API int ssh_set_callbacks(ssh_session session, ssh_callbacks cb);
/**
* @brief SSH channel data callback. Called when data is available on a channel
* @param session Current session handler
* @param channel the actual channel
* @param data the data that has been read on the channel
* @param len the length of the data
* @param is_stderr is 0 for stdout or 1 for stderr
* @param userdata Userdata to be passed to the callback function.
*/
typedef int (*ssh_channel_data_callback) (ssh_session session,
ssh_channel channel,
void *data,
uint32_t len,
int is_stderr,
void *userdata);
/**
* @brief SSH channel eof callback. Called when a channel receives EOF
* @param session Current session handler
* @param channel the actual channel
* @param userdata Userdata to be passed to the callback function.
*/
typedef void (*ssh_channel_eof_callback) (ssh_session session,
ssh_channel channel,
void *userdata);
/**
* @brief SSH channel close callback. Called when a channel is closed by remote peer
* @param session Current session handler
* @param channel the actual channel
* @param userdata Userdata to be passed to the callback function.
*/
typedef void (*ssh_channel_close_callback) (ssh_session session,
ssh_channel channel,
void *userdata);
/**
* @brief SSH channel signal callback. Called when a channel has received a signal
* @param session Current session handler
* @param channel the actual channel
* @param signal the signal name (without the SIG prefix)
* @param userdata Userdata to be passed to the callback function.
*/
typedef void (*ssh_channel_signal_callback) (ssh_session session,
ssh_channel channel,
const char *signal,
void *userdata);
/**
* @brief SSH channel exit status callback. Called when a channel has received an exit status
* @param session Current session handler
* @param channel the actual channel
* @param userdata Userdata to be passed to the callback function.
*/
typedef void (*ssh_channel_exit_status_callback) (ssh_session session,
ssh_channel channel,
int exit_status,
void *userdata);
/**
* @brief SSH channel exit signal callback. Called when a channel has received an exit signal
* @param session Current session handler
* @param channel the actual channel
* @param signal the signal name (without the SIG prefix)
* @param core a boolean telling wether a core has been dumped or not
* @param errmsg the description of the exception
* @param lang the language of the description (format: RFC 3066)
* @param userdata Userdata to be passed to the callback function.
*/
typedef void (*ssh_channel_exit_signal_callback) (ssh_session session,
ssh_channel channel,
const char *signal,
int core,
const char *errmsg,
const char *lang,
void *userdata);
struct ssh_channel_callbacks_struct {
/** DON'T SET THIS use ssh_callbacks_init() instead. */
size_t size;
/**
* User-provided data. User is free to set anything he wants here
*/
void *userdata;
/**
* This functions will be called when there is data available.
*/
ssh_channel_data_callback channel_data_function;
/**
* This functions will be called when the channel has received an EOF.
*/
ssh_channel_eof_callback channel_eof_function;
/**
* This functions will be called when the channel has been closed by remote
*/
ssh_channel_close_callback channel_close_function;
/**
* This functions will be called when a signal has been received
*/
ssh_channel_signal_callback channel_signal_function;
/**
* This functions will be called when an exit status has been received
*/
ssh_channel_exit_status_callback channel_exit_status_function;
/**
* This functions will be called when an exit signal has been received
*/
ssh_channel_exit_signal_callback channel_exit_signal_function;
};
typedef struct ssh_channel_callbacks_struct *ssh_channel_callbacks;
/**
* @brief Set the channel callback functions.
*
* This functions sets the callback structure to use your own callback
* functions for channel data and exceptions
*
* @code
* struct ssh_channel_callbacks_struct cb = {
* .userdata = data,
* .channel_data = my_channel_data_function
* };
* ssh_callbacks_init(&cb);
* ssh_set_channel_callbacks(channel, &cb);
* @endcode
*
* @param channel The channel to set the callback structure.
*
* @param cb The callback structure itself.
*
* @return SSH_OK on success, SSH_ERROR on error.
*/
LIBSSH_API int ssh_set_channel_callbacks(ssh_channel channel,
ssh_channel_callbacks cb);
/** @} */
/** @group libssh_threads
* @{
*/
typedef int (*ssh_thread_callback) (void **lock);
typedef unsigned long (*ssh_thread_id_callback) (void);
struct ssh_threads_callbacks_struct {
const char *type;
ssh_thread_callback mutex_init;
ssh_thread_callback mutex_destroy;
ssh_thread_callback mutex_lock;
ssh_thread_callback mutex_unlock;
ssh_thread_id_callback thread_id;
};
/**
* @brief sets the thread callbacks necessary if your program is using
* libssh in a multithreaded fashion. This function must be called first,
* outside of any threading context (in your main() for instance), before
* ssh_init().
* @param cb pointer to a ssh_threads_callbacks_struct structure, which contains
* the different callbacks to be set.
* @see ssh_threads_callbacks_struct
* @see SSH_THREADS_PTHREAD
*/
LIBSSH_API int ssh_threads_set_callbacks(struct ssh_threads_callbacks_struct
*cb);
/**
* @brief returns a pointer on the pthread threads callbacks, to be used with
* ssh_threads_set_callbacks.
* @warning you have to link with the library ssh_threads.
* @see ssh_threads_set_callbacks
*/
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_pthread(void);
/**
* @brief returns a pointer on the noop threads callbacks, to be used with
* ssh_threads_set_callbacks. These callbacks do nothing and are being used by
* default.
* @see ssh_threads_set_callbacks
*/
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /*_SSH_CALLBACK_H */
/* @} */
+118
View File
@@ -0,0 +1,118 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2009 by Aris Adamantiadis
*
* This 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.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef CHANNELS_H_
#define CHANNELS_H_
#include "libssh/priv.h"
/** @internal
* Describes the different possible states in a
* outgoing (client) channel request
*/
enum ssh_channel_request_state_e {
/** No request has been made */
SSH_CHANNEL_REQ_STATE_NONE = 0,
/** A request has been made and answer is pending */
SSH_CHANNEL_REQ_STATE_PENDING,
/** A request has been replied and accepted */
SSH_CHANNEL_REQ_STATE_ACCEPTED,
/** A request has been replied and refused */
SSH_CHANNEL_REQ_STATE_DENIED,
/** A request has been replied and an error happend */
SSH_CHANNEL_REQ_STATE_ERROR
};
enum ssh_channel_state_e {
SSH_CHANNEL_STATE_NOT_OPEN = 0,
SSH_CHANNEL_STATE_OPENING,
SSH_CHANNEL_STATE_OPEN_DENIED,
SSH_CHANNEL_STATE_OPEN,
SSH_CHANNEL_STATE_CLOSED
};
/* The channel has been closed by the remote side */
#define SSH_CHANNEL_FLAG_CLOSED_REMOTE 0x1
/* The channel has been freed by the calling program */
#define SSH_CHANNEL_FLAG_FREED_LOCAL 0x2
/* the channel has not yet been bound to a remote one */
#define SSH_CHANNEL_FLAG_NOT_BOUND 0x4
struct ssh_channel_struct {
ssh_session session; /* SSH_SESSION pointer */
uint32_t local_channel;
uint32_t local_window;
int local_eof;
uint32_t local_maxpacket;
uint32_t remote_channel;
uint32_t remote_window;
int remote_eof; /* end of file received */
uint32_t remote_maxpacket;
enum ssh_channel_state_e state;
int delayed_close;
int flags;
ssh_buffer stdout_buffer;
ssh_buffer stderr_buffer;
void *userarg;
int version;
int exit_status;
enum ssh_channel_request_state_e request_state;
ssh_channel_callbacks callbacks;
};
SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf);
SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail);
SSH_PACKET_CALLBACK(ssh_packet_channel_success);
SSH_PACKET_CALLBACK(ssh_packet_channel_failure);
SSH_PACKET_CALLBACK(ssh_request_success);
SSH_PACKET_CALLBACK(ssh_request_denied);
SSH_PACKET_CALLBACK(channel_rcv_change_window);
SSH_PACKET_CALLBACK(channel_rcv_eof);
SSH_PACKET_CALLBACK(channel_rcv_close);
SSH_PACKET_CALLBACK(channel_rcv_request);
SSH_PACKET_CALLBACK(channel_rcv_data);
ssh_channel ssh_channel_new(ssh_session session);
int channel_default_bufferize(ssh_channel channel, void *data, int len,
int is_stderr);
int ssh_channel_flush(ssh_channel channel);
uint32_t ssh_channel_new_id(ssh_session session);
ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id);
int channel_write_common(ssh_channel channel, const void *data,
uint32_t len, int is_stderr);
void ssh_channel_do_free(ssh_channel channel);
#ifdef WITH_SSH1
SSH_PACKET_CALLBACK(ssh_packet_data1);
SSH_PACKET_CALLBACK(ssh_packet_close1);
SSH_PACKET_CALLBACK(ssh_packet_exist_status1);
/* channels1.c */
int channel_open_session1(ssh_channel channel);
int channel_request_pty_size1(ssh_channel channel, const char *terminal,
int cols, int rows);
int channel_change_pty_size1(ssh_channel channel, int cols, int rows);
int channel_request_shell1(ssh_channel channel);
int channel_request_exec1(ssh_channel channel, const char *cmd);
int channel_write1(ssh_channel channel, const void *data, int len);
ssh_channel ssh_get_channel1(ssh_session session);
#endif
#endif /* CHANNELS_H_ */
+28
View File
@@ -0,0 +1,28 @@
/*
* crc32.c - simple CRC32 code
*
* This file is part of the SSH Library
*
* Copyright (c) 2005 by Aris Adamantiadis
*
* This 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.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _CRC32_H
#define _CRC32_H
uint32_t ssh_crc32(const char *buf, uint32_t len);
#endif /* _CRC32_H */
+113
View File
@@ -0,0 +1,113 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2003-2009 by Aris Adamantiadis
*
* This 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.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* crypto.h is an include file for internal cryptographic structures of libssh
*/
#ifndef _CRYPTO_H_
#define _CRYPTO_H_
#include "config.h"
#ifdef HAVE_LIBGCRYPT
#include <gcrypt.h>
#endif
#include "libssh/wrapper.h"
#ifdef cbc_encrypt
#undef cbc_encrypt
#endif
#ifdef cbc_decrypt
#undef cbc_decrypt
#endif
#ifdef HAVE_OPENSSL_ECDH_H
#include <openssl/ecdh.h>
#endif
#include "libssh/ecdh.h"
#include "libssh/kex.h"
enum ssh_key_exchange_e {
/* diffie-hellman-group1-sha1 */
SSH_KEX_DH_GROUP1_SHA1=1,
/* diffie-hellman-group14-sha1 */
SSH_KEX_DH_GROUP14_SHA1,
/* ecdh-sha2-nistp256 */
SSH_KEX_ECDH_SHA2_NISTP256
};
struct ssh_crypto_struct {
bignum e,f,x,k,y;
#ifdef HAVE_ECDH
EC_KEY *ecdh_privkey;
ssh_string ecdh_client_pubkey;
ssh_string ecdh_server_pubkey;
#endif
ssh_string dh_server_signature; /* information used by dh_handshake. */
size_t digest_len; /* len of all the fields below */
unsigned char *session_id;
unsigned char *secret_hash; /* Secret hash is same as session id until re-kex */
unsigned char *encryptIV;
unsigned char *decryptIV;
unsigned char *decryptkey;
unsigned char *encryptkey;
unsigned char *encryptMAC;
unsigned char *decryptMAC;
unsigned char hmacbuf[EVP_MAX_MD_SIZE];
struct ssh_cipher_struct *in_cipher, *out_cipher; /* the cipher structures/objects */
ssh_string server_pubkey;
const char *server_pubkey_type;
int do_compress_out; /* idem */
int do_compress_in; /* don't set them, set the option instead */
int delayed_compress_in; /* Use of zlib@openssh.org */
int delayed_compress_out;
void *compress_out_ctx; /* don't touch it */
void *compress_in_ctx; /* really, don't */
/* kex sent by server, client, and mutually elected methods */
struct ssh_kex_struct server_kex;
struct ssh_kex_struct client_kex;
char *kex_methods[SSH_KEX_METHODS];
enum ssh_key_exchange_e kex_type;
enum ssh_mac_e mac_type; /* Mac operations to use for key gen */
};
struct ssh_cipher_struct {
const char *name; /* ssh name of the algorithm */
unsigned int blocksize; /* blocksize of the algo */
unsigned int keylen; /* length of the key structure */
#ifdef HAVE_LIBGCRYPT
gcry_cipher_hd_t *key;
#elif defined HAVE_LIBCRYPTO
void *key; /* a key buffer allocated for the algo */
void *IV;
#endif
unsigned int keysize; /* bytes of key used. != keylen */
/* sets the new key for immediate use */
int (*set_encrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV);
int (*set_decrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV);
void (*cbc_encrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
unsigned long len);
void (*cbc_decrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
unsigned long len);
};
/* vim: set ts=2 sw=2 et cindent: */
#endif /* _CRYPTO_H_ */
+55
View File
@@ -0,0 +1,55 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2009 by Aris Adamantiadis
*
* This 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.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef DH_H_
#define DH_H_
#include "config.h"
#include "libssh/crypto.h"
void ssh_print_bignum(const char *which,bignum num);
int dh_generate_e(ssh_session session);
int dh_generate_f(ssh_session session);
int dh_generate_x(ssh_session session);
int dh_generate_y(ssh_session session);
int ssh_crypto_init(void);
void ssh_crypto_finalize(void);
ssh_string dh_get_e(ssh_session session);
ssh_string dh_get_f(ssh_session session);
int dh_import_f(ssh_session session,ssh_string f_string);
int dh_import_e(ssh_session session, ssh_string e_string);
void dh_import_pubkey(ssh_session session,ssh_string pubkey_string);
int dh_build_k(ssh_session session);
int ssh_client_dh_init(ssh_session session);
int ssh_client_dh_reply(ssh_session session, ssh_buffer packet);
int make_sessionid(ssh_session session);
/* add data for the final cookie */
int hashbufin_add_cookie(ssh_session session, unsigned char *cookie);
int hashbufout_add_cookie(ssh_session session);
int generate_session_keys(ssh_session session);
bignum make_string_bn(ssh_string string);
ssh_string make_bignum_string(bignum num);
#endif /* DH_H_ */
+41
View File
@@ -0,0 +1,41 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2011 by Aris Adamantiadis
*
* This 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.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef ECDH_H_
#define ECDH_H_
#include "config.h"
#ifdef HAVE_LIBCRYPTO
#ifdef HAVE_OPENSSL_ECDH_H
#define HAVE_ECDH
#endif /* HAVE_OPENSSL_ECDH_H */
#endif /* HAVE_LIBCRYPTO */
int ssh_client_ecdh_init(ssh_session session);
int ssh_client_ecdh_reply(ssh_session session, ssh_buffer packet);
#ifdef WITH_SERVER
int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet);
#endif /* WITH_SERVER */
#endif /* ECDH_H_ */
+50
View File
@@ -0,0 +1,50 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2009 by Aris Adamantiadis
*
* This 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.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef KEX_H_
#define KEX_H_
#include "libssh/priv.h"
#include "libssh/callbacks.h"
#define SSH_KEX_METHODS 10
struct ssh_kex_struct {
unsigned char cookie[16];
char *methods[SSH_KEX_METHODS];
};
SSH_PACKET_CALLBACK(ssh_packet_kexinit);
#ifdef WITH_SSH1
SSH_PACKET_CALLBACK(ssh_packet_publickey1);
#endif
int ssh_send_kex(ssh_session session, int server_kex);
void ssh_list_kex(ssh_session session, struct ssh_kex_struct *kex);
int set_client_kex(ssh_session session);
int ssh_kex_select_methods(ssh_session session);
int verify_existing_algo(int algo, const char *name);
char **space_tokenize(const char *chain);
int ssh_get_kex1(ssh_session session);
char *ssh_find_matching(const char *in_d, const char *what_d);
const char *ssh_kex_get_supported_method(uint32_t algo);
const char *ssh_kex_get_description(uint32_t algo);
#endif /* KEX_H_ */
+56
View File
@@ -0,0 +1,56 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2009 by Aris Adamantiadis
*
* This 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.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef KEYS_H_
#define KEYS_H_
#include "config.h"
#include "libssh/libssh.h"
#include "libssh/wrapper.h"
struct ssh_public_key_struct {
int type;
const char *type_c; /* Don't free it ! it is static */
#ifdef HAVE_LIBGCRYPT
gcry_sexp_t dsa_pub;
gcry_sexp_t rsa_pub;
#elif HAVE_LIBCRYPTO
DSA *dsa_pub;
RSA *rsa_pub;
#endif
};
struct ssh_private_key_struct {
int type;
#ifdef HAVE_LIBGCRYPT
gcry_sexp_t dsa_priv;
gcry_sexp_t rsa_priv;
#elif defined HAVE_LIBCRYPTO
DSA *dsa_priv;
RSA *rsa_priv;
#endif
};
const char *ssh_type_to_char(int type);
int ssh_type_from_name(const char *name);
ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s);
#endif /* KEYS_H_ */
+120
View File
@@ -0,0 +1,120 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2010 by Aris Adamantiadis
*
* This 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.
*
* This 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Since libssh.h includes legacy.h, it's important that libssh.h is included
* first. we don't define LEGACY_H now because we want it to be defined when
* included from libssh.h
* All function calls declared in this header are deprecated and meant to be
* removed in future.
*/
#ifndef LEGACY_H_
#define LEGACY_H_
typedef struct ssh_private_key_struct* ssh_private_key;
typedef struct ssh_public_key_struct* ssh_public_key;
LIBSSH_API int ssh_auth_list(ssh_session session);
LIBSSH_API int ssh_userauth_offer_pubkey(ssh_session session, const char *username, int type, ssh_string publickey);
LIBSSH_API int ssh_userauth_pubkey(ssh_session session, const char *username, ssh_string publickey, ssh_private_key privatekey);
#ifndef _WIN32
LIBSSH_API int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
ssh_public_key publickey);
#endif
LIBSSH_API int ssh_userauth_autopubkey(ssh_session session, const char *passphrase);
LIBSSH_API int ssh_userauth_privatekey_file(ssh_session session, const char *username,
const char *filename, const char *passphrase);
LIBSSH_API void buffer_free(ssh_buffer buffer);
LIBSSH_API void *buffer_get(ssh_buffer buffer);
LIBSSH_API uint32_t buffer_get_len(ssh_buffer buffer);
LIBSSH_API ssh_buffer buffer_new(void);
LIBSSH_API ssh_channel channel_accept_x11(ssh_channel channel, int timeout_ms);
LIBSSH_API int channel_change_pty_size(ssh_channel channel,int cols,int rows);
LIBSSH_API ssh_channel channel_forward_accept(ssh_session session, int timeout_ms);
LIBSSH_API int channel_close(ssh_channel channel);
LIBSSH_API int channel_forward_cancel(ssh_session session, const char *address, int port);
LIBSSH_API int channel_forward_listen(ssh_session session, const char *address, int port, int *bound_port);
LIBSSH_API void channel_free(ssh_channel channel);
LIBSSH_API int channel_get_exit_status(ssh_channel channel);
LIBSSH_API ssh_session channel_get_session(ssh_channel channel);
LIBSSH_API int channel_is_closed(ssh_channel channel);
LIBSSH_API int channel_is_eof(ssh_channel channel);
LIBSSH_API int channel_is_open(ssh_channel channel);
LIBSSH_API ssh_channel channel_new(ssh_session session);
LIBSSH_API int channel_open_forward(ssh_channel channel, const char *remotehost,
int remoteport, const char *sourcehost, int localport);
LIBSSH_API int channel_open_session(ssh_channel channel);
LIBSSH_API int channel_poll(ssh_channel channel, int is_stderr);
LIBSSH_API int channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr);
LIBSSH_API int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
int is_stderr);
LIBSSH_API int channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
int is_stderr);
LIBSSH_API int channel_request_env(ssh_channel channel, const char *name, const char *value);
LIBSSH_API int channel_request_exec(ssh_channel channel, const char *cmd);
LIBSSH_API int channel_request_pty(ssh_channel channel);
LIBSSH_API int channel_request_pty_size(ssh_channel channel, const char *term,
int cols, int rows);
LIBSSH_API int channel_request_shell(ssh_channel channel);
LIBSSH_API int channel_request_send_signal(ssh_channel channel, const char *signum);
LIBSSH_API int channel_request_sftp(ssh_channel channel);
LIBSSH_API int channel_request_subsystem(ssh_channel channel, const char *subsystem);
LIBSSH_API int channel_request_x11(ssh_channel channel, int single_connection, const char *protocol,
const char *cookie, int screen_number);
LIBSSH_API int channel_send_eof(ssh_channel channel);
LIBSSH_API int channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct
timeval * timeout);
LIBSSH_API void channel_set_blocking(ssh_channel channel, int blocking);
LIBSSH_API int channel_write(ssh_channel channel, const void *data, uint32_t len);
LIBSSH_API void privatekey_free(ssh_private_key prv);
LIBSSH_API ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
int type, const char *passphrase);
LIBSSH_API void publickey_free(ssh_public_key key);
LIBSSH_API int ssh_publickey_to_file(ssh_session session, const char *file,
ssh_string pubkey, int type);
LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filename,
int *type);
LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv);
LIBSSH_API ssh_string publickey_to_string(ssh_public_key key);
LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
ssh_string *publickey, int *type);
LIBSSH_API enum ssh_keytypes_e ssh_privatekey_type(ssh_private_key privatekey);
LIBSSH_API ssh_string ssh_get_pubkey(ssh_session session);
LIBSSH_API ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype);
LIBSSH_API ssh_public_key ssh_message_auth_publickey(ssh_message msg);
LIBSSH_API void string_burn(ssh_string str);
LIBSSH_API ssh_string string_copy(ssh_string str);
LIBSSH_API void *string_data(ssh_string str);
LIBSSH_API int string_fill(ssh_string str, const void *data, size_t len);
LIBSSH_API void string_free(ssh_string str);
LIBSSH_API ssh_string string_from_char(const char *what);
LIBSSH_API size_t string_len(ssh_string str);
LIBSSH_API ssh_string string_new(size_t size);
LIBSSH_API char *string_to_char(ssh_string str);
#endif /* LEGACY_H_ */

Some files were not shown because too many files have changed in this diff Show More