tool_getparam: add --knownhosts

To allow users to specify a known hosts file that is not the default
one: ~/.ssh/known_hosts

URL: https://github.com/curl/curl/discussions/18784
Closes #18859
This commit is contained in:
Daniel Stenberg
2025-10-05 23:19:13 +02:00
parent 762ce8801b
commit aae18c4bdc
11 changed files with 48 additions and 14 deletions

View File

@@ -147,6 +147,7 @@ DPAGES = \
keepalive-time.md \
key-type.md \
key.md \
knownhosts.md \
krb.md \
libcurl.md \
limit-rate.md \

View File

@@ -0,0 +1,31 @@
---
c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: knownhosts
Arg: <file>
Protocols: SCP SFTP
Help: Specify knownhosts path
Category: ssh
Added: 8.17.0
Multi: single
See-also:
- hostpubsha256
- hostpubmd5
- insecure
- key
Example:
- --knownhost filename --key here $URL
---
# `--knownhosts`
When doing SCP and SFTP transfers, curl automatically checks a database
containing identification for all hosts it has ever been used with to verify
that the host it connects to is the same as previously. Host keys are stored
in such a known hosts file. curl uses the ~/.ssh/known_hosts in the user's
home directory by default.
This option lets a user specify a specific file to check the host against.
The known hosts check can be disabled with --insecure, but that makes the
transfer insecure and is strongly discouraged.

View File

@@ -111,6 +111,7 @@
--keepalive-time 7.18.0
--key 7.9.3
--key-type 7.9.3
--knownhosts 8.17.0
--krb 7.3
--libcurl 7.16.1
--limit-rate 7.10

View File

@@ -195,7 +195,7 @@ static CURLcode ssh_setopts(struct OperationConfig *config, CURL *curl)
my_setopt_long(curl, CURLOPT_SSH_COMPRESSION, 1);
if(!config->insecure_ok) {
char *known = global->knownhosts;
char *known = config->knownhosts;
if(!known)
known = findfile(".ssh/known_hosts", FALSE);
@@ -203,12 +203,12 @@ static CURLcode ssh_setopts(struct OperationConfig *config, CURL *curl)
/* new in curl 7.19.6 */
result = my_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, known);
if(result) {
global->knownhosts = NULL;
config->knownhosts = NULL;
curl_free(known);
return result;
}
/* store it in global to avoid repeated checks */
global->knownhosts = known;
config->knownhosts = known;
}
else if(!config->hostpubmd5 && !config->hostpubsha256) {
errorf("Couldn't find a known_hosts file");

View File

@@ -189,6 +189,7 @@ static void free_config_fields(struct OperationConfig *config)
tool_safefree(config->ech);
tool_safefree(config->ech_config);
tool_safefree(config->ech_public);
tool_safefree(config->knownhosts);
}
void config_free(struct OperationConfig *config)

View File

@@ -94,6 +94,7 @@ struct OperationConfig {
char *proxyuserpwd;
char *proxy;
char *noproxy;
char *knownhosts;
char *mail_from;
struct curl_slist *mail_rcpt;
char *mail_auth;
@@ -335,8 +336,6 @@ struct GlobalConfig {
FILE *trace_stream;
char *libcurl; /* Output libcurl code to this filename */
char *ssl_sessions; /* file to load/save SSL session tickets */
char *knownhosts; /* known host path, if set. curl_free()
this */
struct tool_var *variables;
struct OperationConfig *first;
struct OperationConfig *current;

View File

@@ -196,6 +196,7 @@ static const struct LongShort aliases[]= {
{"keepalive-time", ARG_STRG, ' ', C_KEEPALIVE_TIME},
{"key", ARG_FILE, ' ', C_KEY},
{"key-type", ARG_STRG|ARG_TLS, ' ', C_KEY_TYPE},
{"knownhosts", ARG_FILE, ' ', C_KNOWNHOSTS},
{"krb", ARG_STRG|ARG_DEPR, ' ', C_KRB},
{"krb4", ARG_STRG|ARG_DEPR, ' ', C_KRB4},
{"libcurl", ARG_STRG, ' ', C_LIBCURL},
@@ -2224,6 +2225,9 @@ static ParameterError opt_file(struct OperationConfig *config,
case C_KEY: /* --key */
err = getstr(&config->key, nextarg, DENY_BLANK);
break;
case C_KNOWNHOSTS: /* --knownhosts */
err = getstr(&config->knownhosts, nextarg, DENY_BLANK);
break;
case C_NETRC_FILE: /* --netrc-file */
err = getstr(&config->netrc_file, nextarg, DENY_BLANK);
break;

View File

@@ -139,6 +139,7 @@ typedef enum {
C_KEEPALIVE_TIME,
C_KEY,
C_KEY_TYPE,
C_KNOWNHOSTS,
C_KRB,
C_KRB4,
C_LIBCURL,

View File

@@ -341,6 +341,9 @@ const struct helptxt helptext[] = {
{" --key-type <type>",
"Private key file type (DER/PEM/ENG)",
CURLHELP_TLS},
{" --knownhosts <file>",
"Specify knownhosts path",
CURLHELP_SSH},
{" --krb <level>",
"Enable Kerberos with security <level>",
CURLHELP_DEPRECATED},

View File

@@ -2273,7 +2273,6 @@ CURLcode operate(int argc, argv_item_t argv[])
}
varcleanup();
curl_free(global->knownhosts);
return result;
}

View File

@@ -12,9 +12,6 @@ known_hosts
<server>
sftp
</server>
<precheck>
mkdir -p %PWD/%LOGDIR/test%TESTNUMBER.dir/.ssh
</precheck>
<features>
sftp
!oldlibssh
@@ -23,15 +20,12 @@ sftp
SFTP with corrupted known_hosts
</name>
<command>
-u : sftp://%HOSTIP:%SSHPORT/ -l
-u : sftp://%HOSTIP:%SSHPORT/ -l --knownhosts %LOGDIR/known%TESTNUMBER
</command>
<file name="%LOGDIR/test%TESTNUMBER.dir/.ssh/known_hosts">
<file name="%LOGDIR/known%TESTNUMBER">
|1|qy29Y1x/+/F39AzdG5515YSSw+c=|iB2WX5jrU3ZTWc+ZfGau7HHEvBc= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAynDN8cDJ3xNzRjTNNGciSHSxpubxhZ6YnkLdp1TkrGW8n\
R93Ey5VtBeBblYTRlFXBWJgKFcTKBRJ/O4qBZwbUgt10AHj31i6h8NehfT19tR8wG/YCmj3KtYLHmwdzmW1edEL9G2NdX2KiKYv7/zuly3QvmP0QA0NhWkAz0KdWNM=
</file>
<setenv>
CURL_HOME=%PWD/%LOGDIR/test%TESTNUMBER.dir
</setenv>
</client>
# Verify data after the test has been "shot"