Available HTTP authentication methods. See CURLINFO_HTTPAUTH_AVAIL(3)
+## CURLINFO_HTTPAUTH_USED
+
+Used HTTP authentication method. See CURLINFO_HTTPAUTH_USED(3)
+
## CURLINFO_HTTP_CONNECTCODE
Last proxy CONNECT response code. See CURLINFO_HTTP_CONNECTCODE(3)
Available HTTP proxy authentication methods. See CURLINFO_PROXYAUTH_AVAIL(3)
+## CURLINFO_PROXYAUTH_USED
+
+Used HTTP proxy authentication methods. See CURLINFO_PROXYAUTH_USED(3)
+
## CURLINFO_PROXY_ERROR
Detailed proxy error. See CURLINFO_PROXY_ERROR(3)
--- /dev/null
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_HTTPAUTH_USED
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_PROXYAUTH_USED (3)
+ - CURLINFO_HTTPAUTH_AVAIL (3)
+ - CURLOPT_HTTPAUTH (3)
+Protocol:
+ - HTTP
+Added-in: 8.12.0
+---
+
+# NAME
+
+CURLINFO_HTTPAUTH_USED - get used HTTP authentication method
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTPAUTH_USED, long *authp);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive a bitmask indicating the authentication
+method that was used in the previous HTTP request. The meaning of the possible
+bits is explained in the CURLOPT_HTTPAUTH(3) option for curl_easy_setopt(3).
+
+The returned value has zero or one bit set.
+
+# %PROTOCOLS%
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC | CURLAUTH_DIGEST);
+ curl_easy_setopt(curl, CURLOPT_USERNAME, "shrek");
+ curl_easy_setopt(curl, CURLOPT_PASSWORD, "swamp");
+
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ long auth;
+ res = curl_easy_getinfo(curl, CURLINFO_HTTPAUTH_USED, &auth);
+ if(!res) {
+ if(!auth)
+ printf("No auth used\n");
+ else {
+ if(auth == CURLAUTH_DIGEST)
+ printf("Used Digest authentication\n");
+ else
+ printf("Used Basic authentication\n");
+ }
+ }
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# %AVAILABILITY%
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
--- /dev/null
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_PROXYAUTH_USED
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_HTTPAUTH_USED (3)
+ - CURLINFO_PROXYAUTH_AVAIL (3)
+ - CURLOPT_HTTPAUTH (3)
+Protocol:
+ - HTTP
+Added-in: 8.12.0
+---
+
+# NAME
+
+CURLINFO_PROXYAUTH_USED - get used HTTP proxy authentication method
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXYAUTH_USED, long *authp);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive a bitmask indicating the authentication
+method that was used in the previous request done over an HTTP proxy. The
+meaning of the possible bits is explained in the CURLOPT_HTTPAUTH(3) option
+for curl_easy_setopt(3).
+
+The returned value has zero or one bit set.
+
+# %PROTOCOLS%
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.example.com");
+ curl_easy_setopt(curl, CURLOPT_PROXYAUTH,
+ CURLAUTH_BASIC | CURLAUTH_DIGEST);
+ curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME, "shrek");
+ curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD, "swamp");
+
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ long auth;
+ res = curl_easy_getinfo(curl, CURLINFO_PROXYAUTH_USED, &auth);
+ if(!res) {
+ if(!auth)
+ printf("No auth used\n");
+ else {
+ if(auth == CURLAUTH_DIGEST)
+ printf("Used Digest proxy authentication\n");
+ else
+ printf("Used Basic proxy authentication\n");
+ }
+ }
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# %AVAILABILITY%
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
CURLINFO_HTTP_CONNECTCODE.3 \
CURLINFO_HTTP_VERSION.3 \
CURLINFO_HTTPAUTH_AVAIL.3 \
+ CURLINFO_HTTPAUTH_USED.3 \
CURLINFO_LASTSOCKET.3 \
CURLINFO_LOCAL_IP.3 \
CURLINFO_LOCAL_PORT.3 \
CURLINFO_PROXY_ERROR.3 \
CURLINFO_PROXY_SSL_VERIFYRESULT.3 \
CURLINFO_PROXYAUTH_AVAIL.3 \
+ CURLINFO_PROXYAUTH_USED.3 \
CURLINFO_QUEUE_TIME_T.3 \
CURLINFO_REDIRECT_COUNT.3 \
CURLINFO_REDIRECT_TIME.3 \
CURLINFO_HTTP_CONNECTCODE 7.10.7
CURLINFO_HTTP_VERSION 7.50.0
CURLINFO_HTTPAUTH_AVAIL 7.10.8
+CURLINFO_HTTPAUTH_USED 8.12.0
CURLINFO_LASTONE 7.4.1
CURLINFO_LASTSOCKET 7.15.2 7.45.0
CURLINFO_LOCAL_IP 7.21.0
CURLINFO_PROXY_ERROR 7.73.0
CURLINFO_PROXY_SSL_VERIFYRESULT 7.52.0
CURLINFO_PROXYAUTH_AVAIL 7.10.8
+CURLINFO_PROXYAUTH_USED 8.12.0
CURLINFO_PTR 7.54.1
CURLINFO_QUEUE_TIME_T 8.6.0
CURLINFO_REDIRECT_COUNT 7.9.7
CURLINFO_USED_PROXY = CURLINFO_LONG + 66,
CURLINFO_POSTTRANSFER_TIME_T = CURLINFO_OFF_T + 67,
CURLINFO_EARLYDATA_SENT_T = CURLINFO_OFF_T + 68,
- CURLINFO_LASTONE = 68
+ CURLINFO_HTTPAUTH_USED = CURLINFO_LONG + 69,
+ CURLINFO_PROXYAUTH_USED = CURLINFO_LONG + 70,
+ CURLINFO_LASTONE = 70
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
info->request_size = 0;
info->proxyauthavail = 0;
info->httpauthavail = 0;
+ info->proxyauthpicked = 0;
+ info->httpauthpicked = 0;
info->numconnects = 0;
free(info->contenttype);
lptr.to_long = param_longp;
*lptr.to_ulong = data->info.proxyauthavail;
break;
+ case CURLINFO_HTTPAUTH_USED:
+ lptr.to_long = param_longp;
+ *lptr.to_ulong = data->info.httpauthpicked;
+ break;
+ case CURLINFO_PROXYAUTH_USED:
+ lptr.to_long = param_longp;
+ *lptr.to_ulong = data->info.proxyauthpicked;
+ break;
case CURLINFO_OS_ERRNO:
*param_longp = data->state.os_errno;
break;
pickhost = pickoneauth(&data->state.authhost, authmask);
if(!pickhost)
data->state.authproblem = TRUE;
+ else
+ data->info.httpauthpicked = data->state.authhost.picked;
if(data->state.authhost.picked == CURLAUTH_NTLM &&
conn->httpversion > 11) {
infof(data, "Forcing HTTP/1.1 for NTLM");
authmask & ~CURLAUTH_BEARER);
if(!pickproxy)
data->state.authproblem = TRUE;
+ else
+ data->info.proxyauthpicked = data->state.authproxy.picked;
+
}
#endif
struct connectdata *conn = data->conn;
#ifdef USE_SPNEGO
curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
- &conn->http_negotiate_state;
+ &conn->http_negotiate_state;
#endif
-#if defined(USE_SPNEGO) || \
- defined(USE_NTLM) || \
- !defined(CURL_DISABLE_DIGEST_AUTH) || \
- !defined(CURL_DISABLE_BASIC_AUTH) || \
+#if defined(USE_SPNEGO) || \
+ defined(USE_NTLM) || \
+ !defined(CURL_DISABLE_DIGEST_AUTH) || \
+ !defined(CURL_DISABLE_BASIC_AUTH) || \
!defined(CURL_DISABLE_BEARER_AUTH)
unsigned long *availp;
authp->avail |= CURLAUTH_BEARER;
if(authp->picked == CURLAUTH_BEARER) {
/* We asked for Bearer authentication but got a 40X back
- anyway, which basically means our token is not valid. */
+ anyway, which basically means our token is not valid. */
authp->avail = CURLAUTH_NONE;
infof(data, "Authentication problem. Ignoring this.");
data->state.authproblem = TRUE;
break;
case NTLMSTATE_LAST:
+ /* since this is a little artificial in that this is used without any
+ outgoing auth headers being set, we need to set the bit by force */
+ if(proxy)
+ data->info.proxyauthpicked = CURLAUTH_NTLM;
+ else
+ data->info.httpauthpicked = CURLAUTH_NTLM;
Curl_safefree(*allocuserpwd);
authp->done = TRUE;
break;
curl_off_t request_size; /* the amount of bytes sent in the request(s) */
unsigned long proxyauthavail; /* what proxy auth types were announced */
unsigned long httpauthavail; /* what host auth types were announced */
+ unsigned long proxyauthpicked; /* selected proxy auth type */
+ unsigned long httpauthpicked; /* selected host auth type */
long numconnects; /* how many new connection did libcurl created */
char *contenttype; /* the content type of the object */
char *wouldredirect; /* URL this would have been redirected to if asked to */
test662 test663 test664 test665 test666 test667 test668 test669 test670 \
test671 test672 test673 test674 test675 test676 test677 test678 test679 \
test680 test681 test682 test683 test684 test685 test686 test687 test688 \
-test689 test690 test691 test692 test693 \
+test689 test690 test691 test692 test693 test694 \
\
test700 test701 test702 test703 test704 test705 test706 test707 test708 \
test709 test710 test711 test712 test713 test714 test715 test716 test717 \
--- /dev/null
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+POST callback
+HTTP proxy
+HTTP proxy NTLM auth
+NTLM
+</keywords>
+</info>
+# Server-side
+<reply>
+
+<data>
+HTTP/1.1 401 Authorization Required\r
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2\r
+WWW-Authenticate: Negotiate\r
+WWW-Authenticate: NTLM\r
+Content-Type: text/html; charset=iso-8859-1\r
+Content-Length: 26\r
+\r
+This is not the real page
+</data>
+
+# this is returned first since we get no proxy-auth
+<data1001>
+HTTP/1.1 401 Authorization Required\r
+WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAgACADAAAACGggEAc51AYVDgyNcAAAAAAAAAAG4AbgAyAAAAQ0MCAAQAQwBDAAEAEgBFAEwASQBTAEEAQgBFAFQASAAEABgAYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAwAsAGUAbABpAHMAYQBiAGUAdABoAC4AYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAAAAAA==\r
+Content-Length: 34\r
+\r
+Hey you, authenticate or go away!
+</data1001>
+
+# This is supposed to be returned when the server gets the second
+# Authorization: NTLM line passed-in from the client
+<data1002>
+HTTP/1.1 200 Things are fine\r
+Server: Microsoft-IIS/5.0\r
+Content-Type: text/html; charset=iso-8859-1\r
+Content-Length: 42\r
+\r
+Contents of that page you requested, sir.
+</data1002>
+
+# This is supposed to be returned when the server gets the second
+# request.
+<data10>
+HTTP/1.1 200 Things are fine\r
+Content-Type: yeah/maybe\r
+Content-Length: 42\r
+\r
+Contents of that second request. Differn.
+</data10>
+
+<datacheck>
+HTTP/1.1 401 Authorization Required\r
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2\r
+WWW-Authenticate: Negotiate\r
+WWW-Authenticate: NTLM\r
+Content-Type: text/html; charset=iso-8859-1\r
+Content-Length: 26\r
+\r
+HTTP/1.1 401 Authorization Required\r
+WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAgACADAAAACGggEAc51AYVDgyNcAAAAAAAAAAG4AbgAyAAAAQ0MCAAQAQwBDAAEAEgBFAEwASQBTAEEAQgBFAFQASAAEABgAYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAwAsAGUAbABpAHMAYQBiAGUAdABoAC4AYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAAAAAA==\r
+Content-Length: 34\r
+\r
+HTTP/1.1 200 Things are fine\r
+Server: Microsoft-IIS/5.0\r
+Content-Type: text/html; charset=iso-8859-1\r
+Content-Length: 42\r
+\r
+Contents of that page you requested, sir.
+HTTP/1.1 200 Things are fine\r
+Content-Type: yeah/maybe\r
+Content-Length: 42\r
+\r
+Contents of that second request. Differn.
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# tool to use
+<tool>
+lib%TESTNUMBER
+</tool>
+<features>
+NTLM
+!SSPI
+</features>
+<name>
+HTTP with NTLM twice, verify CURLINFO_HTTPAUTH_USED
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/path/mine http://%HOSTIP:%HTTPPORT/path/%TESTNUMBER0010
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+
+<protocol crlf="yes">
+GET /path/mine HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+GET /path/mine HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
+Accept: */*
+
+GET /path/mine HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAAAgACAHAAAAALAAsAcgAAAAAAAAAAAAAAhoIBAAQt1KW5CgG4YdWWcfXyfXBz1ZMCzYp37xYjBiAizmw58O6eQS7yR66eqYGWeSwl9W1lV09SS1NUQVRJT04=
+Accept: */*
+
+GET /path/6940010 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
lib599 \
lib643 lib645 lib650 lib651 lib652 lib653 lib654 lib655 lib658 \
lib659 lib661 lib666 lib667 lib668 \
- lib670 lib671 lib672 lib673 lib674 lib676 lib677 lib678 \
+ lib670 lib671 lib672 lib673 lib674 lib676 lib677 lib678 lib694 \
lib1156 \
lib1301 \
lib1485 \
lib678_SOURCES = lib678.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib678_LDADD = $(TESTUTIL_LIBS)
+lib694_SOURCES = lib694.c $(SUPPORTFILES)
+
lib1301_SOURCES = lib1301.c $(SUPPORTFILES) $(TESTUTIL)
lib1301_LDADD = $(TESTUTIL_LIBS)
{
CURLcode res;
CURL *curl;
+ long usedauth = 0;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
res = curl_easy_perform(curl);
+ res = curl_easy_getinfo(curl, CURLINFO_PROXYAUTH_USED, &usedauth);
+ if(CURLAUTH_NTLM != usedauth) {
+ printf("CURLINFO_PROXYAUTH_USED did not say NTLM\n");
+ }
+
test_cleanup:
curl_easy_cleanup(curl);
--- /dev/null
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "memdebug.h"
+
+CURLcode test(char *URL)
+{
+ CURLcode res;
+ CURL *curl;
+ long usedauth = 0;
+ int count = 0;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ test_setopt(curl, CURLOPT_URL, URL);
+ test_setopt(curl, CURLOPT_HEADER, 1L);
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_HTTPAUTH,
+ (long) (CURLAUTH_BASIC | CURLAUTH_DIGEST | CURLAUTH_NTLM));
+ test_setopt(curl, CURLOPT_USERPWD, "me:password");
+
+ do {
+
+ res = curl_easy_perform(curl);
+
+ res = curl_easy_getinfo(curl, CURLINFO_HTTPAUTH_USED, &usedauth);
+ if(CURLAUTH_NTLM != usedauth) {
+ printf("CURLINFO_HTTPAUTH_USED did not say NTLM\n");
+ }
+
+ /* set a new URL for the second, so that we don't restart NTLM */
+ test_setopt(curl, CURLOPT_URL, libtest_arg2);
+ } while(!res && ++count < 2);
+
+test_cleanup:
+
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return res;
+}