From eb9422dc0e8e65e4055553922b75fe1a385a297a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 5 Oct 2025 23:19:13 +0200 Subject: [PATCH] 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 --- docs/cmdline-opts/Makefile.inc | 1 + docs/cmdline-opts/knownhosts.md | 31 +++++++++++++++++++++++++++++++ src/config2setopts.c | 6 +++--- src/tool_cfgable.c | 1 + src/tool_cfgable.h | 3 +-- src/tool_getparam.c | 4 ++++ src/tool_getparam.h | 1 + src/tool_listhelp.c | 3 +++ src/tool_operate.c | 1 - 9 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 docs/cmdline-opts/knownhosts.md diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc index b8e88421a9..f7236af1b1 100644 --- a/docs/cmdline-opts/Makefile.inc +++ b/docs/cmdline-opts/Makefile.inc @@ -147,6 +147,7 @@ DPAGES = \ keepalive-time.md \ key-type.md \ key.md \ + knownhosts.md \ krb.md \ libcurl.md \ limit-rate.md \ diff --git a/docs/cmdline-opts/knownhosts.md b/docs/cmdline-opts/knownhosts.md new file mode 100644 index 0000000000..96cf3ea35b --- /dev/null +++ b/docs/cmdline-opts/knownhosts.md @@ -0,0 +1,31 @@ +--- +c: Copyright (C) Daniel Stenberg, , et al. +SPDX-License-Identifier: curl +Long: knownhosts +Arg: +Protocols: SCP SFTP +Help: Specify knownhosts path +Category: ssh +Added: 8.17.0 +Multi: single +See-also: + - hostpubsha256 + - hostpubmd5 + - insecure + - key +Example: + - --cert certificate --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 knownhosts file. By default curl uses ~/.ssh/known_hosts in the +user's home directory. + +This option lets a user specify a specific file to check the host against. + +The known host check can be disabled with --insecure, but that makes the +transfer insecure. diff --git a/src/config2setopts.c b/src/config2setopts.c index 533fe992d3..ef08f98ed8 100644 --- a/src/config2setopts.c +++ b/src/config2setopts.c @@ -192,7 +192,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); @@ -200,12 +200,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"); diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c index e2df7cf91f..48148a88ad 100644 --- a/src/tool_cfgable.c +++ b/src/tool_cfgable.c @@ -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) diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index 3b2ac93a74..0f86c000a2 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -112,6 +112,7 @@ struct OperationConfig { char *proxyuserpwd; char *proxy; char *noproxy; + char *knownhosts; char *mail_from; struct curl_slist *mail_rcpt; char *mail_auth; @@ -353,8 +354,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; diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 0fdd6373e5..7b8dec7da5 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -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; diff --git a/src/tool_getparam.h b/src/tool_getparam.h index a08bbac7b6..6b97b9c11f 100644 --- a/src/tool_getparam.h +++ b/src/tool_getparam.h @@ -139,6 +139,7 @@ typedef enum { C_KEEPALIVE_TIME, C_KEY, C_KEY_TYPE, + C_KNOWNHOSTS, C_KRB, C_KRB4, C_LIBCURL, diff --git a/src/tool_listhelp.c b/src/tool_listhelp.c index bd72dbe15c..c8e31e77a6 100644 --- a/src/tool_listhelp.c +++ b/src/tool_listhelp.c @@ -341,6 +341,9 @@ const struct helptxt helptext[] = { {" --key-type ", "Private key file type (DER/PEM/ENG)", CURLHELP_TLS}, + {" --knownhosts ", + "Specify knownhosts path", + CURLHELP_SSH}, {" --krb ", "Enable Kerberos with security ", CURLHELP_DEPRECATED}, diff --git a/src/tool_operate.c b/src/tool_operate.c index d4a6d4db42..0e96ccd85f 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -2265,7 +2265,6 @@ CURLcode operate(int argc, argv_item_t argv[]) } varcleanup(); - curl_free(global->knownhosts); return result; }