mirror of https://gitee.com/openkylin/curl.git
Repair CVE-2020-8284、CVE-2020-8285、CVE-2020-8286
This commit is contained in:
parent
d0b4e70e20
commit
4915f017ee
|
@ -9,4 +9,6 @@ to curl's PASV command when curl connects the data connection. Instead curl
|
|||
will re-use the same IP address it already uses for the control
|
||||
connection.
|
||||
|
||||
Since curl 7.74.0 this option is enabled by default.
|
||||
|
||||
This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
|
@ -36,11 +36,13 @@ address it already uses for the control connection. But it will use the port
|
|||
number from the 227-response.
|
||||
|
||||
This option thus allows libcurl to work around broken server installations
|
||||
that due to NATs, firewalls or incompetence report the wrong IP address back.
|
||||
that due to NATs, firewalls or incompetence report the wrong IP address
|
||||
back. Setting the option also reduces the risk for various sorts of client
|
||||
abuse by malicious servers.
|
||||
|
||||
This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
|
||||
.SH DEFAULT
|
||||
0
|
||||
1 since 7.74.0, was 0 before then.
|
||||
.SH PROTOCOLS
|
||||
FTP
|
||||
.SH EXAMPLE
|
||||
|
|
224
lib/ftp.c
224
lib/ftp.c
|
@ -3773,129 +3773,131 @@ static CURLcode init_wc_data(struct connectdata *conn)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* This is called recursively */
|
||||
static CURLcode wc_statemach(struct connectdata *conn)
|
||||
{
|
||||
struct WildcardData * const wildcard = &(conn->data->wildcard);
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
switch(wildcard->state) {
|
||||
case CURLWC_INIT:
|
||||
result = init_wc_data(conn);
|
||||
if(wildcard->state == CURLWC_CLEAN)
|
||||
/* only listing! */
|
||||
break;
|
||||
wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
|
||||
break;
|
||||
|
||||
case CURLWC_MATCHING: {
|
||||
/* In this state is LIST response successfully parsed, so lets restore
|
||||
previous WRITEFUNCTION callback and WRITEDATA pointer */
|
||||
struct ftp_wc *ftpwc = wildcard->protdata;
|
||||
conn->data->set.fwrite_func = ftpwc->backup.write_function;
|
||||
conn->data->set.out = ftpwc->backup.file_descriptor;
|
||||
ftpwc->backup.write_function = ZERO_NULL;
|
||||
ftpwc->backup.file_descriptor = NULL;
|
||||
wildcard->state = CURLWC_DOWNLOADING;
|
||||
|
||||
if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
|
||||
/* error found in LIST parsing */
|
||||
wildcard->state = CURLWC_CLEAN;
|
||||
return wc_statemach(conn);
|
||||
}
|
||||
if(wildcard->filelist.size == 0) {
|
||||
/* no corresponding file */
|
||||
wildcard->state = CURLWC_CLEAN;
|
||||
return CURLE_REMOTE_FILE_NOT_FOUND;
|
||||
}
|
||||
return wc_statemach(conn);
|
||||
}
|
||||
|
||||
case CURLWC_DOWNLOADING: {
|
||||
/* filelist has at least one file, lets get first one */
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
|
||||
struct FTP *ftp = conn->data->req.protop;
|
||||
|
||||
char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
|
||||
if(!tmp_path)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* switch default ftp->path and tmp_path */
|
||||
free(ftp->pathalloc);
|
||||
ftp->pathalloc = ftp->path = tmp_path;
|
||||
|
||||
infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
|
||||
if(conn->data->set.chunk_bgn) {
|
||||
long userresponse;
|
||||
Curl_set_in_callback(conn->data, true);
|
||||
userresponse = conn->data->set.chunk_bgn(
|
||||
finfo, wildcard->customptr, (int)wildcard->filelist.size);
|
||||
Curl_set_in_callback(conn->data, false);
|
||||
switch(userresponse) {
|
||||
case CURL_CHUNK_BGN_FUNC_SKIP:
|
||||
infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
|
||||
finfo->filename);
|
||||
wildcard->state = CURLWC_SKIP;
|
||||
return wc_statemach(conn);
|
||||
case CURL_CHUNK_BGN_FUNC_FAIL:
|
||||
return CURLE_CHUNK_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if(finfo->filetype != CURLFILETYPE_FILE) {
|
||||
wildcard->state = CURLWC_SKIP;
|
||||
return wc_statemach(conn);
|
||||
}
|
||||
|
||||
if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
|
||||
ftpc->known_filesize = finfo->size;
|
||||
|
||||
result = ftp_parse_url_path(conn);
|
||||
if(result)
|
||||
for(;;) {
|
||||
switch(wildcard->state) {
|
||||
case CURLWC_INIT:
|
||||
result = init_wc_data(conn);
|
||||
if(wildcard->state == CURLWC_CLEAN)
|
||||
/* only listing! */
|
||||
return result;
|
||||
wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
|
||||
return result;
|
||||
|
||||
/* we don't need the Curl_fileinfo of first file anymore */
|
||||
Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
|
||||
case CURLWC_MATCHING: {
|
||||
/* In this state is LIST response successfully parsed, so lets restore
|
||||
previous WRITEFUNCTION callback and WRITEDATA pointer */
|
||||
struct ftp_wc *ftpwc = wildcard->protdata;
|
||||
conn->data->set.fwrite_func = ftpwc->backup.write_function;
|
||||
conn->data->set.out = ftpwc->backup.file_descriptor;
|
||||
ftpwc->backup.write_function = ZERO_NULL;
|
||||
ftpwc->backup.file_descriptor = NULL;
|
||||
wildcard->state = CURLWC_DOWNLOADING;
|
||||
|
||||
if(wildcard->filelist.size == 0) { /* remains only one file to down. */
|
||||
wildcard->state = CURLWC_CLEAN;
|
||||
/* after that will be ftp_do called once again and no transfer
|
||||
will be done because of CURLWC_CLEAN state */
|
||||
return CURLE_OK;
|
||||
if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
|
||||
/* error found in LIST parsing */
|
||||
wildcard->state = CURLWC_CLEAN;
|
||||
continue;
|
||||
}
|
||||
if(wildcard->filelist.size == 0) {
|
||||
/* no corresponding file */
|
||||
wildcard->state = CURLWC_CLEAN;
|
||||
return CURLE_REMOTE_FILE_NOT_FOUND;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} break;
|
||||
|
||||
case CURLWC_SKIP: {
|
||||
if(conn->data->set.chunk_end) {
|
||||
Curl_set_in_callback(conn->data, true);
|
||||
conn->data->set.chunk_end(conn->data->wildcard.customptr);
|
||||
Curl_set_in_callback(conn->data, false);
|
||||
case CURLWC_DOWNLOADING: {
|
||||
/* filelist has at least one file, lets get first one */
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
|
||||
struct FTP *ftp = conn->data->req.protop;
|
||||
|
||||
char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
|
||||
if(!tmp_path)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* switch default ftp->path and tmp_path */
|
||||
free(ftp->pathalloc);
|
||||
ftp->pathalloc = ftp->path = tmp_path;
|
||||
|
||||
infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
|
||||
if(conn->data->set.chunk_bgn) {
|
||||
long userresponse;
|
||||
Curl_set_in_callback(conn->data, true);
|
||||
userresponse = conn->data->set.chunk_bgn(
|
||||
finfo, wildcard->customptr, (int)wildcard->filelist.size);
|
||||
Curl_set_in_callback(conn->data, false);
|
||||
switch(userresponse) {
|
||||
case CURL_CHUNK_BGN_FUNC_SKIP:
|
||||
infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
|
||||
finfo->filename);
|
||||
wildcard->state = CURLWC_SKIP;
|
||||
continue;
|
||||
case CURL_CHUNK_BGN_FUNC_FAIL:
|
||||
return CURLE_CHUNK_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if(finfo->filetype != CURLFILETYPE_FILE) {
|
||||
wildcard->state = CURLWC_SKIP;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
|
||||
ftpc->known_filesize = finfo->size;
|
||||
|
||||
result = ftp_parse_url_path(conn);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* we don't need the Curl_fileinfo of first file anymore */
|
||||
Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
|
||||
|
||||
if(wildcard->filelist.size == 0) { /* remains only one file to down. */
|
||||
wildcard->state = CURLWC_CLEAN;
|
||||
/* after that will be ftp_do called once again and no transfer
|
||||
will be done because of CURLWC_CLEAN state */
|
||||
return CURLE_OK;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
case CURLWC_SKIP: {
|
||||
if(conn->data->set.chunk_end) {
|
||||
Curl_set_in_callback(conn->data, true);
|
||||
conn->data->set.chunk_end(conn->data->wildcard.customptr);
|
||||
Curl_set_in_callback(conn->data, false);
|
||||
}
|
||||
Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
|
||||
wildcard->state = (wildcard->filelist.size == 0) ?
|
||||
CURLWC_CLEAN : CURLWC_DOWNLOADING;
|
||||
continue;
|
||||
}
|
||||
|
||||
case CURLWC_CLEAN: {
|
||||
struct ftp_wc *ftpwc = wildcard->protdata;
|
||||
result = CURLE_OK;
|
||||
if(ftpwc)
|
||||
result = Curl_ftp_parselist_geterror(ftpwc->parser);
|
||||
|
||||
wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
|
||||
return result;
|
||||
}
|
||||
|
||||
case CURLWC_DONE:
|
||||
case CURLWC_ERROR:
|
||||
case CURLWC_CLEAR:
|
||||
if(wildcard->dtor)
|
||||
wildcard->dtor(wildcard->protdata);
|
||||
return result;
|
||||
}
|
||||
Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
|
||||
wildcard->state = (wildcard->filelist.size == 0) ?
|
||||
CURLWC_CLEAN : CURLWC_DOWNLOADING;
|
||||
return wc_statemach(conn);
|
||||
}
|
||||
|
||||
case CURLWC_CLEAN: {
|
||||
struct ftp_wc *ftpwc = wildcard->protdata;
|
||||
result = CURLE_OK;
|
||||
if(ftpwc)
|
||||
result = Curl_ftp_parselist_geterror(ftpwc->parser);
|
||||
|
||||
wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
|
||||
} break;
|
||||
|
||||
case CURLWC_DONE:
|
||||
case CURLWC_ERROR:
|
||||
case CURLWC_CLEAR:
|
||||
if(wildcard->dtor)
|
||||
wildcard->dtor(wildcard->protdata);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
/* UNREACHABLE */
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -456,6 +456,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
|
|||
set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
|
||||
set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */
|
||||
set->ftp_filemethod = FTPFILE_MULTICWD;
|
||||
set->ftp_skip_ip = TRUE; /* skip PASV IP by default */
|
||||
#endif
|
||||
set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
|
||||
|
||||
|
|
|
@ -1717,6 +1717,11 @@ static CURLcode verifystatus(struct connectdata *conn,
|
|||
OCSP_BASICRESP *br = NULL;
|
||||
X509_STORE *st = NULL;
|
||||
STACK_OF(X509) *ch = NULL;
|
||||
X509 *cert;
|
||||
OCSP_CERTID *id = NULL;
|
||||
int cert_status, crl_reason;
|
||||
ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
|
||||
int ret;
|
||||
|
||||
long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &status);
|
||||
|
||||
|
@ -1785,43 +1790,63 @@ static CURLcode verifystatus(struct connectdata *conn,
|
|||
goto end;
|
||||
}
|
||||
|
||||
for(i = 0; i < OCSP_resp_count(br); i++) {
|
||||
int cert_status, crl_reason;
|
||||
OCSP_SINGLERESP *single = NULL;
|
||||
/* Compute the certificate's ID */
|
||||
cert = SSL_get_peer_certificate(BACKEND->handle);
|
||||
if(!cert) {
|
||||
failf(data, "Error getting peer certficate");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
|
||||
|
||||
single = OCSP_resp_get0(br, i);
|
||||
if(!single)
|
||||
continue;
|
||||
|
||||
cert_status = OCSP_single_get0_status(single, &crl_reason, &rev,
|
||||
&thisupd, &nextupd);
|
||||
|
||||
if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
|
||||
failf(data, "OCSP response has expired");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
for(i = 0; i < sk_X509_num(ch); i++) {
|
||||
X509 *issuer = sk_X509_value(ch, i);
|
||||
if(X509_check_issued(issuer, cert) == X509_V_OK) {
|
||||
id = OCSP_cert_to_id(EVP_sha1(), cert, issuer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
X509_free(cert);
|
||||
|
||||
infof(data, "SSL certificate status: %s (%d)\n",
|
||||
OCSP_cert_status_str(cert_status), cert_status);
|
||||
if(!id) {
|
||||
failf(data, "Error computing OCSP ID");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
switch(cert_status) {
|
||||
case V_OCSP_CERTSTATUS_GOOD:
|
||||
break;
|
||||
/* Find the single OCSP response corresponding to the certificate ID */
|
||||
ret = OCSP_resp_find_status(br, id, &cert_status, &crl_reason, &rev,
|
||||
&thisupd, &nextupd);
|
||||
OCSP_CERTID_free(id);
|
||||
if(ret != 1) {
|
||||
failf(data, "Could not find certificate ID in OCSP response");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
case V_OCSP_CERTSTATUS_REVOKED:
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
/* Validate the corresponding single OCSP response */
|
||||
if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
|
||||
failf(data, "OCSP response has expired");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
failf(data, "SSL certificate revocation reason: %s (%d)",
|
||||
OCSP_crl_reason_str(crl_reason), crl_reason);
|
||||
goto end;
|
||||
infof(data, "SSL certificate status: %s (%d)\n",
|
||||
OCSP_cert_status_str(cert_status), cert_status);
|
||||
|
||||
case V_OCSP_CERTSTATUS_UNKNOWN:
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
switch(cert_status) {
|
||||
case V_OCSP_CERTSTATUS_GOOD:
|
||||
break;
|
||||
|
||||
case V_OCSP_CERTSTATUS_REVOKED:
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
failf(data, "SSL certificate revocation reason: %s (%d)",
|
||||
OCSP_crl_reason_str(crl_reason), crl_reason);
|
||||
goto end;
|
||||
|
||||
case V_OCSP_CERTSTATUS_UNKNOWN:
|
||||
default:
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
|
|
|
@ -44,6 +44,7 @@ void config_init(struct OperationConfig* config)
|
|||
config->tcp_nodelay = TRUE; /* enabled by default */
|
||||
config->happy_eyeballs_timeout_ms = CURL_HET_DEFAULT;
|
||||
config->http09_allowed = FALSE;
|
||||
config->ftp_skip_ip = TRUE;
|
||||
}
|
||||
|
||||
static void free_config_fields(struct OperationConfig *config)
|
||||
|
|
|
@ -76,6 +76,7 @@ int main(int argc, char *argv[])
|
|||
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
|
||||
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
|
||||
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
|
||||
|
||||
/* Here is a list of options the curl code used that cannot get generated
|
||||
|
|
|
@ -90,6 +90,7 @@ int main(int argc, char *argv[])
|
|||
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
|
||||
curl_easy_setopt(hnd, CURLOPT_COOKIE, "chocolate=chip");
|
||||
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_PROTOCOLS, (long)CURLPROTO_FILE |
|
||||
(long)CURLPROTO_FTP |
|
||||
|
|
|
@ -81,6 +81,7 @@ int main(int argc, char *argv[])
|
|||
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
|
||||
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
|
||||
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
|
||||
|
||||
/* Here is a list of options the curl code used that cannot get generated
|
||||
|
|
|
@ -76,6 +76,7 @@ int main(int argc, char *argv[])
|
|||
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
|
||||
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
|
||||
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
|
||||
|
||||
/* Here is a list of options the curl code used that cannot get generated
|
||||
|
|
|
@ -147,6 +147,7 @@ int main(int argc, char *argv[])
|
|||
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
|
||||
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
|
||||
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
|
||||
|
||||
/* Here is a list of options the curl code used that cannot get generated
|
||||
|
|
|
@ -89,6 +89,7 @@ int main(int argc, char *argv[])
|
|||
curl_easy_setopt(hnd, CURLOPT_POSTQUOTE, slist2);
|
||||
curl_easy_setopt(hnd, CURLOPT_PREQUOTE, slist3);
|
||||
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
|
||||
|
||||
/* Here is a list of options the curl code used that cannot get generated
|
||||
|
|
|
@ -79,6 +79,7 @@ int main(int argc, char *argv[])
|
|||
curl_easy_setopt(hnd, CURLOPT_URL, "smtp://%HOSTIP:%SMTPPORT/1406");
|
||||
curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_MAIL_FROM, "sender@example.com");
|
||||
curl_easy_setopt(hnd, CURLOPT_MAIL_RCPT, slist1);
|
||||
|
|
|
@ -62,6 +62,7 @@ int main(int argc, char *argv[])
|
|||
curl_easy_setopt(hnd, CURLOPT_DIRLISTONLY, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_USERPWD, "user:secret");
|
||||
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
|
||||
|
||||
/* Here is a list of options the curl code used that cannot get generated
|
||||
|
|
|
@ -67,6 +67,7 @@ int main(int argc, char *argv[])
|
|||
curl_easy_setopt(hnd, CURLOPT_URL, "imap://%HOSTIP:%IMAPPORT/1420/;MAILINDEX=1");
|
||||
curl_easy_setopt(hnd, CURLOPT_USERPWD, "user:secret");
|
||||
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
|
||||
|
||||
/* Here is a list of options the curl code used that cannot get generated
|
||||
|
|
Loading…
Reference in New Issue