Mercurial > dropbear
diff svr-authpubkey.c @ 1890:45e552ee4391
merge
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Tue, 22 Mar 2022 16:17:47 +0800 |
parents | a7b66ea18632 |
children | f8ed10efaaac |
line wrap: on
line diff
--- a/svr-authpubkey.c Tue Mar 22 16:17:05 2022 +0800 +++ b/svr-authpubkey.c Tue Mar 22 16:17:47 2022 +0800 @@ -257,11 +257,15 @@ } +/* 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; - unsigned int pos, len; + char *info_str = NULL; + unsigned int pos, len, infopos, infolen; int ret = DROPBEAR_FAILURE; if (line->len < MIN_AUTHKEYS_LINE || line->len > MAX_AUTHKEYS_LINE) { @@ -339,11 +343,36 @@ 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; - } + 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++) { + 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); @@ -351,14 +380,30 @@ 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); + /* free pubkey_info if it is filled */ + 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); + } + if (ret_info) { + /* take the (optional) public key information */ + *ret_info = info_str; + info_str = NULL; + } } out: if (options_buf) { buf_free(options_buf); } + if (info_str) { + m_free(info_str); + } return ret; } @@ -431,7 +476,8 @@ } 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; } @@ -548,7 +594,7 @@ 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