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