From 4cf935abab997ca7882fe832324ba4e724c5af61 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 11 Jun 2010 13:05:55 +0200 Subject: [PATCH] inputchecks: make lots of API functions check for NULL pointers If an application accidentally provides a NULL handle pointer to the channel or sftp public functions, they now return an error instead of segfaulting. --- src/channel.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++---- src/sftp.c | 63 +++++++++++++++++++++++---- 2 files changed, 163 insertions(+), 17 deletions(-) diff --git a/src/channel.c b/src/channel.c index 61a23534..966e63d8 100644 --- a/src/channel.c +++ b/src/channel.c @@ -329,6 +329,10 @@ libssh2_channel_open_ex(LIBSSH2_SESSION *session, const char *type, const char *msg, unsigned int msg_len) { LIBSSH2_CHANNEL *ptr; + + if(!session) + return NULL; + BLOCK_ADJUST_ERRNO(ptr, session, _libssh2_channel_open(session, type, type_len, window_size, packet_size, @@ -402,10 +406,14 @@ channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host, * Tunnel TCP/IP connect through the SSH session to direct host/port */ LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION * session, const char *host, +libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, const char *host, int port, const char *shost, int sport) { LIBSSH2_CHANNEL *ptr; + + if(!session) + return NULL; + BLOCK_ADJUST_ERRNO(ptr, session, channel_direct_tcpip(session, host, port, shost, sport)); return ptr; @@ -569,6 +577,10 @@ libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, const char *host, int port, int *bound_port, int queue_maxsize) { LIBSSH2_LISTENER *ptr; + + if(!session) + return NULL; + BLOCK_ADJUST_ERRNO(ptr, session, channel_forward_listen(session, host, port, bound_port, queue_maxsize)); @@ -673,6 +685,10 @@ LIBSSH2_API int libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener) { int rc; + + if(!listener) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, listener->session, _libssh2_channel_forward_cancel(listener)); return rc; @@ -725,6 +741,10 @@ LIBSSH2_API LIBSSH2_CHANNEL * libssh2_channel_forward_accept(LIBSSH2_LISTENER *listener) { LIBSSH2_CHANNEL *ptr; + + if(!listener) + return NULL; + BLOCK_ADJUST_ERRNO(ptr, listener->session, channel_forward_accept(listener)); return ptr; @@ -838,6 +858,10 @@ libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel, const char *value, unsigned int value_len) { int rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, channel_setenv(channel, varname, varname_len, value, value_len)); @@ -955,6 +979,10 @@ libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, const char *term, int width_px, int height_px) { int rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, channel_request_pty(channel, term, term_len, modes, modes_len, width, height, @@ -1031,6 +1059,10 @@ libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL *channel, int width, int height, int width_px, int height_px) { int rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, channel_request_pty_size(channel, width, height, width_px, height_px)); @@ -1175,6 +1207,10 @@ libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection, int screen_number) { int rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, channel_x11_req(channel, single_connection, auth_proto, auth_cookie, screen_number)); @@ -1293,6 +1329,10 @@ libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, const char *msg, unsigned int msg_len) { int rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, _libssh2_channel_process_startup(channel, req, req_len, msg, msg_len)); @@ -1309,7 +1349,8 @@ libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, LIBSSH2_API void libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel, int blocking) { - (void) _libssh2_session_set_blocking(channel->session, blocking); + if(channel) + (void) _libssh2_session_set_blocking(channel->session, blocking); } /* @@ -1394,6 +1435,10 @@ LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int stream) { int rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, _libssh2_channel_flush(channel, stream)); return rc; @@ -1402,11 +1447,17 @@ libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int stream) /* * libssh2_channel_get_exit_status * - * Return the channel's program exit status + * Return the channel's program exit status. Note that the actual protocol + * provides the full 32bit this function returns. We cannot abuse it to + * return error values in case of errors so we return a zero if channel is + * NULL. */ LIBSSH2_API int -libssh2_channel_get_exit_status(LIBSSH2_CHANNEL * channel) +libssh2_channel_get_exit_status(LIBSSH2_CHANNEL *channel) { + if(!channel) + return 0; + return channel->exit_status; } @@ -1529,6 +1580,10 @@ libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel, unsigned int *window) { int rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, _libssh2_channel_receive_window_adjust(channel, adj, force, window)); @@ -1571,6 +1626,10 @@ libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel, int mode) { int rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, _libssh2_channel_extended_data(channel, mode)); return rc; @@ -1776,6 +1835,10 @@ libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf, size_t buflen) { int rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, _libssh2_channel_read(channel, stream_id, buf, buflen)); return rc; @@ -2000,6 +2063,10 @@ libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id, const char *buf, size_t buflen) { ssize_t rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, _libssh2_channel_write(channel, stream_id, buf, buflen)); return rc; @@ -2042,6 +2109,10 @@ LIBSSH2_API int libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel) { int rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, channel_send_eof(channel)); return rc; } @@ -2054,8 +2125,14 @@ libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel) LIBSSH2_API int libssh2_channel_eof(LIBSSH2_CHANNEL * channel) { - LIBSSH2_SESSION *session = channel->session; - LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets); + LIBSSH2_SESSION *session; + LIBSSH2_PACKET *packet; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + + session = channel->session; + packet = _libssh2_list_first(&session->packets); while (packet) { if (((packet->data[0] == SSH_MSG_CHANNEL_DATA) @@ -2120,6 +2197,10 @@ LIBSSH2_API int libssh2_channel_wait_eof(LIBSSH2_CHANNEL *channel) { int rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, channel_wait_eof(channel)); return rc; } @@ -2202,6 +2283,10 @@ LIBSSH2_API int libssh2_channel_close(LIBSSH2_CHANNEL *channel) { int rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, _libssh2_channel_close(channel) ); return rc; } @@ -2259,6 +2344,10 @@ LIBSSH2_API int libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel) { int rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, channel_wait_closed(channel)); return rc; } @@ -2358,12 +2447,16 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel) * Make sure a channel is closed, then remove the channel from the session * and free its resource(s) * - * Returns 0 on success, -1 on failure + * Returns 0 on success, negative on failure */ LIBSSH2_API int libssh2_channel_free(LIBSSH2_CHANNEL *channel) { int rc; + + if(!channel) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, channel->session, _libssh2_channel_free(channel)); return rc; } @@ -2377,10 +2470,13 @@ libssh2_channel_free(LIBSSH2_CHANNEL *channel) * window_size_initial as defined by the channel_open request */ LIBSSH2_API unsigned long -libssh2_channel_window_read_ex(LIBSSH2_CHANNEL * channel, +libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel, unsigned long *read_avail, unsigned long *window_size_initial) { + if(!channel) + return 0; /* no channel, no window! */ + if (window_size_initial) { *window_size_initial = channel->remote.window_size_initial; } @@ -2417,9 +2513,12 @@ libssh2_channel_window_read_ex(LIBSSH2_CHANNEL * channel, * the channel_open request */ LIBSSH2_API unsigned long -libssh2_channel_window_write_ex(LIBSSH2_CHANNEL * channel, +libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel, unsigned long *window_size_initial) { + if(!channel) + return 0; /* no channel, no window! */ + if (window_size_initial) { /* For locally initiated channels this is very often 0, so it's not * *that* useful as information goes */ diff --git a/src/sftp.c b/src/sftp.c index 8d002257..695621ea 100644 --- a/src/sftp.c +++ b/src/sftp.c @@ -698,7 +698,8 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) return sftp_handle; sftp_init_error: - while (_libssh2_channel_free(session->sftpInit_channel) == LIBSSH2_ERROR_EAGAIN); + while (_libssh2_channel_free(session->sftpInit_channel) == + LIBSSH2_ERROR_EAGAIN); session->sftpInit_channel = NULL; if (session->sftpInit_sftp) { LIBSSH2_FREE(session, session->sftpInit_sftp); @@ -717,6 +718,9 @@ LIBSSH2_API LIBSSH2_SFTP *libssh2_sftp_init(LIBSSH2_SESSION *session) { LIBSSH2_SFTP *ptr; + if(!session) + return NULL; + if(!(session->state & LIBSSH2_STATE_AUTHENTICATED)) { _libssh2_error(session, LIBSSH2_ERROR_INVAL, "session not authenticated yet"); @@ -808,6 +812,8 @@ LIBSSH2_API int libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp) { int rc; + if(!sftp) + return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, sftp->channel->session, sftp_shutdown(sftp)); return rc; } @@ -1016,6 +1022,10 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, const char *filename, int open_type) { LIBSSH2_SFTP_HANDLE *hnd; + + if(!sftp) + return NULL; + BLOCK_ADJUST_ERRNO(hnd, sftp->channel->session, sftp_open(sftp, filename, filename_len, flags, mode, open_type)); @@ -1192,6 +1202,8 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *hnd, char *buffer, size_t buffer_maxlen) { ssize_t rc; + if(!hnd) + return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, hnd->sftp->channel->session, sftp_read(hnd, buffer, buffer_maxlen)); return rc; @@ -1363,6 +1375,8 @@ libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *hnd, char *buffer, LIBSSH2_SFTP_ATTRIBUTES *attrs) { int rc; + if(!hnd) + return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, hnd->sftp->channel->session, sftp_readdir(hnd, buffer, buffer_maxlen, longentry, longentry_maxlen, attrs)); @@ -1470,6 +1484,8 @@ libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *hnd, const char *buffer, size_t count) { ssize_t rc; + if(!hnd) + return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, hnd->sftp->channel->session, sftp_write(hnd, buffer, count)); return rc; @@ -1575,10 +1591,12 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle, * Get or Set stat on a file */ LIBSSH2_API int -libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * hnd, +libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *hnd, LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat) { int rc; + if(!hnd || !attrs) + return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, hnd->sftp->channel->session, sftp_fstat(hnd, attrs, setstat)); return rc; @@ -1588,26 +1606,31 @@ libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * hnd, * Set the read/write pointer to an arbitrary position within the file */ LIBSSH2_API void -libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE * handle, size_t offset) +libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset) { - handle->u.file.offset = offset; + if(handle) + handle->u.file.offset = offset; } /* libssh2_sftp_seek64 * Set the read/write pointer to an arbitrary position within the file */ LIBSSH2_API void -libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE * handle, libssh2_uint64_t offset) +libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle, libssh2_uint64_t offset) { - handle->u.file.offset = offset; + if(handle) + handle->u.file.offset = offset; } /* libssh2_sftp_tell * Return the current read/write pointer's offset */ LIBSSH2_API size_t -libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE * handle) +libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle) { + if(!handle) + return 0; /* no handle, no size */ + /* NOTE: this may very well truncate the size if it is larger than what size_t can hold, so libssh2_sftp_tell64() is really the function you should use */ @@ -1618,8 +1641,11 @@ libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE * handle) * Return the current read/write pointer's offset */ LIBSSH2_API libssh2_uint64_t -libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE * handle) +libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE *handle) { + if(!handle) + return 0; /* no handle, no size */ + return handle->u.file.offset; } @@ -1731,6 +1757,8 @@ LIBSSH2_API int libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *hnd) { int rc; + if(!hnd) + return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, hnd->sftp->channel->session, sftp_close_handle(hnd)); return rc; } @@ -1819,6 +1847,8 @@ libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp, const char *filename, unsigned int filename_len) { int rc; + if(!sftp) + return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, sftp->channel->session, sftp_unlink(sftp, filename, filename_len)); return rc; @@ -1949,6 +1979,8 @@ libssh2_sftp_rename_ex(LIBSSH2_SFTP *sftp, const char *source_filename, unsigned int dest_filename_len, long flags) { int rc; + if(!sftp) + return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, sftp->channel->session, sftp_rename(sftp, source_filename, source_filename_len, dest_filename, dest_filename_len, flags)); @@ -2061,6 +2093,8 @@ LIBSSH2_API int libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st) { int rc; + if(!handle || !st) + return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, handle->sftp->channel->session, sftp_fstatvfs(handle, st)); return rc; } @@ -2172,6 +2206,8 @@ libssh2_sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path, size_t path_len, LIBSSH2_SFTP_STATVFS *st) { int rc; + if(!sftp || !st) + return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, sftp->channel->session, sftp_statvfs(sftp, path, path_len, st)); return rc; @@ -2277,6 +2313,8 @@ libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp, const char *path, unsigned int path_len, long mode) { int rc; + if(!sftp) + return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, sftp->channel->session, sftp_mkdir(sftp, path, path_len, mode)); return rc; @@ -2366,6 +2404,8 @@ libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp, const char *path, unsigned int path_len) { int rc; + if(!sftp) + return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, sftp->channel->session, sftp_rmdir(sftp, path, path_len)); return rc; @@ -2488,6 +2528,8 @@ libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, const char *path, LIBSSH2_SFTP_ATTRIBUTES *attrs) { int rc; + if(!sftp) + return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, sftp->channel->session, sftp_stat(sftp, path, path_len, stat_type, attrs)); return rc; @@ -2629,6 +2671,8 @@ libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path, unsigned int target_len, int link_type) { int rc; + if(!sftp) + return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, sftp->channel->session, sftp_symlink(sftp, path, path_len, target, target_len, link_type)); @@ -2641,5 +2685,8 @@ libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path, LIBSSH2_API unsigned long libssh2_sftp_last_error(LIBSSH2_SFTP *sftp) { + if(!sftp) + return 0; + return sftp->last_errno; }