mirror of
				https://github.com/libssh2/libssh2.git
				synced 2025-11-03 22:13:11 +03:00 
			
		
		
		
	Update from:
5fec927374/scripts/checksrc.pl
- suppress these new checks:
  - EQUALSNULL: 320 warnings
  - NOTEQUALSZERO: 142 warnings
  - TYPEDEFSTRUCT: 16 warnings
  We can enabled them in the future.
- fix all other new ones.
- also fix whitespace in two `NMakefile` files.
		
	
		
			
				
	
	
		
			318 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			318 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* Copyright (C) 2022 Xaver Loppenstedt
 | 
						|
 * All rights reserved.
 | 
						|
 *
 | 
						|
 * Redistribution and use in source and binary forms,
 | 
						|
 * with or without modification, are permitted provided
 | 
						|
 * that the following conditions are met:
 | 
						|
 *
 | 
						|
 *   Redistributions of source code must retain the above
 | 
						|
 *   copyright notice, this list of conditions and the
 | 
						|
 *   following disclaimer.
 | 
						|
 *
 | 
						|
 *   Redistributions in binary form must reproduce the above
 | 
						|
 *   copyright notice, this list of conditions and the following
 | 
						|
 *   disclaimer in the documentation and/or other materials
 | 
						|
 *   provided with the distribution.
 | 
						|
 *
 | 
						|
 *   Neither the name of the copyright holder nor the names
 | 
						|
 *   of any other contributors may be used to endorse or
 | 
						|
 *   promote products derived from this software without
 | 
						|
 *   specific prior written permission.
 | 
						|
 *
 | 
						|
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 | 
						|
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 | 
						|
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 | 
						|
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
						|
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 | 
						|
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
						|
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
						|
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 | 
						|
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
						|
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 | 
						|
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
						|
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 | 
						|
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 | 
						|
 * OF SUCH DAMAGE.
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
#include "libssh2_priv.h"
 | 
						|
#include "userauth_kbd_packet.h"
 | 
						|
 | 
						|
#define PASS 0
 | 
						|
#define FAIL -1
 | 
						|
 | 
						|
struct expected {
 | 
						|
    int rc;
 | 
						|
    int last_error_code;
 | 
						|
    const char *last_error_message;
 | 
						|
};
 | 
						|
struct test_case {
 | 
						|
    const char *data;
 | 
						|
    int data_len;
 | 
						|
    struct expected expected;
 | 
						|
};
 | 
						|
 | 
						|
#define TEST_CASES_LEN 16
 | 
						|
