mirror of
				https://github.com/libssh2/libssh2.git
				synced 2025-11-03 22:13:11 +03:00 
			
		
		
		
	- kex: drop unused assigment. - knownhost: error when salt is NULL. - mbedtls: avoid unnecessary inline assigments, that were ignored for the second block and replaceable with a `ret = 0` initialization for the first one. - mbedtls: fix ignoring an API failure and ending up calling `mbedtls_rsa_check_privkey()` unconditionally. - misc: initialize datalen on error in `_libssh2_base64_decode()`. - openssl: drop unused assigments. - openssl: fix unused static function. - packet: avoid NULL deref. - packet: avoid NULL in `memcpy` src. - publickey: optimize struct layout to avoid padding. - sftp: replace ignored `rc` error assigment with `_libssh2_error()` call. - transport: fix potential NULL ptr dereferences. - transport: silence uninitialized value warnings. - userauth: drop unused assigment. - userauth: possible use of unitialized pointer. - userauth: replace `rewind()` with `fseek()`. `rewind()` returns an error condition in `errno`. `errno` is problematic and reduces portability. Use `fseek()` to avoid it. - userauth: replace potential NULL deref by returning error from `sign_frommemory()`. Possible false positive. `rc` should be set upstream if the callback is NULL. - userauth: replace potential NULL deref by returning error from `sign_fromfile()`. clang-tidy did not warn about this one, but let's match `sign_frommemory()` anyway. - wincng: fix potentially unused macros. - wincng: make sure bignum is not NULL before use. tests: - openssh_fixture: drop unused assignment. - session_fixture: exit if `username` not set, to avoid `strlen(NULL)`. - session_fixture: replace `rewind()` with `fseek()`. `rewind()` returns an error condition in `errno`. `errno` is problematic and reduces portability. Use `fseek()` to avoid it. - test_read: exit if `username` not set, to avoid `strlen(NULL)`. examples: - scp_write_nonblock: fix file handle leak. - sftp_write_nonblock: file handle leak on error. - sftp_write_sliding: file handle leak on error. - ssh2_agent_forwarding: fix unused error codes. Details in the subcommits under the PR. Thanks-to: Michael Buckley Thanks-to: Will Cosgrove Closes #1561
		
			
				
	
	
		
			137 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* Copyright (C) The libssh2 project and its contributors.
 | 
						|
 *
 | 
						|
 * libssh2 test receiving large amounts of data through a channel
 | 
						|
 *
 | 
						|
 * SPDX-License-Identifier: BSD-3-Clause
 | 
						|
 */
 | 
						|
 | 
						|
#include "runner.h"
 | 
						|
#include "openssh_fixture.h"
 | 
						|
 | 
						|
#include <stdlib.h>  /* for getenv() */
 | 
						|
 | 
						|
/* set in Dockerfile */
 | 
						|
static const char *username = "libssh2";
 | 
						|
static const char *key_file_private = "key_rsa";
 | 
						|
static const char *key_file_public = "key_rsa.pub";
 | 
						|
 | 
						|
