1---
2c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
3SPDX-License-Identifier: curl
4Title: CURLOPT_SSH_KEYFUNCTION
5Section: 3
6Source: libcurl
7See-also:
8  - CURLOPT_SSH_KEYDATA (3)
9  - CURLOPT_SSH_KNOWNHOSTS (3)
10Protocol:
11  - SFTP
12  - SCP
13---
14
15# NAME
16
17CURLOPT_SSH_KEYFUNCTION - callback for known host matching logic
18
19# SYNOPSIS
20
21~~~c
22#include <curl/curl.h>
23
24enum curl_khstat {
25  CURLKHSTAT_FINE_ADD_TO_FILE,
26  CURLKHSTAT_FINE,
27  CURLKHSTAT_REJECT, /* reject the connection, return an error */
28  CURLKHSTAT_DEFER,  /* do not accept it, but we cannot answer right
29                        now. Causes a CURLE_PEER_FAILED_VERIFICATION error but
30                        the connection is left intact */
31  CURLKHSTAT_FINE_REPLACE
32};
33
34enum curl_khmatch {
35  CURLKHMATCH_OK,       /* match */
36  CURLKHMATCH_MISMATCH, /* host found, key mismatch! */
37  CURLKHMATCH_MISSING,  /* no matching host/key found */
38};
39
40struct curl_khkey {
41  const char *key; /* points to a null-terminated string encoded with
42                      base64 if len is zero, otherwise to the "raw"
43                      data */
44  size_t len;
45  enum curl_khtype keytype;
46};
47
48int ssh_keycallback(CURL *easy,
49                    const struct curl_khkey *knownkey,
50                    const struct curl_khkey *foundkey,
51                    enum curl_khmatch match,
52                    void *clientp);
53
54CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_KEYFUNCTION,
55                          ssh_keycallback);
56~~~
57
58# DESCRIPTION
59
60Pass a pointer to your callback function, which should match the prototype
61shown above.
62
63It gets called when the known_host matching has been done, to allow the
64application to act and decide for libcurl how to proceed. The callback is only
65called if CURLOPT_SSH_KNOWNHOSTS(3) is also set.
66
67This callback function gets passed the CURL handle, the key from the
68known_hosts file *knownkey*, the key from the remote site *foundkey*,
69info from libcurl on the matching status and a custom pointer (set with
70CURLOPT_SSH_KEYDATA(3)). It MUST return one of the following return
71codes to tell libcurl how to act:
72
73## CURLKHSTAT_FINE_REPLACE
74
75The new host+key is accepted and libcurl replaces the old host+key into the
76known_hosts file before continuing with the connection. This also adds the new
77host+key combo to the known_host pool kept in memory if it was not already
78present there. The adding of data to the file is done by completely replacing
79the file with a new copy, so the permissions of the file must allow
80this. (Added in 7.73.0)
81
82## CURLKHSTAT_FINE_ADD_TO_FILE
83
84The host+key is accepted and libcurl appends it to the known_hosts file before
85continuing with the connection. This also adds the host+key combo to the
86known_host pool kept in memory if it was not already present there. The adding
87of data to the file is done by completely replacing the file with a new copy,
88so the permissions of the file must allow this.
89
90## CURLKHSTAT_FINE
91
92The host+key is accepted libcurl continues with the connection. This also adds
93the host+key combo to the known_host pool kept in memory if it was not already
94present there.
95
96## CURLKHSTAT_REJECT
97
98The host+key is rejected. libcurl denies the connection to continue and it is
99closed.
100
101## CURLKHSTAT_DEFER
102
103The host+key is rejected, but the SSH connection is asked to be kept alive.
104This feature could be used when the app wants to return and act on the
105host+key situation and then retry without needing the overhead of setting it
106up from scratch again.
107
108# DEFAULT
109
110NULL
111
112# EXAMPLE
113
114~~~c
115struct mine {
116  void *custom;
117};
118
119static int keycb(CURL *easy,
120                 const struct curl_khkey *knownkey,
121                 const struct curl_khkey *foundkey,
122                 enum curl_khmatch match,
123                 void *clientp)
124{
125  /* 'clientp' points to the callback_data struct */
126  /* investigate the situation and return the correct value */
127  return CURLKHSTAT_FINE_ADD_TO_FILE;
128}
129
130int main(void)
131{
132  CURL *curl = curl_easy_init();
133  if(curl) {
134    struct mine callback_data;
135    curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/thisfile.txt");
136    curl_easy_setopt(curl, CURLOPT_SSH_KEYFUNCTION, keycb);
137    curl_easy_setopt(curl, CURLOPT_SSH_KEYDATA, &callback_data);
138    curl_easy_setopt(curl, CURLOPT_SSH_KNOWNHOSTS, "/home/user/known_hosts");
139
140    curl_easy_perform(curl);
141}
142}
143~~~
144
145# AVAILABILITY
146
147Added in 7.19.6
148
149# RETURN VALUE
150
151Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
152