struct test_case test_cases[TEST_CASES_LEN] = {
 | 
						|
    /* too small */
 | 
						|
    {
 | 
						|
        NULL, 0,
 | 
						|
        {FAIL, -38,
 | 
						|
        "userauth keyboard data buffer too small to get length"}},
 | 
						|
    /* too small */
 | 
						|
    {
 | 
						|
        "1234", 4,
 | 
						|
        {FAIL, -38,
 | 
						|
        "userauth keyboard data buffer too small to get length"}},
 | 
						|
    /* smallest valid packet possible */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\0", 17,
 | 
						|
        {PASS, 0, ""}},
 | 
						|
    /* overrun name */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\x7f"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\0", 17,
 | 
						|
            {FAIL, -6,
 | 
						|
            "Unable to decode keyboard-interactive 'name' request field"}},
 | 
						|
    /* overrun instruction */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\x7f"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\0", 17,
 | 
						|
        {FAIL, -6,
 | 
						|
        "Unable to decode keyboard-interactive 'instruction' "
 | 
						|
        "request field"}},
 | 
						|
    /* overrun language */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\x7f"
 | 
						|
        "\0\0\0\0", 17,
 | 
						|
        {FAIL, -6, "Unable to decode keyboard-interactive 'language tag' "
 | 
						|
        "request field"}},
 | 
						|
    /* underrun prompt number */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\x01"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\0", 17,
 | 
						|
        {FAIL, -38,
 | 
						|
        "Unable to decode keyboard-interactive number of "
 | 
						|
        "keyboard prompts"}},
 | 
						|
    /* too many prompts */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\x7f", 17,
 | 
						|
        {FAIL, -41, "Too many replies for keyboard-interactive prompts"}},
 | 
						|
    /* empty prompt */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0\0\0\x01"
 | 
						|
        "\0\0\0\0"
 | 
						|
        "\0", 22, {PASS, 0, ""}},
 | 
						|
    /* copied from OpenSSH */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"
 | 
						|
        "\0\0\0\x0aPassword: \0", 32, {PASS, 0, ""}},
 | 
						|
    /* overrun in prompt text */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"
 | 
						|
        "\0\0\0\x7bPassword: \0", 32,
 | 
						|
        {FAIL, -6, "Unable to decode keyboard-interactive "
 | 
						|
        "prompt message"}},
 | 
						|
    /* no echo prompt boolean */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"
 | 
						|
        "\0\0\0\x0bPassword: \0", 32,
 | 
						|
        {FAIL, -38, "Unable to decode user auth keyboard prompt echo"}},
 | 
						|
    /* two prompts */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02"
 | 
						|
        "\0\0\0\x0aPassword: \0"
 | 
						|
        "\0\0\0\x07Token: \1", 44,
 | 
						|
        {PASS, 0, ""}},
 | 
						|
    /* example from RFC 4256 */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\x19""CRYPTOCard Authentication"
 | 
						|
        "\0\0\0\x1b""The challenge is '14315716'"
 | 
						|
        "\0\0\0\x05""en-US"
 | 
						|
        "\0\0\0\x01"
 | 
						|
        "\0\0\0\x0aResponse: "
 | 
						|
        "\x01"
 | 
						|
        , 89, {PASS, 0, ""}},
 | 
						|
    /* three prompts, 3rd missing */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03"
 | 
						|
        "\0\0\0\x0aPassword: \0"
 | 
						|
        "\0\0\0\x07Token: \1", 44,
 | 
						|
        {FAIL, -6,
 | 
						|
            "Unable to decode keyboard-interactive prompt message"}},
 | 
						|
    /* overflow language on 32 bit platform */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\x19"
 | 
						|
            "\0\0\0\x01"
 | 
						|
            "\0\0\0\x05""PWN3D\0\1\2\3\4\5\6\7\1\2\3"
 | 
						|
            "\x01"
 | 
						|
        "\0\0\0\x1b""The challenge is '14315716'"
 | 
						|
        "\xff\xff\xff\xc4""en-US"
 | 
						|
        "\0\0\0\x01"
 | 
						|
        "\0\0\0\x0aResponse: "
 | 
						|
        "\x01",
 | 
						|
        89,
 | 
						|
        {FAIL, -6,
 | 
						|
            "Unable to decode keyboard-interactive 'language tag' "
 | 
						|
            "request field"}},
 | 
						|
};
 | 
						|
 | 
						|
#define FAILED_MALLOC_TEST_CASES_LEN 2
 | 
						|
struct test_case failed_malloc_test_cases[FAILED_MALLOC_TEST_CASES_LEN] = {
 | 
						|
    /* malloc fail */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"
 | 
						|
        "\0\0\0\x0aPassword: \0", 32,
 | 
						|
        {FAIL, -6,
 | 
						|
            "Unable to allocate memory for "
 | 
						|
            "keyboard-interactive prompts array"}},
 | 
						|
    /* malloc fail */
 | 
						|
    {
 | 
						|
        "<"
 | 
						|
        "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"
 | 
						|
        "\0\0\0\x0aPassword: \0", 32,
 | 
						|
        {FAIL, -6,
 | 
						|
            "Unable to allocate memory for "
 | 
						|
            "keyboard-interactive responses array"
 | 
						|
        }}
 | 
						|
};
 | 
						|
 | 
						|
