mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-04 12:20:42 +09:00
Compare commits
83 Commits
ef50a3c0f0
...
release-0-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
914a2d8e41 | ||
|
|
956b64d348 | ||
|
|
91489cd378 | ||
|
|
615bc3b8f7 | ||
|
|
5b645419fd | ||
|
|
c436e07022 | ||
|
|
188fb37801 | ||
|
|
44fed3eb9b | ||
|
|
36abd82a7e | ||
|
|
fd6d0b6897 | ||
|
|
09b0018b93 | ||
|
|
2624e603d4 | ||
|
|
fd61eda16d | ||
|
|
a6dda5fefd | ||
|
|
da8356b477 | ||
|
|
e5fb20c17b | ||
|
|
c472bd7437 | ||
|
|
8796756ae5 | ||
|
|
9c8f285a98 | ||
|
|
8154e24027 | ||
|
|
629cfbccc4 | ||
|
|
c5990791db | ||
|
|
16241938af | ||
|
|
6a8cb38dd3 | ||
|
|
bac2227ee2 | ||
|
|
dcb50cc0c8 | ||
|
|
f503c4a3e1 | ||
|
|
a56c925da9 | ||
|
|
833cc00014 | ||
|
|
09e8cf33d7 | ||
|
|
a03bb2fbf7 | ||
|
|
bb784ec6be | ||
|
|
996c00c81c | ||
|
|
30bdca07e9 | ||
|
|
b4b49cf3f6 | ||
|
|
189796e94f | ||
|
|
2431c7d925 | ||
|
|
fc9c61714f | ||
|
|
e096658df3 | ||
|
|
b1d58c5454 | ||
|
|
ced66eb11f | ||
|
|
1b44daddf6 | ||
|
|
a309c1b38e | ||
|
|
e56aaf5f44 | ||
|
|
632cee4426 | ||
|
|
af25fc35d1 | ||
|
|
db49b84a44 | ||
|
|
c5f4b8c1c7 | ||
|
|
6a0daddd8f | ||
|
|
af997b221d | ||
|
|
9d6855702e | ||
|
|
daf256e15f | ||
|
|
0eddcb4424 | ||
|
|
b7f6794e03 | ||
|
|
cd9fc88151 | ||
|
|
fbe0f37e1b | ||
|
|
c496194614 | ||
|
|
ca639ceb63 | ||
|
|
e85537aac4 | ||
|
|
e839c9cae6 | ||
|
|
100e94c18e | ||
|
|
e7f7b4e499 | ||
|
|
eca8b53868 | ||
|
|
b8767be373 | ||
|
|
9658eade0b | ||
|
|
689536ec92 | ||
|
|
3ff2999228 | ||
|
|
4f65104ecc | ||
|
|
242e1c342c | ||
|
|
935e3b70ae | ||
|
|
8d1bfb5a85 | ||
|
|
2ac664968d | ||
|
|
1199ad8f47 | ||
|
|
c12559f8f6 | ||
|
|
840e1abcdc | ||
|
|
e3594ba0ec | ||
|
|
0d07dc5355 | ||
|
|
4170258595 | ||
|
|
dacfc41d21 | ||
|
|
5158877b72 | ||
|
|
a785ba3c4d | ||
|
|
92dbd4eca2 | ||
|
|
a7144c5b6b |
@@ -12,8 +12,8 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
|
||||
|
||||
### versions
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "4")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "90")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "5")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "0")
|
||||
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
ChangeLog
|
||||
==========
|
||||
|
||||
version 0.5.0 (released xxxx-xx-xx)
|
||||
version 0.5.0 (released 2011-06-01)
|
||||
* Added ssh_ prefix to all functions.
|
||||
* Added complete Windows support.
|
||||
* Added improved server support.
|
||||
@@ -10,6 +10,8 @@ version 0.5.0 (released xxxx-xx-xx)
|
||||
* Added a multiplatform ssh_getpass() function.
|
||||
* Added a tutorial.
|
||||
* Added a lot of documentation.
|
||||
* Fixed a lot of bugs.
|
||||
* Fixed several memory leaks.
|
||||
|
||||
version 0.4.8 (released 2011-01-15)
|
||||
* Fixed memory leaks in session signing.
|
||||
|
||||
@@ -43,7 +43,8 @@ endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
|
||||
# HEADER FILES
|
||||
check_include_file(argp.h HAVE_ARGP_H)
|
||||
check_include_file(pty.h HAVE_PTY_H)
|
||||
check_include_file(terminos.h HAVE_TERMIOS_H)
|
||||
check_include_file(termios.h HAVE_TERMIOS_H)
|
||||
|
||||
if (WIN32)
|
||||
check_include_file(wspiapi.h HAVE_WSPIAPI_H)
|
||||
if (NOT HAVE_WSPIAPI_H)
|
||||
@@ -91,18 +92,28 @@ if (UNIX)
|
||||
if (HAVE_LIBSOCKET)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
|
||||
endif (HAVE_LIBSOCKET)
|
||||
|
||||
# libresolv
|
||||
check_library_exists(resolv hstrerror "" HAVE_LIBRESOLV)
|
||||
if (HAVE_LIBRESOLV)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} resolv)
|
||||
endif (HAVE_LIBRESOLV)
|
||||
check_library_exists(rt nanosleep "" HAVE_LIBRT)
|
||||
|
||||
# libnsl/inet_pton (Solaris)
|
||||
check_library_exists(nsl inet_pton "" HAVE_LIBNSL)
|
||||
if (HAVE_LIBNSL)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl)
|
||||
endif (HAVE_LIBNSL)
|
||||
|
||||
# librt
|
||||
if (HAVE_LIBRT)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
|
||||
endif (HAVE_LIBRT)
|
||||
check_library_exists(rt nanosleep "" HAVE_LIBRT)
|
||||
endif (NOT LINUX)
|
||||
|
||||
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
|
||||
if (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
|
||||
endif (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
|
||||
|
||||
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
|
||||
check_function_exists(poll HAVE_POLL)
|
||||
check_function_exists(select HAVE_SELECT)
|
||||
|
||||
@@ -77,6 +77,9 @@
|
||||
/* Define to 1 if you have the `regcomp' function. */
|
||||
#cmakedefine HAVE_REGCOMP 1
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#cmakedefine HAVE_CLOCK_GETTIME 1
|
||||
|
||||
/*************************** LIBRARIES ***************************/
|
||||
|
||||
/* Define to 1 if you have the `crypto' library (-lcrypto). */
|
||||
|
||||
@@ -22,8 +22,8 @@ This tutorial concentrates for its main part on the "client" side of libssh.
|
||||
To learn how to accept incoming SSH connexions (how to write a SSH server),
|
||||
you'll have to jump to the end of this document.
|
||||
|
||||
This tutorial describes libssh version 0.5.0. This version is the development
|
||||
version and is *not* published yet. However, the examples should work with
|
||||
This tutorial describes libssh version 0.5.0. This version is a little different
|
||||
from the 0.4.X series. However, the examples should work with
|
||||
little changes on versions like 0.4.2 and later.
|
||||
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ int authenticate_console(ssh_session session){
|
||||
banner = ssh_get_issue_banner(session);
|
||||
if (banner) {
|
||||
printf("%s\n",banner);
|
||||
free(banner);
|
||||
ssh_string_free_char(banner);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
@@ -32,22 +32,25 @@ ssh_session connect_ssh(const char *host, const char *user,int verbosity){
|
||||
|
||||
if(user != NULL){
|
||||
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
if(ssh_connect(session)){
|
||||
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
if(verify_knownhost(session)<0){
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
auth=authenticate_console(session);
|
||||
@@ -59,5 +62,6 @@ ssh_session connect_ssh(const char *host, const char *user,int verbosity){
|
||||
fprintf(stderr,"Error while authenticating : %s\n",ssh_get_error(session));
|
||||
}
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ int main(void) {
|
||||
|
||||
session = connect_ssh("localhost", NULL, 0);
|
||||
if (session == NULL) {
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -20,6 +21,7 @@ int main(void) {
|
||||
if (channel == NULL) {
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -48,7 +50,9 @@ int main(void) {
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
|
||||
return 0;
|
||||
failed:
|
||||
@@ -56,6 +60,7 @@ failed:
|
||||
ssh_channel_free(channel);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ int verify_knownhost(ssh_session session){
|
||||
case SSH_SERVER_KNOWN_CHANGED:
|
||||
fprintf(stderr,"Host key for server changed : server's one is now :\n");
|
||||
ssh_print_hexa("Public key hash",hash, hlen);
|
||||
free(hash);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"For security reason, connection will be stopped\n");
|
||||
return -1;
|
||||
case SSH_SERVER_FOUND_OTHER:
|
||||
@@ -65,20 +65,23 @@ int verify_knownhost(ssh_session session){
|
||||
hexa = ssh_get_hexa(hash, hlen);
|
||||
fprintf(stderr,"The server is unknown. Do you trust the host key ?\n");
|
||||
fprintf(stderr, "Public key hash: %s\n", hexa);
|
||||
free(hexa);
|
||||
ssh_string_free_char(hexa);
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
if(strncasecmp(buf,"yes",3)!=0){
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
if(strncasecmp(buf,"yes",3)==0){
|
||||
if (ssh_write_knownhost(session) < 0) {
|
||||
free(hash);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr, "error %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
@@ -86,10 +89,10 @@ int verify_knownhost(ssh_session session){
|
||||
|
||||
break;
|
||||
case SSH_SERVER_ERROR:
|
||||
free(hash);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"%s",ssh_get_error(session));
|
||||
return -1;
|
||||
}
|
||||
free(hash);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ program.
|
||||
#include <libssh/libsshpp.hpp>
|
||||
|
||||
int main(int argc, const char **argv){
|
||||
ssh::Session session,s2;
|
||||
ssh::Session session;
|
||||
try {
|
||||
if(argc>1)
|
||||
session.setOption(SSH_OPTIONS_HOST,argv[1]);
|
||||
@@ -24,10 +24,10 @@ int main(int argc, const char **argv){
|
||||
session.setOption(SSH_OPTIONS_HOST,"localhost");
|
||||
session.connect();
|
||||
session.userauthAutopubkey();
|
||||
session.disconnect();
|
||||
} catch (ssh::SshException e){
|
||||
std::cout << "Error during connection : ";
|
||||
std::cout << e.getError() << std::endl;
|
||||
}
|
||||
//s2=session;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
// we already looked for input from stdin. Now, we are looking for input from the channel
|
||||
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
@@ -261,8 +261,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
@@ -280,8 +280,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
@@ -338,7 +338,7 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
}
|
||||
}
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
@@ -353,8 +353,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
@@ -372,8 +372,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",ssh_channel_get_exit_status(channel));
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
@@ -431,8 +431,11 @@ static void batch_shell(ssh_session session){
|
||||
ssh_channel channel;
|
||||
char buffer[1024];
|
||||
int i,s=0;
|
||||
for(i=0;i<MAXCMD && cmds[i];++i)
|
||||
for(i=0;i<MAXCMD && cmds[i];++i) {
|
||||
s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]);
|
||||
free(cmds[i]);
|
||||
cmds[i] = NULL;
|
||||
}
|
||||
channel=ssh_channel_new(session);
|
||||
ssh_channel_open_session(channel);
|
||||
if(ssh_channel_request_exec(channel,buffer)){
|
||||
|
||||
@@ -64,16 +64,21 @@ static void create_files(ssh_session session){
|
||||
}
|
||||
if(ssh_channel_open_session(channel) != SSH_OK){
|
||||
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
|
||||
ssh_channel_free(channel);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(ssh_channel_request_exec(channel,createcommand) != SSH_OK){
|
||||
fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session));
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
while(!ssh_channel_is_eof(channel)){
|
||||
ssh_channel_read(channel,buffer,1,1);
|
||||
if (write(1,buffer,1) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -91,6 +96,7 @@ static int fetch_files(ssh_session session){
|
||||
ssh_scp scp=ssh_scp_new(session, SSH_SCP_READ | SSH_SCP_RECURSIVE, "/tmp/libssh_tests/*");
|
||||
if(ssh_scp_init(scp) != SSH_OK){
|
||||
fprintf(stderr,"error initializing scp: %s\n",ssh_get_error(session));
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
}
|
||||
printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n");
|
||||
@@ -108,12 +114,16 @@ static int fetch_files(ssh_session session){
|
||||
r=ssh_scp_read(scp,buffer,sizeof(buffer));
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(session));
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
}
|
||||
printf("done\n");
|
||||
break;
|
||||
case SSH_ERROR:
|
||||
fprintf(stderr,"Error: %s\n",ssh_get_error(session));
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
case SSH_SCP_REQUEST_WARNING:
|
||||
fprintf(stderr,"Warning: %s\n",ssh_scp_request_get_warning(scp));
|
||||
@@ -134,6 +144,8 @@ static int fetch_files(ssh_session session){
|
||||
}
|
||||
} while (1);
|
||||
end:
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -147,6 +159,7 @@ int main(int argc, char **argv){
|
||||
create_files(session);
|
||||
fetch_files(session);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filen
|
||||
int *type);
|
||||
LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv);
|
||||
LIBSSH_API ssh_string publickey_to_string(ssh_public_key key);
|
||||
|
||||
LIBSSH_API ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype);
|
||||
LIBSSH_API void string_burn(ssh_string str);
|
||||
LIBSSH_API ssh_string string_copy(ssh_string str);
|
||||
LIBSSH_API void *string_data(ssh_string str);
|
||||
|
||||
@@ -323,6 +323,7 @@ enum ssh_scp_request_types {
|
||||
SSH_SCP_REQUEST_WARNING
|
||||
};
|
||||
|
||||
LIBSSH_API int ssh_blocking_flush(ssh_session session, int timeout);
|
||||
LIBSSH_API ssh_channel ssh_channel_accept_x11(ssh_channel channel, int timeout_ms);
|
||||
LIBSSH_API int ssh_channel_change_pty_size(ssh_channel channel,int cols,int rows);
|
||||
LIBSSH_API int ssh_channel_close(ssh_channel channel);
|
||||
@@ -356,6 +357,7 @@ LIBSSH_API int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechan
|
||||
timeval * timeout);
|
||||
LIBSSH_API void ssh_channel_set_blocking(ssh_channel channel, int blocking);
|
||||
LIBSSH_API int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len);
|
||||
LIBSSH_API uint32_t ssh_channel_window_size(ssh_channel channel);
|
||||
|
||||
LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
|
||||
ssh_string *publickey, int *type);
|
||||
|
||||
@@ -31,6 +31,8 @@ int ssh_file_readaccess_ok(const char *file);
|
||||
char *ssh_path_expand_tilde(const char *d);
|
||||
char *ssh_path_expand_escape(ssh_session session, const char *s);
|
||||
int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2);
|
||||
int ssh_is_ipaddr_v4(const char *str);
|
||||
int ssh_is_ipaddr(const char *str);
|
||||
|
||||
/* macro for byte ordering */
|
||||
uint64_t ntohll(uint64_t);
|
||||
@@ -48,6 +50,11 @@ struct ssh_iterator {
|
||||
const void *data;
|
||||
};
|
||||
|
||||
struct ssh_timestamp {
|
||||
long seconds;
|
||||
long useconds;
|
||||
};
|
||||
|
||||
struct ssh_list *ssh_list_new(void);
|
||||
void ssh_list_free(struct ssh_list *list);
|
||||
struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list);
|
||||
@@ -70,4 +77,8 @@ const void *_ssh_list_pop_head(struct ssh_list *list);
|
||||
#define ssh_list_pop_head(type, ssh_list)\
|
||||
((type)_ssh_list_pop_head(ssh_list))
|
||||
|
||||
void ssh_timestamp_init(struct ssh_timestamp *ts);
|
||||
int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout);
|
||||
int ssh_timeout_update(struct ssh_timestamp *ts, int timeout);
|
||||
|
||||
#endif /* MISC_H_ */
|
||||
|
||||
@@ -172,8 +172,6 @@ void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callback
|
||||
void ssh_packet_set_default_callbacks(ssh_session session);
|
||||
void ssh_packet_process(ssh_session session, uint8_t type);
|
||||
/* connect.c */
|
||||
int ssh_regex_init(void);
|
||||
void ssh_regex_finalize(void);
|
||||
socket_t ssh_connect_host(ssh_session session, const char *host,const char
|
||||
*bind_addr, int port, long timeout, long usec);
|
||||
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
|
||||
@@ -87,10 +87,63 @@ LIBSSH_API ssh_bind ssh_bind_new(void);
|
||||
*
|
||||
* @param sshbind The ssh server bind to configure.
|
||||
*
|
||||
* @param type Option to set up.
|
||||
* @param value Value to set.
|
||||
* @returns SSH_OK No error.
|
||||
* @returns SSH_ERROR Invalid option or parameter.
|
||||
* @param type The option type to set. This could be one of the
|
||||
* following:
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_BINDADDR
|
||||
* The ip address to bind (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_BINDPORT
|
||||
* The port to bind (unsigned int).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_BINDPORT_STR
|
||||
* The port to bind (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_HOSTKEY
|
||||
* This specifies the file containing the private host key used
|
||||
* by SSHv1. (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_DSAKEY
|
||||
* This specifies the file containing the private host dsa key
|
||||
* used by SSHv2. (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_RSAKEY
|
||||
* This specifies the file containing the private host dsa key
|
||||
* used by SSHv2. (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_BANNER
|
||||
* That the server banner (version string) for SSH.
|
||||
* (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_LOG_VERBOSITY
|
||||
* Set the session logging verbosity (int).\n
|
||||
* \n
|
||||
* The verbosity of the messages. Every log smaller or
|
||||
* equal to verbosity will be shown.
|
||||
* - SSH_LOG_NOLOG: No logging
|
||||
* - SSH_LOG_RARE: Rare conditions or warnings
|
||||
* - SSH_LOG_ENTRY: API-accessible entrypoints
|
||||
* - SSH_LOG_PACKET: Packet id and size
|
||||
* - SSH_LOG_FUNCTIONS: Function entering and leaving
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR
|
||||
* Set the session logging verbosity (const char *).\n
|
||||
* \n
|
||||
* The verbosity of the messages. Every log smaller or
|
||||
* equal to verbosity will be shown.
|
||||
* - SSH_LOG_NOLOG: No logging
|
||||
* - SSH_LOG_RARE: Rare conditions or warnings
|
||||
* - SSH_LOG_ENTRY: API-accessible entrypoints
|
||||
* - SSH_LOG_PACKET: Packet id and size
|
||||
* - SSH_LOG_FUNCTIONS: Function entering and leaving
|
||||
* \n
|
||||
* See the corresponding numbers in libssh.h.
|
||||
*
|
||||
* @param value The value to set. This is a generic pointer and the
|
||||
* datatype which is used should be set according to the
|
||||
* type set.
|
||||
*
|
||||
* @returns SSH_OK on success, SSH_ERROR on invalid option or parameter.
|
||||
*/
|
||||
LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
|
||||
enum ssh_bind_options_e type, const void *value);
|
||||
@@ -104,6 +157,26 @@ LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
|
||||
*/
|
||||
LIBSSH_API int ssh_bind_listen(ssh_bind ssh_bind_o);
|
||||
|
||||
/**
|
||||
* @brief Set the callback for this bind.
|
||||
*
|
||||
* @param[in] sshbind The bind to set the callback on.
|
||||
*
|
||||
* @param[in] callbacks An already set up ssh_bind_callbacks instance.
|
||||
*
|
||||
* @param[in] userdata A pointer to private data to pass to the callbacks.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR if an error occured.
|
||||
*
|
||||
* @code
|
||||
* struct ssh_callbacks_struct cb = {
|
||||
* .userdata = data,
|
||||
* .auth_function = my_auth_function
|
||||
* };
|
||||
* ssh_callbacks_init(&cb);
|
||||
* ssh_bind_set_callbacks(session, &cb);
|
||||
* @endcode
|
||||
*/
|
||||
LIBSSH_API int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
|
||||
void *userdata);
|
||||
|
||||
@@ -230,6 +303,8 @@ LIBSSH_API int ssh_channel_write_stderr(ssh_channel channel,
|
||||
|
||||
/* deprecated functions */
|
||||
SSH_DEPRECATED LIBSSH_API int ssh_accept(ssh_session session);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_write_stderr(ssh_channel channel,
|
||||
const void *data, uint32_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ void ssh_socket_set_write_wontblock(ssh_socket s);
|
||||
void ssh_socket_set_read_wontblock(ssh_socket s);
|
||||
void ssh_socket_set_except(ssh_socket s);
|
||||
int ssh_socket_get_status(ssh_socket s);
|
||||
int ssh_socket_buffered_write_bytes(ssh_socket s);
|
||||
int ssh_socket_data_available(ssh_socket s);
|
||||
int ssh_socket_data_writable(ssh_socket s);
|
||||
|
||||
|
||||
100
src/auth.c
100
src/auth.c
@@ -308,7 +308,7 @@ int ssh_auth_list(ssh_session session) {
|
||||
/**
|
||||
* @brief retrieves available authentication methods for this session
|
||||
* @param[in] session the SSH session
|
||||
* @param[in] username set to NULL
|
||||
* @param[in] username Deprecated, set to NULL.
|
||||
* @returns A bitfield of values SSH_AUTH_METHOD_NONE, SSH_AUTH_METHOD_PASSWORD,
|
||||
SSH_AUTH_METHOD_PUBLICKEY, SSH_AUTH_METHOD_HOSTBASED,
|
||||
SSH_AUTH_METHOD_INTERACTIVE.
|
||||
@@ -345,7 +345,7 @@ int ssh_userauth_list(ssh_session session, const char *username) {
|
||||
* SSH_AUTH_DENIED: Authentication failed: use another method\n
|
||||
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still
|
||||
* have to use another method\n
|
||||
* SSH_AUTH_SUCCESS: Authentication success
|
||||
* SSH_AUTH_SUCCESS: Authentication success\n
|
||||
* SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
|
||||
* later.
|
||||
*/
|
||||
@@ -384,6 +384,7 @@ int ssh_userauth_none(ssh_session session, const char *username) {
|
||||
}
|
||||
|
||||
if (user == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
leave_function();
|
||||
return rc;
|
||||
}
|
||||
@@ -415,10 +416,12 @@ int ssh_userauth_none(ssh_session session, const char *username) {
|
||||
|
||||
method = ssh_string_from_char("none");
|
||||
if (method == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
service = ssh_string_from_char("ssh-connection");
|
||||
if (service == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -519,6 +522,7 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
|
||||
}
|
||||
|
||||
if (user == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
leave_function();
|
||||
return rc;
|
||||
}
|
||||
@@ -531,14 +535,17 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
|
||||
|
||||
service = ssh_string_from_char("ssh-connection");
|
||||
if (service == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
method = ssh_string_from_char("publickey");
|
||||
if (method == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
algo = ssh_string_from_char(ssh_type_to_char(type));
|
||||
if (algo == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -549,6 +556,7 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
|
||||
buffer_add_u8(session->out_buffer, 0) < 0 ||
|
||||
buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
|
||||
buffer_add_ssh_string(session->out_buffer, publickey) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -640,6 +648,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
|
||||
}
|
||||
|
||||
if (user == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
leave_function();
|
||||
return rc;
|
||||
}
|
||||
@@ -652,24 +661,32 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
|
||||
|
||||
service = ssh_string_from_char("ssh-connection");
|
||||
if (service == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
method = ssh_string_from_char("publickey");
|
||||
if (method == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
algo = ssh_string_from_char(ssh_type_to_char(privatekey->type));
|
||||
if (algo == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
if (publickey == NULL) {
|
||||
pk = publickey_from_privatekey(privatekey);
|
||||
if (pk == NULL) {
|
||||
/* most likely oom, and publickey_from_privatekey does not
|
||||
* return any more information */
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
pkstr = publickey_to_string(pk);
|
||||
publickey_free(pk);
|
||||
if (pkstr == NULL) {
|
||||
/* same as above */
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -682,6 +699,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
|
||||
buffer_add_u8(session->out_buffer, 1) < 0 ||
|
||||
buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
|
||||
buffer_add_ssh_string(session->out_buffer, (publickey == NULL ? pkstr : publickey)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -694,6 +712,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
|
||||
sign = ssh_do_sign(session,session->out_buffer, privatekey);
|
||||
if (sign) {
|
||||
if (buffer_add_ssh_string(session->out_buffer,sign) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
ssh_string_free(sign);
|
||||
@@ -737,7 +756,9 @@ error:
|
||||
* SSH_AUTH_DENIED: Authentication failed: use another method.\n
|
||||
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still
|
||||
* have to use another method.\n
|
||||
* SSH_AUTH_SUCCESS: Authentication successful.
|
||||
* SSH_AUTH_SUCCESS: Authentication successful.\n
|
||||
* SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
|
||||
* later.
|
||||
*
|
||||
* @see publickey_from_file()
|
||||
* @see privatekey_from_file()
|
||||
@@ -756,6 +777,7 @@ int ssh_userauth_privatekey_file(ssh_session session, const char *username,
|
||||
|
||||
pubkeyfile = malloc(strlen(filename) + 1 + 4);
|
||||
if (pubkeyfile == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
@@ -837,6 +859,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
|
||||
}
|
||||
|
||||
if (user == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
leave_function();
|
||||
return rc;
|
||||
}
|
||||
@@ -849,18 +872,22 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
|
||||
|
||||
service = ssh_string_from_char("ssh-connection");
|
||||
if (service == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
method = ssh_string_from_char("publickey");
|
||||
if (method == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
algo = ssh_string_from_char(ssh_type_to_char(publickey->type));
|
||||
if (algo == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
key = publickey_to_string(publickey);
|
||||
if (key == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -872,6 +899,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
|
||||
buffer_add_u8(session->out_buffer, 1) < 0 ||
|
||||
buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
|
||||
buffer_add_ssh_string(session->out_buffer, key) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -879,6 +907,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
|
||||
|
||||
if (sign) {
|
||||
if (buffer_add_ssh_string(session->out_buffer, sign) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
ssh_string_free(sign);
|
||||
@@ -929,7 +958,7 @@ error:
|
||||
* SSH_AUTH_DENIED: Authentication failed: use another method.\n
|
||||
* SSH_AUTH_PARTIAL: You've been partially authenticated, you still
|
||||
* have to use another method.\n
|
||||
* SSH_AUTH_SUCCESS: Authentication successful.
|
||||
* SSH_AUTH_SUCCESS: Authentication successful.\n
|
||||
* SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
|
||||
* later.
|
||||
*
|
||||
@@ -968,6 +997,7 @@ int ssh_userauth_password(ssh_session session, const char *username,
|
||||
}
|
||||
|
||||
if (user == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
leave_function();
|
||||
return rc;
|
||||
}
|
||||
@@ -1000,14 +1030,17 @@ int ssh_userauth_password(ssh_session session, const char *username,
|
||||
|
||||
service = ssh_string_from_char("ssh-connection");
|
||||
if (service == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
method = ssh_string_from_char("password");
|
||||
if (method == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
pwd = ssh_string_from_char(password);
|
||||
if (pwd == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1017,6 +1050,7 @@ int ssh_userauth_password(ssh_session session, const char *username,
|
||||
buffer_add_ssh_string(session->out_buffer, method) < 0 ||
|
||||
buffer_add_u8(session->out_buffer, 0) < 0 ||
|
||||
buffer_add_ssh_string(session->out_buffer, pwd) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1374,18 +1408,22 @@ static int kbdauth_init(ssh_session session, const char *user,
|
||||
|
||||
usr = ssh_string_from_char(user);
|
||||
if (usr == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
sub = (submethods ? ssh_string_from_char(submethods) : ssh_string_from_char(""));
|
||||
if (sub == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
service = ssh_string_from_char("ssh-connection");
|
||||
if (service == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
method = ssh_string_from_char("keyboard-interactive");
|
||||
if (method == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1395,6 +1433,7 @@ static int kbdauth_init(ssh_session session, const char *user,
|
||||
buffer_add_ssh_string(session->out_buffer, method) < 0 ||
|
||||
buffer_add_u32(session->out_buffer, 0) < 0 ||
|
||||
buffer_add_ssh_string(session->out_buffer, sub) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1562,23 +1601,30 @@ static int kbdauth_send(ssh_session session) {
|
||||
|
||||
enter_function();
|
||||
|
||||
if(session==NULL || session->kbdint == NULL) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_INFO_RESPONSE) < 0 ||
|
||||
buffer_add_u32(session->out_buffer,
|
||||
htonl(session->kbdint->nprompts)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < session->kbdint->nprompts; i++) {
|
||||
if (session->kbdint->answers[i]) {
|
||||
if (session->kbdint->answers && session->kbdint->answers[i]) {
|
||||
answer = ssh_string_from_char(session->kbdint->answers[i]);
|
||||
} else {
|
||||
answer = ssh_string_from_char("");
|
||||
}
|
||||
if (answer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_ssh_string(session->out_buffer, answer) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1622,7 +1668,9 @@ error:
|
||||
* have to use another method\n
|
||||
* SSH_AUTH_SUCCESS: Authentication success\n
|
||||
* SSH_AUTH_INFO: The server asked some questions. Use
|
||||
* ssh_userauth_kbdint_getnprompts() and such.
|
||||
* ssh_userauth_kbdint_getnprompts() and such.\n
|
||||
* SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again
|
||||
* later.
|
||||
*
|
||||
* @see ssh_userauth_kbdint_getnprompts()
|
||||
* @see ssh_userauth_kbdint_getname()
|
||||
@@ -1635,7 +1683,7 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
|
||||
int rc = SSH_AUTH_ERROR;
|
||||
|
||||
if (session->version == 1) {
|
||||
/* No keyb-interactive for ssh1 */
|
||||
ssh_set_error(session, SSH_NO_ERROR, "No keyboard-interactive for ssh1");
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
@@ -1688,8 +1736,12 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
|
||||
* @returns The number of prompts.
|
||||
*/
|
||||
int ssh_userauth_kbdint_getnprompts(ssh_session session) {
|
||||
if(session==NULL || session->kbdint == NULL)
|
||||
return SSH_ERROR;
|
||||
if(session==NULL)
|
||||
return SSH_ERROR;
|
||||
if(session->kbdint == NULL) {
|
||||
ssh_set_error_invalid(session, __FUNCTION__);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
return session->kbdint->nprompts;
|
||||
}
|
||||
|
||||
@@ -1704,8 +1756,12 @@ int ssh_userauth_kbdint_getnprompts(ssh_session session) {
|
||||
* @returns The name of the message block. Do not free it.
|
||||
*/
|
||||
const char *ssh_userauth_kbdint_getname(ssh_session session) {
|
||||
if(session==NULL || session->kbdint == NULL)
|
||||
if(session==NULL)
|
||||
return NULL;
|
||||
if(session->kbdint == NULL) {
|
||||
ssh_set_error_invalid(session, __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
return session->kbdint->name;
|
||||
}
|
||||
|
||||
@@ -1721,8 +1777,12 @@ const char *ssh_userauth_kbdint_getname(ssh_session session) {
|
||||
*/
|
||||
|
||||
const char *ssh_userauth_kbdint_getinstruction(ssh_session session) {
|
||||
if(session==NULL || session->kbdint == NULL)
|
||||
return NULL;
|
||||
if(session==NULL)
|
||||
return NULL;
|
||||
if(session->kbdint == NULL) {
|
||||
ssh_set_error_invalid(session, __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
return session->kbdint->instruction;
|
||||
}
|
||||
|
||||
@@ -1744,9 +1804,14 @@ const char *ssh_userauth_kbdint_getinstruction(ssh_session session) {
|
||||
*/
|
||||
const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i,
|
||||
char *echo) {
|
||||
if(session==NULL || session->kbdint == NULL)
|
||||
if(session==NULL)
|
||||
return NULL;
|
||||
if (i > session->kbdint->nprompts) {
|
||||
if(session->kbdint == NULL) {
|
||||
ssh_set_error_invalid(session, __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
if (i > session->kbdint->nprompts) {
|
||||
ssh_set_error_invalid(session, __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1773,14 +1838,18 @@ const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i,
|
||||
*/
|
||||
int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i,
|
||||
const char *answer) {
|
||||
if (session == NULL || answer == NULL || session->kbdint == NULL ||
|
||||
if (session == NULL)
|
||||
return -1;
|
||||
if (answer == NULL || session->kbdint == NULL ||
|
||||
i > session->kbdint->nprompts) {
|
||||
ssh_set_error_invalid(session, __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (session->kbdint->answers == NULL) {
|
||||
session->kbdint->answers = malloc(sizeof(char*) * session->kbdint->nprompts);
|
||||
if (session->kbdint->answers == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
memset(session->kbdint->answers, 0, sizeof(char *) * session->kbdint->nprompts);
|
||||
@@ -1793,6 +1862,7 @@ int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i,
|
||||
|
||||
session->kbdint->answers[i] = strdup(answer);
|
||||
if (session->kbdint->answers[i] == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
28
src/bind.c
28
src/bind.c
@@ -160,6 +160,7 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
||||
socket_t fd;
|
||||
|
||||
if (ssh_init() < 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -185,28 +186,13 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief set the bind callbacks for ssh_bind
|
||||
* @code
|
||||
* struct ssh_callbacks_struct cb = {
|
||||
* .userdata = data,
|
||||
* .auth_function = my_auth_function
|
||||
* };
|
||||
* ssh_callbacks_init(&cb);
|
||||
* ssh_set_callbacks(session, &cb);
|
||||
* @endcode
|
||||
* @param sshbind the ssh_bind structure to set
|
||||
* @param callbacks a ssh_bind_callbacks instance already set up. Do
|
||||
* use ssh_callbacks_init() to initialize it.
|
||||
* @param userdata userdata to be used with each callback called
|
||||
* within callbacks.
|
||||
* @returns SSH_OK on success,
|
||||
* SSH_ERROR on error.
|
||||
*/
|
||||
|
||||
int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
|
||||
void *userdata){
|
||||
if (sshbind == NULL || callbacks == NULL) {
|
||||
if (sshbind == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (callbacks == NULL) {
|
||||
ssh_set_error_invalid(sshbind, __FUNCTION__);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if(callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)){
|
||||
@@ -378,6 +364,8 @@ int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
|
||||
ssh_socket_free(session->socket);
|
||||
session->socket = ssh_socket_new(session);
|
||||
if (session->socket == NULL) {
|
||||
/* perhaps it may be better to copy the error from session to sshbind */
|
||||
ssh_set_error_oom(sshbind);
|
||||
privatekey_free(dsa);
|
||||
privatekey_free(rsa);
|
||||
return SSH_ERROR;
|
||||
|
||||
194
src/channels.c
194
src/channels.c
@@ -71,18 +71,21 @@ ssh_channel ssh_channel_new(ssh_session session) {
|
||||
|
||||
channel = malloc(sizeof(struct ssh_channel_struct));
|
||||
if (channel == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
memset(channel,0,sizeof(struct ssh_channel_struct));
|
||||
|
||||
channel->stdout_buffer = ssh_buffer_new();
|
||||
if (channel->stdout_buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
SAFE_FREE(channel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
channel->stderr_buffer = ssh_buffer_new();
|
||||
if (channel->stderr_buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_free(channel->stdout_buffer);
|
||||
SAFE_FREE(channel);
|
||||
return NULL;
|
||||
@@ -243,6 +246,7 @@ static int channel_open(ssh_channel channel, const char *type_c, int window,
|
||||
|
||||
type = ssh_string_from_char(type_c);
|
||||
if (type == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
@@ -252,6 +256,7 @@ static int channel_open(ssh_channel channel, const char *type_c, int window,
|
||||
buffer_add_u32(session->out_buffer, htonl(channel->local_channel)) < 0 ||
|
||||
buffer_add_u32(session->out_buffer, htonl(channel->local_window)) < 0 ||
|
||||
buffer_add_u32(session->out_buffer, htonl(channel->local_maxpacket)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_string_free(type);
|
||||
leave_function();
|
||||
return err;
|
||||
@@ -261,6 +266,7 @@ static int channel_open(ssh_channel channel, const char *type_c, int window,
|
||||
|
||||
if (payload != NULL) {
|
||||
if (buffer_add_buffer(session->out_buffer, payload) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
@@ -331,6 +337,7 @@ static int grow_window(ssh_session session, ssh_channel channel, int minimumsize
|
||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_WINDOW_ADJUST) < 0 ||
|
||||
buffer_add_u32(session->out_buffer, htonl(channel->remote_channel)) < 0 ||
|
||||
buffer_add_u32(session->out_buffer, htonl(new_window - channel->local_window)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -467,7 +474,7 @@ SSH_PACKET_CALLBACK(channel_rcv_data){
|
||||
len = ssh_string_len(str);
|
||||
|
||||
ssh_log(session, SSH_LOG_PROTOCOL,
|
||||
"Channel receiving %zu bytes data in %d (local win=%d remote win=%d)",
|
||||
"Channel receiving %" PRIdS " bytes data in %d (local win=%d remote win=%d)",
|
||||
len,
|
||||
is_stderr,
|
||||
channel->local_window,
|
||||
@@ -476,7 +483,7 @@ SSH_PACKET_CALLBACK(channel_rcv_data){
|
||||
/* What shall we do in this case? Let's accept it anyway */
|
||||
if (len > channel->local_window) {
|
||||
ssh_log(session, SSH_LOG_RARE,
|
||||
"Data packet too big for our window(%zu vs %d)",
|
||||
"Data packet too big for our window(%" PRIdS " vs %d)",
|
||||
len,
|
||||
channel->local_window);
|
||||
}
|
||||
@@ -799,7 +806,18 @@ SSH_PACKET_CALLBACK(channel_rcv_request) {
|
||||
*/
|
||||
int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
||||
int is_stderr) {
|
||||
ssh_session session = channel->session;
|
||||
ssh_session session;
|
||||
|
||||
if(channel == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
session = channel->session;
|
||||
|
||||
if(data == NULL) {
|
||||
ssh_set_error_invalid(session, __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssh_log(session, SSH_LOG_RARE,
|
||||
"placing %d bytes into channel buffer (stderr=%d)", len, is_stderr);
|
||||
@@ -814,6 +832,7 @@ int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
||||
}
|
||||
|
||||
if (buffer_add_data(channel->stdout_buffer, data, len) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_free(channel->stdout_buffer);
|
||||
channel->stdout_buffer = NULL;
|
||||
return -1;
|
||||
@@ -829,6 +848,7 @@ int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
||||
}
|
||||
|
||||
if (buffer_add_data(channel->stderr_buffer, data, len) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_free(channel->stderr_buffer);
|
||||
channel->stderr_buffer = NULL;
|
||||
return -1;
|
||||
@@ -869,11 +889,12 @@ int ssh_channel_open_session(ssh_channel channel) {
|
||||
*
|
||||
* @param[in] remoteport The remote port.
|
||||
*
|
||||
* @param[in] sourcehost The source host (your local computer). It's optional
|
||||
* and for logging purpose.
|
||||
* @param[in] sourcehost The numeric IP address of the machine from where the
|
||||
* connection request originates. This is mostly for
|
||||
* logging purposes.
|
||||
*
|
||||
* @param[in] localport The source port (your local computer). It's optional
|
||||
* and for logging purpose.
|
||||
* @param[in] localport The port on the host from where the connection
|
||||
* originated. This is mostly for logging purposes.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR if an error occured.
|
||||
*
|
||||
@@ -883,35 +904,51 @@ int ssh_channel_open_session(ssh_channel channel) {
|
||||
*/
|
||||
int ssh_channel_open_forward(ssh_channel channel, const char *remotehost,
|
||||
int remoteport, const char *sourcehost, int localport) {
|
||||
ssh_session session = channel->session;
|
||||
ssh_session session;
|
||||
ssh_buffer payload = NULL;
|
||||
ssh_string str = NULL;
|
||||
int rc = SSH_ERROR;
|
||||
|
||||
if (channel == NULL) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
session = channel->session;
|
||||
|
||||
enter_function();
|
||||
|
||||
if(remotehost == NULL || sourcehost == NULL) {
|
||||
ssh_set_error_invalid(session, __FUNCTION__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
payload = ssh_buffer_new();
|
||||
if (payload == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
str = ssh_string_from_char(remotehost);
|
||||
if (str == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_ssh_string(payload, str) < 0 ||
|
||||
buffer_add_u32(payload,htonl(remoteport)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ssh_string_free(str);
|
||||
str = ssh_string_from_char(sourcehost);
|
||||
if (str == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_ssh_string(payload, str) < 0 ||
|
||||
buffer_add_u32(payload,htonl(localport)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -988,9 +1025,11 @@ int ssh_channel_send_eof(ssh_channel channel){
|
||||
enter_function();
|
||||
|
||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_EOF) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
if (buffer_add_u32(session->out_buffer,htonl(channel->remote_channel)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
rc = packet_send(session);
|
||||
@@ -1040,6 +1079,7 @@ int ssh_channel_close(ssh_channel channel){
|
||||
|
||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_CLOSE) < 0 ||
|
||||
buffer_add_u32(session->out_buffer, htonl(channel->remote_channel)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1064,15 +1104,28 @@ error:
|
||||
|
||||
int channel_write_common(ssh_channel channel, const void *data,
|
||||
uint32_t len, int is_stderr) {
|
||||
ssh_session session = channel->session;
|
||||
ssh_session session;
|
||||
int origlen = len;
|
||||
size_t effectivelen;
|
||||
/* handle the max packet len from remote side, be nice */
|
||||
/* 10 bytes for the headers */
|
||||
size_t maxpacketlen = channel->remote_maxpacket - 10;
|
||||
size_t maxpacketlen;
|
||||
|
||||
if(channel == NULL || data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
session = channel->session;
|
||||
if(data == NULL) {
|
||||
ssh_set_error_invalid(session, __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
enter_function();
|
||||
|
||||
/*
|
||||
* Handle the max packet len from remote side, be nice
|
||||
* 10 bytes for the headers
|
||||
*/
|
||||
maxpacketlen = channel->remote_maxpacket - 10;
|
||||
|
||||
if (channel->local_eof) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Can't write to channel %d:%d after EOF was sent",
|
||||
@@ -1102,15 +1155,12 @@ int channel_write_common(ssh_channel channel, const void *data,
|
||||
"Remote window is %d bytes. going to write %d bytes",
|
||||
channel->remote_window,
|
||||
len);
|
||||
ssh_log(session, SSH_LOG_PROTOCOL,
|
||||
"Waiting for a growing window message...");
|
||||
/* What happens when the channel window is zero? */
|
||||
while(channel->remote_window == 0) {
|
||||
/* parse every incoming packet */
|
||||
if (ssh_handle_packets(session,-1) == SSH_ERROR) {
|
||||
leave_function();
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if(channel->remote_window == 0) {
|
||||
/* nothing can be written */
|
||||
ssh_log(session, SSH_LOG_PROTOCOL,
|
||||
"Wait for a growing window message...");
|
||||
return 0;
|
||||
}
|
||||
effectivelen = len > channel->remote_window ? channel->remote_window : len;
|
||||
} else {
|
||||
@@ -1121,16 +1171,19 @@ int channel_write_common(ssh_channel channel, const void *data,
|
||||
SSH2_MSG_CHANNEL_EXTENDED_DATA : SSH2_MSG_CHANNEL_DATA) < 0 ||
|
||||
buffer_add_u32(session->out_buffer,
|
||||
htonl(channel->remote_channel)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
/* stderr message has an extra field */
|
||||
if (is_stderr &&
|
||||
buffer_add_u32(session->out_buffer, htonl(SSH2_EXTENDED_DATA_STDERR)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
/* append payload data */
|
||||
if (buffer_add_u32(session->out_buffer, htonl(effectivelen)) < 0 ||
|
||||
buffer_add_data(session->out_buffer, data, effectivelen) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1156,6 +1209,10 @@ error:
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
uint32_t ssh_channel_window_size(ssh_channel channel) {
|
||||
return channel->remote_window;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Blocking write on a channel.
|
||||
*
|
||||
@@ -1313,6 +1370,7 @@ static int channel_request(ssh_channel channel, const char *request,
|
||||
|
||||
req = ssh_string_from_char(request);
|
||||
if (req == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1320,6 +1378,7 @@ static int channel_request(ssh_channel channel, const char *request,
|
||||
buffer_add_u32(session->out_buffer, htonl(channel->remote_channel)) < 0 ||
|
||||
buffer_add_ssh_string(session->out_buffer, req) < 0 ||
|
||||
buffer_add_u8(session->out_buffer, reply == 0 ? 0 : 1) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
ssh_string_free(req);
|
||||
@@ -1327,6 +1386,7 @@ static int channel_request(ssh_channel channel, const char *request,
|
||||
if (buffer != NULL) {
|
||||
if (buffer_add_data(session->out_buffer, buffer_get_rest(buffer),
|
||||
buffer_get_rest_len(buffer)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -1409,11 +1469,13 @@ int ssh_channel_request_pty_size(ssh_channel channel, const char *terminal,
|
||||
#endif
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
term = ssh_string_from_char(terminal);
|
||||
if (term == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1424,6 +1486,7 @@ int ssh_channel_request_pty_size(ssh_channel channel, const char *terminal,
|
||||
buffer_add_u32(buffer, 0) < 0 ||
|
||||
buffer_add_u32(buffer, htonl(1)) < 0 || /* Add a 0byte string */
|
||||
buffer_add_u8(buffer, 0) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1481,6 +1544,7 @@ int ssh_channel_change_pty_size(ssh_channel channel, int cols, int rows) {
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1488,6 +1552,7 @@ int ssh_channel_change_pty_size(ssh_channel channel, int cols, int rows) {
|
||||
buffer_add_u32(buffer, htonl(rows)) < 0 ||
|
||||
buffer_add_u32(buffer, 0) < 0 ||
|
||||
buffer_add_u32(buffer, 0) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1533,15 +1598,18 @@ int ssh_channel_request_subsystem(ssh_channel channel, const char *subsys) {
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
subsystem = ssh_string_from_char(subsys);
|
||||
if (subsystem == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_ssh_string(buffer, subsystem) < 0) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1601,11 +1669,13 @@ int ssh_channel_request_x11(ssh_channel channel, int single_connection, const ch
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
p = ssh_string_from_char(protocol ? protocol : "MIT-MAGIC-COOKIE-1");
|
||||
if (p == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1615,6 +1685,7 @@ int ssh_channel_request_x11(ssh_channel channel, int single_connection, const ch
|
||||
c = generate_cookie();
|
||||
}
|
||||
if (c == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1622,6 +1693,7 @@ int ssh_channel_request_x11(ssh_channel channel, int single_connection, const ch
|
||||
buffer_add_ssh_string(buffer, p) < 0 ||
|
||||
buffer_add_ssh_string(buffer, c) < 0 ||
|
||||
buffer_add_u32(buffer, htonl(screen_number)) < 0) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1674,6 +1746,7 @@ static ssh_channel ssh_channel_accept(ssh_session session, int channeltype,
|
||||
}
|
||||
}
|
||||
|
||||
ssh_set_error(session, SSH_NO_ERROR, "No channel request of this type from server");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1771,12 +1844,14 @@ static int global_request(ssh_session session, const char *request,
|
||||
}
|
||||
req = ssh_string_from_char(request);
|
||||
if (req == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST) < 0 ||
|
||||
buffer_add_ssh_string(session->out_buffer, req) < 0 ||
|
||||
buffer_add_u8(session->out_buffer, reply == 0 ? 0 : 1) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
ssh_string_free(req);
|
||||
@@ -1785,6 +1860,7 @@ static int global_request(ssh_session session, const char *request,
|
||||
if (buffer != NULL) {
|
||||
if (buffer_add_data(session->out_buffer, buffer_get_rest(buffer),
|
||||
buffer_get_rest_len(buffer)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -1863,16 +1939,19 @@ int ssh_forward_listen(ssh_session session, const char *address, int port, int *
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
addr = ssh_string_from_char(address ? address : "");
|
||||
if (addr == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_ssh_string(buffer, addr) < 0 ||
|
||||
buffer_add_u32(buffer, htonl(port)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1922,16 +2001,19 @@ int ssh_forward_cancel(ssh_session session, const char *address, int port) {
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
addr = ssh_string_from_char(address ? address : "");
|
||||
if (addr == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_ssh_string(buffer, addr) < 0 ||
|
||||
buffer_add_u32(buffer, htonl(port)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1963,25 +2045,30 @@ int ssh_channel_request_env(ssh_channel channel, const char *name, const char *v
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
str = ssh_string_from_char(name);
|
||||
if (str == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_ssh_string(buffer, str) < 0) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ssh_string_free(str);
|
||||
str = ssh_string_from_char(value);
|
||||
if (str == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_ssh_string(buffer, str) < 0) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -2033,15 +2120,18 @@ int ssh_channel_request_exec(ssh_channel channel, const char *cmd) {
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
command = ssh_string_from_char(cmd);
|
||||
if (command == NULL) {
|
||||
goto error;
|
||||
ssh_set_error_oom(channel->session);
|
||||
}
|
||||
|
||||
if (buffer_add_ssh_string(buffer, command) < 0) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -2061,10 +2151,26 @@ error:
|
||||
* In such a case this request will be silently ignored.
|
||||
* Only SSH-v2 is supported (I'm not sure about SSH-v1).
|
||||
*
|
||||
* OpenSSH doesn't support signals yet, see:
|
||||
* https://bugzilla.mindrot.org/show_bug.cgi?id=1424
|
||||
*
|
||||
* @param[in] channel The channel to send signal.
|
||||
*
|
||||
* @param[in] sig The signal to send (without SIG prefix)
|
||||
* (e.g. "TERM" or "KILL").
|
||||
* \n\n
|
||||
* SIGABRT -> ABRT \n
|
||||
* SIGALRM -> ALRM \n
|
||||
* SIGFPE -> FPE \n
|
||||
* SIGHUP -> HUP \n
|
||||
* SIGILL -> ILL \n
|
||||
* SIGINT -> INT \n
|
||||
* SIGKILL -> KILL \n
|
||||
* SIGPIPE -> PIPE \n
|
||||
* SIGQUIT -> QUIT \n
|
||||
* SIGSEGV -> SEGV \n
|
||||
* SIGTERM -> TERM \n
|
||||
* SIGUSR1 -> USR1 \n
|
||||
* SIGUSR2 -> USR2 \n
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR if an error occured
|
||||
* (including attempts to send signal via SSH-v1 session).
|
||||
@@ -2082,15 +2188,18 @@ int ssh_channel_request_send_signal(ssh_channel channel, const char *sig) {
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
encoded_signal = ssh_string_from_char(sig);
|
||||
if (encoded_signal == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_ssh_string(buffer, encoded_signal) < 0) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -2142,7 +2251,10 @@ int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
|
||||
leave_function();
|
||||
return r;
|
||||
}
|
||||
buffer_add_data(buffer,buffer_tmp,r);
|
||||
if(buffer_add_data(buffer,buffer_tmp,r) < 0){
|
||||
ssh_set_error_oom(session);
|
||||
r = SSH_ERROR;
|
||||
}
|
||||
leave_function();
|
||||
return r;
|
||||
}
|
||||
@@ -2163,7 +2275,11 @@ int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
|
||||
leave_function();
|
||||
return total;
|
||||
}
|
||||
buffer_add_data(buffer,buffer_tmp,r);
|
||||
if(buffer_add_data(buffer,buffer_tmp,r) < 0){
|
||||
ssh_set_error_oom(session);
|
||||
leave_function();
|
||||
return SSH_ERROR;
|
||||
}
|
||||
total += r;
|
||||
}
|
||||
leave_function();
|
||||
@@ -2288,7 +2404,7 @@ int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_std
|
||||
int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
|
||||
int is_stderr) {
|
||||
ssh_session session = channel->session;
|
||||
uint32_t to_read;
|
||||
int to_read;
|
||||
int rc;
|
||||
|
||||
enter_function();
|
||||
@@ -2300,8 +2416,8 @@ int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count
|
||||
return to_read; /* may be an error code */
|
||||
}
|
||||
|
||||
if (to_read > count) {
|
||||
to_read = count;
|
||||
if (to_read > (int)count) {
|
||||
to_read = (int)count;
|
||||
}
|
||||
rc = ssh_channel_read(channel, dest, to_read, is_stderr);
|
||||
|
||||
@@ -2379,7 +2495,7 @@ int ssh_channel_get_exit_status(ssh_channel channel) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (channel->remote_eof == 0 || channel->exit_status == -1) {
|
||||
while ((channel->remote_eof == 0 || channel->exit_status == -1) && channel->session->alive) {
|
||||
/* Parse every incoming packet */
|
||||
if (ssh_handle_packets(channel->session,-1) != SSH_OK) {
|
||||
return -1;
|
||||
@@ -2659,26 +2775,31 @@ int ssh_channel_open_reverse_forward(ssh_channel channel, const char *remotehost
|
||||
|
||||
payload = ssh_buffer_new();
|
||||
if (payload == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
str = ssh_string_from_char(remotehost);
|
||||
if (str == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_ssh_string(payload, str) < 0 ||
|
||||
buffer_add_u32(payload,htonl(remoteport)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ssh_string_free(str);
|
||||
str = ssh_string_from_char(sourcehost);
|
||||
if (str == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_ssh_string(payload, str) < 0 ||
|
||||
buffer_add_u32(payload,htonl(localport)) < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -2717,10 +2838,12 @@ int ssh_channel_request_send_exit_status(ssh_channel channel, int exit_status) {
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_u32(buffer, ntohl(exit_status)) < 0) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -2754,6 +2877,15 @@ int ssh_channel_request_send_exit_signal(ssh_channel channel, const char *sig, i
|
||||
ssh_string tmp = NULL;
|
||||
int rc = SSH_ERROR;
|
||||
|
||||
if(channel == NULL) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if(sig == NULL || errmsg == NULL || lang == NULL) {
|
||||
ssh_set_error_invalid(channel->session, __FUNCTION__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
if (channel->version == 1) {
|
||||
return SSH_ERROR; // TODO: Add support for SSH-v1 if possible.
|
||||
@@ -2762,36 +2894,44 @@ int ssh_channel_request_send_exit_signal(ssh_channel channel, const char *sig, i
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
tmp = ssh_string_from_char(sig);
|
||||
if (tmp == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
if (buffer_add_ssh_string(buffer, tmp) < 0) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_u8(buffer, core?1:0) < 0) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ssh_string_free(tmp);
|
||||
tmp = ssh_string_from_char(errmsg);
|
||||
if (tmp == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
if (buffer_add_ssh_string(buffer, tmp) < 0) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ssh_string_free(tmp);
|
||||
tmp = ssh_string_from_char(lang);
|
||||
if (tmp == NULL) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
if (buffer_add_ssh_string(buffer, tmp) < 0) {
|
||||
ssh_set_error_oom(channel->session);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
@@ -232,7 +232,7 @@ SSH_PACKET_CALLBACK(ssh_packet_data1){
|
||||
}
|
||||
|
||||
ssh_log(session, SSH_LOG_PROTOCOL,
|
||||
"Adding %zu bytes data in %d",
|
||||
"Adding %" PRIdS " bytes data in %d",
|
||||
ssh_string_len(str), is_stderr);
|
||||
|
||||
if (channel_default_bufferize(channel, ssh_string_data(str), ssh_string_len(str),
|
||||
|
||||
14
src/client.c
14
src/client.c
@@ -673,8 +673,6 @@ int ssh_connect(ssh_session session) {
|
||||
} else {
|
||||
ret=ssh_socket_connect(session->socket, session->host, session->port,
|
||||
session->bindaddr);
|
||||
|
||||
/*, session->timeout * 1000 + session->timeout_usec); */
|
||||
}
|
||||
if (ret == SSH_ERROR) {
|
||||
leave_function();
|
||||
@@ -687,8 +685,16 @@ int ssh_connect(ssh_session session) {
|
||||
ssh_log(session,SSH_LOG_PROTOCOL,"Socket connecting, now waiting for the callbacks to work");
|
||||
pending:
|
||||
session->pending_call_state=SSH_PENDING_CALL_CONNECT;
|
||||
if(ssh_is_blocking(session))
|
||||
ssh_handle_packets_termination(session,-1,ssh_connect_termination,session);
|
||||
if(ssh_is_blocking(session)) {
|
||||
int timeout = session->timeout * 1000 + session->timeout_usec;
|
||||
if (timeout <= 0)
|
||||
timeout = -1;
|
||||
ssh_handle_packets_termination(session,timeout,ssh_connect_termination,session);
|
||||
if(!ssh_connect_termination(session)){
|
||||
ssh_set_error(session,SSH_FATAL,"Timeout connecting to %s",session->host);
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
ssh_handle_packets_termination(session,0,ssh_connect_termination, session);
|
||||
ssh_log(session,SSH_LOG_PACKET,"ssh_connect: Actual state : %d",session->session_state);
|
||||
|
||||
@@ -327,9 +327,7 @@ int ssh_config_parse_file(ssh_session session, const char *filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (session->log_verbosity) {
|
||||
fprintf(stderr, "Reading configuration data from %s\n", filename);
|
||||
}
|
||||
ssh_log(session, SSH_LOG_RARE, "Reading configuration data from %s", filename);
|
||||
|
||||
parsing = 1;
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
|
||||
@@ -21,12 +21,17 @@
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/misc.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Only use Windows API functions available on Windows 2000 SP4 or later.
|
||||
@@ -78,14 +83,6 @@
|
||||
#error "Your system must have getaddrinfo()"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_REGCOMP
|
||||
/* don't declare gnu extended regexp's */
|
||||
#ifndef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE
|
||||
#endif
|
||||
#include <regex.h>
|
||||
#endif /* HAVE_REGCOMP */
|
||||
|
||||
#ifdef _WIN32
|
||||
void ssh_sock_set_nonblocking(socket_t sock) {
|
||||
u_long nonblocking = 1;
|
||||
@@ -118,53 +115,6 @@ void ssh_sock_set_blocking(socket_t sock) {
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef HAVE_REGCOMP
|
||||
#define IPEXPR "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
|
||||
|
||||
static regex_t *ip_regex = NULL;
|
||||
|
||||
/** @internal
|
||||
* @brief initializes and compile the regexp to be used for IP matching
|
||||
* @returns -1 on error (and error message is set)
|
||||
* @returns 0 on success
|
||||
*/
|
||||
int ssh_regex_init(){
|
||||
if(ip_regex==NULL){
|
||||
int err;
|
||||
regex_t *regex=malloc(sizeof (regex_t));
|
||||
ZERO_STRUCTP(regex);
|
||||
err = regcomp(regex, IPEXPR, REG_EXTENDED | REG_NOSUB);
|
||||
if(err != 0){
|
||||
char buffer[128];
|
||||
regerror(err,regex,buffer,sizeof(buffer));
|
||||
fprintf(stderr,"Error while compiling regular expression : %s\n",buffer);
|
||||
SAFE_FREE(regex);
|
||||
return -1;
|
||||
}
|
||||
ip_regex=regex;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief clean up the IP regexp
|
||||
*/
|
||||
void ssh_regex_finalize(){
|
||||
if(ip_regex){
|
||||
regfree(ip_regex);
|
||||
SAFE_FREE(ip_regex);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* HAVE_REGCOMP */
|
||||
int ssh_regex_init(){
|
||||
return 0;
|
||||
}
|
||||
void ssh_regex_finalize(){
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int ssh_connect_socket_close(socket_t s){
|
||||
#ifdef _WIN32
|
||||
return closesocket(s);
|
||||
@@ -194,13 +144,13 @@ static int getai(ssh_session session, const char *host, int port, struct addrinf
|
||||
hints.ai_flags=AI_NUMERICSERV;
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_REGCOMP
|
||||
if(regexec(ip_regex,host,0,NULL,0) == 0){
|
||||
|
||||
if (ssh_is_ipaddr(host)) {
|
||||
/* this is an IP address */
|
||||
ssh_log(session,SSH_LOG_PACKET,"host %s matches an IP address",host);
|
||||
hints.ai_flags |= AI_NUMERICHOST;
|
||||
}
|
||||
#endif
|
||||
|
||||
return getaddrinfo(host, service, &hints, ai);
|
||||
}
|
||||
|
||||
@@ -472,7 +422,7 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
*
|
||||
* @param[in] timeout A timeout for the select.
|
||||
*
|
||||
* @return -1 if an error occured. E_INTR if it was interrupted, in
|
||||
* @return -1 if an error occured. SSH_EINTR if it was interrupted, in
|
||||
* that case, just restart it.
|
||||
*
|
||||
* @warning libssh is not threadsafe here. That means that if a signal is caught
|
||||
|
||||
8
src/dh.c
8
src/dh.c
@@ -140,6 +140,7 @@ int ssh_crypto_init(void) {
|
||||
}
|
||||
bignum_bin2bn(p_value, P_LEN, p);
|
||||
OpenSSL_add_all_algorithms();
|
||||
|
||||
#endif
|
||||
|
||||
ssh_crypto_initialized = 1;
|
||||
@@ -154,8 +155,13 @@ void ssh_crypto_finalize(void) {
|
||||
g = NULL;
|
||||
bignum_free(p);
|
||||
p = NULL;
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
gcry_control(GCRYCTL_TERM_SECMEM);
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
EVP_cleanup();
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
#endif
|
||||
ssh_crypto_initialized=0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
16
src/init.c
16
src/init.c
@@ -57,8 +57,6 @@ int ssh_init(void) {
|
||||
return -1;
|
||||
if(ssh_socket_init())
|
||||
return -1;
|
||||
if(ssh_regex_init())
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -73,18 +71,12 @@ int ssh_init(void) {
|
||||
@returns 0 otherwise
|
||||
*/
|
||||
int ssh_finalize(void) {
|
||||
ssh_threads_finalize();
|
||||
ssh_regex_finalize();
|
||||
ssh_crypto_finalize();
|
||||
ssh_socket_cleanup();
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
gcry_control(GCRYCTL_TERM_SECMEM);
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
EVP_cleanup();
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
/* It is important to finalize threading after CRYPTO because
|
||||
* it still depends on it */
|
||||
ssh_threads_finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -761,7 +761,7 @@ SSH_PACKET_CALLBACK(ssh_packet_publickey1){
|
||||
}
|
||||
|
||||
bits = ssh_string_len(enc_session) * 8 - 7;
|
||||
ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %zu bytes encrypted session",
|
||||
ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %" PRIdS " bytes encrypted session",
|
||||
bits, ssh_string_len(enc_session));
|
||||
bits = htons(bits);
|
||||
/* the encrypted mpint */
|
||||
|
||||
@@ -677,11 +677,15 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
DSA *dsa = NULL;
|
||||
RSA *rsa = NULL;
|
||||
BIO *bio = NULL;
|
||||
#endif
|
||||
/* TODO Implement to read both DSA and RSA at once. */
|
||||
|
||||
/* needed for openssl initialization */
|
||||
ssh_init();
|
||||
if (ssh_init() < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssh_log(session, SSH_LOG_RARE, "Trying to open %s", filename);
|
||||
file = fopen(filename,"r");
|
||||
if (file == NULL) {
|
||||
@@ -690,6 +694,15 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
bio = BIO_new_file(filename,"r");
|
||||
if (bio == NULL) {
|
||||
fclose(file);
|
||||
ssh_set_error(session, SSH_FATAL, "Could not create BIO.");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
ssh_log(session, SSH_LOG_RARE, "Trying to read %s, passphase=%s, authcb=%s",
|
||||
filename, passphrase ? "true" : "false",
|
||||
session->callbacks && session->callbacks->auth_function ? "true" : "false");
|
||||
@@ -726,15 +739,16 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
||||
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
if (session->callbacks && session->callbacks->auth_function) {
|
||||
dsa = PEM_read_DSAPrivateKey(file, NULL, pem_get_password, session);
|
||||
dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, pem_get_password, session);
|
||||
} else { /* authcb */
|
||||
/* openssl uses its own callback to get the passphrase here */
|
||||
dsa = PEM_read_DSAPrivateKey(file, NULL, NULL, NULL);
|
||||
dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, NULL);
|
||||
} /* authcb */
|
||||
} else { /* passphrase */
|
||||
dsa = PEM_read_DSAPrivateKey(file, NULL, NULL, (void *) passphrase);
|
||||
dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, (void *) passphrase);
|
||||
}
|
||||
|
||||
BIO_free(bio);
|
||||
fclose(file);
|
||||
if (dsa == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
@@ -766,15 +780,16 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
||||
ssh_set_error(session,SSH_FATAL, "Parsing private key %s", filename);
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
if (session->callbacks && session->callbacks->auth_function) {
|
||||
rsa = PEM_read_RSAPrivateKey(file, NULL, pem_get_password, session);
|
||||
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, pem_get_password, session);
|
||||
} else { /* authcb */
|
||||
/* openssl uses its own callback to get the passphrase here */
|
||||
rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL);
|
||||
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
|
||||
} /* authcb */
|
||||
} else { /* passphrase */
|
||||
rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, (void *) passphrase);
|
||||
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, (void *) passphrase);
|
||||
}
|
||||
|
||||
BIO_free(bio);
|
||||
fclose(file);
|
||||
|
||||
if (rsa == NULL) {
|
||||
@@ -786,6 +801,9 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
BIO_free(bio);
|
||||
#endif
|
||||
fclose(file);
|
||||
ssh_set_error(session, SSH_FATAL, "Invalid private key type %d", type);
|
||||
return NULL;
|
||||
@@ -828,22 +846,31 @@ enum ssh_keytypes_e ssh_privatekey_type(ssh_private_key privatekey){
|
||||
ssh_private_key _privatekey_from_file(void *session, const char *filename,
|
||||
int type) {
|
||||
ssh_private_key privkey = NULL;
|
||||
FILE *file = NULL;
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
FILE *file = NULL;
|
||||
gcry_sexp_t dsa = NULL;
|
||||
gcry_sexp_t rsa = NULL;
|
||||
int valid;
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
DSA *dsa = NULL;
|
||||
RSA *rsa = NULL;
|
||||
BIO *bio = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
file = fopen(filename,"r");
|
||||
if (file == NULL) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Error opening %s: %s", filename, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
bio = BIO_new_file(filename,"r");
|
||||
if (bio == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not create BIO.");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
@@ -855,14 +882,16 @@ ssh_private_key _privatekey_from_file(void *session, const char *filename,
|
||||
if (!valid) {
|
||||
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
dsa = PEM_read_DSAPrivateKey(file, NULL, NULL, NULL);
|
||||
dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, NULL);
|
||||
|
||||
fclose(file);
|
||||
BIO_free(bio);
|
||||
|
||||
if (dsa == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Parsing private key %s: %s",
|
||||
filename, ERR_error_string(ERR_get_error(), NULL));
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
@@ -876,19 +905,26 @@ ssh_private_key _privatekey_from_file(void *session, const char *filename,
|
||||
if (!valid) {
|
||||
ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL);
|
||||
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
|
||||
|
||||
fclose(file);
|
||||
BIO_free(bio);
|
||||
|
||||
if (rsa == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Parsing private key %s: %s",
|
||||
filename, ERR_error_string(ERR_get_error(), NULL));
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
fclose(file);
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
BIO_free(bio);
|
||||
#endif
|
||||
ssh_set_error(session, SSH_FATAL, "Invalid private key type %d", type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -597,7 +597,9 @@ error:
|
||||
ssh_string_free(n);
|
||||
|
||||
return rc;
|
||||
#if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
static int rsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) {
|
||||
@@ -665,7 +667,9 @@ error:
|
||||
ssh_string_free(n);
|
||||
|
||||
return rc;
|
||||
#if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Convert a public_key object into a a SSH string.
|
||||
|
||||
18
src/legacy.c
18
src/legacy.c
@@ -24,7 +24,9 @@
|
||||
* compatibility
|
||||
*/
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include "config.h"
|
||||
|
||||
#include <libssh/priv.h>
|
||||
#include <libssh/server.h>
|
||||
#include <libssh/buffer.h>
|
||||
|
||||
@@ -240,4 +242,18 @@ char *string_to_char(ssh_string str){
|
||||
int ssh_accept(ssh_session session) {
|
||||
return ssh_handle_key_exchange(session);
|
||||
}
|
||||
|
||||
int channel_write_stderr(ssh_channel channel, const void *data, uint32_t len) {
|
||||
return ssh_channel_write(channel, data, len);
|
||||
}
|
||||
|
||||
/** @deprecated
|
||||
* @brief Interface previously exported by error.
|
||||
*/
|
||||
ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype){
|
||||
(void) packettype;
|
||||
ssh_set_error(session, SSH_FATAL, "ssh_message_retrieve: obsolete libssh call");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* WITH_SERVER */
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -67,6 +69,31 @@ static ssh_message ssh_message_new(ssh_session session){
|
||||
return msg;
|
||||
}
|
||||
|
||||
static int ssh_execute_message_callback(ssh_session session, ssh_message msg) {
|
||||
int ret;
|
||||
if(session->ssh_message_callback != NULL) {
|
||||
ret = session->ssh_message_callback(session, msg,
|
||||
session->ssh_message_callback_data);
|
||||
if(ret == 1) {
|
||||
ret = ssh_message_reply_default(msg);
|
||||
ssh_message_free(msg);
|
||||
if(ret != SSH_OK) {
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
ssh_message_free(msg);
|
||||
}
|
||||
} else {
|
||||
ret = ssh_message_reply_default(msg);
|
||||
ssh_message_free(msg);
|
||||
if(ret != SSH_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
@@ -77,12 +104,16 @@ static ssh_message ssh_message_new(ssh_session session){
|
||||
* @param[in] message The message to add to the queue.
|
||||
*/
|
||||
void ssh_message_queue(ssh_session session, ssh_message message){
|
||||
if(message){
|
||||
if(session->ssh_message_list == NULL){
|
||||
session->ssh_message_list=ssh_list_new();
|
||||
if(message) {
|
||||
if(session->ssh_message_list == NULL) {
|
||||
if(session->ssh_message_callback != NULL) {
|
||||
ssh_execute_message_callback(session, message);
|
||||
return;
|
||||
}
|
||||
session->ssh_message_list = ssh_list_new();
|
||||
}
|
||||
ssh_list_append(session->ssh_message_list, message);
|
||||
}
|
||||
ssh_list_append(session->ssh_message_list, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
180
src/misc.c
180
src/misc.c
@@ -22,14 +22,22 @@
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
/* This is needed for a standard getpwuid_r on opensolaris */
|
||||
#define _POSIX_PTHREAD_SEMANTICS
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#ifndef HAVE_CLOCK_GETTIME
|
||||
#include <sys/time.h>
|
||||
#endif /* HAVE_CLOCK_GETTIME */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -37,6 +45,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -136,7 +145,7 @@ char *ssh_get_local_username(ssh_session session) {
|
||||
/* get the size */
|
||||
GetUserName(NULL, &size);
|
||||
|
||||
user = malloc(size);
|
||||
user = (char *) malloc(size);
|
||||
if (user == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
@@ -148,6 +157,49 @@ char *ssh_get_local_username(ssh_session session) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ssh_is_ipaddr_v4(const char *str) {
|
||||
struct sockaddr_storage ss;
|
||||
int sslen = sizeof(ss);
|
||||
int rc = SOCKET_ERROR;
|
||||
|
||||
/* WSAStringToAddressA thinks that 0.0.0 is a valid IP */
|
||||
if (strlen(str) < 7) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = WSAStringToAddressA((LPSTR) str,
|
||||
AF_INET,
|
||||
NULL,
|
||||
(struct sockaddr*)&ss,
|
||||
&sslen);
|
||||
if (rc == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ssh_is_ipaddr(const char *str) {
|
||||
int rc = SOCKET_ERROR;
|
||||
|
||||
if (strchr(str, ':')) {
|
||||
struct sockaddr_storage ss;
|
||||
int sslen = sizeof(ss);
|
||||
|
||||
/* TODO link-local (IP:v6:addr%ifname). */
|
||||
rc = WSAStringToAddressA((LPSTR) str,
|
||||
AF_INET6,
|
||||
NULL,
|
||||
(struct sockaddr*)&ss,
|
||||
&sslen);
|
||||
if (rc == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ssh_is_ipaddr_v4(str);
|
||||
}
|
||||
#else /* _WIN32 */
|
||||
|
||||
#ifndef NSS_BUFLEN_PASSWD
|
||||
@@ -203,6 +255,35 @@ char *ssh_get_local_username(ssh_session session) {
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
int ssh_is_ipaddr_v4(const char *str) {
|
||||
int rc = -1;
|
||||
struct in_addr dest;
|
||||
|
||||
rc = inet_pton(AF_INET, str, &dest);
|
||||
if (rc > 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ssh_is_ipaddr(const char *str) {
|
||||
int rc = -1;
|
||||
|
||||
if (strchr(str, ':')) {
|
||||
struct in6_addr dest6;
|
||||
|
||||
/* TODO link-local (IP:v6:addr%ifname). */
|
||||
rc = inet_pton(AF_INET6, str, &dest6);
|
||||
if (rc > 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ssh_is_ipaddr_v4(str);
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
uint64_t ntohll(uint64_t a) {
|
||||
@@ -779,6 +860,99 @@ int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* try the Monotonic clock if possible for perfs reasons */
|
||||
#ifdef _POSIX_MONOTONIC_CLOCK
|
||||
#define CLOCK CLOCK_MONOTONIC
|
||||
#else
|
||||
#define CLOCK CLOCK_REALTIME
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @brief initializes a timestamp to the current time
|
||||
* @param[out] ts pointer to an allocated ssh_timestamp structure
|
||||
*/
|
||||
void ssh_timestamp_init(struct ssh_timestamp *ts){
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
struct timespec tp;
|
||||
clock_gettime(CLOCK, &tp);
|
||||
ts->useconds = tp.tv_nsec / 1000;
|
||||
#else
|
||||
struct timeval tp;
|
||||
gettimeofday(&tp, NULL);
|
||||
ts->useconds = tp.tv_usec;
|
||||
#endif
|
||||
ts->seconds = tp.tv_sec;
|
||||
}
|
||||
|
||||
#undef CLOCK
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @brief gets the time difference between two timestamps in ms
|
||||
* @param[in] old older value
|
||||
* @param[in] new newer value
|
||||
* @returns difference in milliseconds
|
||||
*/
|
||||
|
||||
static int ssh_timestamp_difference(struct ssh_timestamp *old,
|
||||
struct ssh_timestamp *new){
|
||||
long seconds, usecs, msecs;
|
||||
seconds = new->seconds - old->seconds;
|
||||
usecs = new->useconds - old->useconds;
|
||||
if (usecs < 0){
|
||||
seconds--;
|
||||
usecs += 1000000;
|
||||
}
|
||||
msecs = seconds * 1000 + usecs/1000;
|
||||
return msecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @brief Checks if a timeout is elapsed, in function of a previous
|
||||
* timestamp and an assigned timeout
|
||||
* @param[in] ts pointer to an existing timestamp
|
||||
* @param[in] timeout timeout in milliseconds. Negative values mean infinite
|
||||
* timeout
|
||||
* @returns 1 if timeout is elapsed
|
||||
* 0 otherwise
|
||||
*/
|
||||
int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout) {
|
||||
struct ssh_timestamp now;
|
||||
if(timeout < 0)
|
||||
return 0; // -1 means infinite timeout
|
||||
if(timeout == 0)
|
||||
return 1; // 0 means no timeout
|
||||
ssh_timestamp_init(&now);
|
||||
|
||||
if(ssh_timestamp_difference(ts,&now) >= timeout)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief updates a timeout value so it reflects the remaining time
|
||||
* @param[in] ts pointer to an existing timestamp
|
||||
* @param[in] timeout timeout in milliseconds. Negative values mean infinite
|
||||
* timeout
|
||||
* @returns remaining time in milliseconds, 0 if elapsed, -1 if never.
|
||||
*/
|
||||
int ssh_timeout_update(struct ssh_timestamp *ts, int timeout){
|
||||
struct ssh_timestamp now;
|
||||
int ms, ret;
|
||||
if(timeout == 0)
|
||||
return 0;
|
||||
if(timeout==-1)
|
||||
return -1;
|
||||
ssh_timestamp_init(&now);
|
||||
ms = ssh_timestamp_difference(ts,&now);
|
||||
if(ms < 0)
|
||||
ms = 0;
|
||||
ret = timeout - ms;
|
||||
return ret >= 0 ? ret: 0;
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/* vim: set ts=4 sw=4 et cindent: */
|
||||
|
||||
@@ -125,7 +125,7 @@ struct ssh_pcap_file_struct {
|
||||
ssh_pcap_file ssh_pcap_file_new(){
|
||||
struct ssh_pcap_file_struct *pcap;
|
||||
|
||||
pcap = malloc(sizeof(struct ssh_pcap_file_struct));
|
||||
pcap = (struct ssh_pcap_file_struct *) malloc(sizeof(struct ssh_pcap_file_struct));
|
||||
if (pcap == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -228,7 +228,7 @@ void ssh_pcap_file_free(ssh_pcap_file pcap){
|
||||
*/
|
||||
|
||||
ssh_pcap_context ssh_pcap_context_new(ssh_session session){
|
||||
ssh_pcap_context ctx=malloc(sizeof(struct ssh_pcap_context_struct));
|
||||
ssh_pcap_context ctx = (struct ssh_pcap_context_struct *) malloc(sizeof(struct ssh_pcap_context_struct));
|
||||
if(ctx==NULL){
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
|
||||
62
src/poll.c
62
src/poll.c
@@ -105,29 +105,6 @@ static poll_fn ssh_poll_emu;
|
||||
#include <time.h>
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
|
||||
#if (_WIN32_WINNT < 0x0600)
|
||||
typedef struct ssh_pollfd_struct WSAPOLLFD;
|
||||
#endif
|
||||
|
||||
typedef int (WSAAPI* WSAPoll_FunctionType)(WSAPOLLFD fdarray[],
|
||||
ULONG nfds,
|
||||
INT timeout
|
||||
);
|
||||
|
||||
static WSAPoll_FunctionType wsa_poll;
|
||||
|
||||
int win_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
|
||||
if (wsa_poll) {
|
||||
return (wsa_poll)((WSAPOLLFD *) fds, nfds, timeout);
|
||||
}
|
||||
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
#define WS2_LIBRARY "ws2_32.dll"
|
||||
static HINSTANCE hlib;
|
||||
|
||||
#else /* _WIN32 */
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -261,30 +238,10 @@ static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
|
||||
|
||||
void ssh_poll_init(void) {
|
||||
ssh_poll_emu = bsd_poll;
|
||||
|
||||
#ifdef _WIN32
|
||||
hlib = LoadLibrary(WS2_LIBRARY);
|
||||
if (hlib != NULL) {
|
||||
wsa_poll = (WSAPoll_FunctionType) (void *) GetProcAddress(hlib, "WSAPoll");
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
if (wsa_poll == NULL) {
|
||||
ssh_poll_emu = bsd_poll;
|
||||
} else {
|
||||
ssh_poll_emu = win_poll;
|
||||
}
|
||||
}
|
||||
|
||||
void ssh_poll_cleanup(void) {
|
||||
ssh_poll_emu = bsd_poll;
|
||||
#ifdef _WIN32
|
||||
wsa_poll = NULL;
|
||||
|
||||
FreeLibrary(hlib);
|
||||
|
||||
hlib = NULL;
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
|
||||
@@ -298,8 +255,9 @@ int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
|
||||
*
|
||||
* @param fd Socket that will be polled.
|
||||
* @param events Poll events that will be monitored for the socket. i.e.
|
||||
* POLLIN, POLLPRI, POLLOUT, POLLERR, POLLHUP, POLLNVAL
|
||||
* POLLIN, POLLPRI, POLLOUT
|
||||
* @param cb Function to be called if any of the events are set.
|
||||
*
|
||||
* @param userdata Userdata to be passed to the callback function. NULL if
|
||||
* not needed.
|
||||
*
|
||||
@@ -490,8 +448,13 @@ void ssh_poll_ctx_free(ssh_poll_ctx ctx) {
|
||||
socket_t fd = ctx->pollfds[i].fd;
|
||||
|
||||
/* force poll object removal */
|
||||
if (p->cb(p, fd, POLLERR, p->cb_data) < 0) {
|
||||
used = ctx->polls_used;
|
||||
if (p->cb && p->cb(p, fd, POLLERR, p->cb_data) < 0) {
|
||||
if(ctx->polls_used < used) {
|
||||
used = ctx->polls_used;
|
||||
} else {
|
||||
/* nothing to do */
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
@@ -622,6 +585,7 @@ void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p) {
|
||||
* the poll() function.
|
||||
* @returns SSH_OK No error.
|
||||
* SSH_ERROR Error happened during the poll.
|
||||
* SSH_AGAIN Timeout occured
|
||||
*/
|
||||
|
||||
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
|
||||
@@ -636,9 +600,9 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
|
||||
|
||||
rc = ssh_poll(ctx->pollfds, ctx->polls_used, timeout);
|
||||
if(rc < 0)
|
||||
rc=SSH_ERROR;
|
||||
if(rc <= 0)
|
||||
return rc;
|
||||
return SSH_ERROR;
|
||||
if (rc == 0)
|
||||
return SSH_AGAIN;
|
||||
used = ctx->polls_used;
|
||||
for (i = 0; i < used && rc > 0; ) {
|
||||
if (!ctx->pollfds[i].revents) {
|
||||
|
||||
@@ -148,7 +148,7 @@ int ssh_scp_close(ssh_scp scp){
|
||||
*/
|
||||
while(!ssh_channel_is_eof(scp->channel)){
|
||||
err=ssh_channel_read(scp->channel,buffer,sizeof(buffer),0);
|
||||
if(err==SSH_ERROR)
|
||||
if(err==SSH_ERROR || err==0)
|
||||
break;
|
||||
}
|
||||
if(ssh_channel_close(scp->channel) == SSH_ERROR){
|
||||
|
||||
@@ -104,7 +104,7 @@ static int server_set_kex(ssh_session session) {
|
||||
}
|
||||
}
|
||||
|
||||
server->methods = malloc(10 * sizeof(char **));
|
||||
server->methods = (char **) malloc(10 * sizeof(char **));
|
||||
if (server->methods == NULL) {
|
||||
return -1;
|
||||
}
|
||||
@@ -480,7 +480,7 @@ int ssh_handle_key_exchange(ssh_session session) {
|
||||
* SSH_SESSION_STATE_ERROR
|
||||
*/
|
||||
ssh_handle_packets(session,-1);
|
||||
ssh_log(session,SSH_LOG_PACKET, "ssh_accept: Actual state : %d",
|
||||
ssh_log(session,SSH_LOG_PACKET, "ssh_handle_key_exchange: Actual state : %d",
|
||||
session->session_state);
|
||||
}
|
||||
|
||||
@@ -616,10 +616,13 @@ static int ssh_message_service_request_reply_default(ssh_message msg) {
|
||||
|
||||
int ssh_message_service_reply_success(ssh_message msg) {
|
||||
struct ssh_string_struct *service;
|
||||
ssh_session session=msg->session;
|
||||
ssh_session session;
|
||||
|
||||
if (msg == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
session = msg->session;
|
||||
|
||||
ssh_log(session, SSH_LOG_PACKET,
|
||||
"Sending a SERVICE_ACCEPT for service %s", msg->service_request.service);
|
||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_ACCEPT) < 0) {
|
||||
|
||||
@@ -297,6 +297,40 @@ int ssh_is_blocking(ssh_session session){
|
||||
return (session->flags&SSH_SESSION_FLAG_BLOCKING) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Blocking flush of the outgoing buffer
|
||||
* @param[in] session The SSH session
|
||||
* @param[in] timeout Set an upper limit on the time for which this function
|
||||
* will block, in milliseconds. Specifying a negative value
|
||||
* means an infinite timeout. This parameter is passed to
|
||||
* the poll() function.
|
||||
* @returns SSH_OK on success, SSH_AGAIN if timeout occurred,
|
||||
* SSH_ERROR otherwise.
|
||||
*/
|
||||
|
||||
int ssh_blocking_flush(ssh_session session, int timeout){
|
||||
ssh_socket s;
|
||||
struct ssh_timestamp ts;
|
||||
int rc = SSH_OK;
|
||||
if(session==NULL)
|
||||
return SSH_ERROR;
|
||||
|
||||
enter_function();
|
||||
s=session->socket;
|
||||
ssh_timestamp_init(&ts);
|
||||
while (ssh_socket_buffered_write_bytes(s) > 0 && session->alive) {
|
||||
rc=ssh_handle_packets(session, timeout);
|
||||
if(ssh_timeout_elapsed(&ts,timeout)){
|
||||
rc=SSH_AGAIN;
|
||||
break;
|
||||
}
|
||||
timeout = ssh_timeout_update(&ts, timeout);
|
||||
}
|
||||
|
||||
leave_function();
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if we are connected.
|
||||
*
|
||||
@@ -390,11 +424,14 @@ void ssh_set_fd_except(ssh_session session) {
|
||||
int ssh_handle_packets(ssh_session session, int timeout) {
|
||||
ssh_poll_handle spoll_in,spoll_out;
|
||||
ssh_poll_ctx ctx;
|
||||
int rc;
|
||||
if(session==NULL || session->socket==NULL)
|
||||
return SSH_ERROR;
|
||||
enter_function();
|
||||
spoll_in=ssh_socket_get_poll_handle_in(session->socket);
|
||||
spoll_out=ssh_socket_get_poll_handle_out(session->socket);
|
||||
if(session->server)
|
||||
ssh_poll_add_events(spoll_in, POLLIN);
|
||||
ctx=ssh_poll_get_ctx(spoll_in);
|
||||
if(ctx==NULL){
|
||||
ctx=ssh_poll_get_default_ctx(session);
|
||||
@@ -402,7 +439,9 @@ int ssh_handle_packets(ssh_session session, int timeout) {
|
||||
if(spoll_in != spoll_out)
|
||||
ssh_poll_ctx_add(ctx,spoll_out);
|
||||
}
|
||||
ssh_poll_ctx_dopoll(ctx,timeout);
|
||||
rc = ssh_poll_ctx_dopoll(ctx,timeout);
|
||||
if(rc == SSH_ERROR)
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
leave_function();
|
||||
if (session->session_state != SSH_SESSION_STATE_ERROR)
|
||||
return SSH_OK;
|
||||
@@ -432,17 +471,19 @@ int ssh_handle_packets(ssh_session session, int timeout) {
|
||||
int ssh_handle_packets_termination(ssh_session session, int timeout,
|
||||
ssh_termination_function fct, void *user){
|
||||
int ret = SSH_ERROR;
|
||||
struct ssh_timestamp ts;
|
||||
ssh_timestamp_init(&ts);
|
||||
|
||||
while(!fct(user)){
|
||||
ret = ssh_handle_packets(session, timeout);
|
||||
if(ret == SSH_ERROR)
|
||||
return SSH_ERROR;
|
||||
if(timeout == 0){
|
||||
if(fct(user))
|
||||
return SSH_OK;
|
||||
else
|
||||
return SSH_AGAIN;
|
||||
if(fct(user)) {
|
||||
return SSH_OK;
|
||||
} else if (ssh_timeout_elapsed(&ts, timeout)) {
|
||||
return SSH_AGAIN;
|
||||
}
|
||||
/* TODO: verify that total timeout has not expired and then return SSH_AGAIN */
|
||||
timeout = ssh_timeout_update(&ts,timeout);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -552,6 +593,7 @@ SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback){
|
||||
|
||||
ssh_socket_close(session->socket);
|
||||
session->alive = 0;
|
||||
session->session_state= SSH_SESSION_STATE_ERROR;
|
||||
/* TODO: handle a graceful disconnect */
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
11
src/sftp.c
11
src/sftp.c
@@ -1817,7 +1817,7 @@ ssize_t sftp_read(sftp_file handle, void *buf, size_t count) {
|
||||
if (ssh_string_len(datastring) > count) {
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received a too big DATA packet from sftp server: "
|
||||
"%zu and asked for %zu",
|
||||
"%" PRIdS " and asked for %" PRIdS,
|
||||
ssh_string_len(datastring), count);
|
||||
ssh_string_free(datastring);
|
||||
return -1;
|
||||
@@ -1938,7 +1938,7 @@ int sftp_async_read(sftp_file file, void *data, uint32_t size, uint32_t id){
|
||||
if (ssh_string_len(datastring) > size) {
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received a too big DATA packet from sftp server: "
|
||||
"%zu and asked for %u",
|
||||
"%" PRIdS " and asked for %u",
|
||||
ssh_string_len(datastring), size);
|
||||
ssh_string_free(datastring);
|
||||
sftp_leave_function();
|
||||
@@ -2054,6 +2054,7 @@ int sftp_seek(sftp_file file, uint32_t new_offset) {
|
||||
}
|
||||
|
||||
file->offset = new_offset;
|
||||
file->eof = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2064,6 +2065,7 @@ int sftp_seek64(sftp_file file, uint64_t new_offset) {
|
||||
}
|
||||
|
||||
file->offset = new_offset;
|
||||
file->eof = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2080,6 +2082,7 @@ uint64_t sftp_tell64(sftp_file file) {
|
||||
/* Rewinds the position of the file pointer to the beginning of the file.*/
|
||||
void sftp_rewind(sftp_file file) {
|
||||
file->offset = 0;
|
||||
file->eof = 0;
|
||||
}
|
||||
|
||||
/* code written by Nick */
|
||||
@@ -2109,10 +2112,12 @@ int sftp_unlink(sftp_session sftp, const char *file) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
ssh_buffer_free(buffer);
|
||||
ssh_string_free(filename);
|
||||
return -1;
|
||||
}
|
||||
if (sftp_packet_write(sftp, SSH_FXP_REMOVE, buffer) < 0) {
|
||||
ssh_buffer_free(buffer);
|
||||
ssh_string_free(filename);
|
||||
return -1;
|
||||
}
|
||||
ssh_string_free(filename);
|
||||
ssh_buffer_free(buffer);
|
||||
@@ -2846,7 +2851,7 @@ sftp_statvfs_t sftp_statvfs(sftp_session sftp, const char *path) {
|
||||
ssh_set_error(sftp,SSH_REQUEST_DENIED,"sftp version %d does not support sftp_statvfs",sftp->version);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
if (buffer == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "libssh/misc.h"
|
||||
|
||||
sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
||||
ssh_session session = sftp->session;
|
||||
sftp_packet packet;
|
||||
sftp_client_message msg;
|
||||
ssh_buffer payload;
|
||||
@@ -44,12 +45,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
||||
|
||||
msg = malloc(sizeof (struct sftp_client_message_struct));
|
||||
if (msg == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
ZERO_STRUCTP(msg);
|
||||
|
||||
packet = sftp_packet_read(sftp);
|
||||
if (packet == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -65,6 +68,7 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
||||
case SSH_FXP_READDIR:
|
||||
msg->handle = buffer_get_ssh_string(payload);
|
||||
if (msg->handle == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -72,6 +76,7 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
||||
case SSH_FXP_READ:
|
||||
msg->handle = buffer_get_ssh_string(payload);
|
||||
if (msg->handle == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -81,12 +86,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
||||
case SSH_FXP_WRITE:
|
||||
msg->handle = buffer_get_ssh_string(payload);
|
||||
if (msg->handle == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
buffer_get_u64(payload, &msg->offset);
|
||||
msg->data = buffer_get_ssh_string(payload);
|
||||
if (msg->data == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -98,12 +105,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
||||
case SSH_FXP_REALPATH:
|
||||
tmp = buffer_get_ssh_string(payload);
|
||||
if (tmp == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
msg->filename = ssh_string_to_char(tmp);
|
||||
ssh_string_free(tmp);
|
||||
if (msg->filename == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -112,17 +121,20 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
||||
case SSH_FXP_SYMLINK:
|
||||
tmp = buffer_get_ssh_string(payload);
|
||||
if (tmp == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
msg->filename = ssh_string_to_char(tmp);
|
||||
ssh_string_free(tmp);
|
||||
if (msg->filename == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
msg->data = buffer_get_ssh_string(payload);
|
||||
if (msg->data == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -131,17 +143,20 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
||||
case SSH_FXP_SETSTAT:
|
||||
tmp = buffer_get_ssh_string(payload);
|
||||
if (tmp == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
msg->filename=ssh_string_to_char(tmp);
|
||||
ssh_string_free(tmp);
|
||||
if (msg->filename == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
msg->attr = sftp_parse_attr(sftp, payload, 0);
|
||||
if (msg->attr == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -149,11 +164,13 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
||||
case SSH_FXP_FSETSTAT:
|
||||
msg->handle = buffer_get_ssh_string(payload);
|
||||
if (msg->handle == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
msg->attr = sftp_parse_attr(sftp, payload, 0);
|
||||
if (msg->attr == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -162,12 +179,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
||||
case SSH_FXP_STAT:
|
||||
tmp = buffer_get_ssh_string(payload);
|
||||
if (tmp == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
msg->filename = ssh_string_to_char(tmp);
|
||||
ssh_string_free(tmp);
|
||||
if (msg->filename == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -178,31 +197,38 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
|
||||
case SSH_FXP_OPEN:
|
||||
tmp=buffer_get_ssh_string(payload);
|
||||
if (tmp == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
msg->filename = ssh_string_to_char(tmp);
|
||||
ssh_string_free(tmp);
|
||||
if (msg->filename == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
buffer_get_u32(payload,&msg->flags);
|
||||
msg->attr = sftp_parse_attr(sftp, payload, 0);
|
||||
if (msg->attr == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
case SSH_FXP_FSTAT:
|
||||
msg->handle = buffer_get_ssh_string(payload);
|
||||
if (msg->handle == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
buffer_get_u32(payload, &msg->flags);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Received unhandled sftp message %d\n", msg->type);
|
||||
ssh_set_error(sftp->session, SSH_FATAL,
|
||||
"Received unhandled sftp message %d\n", msg->type);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
msg->flags = ntohl(msg->flags);
|
||||
|
||||
84
src/socket.c
84
src/socket.c
@@ -91,6 +91,8 @@ struct ssh_socket_struct {
|
||||
ssh_poll_handle poll_out;
|
||||
};
|
||||
|
||||
static int sockets_initialized = 0;
|
||||
|
||||
static int ssh_socket_unbuffered_read(ssh_socket s, void *buffer, uint32_t len);
|
||||
static int ssh_socket_unbuffered_write(ssh_socket s, const void *buffer,
|
||||
uint32_t len);
|
||||
@@ -100,16 +102,20 @@ static int ssh_socket_unbuffered_write(ssh_socket s, const void *buffer,
|
||||
* \brief inits the socket system (windows specific)
|
||||
*/
|
||||
int ssh_socket_init(void) {
|
||||
if (sockets_initialized == 0) {
|
||||
#ifdef _WIN32
|
||||
struct WSAData wsaData;
|
||||
struct WSAData wsaData;
|
||||
|
||||
/* Initiates use of the Winsock DLL by a process. */
|
||||
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
|
||||
return -1;
|
||||
}
|
||||
/* Initiates use of the Winsock DLL by a process. */
|
||||
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
ssh_poll_init();
|
||||
ssh_poll_init();
|
||||
|
||||
sockets_initialized = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -118,7 +124,13 @@ int ssh_socket_init(void) {
|
||||
* @brief Cleanup the socket system.
|
||||
*/
|
||||
void ssh_socket_cleanup(void) {
|
||||
if (sockets_initialized == 1) {
|
||||
ssh_poll_cleanup();
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
sockets_initialized = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -131,6 +143,7 @@ ssh_socket ssh_socket_new(ssh_session session) {
|
||||
|
||||
s = malloc(sizeof(struct ssh_socket_struct));
|
||||
if (s == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
s->fd_in = SSH_INVALID_SOCKET;
|
||||
@@ -140,11 +153,13 @@ ssh_socket ssh_socket_new(ssh_session session) {
|
||||
s->session = session;
|
||||
s->in_buffer = ssh_buffer_new();
|
||||
if (s->in_buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
SAFE_FREE(s);
|
||||
return NULL;
|
||||
}
|
||||
s->out_buffer=ssh_buffer_new();
|
||||
if (s->out_buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_free(s->in_buffer);
|
||||
SAFE_FREE(s);
|
||||
return NULL;
|
||||
@@ -215,7 +230,7 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
|
||||
/* Check if we are in a connecting state */
|
||||
if(s->state==SSH_SOCKET_CONNECTING){
|
||||
s->state=SSH_SOCKET_ERROR;
|
||||
getsockopt(fd,SOL_SOCKET,SO_ERROR,(void *)&err,&errlen);
|
||||
getsockopt(fd,SOL_SOCKET,SO_ERROR,(char *)&err,&errlen);
|
||||
s->last_errno=err;
|
||||
ssh_socket_close(s);
|
||||
if(s->callbacks && s->callbacks->connected)
|
||||
@@ -231,20 +246,32 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
|
||||
s->read_wontblock=1;
|
||||
r=ssh_socket_unbuffered_read(s,buffer,sizeof(buffer));
|
||||
if(r<0){
|
||||
if(p != NULL)
|
||||
ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN);
|
||||
if(p != NULL) {
|
||||
ssh_poll_remove_events(p, POLLIN);
|
||||
}
|
||||
if(s->callbacks && s->callbacks->exception){
|
||||
s->callbacks->exception(
|
||||
SSH_SOCKET_EXCEPTION_ERROR,
|
||||
s->last_errno,s->callbacks->userdata);
|
||||
/* p may have been freed, so don't use it
|
||||
* anymore in this function */
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
if(r==0){
|
||||
ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN);
|
||||
if(p != NULL) {
|
||||
ssh_poll_remove_events(p, POLLIN);
|
||||
}
|
||||
if(p != NULL) {
|
||||
ssh_poll_remove_events(p, POLLIN);
|
||||
}
|
||||
if(s->callbacks && s->callbacks->exception){
|
||||
s->callbacks->exception(
|
||||
SSH_SOCKET_EXCEPTION_EOF,
|
||||
0,s->callbacks->userdata);
|
||||
/* p may have been freed, so don't use it
|
||||
* anymore in this function */
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
if(r>0){
|
||||
@@ -255,6 +282,9 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
|
||||
buffer_get_rest_len(s->in_buffer),
|
||||
s->callbacks->userdata);
|
||||
buffer_pass_bytes(s->in_buffer,r);
|
||||
/* p may have been freed, so don't use it
|
||||
* anymore in this function */
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,7 +297,7 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
|
||||
if(s->state == SSH_SOCKET_CONNECTING){
|
||||
ssh_log(s->session,SSH_LOG_PACKET,"Received POLLOUT in connecting state");
|
||||
s->state = SSH_SOCKET_CONNECTED;
|
||||
ssh_poll_set_events(p,POLLOUT | POLLIN | POLLERR);
|
||||
ssh_poll_set_events(p,POLLOUT | POLLIN);
|
||||
ssh_sock_set_blocking(ssh_socket_get_fd_in(s));
|
||||
if(s->callbacks && s->callbacks->connected)
|
||||
s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,0,s->callbacks->userdata);
|
||||
@@ -275,7 +305,9 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
|
||||
}
|
||||
/* So, we can write data */
|
||||
s->write_wontblock=1;
|
||||
ssh_poll_remove_events(p,POLLOUT);
|
||||
if(p != NULL) {
|
||||
ssh_poll_remove_events(p, POLLOUT);
|
||||
}
|
||||
|
||||
/* If buffered data is pending, write it */
|
||||
if(buffer_get_rest_len(s->out_buffer) > 0){
|
||||
@@ -340,16 +372,24 @@ int ssh_socket_unix(ssh_socket s, const char *path) {
|
||||
|
||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd == SSH_INVALID_SOCKET) {
|
||||
ssh_set_error(s->session, SSH_FATAL,
|
||||
"Error from socket(AF_UNIX, SOCK_STREAM, 0): %s",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_SETFD, 1) == -1) {
|
||||
ssh_set_error(s->session, SSH_FATAL,
|
||||
"Error from fcntl(fd, F_SETFD, 1): %s",
|
||||
strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect(fd, (struct sockaddr *) &sunaddr,
|
||||
sizeof(sunaddr)) < 0) {
|
||||
ssh_set_error(s->session, SSH_FATAL, "Error from connect(): %s",
|
||||
strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
@@ -544,6 +584,7 @@ int ssh_socket_write(ssh_socket s, const void *buffer, int len) {
|
||||
enter_function();
|
||||
if(len > 0) {
|
||||
if (buffer_add_data(s->out_buffer, buffer, len) < 0) {
|
||||
ssh_set_error_oom(s->session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
ssh_socket_nonblocking_flush(s);
|
||||
@@ -632,6 +673,18 @@ int ssh_socket_data_writable(ssh_socket s) {
|
||||
return s->write_wontblock;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief returns the number of outgoing bytes currently buffered
|
||||
* @param s the socket
|
||||
* @returns numbers of bytes buffered, or 0 if the socket isn't connected
|
||||
*/
|
||||
int ssh_socket_buffered_write_bytes(ssh_socket s){
|
||||
if(s==NULL || s->out_buffer == NULL)
|
||||
return 0;
|
||||
return buffer_get_rest_len(s->out_buffer);
|
||||
}
|
||||
|
||||
|
||||
int ssh_socket_get_status(ssh_socket s) {
|
||||
int r = 0;
|
||||
|
||||
@@ -665,8 +718,11 @@ int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bin
|
||||
socket_t fd;
|
||||
ssh_session session=s->session;
|
||||
enter_function();
|
||||
if(s->state != SSH_SOCKET_NONE)
|
||||
if(s->state != SSH_SOCKET_NONE) {
|
||||
ssh_set_error(s->session, SSH_FATAL,
|
||||
"ssh_socket_connect called on socket not unconnected");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
fd=ssh_connect_host_nonblocking(s->session,host,bind_addr,port);
|
||||
ssh_log(session,SSH_LOG_PROTOCOL,"Nonblocking connection socket: %d",fd);
|
||||
if(fd == SSH_INVALID_SOCKET)
|
||||
@@ -744,7 +800,7 @@ int ssh_socket_connect_proxycommand(ssh_socket s, const char *command){
|
||||
s->state=SSH_SOCKET_CONNECTED;
|
||||
s->fd_is_socket=0;
|
||||
/* POLLOUT is the event to wait for in a nonblocking connect */
|
||||
ssh_poll_set_events(ssh_socket_get_poll_handle_in(s),POLLIN | POLLERR);
|
||||
ssh_poll_set_events(ssh_socket_get_poll_handle_in(s),POLLIN);
|
||||
ssh_poll_set_events(ssh_socket_get_poll_handle_out(s),POLLOUT);
|
||||
if(s->callbacks && s->callbacks->connected)
|
||||
s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,0,s->callbacks->userdata);
|
||||
|
||||
@@ -92,7 +92,7 @@ static void libcrypto_lock_callback(int mode, int i, const char *file, int line)
|
||||
}
|
||||
}
|
||||
|
||||
static int libcrypto_thread_init(){
|
||||
static int libcrypto_thread_init(void){
|
||||
int n=CRYPTO_num_locks();
|
||||
int i;
|
||||
if(user_callbacks == &ssh_threads_noop)
|
||||
@@ -109,7 +109,7 @@ static int libcrypto_thread_init(){
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static void libcrypto_thread_finalize(){
|
||||
static void libcrypto_thread_finalize(void){
|
||||
int n=CRYPTO_num_locks();
|
||||
int i;
|
||||
if (libcrypto_mutexes==NULL)
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WITH_LIBZ
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
#include "libssh/crypto.h"
|
||||
@@ -82,7 +86,7 @@ static void cipher_free(struct crypto_struct *cipher) {
|
||||
}
|
||||
|
||||
struct ssh_crypto_struct *crypto_new(void) {
|
||||
struct ssh_crypto_struct *crypto;
|
||||
struct ssh_crypto_struct *crypto;
|
||||
|
||||
crypto = malloc(sizeof(struct ssh_crypto_struct));
|
||||
if (crypto == NULL) {
|
||||
@@ -108,6 +112,18 @@ void crypto_free(struct ssh_crypto_struct *crypto){
|
||||
bignum_free(crypto->y);
|
||||
bignum_free(crypto->k);
|
||||
/* lot of other things */
|
||||
|
||||
#ifdef WITH_LIBZ
|
||||
if (crypto->compress_out_ctx &&
|
||||
(deflateEnd(crypto->compress_out_ctx) != 0)) {
|
||||
inflateEnd(crypto->compress_out_ctx);
|
||||
}
|
||||
if (crypto->compress_in_ctx &&
|
||||
(deflateEnd(crypto->compress_in_ctx) != 0)) {
|
||||
inflateEnd(crypto->compress_in_ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* i'm lost in my own code. good work */
|
||||
memset(crypto,0,sizeof(*crypto));
|
||||
|
||||
@@ -219,11 +235,15 @@ int crypt_set_algorithms_server(ssh_session session){
|
||||
int i = 0;
|
||||
struct crypto_struct *ssh_ciphertab=ssh_get_ciphertab();
|
||||
|
||||
if (session == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* we must scan the kex entries to find crypto algorithms and set their appropriate structure */
|
||||
enter_function();
|
||||
/* out */
|
||||
server = session->server_kex.methods[SSH_CRYPT_S_C];
|
||||
if(session && session->client_kex.methods) {
|
||||
if(session->client_kex.methods) {
|
||||
client = session->client_kex.methods[SSH_CRYPT_S_C];
|
||||
} else {
|
||||
ssh_log(session,SSH_LOG_PROTOCOL, "Client KEX empty");
|
||||
|
||||
@@ -75,12 +75,12 @@ int benchmarks_ping_latency (const char *host, float *average){
|
||||
}
|
||||
if(!found)
|
||||
goto parseerror;
|
||||
fclose(fd);
|
||||
pclose(fd);
|
||||
return 0;
|
||||
|
||||
parseerror:
|
||||
fprintf(stderr,"Parse error : couldn't locate average in %s",line);
|
||||
fclose(fd);
|
||||
pclose(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,13 +21,15 @@
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# include <dirent.h>
|
||||
# include <errno.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
@@ -35,6 +37,7 @@
|
||||
|
||||
static int verbosity = 0;
|
||||
|
||||
#ifndef _WIN32
|
||||
static int _torture_auth_kbdint(ssh_session session,
|
||||
const char *password) {
|
||||
const char *prompt;
|
||||
@@ -129,6 +132,7 @@ int torture_rmdirs(const char *path) {
|
||||
rewinddir(d);
|
||||
}
|
||||
} else {
|
||||
closedir(d);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -146,10 +150,6 @@ int torture_isdir(const char *path) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int torture_libssh_verbosity(void){
|
||||
return verbosity;
|
||||
}
|
||||
|
||||
ssh_session torture_ssh_session(const char *host,
|
||||
const char *user,
|
||||
const char *password) {
|
||||
@@ -258,6 +258,7 @@ failed:
|
||||
}
|
||||
ssh_disconnect(t->ssh);
|
||||
ssh_free(t->ssh);
|
||||
free(t);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -281,6 +282,11 @@ void torture_sftp_close(struct torture_sftp *t) {
|
||||
free(t->testdir);
|
||||
free(t);
|
||||
}
|
||||
#endif
|
||||
|
||||
int torture_libssh_verbosity(void){
|
||||
return verbosity;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
struct argument_s arguments;
|
||||
|
||||
@@ -6,6 +6,7 @@ add_cmockery_test(torture_init torture_init.c ${TORTURE_LIBRARY})
|
||||
add_cmockery_test(torture_list torture_list.c ${TORTURE_LIBRARY})
|
||||
add_cmockery_test(torture_misc torture_misc.c ${TORTURE_LIBRARY})
|
||||
add_cmockery_test(torture_options torture_options.c ${TORTURE_LIBRARY})
|
||||
add_cmockery_test(torture_isipaddr torture_isipaddr.c ${TORTURE_LIBRARY})
|
||||
if (UNIX AND NOT WIN32)
|
||||
# requires ssh-keygen
|
||||
add_cmockery_test(torture_keyfiles torture_keyfiles.c ${TORTURE_LIBRARY})
|
||||
|
||||
55
tests/unittests/torture_isipaddr.c
Normal file
55
tests/unittests/torture_isipaddr.c
Normal file
@@ -0,0 +1,55 @@
|
||||
#define LIBSSH_STATIC
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
#include "misc.c"
|
||||
#include "error.c"
|
||||
|
||||
/*
|
||||
* Test the behavior of ssh_is_ipaddr()
|
||||
*/
|
||||
static void torture_ssh_is_ipaddr(void **state) {
|
||||
(void)state;
|
||||
|
||||
assert_int_equal(ssh_is_ipaddr("127.0.0.1"),1);
|
||||
assert_int_equal(ssh_is_ipaddr("0.0.0.0"),1);
|
||||
assert_int_equal(ssh_is_ipaddr("1.1.1.1"),1);
|
||||
assert_int_equal(ssh_is_ipaddr("255.255.255.255"),1);
|
||||
assert_int_equal(ssh_is_ipaddr("128.128.128.128"),1);
|
||||
assert_int_equal(ssh_is_ipaddr("1.10.100.1"),1);
|
||||
assert_int_equal(ssh_is_ipaddr("0.1.10.100"),1);
|
||||
|
||||
assert_int_equal(ssh_is_ipaddr("2001:0db8:85a3:0000:0000:8a2e:0370:7334"),1);
|
||||
assert_int_equal(ssh_is_ipaddr("fe80:0000:0000:0000:0202:b3ff:fe1e:8329"),1);
|
||||
assert_int_equal(ssh_is_ipaddr("fe80:0:0:0:202:b3ff:fe1e:8329"),1);
|
||||
assert_int_equal(ssh_is_ipaddr("fe80::202:b3ff:fe1e:8329"),1);
|
||||
assert_int_equal(ssh_is_ipaddr("::1"),1);
|
||||
|
||||
assert_int_equal(ssh_is_ipaddr("::ffff:192.0.2.128"),1);
|
||||
|
||||
assert_int_equal(ssh_is_ipaddr("0.0.0.0.0"),0);
|
||||
assert_int_equal(ssh_is_ipaddr("0.0.0.0.a"),0);
|
||||
assert_int_equal(ssh_is_ipaddr("a.0.0.0"),0);
|
||||
assert_int_equal(ssh_is_ipaddr("0a.0.0.0.0"),0);
|
||||
assert_int_equal(ssh_is_ipaddr(""),0);
|
||||
assert_int_equal(ssh_is_ipaddr("0.0.0."),0);
|
||||
assert_int_equal(ssh_is_ipaddr("0.0"),0);
|
||||
assert_int_equal(ssh_is_ipaddr("0"),0);
|
||||
|
||||
assert_int_equal(ssh_is_ipaddr("2001:0db8:85a3:0000:0000:8a2e:0370:7334:1002"), 0);
|
||||
assert_int_equal(ssh_is_ipaddr("fe80:x:202:b3ff:fe1e:8329"), 0);
|
||||
assert_int_equal(ssh_is_ipaddr("fe80:x:202:b3ff:fe1e:8329"), 0);
|
||||
assert_int_equal(ssh_is_ipaddr(":1"), 0);
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
const UnitTest tests[] = {
|
||||
unit_test(torture_ssh_is_ipaddr)
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
rc=run_tests(tests);
|
||||
ssh_finalize();
|
||||
return rc;
|
||||
}
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "torture.h"
|
||||
#include "misc.c"
|
||||
#include "error.c"
|
||||
|
||||
#define TORTURE_TEST_DIR "/usr/local/bin/truc/much/.."
|
||||
|
||||
|
||||
@@ -159,6 +161,30 @@ static void torture_path_expand_known_hosts(void **state) {
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
static void torture_timeout_elapsed(void **state){
|
||||
struct ssh_timestamp ts;
|
||||
(void) state;
|
||||
ssh_timestamp_init(&ts);
|
||||
usleep(50000);
|
||||
assert_true(ssh_timeout_elapsed(&ts,25));
|
||||
assert_false(ssh_timeout_elapsed(&ts,30000));
|
||||
assert_false(ssh_timeout_elapsed(&ts,75));
|
||||
assert_true(ssh_timeout_elapsed(&ts,0));
|
||||
assert_false(ssh_timeout_elapsed(&ts,-1));
|
||||
}
|
||||
|
||||
static void torture_timeout_update(void **state){
|
||||
struct ssh_timestamp ts;
|
||||
(void) state;
|
||||
ssh_timestamp_init(&ts);
|
||||
usleep(50000);
|
||||
assert_int_equal(ssh_timeout_update(&ts,25), 0);
|
||||
assert_in_range(ssh_timeout_update(&ts,30000),29000,29960);
|
||||
assert_in_range(ssh_timeout_update(&ts,75),1,40);
|
||||
assert_int_equal(ssh_timeout_update(&ts,0),0);
|
||||
assert_int_equal(ssh_timeout_update(&ts,-1),-1);
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
const UnitTest tests[] = {
|
||||
@@ -173,6 +199,8 @@ int torture_run_tests(void) {
|
||||
#endif
|
||||
unit_test_setup_teardown(torture_path_expand_escape, setup, teardown),
|
||||
unit_test_setup_teardown(torture_path_expand_known_hosts, setup, teardown),
|
||||
unit_test(torture_timeout_elapsed),
|
||||
unit_test(torture_timeout_update),
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
Reference in New Issue
Block a user