int test(LIBSSH2_SESSION *session)
 | 
						|
{
 | 
						|
    int rc;
 | 
						|
    unsigned long xfer_bytes = 0;
 | 
						|
    LIBSSH2_CHANNEL *channel;
 | 
						|
 | 
						|
    /* Size and number of blocks to transfer
 | 
						|
     * This needs to be large to increase the chance of timing effects causing
 | 
						|
     * different code paths to be hit in the unframing code, but not so long
 | 
						|
     * that the integration tests take too long. 5 seconds of run time is
 | 
						|
     * probably a reasonable compromise. The block size is an odd number to
 | 
						|
     * increase the chance that various internal buffer and block boundaries
 | 
						|
     * are overlapped. */
 | 
						|
    const unsigned long xfer_bs = 997;
 | 
						|
    unsigned long xfer_count = 140080;
 | 
						|
 | 
						|
    char remote_command[256];
 | 
						|
    const char *env;
 | 
						|
    const char *userauth_list;
 | 
						|
 | 
						|
    /* Ignore our hard-wired Dockerfile user when not running under Docker */
 | 
						|
    if(!openssh_fixture_have_docker()) {
 | 
						|
        username = getenv("USER");
 | 
						|
#ifdef _WIN32
 | 
						|
        if(!username)
 | 
						|
            username = getenv("USERNAME");
 | 
						|
#endif
 | 
						|
    }
 | 
						|
 | 
						|
    if(!username) {
 | 
						|
        fprintf(stderr, "username not set\n");
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    userauth_list = libssh2_userauth_list(session, username,
 | 
						|
                                          (unsigned int)strlen(username));
 | 
						|
    if(!userauth_list) {
 | 
						|
        print_last_session_error("libssh2_userauth_list");
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if(!strstr(userauth_list, "publickey")) {
 | 
						|
        fprintf(stderr, "'publickey' was expected in userauth list: %s\n",
 | 
						|
                userauth_list);
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    rc = libssh2_userauth_publickey_fromfile_ex(session, username,
 | 
						|
                                                (unsigned int)strlen(username),
 | 
						|
                                                srcdir_path(key_file_public),
 | 
						|
                                                srcdir_path(key_file_private),
 | 
						|
                                                NULL);
 | 
						|
    if(rc) {
 | 
						|
        print_last_session_error("libssh2_userauth_publickey_fromfile_ex");
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Request a session channel on which to run a shell */
 | 
						|
    channel = libssh2_channel_open_session(session);
 | 
						|
    if(!channel) {
 | 
						|
        fprintf(stderr, "Unable to open a session\n");
 | 
						|
        goto shutdown;
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("FIXTURE_XFER_COUNT");
 | 
						|
    if(env) {
 | 
						|
        xfer_count = (unsigned long)strtol(env, NULL, 0);
 | 
						|
        fprintf(stderr, "Custom xfer_count: %lu\n", xfer_count);
 | 
						|
    }
 | 
						|
 | 
						|
    /* command to transfer the desired amount of data */
 | 
						|
    snprintf(remote_command, sizeof(remote_command),
 | 
						|
             "dd if=/dev/zero bs=%lu count=%lu status=none",
 | 
						|
             xfer_bs, xfer_count);
 | 
						|
 | 
						|
    /* Send the command to transfer data */
 | 
						|
    if(libssh2_channel_exec(channel, remote_command)) {
 | 
						|
        fprintf(stderr, "Unable to request command on channel\n");
 | 
						|
        goto shutdown;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Read data */
 | 
						|
    while(!libssh2_channel_eof(channel)) {
 | 
						|
        char buf[1024];
 | 
						|
        ssize_t err = libssh2_channel_read(channel, buf, sizeof(buf));
 | 
						|
        if(err < 0)
 | 
						|
            fprintf(stderr, "Unable to read response: %ld\n", (long)err);
 | 
						|
        else {
 | 
						|
            unsigned int i;
 | 
						|
            for(i = 0; i < (unsigned long)err; ++i) {
 | 
						|
                if(buf[i]) {
 | 
						|
                    fprintf(stderr, "Bad data received\n");
 | 
						|
                    /* Test will fail below due to bad data length */
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            xfer_bytes += i;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* Shut down */
 | 
						|
    if(libssh2_channel_close(channel))
 | 
						|
        fprintf(stderr, "Unable to close channel\n");
 | 
						|
 | 
						|
    if(channel) {
 | 
						|
        libssh2_channel_free(channel);
 | 
						|
        channel = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
shutdown:
 | 
						|
 | 
						|
    /* Test check */
 | 
						|
    if(xfer_bytes != xfer_count * xfer_bs) {
 | 
						|
        fprintf(stderr, "Not enough bytes received: %lu not %lu\n",
 | 
						|
                xfer_bytes, xfer_count * xfer_bs);
 | 
						|
        return 1;  /* error */
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 |