Merge branch 'master' into feat/add-format-pretty

This commit is contained in:
Xavier Claude 2026-07-28 21:42:08 +02:00
commit 14974e40e4
205 changed files with 1422 additions and 1049 deletions

View file

@ -5,4 +5,4 @@
cmakelang==0.6.13
codespell==2.4.3
reuse==6.2.0
ruff==0.15.16
ruff==0.16.0

View file

@ -65,7 +65,7 @@ int main(void)
#include <netdb.h>
int main(void)
{
const char *address = "localhost";
static const char address[] = "localhost";
struct hostent h;
int rc = 0;
#if defined(HAVE_GETHOSTBYNAME_R_3) || \

View file

@ -1344,6 +1344,11 @@ if(CURL_USE_GSSAPI)
elseif(GSS_VERSION) # MIT
set(CURL_KRB5_VERSION "\"${GSS_VERSION}\"")
endif()
cmake_push_check_state()
list(APPEND CMAKE_REQUIRED_LIBRARIES CURL::gss)
check_function_exists("gss_set_neg_mechs" HAVE_GSS_SET_NEG_MECHS)
cmake_pop_check_state()
else()
message(WARNING "GSSAPI has been requested, but no supporting libraries found. Skipping.")
endif()

View file

@ -2097,6 +2097,7 @@ if test "$want_gss" = "yes"; then
AC_MSG_RESULT([no])
AC_MSG_ERROR([--with-gssapi was specified, but a GSS-API library was not found.])
])
AC_CHECK_FUNCS([gss_set_neg_mechs])
fi
build_libstubgss=no

View file

@ -21,6 +21,8 @@ Experimental support in curl means:
to our API/ABI rules as we do for regular features, as long as it is marked
experimental.
5. Experimental features are clearly marked so in documentation. Beware.
6. Vulnerabilities in experimental features are not considered security
problems; please report them as regular bugs/feedback instead.
## Graduation

View file

@ -517,6 +517,7 @@ the parent project, ideally in the "extra" find package redirect file:
Available variables:
- `HAVE_DES_ECB_ENCRYPT`: `DES_ecb_encrypt` present in OpenSSL (or fork).
- `HAVE_GSS_SET_NEG_MECHS`: `gss_set_neg_mechs` present in GSS-API library.
- `HAVE_LDAP_INIT_FD`: `ldap_init_fd` present in LDAP library.
- `HAVE_LDAP_URL_PARSE`: `ldap_url_parse` present in LDAP library.
- `HAVE_MBEDTLS_DES_CRYPT_ECB`: `mbedtls_des_crypt_ecb` present in mbedTLS <4.

View file

@ -64,6 +64,19 @@ these or later versions:
- perl 5.8 (2002-07-19), on Windows: 5.22 (2015-06-01)
- Visual Studio 2010 10.0 (2010-04-12 - 2020-07-14)
## Testing
Certain tests require the following packages to operate. In some cases, tests
that do not find the necessary requirements are automatically skipped.
- OpenSSL (see above)
- nghttp2 (see above)
- OpenSSH
- perl (see above)
- pytest
- Python 3.8 (2019-10-14)
- stunnel
## Library Symbols
All symbols used internally in libcurl must use a `Curl_` prefix if they are

View file

