mirror of
https://github.com/curl/curl.git
synced 2026-08-04 15:06:19 +03:00
hardening: add API guards
Add call stacks to easy and multi instances. Record ongoing API calls and callback invocations there to detect recursion and not allowed invocations. Define enums for easy, multi and callbacks in `api.h`. In `api.c` define properties for these functions: - can they recurse - is the easy/multi handle destroyed during the call or should it be good afterwards - is the call allowed when a multi event callback is ongoing - is the call allowed when a notification callback is ongoing Entering a guard - checks that passed CURL*/CURLM* are GOOD on entering - checks that easy handle's `mid` is correct and it is known for it in the multi. - checks that call properties are obeyed (recursion, callback checks) - checks that passed CURL*/CURLM* are GOOD on leaving, unless call is known to kill it Checks for ongoing callbacks inspect the whole call stack and catches nested invocations (which our current flags can not). Call stacks in easy/multi handle are fixed size and will deny recursion when the limit is reached. The current limits are 7 for easy and 15 for multi now. Removes: - multi->in_callback, check is done via call stack - multi->in_ntfy_cb, check is done via call stack The overhead in my tests seems minimal, if noticeable at all. Closes #22237
This commit is contained in:
parent
ab8d771d31
commit
dfc01ea2a3
30 changed files with 1667 additions and 943 deletions
|
|
@ -290,6 +290,8 @@ static int myssh_is_known(struct Curl_easy *data, struct ssh_conn *sshc)
|
|||
}
|
||||
|
||||
if(func) { /* use callback to determine action */
|
||||
struct Curl_mapi_guard guard;
|
||||
|
||||
rc = ssh_pki_export_pubkey_base64(pubkey, &found_base64);
|
||||
if(rc != SSH_OK)
|
||||
goto cleanup;
|
||||
|
|
@ -321,11 +323,11 @@ static int myssh_is_known(struct Curl_easy *data, struct ssh_conn *sshc)
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
Curl_set_in_callback(data, TRUE);
|
||||
CURL_CBAPI_START(&guard, data, easy_ssh_keyfunc);
|
||||
rc = func(data, knownkeyp, /* from the knownhosts file */
|
||||
&foundkey, /* from the remote host */
|
||||
keymatch, data->set.ssh_keyfunc_userp);
|
||||
Curl_set_in_callback(data, FALSE);
|
||||
CURL_CBAPI_END(&guard);
|
||||
|
||||
switch(rc) {
|
||||
case CURLKHSTAT_FINE_ADD_TO_FILE:
|
||||
|
|
@ -1097,10 +1099,11 @@ static int myssh_in_UPLOAD_INIT(struct Curl_easy *data,
|
|||
int seekerr = CURL_SEEKFUNC_OK;
|
||||
/* Let's read off the proper amount of bytes from the input. */
|
||||
if(data->set.seek_func) {
|
||||
Curl_set_in_callback(data, TRUE);
|
||||
struct Curl_mapi_guard guard;
|
||||
CURL_CBAPI_START(&guard, data, easy_seek_func);
|
||||
seekerr = data->set.seek_func(data->set.seek_client,
|
||||
data->state.resume_from, SEEK_SET);
|
||||
Curl_set_in_callback(data, FALSE);
|
||||
CURL_CBAPI_END(&guard);
|
||||
}
|
||||
|
||||
if(seekerr != CURL_SEEKFUNC_OK) {
|
||||
|
|
|
|||
|
|
@ -330,6 +330,7 @@ static CURLcode ssh_knownhost(struct Curl_easy *data,
|
|||
* What hostname does OpenSSH store in its file if an IDN name is
|
||||
* used?
|
||||
*/
|
||||
struct Curl_mapi_guard guard;
|
||||
enum curl_khmatch keymatch;
|
||||
curl_sshkeycallback func =
|
||||
data->set.ssh_keyfunc ? data->set.ssh_keyfunc : sshkeycallback;
|
||||
|
|
@ -402,11 +403,11 @@ static CURLcode ssh_knownhost(struct Curl_easy *data,
|
|||
keymatch = (enum curl_khmatch)keycheck;
|
||||
|
||||
/* Ask the callback how to behave */
|
||||
Curl_set_in_callback(data, TRUE);
|
||||
CURL_CBAPI_START(&guard, data, easy_ssh_keyfunc);
|
||||
rc = func(data, knownkeyp, /* from the knownhosts file */
|
||||
&foundkey, /* from the remote host */
|
||||
keymatch, data->set.ssh_keyfunc_userp);
|
||||
Curl_set_in_callback(data, FALSE);
|
||||
CURL_CBAPI_END(&guard);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -595,11 +596,12 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data,
|
|||
const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
|
||||
&keylen, &sshkeytype);
|
||||
if(remotekey) {
|
||||
struct Curl_mapi_guard guard;
|
||||
enum curl_khtype keytype = convert_ssh2_keytype(sshkeytype);
|
||||
Curl_set_in_callback(data, TRUE);
|
||||
CURL_CBAPI_START(&guard, data, easy_ssh_hostkeyfunc);
|
||||
rc = data->set.ssh_hostkeyfunc(data->set.ssh_hostkeyfunc_userp,
|
||||
(int)keytype, remotekey, keylen);
|
||||
Curl_set_in_callback(data, FALSE);
|
||||
CURL_CBAPI_END(&guard);
|
||||
if(rc != CURLKHMATCH_OK) {
|
||||
myssh_to(data, sshc, SSH_SESSION_FREE);
|
||||
failf(data, "SSH: callback failed host public key verification");
|
||||
|
|
@ -1028,10 +1030,11 @@ static CURLcode sftp_upload_init(struct Curl_easy *data,
|
|||
int seekerr = CURL_SEEKFUNC_OK;
|
||||
/* Let's read off the proper amount of bytes from the input. */
|
||||
if(data->set.seek_func) {
|
||||
Curl_set_in_callback(data, TRUE);
|
||||
struct Curl_mapi_guard guard;
|
||||
CURL_CBAPI_START(&guard, data, easy_seek_func);
|
||||
seekerr = data->set.seek_func(data->set.seek_client,
|
||||
data->state.resume_from, SEEK_SET);
|
||||
Curl_set_in_callback(data, FALSE);
|
||||
CURL_CBAPI_END(&guard);
|
||||
}
|
||||
|
||||
if(seekerr != CURL_SEEKFUNC_OK) {
|
||||
|
|
@ -1043,6 +1046,7 @@ static CURLcode sftp_upload_init(struct Curl_easy *data,
|
|||
}
|
||||
/* seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */
|
||||
do {
|
||||
struct Curl_mapi_guard guard;
|
||||
char scratch[4 * 1024];
|
||||
size_t readthisamountnow =
|
||||
(data->state.resume_from - passed >
|
||||
|
|
@ -1050,11 +1054,11 @@ static CURLcode sftp_upload_init(struct Curl_easy *data,
|
|||
sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed);
|
||||
|
||||
size_t actuallyread;
|
||||
Curl_set_in_callback(data, TRUE);
|
||||
CURL_CBAPI_START(&guard, data, easy_fread_func);
|
||||
actuallyread = data->state.fread_func(scratch, 1,
|
||||
readthisamountnow,
|
||||
data->state.in);
|
||||
Curl_set_in_callback(data, FALSE);
|
||||
CURL_CBAPI_END(&guard);
|
||||
|
||||
passed += actuallyread;
|
||||
if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue