]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tool_getparam: add --knownhosts
authorDaniel Stenberg <daniel@haxx.se>
Sun, 5 Oct 2025 21:19:13 +0000 (23:19 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 6 Oct 2025 11:41:22 +0000 (13:41 +0200)
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

docs/cmdline-opts/Makefile.inc
docs/cmdline-opts/knownhosts.md [new file with mode: 0644]
docs/options-in-versions
src/config2setopts.c
src/tool_cfgable.c
src/tool_cfgable.h
src/tool_getparam.c
src/tool_getparam.h
src/tool_listhelp.c
src/tool_operate.c
tests/data/test1459

index b8e88421a9a0355cd8def7b0402c12a6153ecbef..f7236af1b12707ac8242cfd30a34bcbf0e9e8b66 100644 (file)
@@ -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 (file)
index 0000000..4709563
--- /dev/null
@@ -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.
index 6d2a9057fa7a2ede686b6b58f79987d2b8a29e4b..95d84a4bfec21093a7a6886e3fd23a8482d57ab1 100644 (file)
 --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
index 5921cd73ce0817327cd4618d8175e38cf21cc25e..0a519ed048654361c72168f3e50c6e3825cc4c5f 100644 (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");
index e2df7cf91f02d5955adf5fa7242a96b72626c4c7..48148a88ad5bce13644fb10ce2f98f3650aaaaf5 100644 (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)
index 762837055106e7a17153cd4433c6ae0e0612950f..3c67695124e7a9849bb7904821a960e12d4d6760 100644 (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;
index a54d3f804c8cd68aacf7e6c5b4845aa518955649..b533f41aa7dfa5bea734a230232018bef9392b66 100644 (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;
index a08bbac7b640092231158901309dda18cc3273c2..6b97b9c11f45806f00d11f5d1bf48e9dd0edbcd7 100644 (file)
@@ -139,6 +139,7 @@ typedef enum {
   C_KEEPALIVE_TIME,
   C_KEY,
   C_KEY_TYPE,
+  C_KNOWNHOSTS,
   C_KRB,
   C_KRB4,
   C_LIBCURL,
index bd72dbe15c51c04976e0102e8f6ac305046ed683..c8e31e77a6aed1f6512251b61b89ba67e68b31fc 100644 (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},
index b49f45fd99041050fe523a438e3692c37616f091..38482b496e7f023fae7b4c40b99688757171eba3 100644 (file)
@@ -2273,7 +2273,6 @@ CURLcode operate(int argc, argv_item_t argv[])
   }
 
   varcleanup();
-  curl_free(global->knownhosts);
 
   return result;
 }
index 335b26576632c0092082389088140377e03e0ed7..e4901d74f06c5b3b05773a91a94b4b261f409465 100644 (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"