static int alloc_count = 0;
 | 
						|
static int free_count = 0;
 | 
						|
 | 
						|
/* libssh2_default_alloc
 | 
						|
 */
 | 
						|
static
 | 
						|
LIBSSH2_ALLOC_FUNC(test_alloc)
 | 
						|
{
 | 
						|
    int *threshold_int_ptr = *abstract;
 | 
						|
    alloc_count++;
 | 
						|
    if (*abstract != NULL && *threshold_int_ptr == alloc_count) {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    return malloc(count);
 | 
						|
}
 | 
						|
 | 
						|
/* libssh2_default_free
 | 
						|
 */
 | 
						|
static
 | 
						|
LIBSSH2_FREE_FUNC(test_free)
 | 
						|
{
 | 
						|
    (void) abstract;
 | 
						|
    free_count++;
 | 
						|
    free(ptr);
 | 
						|
}
 | 
						|
 | 
						|
static
 | 
						|
int test_case(int num,
 | 
						|
              const char *data, int data_len, void *abstract,
 | 
						|
              struct expected expected)
 | 
						|
{
 | 
						|
    int rc;
 | 
						|
    char *message;
 | 
						|
    int error_code;
 | 
						|
    LIBSSH2_SESSION *session = NULL;
 | 
						|
    alloc_count = 0;
 | 
						|
    free_count = 0;
 | 
						|
    session = libssh2_session_init_ex(test_alloc, test_free, NULL, abstract);
 | 
						|
    if(session == NULL) {
 | 
						|
        fprintf(stderr, "libssh2_session_init_ex failed\n");
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    session->userauth_kybd_data = LIBSSH2_ALLOC(session, data_len);
 | 
						|
    session->userauth_kybd_data_len = data_len;
 | 
						|
    memcpy(session->userauth_kybd_data, data, data_len);
 | 
						|
 | 
						|
    rc = userauth_keyboard_interactive_decode_info_request(session);
 | 
						|
 | 
						|
    if(rc != expected.rc) {
 | 
						|
        fprintf(stdout,
 | 
						|
                "Test case %d: expected return code to be %d got %d\n",
 | 
						|
                num, expected.rc, rc);
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    error_code = libssh2_session_last_error(session, &message, NULL, 0);
 | 
						|
 | 
						|
    if(expected.last_error_code != error_code) {
 | 
						|
        fprintf(stdout,
 | 
						|
                "Test case %d: expected last error code to be "
 | 
						|
                "\"%d\" got \"%d\"\n",
 | 
						|
                num, expected.last_error_code, error_code);
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if(strcmp(expected.last_error_message, message) != 0) {
 | 
						|
        fprintf(stdout,
 | 
						|
                "Test case %d: expected last error message to be "
 | 
						|
                "\"%s\" got \"%s\"\n",
 | 
						|
                num, expected.last_error_message, message);
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    libssh2_session_free(session);
 | 
						|
 | 
						|
    fprintf(stderr, "Test case %d passed\n", num);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int main(void)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for(i = 0; i < TEST_CASES_LEN; i++) {
 | 
						|
        test_case(i + 1,
 | 
						|
                  test_cases[i].data, test_cases[i].data_len,
 | 
						|
                  NULL,
 | 
						|
                  test_cases[i].expected);
 | 
						|
    }
 | 
						|
 | 
						|
    for(i = 0; i < FAILED_MALLOC_TEST_CASES_LEN; i++) {
 | 
						|
        int tc =  i + TEST_CASES_LEN + 1;
 | 
						|
        int malloc_call_num = 5 + i;
 | 
						|
        test_case(tc,
 | 
						|
                    failed_malloc_test_cases[i].data,
 | 
						|
                    failed_malloc_test_cases[i].data_len,
 | 
						|
                    &malloc_call_num,
 | 
						|
                    failed_malloc_test_cases[i].expected);
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 |