From 19cfb22d30b5db285a8561b33d60e4155179651c Mon Sep 17 00:00:00 2001 From: HansH111 Date: Sun, 13 Mar 2022 17:37:44 +0000 Subject: [PATCH 01/12] add pubkey_info field to authstate structure --- auth.h | 1 + 1 file changed, 1 insertion(+) diff --git a/auth.h b/auth.h index 9279619..2063cad 100644 --- a/auth.h +++ b/auth.h @@ -125,6 +125,7 @@ struct AuthState { char *pw_passwd; #if DROPBEAR_SVR_PUBKEY_OPTIONS_BUILT struct PubKeyOptions* pubkey_options; + char *pubkey_info; #endif }; From 80e7143fd2d42901eb95d1a2942bf1221708eaac Mon Sep 17 00:00:00 2001 From: HansH111 Date: Sun, 13 Mar 2022 17:38:13 +0000 Subject: [PATCH 02/12] extract pubkey_info when seuccesfully auth with a key and free it in the cleanup function --- svr-authpubkey.c | 23 ++++++++++++++++++++--- svr-authpubkeyoptions.c | 3 +++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/svr-authpubkey.c b/svr-authpubkey.c index a33cc39..10356a8 100644 --- a/svr-authpubkey.c +++ b/svr-authpubkey.c @@ -261,7 +261,7 @@ static int checkpubkey_line(buffer* line, int line_num, const char* filename, const char* algo, unsigned int algolen, const unsigned char* keyblob, unsigned int keybloblen) { buffer *options_buf = NULL; - unsigned int pos, len; + unsigned int pos, len, infopos, infolen; int ret = DROPBEAR_FAILURE; if (line->len < MIN_AUTHKEYS_LINE || line->len > MAX_AUTHKEYS_LINE) { @@ -344,6 +344,11 @@ static int checkpubkey_line(buffer* line, int line_num, const char* filename, for (len = 0; line->pos < line->len; len++) { if (buf_getbyte(line) == ' ') break; } + /* findout the length of the public key info */ + infopos = line->pos; + for (infolen = 0; line->pos < line->len; infolen++) { + if (buf_getbyte(line) == ' ') break; + } buf_setpos(line, pos); buf_setlen(line, line->pos + len); @@ -351,8 +356,20 @@ static int checkpubkey_line(buffer* line, int line_num, const char* filename, ret = cmp_base64_key(keyblob, keybloblen, (const unsigned char *) algo, algolen, line, NULL); - if (ret == DROPBEAR_SUCCESS && options_buf) { - ret = svr_add_pubkey_options(options_buf, line_num, filename); + if (ret == DROPBEAR_SUCCESS) { + if (options_buf) { + ret = svr_add_pubkey_options(options_buf, line_num, filename); + } + /* save the (optional) public key information */ + if (infolen) { + ses.authstate.pubkey_info = m_malloc(infolen + 1); + if (ses.authstate.pubkey_info) { + strncpy(ses.authstate.pubkey_info, &line->data[infopos], infolen); + ses.authstate.pubkey_info[infolen]='\0'; + } + } else { + ses.authstate.pubkey_info = NULL; + } } out: diff --git a/svr-authpubkeyoptions.c b/svr-authpubkeyoptions.c index 7ddf680..447f4b7 100644 --- a/svr-authpubkeyoptions.c +++ b/svr-authpubkeyoptions.c @@ -115,6 +115,9 @@ void svr_pubkey_options_cleanup() { } m_free(ses.authstate.pubkey_options); } + if (ses.authstate.pubkey_info) { + m_free(ses.authstate.pubkey_info); + } } /* helper for svr_add_pubkey_options. returns DROPBEAR_SUCCESS if the option is matched, From 35631a21a230321d6a42ca6891157e099dc91333 Mon Sep 17 00:00:00 2001 From: HansH111 Date: Sun, 13 Mar 2022 17:38:38 +0000 Subject: [PATCH 03/12] set envvar SSH_PUBKEYINFO if authstate.pubkey_info contains information --- svr-chansession.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/svr-chansession.c b/svr-chansession.c index 02cb035..71e0e46 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -1030,6 +1030,9 @@ static void execchild(const void *user_data) { if (chansess->original_command) { addnewvar("SSH_ORIGINAL_COMMAND", chansess->original_command); } + if (ses.authstate.pubkey_info != NULL) { + addnewvar("SSH_PUBKEYINFO", ses.authstate.pubkey_info); + } /* change directory */ if (chdir(ses.authstate.pw_dir) < 0) { From fa4a1ab435283e3ac5e986432638d55c519794c3 Mon Sep 17 00:00:00 2001 From: HansH111 Date: Sun, 13 Mar 2022 14:16:50 +0000 Subject: [PATCH 04/12] added quiet variable in cli_opts --- runopts.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runopts.h b/runopts.h index 5a59e6f..4271d1f 100644 --- a/runopts.h +++ b/runopts.h @@ -92,7 +92,6 @@ typedef struct svr_runopts { /* whether to print the MOTD */ int domotd; #endif - int norootlogin; #ifdef HAVE_GETGROUPLIST @@ -155,6 +154,7 @@ typedef struct cli_runopts { int always_accept_key; int no_hostkey_check; int no_cmd; + int quiet; int backgrounded; int is_subsystem; #if DROPBEAR_CLI_PUBKEY_AUTH From 360d60fb344da3ccd865b8a365785cd026915989 Mon Sep 17 00:00:00 2001 From: HansH111 Date: Sun, 13 Mar 2022 14:20:02 +0000 Subject: [PATCH 05/12] use option -q for suppression remote banner output, pass option also for proxy command --- cli-runopts.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cli-runopts.c b/cli-runopts.c index fdedf72..cbd15b3 100644 --- a/cli-runopts.c +++ b/cli-runopts.c @@ -62,6 +62,7 @@ static void printhelp() { "-T Don't allocate a pty\n" "-N Don't run a remote command\n" "-f Run in background after auth\n" + "-q quiet, don't show remote banner\n" "-y Always accept remote host key if unknown\n" "-y -y Don't perform any remote host key checking (caution)\n" "-s Request a subsystem (use by external sftp)\n" @@ -141,6 +142,7 @@ void cli_getopts(int argc, char ** argv) { cli_opts.username = NULL; cli_opts.cmd = NULL; cli_opts.no_cmd = 0; + cli_opts.quiet = 0; cli_opts.backgrounded = 0; cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */ cli_opts.always_accept_key = 0; @@ -214,6 +216,9 @@ void cli_getopts(int argc, char ** argv) { } cli_opts.always_accept_key = 1; break; + case 'q': /* quiet */ + cli_opts.quiet = 1; + break; case 'p': /* remoteport */ next = (char**)&cli_opts.remoteport; break; @@ -540,6 +545,12 @@ multihop_passthrough_args() { ret = m_malloc(len); total = 0; + if (cli_opts.quiet) + { + int written = snprintf(ret+total, len-total, "-q "); + total += written; + } + if (cli_opts.no_hostkey_check) { int written = snprintf(ret+total, len-total, "-y -y "); From 488ffce133dcb871a856cc35c1d9b8632ebe4147 Mon Sep 17 00:00:00 2001 From: HansH111 Date: Sun, 13 Mar 2022 14:21:13 +0000 Subject: [PATCH 06/12] only show banner when cli_opts.quiet is not set --- cli-auth.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/cli-auth.c b/cli-auth.c index 5179230..49b5ed8 100644 --- a/cli-auth.c +++ b/cli-auth.c @@ -85,31 +85,32 @@ void recv_msg_userauth_banner() { banner = buf_getstring(ses.payload, &bannerlen); buf_eatstring(ses.payload); /* The language string */ - if (bannerlen > MAX_BANNER_SIZE) { - TRACE(("recv_msg_userauth_banner: bannerlen too long: %d", bannerlen)) - truncated = 1; - } else { - cleantext(banner); + if (cli_opts.quiet == 0) { + if (bannerlen > MAX_BANNER_SIZE) { + TRACE(("recv_msg_userauth_banner: bannerlen too long: %d", bannerlen)) + truncated = 1; + } else { + cleantext(banner); - /* Limit to 24 lines */ - linecount = 1; - for (i = 0; i < bannerlen; i++) { - if (banner[i] == '\n') { - if (linecount >= MAX_BANNER_LINES) { - banner[i] = '\0'; - truncated = 1; - break; + /* Limit to 24 lines */ + linecount = 1; + for (i = 0; i < bannerlen; i++) { + if (banner[i] == '\n') { + if (linecount >= MAX_BANNER_LINES) { + banner[i] = '\0'; + truncated = 1; + break; + } + linecount++; } - linecount++; } + fprintf(stderr, "%s\n", banner); } - fprintf(stderr, "%s\n", banner); - } - if (truncated) { - fprintf(stderr, "[Banner from the server is too long]\n"); + if (truncated) { + fprintf(stderr, "[Banner from the server is too long]\n"); + } } - m_free(banner); TRACE(("leave recv_msg_userauth_banner")) } From ae8a0abc34d5717ed1fc0bf19e23431a2dd4fca4 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Tue, 15 Mar 2022 15:38:46 +0800 Subject: [PATCH 07/12] test: Set allow_reuse_addr This avoids intermittent "Address already in use" failure --- test/test_dropbear.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/test_dropbear.py b/test/test_dropbear.py index 5e7fcc6..77d1774 100644 --- a/test/test_dropbear.py +++ b/test/test_dropbear.py @@ -72,6 +72,10 @@ def own_venv_command(): return f"source {venv}/bin/activate" class HandleTcp(socketserver.ThreadingMixIn, socketserver.TCPServer): + + # override TCPServer's default, avoids TIME_WAIT + allow_reuse_addr = True + """ Listens for a single incoming request, sends a response if given, and returns the inbound data. Reponse can be a queue object, in which case each item in the queue will From 212583544a7e3c8ff988904e7c69037b4d1d612c Mon Sep 17 00:00:00 2001 From: HansH111 Date: Tue, 15 Mar 2022 18:57:21 +0000 Subject: [PATCH 08/12] use buf_getptr and m_free on every iteration before m_malloc to insure no memory leaks are happening --- svr-authpubkey.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/svr-authpubkey.c b/svr-authpubkey.c index 10356a8..70e7f70 100644 --- a/svr-authpubkey.c +++ b/svr-authpubkey.c @@ -356,6 +356,11 @@ static int checkpubkey_line(buffer* line, int line_num, const char* filename, ret = cmp_base64_key(keyblob, keybloblen, (const unsigned char *) algo, algolen, line, NULL); + /* free pubkey_info if it is filled */ + if (ses.authstate.pubkey_info) { + m_free(ses.authstate.pubkey_info); + ses.authstate.pubkey_info = NULL; + } if (ret == DROPBEAR_SUCCESS) { if (options_buf) { ret = svr_add_pubkey_options(options_buf, line_num, filename); @@ -364,11 +369,9 @@ static int checkpubkey_line(buffer* line, int line_num, const char* filename, if (infolen) { ses.authstate.pubkey_info = m_malloc(infolen + 1); if (ses.authstate.pubkey_info) { - strncpy(ses.authstate.pubkey_info, &line->data[infopos], infolen); + strncpy(ses.authstate.pubkey_info,(const char *) buf_getptr(line, infopos), infolen); ses.authstate.pubkey_info[infolen]='\0'; } - } else { - ses.authstate.pubkey_info = NULL; } } From 10875e8524b9d38c0ac278c872de697e416ebfac Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Wed, 16 Mar 2022 17:17:23 +0800 Subject: [PATCH 09/12] Fix SSH_PUBKEYINFO, limit characters, add tests We fix a bad_bufptr() failure from a previous commit. We now limit the allowed characters to those that will definitely be safe in a shell. Some scripts/programs may use arbitrary environment variables without escaping correctly - that could be a problem in a restricted environment. The current allowed set is a-z A-Z 0-9 .,_-+@ This also adds a test for SSH_PUBKEYINFO, by default it only runs under github actions (or "act -j build"). --- .github/workflows/build.yml | 9 +++++++ svr-authpubkey.c | 47 ++++++++++++++++++++++++++----------- test/test_svrauth.py | 30 +++++++++++++++++++++++ 3 files changed, 72 insertions(+), 14 deletions(-) create mode 100644 test/test_svrauth.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bf785b9..ba207ec 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -86,6 +86,8 @@ jobs: # for fuzzing CXX: clang++ RANLIB: ${{ matrix.ranlib || 'ranlib' }} + # some pytests depend on special setup from this file. see authorized_keys below. + DBTEST_IN_ACTION: true steps: - name: deps @@ -128,7 +130,14 @@ jobs: - name: keys run: | mkdir -p ~/.ssh + # remove old files so we can rerun in-place with "act -r" during test development + rm -vf ~/.ssh/id_dropbear* ~/inst/bin/dropbearkey -t ecdsa -f ~/.ssh/id_dropbear | grep ^ecdsa > ~/.ssh/authorized_keys + + # to test setting SSH_PUBKEYINFO, replace the trailing comment + ~/inst/bin/dropbearkey -t ecdsa -f ~/.ssh/id_dropbear_key2 | grep ^ecdsa | sed 's/[^ ]*$/key2 extra/' >> ~/.ssh/authorized_keys + ~/inst/bin/dropbearkey -t ecdsa -f ~/.ssh/id_dropbear_key3 | grep ^ecdsa | sed 's/[^ ]*$/key3%char/' >> ~/.ssh/authorized_keys + ~/inst/bin/dropbearkey -t ecdsa -f ~/.ssh/id_dropbear_key4 | grep ^ecdsa | sed 's/[^ ]*$/key4,char/' >> ~/.ssh/authorized_keys chmod 700 ~ ~/.ssh ~/.ssh/authorized_keys ls -ld ~ ~/.ssh ~/.ssh/authorized_keys diff --git a/svr-authpubkey.c b/svr-authpubkey.c index 70e7f70..912114a 100644 --- a/svr-authpubkey.c +++ b/svr-authpubkey.c @@ -261,6 +261,7 @@ static int checkpubkey_line(buffer* line, int line_num, const char* filename, const char* algo, unsigned int algolen, const unsigned char* keyblob, unsigned int keybloblen) { buffer *options_buf = NULL; + char *info_str = NULL; unsigned int pos, len, infopos, infolen; int ret = DROPBEAR_FAILURE; @@ -339,16 +340,36 @@ static int checkpubkey_line(buffer* line, int line_num, const char* filename, goto out; } - /* truncate the line at the space after the base64 data */ + /* find the length of base64 data */ pos = line->pos; for (len = 0; line->pos < line->len; len++) { - if (buf_getbyte(line) == ' ') break; - } - /* findout the length of the public key info */ + if (buf_getbyte(line) == ' ') { + break; + } + } + + /* find out the length of the public key info, stop at the first space */ infopos = line->pos; for (infolen = 0; line->pos < line->len; infolen++) { - if (buf_getbyte(line) == ' ') break; + const char c = buf_getbyte(line); + if (c == ' ') { + break; + } + /* We have an allowlist - authorized_keys lines can't be fully trusted, + some shell scripts may do unsafe things with env var values */ + if (!(isalnum(c) || strchr(".,_-+@", c))) { + TRACE(("Not setting SSH_PUBKEYINFO, special characters")) + infolen = 0; + break; + } } + if (infolen > 0) { + info_str = m_malloc(infolen + 1); + buf_setpos(line, infopos); + strncpy(info_str, buf_getptr(line, infolen), infolen); + } + + /* truncate to base64 data length */ buf_setpos(line, pos); buf_setlen(line, line->pos + len); @@ -359,26 +380,24 @@ static int checkpubkey_line(buffer* line, int line_num, const char* filename, /* free pubkey_info if it is filled */ if (ses.authstate.pubkey_info) { m_free(ses.authstate.pubkey_info); - ses.authstate.pubkey_info = NULL; } + if (ret == DROPBEAR_SUCCESS) { if (options_buf) { ret = svr_add_pubkey_options(options_buf, line_num, filename); } - /* save the (optional) public key information */ - if (infolen) { - ses.authstate.pubkey_info = m_malloc(infolen + 1); - if (ses.authstate.pubkey_info) { - strncpy(ses.authstate.pubkey_info,(const char *) buf_getptr(line, infopos), infolen); - ses.authstate.pubkey_info[infolen]='\0'; - } - } + /* take the (optional) public key information */ + ses.authstate.pubkey_info = info_str; + info_str = NULL; } out: if (options_buf) { buf_free(options_buf); } + if (info_str) { + m_free(info_str); + } return ret; } diff --git a/test/test_svrauth.py b/test/test_svrauth.py new file mode 100644 index 0000000..0ded6d4 --- /dev/null +++ b/test/test_svrauth.py @@ -0,0 +1,30 @@ +from test_dropbear import * +import signal +import queue +import socket +import os +from pathlib import Path + +# Tests for server side authentication + +# Requires keyfile and authorized_keys set up in github action build.yml +@pytest.mark.skipif('DBTEST_IN_ACTION' not in os.environ, reason="DBTEST_PUBKEYINFO not set") +def test_pubkeyinfo(request, dropbear): + kf = str(Path.home() / ".ssh/id_dropbear_key2") + r = dbclient(request, "-i", kf, "echo -n $SSH_PUBKEYINFO", capture_output=True) + # stop at first space + assert r.stdout.decode() == "key2" + +@pytest.mark.skipif('DBTEST_IN_ACTION' not in os.environ, reason="DBTEST_PUBKEYINFO not set") +def test_pubkeyinfo_special(request, dropbear): + kf = str(Path.home() / ".ssh/id_dropbear_key3") + r = dbclient(request, "-i", kf, "echo -n $SSH_PUBKEYINFO", capture_output=True) + # comment contains special characters so the SSH_PUBKEYINFO should not be set + assert r.stdout.decode() == "" + +@pytest.mark.skipif('DBTEST_IN_ACTION' not in os.environ, reason="DBTEST_PUBKEYINFO not set") +def test_pubkeyinfo_okchar(request, dropbear): + kf = str(Path.home() / ".ssh/id_dropbear_key4") + r = dbclient(request, "-i", kf, "echo -n $SSH_PUBKEYINFO", capture_output=True) + # comment contains special characters so the SSH_PUBKEYINFO should not be set + assert r.stdout.decode() == "key4,char" From b58f96526acb8bf9b333766499a6d758030d9fa9 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Wed, 16 Mar 2022 17:25:03 +0800 Subject: [PATCH 10/12] Disable aslr pytest for fsanitize test platforms --- .github/workflows/build.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ba207ec..d474866 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -65,6 +65,8 @@ jobs: # configure_flags: --enable-fuzz --disable-harden --enable-bundled-libtom --enable-werror # ldflags: -fsanitize=address # extracflags: -fsanitize=address + # # -fsanitize=address prevents aslr, don't test it + # pytest_addopts: -k "not aslr" # fuzz: True # cc: clang @@ -74,6 +76,7 @@ jobs: # ldflags: -fsanitize=undefined # # don't fail with alignment due to https://github.com/libtom/libtomcrypt/issues/549 # extracflags: -fsanitize=undefined -fno-sanitize-recover=undefined -fsanitize-recover=alignment + # pytest_addopts: -k "not aslr" # fuzz: True # cc: clang @@ -86,6 +89,8 @@ jobs: # for fuzzing CXX: clang++ RANLIB: ${{ matrix.ranlib || 'ranlib' }} + # pytest in "make check" recognises this for extra arguments + PYTEST_ADDOPTS: ${{ matrix.pytest_addopts }} # some pytests depend on special setup from this file. see authorized_keys below. DBTEST_IN_ACTION: true From 678cc6fcc082f5921cc7f90a5fcee5a923ddb9e9 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Wed, 16 Mar 2022 17:32:43 +0800 Subject: [PATCH 11/12] Fix pytest incorrect skip "reason" string No change to functionality --- test/test_svrauth.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_svrauth.py b/test/test_svrauth.py index 0ded6d4..88f13fa 100644 --- a/test/test_svrauth.py +++ b/test/test_svrauth.py @@ -8,21 +8,21 @@ from pathlib import Path # Tests for server side authentication # Requires keyfile and authorized_keys set up in github action build.yml -@pytest.mark.skipif('DBTEST_IN_ACTION' not in os.environ, reason="DBTEST_PUBKEYINFO not set") +@pytest.mark.skipif('DBTEST_IN_ACTION' not in os.environ, reason="DBTEST_IN_ACTION not set") def test_pubkeyinfo(request, dropbear): kf = str(Path.home() / ".ssh/id_dropbear_key2") r = dbclient(request, "-i", kf, "echo -n $SSH_PUBKEYINFO", capture_output=True) # stop at first space assert r.stdout.decode() == "key2" -@pytest.mark.skipif('DBTEST_IN_ACTION' not in os.environ, reason="DBTEST_PUBKEYINFO not set") +@pytest.mark.skipif('DBTEST_IN_ACTION' not in os.environ, reason="DBTEST_IN_ACTION not set") def test_pubkeyinfo_special(request, dropbear): kf = str(Path.home() / ".ssh/id_dropbear_key3") r = dbclient(request, "-i", kf, "echo -n $SSH_PUBKEYINFO", capture_output=True) # comment contains special characters so the SSH_PUBKEYINFO should not be set assert r.stdout.decode() == "" -@pytest.mark.skipif('DBTEST_IN_ACTION' not in os.environ, reason="DBTEST_PUBKEYINFO not set") +@pytest.mark.skipif('DBTEST_IN_ACTION' not in os.environ, reason="DBTEST_IN_ACTION not set") def test_pubkeyinfo_okchar(request, dropbear): kf = str(Path.home() / ".ssh/id_dropbear_key4") r = dbclient(request, "-i", kf, "echo -n $SSH_PUBKEYINFO", capture_output=True) From 98ef42a8567399edfdca696a4399ef8830e2b34a Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Wed, 16 Mar 2022 18:35:23 +0800 Subject: [PATCH 12/12] Don't set pubkey_info directly in checkpubkey_line This makes it safe to use from fuzzer-pubkey without leaking the value since the cleanup isn't called --- svr-authpubkey.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/svr-authpubkey.c b/svr-authpubkey.c index 912114a..e58751b 100644 --- a/svr-authpubkey.c +++ b/svr-authpubkey.c @@ -257,9 +257,12 @@ static void send_msg_userauth_pk_ok(const char* sigalgo, unsigned int sigalgolen } +/* Content for SSH_PUBKEYINFO is optionally returned malloced in ret_info (will be + freed if already set */ static int checkpubkey_line(buffer* line, int line_num, const char* filename, const char* algo, unsigned int algolen, - const unsigned char* keyblob, unsigned int keybloblen) { + const unsigned char* keyblob, unsigned int keybloblen, + char ** ret_info) { buffer *options_buf = NULL; char *info_str = NULL; unsigned int pos, len, infopos, infolen; @@ -378,17 +381,20 @@ static int checkpubkey_line(buffer* line, int line_num, const char* filename, ret = cmp_base64_key(keyblob, keybloblen, (const unsigned char *) algo, algolen, line, NULL); /* free pubkey_info if it is filled */ - if (ses.authstate.pubkey_info) { - m_free(ses.authstate.pubkey_info); + if (ret_info && *ret_info) { + m_free(*ret_info); + *ret_info = NULL; } if (ret == DROPBEAR_SUCCESS) { if (options_buf) { ret = svr_add_pubkey_options(options_buf, line_num, filename); } - /* take the (optional) public key information */ - ses.authstate.pubkey_info = info_str; - info_str = NULL; + if (ret_info) { + /* take the (optional) public key information */ + *ret_info = info_str; + info_str = NULL; + } } out: @@ -470,7 +476,8 @@ static int checkpubkey(const char* keyalgo, unsigned int keyalgolen, } line_num++; - ret = checkpubkey_line(line, line_num, filename, keyalgo, keyalgolen, keyblob, keybloblen); + ret = checkpubkey_line(line, line_num, filename, keyalgo, keyalgolen, + keyblob, keybloblen, &ses.authstate.pubkey_info); if (ret == DROPBEAR_SUCCESS) { break; } @@ -587,7 +594,7 @@ static int checkfileperm(char * filename) { int fuzz_checkpubkey_line(buffer* line, int line_num, char* filename, const char* algo, unsigned int algolen, const unsigned char* keyblob, unsigned int keybloblen) { - return checkpubkey_line(line, line_num, filename, algo, algolen, keyblob, keybloblen); + return checkpubkey_line(line, line_num, filename, algo, algolen, keyblob, keybloblen, NULL); } #endif