From 0f67ff89d9918344965897887ca47c9bb7471752 Mon Sep 17 00:00:00 2001 From: Aris Adamantiadis Date: Wed, 26 Oct 2005 12:06:11 +0000 Subject: patches from Norbert merged in. I have made some little changes here and there. It still doesn't compile because of the O1 thing passed to ld. git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@41 7dcaeef0-15fb-0310-b436-a5af3365683c --- configure | 267 ++++++++++++++++++++++++++++++++++++++++++------ configure.in | 9 +- include/libssh/libssh.h | 5 +- libssh/auth.c | 12 +++ libssh/auth1.c | 4 +- libssh/channels.c | 6 +- libssh/connect.c | 118 +++++++++++---------- libssh/libssh.vers | 4 +- libssh/session.c | 3 + sftp_server/protocol.c | 1 + 10 files changed, 328 insertions(+), 101 deletions(-) diff --git a/configure b/configure index d26bfb46..598ab082 100755 --- a/configure +++ b/configure @@ -1040,6 +1040,7 @@ Optional Packages: both] --with-tags[=TAGS] include additional configurations [automatic] + --with-libgcypt Use libgcrypt instead of libcrypto Some influential environment variables: CC C compiler command @@ -3244,7 +3245,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 3247 "configure"' > conftest.$ac_ext + echo '#line 3248 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -4714,7 +4715,7 @@ fi # Provide some information about the compiler. -echo "$as_me:4717:" \ +echo "$as_me:4718:" \ "checking for Fortran 77 compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 @@ -5812,11 +5813,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:5815: $lt_compile\"" >&5) + (eval echo "\"\$as_me:5816: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:5819: \$? = $ac_status" >&5 + echo "$as_me:5820: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -6074,11 +6075,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:6077: $lt_compile\"" >&5) + (eval echo "\"\$as_me:6078: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:6081: \$? = $ac_status" >&5 + echo "$as_me:6082: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -6136,11 +6137,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:6139: $lt_compile\"" >&5) + (eval echo "\"\$as_me:6140: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:6143: \$? = $ac_status" >&5 + echo "$as_me:6144: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -8397,7 +8398,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5) + (eval echo "\"\$as_me:10754: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:10757: \$? = $ac_status" >&5 + echo "$as_me:10758: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -10812,11 +10813,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:10815: $lt_compile\"" >&5) + (eval echo "\"\$as_me:10816: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:10819: \$? = $ac_status" >&5 + echo "$as_me:10820: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -12204,7 +12205,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5) + (eval echo "\"\$as_me:13191: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:13194: \$? = $ac_status" >&5 + echo "$as_me:13195: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -13249,11 +13250,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13252: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13253: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:13256: \$? = $ac_status" >&5 + echo "$as_me:13257: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -15392,11 +15393,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15395: $lt_compile\"" >&5) + (eval echo "\"\$as_me:15396: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:15399: \$? = $ac_status" >&5 + echo "$as_me:15400: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -15654,11 +15655,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15657: $lt_compile\"" >&5) + (eval echo "\"\$as_me:15658: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:15661: \$? = $ac_status" >&5 + echo "$as_me:15662: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -15716,11 +15717,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15719: $lt_compile\"" >&5) + (eval echo "\"\$as_me:15720: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:15723: \$? = $ac_status" >&5 + echo "$as_me:15724: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -17977,7 +17978,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5 +echo $ECHO_N "checking for gcry_md_open in -lgcrypt... $ECHO_C" >&6 +if test "${ac_cv_lib_gcrypt_gcry_md_open+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcrypt $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gcry_md_open (); +int +main () +{ +gcry_md_open (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcrypt_gcry_md_open=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_gcrypt_gcry_md_open=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_gcrypt_gcry_md_open" >&5 +echo "${ECHO_T}$ac_cv_lib_gcrypt_gcry_md_open" >&6 +if test $ac_cv_lib_gcrypt_gcry_md_open = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGCRYPT 1 +_ACEOF + + LIBS="-lgcrypt $LIBS" + +fi + +fi; + if test "$ac_cv_lib_gcrypt_gcry_md_open" != yes; then echo "$as_me:$LINENO: checking for BN_init in -lcrypto" >&5 @@ -19507,7 +19588,7 @@ _ACEOF fi fi -#AC_CHECK_LIB([crypto],[BN_init]) + echo "$as_me:$LINENO: checking for deflateInit_ in -lz" >&5 echo $ECHO_N "checking for deflateInit_ in -lz... $ECHO_C" >&6 @@ -19708,6 +19789,132 @@ if test "$ac_cv_search_hstrerror" != no; then fi +echo "$as_me:$LINENO: checking for library containing getaddrinfo" >&5 +echo $ECHO_N "checking for library containing getaddrinfo... $ECHO_C" >&6 +if test "${ac_cv_search_getaddrinfo+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_getaddrinfo=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getaddrinfo (); +int +main () +{ +getaddrinfo (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_getaddrinfo="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_getaddrinfo" = no; then + for ac_lib in nsl resolv; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getaddrinfo (); +int +main () +{ +getaddrinfo (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_getaddrinfo="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_getaddrinfo" >&5 +echo "${ECHO_T}$ac_cv_search_getaddrinfo" >&6 +if test "$ac_cv_search_getaddrinfo" != no; then + test "$ac_cv_search_getaddrinfo" = "none required" || LIBS="$ac_cv_search_getaddrinfo $LIBS" + +fi + echo "$as_me:$LINENO: checking for library containing gethostbyname" >&5 echo $ECHO_N "checking for library containing gethostbyname... $ECHO_C" >&6 if test "${ac_cv_search_gethostbyname+set}" = set; then @@ -21433,7 +21640,7 @@ done -for ac_func in endpwent gethostbyaddr gethostbyname getpass memmove memset \ +for ac_func in endpwent getaddrinfo gethostbyname getpass memmove memset \ cfmakeraw select socket strchr strdup strerror strstr poll do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` diff --git a/configure.in b/configure.in index e071c153..51b9a573 100644 --- a/configure.in +++ b/configure.in @@ -67,12 +67,17 @@ AC_C_BIGENDIAN # Checks for libraries. AC_CHECK_LIB([gcrypt], [gcry_md_open]) +AC_ARG_WITH([libgcrypt], + AC_HELP_STRING([--with-libgcypt],[Use libgcrypt instead of libcrypto]), + [AC_CHECK_LIB([gcrypt], [gcry_md_open])]) + if test "$ac_cv_lib_gcrypt_gcry_md_open" != yes; then AC_CHECK_LIB([crypto], [BN_init]) fi -#AC_CHECK_LIB([crypto],[BN_init]) + AC_CHECK_LIB([z], [deflateInit_]) AC_SEARCH_LIBS([hstrerror],[nsl resolv]) +AC_SEARCH_LIBS([getaddrinfo],[nsl resolv]) AC_SEARCH_LIBS([gethostbyname],[nsl resolv]) # Checks for header files. @@ -108,7 +113,7 @@ AC_FUNC_REALLOC AC_FUNC_SELECT_ARGTYPES AC_TYPE_SIGNAL AC_FUNC_VPRINTF -AC_CHECK_FUNCS([endpwent gethostbyaddr gethostbyname getpass memmove memset \ +AC_CHECK_FUNCS([endpwent getaddrinfo gethostbyname getpass memmove memset \ cfmakeraw select socket strchr strdup strerror strstr poll]) AC_CONFIG_FILES([Makefile diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h index 5f8765fe..ebfe41f1 100644 --- a/include/libssh/libssh.h +++ b/include/libssh/libssh.h @@ -22,9 +22,7 @@ MA 02111-1307, USA. */ #define _LIBSSH_H #include #include /* for fd_set * */ -#include - -#include +#include #define LIBSSH_VERSION "libssh-0.2-dev" @@ -110,6 +108,7 @@ SSH_SESSION *ssh_new(); void ssh_set_options(SSH_SESSION *session, SSH_OPTIONS *options); int ssh_get_fd(SSH_SESSION *session); void ssh_silent_disconnect(SSH_SESSION *session); +int ssh_get_version(SSH_SESSION *session); void ssh_set_fd_toread(SSH_SESSION *session); void ssh_set_fd_towrite(SSH_SESSION *session); void ssh_set_fd_except(SSH_SESSION *session); diff --git a/libssh/auth.c b/libssh/auth.c index 12b90bf4..8c7fb2db 100644 --- a/libssh/auth.c +++ b/libssh/auth.c @@ -311,11 +311,15 @@ int ssh_userauth_autopubkey(SSH_SESSION *session){ free(id); } free(pubkey); + free(privkeyfile); return err; } else if(err != SSH_AUTH_SUCCESS){ ssh_say(2,"Public key refused by server\n"); free(pubkey); + pubkey=NULL; + free(privkeyfile); + privkeyfile=NULL; continue; } /* pubkey accepted by server ! */ @@ -323,6 +327,9 @@ int ssh_userauth_autopubkey(SSH_SESSION *session){ if(!privkey){ ssh_say(0,"Reading private key %s failed (bad passphrase ?)\n",privkeyfile); free(pubkey); + pubkey=NULL; + free(privkeyfile); + privkeyfile=NULL; continue; /* continue the loop with other pubkey */ } err=ssh_userauth_pubkey(session,NULL,pubkey,privkey); @@ -333,12 +340,16 @@ int ssh_userauth_autopubkey(SSH_SESSION *session){ free(id); } free(pubkey); + free(privkeyfile); private_key_free(privkey); return err; } else if(err != SSH_AUTH_SUCCESS){ ssh_say(0,"Weird : server accepted our public key but refused the signature\nit might be a bug of libssh\n"); free(pubkey); + pubkey=NULL; + free(privkeyfile); + privkeyfile=NULL; private_key_free(privkey); continue; } @@ -354,6 +365,7 @@ int ssh_userauth_autopubkey(SSH_SESSION *session){ } return SSH_AUTH_SUCCESS; } + /* at this point, pubkey is NULL and so is privkeyfile */ ssh_say(1,"Tried every public key, none matched\n"); ssh_set_error(session,SSH_NO_ERROR,"no public key matched"); if(id){ diff --git a/libssh/auth1.c b/libssh/auth1.c index 40cccda1..415c42aa 100644 --- a/libssh/auth1.c +++ b/libssh/auth1.c @@ -176,7 +176,9 @@ int ssh_userauth1_password(SSH_SESSION *session,char *username,char *password){ * easy to guess password sizes. * not that sure ... */ - if(strlen(password)>=128){ + /* XXX fix me here ! */ + /* cisco IOS doesn't like when a password is followed by zeroes and random pad. */ + if(strlen(password)>=0){ /* not risky to disclose the size of such a big password .. */ password_s=string_from_char(password); } else { diff --git a/libssh/channels.c b/libssh/channels.c index a89d0034..a8f053c0 100644 --- a/libssh/channels.c +++ b/libssh/channels.c @@ -474,11 +474,11 @@ int channel_write(CHANNEL *channel ,void *data,int len){ } int channel_is_open(CHANNEL *channel){ - return (channel->open!=0); + return (channel->open!=0 && channel->session->alive); } int channel_is_closed(CHANNEL *channel){ - return (channel->open==0); + return (channel->open==0 || !channel->session->alive); } int channel_is_eof(CHANNEL *channel){ @@ -749,7 +749,7 @@ static int channel_protocol_select(CHANNEL **rchans, CHANNEL **wchans, CHANNEL * ++j; } } - wout[j]=NULL; + eout[j]=NULL; return 0; } diff --git a/libssh/connect.c b/libssh/connect.c index d1e8bf59..afe1dadf 100644 --- a/libssh/connect.c +++ b/libssh/connect.c @@ -22,6 +22,7 @@ MA 02111-1307, USA. */ #include #include +#include #include #include #include @@ -33,11 +34,6 @@ MA 02111-1307, USA. */ #include #include "libssh/priv.h" -#ifndef HAVE_GETHOSTBYNAME -#ifndef HAVE_GETHOSTBYADDR -#error "your system doesn't have gethostbyname nor gethostbyaddr" -#endif -#endif #ifndef HAVE_SELECT #error "Your system must have select()" #endif @@ -49,71 +45,67 @@ static void sock_set_blocking(int sock){ fcntl(sock,F_SETFL,0); } +static int getai(const char *host, int port, struct addrinfo **ai) +{ + struct addrinfo hints; + char *service=NULL; + char s_port[10]; + + memset(&hints,0,sizeof(hints)); + hints.ai_protocol=IPPROTO_TCP; + hints.ai_socktype=SOCK_STREAM; + if(port==0){ + hints.ai_flags=AI_PASSIVE; + } else { + snprintf(s_port,sizeof(s_port),"%hu",port); + service=s_port; + } + return getaddrinfo(host,service,&hints,ai); +} + /* connect_host connects to an IPv4 (or IPv6) host */ /* specified by its IP address or hostname. */ /* output is the file descriptor, <0 if failed. */ int ssh_connect_host(SSH_SESSION *session, const char *host, const char *bind_addr, int port,long timeout, long usec){ - struct sockaddr_in sa; - struct sockaddr_in bindsa; - struct hostent *hp=NULL; - static int count=0; /* for reentrencity */ int s; - while(++count>1) - --count; + int my_errno; + struct addrinfo *ai; -#ifdef HAVE_GETHOSTBYNAME - hp=gethostbyname(host); -#endif - if(!hp){ - --count; - ssh_set_error(session,SSH_FATAL,"Failed to resolve hostname %s (%s)",host,hstrerror(h_errno)); + my_errno=getai(host, port, &ai); + if (my_errno){ + ssh_set_error(session,SSH_FATAL,"Failed to resolve hostname %s (%d)",host,my_errno); return -1; } - memset(&sa,0,sizeof(sa)); - memcpy(&sa.sin_addr,hp->h_addr,hp->h_length); - sa.sin_family=hp->h_addrtype; - sa.sin_port=htons((unsigned short)port); - --count; - if(bind_addr){ - ssh_say(2,"resolving %s\n",bind_addr); - hp=NULL; - while(++count>1) - --count; -#ifdef HAVE_GETHOSTBYADDR - hp=gethostbyaddr(bind_addr,4,AF_INET); -#endif -#ifdef HAVE_GETHOSTBYNAME - if(!hp) - hp=gethostbyname(bind_addr); -#endif - if(!hp){ - --count; - ssh_set_error(session,SSH_FATAL,"Failed to resolve bind address %s (%s)",bind_addr,hstrerror(h_errno)); - return -1; - } - } - memset(&bindsa,0,sizeof(bindsa)); /* create socket */ - s=socket(sa.sin_family,SOCK_STREAM,0); + s=socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol); if(s<0){ - if(bind_addr) - --count; ssh_set_error(session,SSH_FATAL,"socket : %s",strerror(errno)); + freeaddrinfo(ai); return s; } if(bind_addr){ - memcpy(&bindsa.sin_addr,hp->h_addr,hp->h_length); - bindsa.sin_family=hp->h_addrtype; - --count; - if(bind(s,(struct sockaddr *)&bindsa,sizeof(bindsa))<0){ + struct addrinfo *bind_ai; + + ssh_say(2,"resolving %s\n",bind_addr); + my_errno=getai(host,0,&bind_ai); + if (my_errno){ + ssh_set_error(session,SSH_FATAL,"Failed to resolve bind address %s (%d)",bind_addr,my_errno); + freeaddrinfo(ai); + return -1; + } + + if(bind(s,bind_ai->ai_addr,bind_ai->ai_addrlen)<0){ ssh_set_error(session,SSH_FATAL,"Binding local address : %s",strerror(errno)); + freeaddrinfo(ai); + freeaddrinfo(bind_ai); close(s); return -1; } + freeaddrinfo(bind_ai); } if(timeout){ struct timeval to; @@ -123,7 +115,8 @@ int ssh_connect_host(SSH_SESSION *session, const char *host, const char to.tv_sec=timeout; to.tv_usec=usec; sock_set_nonblocking(s); - connect(s,(struct sockaddr* )&sa,sizeof(sa)); + connect(s,ai->ai_addr,ai->ai_addrlen); + freeaddrinfo(ai); FD_ZERO(&set); FD_SET(s,&set); ret=select(s+1,NULL,&set,NULL,&to); @@ -150,11 +143,12 @@ int ssh_connect_host(SSH_SESSION *session, const char *host, const char sock_set_blocking(s); return s; } - if(connect(s,(struct sockaddr *)&sa,sizeof(sa))< 0){ - close(s); + if(connect(s,ai->ai_addr,ai->ai_addrlen)<0){ ssh_set_error(session,SSH_FATAL,"connect: %s",strerror(errno)); - return -1; + close(s); + s=-1; } + freeaddrinfo(ai); return s; } @@ -220,13 +214,15 @@ int ssh_select(CHANNEL **channels,CHANNEL **outchannels, int maxfd, fd_set *read j=0; // polls every channel. for(i=0;channels[i];i++){ - if(channel_poll(channels[i],0)>0){ - outchannels[j]=channels[i]; - j++; - } else - if(channel_poll(channels[i],1)>0){ - outchannels[j]=channels[i]; - j++; + if(channels[i]->session->alive){ + if(channel_poll(channels[i],0)>0){ + outchannels[j]=channels[i]; + j++; + } else + if(channel_poll(channels[i],1)>0){ + outchannels[j]=channels[i]; + j++; + } } } outchannels[j]=NULL; @@ -261,13 +257,13 @@ int ssh_select(CHANNEL **channels,CHANNEL **outchannels, int maxfd, fd_set *read } /* set the data_to_read flag on each session */ for(i=0;channels[i];i++) - if(FD_ISSET(channels[i]->session->fd,&localset)) + if(channels[i]->session->alive && FD_ISSET(channels[i]->session->fd,&localset)) channels[i]->session->data_to_read=1; /* now, test each channel */ j=0; for(i=0;channels[i];i++){ - if(FD_ISSET(channels[i]->session->fd,&localset)) + if(channels[i]->session->alive && FD_ISSET(channels[i]->session->fd,&localset)) if((channel_poll(channels[i],0)>0) || (channel_poll(channels[i],1)>0)){ outchannels[j]=channels[i]; j++; diff --git a/libssh/libssh.vers b/libssh/libssh.vers index 3afc8ce9..a1bc8580 100644 --- a/libssh/libssh.vers +++ b/libssh/libssh.vers @@ -3,7 +3,8 @@ SSH_0.2 { ssh_get_error; ssh_get_error_code; ssh_say; ssh_set_verbosity; ssh_new; ssh_set_options; ssh_get_fd; ssh_silent_disconnect; ssh_connect; ssh_disconnect; ssh_service_request; ssh_get_issue_banner; - ssh_copyright; + ssh_copyright; ssh_get_version; + ssh_set_fd_toread; ssh_set_fd_towrite; ssh_set_fd_except; string_from_char; string_len; string_new; string_fill; string_to_char; string_copy; string_burn; string_data; ssh_crypto_init; @@ -19,6 +20,7 @@ SSH_0.2 { channel_request_exec; channel_request_sftp; channel_write; channel_send_eof; channel_read; channel_poll; channel_close; channel_read_nonblocking; channel_is_open; + channel_is_closed; channel_is_eof; channel_select; ssh_options_new; ssh_options_copy; ssh_options_set_wanted_algos; ssh_options_set_username; ssh_options_set_port; ssh_options_getopt; ssh_options_set_host; ssh_options_set_fd; ssh_options_set_bind; diff --git a/libssh/session.c b/libssh/session.c index b084c29d..0d75c5a7 100644 --- a/libssh/session.c +++ b/libssh/session.c @@ -138,3 +138,6 @@ const char *ssh_get_disconnect_message(SSH_SESSION *session){ return NULL; } +int ssh_get_version(SSH_SESSION *session){ + return session->version; +} diff --git a/sftp_server/protocol.c b/sftp_server/protocol.c index 306afed4..8ab16d93 100644 --- a/sftp_server/protocol.c +++ b/sftp_server/protocol.c @@ -33,6 +33,7 @@ MA 02111-1307, USA. */ #include #include #include +#include #include #include "server.h" -- cgit v1.2.3