From 8ed9cdce80d78d3466cbd075ff48e40268d38c91 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 1 Oct 2009 10:19:07 +0200 Subject: [PATCH 01/15] Remove --as-needed linker flag. --- ConfigureChecks.cmake | 3 +++ cmake/Modules/DefineCompilerFlags.cmake | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index 6ccc6070..8ca82585 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -39,8 +39,10 @@ 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) @@ -75,6 +77,7 @@ if (UNIX) check_function_exists(cfmakeraw HAVE_CFMAKERAW) check_function_exists(regcomp HAVE_REGCOMP) endif (UNIX) + set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries") # LIBRARIES diff --git a/cmake/Modules/DefineCompilerFlags.cmake b/cmake/Modules/DefineCompilerFlags.cmake index dafc7996..dcaf8da8 100644 --- a/cmake/Modules/DefineCompilerFlags.cmake +++ b/cmake/Modules/DefineCompilerFlags.cmake @@ -48,8 +48,6 @@ if (UNIX AND NOT WIN32) add_definitions(-D_FORTIFY_SOURCE=2) endif (WITH_FORTIFY_SOURCE) - # Set linker flags - set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed") endif (CMAKE_COMPILER_IS_GNUCC) endif (UNIX AND NOT WIN32) From 42aacc71069d31ff039b4deda2ad13beb08944bd Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Fri, 2 Oct 2009 10:18:27 +0200 Subject: [PATCH 02/15] Remove unused option functions. --- include/libssh/options.h | 6 ------ libssh/options.c | 13 ------------- 2 files changed, 19 deletions(-) diff --git a/include/libssh/options.h b/include/libssh/options.h index 8ec07a6d..8b990d33 100644 --- a/include/libssh/options.h +++ b/include/libssh/options.h @@ -49,10 +49,4 @@ struct ssh_options_struct { }; - -/* this function must be called when no specific username has been asked. it has to guess it */ -int ssh_options_default_username(ssh_options opt); -int ssh_options_default_ssh_dir(ssh_options opt); -int ssh_options_default_known_hosts_file(ssh_options opt); - #endif /* OPTIONS_H_ */ diff --git a/libssh/options.c b/libssh/options.c index 70469d81..95429b0d 100644 --- a/libssh/options.c +++ b/libssh/options.c @@ -923,19 +923,6 @@ int ssh_options_set_wanted_algos(ssh_options opt, int algo, const char *list) { return 0; } -/* this function must be called when no specific username has been asked. it has to guess it */ -int ssh_options_default_username(ssh_options opt) { - return ssh_options_set(opt, SSH_OPTIONS_USER, NULL); -} - -int ssh_options_default_ssh_dir(ssh_options opt) { - return ssh_options_set(opt, SSH_OPTIONS_SSH_DIR, NULL); -} - -int ssh_options_default_known_hosts_file(ssh_options opt) { - return ssh_options_set(opt, SSH_OPTIONS_KNOWNHOSTS, NULL); -} - /** * @brief Set a callback to show connection status in realtime. * From 62cebe23d9e62a4807c5ecb99f88e488055f2c92 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Fri, 2 Oct 2009 14:03:00 +0200 Subject: [PATCH 03/15] Fixed build of sample client. --- CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 210512b6..b5dedd36 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,11 +69,13 @@ include_directories(${CMAKE_SOURCE_DIR}/include) if (UNIX AND NOT WIN32) add_subdirectory(examples) - if (WITH_SFTP AND WITH_SERVER) + if (WITH_SFTP) add_executable(samplessh sample.c) - add_executable(samplesshd samplesshd.c) - target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY}) + endif (WITH_SFTP) + + if (WITH_SERVER) + add_executable(samplesshd samplesshd.c) target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY}) - endif (WITH_SFTP AND WITH_SERVER) + endif (WITH_SERVER) endif (UNIX AND NOT WIN32) From 566fda70a53568cc10d4705c84547b44a8379c7e Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Fri, 2 Oct 2009 20:16:17 +0200 Subject: [PATCH 04/15] Fixed LFS support on unix. --- cmake/Modules/DefineCompilerFlags.cmake | 50 ++++++++++++------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/cmake/Modules/DefineCompilerFlags.cmake b/cmake/Modules/DefineCompilerFlags.cmake index dcaf8da8..112449bc 100644 --- a/cmake/Modules/DefineCompilerFlags.cmake +++ b/cmake/Modules/DefineCompilerFlags.cmake @@ -13,31 +13,6 @@ if (UNIX AND NOT WIN32) add_definitions(-fPIC) endif (WITH_FPIC) - if (CMAKE_SIZEOF_VOID_P MATCHES "8") - # with large file support - execute_process( - COMMAND - getconf LFS64_CFLAGS - OUTPUT_VARIABLE - _lfs_CFLAGS - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - else (CMAKE_SIZEOF_VOID_P MATCHES "8") - # with large file support - execute_process( - COMMAND - getconf LFS_CFLAGS - OUTPUT_VARIABLE - _lfs_CFLAGS - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}") - - add_definitions(${_lfs_CFLAGS}) - endif (CMAKE_SIZEOF_VOID_P MATCHES "8") - check_c_compiler_flag("-fstack-protector" WITH_STACK_PROTECTOR) if (WITH_STACK_PROTECTOR) add_definitions(-fstack-protector) @@ -49,6 +24,31 @@ if (UNIX AND NOT WIN32) endif (WITH_FORTIFY_SOURCE) endif (CMAKE_COMPILER_IS_GNUCC) + + 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") + string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}") + add_definitions(${_lfs_CFLAGS}) + endif (UNIX AND NOT WIN32) # suppress warning about "deprecated" functions From e78334688fa510a5c859b0367d4d4779efae518a Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Fri, 2 Oct 2009 20:19:48 +0200 Subject: [PATCH 05/15] Fixed setting of LFS CFLAGS. --- cmake/Modules/DefineCompilerFlags.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/DefineCompilerFlags.cmake b/cmake/Modules/DefineCompilerFlags.cmake index 112449bc..1ec2cf98 100644 --- a/cmake/Modules/DefineCompilerFlags.cmake +++ b/cmake/Modules/DefineCompilerFlags.cmake @@ -46,8 +46,10 @@ if (UNIX AND NOT WIN32) OUTPUT_STRIP_TRAILING_WHITESPACE ) endif (CMAKE_SIZEOF_VOID_P MATCHES "8") - string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}") - add_definitions(${_lfs_CFLAGS}) + if (_lfs_CFLAGS) + string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}") + add_definitions(${_lfs_CFLAGS}) + endif (_lfs_CFLAGS) endif (UNIX AND NOT WIN32) From ab5b4c7cfe668ee4103de146c2a739532abfc416 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Fri, 2 Oct 2009 14:06:41 +0200 Subject: [PATCH 06/15] Get rid of the options structure. --- examples/connect_ssh.c | 18 +- include/libssh/callback.h | 9 +- include/libssh/libssh.h | 42 +- include/libssh/options.h | 52 --- include/libssh/priv.h | 20 +- include/libssh/server.h | 19 +- include/libssh/session.h | 19 +- libssh/auth.c | 47 ++- libssh/client.c | 46 +-- libssh/config.c | 42 +- libssh/dh.c | 7 +- libssh/kex.c | 4 +- libssh/keyfiles.c | 43 +-- libssh/log.c | 7 +- libssh/options.c | 782 +++++++++++--------------------------- libssh/server.c | 131 ++++--- libssh/session.c | 42 +- sample.c | 23 +- 18 files changed, 499 insertions(+), 854 deletions(-) delete mode 100644 include/libssh/options.h diff --git a/examples/connect_ssh.c b/examples/connect_ssh.c index cfc6bb12..90a2f34c 100644 --- a/examples/connect_ssh.c +++ b/examples/connect_ssh.c @@ -23,24 +23,24 @@ clients must be made or how a client should react. ssh_session connect_ssh(const char *host, const char *user,int verbosity){ ssh_session session; - ssh_options options; int auth=0; - options=ssh_options_new(); + session=ssh_new(); + if (session == NULL) { + return NULL; + } + if(user != NULL){ - if (ssh_options_set_username(options,user) < 0) { - ssh_options_free(options); + if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) { + ssh_disconnect(session); return NULL; } } - if (ssh_options_set_host(options,host) < 0) { - ssh_options_free(options); + if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) { return NULL; } - ssh_options_set_log_verbosity(options,verbosity); - session=ssh_new(); - ssh_set_options(session,options); + 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); diff --git a/include/libssh/callback.h b/include/libssh/callback.h index 3aac65bc..51a2ece9 100644 --- a/include/libssh/callback.h +++ b/include/libssh/callback.h @@ -54,6 +54,7 @@ typedef void (*ssh_log_callback) (ssh_session session, int priority, * connection */ typedef void (*ssh_status_callback) (ssh_session session, float status, void *userdata); + struct ssh_callbacks_struct { /** size of this structure. internal, shoud be set with ssh_callbacks_init()*/ size_t size; @@ -81,12 +82,12 @@ typedef struct ssh_callbacks_struct * ssh_callbacks; p->size=sizeof(*p); \ } while(0); -LIBSSH_API int ssh_options_set_auth_callback(ssh_options opt, ssh_auth_callback cb, +LIBSSH_API int ssh_set_auth_callback(ssh_session session, ssh_auth_callback cb, void *userdata); -LIBSSH_API int ssh_options_set_log_function(ssh_options opt, +LIBSSH_API int ssh_set_log_callback(ssh_session session, ssh_log_callback cb, void *userdata); -LIBSSH_API int ssh_options_set_status_callback(ssh_options opt, void (*callback) - (void *arg, float status), void *arg); +LIBSSH_API int ssh_set_status_callback(ssh_session session, void (*callback) + (void *arg, float status), void *arg); #ifdef __cplusplus } diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h index c6b3b72b..f4cb55b4 100644 --- a/include/libssh/libssh.h +++ b/include/libssh/libssh.h @@ -94,6 +94,12 @@ #define PRINTF_ATTRIBUTE(a,b) #endif /* __GNUC__ */ +#ifdef __GNUC__ +#define SSH_DEPRECATED __attribute__ ((deprecated)) +#else +#define SSH_DEPRECATED +#endif + #ifdef __cplusplus extern "C" { #endif @@ -108,14 +114,14 @@ typedef struct ssh_agent_struct AGENT; #endif typedef struct ssh_message_struct SSH_MESSAGE; -typedef struct ssh_options_struct SSH_OPTIONS; +typedef struct ssh_session_struct SSH_OPTIONS; typedef struct ssh_session_struct SSH_SESSION; typedef struct ssh_agent_struct* ssh_agent; typedef struct ssh_buffer_struct* ssh_buffer; typedef struct ssh_channel_struct* ssh_channel; typedef struct ssh_message_struct *ssh_message; -typedef struct ssh_options_struct* ssh_options; +typedef struct ssh_session_struct* ssh_options; typedef struct ssh_private_key_struct* ssh_private_key; typedef struct ssh_public_key_struct* ssh_public_key; typedef struct ssh_scp_struct* ssh_scp; @@ -267,14 +273,7 @@ enum ssh_options_e { SSH_OPTIONS_CIPHERS_C_S, SSH_OPTIONS_CIPHERS_S_C, SSH_OPTIONS_COMPRESSION_C_S, - SSH_OPTIONS_COMPRESSION_S_C, - - SSH_OPTIONS_SERVER_BINDADDR, - SSH_OPTIONS_SERVER_BINDPORT, - SSH_OPTIONS_SERVER_HOSTKEY, - SSH_OPTIONS_SERVER_DSAKEY, - SSH_OPTIONS_SERVER_RSAKEY, - SSH_OPTIONS_SERVER_BANNER, + SSH_OPTIONS_COMPRESSION_S_C }; enum { @@ -383,30 +382,13 @@ LIBSSH_API int ssh_message_subtype(ssh_message msg); LIBSSH_API int ssh_message_type(ssh_message msg); LIBSSH_API int ssh_mkdir (const char *pathname, mode_t mode); LIBSSH_API ssh_session ssh_new(void); -LIBSSH_API ssh_options ssh_options_copy(ssh_options opt); -LIBSSH_API void ssh_options_free(ssh_options opt); -LIBSSH_API ssh_options ssh_options_new(void); -LIBSSH_API int ssh_options_allow_ssh1(ssh_options opt, int allow); -LIBSSH_API int ssh_options_allow_ssh2(ssh_options opt, int allow); +LIBSSH_API ssh_options ssh_options_copy(ssh_options opt); LIBSSH_API int ssh_options_getopt(ssh_options options, int *argcptr, char **argv); LIBSSH_API int ssh_options_parse_config(ssh_options opt, const char *filename); -LIBSSH_API int ssh_options_set(ssh_options opt, enum ssh_options_e type, +LIBSSH_API int ssh_options_set(ssh_session session, enum ssh_options_e type, const void *value); -LIBSSH_API int ssh_options_set_banner(ssh_options opt, const char *banner); -LIBSSH_API int ssh_options_set_bind(ssh_options opt, const char *bindaddr, int port); -LIBSSH_API int ssh_options_set_dsa_server_key(ssh_options opt, const char *dsakey); -LIBSSH_API int ssh_options_set_fd(ssh_options opt, socket_t fd); -LIBSSH_API int ssh_options_set_host(ssh_options opt, const char *host); -LIBSSH_API int ssh_options_set_identity(ssh_options opt, const char *identity); -LIBSSH_API int ssh_options_set_log_verbosity(ssh_options opt, int verbosity); -LIBSSH_API int ssh_options_set_known_hosts_file(ssh_options opt, const char *dir); -LIBSSH_API int ssh_options_set_port(ssh_options opt, unsigned int port); -LIBSSH_API int ssh_options_set_rsa_server_key(ssh_options opt, const char *rsakey); -LIBSSH_API int ssh_options_set_ssh_dir(ssh_options opt, const char *dir); -LIBSSH_API int ssh_options_set_timeout(ssh_options opt, long seconds, long usec); -LIBSSH_API int ssh_options_set_username(ssh_options opt, const char *username); -LIBSSH_API int ssh_options_set_wanted_algos(ssh_options opt, int algo, const char *list); + LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len); LIBSSH_API int ssh_scp_accept_request(ssh_scp scp); LIBSSH_API int ssh_scp_close(ssh_scp scp); diff --git a/include/libssh/options.h b/include/libssh/options.h deleted file mode 100644 index 8b990d33..00000000 --- a/include/libssh/options.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of the SSH Library - * - * Copyright (c) 2009 by Aris Adamantiadis - * - * The SSH Library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at your - * option) any later version. - * - * The SSH Library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the SSH Library; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef OPTIONS_H_ -#define OPTIONS_H_ - -#include "libssh/priv.h" -#include "libssh/callback.h" - -struct ssh_options_struct { - struct error_struct error; - char *banner; - char *username; - char *host; - char *bindaddr; - int bindport; - char *identity; - char *ssh_dir; - char *known_hosts_file; - socket_t fd; /* specificaly wanted file descriptor, don't connect host */ - int port; - char *wanted_methods[10]; /* the kex methods can be choosed. better use the kex fonctions to do that */ - ssh_callbacks callbacks; /* Callbacks to user functions */ - long timeout; /* seconds */ - long timeout_usec; - int ssh2allowed; - int ssh1allowed; - char *dsakey; - char *rsakey; /* host key for server implementation */ - int log_verbosity; - -}; - -#endif /* OPTIONS_H_ */ diff --git a/include/libssh/priv.h b/include/libssh/priv.h index a9da5a5c..8dbf9a3f 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -95,11 +95,21 @@ struct ssh_message_struct; /* server data */ struct ssh_bind_struct { - struct error_struct error; - socket_t bindfd; - ssh_options options; - int blocking; - int toaccept; + struct error_struct error; + + ssh_callbacks callbacks; /* Callbacks to user functions */ + + /* options */ + char *wanted_methods[10]; + char *banner; + char *dsakey; + char *rsakey; + char *bindaddr; + socket_t bindfd; + unsigned int bindport; + + int blocking; + int toaccept; }; diff --git a/include/libssh/server.h b/include/libssh/server.h index 311003cd..e1ef3df5 100644 --- a/include/libssh/server.h +++ b/include/libssh/server.h @@ -35,7 +35,17 @@ extern "C" { #endif +enum ssh_bind_options_e { + SSH_BIND_OPTIONS_BINDADDR, + SSH_BIND_OPTIONS_BINDPORT, + SSH_BIND_OPTIONS_HOSTKEY, + SSH_BIND_OPTIONS_DSAKEY, + SSH_BIND_OPTIONS_RSAKEY, + SSH_BIND_OPTIONS_BANNER +}; + typedef struct ssh_bind_struct SSH_BIND; +typedef struct ssh_bind_struct *ssh_bind; /** * @brief Creates a new SSH server bind. @@ -51,7 +61,8 @@ LIBSSH_API SSH_BIND *ssh_bind_new(void); * * @param options The option structure to set. */ -LIBSSH_API void ssh_bind_set_options(SSH_BIND *ssh_bind, ssh_options options); +LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind, + enum ssh_bind_options_e type, const void *value); /** * @brief Start listening to the socket. @@ -69,7 +80,7 @@ LIBSSH_API int ssh_bind_listen(SSH_BIND *ssh_bind); * * @param blocking Zero for nonblocking mode. */ -LIBSSH_API void ssh_bind_set_blocking(SSH_BIND *ssh_bind, int blocking); +LIBSSH_API void ssh_bind_set_blocking(SSH_BIND *sshbind, int blocking); /** * @brief Recover the file descriptor from the session. @@ -78,7 +89,7 @@ LIBSSH_API void ssh_bind_set_blocking(SSH_BIND *ssh_bind, int blocking); * * @return The file descriptor. */ -LIBSSH_API socket_t ssh_bind_get_fd(SSH_BIND *ssh_bind); +LIBSSH_API socket_t ssh_bind_get_fd(SSH_BIND *sshbind); /** * @brief Set the file descriptor for a session. @@ -87,7 +98,7 @@ LIBSSH_API socket_t ssh_bind_get_fd(SSH_BIND *ssh_bind); * * @param fd The file descriptor. */ -LIBSSH_API void ssh_bind_set_fd(SSH_BIND *ssh_bind, socket_t fd); +LIBSSH_API void ssh_bind_set_fd(SSH_BIND *sshbind, socket_t fd); /** * @brief Allow the file descriptor to accept new sessions. diff --git a/include/libssh/session.h b/include/libssh/session.h index d7bbfcf2..b9f425a9 100644 --- a/include/libssh/session.h +++ b/include/libssh/session.h @@ -29,7 +29,6 @@ typedef struct ssh_kbdint_struct* ssh_kbdint; struct ssh_session_struct { struct error_struct error; struct socket *socket; - ssh_options options; char *serverbanner; char *clientbanner; int protoversion; @@ -93,6 +92,24 @@ struct ssh_session_struct { int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg); int log_verbosity; /*cached copy of the option structure */ int log_indent; /* indentation level in enter_function logs */ + + ssh_callbacks callbacks; /* Callbacks to user functions */ + + /* options */ + char *username; + char *host; + char *bindaddr; /* TODO: check if needed */ + char *xbanner; /* TODO: looks like it is not needed */ + char *identity; + char *sshdir; + char *knownhosts; + char *wanted_methods[10]; + unsigned long timeout; /* seconds */ + unsigned long timeout_usec; + unsigned int port; + socket_t fd; + int ssh2; + int ssh1; }; int ssh_handle_packets(ssh_session session); diff --git a/libssh/auth.c b/libssh/auth.c index d7fd3fa1..59fd889a 100644 --- a/libssh/auth.c +++ b/libssh/auth.c @@ -37,7 +37,6 @@ #include "libssh/keyfiles.h" #include "libssh/packet.h" #include "libssh/session.h" -#include "libssh/options.h" #include "libssh/keys.h" /** \defgroup ssh_auth SSH Authentication functions @@ -224,13 +223,13 @@ int ssh_userauth_none(ssh_session session, const char *username) { #endif if (username == NULL) { - if (session->options->username == NULL) { - if (ssh_options_set(session->options, SSH_OPTIONS_USER, NULL) < 0) { + if (session->username == NULL) { + if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { leave_function(); return rc; } } - user = string_from_char(session->options->username); + user = string_from_char(session->username); } else { user = string_from_char(username); } @@ -330,13 +329,13 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username, #endif if (username == NULL) { - if (session->options->username == NULL) { - if (ssh_options_set(session->options, SSH_OPTIONS_USER, NULL) < 0) { + if (session->username == NULL) { + if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { leave_function(); return rc; } } - user = string_from_char(session->options->username); + user = string_from_char(session->username); } else { user = string_from_char(username); } @@ -442,13 +441,13 @@ int ssh_userauth_pubkey(ssh_session session, const char *username, #endif if (username == NULL) { - if (session->options->username == NULL) { - if (ssh_options_set(session->options, SSH_OPTIONS_USER, NULL) < 0) { + if (session->username == NULL) { + if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { leave_function(); return rc; } } - user = string_from_char(session->options->username); + user = string_from_char(session->username); } else { user = string_from_char(username); } @@ -560,13 +559,13 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username, } if (username == NULL) { - if (session->options->username == NULL) { - if (ssh_options_set(session->options, SSH_OPTIONS_USER, NULL) < 0) { + if (session->username == NULL) { + if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { leave_function(); return rc; } } - user = string_from_char(session->options->username); + user = string_from_char(session->username); } else { user = string_from_char(username); } @@ -687,13 +686,13 @@ int ssh_userauth_password(ssh_session session, const char *username, #endif if (username == NULL) { - if (session->options->username == NULL) { - if (ssh_options_set(session->options, SSH_OPTIONS_USER, NULL) < 0) { + if (session->username == NULL) { + if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { leave_function(); return rc; } } - user = string_from_char(session->options->username); + user = string_from_char(session->username); } else { user = string_from_char(username); } @@ -903,18 +902,18 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { #endif size = ARRAY_SIZE(keytab); - if (session->options->identity) { + if (session->identity) { ssh_log(session, SSH_LOG_RARE, - "Trying identity file %s\n", session->options->identity); + "Trying identity file %s\n", session->identity); - id = malloc(strlen(session->options->identity) + 1 + 4); + id = malloc(strlen(session->identity) + 1 + 4); if (id == NULL) { leave_function(); return SSH_AUTH_ERROR; } - sprintf(id, "%s.pub", session->options->identity); + sprintf(id, "%s.pub", session->identity); - keytab[size - 1].privatekey = session->options->identity; + keytab[size - 1].privatekey = session->identity; keytab[size - 1].publickey = id; } @@ -1369,12 +1368,12 @@ int ssh_userauth_kbdint(ssh_session session, const char *user, if (session->kbdint == NULL) { /* first time we call. we must ask for a challenge */ if (user == NULL) { - if ((user = session->options->username) == NULL) { - if (ssh_options_set(session->options, SSH_OPTIONS_USER, NULL) < 0) { + if ((user = session->username) == NULL) { + if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { leave_function(); return SSH_AUTH_ERROR; } else { - user = session->options->username; + user = session->username; } } } diff --git a/libssh/client.c b/libssh/client.c index 8c5e8ba7..84fbd845 100644 --- a/libssh/client.c +++ b/libssh/client.c @@ -35,12 +35,11 @@ #include "libssh/packet.h" #include "libssh/socket.h" #include "libssh/session.h" -#include "libssh/options.h" #include "libssh/dh.h" -#define set_status(opt,status) do {\ - if (opt->callbacks && opt->callbacks->connect_status_function) \ - opt->callbacks->connect_status_function(opt->callbacks->userdata, status); \ +#define set_status(session, status) do {\ + if (session->callbacks && session->callbacks->connect_status_function) \ + session->callbacks->connect_status_function(session->callbacks->userdata, status); \ } while (0) /** @@ -169,8 +168,8 @@ int ssh_send_banner(ssh_session session, int server) { banner = session->version == 1 ? CLIENTBANNER1 : CLIENTBANNER2; - if (session->options->banner) { - banner = session->options->banner; + if (session->xbanner) { + banner = session->xbanner; } if (server) { @@ -476,7 +475,6 @@ int ssh_service_request(ssh_session session, const char *service) { * \see ssh_disconnect() */ int ssh_connect(ssh_session session) { - ssh_options options = session->options; int ssh1 = 0; int ssh2 = 0; int fd = -1; @@ -486,12 +484,6 @@ int ssh_connect(ssh_session session) { return SSH_ERROR; } - if (session->options == NULL) { - ssh_set_error(session, SSH_FATAL, "No options set"); - return SSH_ERROR; - } - options = session->options; - enter_function(); session->alive = 0; @@ -501,22 +493,22 @@ int ssh_connect(ssh_session session) { leave_function(); return SSH_ERROR; } - if (options->fd == -1 && options->host == NULL) { + if (session->fd == -1 && session->host == NULL) { ssh_set_error(session, SSH_FATAL, "Hostname required"); leave_function(); return SSH_ERROR; } - if (options->fd != -1) { - fd = options->fd; + if (session->fd != -1) { + fd = session->fd; } else { - fd = ssh_connect_host(session, options->host, options->bindaddr, - options->port, options->timeout, options->timeout_usec); + fd = ssh_connect_host(session, session->host, session->bindaddr, + session->port, session->timeout, session->timeout_usec); } if (fd < 0) { leave_function(); return SSH_ERROR; } - set_status(options, 0.2); + set_status(session, 0.2); ssh_socket_set_fd(session->socket, fd); @@ -528,7 +520,7 @@ int ssh_connect(ssh_session session) { leave_function(); return SSH_ERROR; } - set_status(options, 0.4); + set_status(session, 0.4); ssh_log(session, SSH_LOG_RARE, "SSH server banner: %s", session->serverbanner); @@ -542,9 +534,9 @@ int ssh_connect(ssh_session session) { } /* Here we decide which version of the protocol to use. */ - if (ssh2 && options->ssh2allowed) { + if (ssh2 && session->ssh2) { session->version = 2; - } else if(ssh1 && options->ssh1allowed) { + } else if(ssh1 && session->ssh1) { session->version = 1; } else { ssh_set_error(session, SSH_FATAL, @@ -563,7 +555,7 @@ int ssh_connect(ssh_session session) { leave_function(); return SSH_ERROR; } - set_status(options, 0.5); + set_status(session, 0.5); switch (session->version) { case 2: @@ -573,7 +565,7 @@ int ssh_connect(ssh_session session) { leave_function(); return SSH_ERROR; } - set_status(options,0.6); + set_status(session,0.6); ssh_list_kex(session, &session->server_kex); if (set_kex(session) < 0) { @@ -588,7 +580,7 @@ int ssh_connect(ssh_session session) { leave_function(); return SSH_ERROR; } - set_status(options,0.8); + set_status(session,0.8); if (dh_handshake(session) < 0) { ssh_socket_close(session->socket); @@ -596,7 +588,7 @@ int ssh_connect(ssh_session session) { leave_function(); return SSH_ERROR; } - set_status(options,1.0); + set_status(session,1.0); session->connected = 1; break; @@ -607,7 +599,7 @@ int ssh_connect(ssh_session session) { leave_function(); return SSH_ERROR; } - set_status(options,0.6); + set_status(session,0.6); session->connected = 1; break; diff --git a/libssh/config.c b/libssh/config.c index b9118e67..6bd4e316 100644 --- a/libssh/config.c +++ b/libssh/config.c @@ -26,7 +26,7 @@ #include #include "libssh/priv.h" -#include "libssh/options.h" +#include "libssh/session.h" enum ssh_config_opcode_e { SOC_UNSUPPORTED = -1, @@ -150,7 +150,7 @@ static int ssh_config_get_yesno(char **str, int notfound) { return notfound; } -static int ssh_config_parse_line(ssh_options opt, const char *line, +static int ssh_config_parse_line(ssh_session session, const char *line, unsigned int count, int *parsing) { enum ssh_config_opcode_e opcode; const char *p; @@ -186,7 +186,7 @@ static int ssh_config_parse_line(ssh_options opt, const char *line, *parsing = 0; for (p = ssh_config_get_str(&s, NULL); p && *p; p = ssh_config_get_str(&s, NULL)) { - if (match_hostname(opt->host, p, strlen(p))) { + if (match_hostname(session->host, p, strlen(p))) { *parsing = 1; } } @@ -194,43 +194,43 @@ static int ssh_config_parse_line(ssh_options opt, const char *line, case SOC_HOSTNAME: p = ssh_config_get_str(&s, NULL); if (p && *parsing) { - ssh_options_set(opt, SSH_OPTIONS_HOST, p); + ssh_options_set(session, SSH_OPTIONS_HOST, p); } break; case SOC_PORT: p = ssh_config_get_str(&s, NULL); if (p && *parsing) { - ssh_options_set(opt, SSH_OPTIONS_PORT_STR, p); + ssh_options_set(session, SSH_OPTIONS_PORT_STR, p); } break; case SOC_USERNAME: p = ssh_config_get_str(&s, NULL); if (p && *parsing) { - ssh_options_set(opt, SSH_OPTIONS_USER, p); + ssh_options_set(session, SSH_OPTIONS_USER, p); } break; case SOC_IDENTITY: p = ssh_config_get_str(&s, NULL); if (p && *parsing) { - ssh_options_set(opt, SSH_OPTIONS_IDENTITY, p); + ssh_options_set(session, SSH_OPTIONS_IDENTITY, p); } break; case SOC_CIPHERS: p = ssh_config_get_str(&s, NULL); if (p && *parsing) { - ssh_options_set(opt, SSH_OPTIONS_CIPHERS_C_S, p); - ssh_options_set(opt, SSH_OPTIONS_CIPHERS_S_C, p); + ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, p); + ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, p); } break; case SOC_COMPRESSION: i = ssh_config_get_yesno(&s, -1); if (i >= 0 && *parsing) { if (i) { - ssh_options_set(opt, SSH_OPTIONS_COMPRESSION_C_S, "zlib"); - ssh_options_set(opt, SSH_OPTIONS_COMPRESSION_S_C, "zlib"); + ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "zlib"); + ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "zlib"); } else { - ssh_options_set(opt, SSH_OPTIONS_COMPRESSION_C_S, "none"); - ssh_options_set(opt, SSH_OPTIONS_COMPRESSION_S_C, "none"); + ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "none"); + ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "none"); } } break; @@ -244,18 +244,18 @@ static int ssh_config_parse_line(ssh_options opt, const char *line, return -1; } i = 0; - ssh_options_set(opt, SSH_OPTIONS_SSH1, &i); - ssh_options_set(opt, SSH_OPTIONS_SSH2, &i); + ssh_options_set(session, SSH_OPTIONS_SSH1, &i); + ssh_options_set(session, SSH_OPTIONS_SSH2, &i); for (a = strtok(b, ","); a; a = strtok(NULL, ",")) { switch (atoi(a)) { case 1: i = 1; - ssh_options_set(opt, SSH_OPTIONS_SSH1, &i); + ssh_options_set(session, SSH_OPTIONS_SSH1, &i); break; case 2: i = 1; - ssh_options_set(opt, SSH_OPTIONS_SSH2, &i); + ssh_options_set(session, SSH_OPTIONS_SSH2, &i); break; default: break; @@ -267,7 +267,7 @@ static int ssh_config_parse_line(ssh_options opt, const char *line, case SOC_TIMEOUT: i = ssh_config_get_int(&s, -1); if (i >= 0 && *parsing) { - ssh_options_set(opt, SSH_OPTIONS_TIMEOUT, &i); + ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &i); } break; case SOC_UNSUPPORTED: @@ -285,7 +285,7 @@ static int ssh_config_parse_line(ssh_options opt, const char *line, } /* ssh_config_parse_file */ -int ssh_config_parse_file(ssh_options opt, const char *filename) { +int ssh_config_parse_file(ssh_session session, const char *filename) { char line[1024] = {0}; unsigned int count = 0; FILE *f; @@ -295,14 +295,14 @@ int ssh_config_parse_file(ssh_options opt, const char *filename) { return -1; } - if (opt->log_verbosity) { + if (session->log_verbosity) { fprintf(stderr, "Reading configuration data from %s\n", filename); } parsing = 1; while (fgets(line, sizeof(line), f)) { count++; - if (ssh_config_parse_line(opt, line, count, &parsing) < 0) { + if (ssh_config_parse_line(session, line, count, &parsing) < 0) { fclose(f); return -1; } diff --git a/libssh/dh.c b/libssh/dh.c index 1f1b20b9..0142c8d5 100644 --- a/libssh/dh.c +++ b/libssh/dh.c @@ -53,7 +53,6 @@ #include "libssh/crypto.h" #include "libssh/buffer.h" #include "libssh/session.h" -#include "libssh/options.h" #include "libssh/keys.h" #include "libssh/dh.h" @@ -1006,11 +1005,11 @@ int signature_verify(ssh_session session, ssh_string signature) { return -1; } - if (session->options->wanted_methods[SSH_HOSTKEYS]) { - if(!match(session->options->wanted_methods[SSH_HOSTKEYS],pubkey->type_c)) { + if (session->wanted_methods[SSH_HOSTKEYS]) { + if(!match(session->wanted_methods[SSH_HOSTKEYS],pubkey->type_c)) { ssh_set_error(session, SSH_FATAL, "Public key from server (%s) doesn't match user preference (%s)", - pubkey->type_c, session->options->wanted_methods[SSH_HOSTKEYS]); + pubkey->type_c, session->wanted_methods[SSH_HOSTKEYS]); publickey_free(pubkey); leave_function(); return -1; diff --git a/libssh/kex.c b/libssh/kex.c index d8d5b849..8823fbc4 100644 --- a/libssh/kex.c +++ b/libssh/kex.c @@ -38,7 +38,6 @@ #include "libssh/packet.h" #include "libssh/session.h" #include "libssh/wrapper.h" -#include "libssh/options.h" #include "libssh/keys.h" #include "libssh/dh.h" @@ -339,7 +338,6 @@ void ssh_list_kex(ssh_session session, KEX *kex) { int set_kex(ssh_session session){ KEX *server = &session->server_kex; KEX *client=&session->client_kex; - ssh_options options=session->options; int i; const char *wanted; enter_function(); @@ -352,7 +350,7 @@ int set_kex(ssh_session session){ } memset(client->methods,0,10*sizeof(char **)); for (i=0;i<10;i++){ - if(!(wanted=options->wanted_methods[i])) + if(!(wanted=session->wanted_methods[i])) wanted=default_methods[i]; client->methods[i]=ssh_find_matching(server->methods[i],wanted); if(!client->methods[i] && i < SSH_LANG_C_S){ diff --git a/libssh/keyfiles.c b/libssh/keyfiles.c index 372093a5..d368a287 100644 --- a/libssh/keyfiles.c +++ b/libssh/keyfiles.c @@ -42,7 +42,6 @@ #include "libssh/keyfiles.h" #include "libssh/session.h" #include "libssh/wrapper.h" -#include "libssh/options.h" #include "libssh/misc.h" #include "libssh/keys.h" @@ -599,9 +598,9 @@ static int pem_get_password(char *buf, int size, int rwflag, void *userdata) { ssh_log(session, SSH_LOG_RARE, "Trying to call external authentication function"); - if (session && session->options->callbacks->auth_function) { - if (session->options->callbacks->auth_function("Passphrase for private key:", buf, size, 0, 0, - session->options->callbacks->userdata) < 0) { + if (session && session->callbacks->auth_function) { + if (session->callbacks->auth_function("Passphrase for private key:", buf, size, 0, 0, + session->callbacks->userdata) < 0) { return 0; } @@ -649,13 +648,13 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename, ssh_log(session, SSH_LOG_RARE, "Trying to read %s, passphase=%s, authcb=%s", filename, passphrase ? "true" : "false", - session->options->callbacks->auth_function ? "true" : "false"); + session->callbacks->auth_function ? "true" : "false"); switch (type) { case TYPE_DSS: if (passphrase == NULL) { - if (session->options->callbacks->auth_function) { - auth_cb = session->options->callbacks->auth_function; - auth_ud = session->options->callbacks->userdata; + if (session->callbacks->auth_function) { + auth_cb = session->callbacks->auth_function; + auth_ud = session->callbacks->userdata; #ifdef HAVE_LIBGCRYPT valid = read_dsa_privatekey(file, &dsa, auth_cb, auth_ud, @@ -693,9 +692,9 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename, break; case TYPE_RSA: if (passphrase == NULL) { - if (session->options->callbacks->auth_function) { - auth_cb = session->options->callbacks->auth_function; - auth_ud = session->options->callbacks->userdata; + if (session->callbacks->auth_function) { + auth_cb = session->callbacks->auth_function; + auth_ud = session->callbacks->userdata; #ifdef HAVE_LIBGCRYPT valid = read_rsa_privatekey(file, &rsa, auth_cb, auth_ud, "Passphrase for private key:"); @@ -1386,21 +1385,21 @@ int ssh_is_server_known(ssh_session session) { enter_function(); - if (ssh_options_set(session->options, SSH_OPTIONS_KNOWNHOSTS, NULL) < 0) { + if (ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, NULL) < 0) { ssh_set_error(session, SSH_REQUEST_DENIED, "Can't find a known_hosts file"); leave_function(); return SSH_SERVER_FILE_NOT_FOUND; } - if (session->options->host == NULL) { + if (session->host == NULL) { ssh_set_error(session, SSH_FATAL, "Can't verify host in known hosts if the hostname isn't known"); leave_function(); return SSH_SERVER_ERROR; } - host = lowercase(session->options->host); + host = lowercase(session->host); if (host == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space!"); leave_function(); @@ -1409,7 +1408,7 @@ int ssh_is_server_known(ssh_session session) { do { tokens = ssh_get_knownhost_line(session, &file, - session->options->known_hosts_file, &type); + session->knownhosts, &type); /* End of file, return the current state */ if (tokens == NULL) { @@ -1472,19 +1471,19 @@ int ssh_write_knownhost(ssh_session session) { char *dir; size_t len = 0; - if (ssh_options_set(session->options, SSH_OPTIONS_KNOWNHOSTS, NULL) < 0) { + if (ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, NULL) < 0) { ssh_set_error(session, SSH_FATAL, "Cannot find known_hosts file."); return -1; } - if (session->options->host == NULL) { + if (session->host == NULL) { ssh_set_error(session, SSH_FATAL, "Cannot write host in known hosts if the hostname is unknown"); return -1; } /* Check if ~/.ssh exists and create it if not */ - dir = ssh_dirname(session->options->known_hosts_file); + dir = ssh_dirname(session->knownhosts); if (dir == NULL) { ssh_set_error(session, SSH_FATAL, "%s", strerror(errno)); return -1; @@ -1499,11 +1498,11 @@ int ssh_write_knownhost(ssh_session session) { } SAFE_FREE(dir); - file = fopen(session->options->known_hosts_file, "a"); + file = fopen(session->knownhosts, "a"); if (file == NULL) { ssh_set_error(session, SSH_FATAL, "Couldn't open known_hosts file %s for appending: %s", - session->options->known_hosts_file, strerror(errno)); + session->knownhosts, strerror(errno)); return -1; } @@ -1583,7 +1582,7 @@ int ssh_write_knownhost(ssh_session session) { snprintf(buffer, sizeof(buffer), "%s %d %s %s\n", - session->options->host, + session->host, rsa_size << 3, e_string, n_string); @@ -1608,7 +1607,7 @@ int ssh_write_knownhost(ssh_session session) { snprintf(buffer, sizeof(buffer), "%s %s %s\n", - session->options->host, + session->host, session->current_crypto->server_pubkey_type, pubkey_64); diff --git a/libssh/log.c b/libssh/log.c index d119f541..0dab4aef 100644 --- a/libssh/log.c +++ b/libssh/log.c @@ -27,7 +27,6 @@ #include "libssh/priv.h" #include "libssh/session.h" -#include "libssh/options.h" /** * @defgroup ssh_log SSH Logging @@ -57,9 +56,9 @@ void ssh_log(ssh_session session, int verbosity, const char *format, ...) { vsnprintf(buffer, sizeof(buffer), format, va); va_end(va); - if (session->options->callbacks && session->options->callbacks->log_function) { - session->options->callbacks->log_function(session, verbosity, buffer, - session->options->callbacks->userdata); + if (session->callbacks && session->callbacks->log_function) { + session->callbacks->log_function(session, verbosity, buffer, + session->callbacks->userdata); } else if (verbosity == SSH_LOG_FUNCTIONS) { if (session->log_indent > 255) { min = 255; diff --git a/libssh/options.c b/libssh/options.c index 95429b0d..475cba0f 100644 --- a/libssh/options.c +++ b/libssh/options.c @@ -33,44 +33,11 @@ #endif #include #include "libssh/priv.h" -#include "libssh/options.h" +#include "libssh/session.h" #include "libssh/misc.h" - -/** \defgroup ssh_options SSH Options - * \brief options settings for a new SSH session - */ -/** \addtogroup ssh_options - * @{ */ - -/** This structure is freed automaticaly by ssh_disconnect() - * when you use it. \n - * It can be used by only one ssh_connect(), not more.\n - * also by default, ssh1 support is not allowed - * - * \brief initializes a new option structure - * \returns an empty intialized option structure. - * \see ssh_options_getopt() -*/ - -ssh_options ssh_options_new(void) { - ssh_options option; - - option = malloc(sizeof(struct ssh_options_struct)); - if (option == NULL) { - return NULL; - } - ZERO_STRUCTP(option); - option->port=22; /* set the default port */ - option->fd=-1; - option->ssh2allowed=1; -#ifdef WITH_SSH1 - option->ssh1allowed=1; -#else - option->ssh1allowed=0; +#ifdef WITH_SERVER +#include "libssh/server.h" #endif - option->bindport=22; - return option; -} /** * @brief Duplicate an option structure. @@ -84,134 +51,101 @@ ssh_options ssh_options_new(void) { * * @see ssh_session_connect() */ -ssh_options ssh_options_copy(ssh_options opt) { - ssh_options new = NULL; +#if 0 +ssh_session ssh_session_copy(ssh_options opt) { + ssh_session new = NULL; int i; - if (opt == NULL) { + if (session == NULL) { return NULL; } - new = ssh_options_new(); + new = ssh_session_new(); if (new == NULL) { return NULL; } - if (opt->username) { - new->username = strdup(opt->username); + if (session->username) { + new->username = strdup(session->username); if (new->username == NULL) { goto err; } } - if (opt->host) { - new->host = strdup(opt->host); + if (session->host) { + new->host = strdup(session->host); if (new->host == NULL) { goto err; } } - if (opt->bindaddr) { - new->bindaddr = strdup(opt->bindaddr); + if (session->bindaddr) { + new->bindaddr = strdup(session->bindaddr); if (new->bindaddr == NULL) { goto err; } } - if (opt->identity) { - new->identity=strdup(opt->identity); + if (session->identity) { + new->identity=strdup(session->identity); if (new->identity == NULL) { return NULL; } } - if (opt->ssh_dir) { - new->ssh_dir = strdup(opt->ssh_dir); - if (new->ssh_dir == NULL) { + if (session->sshdir) { + new->ssh_dir = strdup(session->sshdir); + if (new->sshdir == NULL) { goto err; } } - if (opt->known_hosts_file) { - new->known_hosts_file = strdup(opt->known_hosts_file); - if (new->known_hosts_file == NULL) { + if (session->knownhosts) { + new->knownhosts = strdup(session->knownhosts); + if (new->knownhosts == NULL) { goto err; } } - if (opt->dsakey) { - new->dsakey = strdup(opt->dsakey); + if (session->dsakey) { + new->dsakey = strdup(session->dsakey); if (new->dsakey == NULL) { goto err; } } - if (opt->rsakey) { - new->rsakey = strdup(opt->rsakey); + if (session->rsakey) { + new->rsakey = strdup(session->rsakey); if (new->rsakey == NULL) { goto err; } } for (i = 0; i < 10; ++i) { - if (opt->wanted_methods[i]) { - new->wanted_methods[i] = strdup(opt->wanted_methods[i]); + if (session->wanted_methods[i]) { + new->wanted_methods[i] = strdup(session->wanted_methods[i]); if (new->wanted_methods[i] == NULL) { goto err; } } } - new->fd = opt->fd; - new->port = opt->port; - new->callbacks = opt->callbacks; - new->timeout = opt->timeout; - new->timeout_usec = opt->timeout_usec; - new->ssh2allowed = opt->ssh2allowed; - new->ssh1allowed = opt->ssh1allowed; - new->log_verbosity = opt->log_verbosity; + new->fd = session->fd; + new->port = session->port; + new->callbacks = session->callbacks; + new->timeout = session->timeout; + new->timeout_usec = session->timeout_usec; + new->ssh2 = session->ssh2; + new->ssh1 = session->ssh1; + new->log_verbosity = session->log_verbosity; return new; err: - ssh_options_free(new); + ssh_session_free(new); return NULL; } - -/** - * @brief Frees an option structure. - * - * @param opt Option structure to free. - */ -void ssh_options_free(ssh_options opt) { - int i; - - if (opt == NULL) { - return; - } - - /* - * We don't touch the banner. If the implementation - * did use it, they have to free it - */ - - SAFE_FREE(opt->username); - SAFE_FREE(opt->host); - SAFE_FREE(opt->identity); - SAFE_FREE(opt->bindaddr); - SAFE_FREE(opt->ssh_dir); - SAFE_FREE(opt->known_hosts_file); - SAFE_FREE(opt->dsakey); - SAFE_FREE(opt->rsakey); - - for (i = 0; i < 10; i++) { - if (opt->wanted_methods[i]) { - free(opt->wanted_methods[i]); - } - } - ZERO_STRUCTP(opt); - SAFE_FREE(opt); -} +#endif #ifndef _WIN32 -static char *get_username_from_uid(ssh_options opt, uid_t uid){ +static char *get_username_from_uid(ssh_session session, uid_t uid){ struct passwd *pwd = NULL; pwd = getpwuid(uid); if (pwd == NULL) { - ssh_set_error(opt,SSH_FATAL,"uid %d doesn't exist !",uid); + ssh_set_error(session, SSH_FATAL, "uid %d doesn't exist !", uid); return NULL; } @@ -219,24 +153,25 @@ static char *get_username_from_uid(ssh_options opt, uid_t uid){ } #endif -static int ssh_options_set_algo(ssh_options opt, int algo, const char *list) { +static int ssh_options_set_algo(ssh_session session, int algo, + const char *list) { if (!verify_existing_algo(algo, list)) { - ssh_set_error(opt, SSH_REQUEST_DENIED, + ssh_set_error(session, SSH_REQUEST_DENIED, "Setting method: no algorithm for method \"%s\" (%s)\n", ssh_kex_nums[algo], list); return -1; } - SAFE_FREE(opt->wanted_methods[algo]); - opt->wanted_methods[algo] = strdup(list); - if (opt->wanted_methods[algo] == NULL) { + SAFE_FREE(session->wanted_methods[algo]); + session->wanted_methods[algo] = strdup(list); + if (session->wanted_methods[algo] == NULL) { return -1; } return 0; } -static char *dir_expand_dup(ssh_options opt, const char *value, int allowsshdir) { +static char *dir_expand_dup(ssh_session session, const char *value, int allowsshdir) { char *new; if (value[0] == '~' && value[1] == '/') { @@ -252,19 +187,19 @@ static char *dir_expand_dup(ssh_options opt, const char *value, int allowsshdir) } if (allowsshdir && strncmp(value, "SSH_DIR/", 8) == 0) { size_t lv, ls; - if (opt->ssh_dir == NULL) { - if (ssh_options_set(opt, SSH_OPTIONS_SSH_DIR, NULL) < 0) + if (session->sshdir == NULL) { + if (ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL) < 0) return NULL; } value += 7; lv = strlen(value); - ls = strlen(opt->ssh_dir); + ls = strlen(session->sshdir); new = malloc(lv + ls + 1); if (new == NULL) return NULL; - memcpy(new, opt->ssh_dir, ls); + memcpy(new, session->sshdir, ls); memcpy(new + ls, value, lv + 1); return new; } @@ -274,7 +209,7 @@ static char *dir_expand_dup(ssh_options opt, const char *value, int allowsshdir) /** * @brief This function can set all possible ssh options. * - * @param opt An allocated ssh option structure. + * @param session An allocated ssh option structure. * * @param type The option type to set. This could be one of the * following: @@ -403,18 +338,18 @@ static char *dir_expand_dup(ssh_options opt, const char *value, int allowsshdir) * Set the compression to use for server to client * communication (string, "none" or "zlib"). * - * SSH_OPTIONS_SERVER_BINDADDR: - * SSH_OPTIONS_SERVER_HOSTKEY: + * SSH_BIND_OPTIONS_BINDADDR: + * SSH_BIND_OPTIONS_HOSTKEY: * Set the server public key type: ssh-rsa or ssh-dss * (string). * - * SSH_OPTIONS_SERVER_DSAKEY: + * SSH_BIND_OPTIONS_DSAKEY: * Set the path to the dsa ssh host key (string). * - * SSH_OPTIONS_SERVER_RSAKEY: + * SSH_BIND_OPTIONS_RSAKEY: * Set the path to the ssh host rsa key (string). * - * SSH_OPTIONS_SERVER_BANNER: + * SSH_BIND_OPTIONS_BANNER: * Set the server banner sent to clients (string). * * @param value The value to set. This is a generic pointer and the @@ -423,12 +358,12 @@ static char *dir_expand_dup(ssh_options opt, const char *value, int allowsshdir) * * @return 0 on success, < 0 on error. */ -int ssh_options_set(ssh_options opt, enum ssh_options_e type, +int ssh_options_set(ssh_session session, enum ssh_options_e type, const void *value) { char *p, *q; - int i; + long int i; - if (opt == NULL) { + if (session == NULL) { return -1; } @@ -440,38 +375,38 @@ int ssh_options_set(ssh_options opt, enum ssh_options_e type, } p = strchr(q, '@'); - SAFE_FREE(opt->host); + SAFE_FREE(session->host); if (p) { *p = '\0'; - opt->host = strdup(p + 1); - if (opt->host == NULL) { + session->host = strdup(p + 1); + if (session->host == NULL) { SAFE_FREE(q); return -1; } - SAFE_FREE(opt->username); - opt->username = strdup(q); + SAFE_FREE(session->username); + session->username = strdup(q); SAFE_FREE(q); - if (opt->username == NULL) { + if (session->username == NULL) { return -1; } } else { - opt->host = q; + session->host = q; } break; case SSH_OPTIONS_PORT: if (value == NULL) { - opt->port = 22 & 0xffff; + session->port = 22 & 0xffff; } else { int *x = (int *) value; - opt->port = *x & 0xffff; + session->port = *x & 0xffff; } break; case SSH_OPTIONS_PORT_STR: if (value == NULL) { - opt->port = 22 & 0xffff; + session->port = 22 & 0xffff; } else { q = strdup(value); if (q == NULL) { @@ -483,11 +418,11 @@ int ssh_options_set(ssh_options opt, enum ssh_options_e type, } SAFE_FREE(q); - opt->port = i & 0xffff; + session->port = i & 0xffff; } break; case SSH_OPTIONS_USER: - SAFE_FREE(opt->username); + SAFE_FREE(session->username); if (value == NULL) { /* set default username */ #ifdef _WIN32 DWORD size = 0; @@ -497,38 +432,38 @@ int ssh_options_set(ssh_options opt, enum ssh_options_e type, return -1; } if (GetUserName(q, &size)) { - opt->username = q; + session->username = q; } else { SAFE_FREE(q); return -1; } #else /* _WIN32 */ - q = get_username_from_uid(opt, getuid()); + q = get_username_from_uid(session, getuid()); if (q == NULL) { return -1; } - opt->username = q; + session->username = q; #endif /* _WIN32 */ } else { /* username provided */ - opt->username = strdup(value); - if (opt->username == NULL) { + session->username = strdup(value); + if (session->username == NULL) { return -1; } } break; case SSH_OPTIONS_SSH_DIR: if (value == NULL) { - SAFE_FREE(opt->ssh_dir); + SAFE_FREE(session->sshdir); /* TODO: why ~/.ssh/ instead of ~/.ssh ? */ - opt->ssh_dir = dir_expand_dup(opt, "~/.ssh/", 0); - if (opt->ssh_dir == NULL) { + session->sshdir = dir_expand_dup(session, "~/.ssh/", 0); + if (session->sshdir == NULL) { return -1; } } else { - SAFE_FREE(opt->ssh_dir); - opt->ssh_dir = dir_expand_dup(opt, value, 0); - if (opt->ssh_dir == NULL) { + SAFE_FREE(session->sshdir); + session->sshdir = dir_expand_dup(session, value, 0); + if (session->sshdir == NULL) { return -1; } } @@ -538,24 +473,24 @@ int ssh_options_set(ssh_options opt, enum ssh_options_e type, if (value == NULL) { return -1; } - SAFE_FREE(opt->identity); - opt->identity = dir_expand_dup(opt, value, 1); - if (opt->identity == NULL) { + SAFE_FREE(session->identity); + session->identity = dir_expand_dup(session, value, 1); + if (session->identity == NULL) { return -1; } break; case SSH_OPTIONS_KNOWNHOSTS: if (value == NULL) { - SAFE_FREE(opt->known_hosts_file); - opt->known_hosts_file = dir_expand_dup(opt, - "SSH_DIR/known_hosts", 1); - if (opt->known_hosts_file == NULL) { + SAFE_FREE(session->knownhosts); + session->knownhosts = dir_expand_dup(session, + "SSH_DIR/known_hosts", 1); + if (session->knownhosts == NULL) { return -1; } } else { - SAFE_FREE(opt->known_hosts_file); - opt->known_hosts_file = dir_expand_dup(opt, value, 1); - if (opt->known_hosts_file == NULL) { + SAFE_FREE(session->knownhosts); + session->knownhosts = dir_expand_dup(session, value, 1); + if (session->knownhosts == NULL) { return -1; } } @@ -566,7 +501,7 @@ int ssh_options_set(ssh_options opt, enum ssh_options_e type, } else { long *x = (long *) value; - opt->timeout = *x; + session->timeout = *x; } break; case SSH_OPTIONS_TIMEOUT_USEC: @@ -575,7 +510,7 @@ int ssh_options_set(ssh_options opt, enum ssh_options_e type, } else { long *x = (long *) value; - opt->timeout_usec = *x; + session->timeout_usec = *x; } break; case SSH_OPTIONS_SSH1: @@ -583,7 +518,7 @@ int ssh_options_set(ssh_options opt, enum ssh_options_e type, return -1; } else { int *x = (int *) value; - opt->ssh1allowed = *x; + session->ssh1 = *x; } break; case SSH_OPTIONS_SSH2: @@ -591,7 +526,7 @@ int ssh_options_set(ssh_options opt, enum ssh_options_e type, return -1; } else { int *x = (int *) value; - opt->ssh2allowed = *x; + session->ssh2 = *x; } break; case SSH_OPTIONS_LOG_VERBOSITY: @@ -600,93 +535,38 @@ int ssh_options_set(ssh_options opt, enum ssh_options_e type, } else { int *x = (int *) value; - opt->log_verbosity = *x; + session->log_verbosity = *x; } case SSH_OPTIONS_CIPHERS_C_S: if (value == NULL) { return -1; } else { - ssh_options_set_algo(opt, SSH_CRYPT_C_S, value); + ssh_options_set_algo(session, SSH_CRYPT_C_S, value); } break; case SSH_OPTIONS_CIPHERS_S_C: if (value == NULL) { return -1; } else { - ssh_options_set_algo(opt, SSH_CRYPT_S_C, value); + ssh_options_set_algo(session, SSH_CRYPT_S_C, value); } break; case SSH_OPTIONS_COMPRESSION_C_S: if (value == NULL) { return -1; } else { - ssh_options_set_algo(opt, SSH_COMP_C_S, value); + ssh_options_set_algo(session, SSH_COMP_C_S, value); } break; case SSH_OPTIONS_COMPRESSION_S_C: if (value == NULL) { return -1; } else { - ssh_options_set_algo(opt, SSH_COMP_S_C, value); - } - break; - case SSH_OPTIONS_SERVER_HOSTKEY: - if (value == NULL) { - return -1; - } else { - ssh_options_set_algo(opt, SSH_HOSTKEYS, value); - } - break; - case SSH_OPTIONS_SERVER_BINDADDR: - if (value == NULL) { - return -1; - } else { - opt->bindaddr = strdup(value); - if (opt->bindaddr == NULL) { - return -1; - } - } - break; - case SSH_OPTIONS_SERVER_BINDPORT: - if (value == NULL) { - return -1; - } else { - int *x = (int *) value; - opt->bindport = *x & 0xffff; - } - break; - case SSH_OPTIONS_SERVER_DSAKEY: - if (value == NULL) { - return -1; - } else { - opt->dsakey = strdup(value); - if (opt->dsakey == NULL) { - return -1; - } - } - break; - case SSH_OPTIONS_SERVER_RSAKEY: - if (value == NULL) { - return -1; - } else { - opt->rsakey = strdup(value); - if (opt->rsakey == NULL) { - return -1; - } - } - break; - case SSH_OPTIONS_SERVER_BANNER: - if (value == NULL) { - return -1; - } else { - opt->banner = strdup(value); - if (opt->banner == NULL) { - return -1; - } + ssh_options_set_algo(session, SSH_COMP_S_C, value); } break; default: - ssh_set_error(opt, SSH_REQUEST_DENIED, "Unkown ssh option %d", type); + ssh_set_error(session, SSH_REQUEST_DENIED, "Unkown ssh option %d", type); return -1; break; } @@ -694,235 +574,102 @@ int ssh_options_set(ssh_options opt, enum ssh_options_e type, return 0; } -/** - * @brief Set destination hostname - * - * @param opt The option structure to use. - * - * @param hostname The host name to connect. - * - * @return 0 on succes, < 0 on error. - */ -int ssh_options_set_host(ssh_options opt, const char *hostname){ - return ssh_options_set(opt, SSH_OPTIONS_HOST, hostname); -} - -/** - * @brief Set port to connect or to bind for a connection. - * - * @param opt The options structure to use. - * - * @param port The port to connect or to bind. - * - * @return 0 on success, < 0 on error. - */ -int ssh_options_set_port(ssh_options opt, unsigned int port) { - return ssh_options_set(opt, SSH_OPTIONS_PORT, &port); -} - -/** - * @brief Set the username for authentication - * - * @param opt The options structure to use. - * - * @param username The username to authenticate. - * - * @return 0 on success, -1 on error. - * - * @bug this should not be set at options time - */ -int ssh_options_set_username(ssh_options opt, const char *username) { - return ssh_options_set(opt, SSH_OPTIONS_USER, username); -} - -/** - * @brief Set a file descriptor for connection. - * - * If you wish to open the socket yourself for a reason or another, set the - * file descriptor. Don't forget to use ssh_option_set_hostname() as the - * hostname is used as a key in the known_host mechanism. - * - * @param opt The options structure to use. - * - * @param fd An opened file descriptor to use. - * - * @return 0 on success, < 0 on error. - */ -int ssh_options_set_fd(ssh_options opt, socket_t fd) { - return ssh_options_set(opt, SSH_OPTIONS_FD, &fd); -} - -/** - * @brief Set the local address and port binding. - * - * In case your client has multiple IP adresses, select the local address and - * port to use for the socket.\n - * If the address or port is not bindable, it may be impossible to connect. - * - * @param opt The options structure to use. - * - * @param bindaddr The bind address in form of hostname or ip address. - * - * @param port The port number to bind. - * - * @return 0 on success, < 0 on error. - */ -int ssh_options_set_bind(ssh_options opt, const char *bindaddr, int port) { - int rc; - - rc = ssh_options_set(opt, SSH_OPTIONS_SERVER_BINDADDR, bindaddr); - if (rc < 0) { - return -1; - } - rc = ssh_options_set(opt, SSH_OPTIONS_SERVER_BINDPORT, &port); - - return rc; -} - -/** - * @brief Set the ssh directory. - * - * The ssh directory is used for files like known_hosts and identity (public - * and private keys) - * - * @param opt The options structure to use. - * - * @param dir The directory to set. It may include "%s" which will be - * replaced by the user home directory. - * - * @return 0 on success, < 0 on error. - * - * @see ssh_options_set_user_home_dir() - */ -int ssh_options_set_ssh_dir(ssh_options opt, const char *dir) { - return ssh_options_set(opt, SSH_OPTIONS_SSH_DIR, dir); -} - -/** - * @brief Set the known hosts file name. - * - * The known hosts file is used to certify remote hosts are genuine. - * - * @param opt The options structure to use. - * - * @param dir The path to the file including its name. "%s" will be - * substitued with the user home directory. - * - * @return 0 on success, < 0 on error. - * - * @see ssh_options_set_user_home_dir() - */ -int ssh_options_set_known_hosts_file(ssh_options opt, const char *dir){ - return ssh_options_set(opt, SSH_OPTIONS_KNOWNHOSTS, dir); -} - -/** - * @brief Set the identity file name. - * - * The identity file is used authenticate with public key. - * - * @param opt The options structure to use. - * - * @param identity The path to the file including its name. "%s" will be - * substitued with the user home directory. - * - * @return 0 on success, < 0 on error. - * - * @see ssh_options_set_user_home_dir() - */ -int ssh_options_set_identity(ssh_options opt, const char *identity){ - return ssh_options_set(opt, SSH_OPTIONS_IDENTITY, identity); -} - -/** - * @brief Set the path to the dsa ssh host key. - * - * @param opt The options structure to use. - * - * @param dsakey The path to the dsa key to set. - * - * @return 0 on success, < 0 on error. - */ -int ssh_options_set_dsa_server_key(ssh_options opt, const char *dsakey) { - return ssh_options_set(opt, SSH_OPTIONS_SERVER_DSAKEY, dsakey); -} - -/** - * @brief Set the path to the ssh host rsa key. - * - * @param opt The options structure to use. - * - * @param rsakey The path to the rsa key to set. - * - * @return 0 on success, < 0 on error. - */ -int ssh_options_set_rsa_server_key(ssh_options opt, const char *rsakey) { - return ssh_options_set(opt, SSH_OPTIONS_SERVER_RSAKEY, rsakey); -} - -/** - * @brief Set the server banner sent to clients. - * - * @param opt The options structure to use. - * - * @param banner A text banner to be shown. - * - * @return 0 on success, < 0 on error. - */ -int ssh_options_set_banner(ssh_options opt, const char *banner) { - return ssh_options_set(opt, SSH_OPTIONS_SERVER_BANNER, banner); -} - -/** - * @brief Set the algorithms to be used for cryptography and compression. - * - * The methods are:\n - * KEX_HOSTKEY (server public key type) : ssh-rsa or ssh-dss\n - * KEX_CRYPT_C_S (symmetric cipher client to server)\n - * KEX_CRYPT_S_C (symmetric cipher server to client)\n - * KEX_COMP_C_S (Compression client to server): zlib or none\n - * KEX_COMP_S_C (Compression server to client): zlib or none\n - * You don't have to use this function if using the default ciphers - * is okay for you\n - * in order to enable compression client to server, do\n - * @code - * ret = ssh_options_set_wanted_algos(opt,KEX_COMP_C_S,"zlib"); - * @endcode - * - * @param opt The options structure to use. - * - * @param algo The method which needs to be changed. - * - * @param list A list of algorithms to be used, in order of preference - * and separated by commas. - * - * @return 0 on success, < 0 on error - */ -int ssh_options_set_wanted_algos(ssh_options opt, int algo, const char *list) { - if (opt == NULL || list == NULL) { - return -1; - } - - if(algo > SSH_LANG_S_C || algo < 0) { - ssh_set_error(opt, SSH_REQUEST_DENIED, "algo %d out of range", algo); - return -1; - } - +#ifdef WITH_SERVER +static int ssh_bind_options_set_algo(ssh_bind sshbind, int algo, + const char *list) { if (!verify_existing_algo(algo, list)) { - ssh_set_error(opt, SSH_REQUEST_DENIED, "Setting method: no algorithm " - "for method \"%s\" (%s)\n", ssh_kex_nums[algo], list); + ssh_set_error(sshbind, SSH_REQUEST_DENIED, + "Setting method: no algorithm for method \"%s\" (%s)\n", + ssh_kex_nums[algo], list); return -1; } - SAFE_FREE(opt->wanted_methods[algo]); - opt->wanted_methods[algo] = strdup(list); - if (opt->wanted_methods[algo] == NULL) { + SAFE_FREE(sshbind->wanted_methods[algo]); + sshbind->wanted_methods[algo] = strdup(list); + if (sshbind->wanted_methods[algo] == NULL) { return -1; } return 0; } +int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type, + const void *value) { +#if 0 + char *p, *q; + int i; +#endif + + if (sshbind == NULL) { + return -1; + } + + switch (type) { + case SSH_BIND_OPTIONS_HOSTKEY: + if (value == NULL) { + return -1; + } else { + ssh_bind_options_set_algo(sshbind, SSH_HOSTKEYS, value); + } + break; + case SSH_BIND_OPTIONS_BINDADDR: + if (value == NULL) { + return -1; + } else { + sshbind->bindaddr = strdup(value); + if (sshbind->bindaddr == NULL) { + return -1; + } + } + break; + case SSH_BIND_OPTIONS_BINDPORT: + if (value == NULL) { + return -1; + } else { + int *x = (int *) value; + sshbind->bindport = *x & 0xffff; + } + break; + case SSH_BIND_OPTIONS_DSAKEY: + if (value == NULL) { + return -1; + } else { + sshbind->dsakey = strdup(value); + if (sshbind->dsakey == NULL) { + return -1; + } + } + break; + case SSH_BIND_OPTIONS_RSAKEY: + if (value == NULL) { + return -1; + } else { + sshbind->rsakey = strdup(value); + if (sshbind->rsakey == NULL) { + return -1; + } + } + break; + case SSH_BIND_OPTIONS_BANNER: + if (value == NULL) { + return -1; + } else { + sshbind->banner = strdup(value); + if (sshbind->banner == NULL) { + return -1; + } + } + break; + default: + ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unkown ssh option %d", type); + return -1; + break; + } + + return 0; +} +#endif + /** * @brief Set a callback to show connection status in realtime. * @@ -941,71 +688,19 @@ int ssh_options_set_wanted_algos(ssh_options opt, int algo, const char *list) { * * @see ssh_connect() */ -int ssh_options_set_status_callback(ssh_options opt, +int ssh_set_status_callback(ssh_session session, void (*callback)(void *arg, float status), void *arg) { - if (opt == NULL || callback == NULL || opt->callbacks==NULL) { + if (session == NULL || callback == NULL || session->callbacks == NULL) { return -1; } - opt->callbacks->connect_status_function = callback; + session->callbacks->connect_status_function = callback; if(arg) - opt->callbacks->userdata=arg; + session->callbacks->userdata = arg; return 0; } -/** - * @brief Set a timeout for the connection. - * - * @param opt The options structure to use. - * - * @param seconds Number of seconds. - * - * @param usec Number of micro seconds. - * - * @return 0 on success, < 0 on error. - * - * @bug Currently it only timeouts the socket connection, not the - * complete exchange. - */ -int ssh_options_set_timeout(ssh_options opt, long seconds, long usec) { - if (ssh_options_set(opt, SSH_OPTIONS_TIMEOUT, &seconds) < 0) { - return -1; - } - - return ssh_options_set(opt, SSH_OPTIONS_TIMEOUT_USEC, &usec); -} - -/** - * @brief Allow or deny the connection to SSH1 servers. - * - * Default value is 0 (no connection to SSH1 servers). - * - * @param opt The options structure to use. - * - * @param allow Non zero value allow ssh1. - * - * @return 0 on success, < 0 on error. - */ -int ssh_options_allow_ssh1(ssh_options opt, int allow) { - return ssh_options_set(opt, SSH_OPTIONS_SSH1, &allow); -} - -/** - * @brief Allow or deny the connection to SSH2 servers. - * - * Default value is 1 (allow connection to SSH2 servers). - * - * @param opt The options structure to use. - * - * @param allow Non zero values allow ssh2. - * - * @return 0 on success, < 0 on error. - */ -int ssh_options_allow_ssh2(ssh_options opt, int allow) { - return ssh_options_set(opt, SSH_OPTIONS_SSH2, &allow); -} - /** * @brief Change the writer callback for logging. * @@ -1021,37 +716,44 @@ int ssh_options_allow_ssh2(ssh_options opt, int allow) { * * @warning The message string may contain format string characters. */ -int ssh_options_set_log_function(ssh_options opt, ssh_log_callback cb, +int ssh_set_log_callback(ssh_session session, ssh_log_callback cb, void *userdata) { - if (opt == NULL || cb == NULL || opt->callbacks==NULL) { + if (session == NULL || cb == NULL || session->callbacks == NULL) { return -1; } - opt->callbacks->log_function = cb; + session->callbacks->log_function = cb; if(userdata) - opt->callbacks->userdata = userdata; + session->callbacks->userdata = userdata; return 0; } /** - * @brief Set the session logging priority. + * @brief Set the authentication callback. * * @param opt The options structure to use. * - * @param verbosity The verbosity of the messages. Every log smaller or - * equal to verbosity will be shown\n - * SSH_LOG_NOLOG No logging \n - * SSH_LOG_RARE Rare conditions or warnings\n - * SSH_LOG_ENTRY Api-accessible entrypoints\n - * SSH_LOG_PACKET Packet id and size\n - * SSH_LOG_FUNCTIONS function entering and leaving\n + * @param cb The callback function to use. + * + * @param userdata A pointer to some user data you can pass to the + * callback. * * @return 0 on success, < 0 on error. */ -int ssh_options_set_log_verbosity(ssh_options opt, int verbosity) { - return ssh_options_set(opt, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); +int ssh_set_auth_callback(ssh_session session, ssh_auth_callback cb, + void *userdata) { + if (session == NULL || cb == NULL || session->callbacks == NULL) { + return -1; + } + + session->callbacks->auth_function = cb; + if (userdata != NULL) + session->callbacks->userdata = userdata; + + return 0; } + /** * @brief Parse command line arguments. * @@ -1071,7 +773,7 @@ int ssh_options_set_log_verbosity(ssh_options opt, int verbosity) { * * @returns 0 on success, < 0 on error. * - * @see ssh_options_new() + * @see ssh_session_new() */ int ssh_options_getopt(ssh_options options, int *argcptr, char **argv) { char *user = NULL; @@ -1194,10 +896,10 @@ int ssh_options_getopt(ssh_options options, int *argcptr, char **argv) { /* set a new option struct */ if (compress) { - if (ssh_options_set_wanted_algos(options, SSH_COMP_C_S, "zlib") < 0) { + if (ssh_options_set(options, SSH_OPTIONS_COMPRESSION_C_S, "zlib") < 0) { cont = 0; } - if (ssh_options_set_wanted_algos(options, SSH_COMP_S_C, "zlib") < 0) { + if (ssh_options_set(options, SSH_OPTIONS_COMPRESSION_S_C, "zlib") < 0) { cont = 0; } } @@ -1211,18 +913,6 @@ int ssh_options_getopt(ssh_options options, int *argcptr, char **argv) { } } - if (cont && usersa) { - if (ssh_options_set(options, SSH_OPTIONS_SERVER_HOSTKEY, "ssh-rsa") < 0) { - cont = 0; - } - } - - if (cont && usedss) { - if (ssh_options_set(options, SSH_OPTIONS_SERVER_HOSTKEY, "ssh-dss") < 0) { - cont = 0; - } - } - if (cont && user) { if (ssh_options_set(options, SSH_OPTIONS_USER, user) < 0) { cont = 0; @@ -1235,19 +925,6 @@ int ssh_options_getopt(ssh_options options, int *argcptr, char **argv) { } } - if (cont && localaddr) { - if (ssh_options_set(options, SSH_OPTIONS_SERVER_BINDADDR, localaddr) < 0) { - cont = 0; - } - } - - if (cont && bindport) { - i = atoi(bindport); - if (ssh_options_set(options, SSH_OPTIONS_SERVER_BINDPORT, &i) < 0) { - cont = 0; - } - } - ssh_options_set(options, SSH_OPTIONS_PORT_STR, port); ssh_options_set(options, SSH_OPTIONS_SSH1, &ssh1); @@ -1261,31 +938,6 @@ int ssh_options_getopt(ssh_options options, int *argcptr, char **argv) { #endif } -/** - * @brief Set the authentication callback. - * - * @param opt The options structure to use. - * - * @param cb The callback function to use. - * - * @param userdata A pointer to some user data you can pass to the - * callback. - * - * @return 0 on success, < 0 on error. - */ -int ssh_options_set_auth_callback(ssh_options opt, ssh_auth_callback cb, - void *userdata) { - if (opt == NULL || cb == NULL || opt->callbacks==NULL) { - return -1; - } - - opt->callbacks->auth_function = cb; - if(userdata != NULL) - opt->callbacks->userdata = userdata; - - return 0; -} - /** * @brief Parse the ssh config file. * diff --git a/libssh/server.c b/libssh/server.c index 703a24f2..7821faac 100644 --- a/libssh/server.c +++ b/libssh/server.c @@ -74,7 +74,7 @@ static char *hstrerror(int h_errno_val) { #endif /* _WIN32 */ /* TODO FIXME: must use getaddrinfo */ -static socket_t bind_socket(SSH_BIND *ssh_bind, const char *hostname, +static socket_t bind_socket(SSH_BIND *sshbind, const char *hostname, int port) { struct sockaddr_in myaddr; struct hostent *hp=NULL; @@ -83,7 +83,7 @@ static socket_t bind_socket(SSH_BIND *ssh_bind, const char *hostname, s = socket(PF_INET, SOCK_STREAM, 0); if (s < 0) { - ssh_set_error(ssh_bind, SSH_FATAL, "%s", strerror(errno)); + ssh_set_error(sshbind, SSH_FATAL, "%s", strerror(errno)); return -1; } @@ -92,7 +92,7 @@ static socket_t bind_socket(SSH_BIND *ssh_bind, const char *hostname, #endif if (hp == NULL) { - ssh_set_error(ssh_bind, SSH_FATAL, + ssh_set_error(sshbind, SSH_FATAL, "Resolving %s: %s", hostname, hstrerror(h_errno)); close(s); return -1; @@ -104,14 +104,14 @@ static socket_t bind_socket(SSH_BIND *ssh_bind, const char *hostname, myaddr.sin_port = htons(port); if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) { - ssh_set_error(ssh_bind, SSH_FATAL, + ssh_set_error(sshbind, SSH_FATAL, "Setting socket options failed: %s", hstrerror(h_errno)); close(s); return -1; } if (bind(s, (struct sockaddr *) &myaddr, sizeof(myaddr)) < 0) { - ssh_set_error(ssh_bind, SSH_FATAL, "Binding to %s:%d: %s", + ssh_set_error(sshbind, SSH_FATAL, "Binding to %s:%d: %s", hostname, port, strerror(errno)); @@ -135,35 +135,27 @@ SSH_BIND *ssh_bind_new(void) { return ptr; } -void ssh_bind_set_options(SSH_BIND *ssh_bind, ssh_options options) { - ssh_bind->options = options; -} - -int ssh_bind_listen(SSH_BIND *ssh_bind) { +int ssh_bind_listen(SSH_BIND *sshbind) { const char *host; int fd; - if (ssh_bind->options == NULL) { - return -1; - } - if (ssh_init() < 0) { return -1; } - host = ssh_bind->options->bindaddr; + host = sshbind->bindaddr; if (host == NULL) { host = "0.0.0.0"; } - fd = bind_socket(ssh_bind, host, ssh_bind->options->bindport); + fd = bind_socket(sshbind, host, sshbind->bindport); if (fd < 0) { return -1; } - ssh_bind->bindfd = fd; + sshbind->bindfd = fd; if (listen(fd, 10) < 0) { - ssh_set_error(ssh_bind, SSH_FATAL, + ssh_set_error(sshbind, SSH_FATAL, "Listening to socket %d: %s", fd, strerror(errno)); close(fd); @@ -173,58 +165,59 @@ int ssh_bind_listen(SSH_BIND *ssh_bind) { return 0; } -void ssh_bind_set_blocking(SSH_BIND *ssh_bind, int blocking) { - ssh_bind->blocking = blocking ? 1 : 0; +void ssh_bind_set_blocking(SSH_BIND *sshbind, int blocking) { + sshbind->blocking = blocking ? 1 : 0; } -socket_t ssh_bind_get_fd(SSH_BIND *ssh_bind) { - return ssh_bind->bindfd; +socket_t ssh_bind_get_fd(SSH_BIND *sshbind) { + return sshbind->bindfd; } -void ssh_bind_set_fd(SSH_BIND *ssh_bind, socket_t fd) { - ssh_bind->bindfd = fd; +void ssh_bind_set_fd(SSH_BIND *sshbind, socket_t fd) { + sshbind->bindfd = fd; } -void ssh_bind_fd_toaccept(SSH_BIND *ssh_bind) { - ssh_bind->toaccept = 1; +void ssh_bind_fd_toaccept(SSH_BIND *sshbind) { + sshbind->toaccept = 1; } -ssh_session ssh_bind_accept(SSH_BIND *ssh_bind) { +ssh_session ssh_bind_accept(SSH_BIND *sshbind) { ssh_session session; ssh_private_key dsa = NULL; ssh_private_key rsa = NULL; int fd = -1; + int i; - if (ssh_bind->bindfd < 0) { - ssh_set_error(ssh_bind, SSH_FATAL, + if (sshbind->bindfd < 0) { + ssh_set_error(sshbind, SSH_FATAL, "Can't accept new clients on a not bound socket."); return NULL; } - if (ssh_bind->options->dsakey == NULL || ssh_bind->options->rsakey == NULL) { - ssh_set_error(ssh_bind, SSH_FATAL, + if (sshbind->dsakey == NULL || sshbind->rsakey == NULL) { + ssh_set_error(sshbind, SSH_FATAL, "DSA or RSA host key file must be set before accept()"); return NULL; } - if (ssh_bind->options->dsakey) { - dsa = _privatekey_from_file(ssh_bind, ssh_bind->options->dsakey, TYPE_DSS); + if (sshbind->dsakey) { + dsa = _privatekey_from_file(sshbind, sshbind->dsakey, TYPE_DSS); if (dsa == NULL) { return NULL; } } - if (ssh_bind->options->rsakey) { - rsa = _privatekey_from_file(ssh_bind, ssh_bind->options->rsakey, TYPE_RSA); + if (sshbind->rsakey) { + rsa = _privatekey_from_file(sshbind, sshbind->rsakey, TYPE_RSA); if (rsa == NULL) { privatekey_free(dsa); return NULL; } } - fd = accept(ssh_bind->bindfd, NULL, NULL); + fd = accept(sshbind->bindfd, NULL, NULL); if (fd < 0) { - ssh_set_error(ssh_bind, SSH_FATAL, + ssh_set_error(sshbind, SSH_FATAL, "Accepting a new connection: %s", strerror(errno)); privatekey_free(dsa); @@ -234,16 +227,33 @@ ssh_session ssh_bind_accept(SSH_BIND *ssh_bind) { session = ssh_new(); if (session == NULL) { - ssh_set_error(ssh_bind, SSH_FATAL, "Not enough space"); + ssh_set_error(sshbind, SSH_FATAL, "Not enough space"); privatekey_free(dsa); privatekey_free(rsa); return NULL; } session->server = 1; session->version = 2; - session->options = ssh_options_copy(ssh_bind->options); - if (session->options == NULL) { - ssh_set_error(ssh_bind, SSH_FATAL, "No space left"); + + /* TODO: is wanted methods enough? */ +#if 0 + session->options = ssh_options_copy(sshbind->options); +#endif + /* copy options */ + for (i = 0; i < 10; ++i) { + if (sshbind->wanted_methods[i]) { + session->wanted_methods[i] = strdup(sshbind->wanted_methods[i]); + if (session->wanted_methods[i] == NULL) { + privatekey_free(dsa); + privatekey_free(rsa); + ssh_cleanup(session); + return NULL; + } + } + } + + session->bindaddr = strdup(sshbind->bindaddr); + if (session->bindaddr == NULL) { privatekey_free(dsa); privatekey_free(rsa); ssh_cleanup(session); @@ -258,33 +268,44 @@ ssh_session ssh_bind_accept(SSH_BIND *ssh_bind) { ssh_cleanup(session); return NULL; } - ssh_socket_set_fd(session->socket,fd); + ssh_socket_set_fd(session->socket, fd); session->dsa_key = dsa; session->rsa_key = rsa; return session; } -void ssh_bind_free(SSH_BIND *ssh_bind){ - if (ssh_bind == NULL) { +void ssh_bind_free(SSH_BIND *sshbind){ + int i; + + if (sshbind == NULL) { return; } - if (ssh_bind->bindfd >= 0) { - close(ssh_bind->bindfd); + if (sshbind->bindfd >= 0) { + close(sshbind->bindfd); } - ssh_bind->bindfd = -1; - if (ssh_bind->options) { - ssh_options_free(ssh_bind->options); + sshbind->bindfd = -1; + + /* options */ + SAFE_FREE(sshbind->banner); + SAFE_FREE(sshbind->dsakey); + SAFE_FREE(sshbind->rsakey); + SAFE_FREE(sshbind->bindaddr); + + for (i = 0; i < 10; i++) { + if (sshbind->wanted_methods[i]) { + SAFE_FREE(sshbind->wanted_methods[i]); + } } - SAFE_FREE(ssh_bind); + + SAFE_FREE(sshbind); } extern char *supported_methods[]; -static int server_set_kex(ssh_session session) { +static int server_set_kex(ssh_session session) { KEX *server = &session->server_kex; - ssh_options options = session->options; int i, j; char *wanted; @@ -292,16 +313,16 @@ static int server_set_kex(ssh_session session) { ssh_get_random(server->cookie, 16, 0); if (session->dsa_key != NULL && session->rsa_key != NULL) { - if (ssh_options_set(options, SSH_OPTIONS_SERVER_HOSTKEY, + if (ssh_bind_options_set(options, SSH_BIND_OPTIONS_HOSTKEY, "ssh-dss,ssh-rsa") < 0) { return -1; } } else if (session->dsa_key != NULL) { - if (ssh_options_set(options, SSH_OPTIONS_SERVER_HOSTKEY, "ssh-dss") < 0) { + if (ssh_bind_options_set(options, SSH_BIND_OPTIONS_HOSTKEY, "ssh-dss") < 0) { return -1; } } else { - if (ssh_options_set(options, SSH_OPTIONS_SERVER_HOSTKEY, "ssh-rsa") < 0) { + if (ssh_bind_options_set(options, SSH_BIND_OPTIONS_HOSTKEY, "ssh-rsa") < 0) { return -1; } } diff --git a/libssh/session.c b/libssh/session.c index 25245608..2ba628e0 100644 --- a/libssh/session.c +++ b/libssh/session.c @@ -27,12 +27,10 @@ #include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/server.h" -#include "libssh/callback.h" #include "libssh/socket.h" #include "libssh/agent.h" #include "libssh/packet.h" #include "libssh/session.h" -#include "libssh/options.h" #include "libssh/misc.h" #define FIRST_CHANNEL 42 // why not ? it helps to find bugs. @@ -60,17 +58,11 @@ ssh_session ssh_new(void) { goto err; } - session->maxchannel = FIRST_CHANNEL; session->socket = ssh_socket_new(session); if (session->socket == NULL) { goto err; } - session->alive = 0; - session->auth_methods = 0; - session->blocking = 1; - session->log_indent = 0; - session->out_buffer = buffer_new(); if (session->out_buffer == NULL) { goto err; @@ -81,6 +73,22 @@ ssh_session ssh_new(void) { goto err; } + session->alive = 0; + session->auth_methods = 0; + session->blocking = 1; + session->log_indent = 0; + session->maxchannel = FIRST_CHANNEL; + + /* options */ + session->port = 22; + session->fd = -1; + session->ssh2 = 1; +#ifdef WITH_SSH1 + session->ssh1 = 1; +#else + session->ssh1 = 0; +#endif + #ifndef _WIN32 session->agent = agent_new(session); if (session->agent == NULL) { @@ -142,12 +150,23 @@ void ssh_cleanup(ssh_session session) { } ssh_list_free(session->ssh_message_list); } - ssh_options_free(session->options); + + /* options */ + SAFE_FREE(session->username); + SAFE_FREE(session->host); + SAFE_FREE(session->identity); + SAFE_FREE(session->sshdir); + SAFE_FREE(session->knownhosts); + + for (i = 0; i < 10; i++) { + if (session->wanted_methods[i]) { + SAFE_FREE(session->wanted_methods[i]); + } + } /* burn connection, it could hang sensitive datas */ ZERO_STRUCTP(session); SAFE_FREE(session); - /* FIXME: leave_function(); ??? */ } /** \brief disconnect impolitely from remote host @@ -177,8 +196,7 @@ void ssh_set_options(ssh_session session, ssh_options options) { return; } - session->options = options; - session->log_verbosity = options->log_verbosity; + return; } /** \brief set the session in blocking/nonblocking mode diff --git a/sample.c b/sample.c index 38feea18..62cd8131 100644 --- a/sample.c +++ b/sample.c @@ -502,7 +502,6 @@ static int auth_kbdint(ssh_session session){ int main(int argc, char **argv){ ssh_session session; - ssh_options options; int auth=0; char *password; char *banner; @@ -512,30 +511,30 @@ int main(int argc, char **argv){ unsigned char *hash = NULL; int hlen; - options=ssh_options_new(); - if(ssh_options_getopt(options,&argc, argv)){ - fprintf(stderr,"error parsing command line :%s\n",ssh_get_error(options)); - usage(); + 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); signal(SIGTERM, do_exit); if (user) { - if (ssh_options_set(options, SSH_OPTIONS_USER, user) < 0) { - ssh_options_free(options); + if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) { + ssh_disconnect(session); return 1; } } - if (ssh_options_set(options, SSH_OPTIONS_HOST ,host) < 0) { - ssh_options_free(options); + if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0) { + ssh_disconnect(session); return 1; } - ssh_options_parse_config(options, NULL); + ssh_options_parse_config(session, NULL); - session=ssh_new(); - ssh_set_options(session,options); if(ssh_connect(session)){ fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session)); ssh_disconnect(session); From 149a2b4a18a70fd41aef9cdfdb4b7b277187a95f Mon Sep 17 00:00:00 2001 From: Aris Adamantiadis Date: Sat, 3 Oct 2009 23:06:26 +0200 Subject: [PATCH 07/15] Temporary server fixup for options structure delet server_set_kex needs to be rewritten --- libssh/server.c | 15 ++++++++++++--- samplesshd.c | 23 +++++++++++------------ 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/libssh/server.c b/libssh/server.c index 7821faac..2a8ba334 100644 --- a/libssh/server.c +++ b/libssh/server.c @@ -45,7 +45,6 @@ #include "libssh/socket.h" #include "libssh/channels.h" #include "libssh/session.h" -#include "libssh/options.h" #include "libssh/misc.h" #include "libssh/keys.h" #include "libssh/dh.h" @@ -303,6 +302,15 @@ void ssh_bind_free(SSH_BIND *sshbind){ } extern char *supported_methods[]; +/** @internal + * This functions sets the Key Exchange protocols to be accepted + * by the server. They depend on + * -What the user asked (via options) + * -What is available (keys) + * It should then accept the intersection of what the user asked + * and what is available, and return an error if nothing matches + * @bug To rewrite, it's broken !! + */ static int server_set_kex(ssh_session session) { KEX *server = &session->server_kex; @@ -311,7 +319,7 @@ static int server_set_kex(ssh_session session) { ZERO_STRUCTP(server); ssh_get_random(server->cookie, 16, 0); - +#if 0 if (session->dsa_key != NULL && session->rsa_key != NULL) { if (ssh_bind_options_set(options, SSH_BIND_OPTIONS_HOSTKEY, "ssh-dss,ssh-rsa") < 0) { @@ -326,6 +334,7 @@ static int server_set_kex(ssh_session session) { return -1; } } +#endif server->methods = malloc(10 * sizeof(char **)); if (server->methods == NULL) { @@ -333,7 +342,7 @@ static int server_set_kex(ssh_session session) { } for (i = 0; i < 10; i++) { - if ((wanted = options->wanted_methods[i]) == NULL) { + if ((wanted = session->wanted_methods[i]) == NULL) { wanted = supported_methods[i]; } server->methods[i] = strdup(wanted); diff --git a/samplesshd.c b/samplesshd.c index 9d6e3bb0..fa97fabf 100644 --- a/samplesshd.c +++ b/samplesshd.c @@ -40,29 +40,28 @@ static int auth_password(char *user, char *password){ } int main(int argc, char **argv){ - ssh_options options=ssh_options_new(); ssh_session session; - SSH_BIND *ssh_bind; + ssh_bind ssh_bind_o; ssh_message message; ssh_channel chan=0; ssh_buffer buf; int auth=0; int sftp=0; int i; - ssh_options_getopt(options, &argc, argv); - ssh_options_set(options, SSH_OPTIONS_SERVER_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key"); - ssh_options_set(options, SSH_OPTIONS_SERVER_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key"); + ssh_bind_o=ssh_bind_new(); +// ssh_options_getopt(options, &argc, argv); + ssh_bind_options_set(ssh_bind_o, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key"); + ssh_bind_options_set(ssh_bind_o, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key"); - ssh_bind=ssh_bind_new(); - ssh_bind_set_options(ssh_bind,options); - if(ssh_bind_listen(ssh_bind)<0){ - printf("Error listening to socket: %s\n",ssh_get_error(ssh_bind)); +// ssh_bind_set_options(ssh_bind_o,options); + if(ssh_bind_listen(ssh_bind_o)<0){ + printf("Error listening to socket: %s\n",ssh_get_error(ssh_bind_o)); return 1; } - session=ssh_bind_accept(ssh_bind); + session=ssh_bind_accept(ssh_bind_o); if(!session){ - printf("error accepting a connection : %s\n",ssh_get_error(ssh_bind)); + printf("error accepting a connection : %s\n",ssh_get_error(ssh_bind_o)); return 1; } printf("Socket connected: fd = %d\n", ssh_get_fd(session)); @@ -153,7 +152,7 @@ int main(int argc, char **argv){ } while (i>0); buffer_free(buf); ssh_disconnect(session); - ssh_bind_free(ssh_bind); + ssh_bind_free(ssh_bind_o); ssh_finalize(); return 0; } From 7a37f9faf788897ce7bf44a65f828d4980d19c77 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Sun, 4 Oct 2009 10:10:19 +0200 Subject: [PATCH 08/15] Fixed ssh_options_copy(). --- include/libssh/libssh.h | 2 +- libssh/options.c | 97 ++++++++++++++++------------------------- 2 files changed, 39 insertions(+), 60 deletions(-) diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h index f4cb55b4..e7948937 100644 --- a/include/libssh/libssh.h +++ b/include/libssh/libssh.h @@ -383,7 +383,7 @@ LIBSSH_API int ssh_message_type(ssh_message msg); LIBSSH_API int ssh_mkdir (const char *pathname, mode_t mode); LIBSSH_API ssh_session ssh_new(void); -LIBSSH_API ssh_options ssh_options_copy(ssh_options opt); +LIBSSH_API int ssh_options_copy(ssh_session src, ssh_session *dest); LIBSSH_API int ssh_options_getopt(ssh_options options, int *argcptr, char **argv); LIBSSH_API int ssh_options_parse_config(ssh_options opt, const char *filename); LIBSSH_API int ssh_options_set(ssh_session session, enum ssh_options_e type, diff --git a/libssh/options.c b/libssh/options.c index 475cba0f..591aaeed 100644 --- a/libssh/options.c +++ b/libssh/options.c @@ -40,7 +40,7 @@ #endif /** - * @brief Duplicate an option structure. + * @brief Duplicate the options of a session structure. * * If you make several sessions with the same options this is useful. You * cannot use twice the same option structure in ssh_session_connect. @@ -51,92 +51,71 @@ * * @see ssh_session_connect() */ -#if 0 -ssh_session ssh_session_copy(ssh_options opt) { - ssh_session new = NULL; +int ssh_options_copy(ssh_session src, ssh_session *dest) { + ssh_session new; int i; - if (session == NULL) { - return NULL; + if (src == NULL || dest == NULL || *dest == NULL) { + return -1; } - new = ssh_session_new(); - if (new == NULL) { - return NULL; - } + new = *dest; - if (session->username) { - new->username = strdup(session->username); + if (src->username) { + new->username = strdup(src->username); if (new->username == NULL) { - goto err; + return -1; } } - if (session->host) { - new->host = strdup(session->host); + + if (src->host) { + new->host = strdup(src->host); if (new->host == NULL) { - goto err; + return -1; } } - if (session->bindaddr) { - new->bindaddr = strdup(session->bindaddr); - if (new->bindaddr == NULL) { - goto err; - } - } - if (session->identity) { - new->identity=strdup(session->identity); + + if (src->identity) { + new->identity = strdup(src->identity); if (new->identity == NULL) { - return NULL; + return -1; } } - if (session->sshdir) { - new->ssh_dir = strdup(session->sshdir); + + if (src->sshdir) { + new->sshdir = strdup(src->sshdir); if (new->sshdir == NULL) { - goto err; + return -1; } } - if (session->knownhosts) { - new->knownhosts = strdup(session->knownhosts); + + if (src->knownhosts) { + new->knownhosts = strdup(src->knownhosts); if (new->knownhosts == NULL) { - goto err; - } - } - if (session->dsakey) { - new->dsakey = strdup(session->dsakey); - if (new->dsakey == NULL) { - goto err; - } - } - if (session->rsakey) { - new->rsakey = strdup(session->rsakey); - if (new->rsakey == NULL) { - goto err; + return -1; } } + for (i = 0; i < 10; ++i) { - if (session->wanted_methods[i]) { - new->wanted_methods[i] = strdup(session->wanted_methods[i]); + if (src->wanted_methods[i]) { + new->wanted_methods[i] = strdup(src->wanted_methods[i]); if (new->wanted_methods[i] == NULL) { - goto err; + return -1; } } } - new->fd = session->fd; - new->port = session->port; - new->callbacks = session->callbacks; - new->timeout = session->timeout; - new->timeout_usec = session->timeout_usec; - new->ssh2 = session->ssh2; - new->ssh1 = session->ssh1; - new->log_verbosity = session->log_verbosity; + new->fd = src->fd; + new->port = src->port; + new->callbacks = src->callbacks; + new->timeout = src->timeout; + new->timeout_usec = src->timeout_usec; + new->ssh2 = src->ssh2; + new->ssh1 = src->ssh1; + new->log_verbosity = src->log_verbosity; - return new; -err: - ssh_session_free(new); - return NULL; + return 0; } -#endif #ifndef _WIN32 static char *get_username_from_uid(ssh_session session, uid_t uid){ From d7c0270c89777e2ad74ad11a1bac4c0d06d2a940 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Sun, 4 Oct 2009 11:47:26 +0200 Subject: [PATCH 09/15] Fixed SSHv1 to work with the option changes. --- libssh/auth1.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libssh/auth1.c b/libssh/auth1.c index 36db5b1d..c3d5b3f4 100644 --- a/libssh/auth1.c +++ b/libssh/auth1.c @@ -21,6 +21,8 @@ * MA 02111-1307, USA. */ +#include "config.h" + #include #include @@ -30,7 +32,6 @@ #include "libssh/packet.h" #include "libssh/session.h" #include "libssh/string.h" -#include "libssh/options.h" #ifdef WITH_SSH1 static int wait_auth1_status(ssh_session session) { @@ -64,11 +65,11 @@ static int send_username(ssh_session session, const char *username) { } if (!username) { - if(!(username = session->options->username)) { - if (ssh_options_set(session->options, SSH_OPTIONS_USER, NULL) < 0) { + if(!(username = session->username)) { + if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { return session->auth_service_asked = SSH_AUTH_ERROR; } else { - username = session->options->username; + username = session->username; } } } From d54e9550da59465d9a795c885e18199122b57ba5 Mon Sep 17 00:00:00 2001 From: "Bernhard R. Link" Date: Sun, 4 Oct 2009 13:59:03 +0200 Subject: [PATCH 10/15] proper prototype of ssh_session_new Signed-off-by: Andreas Schneider --- include/libssh/priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/libssh/priv.h b/include/libssh/priv.h index 8dbf9a3f..5dc3889d 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -134,7 +134,7 @@ int packet_hmac_verify(ssh_session session,ssh_buffer buffer,unsigned char *mac) /* connect.c */ int ssh_regex_init(void); void ssh_regex_finalize(void); -ssh_session ssh_session_new(); +ssh_session ssh_session_new(void); socket_t ssh_connect_host(ssh_session session, const char *host,const char *bind_addr, int port, long timeout, long usec); From 7c759b961521ecae451b113eaa7531f9c77b0079 Mon Sep 17 00:00:00 2001 From: "Bernhard R. Link" Date: Sun, 4 Oct 2009 14:03:25 +0200 Subject: [PATCH 11/15] add ssh_set_error_oom and ssh_set_error_invalid Signed-off-by: Andreas Schneider --- include/libssh/priv.h | 2 ++ libssh/error.c | 31 ++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/include/libssh/priv.h b/include/libssh/priv.h index 5dc3889d..bea4c343 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -123,6 +123,8 @@ int ssh_config_parse_file(ssh_options opt, const char *filename); /* errors.c */ void ssh_set_error(void *error, int code, const char *descr, ...) PRINTF_ATTRIBUTE(3, 4); +void ssh_set_error_oom(void *); +void ssh_set_error_invalid(void *, const char *); /* in crypt.c */ uint32_t packet_decrypt_len(ssh_session session,char *crypted); diff --git a/libssh/error.c b/libssh/error.c index 392e7414..f44bf492 100644 --- a/libssh/error.c +++ b/libssh/error.c @@ -41,7 +41,7 @@ * * @brief Registers an error with a description. * - * @param error The class of error. + * @param error The place to store the error. * * @param code The class of error. * @@ -58,6 +58,35 @@ void ssh_set_error(void *error, int code, const char *descr, ...) { err->error_code = code; } +/** + * @internal + * + * @brief Registers an out of memory error + * + * @param error The place to store the error. + * + */ +void ssh_set_error_oom(void *error) { + struct error_struct *err = error; + + strcpy(err->error_buffer, "Out of memory"); + err->error_code = SSH_FATAL; +} + +/** + * @internal + * + * @brief Registers an out of memory error + * + * @param error The place to store the error. + * + * @param function The function the error happened in. + * + */ +void ssh_set_error_invalid(void *error, const char *function) { + ssh_set_error(error, SSH_FATAL, "Invalid argument in %s", function); +} + /** * @brief Retrieve the error text message from the last error. * From f1f17f18dc26e4ca79de73f2000c7d4c1235bce6 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 5 Oct 2009 00:03:47 +0200 Subject: [PATCH 12/15] Fix documentation. --- libssh/error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libssh/error.c b/libssh/error.c index f44bf492..aa373e38 100644 --- a/libssh/error.c +++ b/libssh/error.c @@ -76,7 +76,7 @@ void ssh_set_error_oom(void *error) { /** * @internal * - * @brief Registers an out of memory error + * @brief Registers an invalid argument error * * @param error The place to store the error. * From ff52e3630f8cbe37ea93962d4bd104c581b33655 Mon Sep 17 00:00:00 2001 From: "Bernhard R. Link" Date: Sun, 4 Oct 2009 14:19:19 +0200 Subject: [PATCH 13/15] improve error handling in options.c Signed-off-by: Andreas Schneider --- libssh/options.c | 94 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 13 deletions(-) diff --git a/libssh/options.c b/libssh/options.c index 591aaeed..09b32371 100644 --- a/libssh/options.c +++ b/libssh/options.c @@ -120,6 +120,7 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) { #ifndef _WIN32 static char *get_username_from_uid(ssh_session session, uid_t uid){ struct passwd *pwd = NULL; + char *name; pwd = getpwuid(uid); @@ -128,7 +129,14 @@ static char *get_username_from_uid(ssh_session session, uid_t uid){ return NULL; } - return strdup(pwd->pw_name); + name = strdup(pwd->pw_name); + + if (name == NULL) { + ssh_set_error_oom(session); + return NULL; + } + + return name; } #endif @@ -144,6 +152,7 @@ static int ssh_options_set_algo(ssh_session session, int algo, SAFE_FREE(session->wanted_methods[algo]); session->wanted_methods[algo] = strdup(list); if (session->wanted_methods[algo] == NULL) { + ssh_set_error_oom(session); return -1; } @@ -158,8 +167,10 @@ static char *dir_expand_dup(ssh_session session, const char *value, int allowssh size_t lv = strlen(value + 1), lh = strlen(homedir); new = malloc(lv + lh + 1); - if (new == NULL) + if (new == NULL) { + ssh_set_error_oom(session); return NULL; + } memcpy(new, homedir, lh); memcpy(new + lh, value + 1, lv + 1); return new; @@ -176,13 +187,20 @@ static char *dir_expand_dup(ssh_session session, const char *value, int allowssh ls = strlen(session->sshdir); new = malloc(lv + ls + 1); - if (new == NULL) + if (new == NULL) { + ssh_set_error_oom(session); return NULL; + } memcpy(new, session->sshdir, ls); memcpy(new + ls, value, lv + 1); return new; } - return strdup(value); + new = strdup(value); + if (new == NULL) { + ssh_set_error_oom(session); + return NULL; + } + return new; } /** @@ -350,6 +368,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, case SSH_OPTIONS_HOST: q = strdup(value); if (q == NULL) { + ssh_set_error_oom(session); return -1; } p = strchr(q, '@'); @@ -361,6 +380,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, session->host = strdup(p + 1); if (session->host == NULL) { SAFE_FREE(q); + ssh_set_error_oom(session); return -1; } @@ -368,6 +388,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, session->username = strdup(q); SAFE_FREE(q); if (session->username == NULL) { + ssh_set_error_oom(session); return -1; } } else { @@ -389,6 +410,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, } else { q = strdup(value); if (q == NULL) { + ssh_set_error_oom(session); return -1; } i = strtol(q, &p, 10); @@ -408,6 +430,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, GetUserName(NULL, &size); //Get Size q = malloc(size); if (q == NULL) { + ssh_set_error_oom(session); return -1; } if (GetUserName(q, &size)) { @@ -426,6 +449,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, } else { /* username provided */ session->username = strdup(value); if (session->username == NULL) { + ssh_set_error_oom(session); return -1; } } @@ -450,6 +474,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, case SSH_OPTIONS_IDENTITY: if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); return -1; } SAFE_FREE(session->identity); @@ -476,6 +501,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, break; case SSH_OPTIONS_TIMEOUT: if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); return -1; } else { long *x = (long *) value; @@ -485,6 +511,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, break; case SSH_OPTIONS_TIMEOUT_USEC: if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); return -1; } else { long *x = (long *) value; @@ -494,6 +521,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, break; case SSH_OPTIONS_SSH1: if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); return -1; } else { int *x = (int *) value; @@ -502,6 +530,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, break; case SSH_OPTIONS_SSH2: if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); return -1; } else { int *x = (int *) value; @@ -510,6 +539,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, break; case SSH_OPTIONS_LOG_VERBOSITY: if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); return -1; } else { int *x = (int *) value; @@ -518,30 +548,38 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, } case SSH_OPTIONS_CIPHERS_C_S: if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); return -1; } else { - ssh_options_set_algo(session, SSH_CRYPT_C_S, value); + if (ssh_options_set_algo(session, SSH_CRYPT_C_S, value) < 0) + return -1; } break; case SSH_OPTIONS_CIPHERS_S_C: if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); return -1; } else { - ssh_options_set_algo(session, SSH_CRYPT_S_C, value); + if (ssh_options_set_algo(session, SSH_CRYPT_S_C, value) < 0) + return -1; } break; case SSH_OPTIONS_COMPRESSION_C_S: if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); return -1; } else { - ssh_options_set_algo(session, SSH_COMP_C_S, value); + if (ssh_options_set_algo(session, SSH_COMP_C_S, value) < 0) + return -1; } break; case SSH_OPTIONS_COMPRESSION_S_C: if (value == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); return -1; } else { - ssh_options_set_algo(session, SSH_COMP_S_C, value); + if (ssh_options_set_algo(session, SSH_COMP_S_C, value) < 0) + return -1; } break; default: @@ -566,6 +604,7 @@ static int ssh_bind_options_set_algo(ssh_bind sshbind, int algo, SAFE_FREE(sshbind->wanted_methods[algo]); sshbind->wanted_methods[algo] = strdup(list); if (sshbind->wanted_methods[algo] == NULL) { + ssh_set_error_oom(sshbind); return -1; } @@ -586,23 +625,28 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type, switch (type) { case SSH_BIND_OPTIONS_HOSTKEY: if (value == NULL) { + ssh_set_error_invalid(sshbind, __FUNCTION__); return -1; } else { - ssh_bind_options_set_algo(sshbind, SSH_HOSTKEYS, value); + if (ssh_bind_options_set_algo(sshbind, SSH_HOSTKEYS, value) < 0) + return -1; } break; case SSH_BIND_OPTIONS_BINDADDR: if (value == NULL) { + ssh_set_error_invalid(sshbind, __FUNCTION__); return -1; } else { sshbind->bindaddr = strdup(value); if (sshbind->bindaddr == NULL) { + ssh_set_error_oom(sshbind); return -1; } } break; case SSH_BIND_OPTIONS_BINDPORT: if (value == NULL) { + ssh_set_error_invalid(sshbind, __FUNCTION__); return -1; } else { int *x = (int *) value; @@ -611,30 +655,36 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type, break; case SSH_BIND_OPTIONS_DSAKEY: if (value == NULL) { + ssh_set_error_invalid(sshbind, __FUNCTION__); return -1; } else { sshbind->dsakey = strdup(value); if (sshbind->dsakey == NULL) { + ssh_set_error_oom(sshbind); return -1; } } break; case SSH_BIND_OPTIONS_RSAKEY: if (value == NULL) { + ssh_set_error_invalid(sshbind, __FUNCTION__); return -1; } else { sshbind->rsakey = strdup(value); if (sshbind->rsakey == NULL) { + ssh_set_error_oom(sshbind); return -1; } } break; case SSH_BIND_OPTIONS_BANNER: if (value == NULL) { + ssh_set_error_invalid(sshbind, __FUNCTION__); return -1; } else { sshbind->banner = strdup(value); if (sshbind->banner == NULL) { + ssh_set_error_oom(sshbind); return -1; } } @@ -669,7 +719,11 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type, */ int ssh_set_status_callback(ssh_session session, void (*callback)(void *arg, float status), void *arg) { - if (session == NULL || callback == NULL || session->callbacks == NULL) { + if (session == NULL) { + return -1; + } + if (callback == NULL || session->callbacks == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); return -1; } @@ -697,7 +751,11 @@ int ssh_set_status_callback(ssh_session session, */ int ssh_set_log_callback(ssh_session session, ssh_log_callback cb, void *userdata) { - if (session == NULL || cb == NULL || session->callbacks == NULL) { + if (session == NULL) { + return -1; + } + if (cb == NULL || session->callbacks == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); return -1; } @@ -722,7 +780,11 @@ int ssh_set_log_callback(ssh_session session, ssh_log_callback cb, */ int ssh_set_auth_callback(ssh_session session, ssh_auth_callback cb, void *userdata) { - if (session == NULL || cb == NULL || session->callbacks == NULL) { + if (session == NULL) { + return -1; + } + if (cb == NULL || session->callbacks == NULL) { + ssh_set_error_invalid(session, __FUNCTION__); return -1; } @@ -785,6 +847,7 @@ int ssh_options_getopt(ssh_options options, int *argcptr, char **argv) { save = malloc(argc * sizeof(char *)); if (save == NULL) { + ssh_set_error_oom(options); return -1; } @@ -836,6 +899,7 @@ int ssh_options_getopt(ssh_options options, int *argcptr, char **argv) { save[current] = strdup(opt); if (save[current] == NULL) { SAFE_FREE(save); + ssh_set_error_oom(options); return -1; } current++; @@ -937,7 +1001,11 @@ int ssh_options_parse_config(ssh_options opt, const char *filename) { char *expanded_filename; int r; - if (opt == NULL || opt->host == NULL) { + if (opt == NULL) { + return -1; + } + if (opt->host == NULL) { + ssh_set_error_invalid(opt, __FUNCTION__); return -1; } From bf376b6d4fd4dad7ced0e49bedc76cc2a0d797f1 Mon Sep 17 00:00:00 2001 From: "Bernhard R. Link" Date: Sun, 4 Oct 2009 14:23:50 +0200 Subject: [PATCH 14/15] do not segfault in ssh_bind_accept if bindaddr is NULL Signed-off-by: Andreas Schneider --- libssh/server.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/libssh/server.c b/libssh/server.c index 2a8ba334..96acb5b0 100644 --- a/libssh/server.c +++ b/libssh/server.c @@ -251,12 +251,16 @@ ssh_session ssh_bind_accept(SSH_BIND *sshbind) { } } - session->bindaddr = strdup(sshbind->bindaddr); - if (session->bindaddr == NULL) { - privatekey_free(dsa); - privatekey_free(rsa); - ssh_cleanup(session); - return NULL; + if (sshbind->bindaddr == NULL) + session->bindaddr = NULL; + else { + session->bindaddr = strdup(sshbind->bindaddr); + if (session->bindaddr == NULL) { + privatekey_free(dsa); + privatekey_free(rsa); + ssh_cleanup(session); + return NULL; + } } ssh_socket_free(session->socket); From 60d6954b7560df62634b305fec65dffbc98ff0b8 Mon Sep 17 00:00:00 2001 From: "Bernhard R. Link" Date: Sun, 4 Oct 2009 14:25:05 +0200 Subject: [PATCH 15/15] samplesshd: allow overriding KEYS_FOLDER by compiler option Signed-off-by: Andreas Schneider --- samplesshd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/samplesshd.c b/samplesshd.c index fa97fabf..9cd9449b 100644 --- a/samplesshd.c +++ b/samplesshd.c @@ -25,11 +25,13 @@ MA 02111-1307, USA. */ #include #include #include +#ifndef KEYS_FOLDER #ifdef _WIN32 #define KEYS_FOLDER #else #define KEYS_FOLDER "/etc/ssh/" #endif +#endif static int auth_password(char *user, char *password){ if(strcmp(user,"aris"))