@ -30,7 +30,7 @@
#include <curl/curl.h>
static const char *urls[] = {
static const char * const urls[] = {
"https://01.example/",
"https://02.example/",
"https://03.example/",

View file

@ -47,7 +47,7 @@ static int max_total = 20000;
static int max_requests = 500;
static size_t max_link_per_page = 5;
static int follow_relative_links = 0;
static const char *start_page = "https://www.reuters.com/";
static const char start_page[] = "https://www.reuters.com/";
static int pending_interrupt = 0;
static void sighandler(int dummy)

View file

@ -303,7 +303,9 @@ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
{
struct GlobalInfo *g = (struct GlobalInfo *)cbp;
struct SockInfo *fdp = (struct SockInfo *)sockp;
const char *whatstr[] = { "none", "IN", "OUT", "INOUT", "REMOVE" };
static const char * const whatstr[] = {
"none", "IN", "OUT", "INOUT", "REMOVE"
};
fprintf(MSG_OUT, "socket callback: s=%d e=%p what=%s ", s, e, whatstr[what]);
if(what == CURL_POLL_REMOVE) {
@ -407,7 +409,7 @@ static void fifo_cb(struct GlobalInfo *g, int revents)
static int init_fifo(struct GlobalInfo *g)
{
struct stat st;
static const char *fifo = "hiper.fifo";
static const char fifo[] = "hiper.fifo";
curl_socket_t sockfd;
struct epoll_event epev;

View file

@ -267,7 +267,9 @@ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
{
struct GlobalInfo *g = (struct GlobalInfo *)cbp;
struct SockInfo *fdp = (struct SockInfo *)sockp;
const char *whatstr[] = { "none", "IN", "OUT", "INOUT", "REMOVE" };
static const char * const whatstr[] = {
"none", "IN", "OUT", "INOUT", "REMOVE"
};
printf("%s e %p s %d what %d cbp %p sockp %p\n",
__PRETTY_FUNCTION__, e, s, what, cbp, sockp);
@ -378,7 +380,7 @@ static void fifo_cb(EV_P_ struct ev_io *w, int revents)
static int init_fifo(struct GlobalInfo *g)
{
struct stat st;
static const char *fifo = "hiper.fifo";
static const char fifo[] = "hiper.fifo";
curl_socket_t sockfd;
fprintf(MSG_OUT, "Creating named pipe \"%s\"\n", fifo);

View file

@ -258,7 +258,9 @@ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
{
struct GlobalInfo *g = (struct GlobalInfo *)cbp;
struct SockInfo *fdp = (struct SockInfo *)sockp;
static const char *whatstr[] = { "none", "IN", "OUT", "INOUT", "REMOVE" };
static const char * const whatstr[] = {
"none", "IN", "OUT", "INOUT", "REMOVE"
};
MSG_OUT("socket callback: s=%d e=%p what=%s ", s, e, whatstr[what]);
if(what == CURL_POLL_REMOVE) {
@ -395,8 +397,8 @@ static gboolean fifo_cb(GIOChannel *ch, GIOCondition condition, gpointer data)
int init_fifo(void)
{
static const char fifo[] = "hiper.fifo";
struct stat st;
const char *fifo = "hiper.fifo";
int socket;
if(!lstat(fifo, &st)) {

View file

@ -270,7 +270,9 @@ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
{
struct GlobalInfo *g = (struct GlobalInfo *)cbp;
struct SockInfo *fdp = (struct SockInfo *)sockp;
const char *whatstr[] = { "none", "IN", "OUT", "INOUT", "REMOVE" };
static const char * const whatstr[] = {
"none", "IN", "OUT", "INOUT", "REMOVE"
};
fprintf(MSG_OUT, "socket callback: s=%d e=%p what=%s ", s, e, whatstr[what]);
if(what == CURL_POLL_REMOVE) {
@ -376,7 +378,7 @@ static void fifo_cb(int fd, short event, void *arg)
}
/* Create a named pipe and tell libevent to monitor it */
static const char *fifo = "hiper.fifo";
static const char fifo[] = "hiper.fifo";
static int init_fifo(struct GlobalInfo *g)
{
struct stat st;

View file

@ -40,7 +40,7 @@
#define TO "<addressee@example.net>"
#define CC "<info@example.org>"
static const char *payload_text =
static const char payload_text[] =
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n"
"To: " TO "\r\n"
"From: " FROM "(Example User)\r\n"
@ -111,7 +111,7 @@ int main(void)
curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
filesize = strlen(payload_text);
filesize = sizeof(payload_text) - 1;
if(filesize <= LONG_MAX)
infilesize = (long)filesize;
curl_easy_setopt(curl, CURLOPT_INFILESIZE, infilesize);

View file

@ -39,7 +39,7 @@ int main(void)
curl = curl_easy_init();
if(curl) {
const char *urls[] = {
static const char * const urls[] = {
"https://example.com/",
"https://curl.se/",
"https://www.example/",

View file

@ -61,7 +61,7 @@ int main(void)
CURL *curl;
CURLcode result;
struct MemoryStruct chunk;
static const char *postthis = "Field=1&Field=2&Field=3";
static const char postthis[] = "Field=1&Field=2&Field=3";
result = curl_global_init(CURL_GLOBAL_ALL);
if(result != CURLE_OK)
@ -87,7 +87,7 @@ int main(void)
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);
/* if we do not provide POSTFIELDSIZE, libcurl calls strlen() by itself */
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(postthis));
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)sizeof(postthis) - 1);
/* Perform the request, result gets the return code */
result = curl_easy_perform(curl);

View file

@ -77,8 +77,8 @@ int main(void)
{
CURL *curl;
/* Minimalistic http request */
const char *request = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n";
size_t request_len = strlen(request);
static const char request[] = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n";
static const size_t request_len = sizeof(request) - 1;
CURLcode result = curl_global_init(CURL_GLOBAL_ALL);
if(result != CURLE_OK)

View file

@ -53,9 +53,9 @@ int main(void)
/* init the curl session */
curl = curl_easy_init();
if(curl) {
static const char *headerfilename = "head.out";
static const char headerfilename[] = "head.out";
FILE *headerfile;
static const char *bodyfilename = "body.out";
static const char bodyfilename[] = "body.out";
FILE *bodyfile;
/* set URL to get */

View file

@ -134,8 +134,8 @@ int main(void)
curl = curl_easy_init();
if(curl) {
const char *remote = "sftp://user:pass@example.com/path/filename";
const char *filename = "filename";
static const char remote[] = "sftp://user:pass@example.com/path/filename";
static const char filename[] = "filename";
if(!sftpResumeUpload(curl, remote, filename)) {
printf("resumed upload using curl %s failed\n", curl_version());

View file

@ -32,7 +32,7 @@
int main(void)
{
static const char *postthis = "moo mooo moo moo";
static const char postthis[] = "moo mooo moo moo";
CURL *curl;
@ -46,7 +46,7 @@ int main(void)
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);
/* if we do not provide POSTFIELDSIZE, libcurl calls strlen() by itself */
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(postthis));
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)sizeof(postthis) - 1);
/* Perform the request, result gets the return code */
result = curl_easy_perform(curl);

View file

@ -55,9 +55,9 @@ int main(void)
FILE *headerfile;
const char *pPassphrase = NULL;
static const char *pCertFile = "testcert.pem";
static const char *pCACertFile = "cacert.pem";
static const char *pHeaderFile = "dumpit";
static const char pCertFile[] = "testcert.pem";
static const char pCACertFile[] = "cacert.pem";
static const char pHeaderFile[] = "dumpit";
const char *pKeyName;
const char *pKeyType;

View file

@ -48,7 +48,7 @@
#define SENDER_MAIL "Kurt " SENDER_ADDR
#define TO_MAIL "A Receiver " TO_ADDR
static const char *payload_text =
static const char payload_text[] =
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n"
"To: " TO_MAIL "\r\n"
"From: " FROM_MAIL "\r\n"

View file

@ -45,7 +45,7 @@
#define TO_MAIL "A Receiver " TO_ADDR
#define CC_MAIL "John CC Smith " CC_ADDR
static const char *payload_text =
static const char payload_text[] =
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n"
"To: " TO_MAIL "\r\n"
"From: " FROM_MAIL "\r\n"

View file

@ -41,7 +41,7 @@
#define TO "<addressee@example.net>"
#define CC "<info@example.org>"
static const char *headers_text[] = {
static const char * const headers_text[] = {
"Date: Tue, 22 Aug 2017 14:08:43 +0100",
"To: " TO,
"From: " FROM " (Example User)",
@ -82,7 +82,7 @@ int main(void)
curl_mime *mime;
curl_mime *alt;
curl_mimepart *part;
const char **cpp;
const char * const *cpp;
/* This is the URL for your mailserver */
curl_easy_setopt(curl, CURLOPT_URL, "smtp://mail.example.com");

View file

@ -38,7 +38,7 @@
#define TO_MAIL "<recipient@example.com>"
#define CC_MAIL "<info@example.com>"
static const char *payload_text =
static const char payload_text[] =
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n"
"To: " TO_MAIL "\r\n"
"From: " FROM_MAIL "\r\n"

View file

@ -42,7 +42,7 @@
#define TO_MAIL "<recipient@example.com>"
#define CC_MAIL "<info@example.com>"
static const char *payload_text =
static const char payload_text[] =
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n"
"To: " TO_MAIL "\r\n"
"From: " FROM_MAIL "\r\n"

View file

@ -42,7 +42,7 @@
#define TO_MAIL "<recipient@example.com>"
#define CC_MAIL "<info@example.com>"
static const char *payload_text =
static const char payload_text[] =
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n"
"To: " TO_MAIL "\r\n"
"From: " FROM_MAIL "\r\n"

View file

@ -99,10 +99,10 @@ static int AutoSyncTime;
static SYSTEMTIME SYSTime;
static SYSTEMTIME LOCALTime;
static const char *DayStr[] = {
static const char * const DayStr[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static const char *MthStr[] = {
static const char * const MthStr[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

View file

@ -44,7 +44,7 @@ static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *stream)
int main(int argc, const char *argv[])
{
static const char *pagefilename = "page.out";
static const char pagefilename[] = "page.out";
CURLcode result;
CURL *curl;

View file

@ -88,7 +88,7 @@ int main(int argc, const char *argv[])
{
CURL *curl;
struct read_ctx rctx;
const char *payload = "Hello, friend!";
static const char payload[] = "Hello, friend!";
CURLcode result = curl_global_init(CURL_GLOBAL_ALL);
if(result != CURLE_OK)
@ -108,7 +108,7 @@ int main(int argc, const char *argv[])
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb);
/* tell curl that we want to send the payload */
rctx.curl = curl;
rctx.blen = strlen(payload);
rctx.blen = sizeof(payload) - 1;
memcpy(rctx.buf, payload, rctx.blen);
curl_easy_setopt(curl, CURLOPT_READDATA, &rctx);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);

View file

@ -724,6 +724,11 @@ libcurl lacks IDN support.
A value or data field is larger than allowed.
## CURLUE_BACKSLASH (32)
Found a backslash character where a forward slash was expected. URL separators
are forward slashes (`/`), not backslashes (`\`).
# CURLHcode
The header interface returns a *CURLHcode* to indicate when an error has

View file

@ -1113,6 +1113,7 @@ CURLU_PUNY2IDN 8.3.0
CURLU_PUNYCODE 7.88.0
CURLU_URLDECODE 7.62.0
CURLU_URLENCODE 7.62.0
CURLUE_BACKSLASH 8.22.0
CURLUE_BAD_FILE_URL 7.81.0
CURLUE_BAD_FRAGMENT 7.81.0
CURLUE_BAD_HANDLE 7.62.0

View file

@ -64,6 +64,7 @@ typedef enum {
CURLUE_BAD_USER, /* 29 */
CURLUE_LACKS_IDN, /* 30 */
CURLUE_TOO_LARGE, /* 31 */
CURLUE_BACKSLASH, /* 32 */
CURLUE_LAST
} CURLUcode;

View file

@ -329,7 +329,7 @@ static CURLcode on_resp_header_udp(struct Curl_cfilter *cf,
k->httpcode);
}
else {
const char *p = header + strlen("Content-Length:");
const char *p = header + CURL_CSTRLEN("Content-Length:");
if(curlx_str_numblanks(&p, &ts->cl)) {
failf(data, "Unsupported Content-Length value");
return CURLE_WEIRD_SERVER_REPLY;
@ -419,7 +419,7 @@ static CURLcode on_resp_header(struct Curl_cfilter *cf,
k->httpcode);
}
else {
const char *p = header + strlen("Content-Length:");
const char *p = header + CURL_CSTRLEN("Content-Length:");
if(curlx_str_numblanks(&p, &ts->cl)) {
failf(data, "Unsupported Content-Length value");
return CURLE_WEIRD_SERVER_REPLY;

View file

@ -574,7 +574,7 @@ static int proxy_h2_on_header(nghttp2_session *session,
return 0;
}
if(namelen == sizeof(HTTP_PSEUDO_STATUS) - 1 &&
if(namelen == CURL_CSTRLEN(HTTP_PSEUDO_STATUS) &&
!memcmp(HTTP_PSEUDO_STATUS, name, namelen)) {
int http_status;
struct http_resp *resp;

View file

@ -450,9 +450,9 @@ static CURLcode cf_cntrl_all(struct connectdata *conn,
int event, int arg1, void *arg2)
{
CURLcode result = CURLE_OK;
size_t i;
int i;
for(i = 0; i < CURL_ARRAYSIZE(conn->cfilter); ++i) {
for(i = 0; i < (int)CURL_ARRAYSIZE(conn->cfilter); ++i) {
result = Curl_conn_cf_cntrl(conn->cfilter[i], data, ignore_result,
event, arg1, arg2);
if(!ignore_result && result)
@ -753,7 +753,7 @@ CURLcode Curl_conn_adjust_pollset(struct Curl_easy *data,
* connect or shutdown does not add poll events for the other. Check
* against the transfer's own interest, before any chain added sockets
* of its own. */
for(i = 0; (i < 2) && !result; ++i) {
for(i = 0; (i < (int)CURL_ARRAYSIZE(conn->cfilter)) && !result; ++i) {
if(conn->cfilter[i] &&
(want_io || !Curl_conn_is_connected(conn, i) ||
Curl_shutdown_started(conn, i)))
@ -978,15 +978,17 @@ bool Curl_conn_is_alive(struct Curl_easy *data, struct connectdata *conn,
}
CURLcode Curl_conn_keep_alive(struct Curl_easy *data,
struct connectdata *conn,
int sockindex)
struct connectdata *conn)
{
struct Curl_cfilter *cf;
CURLcode result = CURLE_OK;
int i;
if(!CONN_SOCK_IDX_VALID(sockindex))
return CURLE_BAD_FUNCTION_ARGUMENT;
cf = conn->cfilter[sockindex];
return cf ? cf->cft->keep_alive(cf, data) : CURLE_OK;
for(i = 0; (i < (int)CURL_ARRAYSIZE(conn->cfilter)) && !result; ++i) {
struct Curl_cfilter *cf = conn->cfilter[i];
if(cf)
result = cf->cft->keep_alive(cf, data);
}
return result;
}
size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,

View file

@ -558,11 +558,10 @@ bool Curl_conn_is_alive(struct Curl_easy *data, struct connectdata *conn,
bool *input_pending);
/**
* Try to upkeep the connection filters at sockindex.
* Try to upkeep the connection filters.
*/
CURLcode Curl_conn_keep_alive(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
struct connectdata *conn);
/**
* Get the remote hostname and port that the connection is currently

View file

@ -715,7 +715,7 @@ static int cpool_reap_dead_cb(struct Curl_easy *data,
if(!terminate) {
reaper->checked++;
terminate = Curl_conn_seems_dead(conn, data, &reaper->now);
terminate = Curl_cpool_conn_seems_dead(conn, data, &reaper->now);
}
if(terminate) {
/* stop the iteration here, pass back the connection that was pruned */
@ -761,7 +761,21 @@ static int conn_upkeep(struct Curl_easy *data,
void *param)
{
(void)param;
Curl_conn_upkeep(data, conn);
if(curlx_ptimediff_ms(Curl_pgrs_now(data), &conn->keepalive) >=
data->set.upkeep_interval_ms) {
CURLcode result;
/* briefly attach for action */
Curl_attach_connection(data, conn);
result = Curl_conn_keep_alive(data, conn);
conn->keepalive = *Curl_pgrs_now(data);
Curl_detach_connection(data);
if(result && !CONN_INUSE(conn)) {
Curl_conn_terminate(data, conn, FALSE);
return 1;
}
}
return 0; /* continue iteration */
}
@ -773,7 +787,8 @@ CURLcode Curl_cpool_upkeep(struct Curl_easy *data)
return CURLE_OK;
CPOOL_LOCK(cpool, data);
cpool_foreach(data, cpool, NULL, conn_upkeep);
while(cpool_foreach(data, cpool, NULL, conn_upkeep))
;
CPOOL_UNLOCK(cpool, data);
return CURLE_OK;
}
@ -858,6 +873,84 @@ void Curl_cpool_nw_changed(struct Curl_easy *data)
}
}
/* A connection has to have been idle for less than 'conn_max_idle_ms'
(the success rate is too low after this), or created less than
'conn_max_age_ms' ago, to be subject for reuse. */
static bool cpool_conn_maxage(struct Curl_easy *data,
struct connectdata *conn,
const struct curltime *pnow)
{
timediff_t age_ms;
if(data->set.conn_max_idle_ms) {
age_ms = curlx_ptimediff_ms(pnow, &conn->lastused);
if(age_ms > data->set.conn_max_idle_ms) {
infof(data, "Too old connection (%" FMT_TIMEDIFF_T
" ms idle, max idle is %" FMT_TIMEDIFF_T " ms), disconnect it",
age_ms, data->set.conn_max_idle_ms);
return TRUE;
}
}
if(data->set.conn_max_age_ms) {
age_ms = curlx_ptimediff_ms(pnow, &conn->created);
if(age_ms > data->set.conn_max_age_ms) {
infof(data,
"Too old connection (created %" FMT_TIMEDIFF_T
" ms ago, max lifetime is %" FMT_TIMEDIFF_T " ms), disconnect it",
age_ms, data->set.conn_max_age_ms);
return TRUE;
}
}
return FALSE;
}
/*
* Return TRUE iff the given connection is considered dead.
*/
bool Curl_cpool_conn_seems_dead(struct connectdata *conn,
struct Curl_easy *data,
const struct curltime *pnow)
{
bool input_pending = FALSE;
bool dead = FALSE;
DEBUGASSERT(!data->conn);
/* The check only makes sense only if the connection is not in use */
if(CONN_INUSE(conn))
return FALSE;
else if(cpool_conn_maxage(data, conn, pnow)) /* too old? */
return TRUE;
else if(curlx_ptimediff_ms(pnow, &conn->lastchecked) < 1000)
return FALSE;
else if(conn->scheme->run->connection_is_dead) {
Curl_attach_connection(data, conn);
dead = conn->scheme->run->connection_is_dead(data, conn);
Curl_detach_connection(data);
}
else {
Curl_attach_connection(data, conn);
dead = !Curl_conn_is_alive(data, conn, &input_pending);
Curl_detach_connection(data);
}
if(input_pending) {
/* For reuse, we want a "clean" connection state. This includes
* that we expect - in general - no waiting input data. Input
* waiting might be a TLS Notify Close, for example. We reject
* that.
* For protocols where data from other end may arrive at
* any time (HTTP/2 PING for example), the protocol handler needs
* to install its own `connection_check` callback.
*/
DEBUGF(infof(data, "connection has input pending, not reusable"));
dead = TRUE;
}
return dead;
}
#if 0
/* Useful for debugging the connection pool */
void Curl_cpool_print(struct cpool *cpool)

View file

@ -156,4 +156,11 @@ void Curl_cpool_do_locked(struct Curl_easy *data,
/* Close all unused connections, prevent reuse of existing ones. */
void Curl_cpool_nw_changed(struct Curl_easy *data);
/**
* Return TRUE iff the given connection is considered dead.
*/
bool Curl_cpool_conn_seems_dead(struct connectdata *conn,
struct Curl_easy *data,
const struct curltime *pnow);
#endif /* HEADER_CURL_CONNCACHE_H */

View file

@ -330,6 +330,9 @@
/* if you have the GNU gssapi libraries */
#cmakedefine HAVE_GSSGNU 1
/* if you have gss_set_neg_mechs */
#cmakedefine HAVE_GSS_SET_NEG_MECHS 1
/* MIT Kerberos version */
#cmakedefine CURL_KRB5_VERSION ${CURL_KRB5_VERSION}

View file

@ -81,7 +81,6 @@ enum min_err_code {
/* libcurl is also passing this struct to these functions, which are not yet
* stubbed:
* gss_inquire_context()
* gss_unwrap()
* gss_wrap()
*/
@ -93,6 +92,12 @@ struct stub_gss_ctx_id_t_desc {
char creds[250];
};
/* Stub credential: tracks which mechanisms are allowed */
struct stub_gss_cred_id_t_desc {
int allow_krb5;
int allow_ntlm;
};
static OM_uint32 stub_gss_init_sec_context(
OM_uint32 *min,
gss_cred_id_t initiator_cred_handle,
@ -116,7 +121,6 @@ static OM_uint32 stub_gss_init_sec_context(
char *token = NULL;
const char *creds = NULL;
(void)initiator_cred_handle;
(void)mech_type;
(void)time_req;
(void)input_chan_bindings;
@ -214,6 +218,16 @@ static OM_uint32 stub_gss_init_sec_context(
if(strstr(creds, "NTLM"))
ctx->have_ntlm = 1;
/* If a credential restricts allowed mechs, honour it */
if(initiator_cred_handle != GSS_C_NO_CREDENTIAL) {
struct stub_gss_cred_id_t_desc *cred =
(struct stub_gss_cred_id_t_desc *)initiator_cred_handle;
if(!cred->allow_krb5)
ctx->have_krb5 = 0;
if(!cred->allow_ntlm)
ctx->have_ntlm = 0;
}
if(ctx->have_krb5)
ctx->sent = STUB_GSS_KRB5;
else if(ctx->have_ntlm)
@ -307,6 +321,175 @@ static OM_uint32 stub_gss_delete_sec_context(
return GSS_S_COMPLETE;
}
/* NTLMSSP OID: 1.3.6.1.4.1.311.2.2.10 */
static gss_OID_desc stub_ntlmssp_oid = {
10, CURL_UNCONST("\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a")
};
static OM_uint32 stub_gss_inquire_context(
OM_uint32 *min,
struct stub_gss_ctx_id_t_desc *context,
gss_name_t *src_name,
gss_name_t *targ_name,
OM_uint32 *lifetime_rec,
gss_OID *mech_type,
OM_uint32 *ctx_flags,
int *locally_initiated,
int *open_context)
{
(void)src_name;
(void)targ_name;
(void)lifetime_rec;
(void)ctx_flags;
(void)locally_initiated;
(void)open_context;
if(!min)
return GSS_S_FAILURE;
if(!context) {
*min = STUB_GSS_INVALID_CTX;
return GSS_S_FAILURE;
}
*min = 0;
if(mech_type) {
switch(context->sent) {
case STUB_GSS_NTLM1:
case STUB_GSS_NTLM3:
*mech_type = &stub_ntlmssp_oid;
break;
default:
*mech_type = (gss_OID)&Curl_krb5_mech_oid;
break;
}
}
return GSS_S_COMPLETE;
}
static OM_uint32 stub_gss_acquire_cred(
OM_uint32 *min,
gss_name_t desired_name,
OM_uint32 time_req,
gss_OID_set desired_mechs,
gss_cred_usage_t cred_usage,
gss_cred_id_t *output_cred_handle,
gss_OID_set *actual_mechs,
OM_uint32 *time_rec)
{
(void)desired_name;
(void)time_req;
(void)desired_mechs;
(void)cred_usage;
(void)actual_mechs;
(void)time_rec;
if(!min)
return GSS_S_FAILURE;
*min = 0;
/* Allocate a stub credential that initially allows all mechanisms */
if(output_cred_handle) {
struct stub_gss_cred_id_t_desc *cred =
curlx_calloc(1, sizeof(*cred));
if(!cred) {
*min = STUB_GSS_NO_MEMORY;
return GSS_S_FAILURE;
}
cred->allow_krb5 = 1;
cred->allow_ntlm = 1;
*output_cred_handle = (gss_cred_id_t)cred;
}
return GSS_S_COMPLETE;
}
static OM_uint32 stub_gss_indicate_mechs(
OM_uint32 *min,
gss_OID_set *mech_set)
{
const char *creds;
OM_uint32 major;
if(!min)
return GSS_S_FAILURE;
*min = 0;
creds = getenv("CURL_STUB_GSS_CREDS");
if(!creds) {
*min = STUB_GSS_INVALID_CREDS;
return GSS_S_FAILURE;
}
major = gss_create_empty_oid_set(min, mech_set);
if(GSS_ERROR(major))
return major;
/* Always include Kerberos */
gss_add_oid_set_member(min, (gss_OID)&Curl_krb5_mech_oid, mech_set);
/* Include NTLM if the stub creds contain NTLM */
if(strstr(creds, "NTLM"))
gss_add_oid_set_member(min, &stub_ntlmssp_oid, mech_set);
return GSS_S_COMPLETE;
}
#ifdef HAVE_GSS_SET_NEG_MECHS /* MIT Kerberos 1.8+ (2010-03-02),
missing from Apple GSS, GNU GSS */
static OM_uint32 stub_gss_set_neg_mechs(
OM_uint32 *min,
gss_cred_id_t cred_handle,
const gss_OID_set mech_set)
{
struct stub_gss_cred_id_t_desc *cred;
size_t i;
int found_krb5 = 0;
int found_ntlm = 0;
if(!min)
return GSS_S_FAILURE;
*min = 0;
if(cred_handle == GSS_C_NO_CREDENTIAL)
return GSS_S_FAILURE;
cred = (struct stub_gss_cred_id_t_desc *)cred_handle;
/* Determine which mechs are in the allowed set */
if(mech_set) {
for(i = 0; i < mech_set->count; i++) {
gss_OID oid = &mech_set->elements[i];
if(oid->length == Curl_krb5_mech_oid.length &&
!memcmp(oid->elements, Curl_krb5_mech_oid.elements, oid->length))
found_krb5 = 1;
if(oid->length == stub_ntlmssp_oid.length &&
!memcmp(oid->elements, stub_ntlmssp_oid.elements, oid->length))
found_ntlm = 1;
}
}
cred->allow_krb5 = found_krb5;
cred->allow_ntlm = found_ntlm;
return GSS_S_COMPLETE;
}
#endif /* HAVE_GSS_SET_NEG_MECHS */
static OM_uint32 stub_gss_release_cred(
OM_uint32 *min,
gss_cred_id_t *cred_handle)
{
if(!min)
return GSS_S_FAILURE;
*min = 0;
if(cred_handle && *cred_handle != GSS_C_NO_CREDENTIAL) {
curlx_free(*cred_handle);
*cred_handle = GSS_C_NO_CREDENTIAL;
}
return GSS_S_COMPLETE;
}
#endif /* CURL_GSS_STUB */
OM_uint32 Curl_gss_init_sec_context(struct Curl_easy *data,
@ -318,7 +501,8 @@ OM_uint32 Curl_gss_init_sec_context(struct Curl_easy *data,
gss_buffer_t input_token,
gss_buffer_t output_token,
const bool mutual_auth,
OM_uint32 *ret_flags)
OM_uint32 *ret_flags,
gss_cred_id_t cred_handle)
{
OM_uint32 req_flags = GSS_C_REPLAY_FLAG;
@ -326,7 +510,8 @@ OM_uint32 Curl_gss_init_sec_context(struct Curl_easy *data,
req_flags |= GSS_C_MUTUAL_FLAG;
if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_POLICY_FLAG) {
#ifdef GSS_C_DELEG_POLICY_FLAG /* MIT Kerberos 1.8+, missing from GNU GSS */
#ifdef GSS_C_DELEG_POLICY_FLAG /* MIT Kerberos 1.7+ (2009-06-02), Apple GSS,
missing from GNU GSS */
req_flags |= GSS_C_DELEG_POLICY_FLAG;
#else
infof(data, "WARNING: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not "
@ -340,7 +525,7 @@ OM_uint32 Curl_gss_init_sec_context(struct Curl_easy *data,
#ifdef CURL_GSS_STUB
if(getenv("CURL_STUB_GSS_CREDS"))
return stub_gss_init_sec_context(minor_status,
GSS_C_NO_CREDENTIAL, /* cred_handle */
cred_handle,
(struct stub_gss_ctx_id_t_desc **)context,
target_name,
mech_type,
@ -355,7 +540,7 @@ OM_uint32 Curl_gss_init_sec_context(struct Curl_easy *data,
#endif /* CURL_GSS_STUB */
return gss_init_sec_context(minor_status,
GSS_C_NO_CREDENTIAL, /* cred_handle */
cred_handle,
context,
target_name,
mech_type,
@ -383,6 +568,80 @@ OM_uint32 Curl_gss_delete_sec_context(OM_uint32 *min,
return gss_delete_sec_context(min, context, output_token);
}
OM_uint32 Curl_gss_inquire_context(OM_uint32 *minor_status,
gss_ctx_id_t context,
gss_OID *mech_type)
{
#ifdef CURL_GSS_STUB
if(getenv("CURL_STUB_GSS_CREDS"))
return stub_gss_inquire_context(minor_status,
(struct stub_gss_ctx_id_t_desc *)context,
NULL, NULL, NULL, mech_type,
NULL, NULL, NULL);
#endif /* CURL_GSS_STUB */
return gss_inquire_context(minor_status, context,
NULL, NULL, NULL, mech_type,
NULL, NULL, NULL);
}
OM_uint32 Curl_gss_acquire_cred(OM_uint32 *minor_status,
gss_name_t desired_name,
OM_uint32 time_req,
gss_OID_set desired_mechs,
gss_cred_usage_t cred_usage,
gss_cred_id_t *output_cred_handle,
gss_OID_set *actual_mechs,
OM_uint32 *time_rec)
{
#ifdef CURL_GSS_STUB
if(getenv("CURL_STUB_GSS_CREDS"))
return stub_gss_acquire_cred(minor_status, desired_name, time_req,
desired_mechs, cred_usage,
output_cred_handle, actual_mechs, time_rec);
#endif /* CURL_GSS_STUB */
return gss_acquire_cred(minor_status, desired_name, time_req,
desired_mechs, cred_usage,
output_cred_handle, actual_mechs, time_rec);
}
OM_uint32 Curl_gss_indicate_mechs(OM_uint32 *minor_status,
gss_OID_set *mech_set)
{
#ifdef CURL_GSS_STUB
if(getenv("CURL_STUB_GSS_CREDS"))
return stub_gss_indicate_mechs(minor_status, mech_set);
#endif /* CURL_GSS_STUB */
return gss_indicate_mechs(minor_status, mech_set);
}
#ifdef HAVE_GSS_SET_NEG_MECHS
OM_uint32 Curl_gss_set_neg_mechs(OM_uint32 *minor_status,
gss_cred_id_t cred_handle,
const gss_OID_set mech_set)
{
#ifdef CURL_GSS_STUB
if(getenv("CURL_STUB_GSS_CREDS"))
return stub_gss_set_neg_mechs(minor_status, cred_handle, mech_set);
#endif /* CURL_GSS_STUB */
return gss_set_neg_mechs(minor_status, cred_handle, mech_set);
}
#endif /* HAVE_GSS_SET_NEG_MECHS */
OM_uint32 Curl_gss_release_cred(OM_uint32 *minor_status,
gss_cred_id_t *cred_handle)
{
#ifdef CURL_GSS_STUB
if(getenv("CURL_STUB_GSS_CREDS"))
return stub_gss_release_cred(minor_status, cred_handle);
#endif /* CURL_GSS_STUB */
return gss_release_cred(minor_status, cred_handle);
}
#ifdef CURLVERBOSE
#define GSS_LOG_BUFFER_LEN 1024
static size_t display_gss_error(OM_uint32 status, int type,

View file

@ -41,12 +41,38 @@ OM_uint32 Curl_gss_init_sec_context(struct Curl_easy *data,
gss_buffer_t input_token,
gss_buffer_t output_token,
const bool mutual_auth,
OM_uint32 *ret_flags);
OM_uint32 *ret_flags,
gss_cred_id_t cred_handle);
OM_uint32 Curl_gss_delete_sec_context(OM_uint32 *min,
gss_ctx_id_t *context,
gss_buffer_t output_token);
OM_uint32 Curl_gss_inquire_context(OM_uint32 *minor_status,
gss_ctx_id_t context,
gss_OID *mech_type);
OM_uint32 Curl_gss_acquire_cred(OM_uint32 *minor_status,
gss_name_t desired_name,
OM_uint32 time_req,
gss_OID_set desired_mechs,
gss_cred_usage_t cred_usage,
gss_cred_id_t *output_cred_handle,
gss_OID_set *actual_mechs,
OM_uint32 *time_rec);
OM_uint32 Curl_gss_indicate_mechs(OM_uint32 *minor_status,
gss_OID_set *mech_set);
#ifdef HAVE_GSS_SET_NEG_MECHS
OM_uint32 Curl_gss_set_neg_mechs(OM_uint32 *minor_status,
gss_cred_id_t cred_handle,
const gss_OID_set mech_set);
#endif
OM_uint32 Curl_gss_release_cred(OM_uint32 *minor_status,
gss_cred_id_t *cred_handle);
#ifdef CURLVERBOSE
/* Helper to log a GSS-API error status */
void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,

View file

@ -1291,10 +1291,14 @@ typedef unsigned int curl_bit;
#define CURLMAX(x, y) ((x) > (y) ? (x) : (y))
#define CURLMIN(x, y) ((x) < (y) ? (x) : (y))
/* Convenience macro to provide the length of a string literal size without
the null-terminator. Equivalent to strlen() for constant strings. */
#define CURL_CSTRLEN(x) (sizeof(x) - 1)
/* A convenience macro to provide both the string literal and the length of
the string literal in one go, useful for functions that take "string,len"
as their argument */
#define STRCONST(x) x, sizeof(x) - 1
#define STRCONST(x) x, CURL_CSTRLEN(x)
#define CURL_ARRAYSIZE(A) (sizeof(A) / sizeof((A)[0]))

View file

@ -93,7 +93,7 @@ void Curl_sspi_global_cleanup(void)
* Returns CURLE_OK on success.
*/
CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
SEC_WINNT_AUTH_IDENTITY *identity)
SEC_WINNT_AUTH_IDENTITY_EX *identity)
{
xcharp_u useranddomain;
xcharp_u user, dup_user;
@ -105,6 +105,8 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
/* Initialize the identity */
memset(identity, 0, sizeof(*identity));
identity->Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
identity->Length = sizeof(*identity);
useranddomain.tchar_ptr = curlx_convert_UTF8_to_tchar(userp);
if(!useranddomain.tchar_ptr)
@ -195,7 +197,7 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
*
* identity [in/out] - The identity structure.
*/
void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity)
void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY_EX *identity)
{
if(identity) {
curlx_safefree(identity->User);

View file

@ -34,14 +34,14 @@ void Curl_sspi_global_cleanup(void);
/* This is used to populate the domain in an SSPI identity structure */
CURLcode Curl_override_sspi_http_realm(const char *chlg,
SEC_WINNT_AUTH_IDENTITY *identity);
SEC_WINNT_AUTH_IDENTITY_EX *identity);
/* This is used to generate an SSPI identity structure */
CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
SEC_WINNT_AUTH_IDENTITY *identity);
SEC_WINNT_AUTH_IDENTITY_EX *identity);
/* This is used to free an SSPI identity structure */
void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity);
void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY_EX *identity);
/* Forward-declaration of global variables defined in curl_sspi.c */
extern PSecurityFunctionTable Curl_pSecFn;

View file

@ -153,9 +153,9 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
if(result)
return result;
if(curl_strnequal(path, DICT_MATCH, sizeof(DICT_MATCH) - 1) ||
curl_strnequal(path, DICT_MATCH2, sizeof(DICT_MATCH2) - 1) ||
curl_strnequal(path, DICT_MATCH3, sizeof(DICT_MATCH3) - 1)) {
if(curl_strnequal(path, DICT_MATCH, CURL_CSTRLEN(DICT_MATCH)) ||
curl_strnequal(path, DICT_MATCH2, CURL_CSTRLEN(DICT_MATCH2)) ||
curl_strnequal(path, DICT_MATCH3, CURL_CSTRLEN(DICT_MATCH3))) {
word = strchr(path, ':');
if(word) {
@ -200,9 +200,9 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
}
Curl_xfer_setup_recv(data, FIRSTSOCKET, -1);
}
else if(curl_strnequal(path, DICT_DEFINE, sizeof(DICT_DEFINE) - 1) ||
curl_strnequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2) - 1) ||
curl_strnequal(path, DICT_DEFINE3, sizeof(DICT_DEFINE3) - 1)) {
else if(curl_strnequal(path, DICT_DEFINE, CURL_CSTRLEN(DICT_DEFINE)) ||
curl_strnequal(path, DICT_DEFINE2, CURL_CSTRLEN(DICT_DEFINE2)) ||
curl_strnequal(path, DICT_DEFINE3, CURL_CSTRLEN(DICT_DEFINE3))) {
word = strchr(path, ':');
if(word) {

View file

@ -5026,7 +5026,7 @@ CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
if(e->namelen == 2 && curl_strequal("TE", e->name)) {
if(http_TE_has_token(e->value, "trailers"))
result = Curl_dynhds_add(h2_headers, e->name, e->namelen,
"trailers", sizeof("trailers") - 1);
"trailers", CURL_CSTRLEN("trailers"));
}
else if(h2_permissible_field(e)) {
result = Curl_dynhds_add(h2_headers, e->name, e->namelen,

View file

@ -1427,7 +1427,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(frame->hd.type == NGHTTP2_PUSH_PROMISE) {
char *h;
if((namelen == (sizeof(HTTP_PSEUDO_AUTHORITY) - 1)) &&
if((namelen == CURL_CSTRLEN(HTTP_PSEUDO_AUTHORITY)) &&
!strncmp(HTTP_PSEUDO_AUTHORITY, (const char *)name, namelen)) {
/* pseudo headers are lower case */
int rc = 0;
@ -1503,7 +1503,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
return 0;
}
if(namelen == sizeof(HTTP_PSEUDO_STATUS) - 1 &&
if(namelen == CURL_CSTRLEN(HTTP_PSEUDO_STATUS) &&
!memcmp(HTTP_PSEUDO_STATUS, name, namelen)) {
/* nghttp2 guarantees :status is received first and only once. */
char buffer[32];

View file

@ -623,7 +623,7 @@ static CURLcode calc_s3_payload_hash(struct Curl_easy *data,
}
else {
/* Fall back to s3's UNSIGNED-PAYLOAD */
size_t len = sizeof(S3_UNSIGNED_PAYLOAD) - 1;
size_t len = CURL_CSTRLEN(S3_UNSIGNED_PAYLOAD);
DEBUGASSERT(len < SHA256_HEX_LENGTH); /* 16 < 65 */
memcpy(sha_hex, S3_UNSIGNED_PAYLOAD, len);
sha_hex[len] = 0;
@ -1143,7 +1143,7 @@ static CURLcode sign_and_set_auth_headers(struct Curl_easy *data,
goto fail;
/* provider 0 uppercase */
Curl_strntoupper(&auth_headers[sizeof("Authorization: ") - 1],
Curl_strntoupper(&auth_headers[CURL_CSTRLEN("Authorization: ")],
curlx_str(provider0), curlx_strlen(provider0));
curlx_free(data->req.hd_auth);

View file

@ -54,7 +54,7 @@ CURLcode Curl_input_digest(struct Curl_easy *data,
if(!checkprefix("Digest", header) || !ISBLANK(header[6]))
return CURLE_AUTH_ERROR;
header += strlen("Digest");
header += CURL_CSTRLEN("Digest");
curlx_str_passblanks(&header);
return Curl_auth_decode_digest_http_message(header, digest);

View file

@ -83,7 +83,7 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
/* Obtain the input token, if any */
header += strlen("Negotiate");
header += CURL_CSTRLEN("Negotiate");
curlx_str_passblanks(&header);
len = strlen(header);

View file

@ -65,7 +65,7 @@ CURLcode Curl_input_ntlm(struct Curl_easy *data,
if(!ntlm)
return CURLE_OUT_OF_MEMORY;
header += strlen("NTLM");
header += CURL_CSTRLEN("NTLM");
curlx_str_passblanks(&header);
if(*header) {
unsigned char *hdr;

View file

@ -215,7 +215,7 @@ static CURLcode http_proxy_create_CONNECT(struct httpreq **preq,
goto out;
}
result = Curl_http_req_make(&req, "CONNECT", sizeof("CONNECT") - 1,
result = Curl_http_req_make(&req, "CONNECT", CURL_CSTRLEN("CONNECT"),
NULL, 0, authority, strlen(authority),
NULL, 0);
if(result)
@ -340,7 +340,7 @@ static CURLcode http_proxy_create_CONNECTUDP(struct httpreq **preq,
}
if(ver == PROXY_HTTP_V1) {
result = Curl_http_req_make(&req, "GET", sizeof("GET")-1,
result = Curl_http_req_make(&req, "GET", CURL_CSTRLEN("GET"),
proxy_scheme, strlen(proxy_scheme),
authority, strlen(authority),
path, strlen(path));
@ -348,7 +348,7 @@ static CURLcode http_proxy_create_CONNECTUDP(struct httpreq **preq,
goto out;
}
else if(ver == PROXY_HTTP_V2 || ver == PROXY_HTTP_V3) {
result = Curl_http_req_make(&req, "CONNECT", sizeof("CONNECT") - 1,
result = Curl_http_req_make(&req, "CONNECT", CURL_CSTRLEN("CONNECT"),
proxy_scheme, strlen(proxy_scheme),
authority, strlen(authority),
path, strlen(path));

View file

@ -1357,7 +1357,7 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data,
size_t len = curlx_dyn_len(&imapc->pp.recvbuf);
if((len >= 18) && checkprefix("OK [UIDVALIDITY ", &line[2])) {
curl_off_t value;
const char *p = &line[2] + strlen("OK [UIDVALIDITY ");
const char *p = &line[2] + CURL_CSTRLEN("OK [UIDVALIDITY ");
if(!curlx_str_number(&p, &value, UINT_MAX)) {
imapc->mb_uidvalidity = (unsigned int)value;
imapc->mb_uidvalidity_set = TRUE;

View file

@ -157,7 +157,7 @@ static ULONG ldap_win_bind_auth(LDAP *server, const char *user,
const char *passwd, unsigned long authflags)
{
ULONG method = 0;
SEC_WINNT_AUTH_IDENTITY cred;
SEC_WINNT_AUTH_IDENTITY_EX cred;
ULONG rc = LDAP_AUTH_METHOD_NOT_SUPPORTED;
memset(&cred, 0, sizeof(cred));
@ -976,9 +976,9 @@ void Curl_ldap_version(char *buf, size_t bufsz)
curl_msnprintf(buf, bufsz, "WinLDAP");
#else
#ifdef LDAP_OPT_X_TLS_PASSPHRASE
static const char *flavor = "/Apple";
static const char flavor[] = "/Apple";
#else
static const char *flavor = "";
static const char flavor[] = "";
#endif
LDAPAPIInfo api;
api.ldapai_info_version = LDAP_API_INFO_VERSION;

View file

@ -276,7 +276,7 @@ static CURLcode mqtt_connect(struct Curl_easy *data)
size_t start_user = 0;
size_t start_pwd = 0;
char client_id[MQTT_CLIENTID_LEN + 1] = "curl";
const size_t clen = strlen("curl");
const size_t clen = CURL_CSTRLEN("curl");
char *packet = NULL;
/* extracting username from request */
@ -627,7 +627,7 @@ static bool mqtt_decode_len(size_t *lenp, const unsigned char *buf,
}
#if defined(DEBUGBUILD) && defined(CURLVERBOSE)
static const char *statenames[] = {
static const char * const statenames[] = {
"MQTT_FIRST",
"MQTT_REMAINING_LENGTH",
"MQTT_CONNACK",

View file

@ -91,7 +91,7 @@ UNITTEST char *max6out(curl_off_t bytes, char *max6, size_t mlen)
if(bytes < 100000)
curl_msnprintf(max6, mlen, "%6" CURL_FORMAT_CURL_OFF_T, bytes);
else {
const char unit[] = { 'k', 'M', 'G', 'T', 'P', 'E', 0 };
static const char unit[] = { 'k', 'M', 'G', 'T', 'P', 'E', 0 };
int k = 0;
curl_off_t nbytes;
curl_off_t rest;

View file

@ -654,9 +654,10 @@ static CURLcode smb_send_negotiate(struct Curl_easy *data,
struct smb_conn *smbc,
struct smb_request *req)
{
const char *msg = "\x00\x0c\x00\x02NT LM 0.12";
static const char msg[] = "\x00\x0c\x00\x02NT LM 0.12";
return smb_send_message(data, smbc, req, SMB_COM_NEGOTIATE, msg, 15);
return smb_send_message(data, smbc, req, SMB_COM_NEGOTIATE, msg,
sizeof(msg));
}
static CURLcode smb_send_setup(struct Curl_easy *data)
@ -678,7 +679,7 @@ static CURLcode smb_send_setup(struct Curl_easy *data)
byte_count = sizeof(lm) + sizeof(nt) +
strlen(smbc->user) + strlen(smbc->domain) +
strlen(CURL_OS) + strlen(CLIENTNAME) + 4; /* 4 null chars */
CURL_CSTRLEN(CURL_OS) + CURL_CSTRLEN(CLIENTNAME) + 4; /* 4 null chars */
if(byte_count > sizeof(msg.bytes))
return CURLE_FILESIZE_EXCEEDED;
@ -724,7 +725,7 @@ static CURLcode smb_send_tree_connect(struct Curl_easy *data,
char *p = msg.bytes;
const size_t byte_count = strlen(conn->origin->hostname) +
strlen(smbc->share) +
strlen(SERVICENAME) + 5; /* 2 nulls and 3 backslashes */
CURL_CSTRLEN(SERVICENAME) + 5; /* 2 nulls and 3 backslashes */
if(byte_count > sizeof(msg.bytes))
return CURLE_FILESIZE_EXCEEDED;

View file

@ -176,7 +176,8 @@ static CURLcode socks5_gss_auth_loop(struct Curl_cfilter *cf,
gss_token,
&gss_send_token,
TRUE,
gss_ret_flags);
gss_ret_flags,
GSS_C_NO_CREDENTIAL);
if(gss_token != GSS_C_NO_BUFFER) {
curlx_safefree(gss_recv_token.value);

View file

@ -452,34 +452,34 @@ const char *curl_url_strerror(CURLUcode error)
return "An unknown part ID was passed to a URL API function";
case CURLUE_NO_SCHEME:
return "No scheme part in the URL";
return "No scheme present";
case CURLUE_NO_USER:
return "No user part in the URL";
return "No user present";
case CURLUE_NO_PASSWORD:
return "No password part in the URL";
return "No password present";
case CURLUE_NO_OPTIONS:
return "No options part in the URL";
return "No options present";
case CURLUE_NO_HOST:
return "No host part in the URL";
return "No host present";
case CURLUE_NO_PORT:
return "No port part in the URL";
return "No port number present";
case CURLUE_NO_QUERY:
return "No query part in the URL";
return "No query present";
case CURLUE_NO_FRAGMENT:
return "No fragment part in the URL";
return "No fragment present";
case CURLUE_NO_ZONEID:
return "No zoneid part in the URL";
return "No zoneid present";
case CURLUE_BAD_LOGIN:
return "Bad login part";
return "Bad login";
case CURLUE_BAD_IPV6:
return "Bad IPv6 address";
@ -517,6 +517,9 @@ const char *curl_url_strerror(CURLUcode error)
case CURLUE_TOO_LARGE:
return "A value or data field is larger than allowed";
case CURLUE_BACKSLASH:
return "Found a backslash where a forward slash was expected";
case CURLUE_LAST:
break;
}

View file

@ -278,7 +278,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_conn *state,
infof(data, "got option=(%s) value=(%s)", option, value);
if((strlen(TFTP_OPTION_BLKSIZE) == olen) &&
if((CURL_CSTRLEN(TFTP_OPTION_BLKSIZE) == olen) &&
checkprefix(TFTP_OPTION_BLKSIZE, option)) {
curl_off_t blksize;
if(curlx_str_number(&value, &blksize, TFTP_BLKSIZE_MAX)) {
@ -308,7 +308,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_conn *state,
infof(data, "blksize parsed from OACK (%u) requested (%u)",
state->blksize, state->requested_blksize);
}
else if((strlen(TFTP_OPTION_TSIZE) == olen) &&
else if((CURL_CSTRLEN(TFTP_OPTION_TSIZE) == olen) &&
checkprefix(TFTP_OPTION_TSIZE, option)) {
curl_off_t tsize = 0;
/* tsize should be ignored on upload: Who cares about the size of the

113
lib/url.c
View file

@ -564,115 +564,6 @@ static bool proxy_info_matches(const struct proxy_info *data,
}
#endif
/* A connection has to have been idle for less than 'conn_max_idle_ms'
(the success rate is too low after this), or created less than
'conn_max_age_ms' ago, to be subject for reuse. */
static bool conn_maxage(struct Curl_easy *data,
struct connectdata *conn,
struct curltime now)
{
timediff_t age_ms;
if(data->set.conn_max_idle_ms) {
age_ms = curlx_ptimediff_ms(&now, &conn->lastused);
if(age_ms > data->set.conn_max_idle_ms) {
infof(data, "Too old connection (%" FMT_TIMEDIFF_T
" ms idle, max idle is %" FMT_TIMEDIFF_T " ms), disconnect it",
age_ms, data->set.conn_max_idle_ms);
return TRUE;
}
}
if(data->set.conn_max_age_ms) {
age_ms = curlx_ptimediff_ms(&now, &conn->created);
if(age_ms > data->set.conn_max_age_ms) {
infof(data,
"Too old connection (created %" FMT_TIMEDIFF_T
" ms ago, max lifetime is %" FMT_TIMEDIFF_T " ms), disconnect it",
age_ms, data->set.conn_max_age_ms);
return TRUE;
}
}
return FALSE;
}
/*
* Return TRUE iff the given connection is considered dead.
*/
bool Curl_conn_seems_dead(struct connectdata *conn,
struct Curl_easy *data,
const struct curltime *pnow)
{
DEBUGASSERT(!data->conn);
if(!CONN_INUSE(conn)) {
/* The check for a dead socket makes sense only if the connection is not in
use */
bool dead;
if(conn_maxage(data, conn, *pnow)) {
/* avoid check if already too old */
dead = TRUE;
}
else if(curlx_ptimediff_ms(pnow, &conn->lastchecked) < 1000)
dead = FALSE;
else if(conn->scheme->run->connection_is_dead) {
/* The protocol has a special method for checking the state of the
connection. Use it to check if the connection is dead. */
/* briefly attach the connection for the check */
Curl_attach_connection(data, conn);
dead = conn->scheme->run->connection_is_dead(data, conn);
Curl_detach_connection(data);
conn->lastchecked = *pnow;
}
else {
bool input_pending = FALSE;
Curl_attach_connection(data, conn);
dead = !Curl_conn_is_alive(data, conn, &input_pending);
if(input_pending) {
/* For reuse, we want a "clean" connection state. This includes
* that we expect - in general - no waiting input data. Input
* waiting might be a TLS Notify Close, for example. We reject
* that.
* For protocols where data from other end may arrive at
* any time (HTTP/2 PING for example), the protocol handler needs
* to install its own `connection_check` callback.
*/
DEBUGF(infof(data, "connection has input pending, not reusable"));
dead = TRUE;
}
Curl_detach_connection(data);
conn->lastchecked = *pnow;
}
if(dead) {
/* remove connection from cpool */
infof(data, "Connection %" FMT_OFF_T " seems to be dead",
conn->connection_id);
return TRUE;
}
}
return FALSE;
}
CURLcode Curl_conn_upkeep(struct Curl_easy *data,
struct connectdata *conn)
{
CURLcode result = CURLE_OK;
if(curlx_ptimediff_ms(Curl_pgrs_now(data), &conn->keepalive) <=
data->set.upkeep_interval_ms)
return result;
/* briefly attach for action */
Curl_attach_connection(data, conn);
result = Curl_conn_keep_alive(data, conn, FIRSTSOCKET);
Curl_detach_connection(data);
conn->keepalive = *Curl_pgrs_now(data);
return result;
}
#ifdef USE_SSH
static bool ssh_config_matches(struct connectdata *one,
struct connectdata *two)
@ -1172,8 +1063,10 @@ static bool url_match_conn(struct connectdata *conn, void *userdata)
if(!url_match_multiplex_limits(conn, m))
return FALSE;
if(!CONN_INUSE(conn) && Curl_conn_seems_dead(conn, m->data, &m->now)) {
if(Curl_cpool_conn_seems_dead(conn, m->data, &m->now)) {
/* remove and disconnect. */
infof(m->data, "Connection %" FMT_OFF_T " seems to be dead, terminating",
conn->connection_id);
Curl_conn_terminate(m->data, conn, FALSE);
return FALSE;
}

View file

@ -71,23 +71,8 @@ void *Curl_conn_meta_get(struct connectdata *conn, const char *key);
#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless
specified */
/**
* Return TRUE iff the given connection is considered dead.
*/
bool Curl_conn_seems_dead(struct connectdata *conn,
struct Curl_easy *data,
const struct curltime *pnow);
/**
* Perform upkeep operations on the connection.
*/
CURLcode Curl_conn_upkeep(struct Curl_easy *data,
struct connectdata *conn);
/**
* Always eval all arguments, return the first
* result != (CURLE_OK | CURLE_AGAIN) or `r1`.
*/
/* Always eval all arguments, return the first
* result != (CURLE_OK | CURLE_AGAIN) or `r1`. */
CURLcode Curl_1st_fatal(CURLcode r1, CURLcode r2);
#if defined(USE_HTTP2) || defined(USE_HTTP3)

View file

@ -382,6 +382,7 @@ UNITTEST CURLUcode parse_port(struct Curl_URL *u, struct dynbuf *host,
if(portptr) {
curl_off_t port;
size_t keep = portptr - hostname;
int rc;
/* Browser behavior adaptation. If there is a colon with no digits after,
cut off the name there which makes us ignore the colon and use the
@ -393,8 +394,14 @@ UNITTEST CURLUcode parse_port(struct Curl_URL *u, struct dynbuf *host,
portptr++;
if(!*portptr)
return has_scheme ? CURLUE_OK : CURLUE_BAD_PORT_NUMBER;
if(curlx_str_number(&portptr, &port, 0xffff) || *portptr)
if(*portptr == '\\')
return CURLUE_BACKSLASH;
rc = curlx_str_number(&portptr, &port, 0xffff);
if(rc)
return CURLUE_BAD_PORT_NUMBER;
else if(*portptr == '\\')
return CURLUE_BACKSLASH;
else if(*portptr)
return CURLUE_BAD_PORT_NUMBER;
u->portnum = (uint16_t)port;
@ -666,12 +673,11 @@ static CURLUcode parse_authority(struct Curl_URL *u,
}
uc = parse_port(u, host, has_scheme);
if(uc)
return uc;
if(!curlx_dyn_len(host))
/* this makes no-host errors override port number problems */
uc = CURLUE_NO_HOST;
else
if(!uc)
uc = urldecode_host(host);
if(uc)
return uc;

View file

@ -95,8 +95,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
CredHandle credentials;
CtxtHandle context;
PSecPkgInfo SecurityPackage;
SEC_WINNT_AUTH_IDENTITY identity;
SEC_WINNT_AUTH_IDENTITY *p_identity;
SEC_WINNT_AUTH_IDENTITY_EX identity;
SEC_WINNT_AUTH_IDENTITY_EX *p_identity;
SecBuffer chlg_buf;
SecBuffer resp_buf;
SecBufferDesc chlg_desc;
@ -243,7 +243,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
* Returns CURLE_OK on success.
*/
CURLcode Curl_override_sspi_http_realm(const char *chlg,
SEC_WINNT_AUTH_IDENTITY *identity)
SEC_WINNT_AUTH_IDENTITY_EX *identity)
{
xcharp_u domain, dup_domain;
@ -465,8 +465,8 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
if(!digest->http_context) {
CredHandle credentials;
SEC_WINNT_AUTH_IDENTITY identity;
SEC_WINNT_AUTH_IDENTITY *p_identity;
SEC_WINNT_AUTH_IDENTITY_EX identity;
SEC_WINNT_AUTH_IDENTITY_EX *p_identity;
SecBuffer resp_buf;
SecBufferDesc resp_desc;
unsigned long attrs;

View file

@ -136,7 +136,8 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
&input_token,
&output_token,
mutual_auth,
NULL);
NULL,
GSS_C_NO_CREDENTIAL);
if(GSS_ERROR(major_status)) {
if(output_token.value)

View file

@ -158,6 +158,57 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
}
#endif
#ifdef HAVE_GSS_SET_NEG_MECHS
/* Acquire explicit credentials and restrict SPNEGO sub-mechanisms to
* exclude NTLM. We enumerate all available mechanisms and filter out
* the NTLMSSP OID, matching SSPI's "!ntlm". */
if(nego->cred == GSS_C_NO_CREDENTIAL) {
/* OID 1.3.6.1.4.1.311.2.2.10 (NTLMSSP) */
static const gss_OID_desc ntlmssp_oid = {
10, CURL_UNCONST("\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a")
};
gss_OID_set available_mechs = GSS_C_NO_OID_SET;
gss_OID_set filtered_mechs = GSS_C_NO_OID_SET;
/* Acquire default credentials for SPNEGO */
major_status = Curl_gss_acquire_cred(&minor_status, GSS_C_NO_NAME,
GSS_C_INDEFINITE, GSS_C_NO_OID_SET,
GSS_C_INITIATE, &nego->cred, NULL, NULL);
if(GSS_ERROR(major_status)) {
Curl_gss_log_error(data, "gss_acquire_cred() failed: ",
major_status, minor_status);
curlx_safefree(input_token.value);
return CURLE_AUTH_ERROR;
}
/* Get all available mechanisms */
major_status = Curl_gss_indicate_mechs(&minor_status, &available_mechs);
if(!GSS_ERROR(major_status)) {
/* Build a set excluding NTLMSSP */
major_status = gss_create_empty_oid_set(&minor_status, &filtered_mechs);
if(!GSS_ERROR(major_status)) {
size_t i;
for(i = 0; i < available_mechs->count; i++) {
gss_OID oid = &available_mechs->elements[i];
if(oid->length != ntlmssp_oid.length ||
memcmp(oid->elements, ntlmssp_oid.elements, oid->length)) {
gss_add_oid_set_member(&minor_status, oid, &filtered_mechs);
}
}
/* Restrict SPNEGO to only use non-NTLM mechanisms */
major_status = Curl_gss_set_neg_mechs(&minor_status, nego->cred,
filtered_mechs);
if(GSS_ERROR(major_status)) {
Curl_gss_log_error(data, "gss_set_neg_mechs() failed: ",
major_status, minor_status);
}
gss_release_oid_set(&minor_status, &filtered_mechs);
}
gss_release_oid_set(&minor_status, &available_mechs);
}
}
#endif /* HAVE_GSS_SET_NEG_MECHS */
/* Generate our challenge-response message */
major_status = Curl_gss_init_sec_context(data,
&minor_status,
@ -168,7 +219,8 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
&input_token,
&output_token,
TRUE,
NULL);
NULL,
nego->cred);
/* Free the decoded challenge as it is not required anymore */
curlx_safefree(input_token.value);
@ -191,6 +243,29 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
return CURLE_AUTH_ERROR;
}
/* Check if NTLM was selected and is disallowed */
if(nego->context != GSS_C_NO_CONTEXT) {
/* OID 1.3.6.1.4.1.311.2.2.10 (NTLMSSP) */
static const gss_OID_desc ntlmssp_oid = {
10, CURL_UNCONST("\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a")
};
OM_uint32 inquire_major, inquire_minor;
gss_OID mech_type = GSS_C_NO_OID;
inquire_major = Curl_gss_inquire_context(&inquire_minor,
nego->context,
&mech_type);
if(!GSS_ERROR(inquire_major) && mech_type &&
mech_type->length == ntlmssp_oid.length &&
!memcmp(mech_type->elements, ntlmssp_oid.elements,
ntlmssp_oid.length)) {
infof(data, "SPNEGO chose NTLM, but NTLM is not allowed");
gss_release_buffer(&unused_status, &output_token);
Curl_auth_cleanup_spnego(nego);
return CURLE_AUTH_ERROR;
}
}
/* Free previous token */
if(nego->output_token.length && nego->output_token.value)
gss_release_buffer(&unused_status, &nego->output_token);
@ -280,6 +355,12 @@ void Curl_auth_cleanup_spnego(struct negotiatedata *nego)
nego->spn = GSS_C_NO_NAME;
}
/* Free our credentials */
if(nego->cred != GSS_C_NO_CREDENTIAL) {
Curl_gss_release_cred(&minor_status, &nego->cred);
nego->cred = GSS_C_NO_CREDENTIAL;
}
/* Reset any variables */
nego->status = 0;
nego->noauthpersist = FALSE;

View file

@ -148,6 +148,32 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
/* Use the current Windows user */
nego->p_identity = NULL;
/* Exclude NTLM from SPNEGO negotiation via the PackageList field */
if(!nego->p_identity) {
memset(&nego->identity, 0, sizeof(nego->identity));
nego->identity.Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
nego->identity.Length = sizeof(nego->identity);
nego->identity.Flags =
#ifdef UNICODE
SEC_WINNT_AUTH_IDENTITY_UNICODE;
#else
SEC_WINNT_AUTH_IDENTITY_ANSI;
#endif
nego->p_identity = &nego->identity;
}
/* Use the special name "!ntlm" to prevent NTLM from being used:
* https://learn.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-sec_winnt_auth_identity_exa
*/
#ifdef UNICODE
nego->identity.PackageList =
(unsigned short *)CURL_UNCONST(TEXT("!ntlm"));
#else
nego->identity.PackageList =
(unsigned char *)CURL_UNCONST(TEXT("!ntlm"));
#endif
nego->identity.PackageListLength = 5;
/* Allocate our credentials handle */
nego->credentials = curlx_calloc(1, sizeof(CredHandle));
if(!nego->credentials)

View file

@ -169,8 +169,8 @@ struct ntlmdata {
#endif
CredHandle *credentials;
CtxtHandle *context;
SEC_WINNT_AUTH_IDENTITY identity;
SEC_WINNT_AUTH_IDENTITY *p_identity;
SEC_WINNT_AUTH_IDENTITY_EX identity;
SEC_WINNT_AUTH_IDENTITY_EX *p_identity;
size_t token_max;
BYTE *output_token;
BYTE *input_token;
@ -236,8 +236,8 @@ struct kerberos5data {
CredHandle *credentials;
CtxtHandle *context;
TCHAR *spn;
SEC_WINNT_AUTH_IDENTITY identity;
SEC_WINNT_AUTH_IDENTITY *p_identity;
SEC_WINNT_AUTH_IDENTITY_EX identity;
SEC_WINNT_AUTH_IDENTITY_EX *p_identity;
size_t token_max;
BYTE *output_token;
#else
@ -291,6 +291,7 @@ struct negotiatedata {
OM_uint32 status;
gss_ctx_id_t context;
gss_name_t spn;
gss_cred_id_t cred;
gss_buffer_desc output_token;
#ifdef GSS_C_CHANNEL_BOUND_FLAG
struct dynbuf channel_binding_data;
@ -303,8 +304,8 @@ struct negotiatedata {
SECURITY_STATUS status;
CredHandle *credentials;
CtxtHandle *context;
SEC_WINNT_AUTH_IDENTITY identity;
SEC_WINNT_AUTH_IDENTITY *p_identity;
SEC_WINNT_AUTH_IDENTITY_EX identity;
SEC_WINNT_AUTH_IDENTITY_EX *p_identity;
TCHAR *spn;
size_t token_max;
BYTE *output_token;

View file

@ -1298,9 +1298,8 @@ static CURLcode cf_quiche_ctx_open(struct Curl_cfilter *cf,
10 * QUIC_MAX_STREAMS * H3_STREAM_WINDOW_SIZE);
quiche_config_set_max_stream_window(ctx->cfg, 10 * H3_STREAM_WINDOW_SIZE);
quiche_config_set_application_protos(ctx->cfg,
(uint8_t *)CURL_UNCONST(QUICHE_H3_APPLICATION_PROTOCOL),
sizeof(QUICHE_H3_APPLICATION_PROTOCOL)
- 1);
(uint8_t *)CURL_UNCONST(QUICHE_H3_APPLICATION_PROTOCOL),
CURL_CSTRLEN(QUICHE_H3_APPLICATION_PROTOCOL));
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->ssl_peer,
&ALPN_SPEC_H3, NULL, NULL, cf, NULL);
@ -1351,7 +1350,7 @@ static CURLcode cf_quiche_ctx_open(struct Curl_cfilter *cf,
unsigned alpn_len, offset = 0;
/* Replace each ALPN length prefix by a comma. */
while(offset < sizeof(alpn_protocols) - 1) {
while(offset < CURL_CSTRLEN(alpn_protocols)) {
alpn_len = alpn_protocols[offset];
alpn_protocols[offset] = ',';
offset += 1 + alpn_len;

View file

@ -1768,7 +1768,7 @@ static CURLcode ssh_state_sftp_realpath(struct Curl_easy *data,
return CURLE_FAILED_INIT;
rc = libssh2_sftp_symlink_ex(sshc->sftp_session, ".",
curlx_uztoui(strlen(".")),
curlx_uztoui(CURL_CSTRLEN(".")),
sshp->readdir_filename, CURL_PATH_MAX,
LIBSSH2_SFTP_REALPATH);
if(rc == LIBSSH2_ERROR_EAGAIN)

View file

@ -48,7 +48,7 @@
/* Text for cipher suite parts (max 64 entries),
keep indexes below in sync with this! */
static const char *cs_txt =
static const char cs_txt[] =
"\0"
"TLS" "\0"
"WITH" "\0"

View file

@ -591,7 +591,7 @@ static struct gtls_shared_creds *gtls_get_cached_creds(struct Curl_cfilter *cf,
if(data->multi) {
shared_creds = Curl_hash_pick(&data->multi->proto_hash,
CURL_UNCONST(MPROTO_GTLS_X509_KEY),
sizeof(MPROTO_GTLS_X509_KEY) - 1);
CURL_CSTRLEN(MPROTO_GTLS_X509_KEY));
if(shared_creds && shared_creds->creds &&
!gtls_shared_creds_expired(data, shared_creds) &&
!gtls_shared_creds_different(cf, shared_creds)) {
@ -604,7 +604,7 @@ static struct gtls_shared_creds *gtls_get_cached_creds(struct Curl_cfilter *cf,
static void gtls_shared_creds_hash_free(void *key, size_t key_len, void *p)
{
struct gtls_shared_creds *sc = p;
DEBUGASSERT(key_len == (sizeof(MPROTO_GTLS_X509_KEY) - 1));
DEBUGASSERT(key_len == CURL_CSTRLEN(MPROTO_GTLS_X509_KEY));
DEBUGASSERT(!memcmp(MPROTO_GTLS_X509_KEY, key, key_len));
(void)key;
(void)key_len;
@ -635,7 +635,7 @@ static void gtls_set_cached_creds(struct Curl_cfilter *cf,
if(!Curl_hash_add2(&data->multi->proto_hash,
CURL_UNCONST(MPROTO_GTLS_X509_KEY),
sizeof(MPROTO_GTLS_X509_KEY) - 1,
CURL_CSTRLEN(MPROTO_GTLS_X509_KEY),
sc, gtls_shared_creds_hash_free)) {
Curl_gtls_shared_creds_free(&sc); /* down reference again */
return;

View file

@ -25,7 +25,7 @@
***************************************************************************/
#include "curl_setup.h"
#define KEYLOG_LABEL_MAXLEN (sizeof("CLIENT_HANDSHAKE_TRAFFIC_SECRET") - 1)
#define KEYLOG_LABEL_MAXLEN CURL_CSTRLEN("CLIENT_HANDSHAKE_TRAFFIC_SECRET")
#define CLIENT_RANDOM_SIZE 32

View file

@ -248,7 +248,7 @@ static CURLcode X509V3_ext(struct Curl_easy *data,
if(asn1_object_dump(obj, namebuf, sizeof(namebuf)))
/* make sure the name is null-terminated */
namebuf[sizeof(namebuf) - 1] = 0;
namebuf[CURL_CSTRLEN(namebuf)] = 0;
if(!X509V3_EXT_print(bio_out, ext, 0, 0))
ASN1_STRING_print(bio_out,
@ -1176,7 +1176,7 @@ static int engineload(struct Curl_easy *data,
}
if(data->state.engine) {
const char *cmd_name = "LOAD_CERT_CTRL";
static const char cmd_name[] = "LOAD_CERT_CTRL";
struct {
const char *cert_id;
X509 *cert;
@ -2965,7 +2965,7 @@ static CURLcode ossl_windows_load_anchors(struct Curl_cfilter *cf,
https://stackoverflow.com/questions/9507184/
https://github.com/d3x0r/SACK/blob/ff15424d3c581b86d40f818532e5a400c516d39d/src/netlib/ssl_layer.c#L1410
https://datatracker.ietf.org/doc/html/rfc5280 */
const char *win_stores[] = {
static const char * const win_stores[] = {
"ROOT", /* Trusted Root Certification Authorities */
"CA" /* Intermediate Certification Authorities */
};
@ -3180,7 +3180,7 @@ struct ossl_x509_share {
static void oss_x509_share_free(void *key, size_t key_len, void *p)
{
struct ossl_x509_share *share = p;
DEBUGASSERT(key_len == (sizeof(MPROTO_OSSL_X509_KEY) - 1));
DEBUGASSERT(key_len == CURL_CSTRLEN(MPROTO_OSSL_X509_KEY));
DEBUGASSERT(!memcmp(MPROTO_OSSL_X509_KEY, key, key_len));
(void)key;
(void)key_len;
@ -3231,7 +3231,7 @@ static X509_STORE *ossl_get_cached_x509_store(struct Curl_cfilter *cf,
*pempty = TRUE;
share = multi ? Curl_hash_pick(&multi->proto_hash,
CURL_UNCONST(MPROTO_OSSL_X509_KEY),
sizeof(MPROTO_OSSL_X509_KEY) - 1) : NULL;
CURL_CSTRLEN(MPROTO_OSSL_X509_KEY)) : NULL;
if(share && share->store &&
!ossl_cached_x509_store_expired(data, share) &&
!ossl_cached_x509_store_different(cf, data, share)) {
@ -3256,7 +3256,7 @@ static void ossl_set_cached_x509_store(struct Curl_cfilter *cf,
return;
share = Curl_hash_pick(&multi->proto_hash,
CURL_UNCONST(MPROTO_OSSL_X509_KEY),
sizeof(MPROTO_OSSL_X509_KEY) - 1);
CURL_CSTRLEN(MPROTO_OSSL_X509_KEY));
if(!share) {
share = curlx_calloc(1, sizeof(*share));
@ -3264,7 +3264,7 @@ static void ossl_set_cached_x509_store(struct Curl_cfilter *cf,
return;
if(!Curl_hash_add2(&multi->proto_hash,
CURL_UNCONST(MPROTO_OSSL_X509_KEY),
sizeof(MPROTO_OSSL_X509_KEY) - 1,
CURL_CSTRLEN(MPROTO_OSSL_X509_KEY),
share, oss_x509_share_free)) {
curlx_free(share);
return;
@ -5283,7 +5283,7 @@ static CURLcode ossl_get_channel_binding(struct Curl_easy *data,
unsigned int length;
unsigned char buf[EVP_MAX_MD_SIZE];
const char prefix[] = "tls-server-end-point:";
static const char prefix[] = "tls-server-end-point:";
struct connectdata *conn = data->conn;
struct Curl_cfilter *cf = conn->cfilter[sockindex];
struct ossl_ctx *octx = NULL;
@ -5405,7 +5405,7 @@ static CURLcode ossl_get_channel_binding(struct Curl_easy *data,
}
/* Append "tls-server-end-point:" */
result = curlx_dyn_addn(binding, prefix, sizeof(prefix) - 1);
result = curlx_dyn_addn(binding, prefix, CURL_CSTRLEN(prefix));
if(result)
goto out;
@ -5423,9 +5423,9 @@ size_t Curl_ossl_version(char *buffer, size_t size)
char *p;
size_t count;
const char *ver = OpenSSL_version(OPENSSL_VERSION);
const char expected[] = OSSL_PACKAGE " "; /* ie "LibreSSL " */
if(curl_strnequal(ver, expected, sizeof(expected) - 1)) {
ver += sizeof(expected) - 1;
static const char expected[] = OSSL_PACKAGE " "; /* ie "LibreSSL " */
if(curl_strnequal(ver, expected, CURL_CSTRLEN(expected))) {
ver += CURL_CSTRLEN(expected);
}
count = curl_msnprintf(buffer, size, "%s/%s", OSSL_PACKAGE, ver);
for(p = buffer; *p; ++p) {

View file

@ -291,9 +291,9 @@ static CURLcode set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers,
if(alg)
algIds[algCount++] = (ALG_ID)alg;
else if(!strncmp(startCur, "USE_STRONG_CRYPTO",
sizeof("USE_STRONG_CRYPTO") - 1) ||
CURL_CSTRLEN("USE_STRONG_CRYPTO")) ||
!strncmp(startCur, "SCH_USE_STRONG_CRYPTO",
sizeof("SCH_USE_STRONG_CRYPTO") - 1))
CURL_CSTRLEN("SCH_USE_STRONG_CRYPTO")))
schannel_cred->dwFlags |= SCH_USE_STRONG_CRYPTO;
else
return CURLE_SSL_CIPHER;
@ -441,12 +441,13 @@ static CURLcode get_client_cert(struct Curl_cfilter *cf,
if(fInCert) {
long cert_tell = 0;
bool continue_reading = fseek(fInCert, 0, SEEK_END) == 0;
if(continue_reading)
if(continue_reading) {
cert_tell = ftell(fInCert);
if(cert_tell < 0)
continue_reading = FALSE;
else
certsize = (size_t)cert_tell;
if(cert_tell < 0)
continue_reading = FALSE;
else
certsize = (size_t)cert_tell;
}
if(continue_reading)
continue_reading = fseek(fInCert, 0, SEEK_SET) == 0;
if(continue_reading && (certsize < CURL_MAX_INPUT_LENGTH))
@ -2736,7 +2737,7 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
share = Curl_hash_pick(&multi->proto_hash,
CURL_UNCONST(MPROTO_SCHANNEL_CERT_SHARE_KEY),
sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY) - 1);
CURL_CSTRLEN(MPROTO_SCHANNEL_CERT_SHARE_KEY));
if(!share || !share->cert_store) {
return NULL;
}
@ -2785,7 +2786,7 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
static void schannel_cert_share_free(void *key, size_t key_len, void *p)
{
struct schannel_cert_share *share = p;
DEBUGASSERT(key_len == (sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY) - 1));
DEBUGASSERT(key_len == CURL_CSTRLEN(MPROTO_SCHANNEL_CERT_SHARE_KEY));
DEBUGASSERT(!memcmp(MPROTO_SCHANNEL_CERT_SHARE_KEY, key, key_len));
(void)key;
(void)key_len;
@ -2828,7 +2829,7 @@ bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
share = Curl_hash_pick(&multi->proto_hash,
CURL_UNCONST(MPROTO_SCHANNEL_CERT_SHARE_KEY),
sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY) - 1);
CURL_CSTRLEN(MPROTO_SCHANNEL_CERT_SHARE_KEY));
if(!share) {
share = curlx_calloc(1, sizeof(*share));
if(!share) {
@ -2837,7 +2838,7 @@ bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
}
if(!Curl_hash_add2(&multi->proto_hash,
CURL_UNCONST(MPROTO_SCHANNEL_CERT_SHARE_KEY),
sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY) - 1,
CURL_CSTRLEN(MPROTO_SCHANNEL_CERT_SHARE_KEY),
share, schannel_cert_share_free)) {
curlx_free(share);
curlx_free(CAfile);

View file

@ -119,8 +119,8 @@ static CURLcode add_certs_data_to_store(HCERTSTORE trust_store,
const char *ca_file_text,
struct Curl_easy *data)
{
const size_t begin_cert_len = strlen(BEGIN_CERT);
const size_t end_cert_len = strlen(END_CERT);
const size_t begin_cert_len = CURL_CSTRLEN(BEGIN_CERT);
const size_t end_cert_len = CURL_CSTRLEN(END_CERT);
CURLcode result = CURLE_OK;
int num_certs = 0;
bool more_certs = 1;

View file

@ -483,8 +483,8 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
pinned_hash = pinnedpubkey;
while(pinned_hash &&
!strncmp(pinned_hash, "sha256//", (sizeof("sha256//") - 1))) {
pinned_hash = pinned_hash + (sizeof("sha256//") - 1);
!strncmp(pinned_hash, "sha256//", CURL_CSTRLEN("sha256//"))) {
pinned_hash = pinned_hash + CURL_CSTRLEN("sha256//");
end_pos = strchr(pinned_hash, ';');
pinned_hash_len = end_pos ?
(size_t)(end_pos - pinned_hash) : strlen(pinned_hash);

View file

@ -686,7 +686,7 @@ struct wssl_x509_share {
static void wssl_x509_share_free(void *key, size_t key_len, void *p)
{
struct wssl_x509_share *share = p;
DEBUGASSERT(key_len == (sizeof(MPROTO_WSSL_X509_KEY) - 1));
DEBUGASSERT(key_len == CURL_CSTRLEN(MPROTO_WSSL_X509_KEY));
DEBUGASSERT(!memcmp(MPROTO_WSSL_X509_KEY, key, key_len));
(void)key;
(void)key_len;
@ -730,7 +730,7 @@ static WOLFSSL_X509_STORE *wssl_get_cached_x509_store(struct Curl_cfilter *cf,
DEBUGASSERT(multi);
share = multi ? Curl_hash_pick(&multi->proto_hash,
CURL_UNCONST(MPROTO_WSSL_X509_KEY),
sizeof(MPROTO_WSSL_X509_KEY) - 1) : NULL;
CURL_CSTRLEN(MPROTO_WSSL_X509_KEY)) : NULL;
if(share && share->store &&
!wssl_cached_x509_store_expired(data, share) &&
!wssl_cached_x509_store_different(cf, share)) {
@ -753,7 +753,7 @@ static void wssl_set_cached_x509_store(struct Curl_cfilter *cf,
return;
share = Curl_hash_pick(&multi->proto_hash,
CURL_UNCONST(MPROTO_WSSL_X509_KEY),
sizeof(MPROTO_WSSL_X509_KEY) - 1);
CURL_CSTRLEN(MPROTO_WSSL_X509_KEY));
if(!share) {
share = curlx_calloc(1, sizeof(*share));
@ -761,7 +761,7 @@ static void wssl_set_cached_x509_store(struct Curl_cfilter *cf,
return;
if(!Curl_hash_add2(&multi->proto_hash,
CURL_UNCONST(MPROTO_WSSL_X509_KEY),
sizeof(MPROTO_WSSL_X509_KEY) - 1,
CURL_CSTRLEN(MPROTO_WSSL_X509_KEY),
share, wssl_x509_share_free)) {
curlx_free(share);
return;

View file

@ -2340,6 +2340,8 @@
d c 30
d CURLUE_TOO_LARGE...
d c 31
d CURLUE_BACKSLASH...
d c 32
*
d CURLUPart s 10i 0 based(######ptr######) Enum
d CURLUPART_URL c 0

View file

@ -29,9 +29,11 @@
set -eu
ruff check --extend-select=B007,B016,C405,C416,COM818,D200,D213,D204,D401,\
ruff check --target-version=py38 \
--extend-select=B007,B016,C405,C416,COM818,D200,D213,D204,D401,\
D415,FURB129,N818,PERF401,PERF403,PIE790,PIE808,PLW0127,Q004,RUF010,SIM101,\
SIM117,SIM118,TRY400,TRY401,RET503,RET504,UP004,B018,B904,RSE102,RET505,I001 \
--ignore=FA100 \
"$@"
# Checks that are in preview only, since --preview otherwise turns them all on
ruff check --preview --select=E301,E302,E303,E304,E305,E306,E502 "$@"
ruff check --target-version=py38 --preview --select=E301,E302,E303,E304,E305,E306,E502 "$@"

View file

@ -29,7 +29,7 @@
* function in url.c.
*/
static const char *scheme[] = {
static const char * const scheme[] = {
"dict",
"file",
"ftp",

View file

@ -43,7 +43,7 @@
#include <openssl/opensslconf.h> /* for OPENSSL_NO_OCSP */
#endif
static const char *disabled[] = {
static const char * const disabled[] = {
"bindlocal: "
#ifdef CURL_DISABLE_BINDLOCAL
"OFF"

View file

@ -145,13 +145,13 @@ static SANITIZEcode msdosify(char ** const sanitized, const char *file_name,
static const char illegal_chars_dos[] =
".+, ;=[]" /* illegal in DOS */
"|<>/\\\":?*"; /* illegal in DOS & W95 */
static const char *illegal_chars_w95 = &illegal_chars_dos[8];
static const char * const illegal_chars_w95 = &illegal_chars_dos[8];
int idx, dot_idx;
const char *s = file_name;
char *d = dos_name;
const char * const dlimit = dos_name + sizeof(dos_name) - 1;
const char * const dlimit = dos_name + CURL_CSTRLEN(dos_name);
const char *illegal_aliens = illegal_chars_dos;
size_t len = sizeof(illegal_chars_dos) - 1;
size_t len = CURL_CSTRLEN(illegal_chars_dos);
if(!sanitized)
return SANITIZE_ERR_BAD_ARGUMENT;

View file

@ -64,7 +64,7 @@ static const char * const srchard[] = {
"",
NULL
};
static const char *const srcend[] = {
static const char * const srcend[] = {
"",
" return (int)result;",
"}",

View file

@ -509,7 +509,7 @@ static void param_type(char **ptr, char **ptype, char **endct, char *sep)
{
char *p = *ptr;
size_t tlen;
for(p += sizeof("type=") - 1; ISBLANK(*p); p++)
for(p += CURL_CSTRLEN("type="); ISBLANK(*p); p++)
;
/* set type pointer */
*ptype = p;
@ -533,7 +533,7 @@ static void param_filename(char **ptr, char **endct, char **pfilename,
**endct = '\0';
*endct = NULL;
}
for(p += sizeof("filename=") - 1; ISBLANK(*p); p++)
for(p += CURL_CSTRLEN("filename="); ISBLANK(*p); p++)
;
tp = p;
*pfilename = get_param_word(&p, &endpos, endchar);
@ -557,7 +557,7 @@ static int param_headers(char **ptr, char **endct,
**endct = '\0';
*endct = NULL;
}
p += sizeof("headers=") - 1;
p += CURL_CSTRLEN("headers=");
if(*p == '@' || *p == '<') {
char *hdrfile;
FILE *fp;
@ -623,7 +623,7 @@ static void param_encoder(char **ptr, char **endct, char **pencoder,
**endct = '\0';
*endct = NULL;
}
for(p += sizeof("encoder=") - 1; ISBLANK(*p); p++)
for(p += CURL_CSTRLEN("encoder="); ISBLANK(*p); p++)
;
tp = p;
*pencoder = get_param_word(&p, &endpos, endchar);

View file

@ -2488,7 +2488,7 @@ static ParameterError opt_string(struct OperationConfig *config,
{
ParameterError err = PARAM_OK;
curl_off_t value;
static const char *redir_protos[] = {
static const char * const redir_protos[] = {
"http",
"https",
"ftp",

View file

@ -77,7 +77,7 @@ const char *param2text(ParameterError error)
int SetHTTPrequest(HttpReq req, HttpReq *store)
{
/* this mirrors the HttpReq enum in tool_sdecls.h */
const char *reqname[] = {
static const char * const reqname[] = {
"", /* unspec */
"GET (-G, --get)",
"HEAD (-I, --head)",
@ -101,7 +101,7 @@ int SetHTTPrequest(HttpReq req, HttpReq *store)
void customrequest_helper(HttpReq req, const char *method)
{
/* this mirrors the HttpReq enum in tool_sdecls.h */
const char *dflt[] = {
static const char * const dflt[] = {
"GET",
"GET",
"HEAD",

View file

@ -27,7 +27,7 @@
/* global variable definitions, for libcurl runtime info */
static const char *no_protos = NULL;
static const char * const no_protos = NULL;
curl_version_info_data *curlinfo = NULL;
const char * const *built_in_protos = &no_protos;

View file

@ -297,7 +297,7 @@ ParameterError secs2ms(long *val, const char *str)
{
curl_off_t secs;
long ms = 0;
const unsigned int digs[] = {
static const unsigned int digs[] = {
1,
10,
100,

View file

@ -62,15 +62,15 @@ static const struct tool_var *varcontent(const char *name, size_t nlen)
(!strncmp(ptr, name, len) && ENDOFFUNC((ptr)[len]))
#define FUNC_TRIM "trim"
#define FUNC_TRIM_LEN (sizeof(FUNC_TRIM) - 1)
#define FUNC_TRIM_LEN CURL_CSTRLEN(FUNC_TRIM)
#define FUNC_JSON "json"
#define FUNC_JSON_LEN (sizeof(FUNC_JSON) - 1)
#define FUNC_JSON_LEN CURL_CSTRLEN(FUNC_JSON)
#define FUNC_URL "url"
#define FUNC_URL_LEN (sizeof(FUNC_URL) - 1)
#define FUNC_URL_LEN CURL_CSTRLEN(FUNC_URL)
#define FUNC_B64 "b64"
#define FUNC_B64_LEN (sizeof(FUNC_B64) - 1)
#define FUNC_B64_LEN CURL_CSTRLEN(FUNC_B64)
#define FUNC_64DEC "64dec" /* base64 decode */
#define FUNC_64DEC_LEN (sizeof(FUNC_64DEC) - 1)
#define FUNC_64DEC_LEN CURL_CSTRLEN(FUNC_64DEC)
static ParameterError varfunc(char *c, /* content */
size_t clen, /* content length */

View file

@ -252,7 +252,7 @@ test2056 test2057 test2058 test2059 test2060 test2061 test2062 test2063 \
test2064 test2065 test2066 test2067 test2068 test2069 test2070 test2071 \
test2072 test2073 test2074 test2075 test2076 test2077 test2078 test2079 \
test2080 test2081 test2082 test2083 test2084 test2085 test2086 test2087 \
test2088 test2089 test2090 test2091 test2092 test2093 \
test2088 test2089 test2090 test2091 test2092 test2093 test2094 \
test2100 test2101 test2102 test2103 test2104 test2105 test2106 test2107 \
test2108 test2109 test2110 test2113 test2114 test2115 test2116 test2117 \
\

View file

@ -163,20 +163,20 @@ u6: URL decode error, most likely because of rubbish in the input
u7: A memory function failed
u8: Credentials was passed in the URL when prohibited
u9: An unknown part ID was passed to a URL API function
u10: No scheme part in the URL
u11: No user part in the URL
u12: No password part in the URL
u13: No options part in the URL
u14: No host part in the URL
u15: No port part in the URL
u16: No query part in the URL
u17: No fragment part in the URL
u18: No zoneid part in the URL
u10: No scheme present
u11: No user present
u12: No password present
u13: No options present
u14: No host present
u15: No port number present
u16: No query present
u17: No fragment present
u18: No zoneid present
u19: Bad file:// URL
u20: Bad fragment
u21: Bad hostname
u22: Bad IPv6 address
u23: Bad login part
u23: Bad login
u24: Bad password
u25: Bad path
u26: Bad query
@ -185,7 +185,8 @@ u28: Unsupported number of slashes following scheme
u29: Bad user
u30: libcurl lacks IDN support
u31: A value or data field is larger than allowed
u32: CURLUcode unknown
u32: Found a backslash where a forward slash was expected
u33: CURLUcode unknown
</stdout>
</verify>

View file

@ -5,45 +5,17 @@
HTTP
HTTP GET
HTTP Negotiate auth (stub ntlm)
SPNEGO NTLM disallowed
</keywords>
</info>
# Server-side
<reply>
<!-- First request, expect 401 (ntlm challenge) -->
<data1>
HTTP/1.1 401 Authorization Required
Server: Microsoft-IIS/7.0
Content-Type: text/html; charset=iso-8859-1
WWW-Authenticate: Negotiate Qw==
Content-Length: 19
<data nocheck="yes" crlf="headers">
HTTP/1.1 200 OK swsclose
Content-Length: 23
Still not yet sir!
</data1>
<!-- Second request, expect success -->
<data2>
HTTP/1.1 200 Things are fine in server land
Server: Microsoft-IIS/7.0
Content-Type: text/html; charset=iso-8859-1
WWW-Authenticate: Negotiate RA==
Content-Length: 15
Nice auth sir!
</data2>
<datacheck>
HTTP/1.1 401 Authorization Required
Server: Microsoft-IIS/7.0
Content-Type: text/html; charset=iso-8859-1
WWW-Authenticate: Negotiate Qw==
Content-Length: 19
HTTP/1.1 200 Things are fine in server land
Server: Microsoft-IIS/7.0
Content-Type: text/html; charset=iso-8859-1
WWW-Authenticate: Negotiate RA==
Content-Length: 15
Nice auth sir!
</datacheck>
This IS the real page!
</data>
</reply>
# Client-side
@ -52,7 +24,7 @@ Nice auth sir!
http
</server>
<name>
HTTP Negotiate authentication (stub NTLM)
HTTP Negotiate authentication blocked for stub NTLM credentials
</name>
<features>
GSS-API
@ -68,16 +40,15 @@ CURL_STUB_GSS_CREDS="NTLM_Alice"
# Verify data after the test has been "shot"
<verify>
<errorcode>
0
</errorcode>
# NTLM is blocked within SPNEGO, so when only NTLM credentials are
# available, negotiate auth silently fails and the request is sent
# without any Authorization header.
<protocol crlf="headers">
GET /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Authorization: Negotiate %b64["NTLM_Alice":HTTP@127.0.0.1:2:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA]b64%
User-Agent: curl/%VERSION
Accept: */*
GET /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Authorization: Negotiate %b64["NTLM_Alice":HTTP@127.0.0.1:3:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA]b64%
User-Agent: curl/%VERSION
Accept: */*

68
tests/data/test2094 Normal file
View file

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="US-ASCII"?>
<testcase>
<info>
<keywords>
HTTP
HTTP GET
HTTP Negotiate auth (stub krb5)
SPNEGO NTLM disallowed
</keywords>
</info>
# Server-side
<reply>
<data1>
HTTP/1.1 200 Things are fine in server land
Server: Microsoft-IIS/7.0
Content-Type: text/html; charset=iso-8859-1
WWW-Authenticate: Negotiate RA==
Content-Length: 15
Nice auth sir!
</data1>
<datacheck>
HTTP/1.1 200 Things are fine in server land
Server: Microsoft-IIS/7.0
Content-Type: text/html; charset=iso-8859-1
WWW-Authenticate: Negotiate RA==
Content-Length: 15
Nice auth sir!
</datacheck>
</reply>
# Client-side
<client>
<server>
http
</server>
<name>
SPNEGO with Kerberos still works when NTLM is blocked
</name>
<features>
GSS-API
Debug
</features>
<setenv>
CURL_STUB_GSS_CREDS="KRB5_Alice"
</setenv>
<command>
--negotiate http://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<errorcode>
0
</errorcode>
<protocol crlf="headers">
GET /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Authorization: Negotiate %b64["KRB5_Alice":HTTP@127.0.0.1:1:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA]b64%
User-Agent: curl/%VERSION
Accept: */*
</protocol>
</verify>
</testcase>

View file

@ -4,7 +4,6 @@
<keywords>
multi
HTTP
flaky
</keywords>
</info>

View file

@ -5,7 +5,6 @@
multi
HTTP
HTTP/2
flaky
</keywords>
</info>

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
@ -26,8 +25,6 @@
#
"""DICT server."""
from __future__ import absolute_import, division, print_function, unicode_literals
import argparse
import logging
import os
@ -97,12 +94,12 @@ class DictHandler(socketserver.BaseRequestHandler):
response_data = "No matches"
# Send back a failure to find.
response = "552 {0}\n".format(response_data)
response = f"552 {response_data}\n"
log.debug("[DICT] Responding with %r", response)
self.request.sendall(response.encode("utf-8"))
except IOError:
log.exception("[DICT] IOError hit during request")
except OSError:
log.exception("[DICT] OSError hit during request")
def get_options():

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
@ -45,12 +44,12 @@ def CombinationRepetitionUtil(chosen, arr, badarr, index,
if chosen[j] in badarr:
res = 0
j = j - 1
print("cli_test $turl 1", res, end = " ")
print("cli_test $turl 1", res, end=" ")
# print combination but eliminating any runs of
# two identical params
for j in range(r):
if j != 0 and chosen[j] != chosen[j-1]:
print(chosen[j], end = " ")
print(chosen[j], end=" ")
print()
return
@ -89,8 +88,8 @@ def CombinationRepetition(arr, badarr, n, r):
# Driver code
badarr = [ '--ech grease', '--ech false', '--ech ecl:$badecl', '--ech pn:$badpn' ]
goodarr = [ '--ech hard', '--ech true', '--ech ecl:$goodecl', '--ech pn:$goodpn' ]
badarr = ['--ech grease', '--ech false', '--ech ecl:$badecl', '--ech pn:$badpn']
goodarr = ['--ech hard', '--ech true', '--ech ecl:$goodecl', '--ech pn:$goodpn']
arr = badarr + goodarr
r = 8
n = len(arr) - 1

31
tests/http/scorecard.py Normal file → Executable file
View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
@ -148,7 +147,7 @@ class Card:
def parse_size(cls, s):
m = re.match(r'(\d+)(mb|kb|gb)?', s, re.IGNORECASE)
if m is None:
raise Exception(f'unrecognized size: {s}')
raise ScoreCardError(f'unrecognized size: {s}')
size = int(m.group(1))
if not m.group(2):
pass
@ -211,7 +210,7 @@ class Card:
print(f' {col:>{colw[idx]}} {"[cpu/rss]":<{statw}}', end='')
else:
print(f' {col:>{colw[idx]}}', end='')
print('')
print()
for row in rows:
for idx, cell in enumerate(row):
print(f' {cell["sval"]:>{colw[idx]}}', end='')
@ -224,7 +223,7 @@ class Card:
print(f' {s:<{statw}}', end='')
if 'errors' in cell:
errors.extend(cell['errors'])
print('')
print()
if len(errors):
print(f'Errors: {errors}')
@ -263,7 +262,7 @@ class ScoreRunner:
if self._limit_rate:
m = re.match(r'(\d+(\.\d+)?)([gmkb])?', self._limit_rate.lower())
if not m:
raise Exception(f'unrecognised limit-rate: {self._limit_rate}')
raise ScoreCardError(f'unrecognised limit-rate: {self._limit_rate}')
self._limit_rate_num = float(m.group(1))
if m.group(3) == 'g':
self._limit_rate_num *= 1024 * 1024 * 1024
@ -274,7 +273,7 @@ class ScoreRunner:
elif m.group(3) == 'b':
pass
else:
raise Exception(f'unrecognised limit-rate: {self._limit_rate}')
raise ScoreCardError(f'unrecognised limit-rate: {self._limit_rate}')
self.suppress_cl = suppress_cl
def info(self, msg):
@ -647,13 +646,15 @@ class ScoreRunner:
rows = []
mparallel = meta['request_parallels']
cols.extend([f'{mp} max' for mp in mparallel])
row = [{
'val': fsize,
'sval': Card.fmt_size(fsize)
},{
'val': count,
'sval': f'{count}',
}]
row = [
{
'val': fsize,
'sval': Card.fmt_size(fsize)
}, {
'val': count,
'sval': f'{count}',
}
]
self.info('requests, max parallel...')
row.extend([self.do_requests(url=url, count=count,
max_parallel=mp, nsamples=meta["samples"])
@ -794,7 +795,7 @@ def run_score(args, protocol):
socks_args = None
if args.socks4 and args.socks5:
raise ScoreCardError('unable to run --socks4 and --socks5 together')
elif args.socks4 or args.socks5:
if args.socks4 or args.socks5:
sockd = Dante(env=env)
if sockd:
assert sockd.initial_start()
@ -992,7 +993,7 @@ def main():
parser.add_argument("--remote", action='store', type=str,
default=None, help="score against the remote server at <ip>:<port>")
parser.add_argument("--flame", action='store_true',
default = False, help="produce a flame graph on curl")
default=False, help="produce a flame graph on curl")
parser.add_argument("--limit-rate", action='store', type=str,
default=None, help="use curl's --limit-rate")
parser.add_argument("--http-plain", action='store_true',

Some files were not shown because too many files have changed in this diff Show more