curl: switched back to OpenSSL, updated to latest version
This commit is contained in:
@@ -69,14 +69,14 @@ CURL_HEADERS := \
|
||||
typecheck-gcc.h
|
||||
|
||||
LOCAL_SRC_FILES := $(addprefix lib/,$(CSOURCES))
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/include/curl $(LOCAL_PATH)/lib $(LOCAL_PATH)/../boringssl/include
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/include/curl $(LOCAL_PATH)/lib $(LOCAL_PATH)/../openssl/include
|
||||
LOCAL_CFLAGS += $(common_CFLAGS)
|
||||
|
||||
LOCAL_MODULE:= libcurl
|
||||
|
||||
LOCAL_SHARED_LIBRARIES :=
|
||||
LOCAL_SHARED_LIBRARIES := ssl crypto
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := ssl crypto
|
||||
#LOCAL_STATIC_LIBRARIES := ssl crypto
|
||||
|
||||
LOCAL_LDLIBS := -lz
|
||||
|
||||
|
||||
@@ -4,52 +4,46 @@
|
||||
| (__| |_| | _ <| |___
|
||||
\___|\___/|_| \_\_____|
|
||||
|
||||
Include files for libcurl, external users.
|
||||
README
|
||||
|
||||
They're all placed in the curl subdirectory here for better fit in any kind
|
||||
of environment. You must include files from here using...
|
||||
Curl is a command line tool for transferring data specified with URL
|
||||
syntax. Find out how to use curl by reading the curl.1 man page or the
|
||||
MANUAL document. Find out how to install Curl by reading the INSTALL
|
||||
document.
|
||||
|
||||
#include <curl/curl.h>
|
||||
libcurl is the library curl is using to do its job. It is readily
|
||||
available to be used by your software. Read the libcurl.3 man page to
|
||||
learn how!
|
||||
|
||||
... style and point the compiler's include path to the directory holding the
|
||||
curl subdirectory. It makes it more likely to survive future modifications.
|
||||
You find answers to the most frequent questions we get in the FAQ document.
|
||||
|
||||
NOTE FOR LIBCURL HACKERS
|
||||
Study the COPYING file for distribution terms and similar. If you distribute
|
||||
curl binaries or other binaries that involve libcurl, you might enjoy the
|
||||
LICENSE-MIXING document.
|
||||
|
||||
The following notes apply to libcurl version 7.19.0 and later.
|
||||
CONTACT
|
||||
|
||||
* The distributed curl/curlbuild.h file is only intended to be used on systems
|
||||
which can not run the also distributed configure script.
|
||||
If you have problems, questions, ideas or suggestions, please contact us
|
||||
by posting to a suitable mailing list. See https://curl.haxx.se/mail/
|
||||
|
||||
* The distributed curlbuild.h file is generated as a copy of curlbuild.h.dist
|
||||
when the libcurl source code distribution archive file is originally created.
|
||||
All contributors to the project are listed in the THANKS document.
|
||||
|
||||
* If you check out from git on a non-configure platform, you must run the
|
||||
appropriate buildconf* script to set up curlbuild.h and other local files
|
||||
before being able of compiling the library.
|
||||
WEB SITE
|
||||
|
||||
* On systems capable of running the configure script, the configure process
|
||||
will overwrite the distributed include/curl/curlbuild.h file with one that
|
||||
is suitable and specific to the library being configured and built, which
|
||||
is generated from the include/curl/curlbuild.h.in template file.
|
||||
Visit the curl web site for the latest news and downloads:
|
||||
|
||||
* If you intend to distribute an already compiled libcurl library you _MUST_
|
||||
also distribute along with it the generated curl/curlbuild.h which has been
|
||||
used to compile it. Otherwise the library will be of no use for the users of
|
||||
the library that you have built. It is _your_ responsibility to provide this
|
||||
file. No one at the cURL project can know how you have built the library.
|
||||
https://curl.haxx.se/
|
||||
|
||||
* File curl/curlbuild.h includes platform and configuration dependent info,
|
||||
and must not be modified by anyone. Configure script generates it for you.
|
||||
GIT
|
||||
|
||||
* We cannot assume anything else but very basic compiler features being
|
||||
present. While libcurl requires an ANSI C compiler to build, some of the
|
||||
earlier ANSI compilers clearly can't deal with some preprocessor operators.
|
||||
To download the very latest source off the GIT server do this:
|
||||
|
||||
* Newlines must remain unix-style for older compilers' sake.
|
||||
git clone https://github.com/curl/curl.git
|
||||
|
||||
* Comments must be written in the old-style /* unnested C-fashion */
|
||||
(you'll get a directory named curl created, filled with the source code)
|
||||
|
||||
To figure out how to do good and portable checks for features, operating
|
||||
systems or specific hardwarare, a very good resource is Bjorn Reese's
|
||||
collection at http://predef.sf.net/
|
||||
NOTICE
|
||||
|
||||
Curl contains pieces of source code that is Copyright (c) 1998, 1999
|
||||
Kungliga Tekniska Högskolan. This notice is included here to comply with the
|
||||
distribution terms.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -373,6 +373,7 @@ typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
|
||||
int cmd,
|
||||
void *clientp);
|
||||
|
||||
#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS
|
||||
/*
|
||||
* The following typedef's are signatures of malloc, free, realloc, strdup and
|
||||
* calloc respectively. Function pointers of these types can be passed to the
|
||||
@@ -385,6 +386,9 @@ typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
|
||||
typedef char *(*curl_strdup_callback)(const char *str);
|
||||
typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
|
||||
|
||||
#define CURL_DID_MEMORY_FUNC_TYPEDEFS
|
||||
#endif
|
||||
|
||||
/* the kind of data that is passed to information_callback*/
|
||||
typedef enum {
|
||||
CURLINFO_TEXT = 0,
|
||||
@@ -471,9 +475,9 @@ typedef enum {
|
||||
CURLE_OBSOLETE44, /* 44 - NOT USED */
|
||||
CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */
|
||||
CURLE_OBSOLETE46, /* 46 - NOT USED */
|
||||
CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */
|
||||
CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */
|
||||
CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */
|
||||
CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */
|
||||
CURLE_TELNET_OPTION_SYNTAX, /* 49 - Malformed telnet option */
|
||||
CURLE_OBSOLETE50, /* 50 - NOT USED */
|
||||
CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint
|
||||
wasn't verified fine */
|
||||
@@ -535,6 +539,8 @@ typedef enum {
|
||||
CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not
|
||||
match */
|
||||
CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */
|
||||
CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer
|
||||
*/
|
||||
CURL_LAST /* never use! */
|
||||
} CURLcode;
|
||||
|
||||
@@ -1460,7 +1466,7 @@ typedef enum {
|
||||
CINIT(TFTP_BLKSIZE, LONG, 178),
|
||||
|
||||
/* Socks Service */
|
||||
CINIT(SOCKS5_GSSAPI_SERVICE, STRINGPOINT, 179),
|
||||
CINIT(SOCKS5_GSSAPI_SERVICE, STRINGPOINT, 179), /* DEPRECATED, do not use! */
|
||||
|
||||
/* Socks Service */
|
||||
CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),
|
||||
@@ -1676,6 +1682,13 @@ typedef enum {
|
||||
/* Do not send any tftp option requests to the server */
|
||||
CINIT(TFTP_NO_OPTIONS, LONG, 242),
|
||||
|
||||
/* Linked-list of host:port:connect-to-host:connect-to-port,
|
||||
overrides the URL's host:port (only for the network layer) */
|
||||
CINIT(CONNECT_TO, OBJECTPOINT, 243),
|
||||
|
||||
/* Set TCP Fast Open */
|
||||
CINIT(TCP_FASTOPEN, LONG, 244),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
@@ -1727,6 +1740,8 @@ enum {
|
||||
CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */
|
||||
CURL_HTTP_VERSION_2_0, /* please use HTTP 2 in the request */
|
||||
CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */
|
||||
CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, /* please use HTTP 2 without HTTP/1.1
|
||||
Upgrade */
|
||||
|
||||
CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
|
||||
};
|
||||
@@ -2110,6 +2125,11 @@ typedef enum {
|
||||
CURLSSLBACKEND_MBEDTLS = 11
|
||||
} curl_sslbackend;
|
||||
|
||||
/* aliases for library clones and renames */
|
||||
#define CURLSSLBACKEND_LIBRESSL 1
|
||||
#define CURLSSLBACKEND_BORINGSSL 1
|
||||
#define CURLSSLBACKEND_WOLFSSL 6
|
||||
|
||||
/* Information about the SSL library used and the respective internal SSL
|
||||
handle, which can be used to obtain further information regarding the
|
||||
connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2012, 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 http://curl.haxx.se/docs/copyright.html.
|
||||
* are also available at https://curl.haxx.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
|
||||
@@ -36,7 +36,7 @@
|
||||
*
|
||||
* If you think that something actually needs to be changed, adjusted
|
||||
* or fixed in this file, then, report it on the libcurl development
|
||||
* mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/
|
||||
* mailing list: https://cool.haxx.se/mailman/listinfo/curl-library/
|
||||
*
|
||||
* This header file shall only export symbols which are 'curl' or 'CURL'
|
||||
* prefixed, otherwise public name space would be polluted.
|
||||
@@ -59,52 +59,52 @@
|
||||
/* ================================================================ */
|
||||
|
||||
#ifdef CURL_SIZEOF_LONG
|
||||
# error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
|
||||
#error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
|
||||
# error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
|
||||
#error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_SIZEOF_CURL_SOCKLEN_T
|
||||
# error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
|
||||
#error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_TYPEOF_CURL_OFF_T
|
||||
# error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
#error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_FORMAT_CURL_OFF_T
|
||||
# error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
#error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_FORMAT_CURL_OFF_TU
|
||||
# error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
|
||||
#error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_FORMAT_OFF_T
|
||||
# error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
|
||||
#error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_SIZEOF_CURL_OFF_T
|
||||
# error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
#error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_SUFFIX_CURL_OFF_T
|
||||
# error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
#error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_SUFFIX_CURL_OFF_TU
|
||||
# error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
|
||||
#error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
|
||||
#endif
|
||||
|
||||
@@ -133,14 +133,14 @@
|
||||
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* header file stdint.h must be included by the external interface. */
|
||||
#define CURL_PULL_STDINT_H 1
|
||||
/* #undef CURL_PULL_STDINT_H */
|
||||
#ifdef CURL_PULL_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* header file inttypes.h must be included by the external interface. */
|
||||
#define CURL_PULL_INTTYPES_H 1
|
||||
/* #undef CURL_PULL_INTTYPES_H */
|
||||
#ifdef CURL_PULL_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
@@ -152,6 +152,13 @@
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* header file sys/poll.h must be included by the external interface. */
|
||||
/* #undef CURL_PULL_SYS_POLL_H */
|
||||
#ifdef CURL_PULL_SYS_POLL_H
|
||||
# include <sys/poll.h>
|
||||
#endif
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#ifdef __LP64__
|
||||
#define CURL_SIZEOF_LONG 8
|
||||
@@ -169,27 +176,27 @@
|
||||
typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
|
||||
|
||||
/* Signed integral data type used for curl_off_t. */
|
||||
#define CURL_TYPEOF_CURL_OFF_T int64_t
|
||||
#define CURL_TYPEOF_CURL_OFF_T long
|
||||
|
||||
/* Data type definition of curl_off_t. */
|
||||
typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
|
||||
|
||||
/* curl_off_t formatting string directive without "%" conversion specifier. */
|
||||
#define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
#define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
|
||||
/* unsigned curl_off_t formatting string without "%" conversion specifier. */
|
||||
#define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
#define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
|
||||
/* curl_off_t formatting string directive with "%" conversion specifier. */
|
||||
#define CURL_FORMAT_OFF_T "%lld"
|
||||
#define CURL_FORMAT_OFF_T "%ld"
|
||||
|
||||
/* The size of `curl_off_t', as computed by sizeof. */
|
||||
#define CURL_SIZEOF_CURL_OFF_T 8
|
||||
#define CURL_SIZEOF_CURL_OFF_T CURL_SIZEOF_LONG
|
||||
|
||||
/* curl_off_t constant suffix. */
|
||||
#define CURL_SUFFIX_CURL_OFF_T LL
|
||||
#define CURL_SUFFIX_CURL_OFF_T L
|
||||
|
||||
/* unsigned curl_off_t constant suffix. */
|
||||
#define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
#define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
|
||||
#endif /* __CURL_CURLBUILD_H */
|
||||
|
||||
@@ -30,12 +30,12 @@
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "7.48.0"
|
||||
#define LIBCURL_VERSION "7.49.0"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 48
|
||||
#define LIBCURL_VERSION_MINOR 49
|
||||
#define LIBCURL_VERSION_PATCH 0
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
@@ -57,7 +57,7 @@
|
||||
CURL_VERSION_BITS() macro since curl's own configure script greps for it
|
||||
and needs it to contain the full number.
|
||||
*/
|
||||
#define LIBCURL_VERSION_NUM 0x073000
|
||||
#define LIBCURL_VERSION_NUM 0x073100
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
@@ -68,7 +68,7 @@
|
||||
*
|
||||
* "Mon Feb 12 11:35:33 UTC 2007"
|
||||
*/
|
||||
#define LIBCURL_TIMESTAMP "Wed Mar 23 06:57:50 UTC 2016"
|
||||
#define LIBCURL_TIMESTAMP "Wed May 18 05:59:55 UTC 2016"
|
||||
|
||||
#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z)
|
||||
#define CURL_AT_LEAST_VERSION(x,y,z) \
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -24,8 +24,7 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h> /* needed for FILE */
|
||||
|
||||
#include "curl.h"
|
||||
#include "curl.h" /* for CURL_EXTERN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -44,29 +43,6 @@ CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength,
|
||||
CURL_EXTERN char *curl_maprintf(const char *format, ...);
|
||||
CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
|
||||
|
||||
#ifdef _MPRINTF_REPLACE
|
||||
# undef printf
|
||||
# undef fprintf
|
||||
# undef sprintf
|
||||
# undef vsprintf
|
||||
# undef snprintf
|
||||
# undef vprintf
|
||||
# undef vfprintf
|
||||
# undef vsnprintf
|
||||
# undef aprintf
|
||||
# undef vaprintf
|
||||
# define printf curl_mprintf
|
||||
# define fprintf curl_mfprintf
|
||||
# define sprintf curl_msprintf
|
||||
# define vsprintf curl_mvsprintf
|
||||
# define snprintf curl_msnprintf
|
||||
# define vprintf curl_mvprintf
|
||||
# define vfprintf curl_mvfprintf
|
||||
# define vsnprintf curl_mvsnprintf
|
||||
# define aprintf curl_maprintf
|
||||
# define vaprintf curl_mvaprintf
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
# Copyright (C) 1998 - 2016, 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
|
||||
@@ -20,6 +20,13 @@
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c \
|
||||
vauth/digest.c vauth/digest_sspi.c vauth/krb5_gssapi.c \
|
||||
vauth/krb5_sspi.c vauth/ntlm.c vauth/ntlm_sspi.c vauth/oauth2.c \
|
||||
vauth/spnego_gssapi.c vauth/spnego_sspi.c
|
||||
|
||||
LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h
|
||||
|
||||
LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \
|
||||
vtls/polarssl.c vtls/polarssl_threadlock.c vtls/axtls.c \
|
||||
vtls/cyassl.c vtls/schannel.c vtls/darwinssl.c vtls/gskit.c \
|
||||
@@ -43,12 +50,10 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
||||
curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c \
|
||||
pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c \
|
||||
openldap.c curl_gethostname.c gopher.c idn_win32.c \
|
||||
http_negotiate_sspi.c http_proxy.c non-ascii.c asyn-ares.c \
|
||||
asyn-thread.c curl_gssapi.c curl_ntlm.c curl_ntlm_wb.c \
|
||||
curl_ntlm_core.c curl_ntlm_msgs.c curl_sasl.c curl_multibyte.c \
|
||||
hostcheck.c conncache.c pipeline.c dotdot.c x509asn1.c \
|
||||
http2.c curl_sasl_sspi.c smb.c curl_sasl_gssapi.c curl_endian.c \
|
||||
curl_des.c
|
||||
http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c \
|
||||
http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c \
|
||||
curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c \
|
||||
x509asn1.c http2.c smb.c curl_endian.c curl_des.c
|
||||
|
||||
LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
|
||||
formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \
|
||||
@@ -63,13 +68,13 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
|
||||
slist.h nonblock.h curl_memrchr.h imap.h pop3.h smtp.h pingpong.h \
|
||||
rtsp.h curl_threads.h warnless.h curl_hmac.h curl_rtmp.h \
|
||||
curl_gethostname.h gopher.h http_proxy.h non-ascii.h asyn.h \
|
||||
curl_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h \
|
||||
curl_ntlm_msgs.h curl_sasl.h curl_multibyte.h hostcheck.h \
|
||||
conncache.h curl_setup_once.h multihandle.h setup-vms.h pipeline.h \
|
||||
dotdot.h x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \
|
||||
http_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h \
|
||||
curl_sasl.h curl_multibyte.h hostcheck.h conncache.h \
|
||||
curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h \
|
||||
x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \
|
||||
curl_printf.h
|
||||
|
||||
LIB_RCFILES = libcurl.rc
|
||||
|
||||
CSOURCES = $(LIB_CFILES) $(LIB_VTLS_CFILES)
|
||||
HHEADERS = $(LIB_HFILES) $(LIB_VTLS_HFILES)
|
||||
CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES)
|
||||
HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -35,7 +35,7 @@ extern int errno, h_errno;
|
||||
#include <stabs.h>
|
||||
void __request(const char *msg);
|
||||
#else
|
||||
# define __request( msg ) Printf( msg "\n\a")
|
||||
# define __request(msg) Printf(msg "\n\a")
|
||||
#endif
|
||||
|
||||
void Curl_amiga_cleanup()
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -68,7 +68,6 @@
|
||||
#include "connect.h"
|
||||
#include "select.h"
|
||||
#include "progress.h"
|
||||
#include "curl_printf.h"
|
||||
|
||||
# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
|
||||
(defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__))
|
||||
@@ -83,8 +82,9 @@
|
||||
#define HAVE_CARES_CALLBACK_TIMEOUTS 1
|
||||
#endif
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
struct ResolverResults {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -69,10 +69,9 @@
|
||||
#include "inet_ntop.h"
|
||||
#include "curl_threads.h"
|
||||
#include "connect.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
@@ -23,13 +23,13 @@
|
||||
/* Base64 encoding/decoding */
|
||||
|
||||
#include "curl_setup.h"
|
||||
#include "curl_printf.h"
|
||||
#include "urldata.h" /* for the SessionHandle definition */
|
||||
#include "warnless.h"
|
||||
#include "curl_base64.h"
|
||||
#include "non-ascii.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -246,7 +246,7 @@ static CURLcode base64_encode(const char *table64,
|
||||
table64[obuf[0]],
|
||||
table64[obuf[1]],
|
||||
table64[obuf[2]],
|
||||
table64[obuf[3]] );
|
||||
table64[obuf[3]]);
|
||||
break;
|
||||
}
|
||||
output += 4;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se>
|
||||
* Copyright (C) 2012, 2016, Linus Nielsen Feltzing, <linus@haxx.se>
|
||||
* Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
@@ -32,10 +32,9 @@
|
||||
#include "sendf.h"
|
||||
#include "rawstr.h"
|
||||
#include "conncache.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
static void conn_llist_dtor(void *user, void *element)
|
||||
@@ -132,9 +131,16 @@ void Curl_conncache_destroy(struct conncache *connc)
|
||||
/* returns an allocated key to find a bundle for this connection */
|
||||
static char *hashkey(struct connectdata *conn)
|
||||
{
|
||||
return aprintf("%s:%d",
|
||||
conn->bits.proxy?conn->proxy.name:conn->host.name,
|
||||
conn->localport);
|
||||
const char *hostname;
|
||||
|
||||
if(conn->bits.proxy)
|
||||
hostname = conn->proxy.name;
|
||||
else if(conn->bits.conn_to_host)
|
||||
hostname = conn->conn_to_host.name;
|
||||
else
|
||||
hostname = conn->host.name;
|
||||
|
||||
return aprintf("%s:%d", hostname, conn->port);
|
||||
}
|
||||
|
||||
/* Look up the bundle with all the connections to the same host this
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
#include <inet.h>
|
||||
#endif
|
||||
|
||||
#include "curl_printf.h"
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "if2ip.h"
|
||||
@@ -74,7 +73,8 @@
|
||||
#include "conncache.h"
|
||||
#include "multihandle.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -668,7 +668,7 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
|
||||
/* there's no connection! */
|
||||
return;
|
||||
|
||||
if(!conn->bits.reuse) {
|
||||
if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
|
||||
int error;
|
||||
|
||||
len = sizeof(struct Curl_sockaddr_storage);
|
||||
@@ -764,6 +764,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
rc = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
|
||||
|
||||
if(rc == 0) { /* no connection yet */
|
||||
error = 0;
|
||||
if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
|
||||
infof(data, "After %ldms connect time, move on!\n",
|
||||
conn->timeoutms_per_addr);
|
||||
@@ -776,7 +777,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
trynextip(conn, sockindex, 1);
|
||||
}
|
||||
}
|
||||
else if(rc == CURL_CSELECT_OUT) {
|
||||
else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
|
||||
if(verifyconnect(conn->tempsock[i], &error)) {
|
||||
/* we are connected with TCP, awesome! */
|
||||
|
||||
@@ -841,6 +842,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
if(result) {
|
||||
/* no more addresses to try */
|
||||
|
||||
const char* hostname;
|
||||
|
||||
/* if the first address family runs out of addresses to try before
|
||||
the happy eyeball timeout, go ahead and try the next family now */
|
||||
if(conn->tempaddr[1] == NULL) {
|
||||
@@ -849,9 +852,15 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
return result;
|
||||
}
|
||||
|
||||
if(conn->bits.proxy)
|
||||
hostname = conn->proxy.name;
|
||||
else if(conn->bits.conn_to_host)
|
||||
hostname = conn->conn_to_host.name;
|
||||
else
|
||||
hostname = conn->host.name;
|
||||
|
||||
failf(data, "Failed to connect to %s port %ld: %s",
|
||||
conn->bits.proxy?conn->proxy.name:conn->host.name,
|
||||
conn->port, Curl_strerror(conn, error));
|
||||
hostname, conn->port, Curl_strerror(conn, error));
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -1000,7 +1009,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
|
||||
curl_socket_t *sockp)
|
||||
{
|
||||
struct Curl_sockaddr_ex addr;
|
||||
int rc;
|
||||
int rc = -1;
|
||||
int error = 0;
|
||||
bool isconnected = FALSE;
|
||||
struct SessionHandle *data = conn->data;
|
||||
@@ -1089,7 +1098,26 @@ static CURLcode singleipconnect(struct connectdata *conn,
|
||||
|
||||
/* Connect TCP sockets, bind UDP */
|
||||
if(!isconnected && (conn->socktype == SOCK_STREAM)) {
|
||||
rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
|
||||
if(conn->bits.tcp_fastopen) {
|
||||
#if defined(CONNECT_DATA_IDEMPOTENT) /* OS X */
|
||||
sa_endpoints_t endpoints;
|
||||
endpoints.sae_srcif = 0;
|
||||
endpoints.sae_srcaddr = NULL;
|
||||
endpoints.sae_srcaddrlen = 0;
|
||||
endpoints.sae_dstaddr = &addr.sa_addr;
|
||||
endpoints.sae_dstaddrlen = addr.addrlen;
|
||||
|
||||
rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
|
||||
CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
|
||||
NULL, 0, NULL, NULL);
|
||||
#elif defined(MSG_FASTOPEN) /* Linux */
|
||||
rc = 0; /* Do nothing */
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
|
||||
}
|
||||
|
||||
if(-1 == rc)
|
||||
error = SOCKERRNO;
|
||||
}
|
||||
|
||||
@@ -88,7 +88,6 @@ Example set of cookies:
|
||||
# include <libpsl.h>
|
||||
#endif
|
||||
|
||||
#include "curl_printf.h"
|
||||
#include "urldata.h"
|
||||
#include "cookie.h"
|
||||
#include "strequal.h"
|
||||
@@ -101,7 +100,8 @@ Example set of cookies:
|
||||
#include "curl_memrchr.h"
|
||||
#include "inet_pton.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -50,10 +50,9 @@
|
||||
#include "curl_addrinfo.h"
|
||||
#include "inet_pton.h"
|
||||
#include "warnless.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
/* lib/curl_config.h. Generated from curl_config.h.in by configure. */
|
||||
/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* when building libcurl itself */
|
||||
/* #undef BUILDING_LIBCURL */
|
||||
|
||||
/* Location of default ca bundle */
|
||||
#define CURL_CA_BUNDLE "ca-certificates.crt"
|
||||
|
||||
@@ -52,6 +49,9 @@
|
||||
/* to disable RTSP */
|
||||
#define CURL_DISABLE_RTSP 1
|
||||
|
||||
/* to disable SMB/CIFS */
|
||||
#define CURL_DISABLE_SMB 1
|
||||
|
||||
/* to disable SMTP */
|
||||
#define CURL_DISABLE_SMTP 1
|
||||
|
||||
@@ -61,27 +61,24 @@
|
||||
/* to disable TFTP */
|
||||
#define CURL_DISABLE_TFTP 1
|
||||
|
||||
/* to disable TLS-SRP authentication */
|
||||
#define CURL_DISABLE_TLS_SRP 1
|
||||
|
||||
/* to disable verbose strings */
|
||||
/* #undef CURL_DISABLE_VERBOSE_STRINGS */
|
||||
|
||||
/* to make a symbol visible */
|
||||
/* Definition to make a library symbol externally visible. */
|
||||
#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default")))
|
||||
|
||||
/* to enable hidden symbols */
|
||||
/* #undef CURL_HIDDEN_SYMBOLS */
|
||||
|
||||
/* Use Windows LDAP implementation */
|
||||
/* #undef CURL_LDAP_WIN */
|
||||
|
||||
/* when not building a shared library */
|
||||
/* #undef CURL_STATICLIB */
|
||||
|
||||
/* your Entropy Gathering Daemon socket pathname */
|
||||
/* #undef EGD_SOCKET */
|
||||
|
||||
/* Define if you want to enable IPv6 support */
|
||||
#define ENABLE_IPV6 1
|
||||
|
||||
/* Define to the type of arg 2 for gethostname. */
|
||||
#define GETHOSTNAME_TYPE_ARG2 size_t
|
||||
|
||||
/* Define to the type qualifier of arg 1 for getnameinfo. */
|
||||
#define GETNAMEINFO_QUAL_ARG1 const
|
||||
|
||||
@@ -125,7 +122,7 @@
|
||||
#define HAVE_BOOL_T 1
|
||||
|
||||
/* Define to 1 if using BoringSSL. */
|
||||
#define HAVE_BORINGSSL 1
|
||||
/* #undef HAVE_BORINGSSL */
|
||||
|
||||
/* Define to 1 if you have the clock_gettime function and monotonic timer. */
|
||||
#define HAVE_CLOCK_GETTIME_MONOTONIC 1
|
||||
@@ -145,14 +142,23 @@
|
||||
/* Define to 1 if you have the <crypto.h> header file. */
|
||||
/* #undef HAVE_CRYPTO_H */
|
||||
|
||||
/* Define to 1 if you have the <des.h> header file. */
|
||||
/* #undef HAVE_DES_H */
|
||||
/* Define to 1 if you have the `CyaSSL_CTX_UseSupportedCurve' function. */
|
||||
/* #undef HAVE_CYASSL_CTX_USESUPPORTEDCURVE */
|
||||
|
||||
/* Define to 1 if you have the <cyassl/error-ssl.h> header file. */
|
||||
/* #undef HAVE_CYASSL_ERROR_SSL_H */
|
||||
|
||||
/* Define to 1 if you have the `CyaSSL_get_peer_certificate' function. */
|
||||
/* #undef HAVE_CYASSL_GET_PEER_CERTIFICATE */
|
||||
|
||||
/* Define to 1 if you have the <cyassl/options.h> header file. */
|
||||
/* #undef HAVE_CYASSL_OPTIONS_H */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have the `ENGINE_cleanup' function. */
|
||||
/* #undef HAVE_ENGINE_CLEANUP */
|
||||
#define HAVE_ENGINE_CLEANUP 1
|
||||
|
||||
/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
|
||||
#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1
|
||||
@@ -262,6 +268,9 @@
|
||||
/* Define to 1 if you have the `getpwuid' function. */
|
||||
#define HAVE_GETPWUID 1
|
||||
|
||||
/* Define to 1 if you have the `getpwuid_r' function. */
|
||||
/* #undef HAVE_GETPWUID_R */
|
||||
|
||||
/* Define to 1 if you have the `getrlimit' function. */
|
||||
#define HAVE_GETRLIMIT 1
|
||||
|
||||
@@ -277,7 +286,14 @@
|
||||
/* Define to 1 if you have a working gmtime_r function. */
|
||||
#define HAVE_GMTIME_R 1
|
||||
|
||||
/* if you have the gssapi libraries */
|
||||
/* Define to 1 if you have the `gnutls_certificate_set_x509_key_file2'
|
||||
function. */
|
||||
/* #undef HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2 */
|
||||
|
||||
/* if you have the function gnutls_srp_verifier */
|
||||
/* #undef HAVE_GNUTLS_SRP */
|
||||
|
||||
/* if you have GSS-API libraries */
|
||||
/* #undef HAVE_GSSAPI */
|
||||
|
||||
/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
|
||||
@@ -310,6 +326,9 @@
|
||||
/* Define to 1 if you have the <ifaddrs.h> header file. */
|
||||
/* #undef HAVE_IFADDRS_H */
|
||||
|
||||
/* Define to 1 if you have the `if_nametoindex' function. */
|
||||
/* #undef HAVE_IF_NAMETOINDEX */
|
||||
|
||||
/* Define to 1 if you have the `inet_addr' function. */
|
||||
#define HAVE_INET_ADDR 1
|
||||
|
||||
@@ -365,6 +384,15 @@
|
||||
/* Define to 1 if you have the <krb.h> header file. */
|
||||
/* #undef HAVE_KRB_H */
|
||||
|
||||
/* if you have the Kerberos4 libraries (including -ldes) */
|
||||
/* #undef HAVE_KRB4 */
|
||||
|
||||
/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
|
||||
/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */
|
||||
|
||||
/* Define to 1 if you have the <krb.h> header file. */
|
||||
/* #undef HAVE_KRB_H */
|
||||
|
||||
/* Define to 1 if you have the lber.h header file. */
|
||||
/* #undef HAVE_LBER_H */
|
||||
|
||||
@@ -386,20 +414,14 @@
|
||||
/* Define to 1 if you have the `ldap_url_parse' function. */
|
||||
/* #undef HAVE_LDAP_URL_PARSE */
|
||||
|
||||
/* Define to 1 if you have the `gcrypt' library (-lgcrypt). */
|
||||
/* #undef HAVE_LIBGCRYPT */
|
||||
|
||||
/* Define to 1 if you have the <libgen.h> header file. */
|
||||
#define HAVE_LIBGEN_H 1
|
||||
|
||||
/* Define to 1 if you have the `idn' library (-lidn). */
|
||||
/* #undef HAVE_LIBIDN */
|
||||
|
||||
/* Define to 1 if you have the `resolv' library (-lresolv). */
|
||||
/* #undef HAVE_LIBRESOLV */
|
||||
|
||||
/* Define to 1 if you have the `resolve' library (-lresolve). */
|
||||
/* #undef HAVE_LIBRESOLVE */
|
||||
/* Define to 1 if using libressl. */
|
||||
/* #undef HAVE_LIBRESSL */
|
||||
|
||||
/* Define to 1 if you have the <librtmp/rtmp.h> header file. */
|
||||
/* #undef HAVE_LIBRTMP_RTMP_H */
|
||||
@@ -407,26 +429,11 @@
|
||||
/* Define to 1 if you have the `ssh2' library (-lssh2). */
|
||||
/* #undef HAVE_LIBSSH2 */
|
||||
|
||||
/* Define to 1 if you have the `libssh2_exit' function. */
|
||||
/* #undef HAVE_LIBSSH2_EXIT */
|
||||
|
||||
/* Define to 1 if you have the <libssh2.h> header file. */
|
||||
/* #undef HAVE_LIBSSH2_H */
|
||||
|
||||
/* Define to 1 if you have the `libssh2_init' function. */
|
||||
/* #undef HAVE_LIBSSH2_INIT */
|
||||
|
||||
/* Define to 1 if you have the `libssh2_scp_send64' function. */
|
||||
/* #undef HAVE_LIBSSH2_SCP_SEND64 */
|
||||
|
||||
/* Define to 1 if you have the `libssh2_session_handshake' function. */
|
||||
/* #undef HAVE_LIBSSH2_SESSION_HANDSHAKE */
|
||||
|
||||
/* Define to 1 if you have the `libssh2_version' function. */
|
||||
/* #undef HAVE_LIBSSH2_VERSION */
|
||||
|
||||
/* Define to 1 if you have the `ssl' library (-lssl). */
|
||||
/* #undef HAVE_LIBSSL */
|
||||
#define HAVE_LIBSSL 1
|
||||
|
||||
/* if zlib is available */
|
||||
#define HAVE_LIBZ 1
|
||||
@@ -470,10 +477,13 @@
|
||||
/* Define to 1 if you have the <net/if.h> header file. */
|
||||
#define HAVE_NET_IF_H 1
|
||||
|
||||
/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
|
||||
/* #undef HAVE_NGHTTP2_NGHTTP2_H */
|
||||
|
||||
/* Define to 1 if NI_WITHSCOPEID exists and works. */
|
||||
/* #undef HAVE_NI_WITHSCOPEID */
|
||||
|
||||
/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE
|
||||
/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE
|
||||
*/
|
||||
/* #undef HAVE_OLD_GSSMIT */
|
||||
|
||||
@@ -496,7 +506,7 @@
|
||||
#define HAVE_OPENSSL_RSA_H 1
|
||||
|
||||
/* if you have the function SRP_Calc_client_key */
|
||||
/* #define HAVE_OPENSSL_SRP 1 */
|
||||
#define HAVE_OPENSSL_SRP 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/ssl.h> header file. */
|
||||
#define HAVE_OPENSSL_SSL_H 1
|
||||
@@ -512,9 +522,6 @@
|
||||
/* Define to 1 if you have the `pipe' function. */
|
||||
#define HAVE_PIPE 1
|
||||
|
||||
/* if you have the function PK11_CreateGenericObject */
|
||||
/* #undef HAVE_PK11_CREATEGENERICOBJECT */
|
||||
|
||||
/* Define to 1 if you have a working poll function. */
|
||||
#define HAVE_POLL 1
|
||||
|
||||
@@ -534,20 +541,17 @@
|
||||
#define HAVE_PWD_H 1
|
||||
|
||||
/* Define to 1 if you have the `RAND_egd' function. */
|
||||
/* #undef HAVE_RAND_EGD */
|
||||
#define HAVE_RAND_EGD 1
|
||||
|
||||
/* Define to 1 if you have the `RAND_screen' function. */
|
||||
/* #undef HAVE_RAND_SCREEN */
|
||||
|
||||
/* Define to 1 if you have the `RAND_status' function. */
|
||||
/* #undef HAVE_RAND_STATUS */
|
||||
#define HAVE_RAND_STATUS 1
|
||||
|
||||
/* Define to 1 if you have the recv function. */
|
||||
#define HAVE_RECV 1
|
||||
|
||||
/* Define to 1 if you have the recvfrom function. */
|
||||
#define HAVE_RECVFROM 1
|
||||
|
||||
/* Define to 1 if you have the <rsa.h> header file. */
|
||||
/* #undef HAVE_RSA_H */
|
||||
|
||||
@@ -611,8 +615,8 @@
|
||||
/* Define to 1 if you have the <socket.h> header file. */
|
||||
/* #undef HAVE_SOCKET_H */
|
||||
|
||||
/* Define this if you have the SPNEGO library fbopenssl */
|
||||
/* #undef HAVE_SPNEGO */
|
||||
/* Define to 1 if you have the `SSLv2_client_method' function. */
|
||||
/* #undef HAVE_SSLV2_CLIENT_METHOD */
|
||||
|
||||
/* Define to 1 if you have the `SSL_get_shutdown' function. */
|
||||
#define HAVE_SSL_GET_SHUTDOWN 1
|
||||
@@ -635,12 +639,6 @@
|
||||
/* Define to 1 if you have the strcasecmp function. */
|
||||
#define HAVE_STRCASECMP 1
|
||||
|
||||
/* Define to 1 if you have the strcasestr function. */
|
||||
#define HAVE_STRCASESTR 1
|
||||
|
||||
/* Define to 1 if you have the strcasestr function. */
|
||||
#define HAVE_STRCASESTR 1
|
||||
|
||||
/* Define to 1 if you have the strcmpi function. */
|
||||
/* #undef HAVE_STRCMPI */
|
||||
|
||||
@@ -659,12 +657,6 @@
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the strlcat function. */
|
||||
#define HAVE_STRLCAT 1
|
||||
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
#define HAVE_STRLCPY 1
|
||||
|
||||
/* Define to 1 if you have the strncasecmp function. */
|
||||
#define HAVE_STRNCASECMP 1
|
||||
|
||||
@@ -788,6 +780,18 @@
|
||||
/* Define to 1 if you have the winsock.h header file. */
|
||||
/* #undef HAVE_WINSOCK_H */
|
||||
|
||||
/* Define to 1 if you have the `wolfSSLv3_client_method' function. */
|
||||
/* #undef HAVE_WOLFSSLV3_CLIENT_METHOD */
|
||||
|
||||
/* Define to 1 if you have the `wolfSSL_CTX_UseSupportedCurve' function. */
|
||||
/* #undef HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE */
|
||||
|
||||
/* Define to 1 if you have the `wolfSSL_get_peer_certificate' function. */
|
||||
/* #undef HAVE_WOLFSSL_GET_PEER_CERTIFICATE */
|
||||
|
||||
/* Define to 1 if you have the `wolfSSL_UseALPN' function. */
|
||||
/* #undef HAVE_WOLFSSL_USEALPN */
|
||||
|
||||
/* Define this symbol if your OS supports changing the contents of argv */
|
||||
/* #undef HAVE_WRITABLE_ARGV */
|
||||
|
||||
@@ -803,13 +807,9 @@
|
||||
/* if you have the zlib.h header file */
|
||||
#define HAVE_ZLIB_H 1
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Define to 1 if you are building a native Windows target. */
|
||||
/* #undef NATIVE_WINDOWS */
|
||||
|
||||
/* Define to 1 if you need the lber.h header file even with ldap.h */
|
||||
/* #undef NEED_LBER_H */
|
||||
|
||||
@@ -825,6 +825,12 @@
|
||||
/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
|
||||
/* #undef NEED_THREAD_SAFE */
|
||||
|
||||
/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */
|
||||
#define NTLM_WB_ENABLED 1
|
||||
|
||||
/* Define absolute filename for winbind's ntlm_auth helper. */
|
||||
#define NTLM_WB_FILE "/usr/bin/ntlm_auth"
|
||||
|
||||
/* cpu-machine-OS */
|
||||
#define OS "arm-linux-eabi"
|
||||
|
||||
@@ -832,7 +838,7 @@
|
||||
#define PACKAGE "curl"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/"
|
||||
#define PACKAGE_BUGREPORT "a suitable curl mailing list: https://curl.haxx.se/mail/"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "curl"
|
||||
@@ -850,37 +856,7 @@
|
||||
#define PACKAGE_VERSION "-"
|
||||
|
||||
/* a suitable file to read random data from */
|
||||
/* #undef RANDOM_FILE */
|
||||
|
||||
/* Define to the type of arg 1 for recvfrom. */
|
||||
/* #undef RECVFROM_TYPE_ARG1 */
|
||||
|
||||
/* Define to the type pointed by arg 2 for recvfrom. */
|
||||
/* #undef RECVFROM_TYPE_ARG2 */
|
||||
|
||||
/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */
|
||||
/* #undef RECVFROM_TYPE_ARG2_IS_VOID */
|
||||
|
||||
/* Define to the type of arg 3 for recvfrom. */
|
||||
/* #undef RECVFROM_TYPE_ARG3 */
|
||||
|
||||
/* Define to the type of arg 4 for recvfrom. */
|
||||
/* #undef RECVFROM_TYPE_ARG4 */
|
||||
|
||||
/* Define to the type pointed by arg 5 for recvfrom. */
|
||||
/* #undef RECVFROM_TYPE_ARG5 */
|
||||
|
||||
/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */
|
||||
/* #undef RECVFROM_TYPE_ARG5_IS_VOID */
|
||||
|
||||
/* Define to the type pointed by arg 6 for recvfrom. */
|
||||
/* #undef RECVFROM_TYPE_ARG6 */
|
||||
|
||||
/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */
|
||||
/* #undef RECVFROM_TYPE_ARG6_IS_VOID */
|
||||
|
||||
/* Define to the function return type for recvfrom. */
|
||||
/* #undef RECVFROM_TYPE_RETV */
|
||||
#define RANDOM_FILE "/dev/urandom"
|
||||
|
||||
/* Define to the type of arg 1 for recv. */
|
||||
#define RECV_TYPE_ARG1 int
|
||||
@@ -982,8 +958,14 @@
|
||||
/* Define to enable c-ares support */
|
||||
/* #undef USE_ARES */
|
||||
|
||||
/* Define to disable non-blocking sockets. */
|
||||
/* #undef USE_BLOCKING_SOCKETS */
|
||||
/* if axTLS is enabled */
|
||||
/* #undef USE_AXTLS */
|
||||
|
||||
/* if CyaSSL/WolfSSL is enabled */
|
||||
/* #undef USE_CYASSL */
|
||||
|
||||
/* to enable iOS/Mac OS X native SSL/TLS support */
|
||||
/* #undef USE_DARWINSSL */
|
||||
|
||||
/* if GnuTLS is enabled */
|
||||
/* #undef USE_GNUTLS */
|
||||
@@ -997,6 +979,15 @@
|
||||
/* If you want to build curl with the built-in manual */
|
||||
#define USE_MANUAL 1
|
||||
|
||||
/* if mbedTLS is enabled */
|
||||
/* #undef USE_MBEDTLS */
|
||||
|
||||
/* Define to enable metalink support */
|
||||
/* #undef USE_METALINK */
|
||||
|
||||
/* if nghttp2 is in use */
|
||||
/* #undef USE_NGHTTP2 */
|
||||
|
||||
/* if NSS is enabled */
|
||||
/* #undef USE_NSS */
|
||||
|
||||
@@ -1004,14 +995,33 @@
|
||||
/* #undef USE_OPENLDAP */
|
||||
|
||||
/* if OpenSSL is in use */
|
||||
/* #define USE_OPENSSL 1 */
|
||||
#define USE_OPENSSL 1
|
||||
|
||||
/* if PolarSSL is enabled */
|
||||
/* #undef USE_POLARSSL */
|
||||
|
||||
/* to enable Windows native SSL/TLS support */
|
||||
/* #undef USE_SCHANNEL */
|
||||
|
||||
/* if you want POSIX threaded DNS lookup */
|
||||
/* #undef USE_THREADS_POSIX */
|
||||
|
||||
/* Use TLS-SRP authentication */
|
||||
#define USE_TLS_SRP 1
|
||||
|
||||
/* Use Unix domain sockets */
|
||||
#define USE_UNIX_SOCKETS 1
|
||||
|
||||
/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */
|
||||
/* #undef USE_WIN32_IDN */
|
||||
|
||||
/* Define to 1 if you are building a Windows target with large file support.
|
||||
*/
|
||||
/* #undef USE_WIN32_SMALL_FILES */
|
||||
|
||||
/* Use Windows LDAP implementation */
|
||||
/* #undef USE_WIN32_LDAP */
|
||||
|
||||
/* Define to 1 if you are building a Windows target without large file
|
||||
support. */
|
||||
/* #undef USE_WIN32_LARGE_FILES */
|
||||
@@ -1019,8 +1029,11 @@
|
||||
/* to enable SSPI support */
|
||||
/* #undef USE_WINDOWS_SSPI */
|
||||
|
||||
/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
|
||||
/* #undef USE_YASSLEMUL */
|
||||
/* Version number of package */
|
||||
#define VERSION "-"
|
||||
|
||||
/* Define to 1 to provide own prototypes. */
|
||||
/* #undef WANT_IDN_PROTOTYPES */
|
||||
|
||||
/* Define to avoid automatic inclusion of winsock.h */
|
||||
/* #undef WIN32_LEAN_AND_MEAN */
|
||||
@@ -1030,6 +1043,11 @@
|
||||
/* # undef _ALL_SOURCE */
|
||||
#endif
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
/* #undef _FILE_OFFSET_BITS */
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "curl_fnmatch.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2011 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2011 - 2016, 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
|
||||
@@ -76,6 +76,32 @@ OM_uint32 Curl_gss_init_sec_context(
|
||||
NULL /* time_rec */);
|
||||
}
|
||||
|
||||
#define GSS_LOG_BUFFER_LEN 1024
|
||||
static size_t display_gss_error(OM_uint32 status, int type,
|
||||
char *buf, size_t len) {
|
||||
OM_uint32 maj_stat;
|
||||
OM_uint32 min_stat;
|
||||
OM_uint32 msg_ctx = 0;
|
||||
gss_buffer_desc status_string;
|
||||
|
||||
do {
|
||||
maj_stat = gss_display_status(&min_stat,
|
||||
status,
|
||||
type,
|
||||
GSS_C_NO_OID,
|
||||
&msg_ctx,
|
||||
&status_string);
|
||||
if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) {
|
||||
len += snprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
|
||||
"%.*s. ", (int)status_string.length,
|
||||
(char*)status_string.value);
|
||||
}
|
||||
gss_release_buffer(&min_stat, &status_string);
|
||||
} while(!GSS_ERROR(maj_stat) && msg_ctx != 0);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_gss_log_error()
|
||||
*
|
||||
@@ -84,37 +110,22 @@ OM_uint32 Curl_gss_init_sec_context(
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* status [in] - The status code.
|
||||
* prefix [in] - The prefix of the log message.
|
||||
* major [in] - The major status code.
|
||||
* minor [in] - The minor status code.
|
||||
*/
|
||||
void Curl_gss_log_error(struct SessionHandle *data, OM_uint32 status,
|
||||
const char *prefix)
|
||||
void Curl_gss_log_error(struct SessionHandle *data, const char *prefix,
|
||||
OM_uint32 major, OM_uint32 minor)
|
||||
{
|
||||
OM_uint32 maj_stat;
|
||||
OM_uint32 min_stat;
|
||||
OM_uint32 msg_ctx = 0;
|
||||
gss_buffer_desc status_string;
|
||||
char buf[1024];
|
||||
size_t len;
|
||||
char buf[GSS_LOG_BUFFER_LEN];
|
||||
size_t len = 0;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s", prefix);
|
||||
len = strlen(buf);
|
||||
do {
|
||||
maj_stat = gss_display_status(&min_stat,
|
||||
status,
|
||||
GSS_C_MECH_CODE,
|
||||
GSS_C_NO_OID,
|
||||
&msg_ctx,
|
||||
&status_string);
|
||||
if(sizeof(buf) > len + status_string.length + 1) {
|
||||
snprintf(buf + len, sizeof(buf) - len,
|
||||
": %s", (char*)status_string.value);
|
||||
len += status_string.length;
|
||||
}
|
||||
gss_release_buffer(&min_stat, &status_string);
|
||||
} while(!GSS_ERROR(maj_stat) && msg_ctx != 0);
|
||||
if(major != GSS_S_FAILURE)
|
||||
len = display_gss_error(major, GSS_C_GSS_CODE, buf, len);
|
||||
|
||||
infof(data, "%s\n", buf);
|
||||
display_gss_error(minor, GSS_C_MECH_CODE, buf, len);
|
||||
|
||||
infof(data, "%s%s\n", prefix, buf);
|
||||
}
|
||||
|
||||
#endif /* HAVE_GSSAPI */
|
||||
|
||||
@@ -56,8 +56,8 @@ OM_uint32 Curl_gss_init_sec_context(
|
||||
OM_uint32 *ret_flags);
|
||||
|
||||
/* Helper to log a GSS-API error status */
|
||||
void Curl_gss_log_error(struct SessionHandle *data, OM_uint32 status,
|
||||
const char *prefix);
|
||||
void Curl_gss_log_error(struct SessionHandle *data, const char *prefix,
|
||||
OM_uint32 major, OM_uint32 minor);
|
||||
|
||||
/* Provide some definitions missing in old headers */
|
||||
#ifdef HAVE_OLD_GSSMIT
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -83,7 +83,20 @@
|
||||
|
||||
#ifndef CURLX_NO_MEMORY_CALLBACKS
|
||||
|
||||
#include <curl/curl.h> /* for the callback typedefs */
|
||||
#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS /* only if not already done */
|
||||
/*
|
||||
* The following memory function replacement typedef's are COPIED from
|
||||
* curl/curl.h and MUST match the originals. We copy them to avoid having to
|
||||
* include curl/curl.h here. We avoid that include since it includes stdio.h
|
||||
* and other headers that may get messed up with defines done here.
|
||||
*/
|
||||
typedef void *(*curl_malloc_callback)(size_t size);
|
||||
typedef void (*curl_free_callback)(void *ptr);
|
||||
typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
|
||||
typedef char *(*curl_strdup_callback)(const char *str);
|
||||
typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
|
||||
#define CURL_DID_MEMORY_FUNC_TYPEDEFS
|
||||
#endif
|
||||
|
||||
extern curl_malloc_callback Curl_cmalloc;
|
||||
extern curl_free_callback Curl_cfree;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -21,6 +21,9 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "curl_memrchr.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -28,7 +28,7 @@
|
||||
* NTLM details:
|
||||
*
|
||||
* http://davenport.sourceforge.net/ntlm.html
|
||||
* http://www.innovation.ch/java/ntlm.html
|
||||
* https://www.innovation.ch/java/ntlm.html
|
||||
*/
|
||||
|
||||
#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
|
||||
@@ -107,9 +107,8 @@
|
||||
#include "warnless.h"
|
||||
#include "curl_endian.h"
|
||||
#include "curl_des.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -29,7 +29,7 @@
|
||||
* NTLM details:
|
||||
*
|
||||
* http://davenport.sourceforge.net/ntlm.html
|
||||
* http://www.innovation.ch/java/ntlm.html
|
||||
* https://www.innovation.ch/java/ntlm.html
|
||||
*/
|
||||
|
||||
#define DEBUG_ME 0
|
||||
@@ -47,13 +47,12 @@
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "select.h"
|
||||
#include "curl_ntlm_msgs.h"
|
||||
#include "vauth/ntlm.h"
|
||||
#include "curl_ntlm_wb.h"
|
||||
#include "url.h"
|
||||
#include "strerror.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,18 +27,6 @@
|
||||
struct SessionHandle;
|
||||
struct connectdata;
|
||||
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
struct digestdata;
|
||||
#endif
|
||||
|
||||
#if defined(USE_NTLM)
|
||||
struct ntlmdata;
|
||||
#endif
|
||||
|
||||
#if defined(USE_KERBEROS5)
|
||||
struct kerberos5data;
|
||||
#endif
|
||||
|
||||
/* Authentication mechanism flags */
|
||||
#define SASL_MECH_LOGIN (1 << 0)
|
||||
#define SASL_MECH_PLAIN (1 << 1)
|
||||
@@ -66,16 +54,6 @@ struct kerberos5data;
|
||||
#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2"
|
||||
#define SASL_MECH_STRING_OAUTHBEARER "OAUTHBEARER"
|
||||
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#define DIGEST_MAX_VALUE_LENGTH 256
|
||||
#define DIGEST_MAX_CONTENT_LENGTH 1024
|
||||
#endif
|
||||
|
||||
enum {
|
||||
CURLDIGESTALGO_MD5,
|
||||
CURLDIGESTALGO_MD5SESS
|
||||
};
|
||||
|
||||
/* SASL machine states */
|
||||
typedef enum {
|
||||
SASL_STOP,
|
||||
@@ -136,96 +114,6 @@ struct SASL {
|
||||
(wordlen == (sizeof(mech) - 1) / sizeof(char) && \
|
||||
!memcmp(line, mech, wordlen))
|
||||
|
||||
/* This is used to build a SPN string */
|
||||
#if !defined(USE_WINDOWS_SSPI)
|
||||
char *Curl_sasl_build_spn(const char *service, const char *instance);
|
||||
#else
|
||||
TCHAR *Curl_sasl_build_spn(const char *service, const char *instance);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GSSAPI)
|
||||
char *Curl_sasl_build_gssapi_spn(const char *service, const char *instance);
|
||||
#endif
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
/* This is used to extract the realm from a challenge message */
|
||||
bool Curl_sasl_digest_get_pair(const char *str, char *value, char *content,
|
||||
const char **endptr);
|
||||
|
||||
/* This is used to generate a base64 encoded DIGEST-MD5 response message */
|
||||
CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
||||
const char *chlg64,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
const char *service,
|
||||
char **outptr, size_t *outlen);
|
||||
|
||||
/* This is used to decode a HTTP DIGEST challenge message */
|
||||
CURLcode Curl_sasl_decode_digest_http_message(const char *chlg,
|
||||
struct digestdata *digest);
|
||||
|
||||
/* This is used to generate a HTTP DIGEST response message */
|
||||
CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
const unsigned char *request,
|
||||
const unsigned char *uri,
|
||||
struct digestdata *digest,
|
||||
char **outptr, size_t *outlen);
|
||||
|
||||
/* This is used to clean up the digest specific data */
|
||||
void Curl_sasl_digest_cleanup(struct digestdata *digest);
|
||||
#endif
|
||||
|
||||
#ifdef USE_NTLM
|
||||
/* This is used to generate a base64 encoded NTLM type-1 message */
|
||||
CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
|
||||
const char *passwdp,
|
||||
struct ntlmdata *ntlm,
|
||||
char **outptr,
|
||||
size_t *outlen);
|
||||
|
||||
/* This is used to decode a base64 encoded NTLM type-2 message */
|
||||
CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data,
|
||||
const char *type2msg,
|
||||
struct ntlmdata *ntlm);
|
||||
|
||||
/* This is used to generate a base64 encoded NTLM type-3 message */
|
||||
CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
struct ntlmdata *ntlm,
|
||||
char **outptr, size_t *outlen);
|
||||
|
||||
/* This is used to clean up the ntlm specific data */
|
||||
void Curl_sasl_ntlm_cleanup(struct ntlmdata *ntlm);
|
||||
|
||||
#endif /* USE_NTLM */
|
||||
|
||||
#if defined(USE_KERBEROS5)
|
||||
/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) user token
|
||||
message */
|
||||
CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
const char *service,
|
||||
const bool mutual,
|
||||
const char *chlg64,
|
||||
struct kerberos5data *krb5,
|
||||
char **outptr, size_t *outlen);
|
||||
|
||||
/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) security
|
||||
token message */
|
||||
CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||
const char *input,
|
||||
struct kerberos5data *krb5,
|
||||
char **outptr,
|
||||
size_t *outlen);
|
||||
|
||||
/* This is used to clean up the gssapi specific data */
|
||||
void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5);
|
||||
#endif /* USE_KERBEROS5 */
|
||||
|
||||
/* This is used to cleanup any libraries or curl modules used by the sasl
|
||||
functions */
|
||||
void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -473,7 +473,7 @@
|
||||
# endif
|
||||
|
||||
# ifndef fileno /* sunos 4 have this as a macro! */
|
||||
int fileno( FILE *stream);
|
||||
int fileno(FILE *stream);
|
||||
# endif
|
||||
|
||||
#endif /* WIN32 */
|
||||
@@ -722,4 +722,19 @@ endings either CRLF or LF so 't' is appropriate.
|
||||
#define FOPEN_WRITETEXT "w"
|
||||
#endif
|
||||
|
||||
/* WinSock destroys recv() buffer when send() failed.
|
||||
* Enabled automatically for Windows and for Cygwin as Cygwin sockets are
|
||||
* wrappers for WinSock sockets. https://github.com/curl/curl/issues/657
|
||||
* Define DONT_USE_RECV_BEFORE_SEND_WORKAROUND to force disable workaround.
|
||||
*/
|
||||
#if !defined(DONT_USE_RECV_BEFORE_SEND_WORKAROUND)
|
||||
# if defined(WIN32) || defined(__CYGWIN__)
|
||||
# define USE_RECV_BEFORE_SEND_WORKAROUND
|
||||
# endif
|
||||
#else /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */
|
||||
# ifdef USE_RECV_BEFORE_SEND_WORKAROUND
|
||||
# undef USE_RECV_BEFORE_SEND_WORKAROUND
|
||||
# endif
|
||||
#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */
|
||||
|
||||
#endif /* HEADER_CURL_SETUP_H */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#if defined(USE_THREADS_POSIX)
|
||||
# ifdef HAVE_PTHREAD_H
|
||||
# include <pthread.h>
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include "dotdot.h"
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "dotdot.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
@@ -73,9 +73,8 @@
|
||||
#include "multiif.h"
|
||||
#include "sigpipe.h"
|
||||
#include "ssh.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -121,8 +120,8 @@ static CURLcode win32_init(void)
|
||||
/* wVersionRequested in wVersion. wHighVersion contains the */
|
||||
/* highest supported version. */
|
||||
|
||||
if(LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) ||
|
||||
HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) {
|
||||
if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
|
||||
HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) {
|
||||
/* Tell the user that we couldn't find a useable */
|
||||
|
||||
/* winsock.dll. */
|
||||
@@ -625,7 +624,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
|
||||
if(0 == pollrc) {
|
||||
/* timeout! */
|
||||
ev->ms = 0;
|
||||
/* fprintf(stderr, "call curl_multi_socket_action( TIMEOUT )\n"); */
|
||||
/* fprintf(stderr, "call curl_multi_socket_action(TIMEOUT)\n"); */
|
||||
mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0,
|
||||
&ev->running_handles);
|
||||
}
|
||||
@@ -635,7 +634,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
|
||||
if(fds[i].revents) {
|
||||
/* socket activity, tell libcurl */
|
||||
int act = poll2cselect(fds[i].revents); /* convert */
|
||||
infof(multi->easyp, "call curl_multi_socket_action( socket %d )\n",
|
||||
infof(multi->easyp, "call curl_multi_socket_action(socket %d)\n",
|
||||
fds[i].fd);
|
||||
mcode = curl_multi_socket_action(multi, fds[i].fd, act,
|
||||
&ev->running_handles);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -31,9 +31,8 @@
|
||||
#include "warnless.h"
|
||||
#include "non-ascii.h"
|
||||
#include "escape.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -105,7 +104,7 @@ char *curl_easy_escape(CURL *handle, const char *string, int inlength)
|
||||
alloc *= 2;
|
||||
testing_ptr = realloc(ns, alloc);
|
||||
if(!testing_ptr) {
|
||||
free( ns );
|
||||
free(ns);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -61,9 +61,8 @@
|
||||
#include "url.h"
|
||||
#include "parsedate.h" /* for the week day and month names */
|
||||
#include "warnless.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -368,7 +367,7 @@ static CURLcode file_upload(struct connectdata *conn)
|
||||
|
||||
/*skip bytes before resume point*/
|
||||
if(data->state.resume_from) {
|
||||
if((curl_off_t)nread <= data->state.resume_from ) {
|
||||
if((curl_off_t)nread <= data->state.resume_from) {
|
||||
data->state.resume_from -= nread;
|
||||
nread = 0;
|
||||
buf2 = buf;
|
||||
@@ -469,6 +468,9 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
|
||||
information. Which for FILE can't be much more than the file size and
|
||||
date. */
|
||||
if(data->set.opt_no_body && data->set.include_header && fstated) {
|
||||
time_t filetime;
|
||||
struct tm buffer;
|
||||
const struct tm *tm = &buffer;
|
||||
snprintf(buf, sizeof(data->state.buffer),
|
||||
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size);
|
||||
result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
|
||||
@@ -480,29 +482,24 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(fstated) {
|
||||
time_t filetime = (time_t)statbuf.st_mtime;
|
||||
struct tm buffer;
|
||||
const struct tm *tm = &buffer;
|
||||
result = Curl_gmtime(filetime, &buffer);
|
||||
if(result)
|
||||
return result;
|
||||
filetime = (time_t)statbuf.st_mtime;
|
||||
result = Curl_gmtime(filetime, &buffer);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
|
||||
snprintf(buf, BUFSIZE-1,
|
||||
"Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
|
||||
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
|
||||
tm->tm_mday,
|
||||
Curl_month[tm->tm_mon],
|
||||
tm->tm_year + 1900,
|
||||
tm->tm_hour,
|
||||
tm->tm_min,
|
||||
tm->tm_sec);
|
||||
result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
|
||||
}
|
||||
/* if we fstat()ed the file, set the file size to make it available post-
|
||||
transfer */
|
||||
if(fstated)
|
||||
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
|
||||
snprintf(buf, BUFSIZE-1,
|
||||
"Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
|
||||
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
|
||||
tm->tm_mday,
|
||||
Curl_month[tm->tm_mon],
|
||||
tm->tm_year + 1900,
|
||||
tm->tm_hour,
|
||||
tm->tm_min,
|
||||
tm->tm_sec);
|
||||
result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
|
||||
if(!result)
|
||||
/* set the file size to make it available post transfer */
|
||||
Curl_pgrsSetDownloadSize(data, expected_size);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -36,9 +36,8 @@
|
||||
#include "strequal.h"
|
||||
#include "sendf.h"
|
||||
#include "strdup.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -632,7 +631,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
||||
else {
|
||||
if(((form->flags & HTTPPOST_FILENAME) ||
|
||||
(form->flags & HTTPPOST_BUFFER)) &&
|
||||
!form->contenttype ) {
|
||||
!form->contenttype) {
|
||||
char *f = form->flags & HTTPPOST_BUFFER?
|
||||
form->showfilename : form->value;
|
||||
|
||||
@@ -770,7 +769,7 @@ curl_off_t VmsRealFileSize(const char * name,
|
||||
int ret_stat;
|
||||
FILE * file;
|
||||
|
||||
file = fopen(name, "r"); /* VMS */
|
||||
file = fopen(name, FOPEN_READTEXT); /* VMS */
|
||||
if(file == NULL)
|
||||
return 0;
|
||||
|
||||
@@ -1273,7 +1272,7 @@ CURLcode Curl_getformdata(struct SessionHandle *data,
|
||||
curList = file->contentheader;
|
||||
while(curList) {
|
||||
/* Process the additional headers specified for this form */
|
||||
result = AddFormDataf( &form, &size, "\r\n%s", curList->data );
|
||||
result = AddFormDataf(&form, &size, "\r\n%s", curList->data);
|
||||
if(result)
|
||||
break;
|
||||
curList = curList->next;
|
||||
@@ -1386,7 +1385,7 @@ CURLcode Curl_getformdata(struct SessionHandle *data,
|
||||
* Curl_FormInit() inits the struct 'form' points to with the 'formdata'
|
||||
* and resets the 'sent' counter.
|
||||
*/
|
||||
int Curl_FormInit(struct Form *form, struct FormData *formdata )
|
||||
int Curl_FormInit(struct Form *form, struct FormData *formdata)
|
||||
{
|
||||
if(!formdata)
|
||||
return 1; /* error */
|
||||
@@ -1421,10 +1420,10 @@ static FILE * vmsfopenread(const char *file, const char *mode) {
|
||||
case FAB$C_VAR:
|
||||
case FAB$C_VFC:
|
||||
case FAB$C_STMCR:
|
||||
return fopen(file, "r"); /* VMS */
|
||||
return fopen(file, FOPEN_READTEXT); /* VMS */
|
||||
break;
|
||||
default:
|
||||
return fopen(file, "r", "rfm=stmlf", "ctx=stm");
|
||||
return fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1499,9 +1498,9 @@ size_t Curl_FormReader(char *buffer,
|
||||
}
|
||||
do {
|
||||
|
||||
if((form->data->length - form->sent ) > wantedsize - gotsize) {
|
||||
if((form->data->length - form->sent) > wantedsize - gotsize) {
|
||||
|
||||
memcpy(buffer + gotsize , form->data->line + form->sent,
|
||||
memcpy(buffer + gotsize, form->data->line + form->sent,
|
||||
wantedsize - gotsize);
|
||||
|
||||
form->sent += wantedsize-gotsize;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -68,7 +68,7 @@ typedef struct FormInfo {
|
||||
struct FormInfo *more;
|
||||
} FormInfo;
|
||||
|
||||
int Curl_FormInit(struct Form *form, struct FormData *formdata );
|
||||
int Curl_FormInit(struct Form *form, struct FormData *formdata);
|
||||
|
||||
CURLcode Curl_getformdata(struct SessionHandle *data,
|
||||
struct FormData **,
|
||||
|
||||
@@ -77,10 +77,9 @@
|
||||
#include "warnless.h"
|
||||
#include "http_proxy.h"
|
||||
#include "non-ascii.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
#ifndef NI_MAXHOST
|
||||
@@ -710,7 +709,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
||||
/* check and reset timeout value every lap */
|
||||
timeout = Curl_pp_state_timeout(pp);
|
||||
|
||||
if(timeout <=0 ) {
|
||||
if(timeout <=0) {
|
||||
failf(data, "FTP response timeout");
|
||||
return CURLE_OPERATION_TIMEDOUT; /* already too little time */
|
||||
}
|
||||
@@ -1036,7 +1035,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
||||
if(*string_ftpport == '[') {
|
||||
/* [ipv6]:port(-range) */
|
||||
ip_start = string_ftpport + 1;
|
||||
if((ip_end = strchr(string_ftpport, ']')) != NULL )
|
||||
if((ip_end = strchr(string_ftpport, ']')) != NULL)
|
||||
strncpy(addr, ip_start, ip_end - ip_start);
|
||||
}
|
||||
else
|
||||
@@ -1057,7 +1056,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
||||
else
|
||||
#endif
|
||||
/* (ipv4|domain|interface):port(-range) */
|
||||
strncpy(addr, string_ftpport, ip_end - ip_start );
|
||||
strncpy(addr, string_ftpport, ip_end - ip_start);
|
||||
}
|
||||
else
|
||||
/* ipv4|interface */
|
||||
@@ -1077,11 +1076,11 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
||||
|
||||
/* correct errors like:
|
||||
* :1234-1230
|
||||
* :-4711 , in this case port_min is (unsigned)-1,
|
||||
* :-4711, in this case port_min is (unsigned)-1,
|
||||
* therefore port_min > port_max for all cases
|
||||
* but port_max = (unsigned)-1
|
||||
*/
|
||||
if(port_min > port_max )
|
||||
if(port_min > port_max)
|
||||
port_min = port_max = 0;
|
||||
|
||||
|
||||
@@ -1525,12 +1524,12 @@ static CURLcode ftp_state_list(struct connectdata *conn)
|
||||
}
|
||||
}
|
||||
|
||||
cmd = aprintf( "%s%s%s",
|
||||
data->set.str[STRING_CUSTOMREQUEST]?
|
||||
data->set.str[STRING_CUSTOMREQUEST]:
|
||||
(data->set.ftp_list_only?"NLST":"LIST"),
|
||||
lstArg? " ": "",
|
||||
lstArg? lstArg: "" );
|
||||
cmd = aprintf("%s%s%s",
|
||||
data->set.str[STRING_CUSTOMREQUEST]?
|
||||
data->set.str[STRING_CUSTOMREQUEST]:
|
||||
(data->set.ftp_list_only?"NLST":"LIST"),
|
||||
lstArg? " ": "",
|
||||
lstArg? lstArg: "");
|
||||
|
||||
if(!cmd) {
|
||||
free(lstArg);
|
||||
@@ -1652,7 +1651,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
|
||||
/* 4. lower the infilesize counter */
|
||||
/* => transfer as usual */
|
||||
|
||||
if(data->state.resume_from < 0 ) {
|
||||
if(data->state.resume_from < 0) {
|
||||
/* Got no given size to start from, figure it out */
|
||||
PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
|
||||
state(conn, FTP_STOR_SIZE);
|
||||
@@ -3242,7 +3241,7 @@ static CURLcode ftp_connect(struct connectdata *conn,
|
||||
* Input argument is already checked for validity.
|
||||
*/
|
||||
static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
||||
bool premature)
|
||||
bool premature)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct FTP *ftp = data->req.protop;
|
||||
@@ -3256,11 +3255,6 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
||||
const char *path_to_use = data->state.path;
|
||||
|
||||
if(!ftp)
|
||||
/* When the easy handle is removed from the multi while libcurl is still
|
||||
* trying to resolve the host name, it seems that the ftp struct is not
|
||||
* yet initialized, but the removal action calls Curl_done() which calls
|
||||
* this function. So we simply return success if no ftp pointer is set.
|
||||
*/
|
||||
return CURLE_OK;
|
||||
|
||||
switch(status) {
|
||||
|
||||
@@ -307,7 +307,7 @@ static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info,
|
||||
#elif defined(USE_GSKIT)
|
||||
tsi->internals = (void *)conn->ssl[i].handle;
|
||||
#elif defined(USE_MBEDTLS)
|
||||
tsi->internals = (void *)&conn->ssl[i].ssn;
|
||||
tsi->internals = (void *)&conn->ssl[i].ssl;
|
||||
#elif defined(USE_NSS)
|
||||
tsi->internals = (void *)conn->ssl[i].handle;
|
||||
#elif defined(USE_OPENSSL)
|
||||
@@ -316,7 +316,7 @@ static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info,
|
||||
(void *)conn->ssl[i].ctx :
|
||||
(void *)conn->ssl[i].handle);
|
||||
#elif defined(USE_POLARSSL)
|
||||
tsi->internals = (void *)&conn->ssl[i].ssn;
|
||||
tsi->internals = (void *)&conn->ssl[i].ssl;
|
||||
#elif defined(USE_SCHANNEL)
|
||||
tsi->internals = (void *)&conn->ssl[i].ctxt->ctxt_handle;
|
||||
#elif defined(USE_SSL)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -22,9 +22,12 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "hash.h"
|
||||
#include "llist.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -26,8 +26,11 @@
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "curl_hmac.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -56,9 +56,9 @@
|
||||
#include "url.h"
|
||||
#include "inet_ntop.h"
|
||||
#include "warnless.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
#if defined(CURLRES_SYNCH) && \
|
||||
@@ -353,7 +353,8 @@ Curl_fetch_addr(struct connectdata *conn,
|
||||
|
||||
dns = fetch_addr(conn, hostname, port);
|
||||
|
||||
if(dns) dns->inuse++; /* we use it! */
|
||||
if(dns)
|
||||
dns->inuse++; /* we use it! */
|
||||
|
||||
if(data->share)
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
||||
@@ -777,7 +778,7 @@ CURLcode Curl_loadhostpairs(struct SessionHandle *data)
|
||||
char address[256];
|
||||
int port;
|
||||
|
||||
for(hostp = data->change.resolve; hostp; hostp = hostp->next ) {
|
||||
for(hostp = data->change.resolve; hostp; hostp = hostp->next) {
|
||||
if(!hostp->data)
|
||||
continue;
|
||||
if(hostp->data[0] == '-') {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -48,9 +48,9 @@
|
||||
#include "strerror.h"
|
||||
#include "url.h"
|
||||
#include "inet_pton.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
@@ -49,10 +49,9 @@
|
||||
#include "url.h"
|
||||
#include "inet_pton.h"
|
||||
#include "connect.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
@@ -54,9 +54,10 @@
|
||||
#include "curl_base64.h"
|
||||
#include "cookie.h"
|
||||
#include "strequal.h"
|
||||
#include "vauth/vauth.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "http_digest.h"
|
||||
#include "curl_ntlm.h"
|
||||
#include "http_ntlm.h"
|
||||
#include "curl_ntlm_wb.h"
|
||||
#include "http_negotiate.h"
|
||||
#include "url.h"
|
||||
@@ -76,9 +77,9 @@
|
||||
#include "pipeline.h"
|
||||
#include "http2.h"
|
||||
#include "connect.h"
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -144,11 +145,10 @@ const struct Curl_handler Curl_handler_https = {
|
||||
ZERO_NULL, /* readwrite */
|
||||
PORT_HTTPS, /* defport */
|
||||
CURLPROTO_HTTPS, /* protocol */
|
||||
PROTOPT_SSL | PROTOPT_CREDSPERREQUEST /* flags */
|
||||
PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN /* flags */
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
CURLcode Curl_http_setup_conn(struct connectdata *conn)
|
||||
{
|
||||
/* allocate the HTTP-specific struct for the SessionHandle, only to survive
|
||||
@@ -185,6 +185,7 @@ char *Curl_checkheaders(const struct connectdata *conn,
|
||||
if(Curl_raw_nequal(head->data, thisheader, thislen))
|
||||
return head->data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -196,7 +197,6 @@ char *Curl_checkheaders(const struct connectdata *conn,
|
||||
* It takes a connectdata struct as input instead of the SessionHandle simply
|
||||
* to know if this is a proxy request or not, as it then might check a
|
||||
* different header list.
|
||||
*
|
||||
*/
|
||||
char *Curl_checkProxyheaders(const struct connectdata *conn,
|
||||
const char *thisheader)
|
||||
@@ -205,12 +205,13 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
|
||||
size_t thislen = strlen(thisheader);
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
for(head = (conn->bits.proxy && data->set.sep_headers)?
|
||||
data->set.proxyheaders:data->set.headers;
|
||||
for(head = (conn->bits.proxy && data->set.sep_headers) ?
|
||||
data->set.proxyheaders : data->set.headers;
|
||||
head; head=head->next) {
|
||||
if(Curl_raw_nequal(head->data, thisheader, thislen))
|
||||
return head->data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -309,7 +310,7 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
|
||||
|
||||
free(*userp);
|
||||
*userp = aprintf("%sAuthorization: Basic %s\r\n",
|
||||
proxy?"Proxy-":"",
|
||||
proxy ? "Proxy-" : "",
|
||||
authorization);
|
||||
free(authorization);
|
||||
if(!*userp)
|
||||
@@ -528,7 +529,6 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
else if((data->req.httpcode < 300) &&
|
||||
(!data->state.authhost.done) &&
|
||||
conn->bits.authneg) {
|
||||
@@ -553,7 +553,6 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Output the correct authentication header depending on the auth type
|
||||
* and whether or not it is to a proxy.
|
||||
@@ -584,7 +583,7 @@ output_auth_headers(struct connectdata *conn,
|
||||
negdata->state = GSS_AUTHNONE;
|
||||
if((authstatus->picked == CURLAUTH_NEGOTIATE) &&
|
||||
negdata->context && !GSS_ERROR(negdata->status)) {
|
||||
auth="Negotiate";
|
||||
auth = "Negotiate";
|
||||
result = Curl_output_negotiate(conn, proxy);
|
||||
if(result)
|
||||
return result;
|
||||
@@ -595,7 +594,7 @@ output_auth_headers(struct connectdata *conn,
|
||||
#endif
|
||||
#ifdef USE_NTLM
|
||||
if(authstatus->picked == CURLAUTH_NTLM) {
|
||||
auth="NTLM";
|
||||
auth = "NTLM";
|
||||
result = Curl_output_ntlm(conn, proxy);
|
||||
if(result)
|
||||
return result;
|
||||
@@ -613,7 +612,7 @@ output_auth_headers(struct connectdata *conn,
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
if(authstatus->picked == CURLAUTH_DIGEST) {
|
||||
auth="Digest";
|
||||
auth = "Digest";
|
||||
result = Curl_output_digest(conn,
|
||||
proxy,
|
||||
(const unsigned char *)request,
|
||||
@@ -629,11 +628,12 @@ output_auth_headers(struct connectdata *conn,
|
||||
!Curl_checkProxyheaders(conn, "Proxy-authorization:")) ||
|
||||
(!proxy && conn->bits.user_passwd &&
|
||||
!Curl_checkheaders(conn, "Authorization:"))) {
|
||||
auth="Basic";
|
||||
auth = "Basic";
|
||||
result = http_output_basic(conn, proxy);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* NOTE: this function should set 'done' TRUE, as the other auth
|
||||
functions work that way */
|
||||
authstatus->done = TRUE;
|
||||
@@ -641,9 +641,9 @@ output_auth_headers(struct connectdata *conn,
|
||||
|
||||
if(auth) {
|
||||
infof(data, "%s auth using %s with user '%s'\n",
|
||||
proxy?"Proxy":"Server", auth,
|
||||
proxy?(conn->proxyuser?conn->proxyuser:""):
|
||||
(conn->user?conn->user:""));
|
||||
proxy ? "Proxy" : "Server", auth,
|
||||
proxy ? (conn->proxyuser ? conn->proxyuser : "") :
|
||||
(conn->user ? conn->user : ""));
|
||||
authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
|
||||
}
|
||||
else
|
||||
@@ -735,7 +735,6 @@ Curl_http_output_auth(struct connectdata *conn,
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
|
||||
* headers. They are dealt with both in the transfer.c main loop and in the
|
||||
@@ -780,7 +779,6 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
|
||||
* request is sent, and then it is again set _after_ all response 401/407
|
||||
* headers have been received but then only to a single preferred method
|
||||
* (bit).
|
||||
*
|
||||
*/
|
||||
|
||||
while(*auth) {
|
||||
@@ -893,6 +891,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
|
||||
while(*auth && ISSPACE(*auth))
|
||||
auth++;
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@@ -934,8 +933,7 @@ static int http_should_fail(struct connectdata *conn)
|
||||
** Any code >= 400 that's not 401 or 407 is always
|
||||
** a terminal error
|
||||
*/
|
||||
if((httpcode != 401) &&
|
||||
(httpcode != 407))
|
||||
if((httpcode != 401) && (httpcode != 407))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
@@ -986,7 +984,7 @@ static size_t readmoredata(char *buffer,
|
||||
struct HTTP *http = conn->data->req.protop;
|
||||
size_t fullsize = size * nitems;
|
||||
|
||||
if(0 == http->postsize)
|
||||
if(!http->postsize)
|
||||
/* nothing to return */
|
||||
return 0;
|
||||
|
||||
@@ -1092,7 +1090,6 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
if((conn->handler->flags & PROTOPT_SSL) && conn->httpversion != 20) {
|
||||
/* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
|
||||
when we speak HTTPS, as if only a fraction of it is sent now, this data
|
||||
@@ -1100,7 +1097,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
|
||||
buffer is using this size.
|
||||
*/
|
||||
|
||||
sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size;
|
||||
sendsize = (size > CURL_MAX_WRITE_SIZE) ? CURL_MAX_WRITE_SIZE : size;
|
||||
|
||||
/* OpenSSL is very picky and we must send the SAME buffer pointer to the
|
||||
library when we attempt to re-send this buffer. Sending the same data
|
||||
@@ -1123,7 +1120,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
|
||||
* only send away a part).
|
||||
*/
|
||||
/* how much of the header that was sent */
|
||||
size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount;
|
||||
size_t headlen = (size_t)amount>headersize ? headersize : (size_t)amount;
|
||||
size_t bodylen = amount - headlen;
|
||||
|
||||
if(conn->data->set.verbose) {
|
||||
@@ -1136,10 +1133,6 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
|
||||
ptr+headlen, bodylen, conn);
|
||||
}
|
||||
}
|
||||
if(bodylen)
|
||||
/* since we sent a piece of the body here, up the byte counter for it
|
||||
accordingly */
|
||||
http->writebytecount += bodylen;
|
||||
|
||||
/* 'amount' can never be a very large value here so typecasting it so a
|
||||
signed 31 bit value should not cause problems even if ssize_t is
|
||||
@@ -1147,6 +1140,10 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
|
||||
*bytes_written += (long)amount;
|
||||
|
||||
if(http) {
|
||||
/* if we sent a piece of the body here, up the byte counter for it
|
||||
accordingly */
|
||||
http->writebytecount += bodylen;
|
||||
|
||||
if((size_t)amount != size) {
|
||||
/* The whole request could not be sent in one system call. We must
|
||||
queue it up and send it later when we get the chance. We must not
|
||||
@@ -1242,11 +1239,11 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
|
||||
buffer size that doubles the required size. If this new size
|
||||
would wrap size_t, then just use the largest possible one */
|
||||
|
||||
if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) ||
|
||||
(~(size*2) < (in->size_used*2)))
|
||||
if((size > (size_t)-1 / 2) || (in->size_used > (size_t)-1 / 2) ||
|
||||
(~(size * 2) < (in->size_used * 2)))
|
||||
new_size = (size_t)-1;
|
||||
else
|
||||
new_size = (in->size_used+size)*2;
|
||||
new_size = (in->size_used+size) * 2;
|
||||
|
||||
if(in->buffer)
|
||||
/* we have a buffer, enlarge the existing one */
|
||||
@@ -1419,6 +1416,7 @@ static int https_getsock(struct connectdata *conn,
|
||||
return GETSOCK_READSOCK(0);
|
||||
}
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
#else
|
||||
@@ -1436,8 +1434,8 @@ static int https_getsock(struct connectdata *conn,
|
||||
#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */
|
||||
|
||||
/*
|
||||
* Curl_http_done() gets called from Curl_done() after a single HTTP request
|
||||
* has been performed.
|
||||
* Curl_http_done() gets called after a single HTTP request has been
|
||||
* performed.
|
||||
*/
|
||||
|
||||
CURLcode Curl_http_done(struct connectdata *conn,
|
||||
@@ -1456,8 +1454,10 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
||||
data->state.negotiate.state == GSS_AUTHSENT) {
|
||||
/* add forbid re-use if http-code != 401/407 as a WA only needed for
|
||||
* 401/407 that signal auth failure (empty) otherwise state will be RECV
|
||||
* with current code */
|
||||
if((data->req.httpcode != 401) && (data->req.httpcode != 407))
|
||||
* with current code.
|
||||
* Do not close CONNECT_ONLY connections. */
|
||||
if((data->req.httpcode != 401) && (data->req.httpcode != 407) &&
|
||||
!data->set.connect_only)
|
||||
connclose(conn, "Negotiate transfer completed");
|
||||
Curl_cleanup_negotiate(data);
|
||||
}
|
||||
@@ -1467,7 +1467,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
||||
conn->seek_func = data->set.seek_func; /* restore */
|
||||
conn->seek_client = data->set.seek_client; /* restore */
|
||||
|
||||
if(http == NULL)
|
||||
if(!http)
|
||||
return CURLE_OK;
|
||||
|
||||
if(http->send_buffer) {
|
||||
@@ -1517,9 +1517,9 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
||||
entire operation is complete */
|
||||
!conn->bits.retry &&
|
||||
!data->set.connect_only &&
|
||||
((http->readbytecount +
|
||||
data->req.headerbytecount -
|
||||
data->req.deductheadercount)) <= 0) {
|
||||
(http->readbytecount +
|
||||
data->req.headerbytecount -
|
||||
data->req.deductheadercount) <= 0) {
|
||||
/* If this connection isn't simply closed to be retried, AND nothing was
|
||||
read from the HTTP server (that counts), this can't be right so we
|
||||
return an error here */
|
||||
@@ -1530,7 +1530,6 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
|
||||
* to avoid it include:
|
||||
@@ -1578,6 +1577,7 @@ static CURLcode expect100(struct SessionHandle *data,
|
||||
data->state.expect100header = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1696,6 +1696,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
|
||||
headers = headers->next;
|
||||
}
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@@ -1793,13 +1794,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
switch(conn->negnpn) {
|
||||
case CURL_HTTP_VERSION_2:
|
||||
conn->httpversion = 20; /* we know we're on HTTP/2 now */
|
||||
result = Curl_http2_init(conn);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
result = Curl_http2_setup(conn);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
result = Curl_http2_switched(conn, NULL, 0);
|
||||
if(result)
|
||||
@@ -1809,7 +1803,18 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
/* continue with HTTP/1.1 when explicitly requested */
|
||||
break;
|
||||
default:
|
||||
/* and as fallback */
|
||||
/* Check if user wants to use HTTP/2 with clear TCP*/
|
||||
#ifdef USE_NGHTTP2
|
||||
if(conn->data->set.httpversion ==
|
||||
CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
|
||||
DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
|
||||
conn->httpversion = 20;
|
||||
|
||||
result = Curl_http2_switched(conn, NULL, 0);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1829,6 +1834,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
data->state.first_host = strdup(conn->host.name);
|
||||
if(!data->state.first_host)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
data->state.first_remote_port = conn->remote_port;
|
||||
}
|
||||
http->writebytecount = http->readbytecount = 0;
|
||||
|
||||
@@ -1910,6 +1917,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
if(!conn->allocptr.accept_encoding)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else {
|
||||
Curl_safefree(conn->allocptr.accept_encoding);
|
||||
conn->allocptr.accept_encoding = NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
/* we only consider transfer-encoding magic if libz support is built-in */
|
||||
@@ -2145,7 +2156,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
* file size before we continue this venture in the dark lands of HTTP.
|
||||
*********************************************************************/
|
||||
|
||||
if(data->state.resume_from < 0 ) {
|
||||
if(data->state.resume_from < 0) {
|
||||
/*
|
||||
* This is meant to get the size of the present remote-file by itself.
|
||||
* We don't support this now. Bail out!
|
||||
|
||||
@@ -214,6 +214,7 @@ struct http_conn {
|
||||
them for both cases. */
|
||||
int32_t pause_stream_id; /* stream ID which paused
|
||||
nghttp2_session_mem_recv */
|
||||
size_t drain_total; /* sum of all stream's UrlState.drain */
|
||||
|
||||
/* this is a hash of all individual streams (SessionHandle structs) */
|
||||
struct h2settings settings;
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifdef USE_NGHTTP2
|
||||
#include "curl_printf.h"
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#include "urldata.h"
|
||||
#include "http2.h"
|
||||
@@ -35,8 +34,10 @@
|
||||
#include "conncache.h"
|
||||
#include "url.h"
|
||||
#include "connect.h"
|
||||
#include "strtoofft.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -46,6 +47,18 @@
|
||||
#error too old nghttp2 version, upgrade!
|
||||
#endif
|
||||
|
||||
#if (NGHTTP2_VERSION_NUM > 0x010800)
|
||||
#define NGHTTP2_HAS_HTTP2_STRERROR 1
|
||||
#endif
|
||||
|
||||
#if (NGHTTP2_VERSION_NUM >= 0x010900)
|
||||
/* nghttp2_session_callbacks_set_error_callback is present in nghttp2 1.9.0 or
|
||||
later */
|
||||
#define NGHTTP2_HAS_ERROR_CALLBACK 1
|
||||
#else
|
||||
#define nghttp2_session_callbacks_set_error_callback(x,y)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Curl_http2_init_state() is called when the easy handle is created and
|
||||
* allows for HTTP/2 specific init of state.
|
||||
@@ -155,7 +168,7 @@ void Curl_http2_setup_conn(struct connectdata *conn)
|
||||
* HTTP to HTTP2.
|
||||
*/
|
||||
const struct Curl_handler Curl_handler_http2 = {
|
||||
"HTTP2", /* scheme */
|
||||
"HTTP", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
@@ -175,7 +188,7 @@ const struct Curl_handler Curl_handler_http2 = {
|
||||
};
|
||||
|
||||
const struct Curl_handler Curl_handler_http2_ssl = {
|
||||
"HTTP2", /* scheme */
|
||||
"HTTPS", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
@@ -204,6 +217,34 @@ int Curl_http2_ver(char *p, size_t len)
|
||||
return snprintf(p, len, " nghttp2/%s", h2->version_str);
|
||||
}
|
||||
|
||||
/* HTTP/2 error code to name based on the Error Code Registry.
|
||||
https://tools.ietf.org/html/rfc7540#page-77
|
||||
nghttp2_error_code enums are identical.
|
||||
*/
|
||||
const char *Curl_http2_strerror(uint32_t err) {
|
||||
#ifndef NGHTTP2_HAS_HTTP2_STRERROR
|
||||
const char *str[] = {
|
||||
"NO_ERROR", /* 0x0 */
|
||||
"PROTOCOL_ERROR", /* 0x1 */
|
||||
"INTERNAL_ERROR", /* 0x2 */
|
||||
"FLOW_CONTROL_ERROR", /* 0x3 */
|
||||
"SETTINGS_TIMEOUT", /* 0x4 */
|
||||
"STREAM_CLOSED", /* 0x5 */
|
||||
"FRAME_SIZE_ERROR", /* 0x6 */
|
||||
"REFUSED_STREAM", /* 0x7 */
|
||||
"CANCEL", /* 0x8 */
|
||||
"COMPRESSION_ERROR", /* 0x9 */
|
||||
"CONNECT_ERROR", /* 0xA */
|
||||
"ENHANCE_YOUR_CALM", /* 0xB */
|
||||
"INADEQUATE_SECURITY", /* 0xC */
|
||||
"HTTP_1_1_REQUIRED" /* 0xD */
|
||||
};
|
||||
return (err < sizeof str / sizeof str[0]) ? str[err] : "unknown";
|
||||
#else
|
||||
return nghttp2_http2_strerror(err);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* The implementation of nghttp2_send_callback type. Here we write |data| with
|
||||
* size |length| to the network and return the number of bytes actually
|
||||
@@ -499,6 +540,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
stream->memlen += ncopy;
|
||||
|
||||
data_s->state.drain++;
|
||||
httpc->drain_total++;
|
||||
{
|
||||
/* get the pointer from userp again since it was re-assigned above */
|
||||
struct connectdata *conn_s = (struct connectdata *)userp;
|
||||
@@ -575,6 +617,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
|
||||
stream->memlen += nread;
|
||||
|
||||
data_s->state.drain++;
|
||||
conn->proto.httpc.drain_total++;
|
||||
|
||||
/* if we receive data for another handle, wake that up */
|
||||
if(conn->data != data_s)
|
||||
@@ -594,8 +637,18 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
|
||||
", stream %u\n",
|
||||
len - nread, stream_id));
|
||||
data_s->easy_conn->proto.httpc.pause_stream_id = stream_id;
|
||||
|
||||
return NGHTTP2_ERR_PAUSE;
|
||||
}
|
||||
|
||||
/* pause execution of nghttp2 if we received data for another handle
|
||||
in order to process them first. */
|
||||
if(conn->data != data_s) {
|
||||
data_s->easy_conn->proto.httpc.pause_stream_id = stream_id;
|
||||
|
||||
return NGHTTP2_ERR_PAUSE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -647,9 +700,9 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
|
||||
{
|
||||
struct SessionHandle *data_s;
|
||||
struct HTTP *stream;
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
(void)session;
|
||||
(void)stream_id;
|
||||
(void)userp;
|
||||
|
||||
if(stream_id) {
|
||||
/* get the stream from the hash based on Stream ID, stream ID zero is for
|
||||
@@ -660,14 +713,16 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
|
||||
decided to reject stream (e.g., PUSH_PROMISE). */
|
||||
return 0;
|
||||
}
|
||||
DEBUGF(infof(data_s, "on_stream_close(), error_code = %d, stream %u\n",
|
||||
error_code, stream_id));
|
||||
DEBUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
|
||||
Curl_http2_strerror(error_code), error_code, stream_id));
|
||||
stream = data_s->req.protop;
|
||||
if(!stream)
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
|
||||
stream->error_code = error_code;
|
||||
stream->closed = TRUE;
|
||||
data_s->state.drain++;
|
||||
conn->proto.httpc.drain_total++;
|
||||
|
||||
/* remove the entry from the hash as the stream is now gone */
|
||||
nghttp2_session_set_stream_user_data(session, stream_id, 0);
|
||||
@@ -807,7 +862,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
|
||||
Curl_add_buffer(stream->trailer_recvbuf, &n, sizeof(n));
|
||||
Curl_add_buffer(stream->trailer_recvbuf, name, namelen);
|
||||
Curl_add_buffer(stream->trailer_recvbuf, ":", 1);
|
||||
Curl_add_buffer(stream->trailer_recvbuf, ": ", 2);
|
||||
Curl_add_buffer(stream->trailer_recvbuf, value, valuelen);
|
||||
Curl_add_buffer(stream->trailer_recvbuf, "\r\n\0", 3);
|
||||
|
||||
@@ -824,8 +879,8 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
|
||||
Curl_add_buffer(stream->header_recvbuf, "HTTP/2.0 ", 9);
|
||||
Curl_add_buffer(stream->header_recvbuf, value, valuelen);
|
||||
Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);
|
||||
data_s->state.drain++;
|
||||
/* the space character after the status code is mandatory */
|
||||
Curl_add_buffer(stream->header_recvbuf, " \r\n", 3);
|
||||
/* if we receive data for another handle, wake that up */
|
||||
if(conn->data != data_s)
|
||||
Curl_expire(data_s, 1);
|
||||
@@ -839,10 +894,9 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
received, and this is not pseudo-header field . */
|
||||
/* convert to a HTTP1-style header */
|
||||
Curl_add_buffer(stream->header_recvbuf, name, namelen);
|
||||
Curl_add_buffer(stream->header_recvbuf, ":", 1);
|
||||
Curl_add_buffer(stream->header_recvbuf, ": ", 2);
|
||||
Curl_add_buffer(stream->header_recvbuf, value, valuelen);
|
||||
Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);
|
||||
data_s->state.drain++;
|
||||
/* if we receive data for another handle, wake that up */
|
||||
if(conn->data != data_s)
|
||||
Curl_expire(data_s, 1);
|
||||
@@ -912,6 +966,19 @@ static nghttp2_settings_entry settings[] = {
|
||||
|
||||
#define H2_BUFSIZE 32768
|
||||
|
||||
#ifdef NGHTTP2_HAS_ERROR_CALLBACK
|
||||
static int error_callback(nghttp2_session *session,
|
||||
const char *msg,
|
||||
size_t len,
|
||||
void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
(void)session;
|
||||
infof(conn->data, "http2 error: %.*s\n", len, msg);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize nghttp2 for a Curl connection
|
||||
*/
|
||||
@@ -961,6 +1028,8 @@ CURLcode Curl_http2_init(struct connectdata *conn)
|
||||
/* nghttp2_on_header_callback */
|
||||
nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header);
|
||||
|
||||
nghttp2_session_callbacks_set_error_callback(callbacks, error_callback);
|
||||
|
||||
/* The nghttp2 session is not yet setup, do it */
|
||||
rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn);
|
||||
|
||||
@@ -1019,6 +1088,73 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns nonzero if current HTTP/2 session should be closed.
|
||||
*/
|
||||
static int should_close_session(struct http_conn *httpc) {
|
||||
return httpc->drain_total == 0 && !nghttp2_session_want_read(httpc->h2) &&
|
||||
!nghttp2_session_want_write(httpc->h2);
|
||||
}
|
||||
|
||||
static int h2_session_send(struct SessionHandle *data,
|
||||
nghttp2_session *h2);
|
||||
|
||||
/*
|
||||
* h2_process_pending_input() processes pending input left in
|
||||
* httpc->inbuf. Then, call h2_session_send() to send pending data.
|
||||
* This function returns 0 if it succeeds, or -1 and error code will
|
||||
* be assigned to *err.
|
||||
*/
|
||||
static int h2_process_pending_input(struct SessionHandle *data,
|
||||
struct http_conn *httpc,
|
||||
CURLcode *err) {
|
||||
ssize_t nread;
|
||||
char *inbuf;
|
||||
ssize_t rv;
|
||||
|
||||
nread = httpc->inbuflen - httpc->nread_inbuf;
|
||||
inbuf = httpc->inbuf + httpc->nread_inbuf;
|
||||
|
||||
rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
|
||||
if(rv < 0) {
|
||||
failf(data,
|
||||
"h2_process_pending_input: nghttp2_session_mem_recv() returned "
|
||||
"%d:%s\n", rv, nghttp2_strerror((int)rv));
|
||||
*err = CURLE_RECV_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(nread == rv) {
|
||||
DEBUGF(infof(data,
|
||||
"h2_process_pending_input: All data in connection buffer "
|
||||
"processed\n"));
|
||||
httpc->inbuflen = 0;
|
||||
httpc->nread_inbuf = 0;
|
||||
}
|
||||
else {
|
||||
httpc->nread_inbuf += rv;
|
||||
DEBUGF(infof(data,
|
||||
"h2_process_pending_input: %zu bytes left in connection "
|
||||
"buffer\n",
|
||||
httpc->inbuflen - httpc->nread_inbuf));
|
||||
}
|
||||
|
||||
rv = h2_session_send(data, httpc->h2);
|
||||
if(rv != 0) {
|
||||
*err = CURLE_SEND_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(should_close_session(httpc)) {
|
||||
DEBUGF(infof(data,
|
||||
"h2_process_pending_input: nothing to do in this session\n"));
|
||||
*err = CURLE_HTTP2;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t http2_handle_stream_close(struct connectdata *conn,
|
||||
struct SessionHandle *data,
|
||||
struct HTTP *stream, CURLcode *err) {
|
||||
@@ -1029,13 +1165,35 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
|
||||
if(httpc->pause_stream_id == stream->stream_id) {
|
||||
httpc->pause_stream_id = 0;
|
||||
}
|
||||
|
||||
DEBUGASSERT(httpc->drain_total >= data->state.drain);
|
||||
httpc->drain_total -= data->state.drain;
|
||||
data->state.drain = 0;
|
||||
|
||||
if(httpc->pause_stream_id == 0) {
|
||||
if(h2_process_pending_input(data, httpc, err) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUGASSERT(data->state.drain == 0);
|
||||
|
||||
/* Reset to FALSE to prevent infinite loop in readwrite_data
|
||||
function. */
|
||||
stream->closed = FALSE;
|
||||
if(stream->error_code != NGHTTP2_NO_ERROR) {
|
||||
failf(data, "HTTP/2 stream %u was not closed cleanly: error_code = %d",
|
||||
stream->stream_id, stream->error_code);
|
||||
*err = CURLE_HTTP2;
|
||||
failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %d)",
|
||||
stream->stream_id, Curl_http2_strerror(stream->error_code),
|
||||
stream->error_code);
|
||||
*err = CURLE_HTTP2_STREAM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!stream->bodystarted) {
|
||||
failf(data, "HTTP/2 stream %u was closed cleanly, but before getting "
|
||||
" all response header fields, teated as error",
|
||||
stream->stream_id);
|
||||
*err = CURLE_HTTP2_STREAM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1126,12 +1284,11 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
|
||||
(void)sockindex; /* we always do HTTP2 on sockindex 0 */
|
||||
|
||||
/* If stream is closed, return 0 to signal the http routine to close
|
||||
the connection. We need to handle stream closure here,
|
||||
otherwise, we may be going to read from underlying connection,
|
||||
and gets EAGAIN, and we will get stuck there. */
|
||||
if(stream->memlen == 0 && stream->closed) {
|
||||
return http2_handle_stream_close(conn, data, stream, err);
|
||||
if(should_close_session(httpc)) {
|
||||
DEBUGF(infof(data,
|
||||
"http2_recv: nothing to do in this session\n"));
|
||||
*err = CURLE_HTTP2;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Nullify here because we call nghttp2_session_send() and they
|
||||
@@ -1173,8 +1330,18 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
stream->len = len - stream->memlen;
|
||||
stream->mem = mem;
|
||||
}
|
||||
if(httpc->pause_stream_id == stream->stream_id && !stream->pausedata) {
|
||||
/* We have paused nghttp2, but we have no pause data (see
|
||||
on_data_chunk_recv). */
|
||||
httpc->pause_stream_id = 0;
|
||||
if(h2_process_pending_input(data, httpc, &result) != 0) {
|
||||
*err = result;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(stream->pausedata) {
|
||||
DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
|
||||
nread = MIN(len, stream->pauselen);
|
||||
memcpy(mem, stream->pausedata, nread);
|
||||
|
||||
@@ -1197,7 +1364,10 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
frames, then we have to call it again with 0-length data.
|
||||
Without this, on_stream_close callback will not be called,
|
||||
and stream could be hanged. */
|
||||
nghttp2_session_mem_recv(httpc->h2, NULL, 0);
|
||||
if(h2_process_pending_input(data, httpc, &result) != 0) {
|
||||
*err = result;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
DEBUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n",
|
||||
nread, stream->stream_id));
|
||||
@@ -1230,6 +1400,10 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
if(nread == -1) {
|
||||
if(result != CURLE_AGAIN)
|
||||
failf(data, "Failed receiving HTTP2 data");
|
||||
else if(stream->closed)
|
||||
/* received when the stream was already closed! */
|
||||
return http2_handle_stream_close(conn, data, stream, err);
|
||||
|
||||
*err = result;
|
||||
return -1;
|
||||
}
|
||||
@@ -1278,6 +1452,12 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
*err = CURLE_SEND_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(should_close_session(httpc)) {
|
||||
DEBUGF(infof(data, "http2_recv: nothing to do in this session\n"));
|
||||
*err = CURLE_HTTP2;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(stream->memlen) {
|
||||
ssize_t retlen = stream->memlen;
|
||||
@@ -1291,8 +1471,11 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
DEBUGF(infof(data, "Data returned for PAUSED stream %u\n",
|
||||
stream->stream_id));
|
||||
}
|
||||
else
|
||||
else if(!stream->closed) {
|
||||
DEBUGASSERT(httpc->drain_total >= data->state.drain);
|
||||
httpc->drain_total -= data->state.drain;
|
||||
data->state.drain = 0; /* this stream is hereby drained */
|
||||
}
|
||||
|
||||
return retlen;
|
||||
}
|
||||
@@ -1311,6 +1494,9 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
field list. */
|
||||
#define AUTHORITY_DST_IDX 3
|
||||
|
||||
#define HEADER_OVERFLOW(x) \
|
||||
(x.namelen > (uint16_t)-1 || x.valuelen > (uint16_t)-1 - x.namelen)
|
||||
|
||||
/* return number of received (decrypted) bytes */
|
||||
static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
const void *mem, size_t len, CURLcode *err)
|
||||
@@ -1323,12 +1509,12 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
int rv;
|
||||
struct http_conn *httpc = &conn->proto.httpc;
|
||||
struct HTTP *stream = conn->data->req.protop;
|
||||
nghttp2_nv *nva;
|
||||
nghttp2_nv *nva = NULL;
|
||||
size_t nheader;
|
||||
size_t i;
|
||||
size_t authority_idx;
|
||||
char *hdbuf = (char*)mem;
|
||||
char *end;
|
||||
char *end, *line_end;
|
||||
nghttp2_data_provider data_prd;
|
||||
int32_t stream_id;
|
||||
nghttp2_session *h2 = httpc->h2;
|
||||
@@ -1356,6 +1542,12 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
stream->upload_mem = NULL;
|
||||
stream->upload_len = 0;
|
||||
|
||||
if(should_close_session(httpc)) {
|
||||
DEBUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
|
||||
*err = CURLE_HTTP2;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(stream->upload_left) {
|
||||
/* we are sure that we have more data to send here. Calling the
|
||||
following API will make nghttp2_session_want_write() return
|
||||
@@ -1373,12 +1565,16 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
/* Here, we assume the curl http code generate *correct* HTTP header
|
||||
field block */
|
||||
nheader = 0;
|
||||
for(i = 0; i < len; ++i) {
|
||||
if(hdbuf[i] == 0x0a) {
|
||||
for(i = 1; i < len; ++i) {
|
||||
if(hdbuf[i] == '\n' && hdbuf[i - 1] == '\r') {
|
||||
++nheader;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
/* We counted additional 2 \n in the first and last line. We need 3
|
||||
if(nheader < 2)
|
||||
goto fail;
|
||||
|
||||
/* We counted additional 2 \r\n in the first and last line. We need 3
|
||||
new headers: :method, :path and :scheme. Therefore we need one
|
||||
more space. */
|
||||
nheader += 1;
|
||||
@@ -1387,51 +1583,84 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
*err = CURLE_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Extract :method, :path from request line */
|
||||
end = strchr(hdbuf, ' ');
|
||||
if(!end)
|
||||
line_end = strstr(hdbuf, "\r\n");
|
||||
|
||||
/* Method does not contain spaces */
|
||||
end = memchr(hdbuf, ' ', line_end - hdbuf);
|
||||
if(!end || end == hdbuf)
|
||||
goto fail;
|
||||
nva[0].name = (unsigned char *)":method";
|
||||
nva[0].namelen = (uint16_t)strlen((char *)nva[0].name);
|
||||
nva[0].namelen = strlen((char *)nva[0].name);
|
||||
nva[0].value = (unsigned char *)hdbuf;
|
||||
nva[0].valuelen = (uint16_t)(end - hdbuf);
|
||||
nva[0].valuelen = (size_t)(end - hdbuf);
|
||||
nva[0].flags = NGHTTP2_NV_FLAG_NONE;
|
||||
if(HEADER_OVERFLOW(nva[0])) {
|
||||
failf(conn->data, "Failed sending HTTP request: Header overflow");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hdbuf = end + 1;
|
||||
|
||||
end = strchr(hdbuf, ' ');
|
||||
if(!end)
|
||||
/* Path may contain spaces so scan backwards */
|
||||
end = NULL;
|
||||
for(i = (size_t)(line_end - hdbuf); i; --i) {
|
||||
if(hdbuf[i - 1] == ' ') {
|
||||
end = &hdbuf[i - 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!end || end == hdbuf)
|
||||
goto fail;
|
||||
nva[1].name = (unsigned char *)":path";
|
||||
nva[1].namelen = (uint16_t)strlen((char *)nva[1].name);
|
||||
nva[1].namelen = strlen((char *)nva[1].name);
|
||||
nva[1].value = (unsigned char *)hdbuf;
|
||||
nva[1].valuelen = (uint16_t)(end - hdbuf);
|
||||
nva[1].valuelen = (size_t)(end - hdbuf);
|
||||
nva[1].flags = NGHTTP2_NV_FLAG_NONE;
|
||||
if(HEADER_OVERFLOW(nva[1])) {
|
||||
failf(conn->data, "Failed sending HTTP request: Header overflow");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hdbuf = end + 1;
|
||||
|
||||
end = line_end;
|
||||
nva[2].name = (unsigned char *)":scheme";
|
||||
nva[2].namelen = (uint16_t)strlen((char *)nva[2].name);
|
||||
nva[2].namelen = strlen((char *)nva[2].name);
|
||||
if(conn->handler->flags & PROTOPT_SSL)
|
||||
nva[2].value = (unsigned char *)"https";
|
||||
else
|
||||
nva[2].value = (unsigned char *)"http";
|
||||
nva[2].valuelen = (uint16_t)strlen((char *)nva[2].value);
|
||||
nva[2].valuelen = strlen((char *)nva[2].value);
|
||||
nva[2].flags = NGHTTP2_NV_FLAG_NONE;
|
||||
|
||||
hdbuf = strchr(hdbuf, 0x0a);
|
||||
if(!hdbuf)
|
||||
if(HEADER_OVERFLOW(nva[2])) {
|
||||
failf(conn->data, "Failed sending HTTP request: Header overflow");
|
||||
goto fail;
|
||||
++hdbuf;
|
||||
}
|
||||
|
||||
authority_idx = 0;
|
||||
|
||||
i = 3;
|
||||
while(i < nheader) {
|
||||
size_t hlen;
|
||||
int skip = 0;
|
||||
end = strchr(hdbuf, ':');
|
||||
if(!end)
|
||||
|
||||
hdbuf = line_end + 2;
|
||||
|
||||
line_end = strstr(hdbuf, "\r\n");
|
||||
if(line_end == hdbuf)
|
||||
goto fail;
|
||||
|
||||
/* header continuation lines are not supported */
|
||||
if(*hdbuf == ' ' || *hdbuf == '\t')
|
||||
goto fail;
|
||||
|
||||
for(end = hdbuf; end < line_end && *end != ':'; ++end)
|
||||
;
|
||||
if(end == hdbuf || end == line_end)
|
||||
goto fail;
|
||||
hlen = end - hdbuf;
|
||||
|
||||
if(hlen == 10 && Curl_raw_nequal("connection", hdbuf, 10)) {
|
||||
/* skip Connection: headers! */
|
||||
skip = 1;
|
||||
@@ -1440,21 +1669,24 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
else if(hlen == 4 && Curl_raw_nequal("host", hdbuf, 4)) {
|
||||
authority_idx = i;
|
||||
nva[i].name = (unsigned char *)":authority";
|
||||
nva[i].namelen = (uint16_t)strlen((char *)nva[i].name);
|
||||
nva[i].namelen = strlen((char *)nva[i].name);
|
||||
}
|
||||
else {
|
||||
nva[i].name = (unsigned char *)hdbuf;
|
||||
nva[i].namelen = (uint16_t)(end - hdbuf);
|
||||
nva[i].namelen = (size_t)(end - hdbuf);
|
||||
}
|
||||
hdbuf = end + 1;
|
||||
for(; *hdbuf == ' '; ++hdbuf);
|
||||
end = strchr(hdbuf, 0x0d);
|
||||
if(!end)
|
||||
goto fail;
|
||||
while(*hdbuf == ' ' || *hdbuf == '\t')
|
||||
++hdbuf;
|
||||
end = line_end;
|
||||
if(!skip) {
|
||||
nva[i].value = (unsigned char *)hdbuf;
|
||||
nva[i].valuelen = (uint16_t)(end - hdbuf);
|
||||
nva[i].valuelen = (size_t)(end - hdbuf);
|
||||
nva[i].flags = NGHTTP2_NV_FLAG_NONE;
|
||||
if(HEADER_OVERFLOW(nva[i])) {
|
||||
failf(conn->data, "Failed sending HTTP request: Header overflow");
|
||||
goto fail;
|
||||
}
|
||||
/* Inspect Content-Length header field and retrieve the request
|
||||
entity length so that we can set END_STREAM to the last DATA
|
||||
frame. */
|
||||
@@ -1462,7 +1694,13 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
Curl_raw_nequal("content-length", (char*)nva[i].name, 14)) {
|
||||
size_t j;
|
||||
stream->upload_left = 0;
|
||||
if(!nva[i].valuelen)
|
||||
goto fail;
|
||||
for(j = 0; j < nva[i].valuelen; ++j) {
|
||||
if(nva[i].value[j] < '0' || nva[i].value[j] > '9')
|
||||
goto fail;
|
||||
if(stream->upload_left >= CURL_OFF_T_MAX / 10)
|
||||
goto fail;
|
||||
stream->upload_left *= 10;
|
||||
stream->upload_left += nva[i].value[j] - '0';
|
||||
}
|
||||
@@ -1473,7 +1711,6 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
}
|
||||
++i;
|
||||
}
|
||||
hdbuf = end + 2;
|
||||
}
|
||||
|
||||
/* :authority must come before non-pseudo header fields */
|
||||
@@ -1485,6 +1722,29 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
nva[i] = authority;
|
||||
}
|
||||
|
||||
/* Warn stream may be rejected if cumulative length of headers is too large.
|
||||
It appears nghttp2 will not send a header frame larger than 64KB. */
|
||||
{
|
||||
size_t acc = 0;
|
||||
const size_t max_acc = 60000; /* <64KB to account for some overhead */
|
||||
|
||||
for(i = 0; i < nheader; ++i) {
|
||||
if(nva[i].namelen > max_acc - acc)
|
||||
break;
|
||||
acc += nva[i].namelen;
|
||||
|
||||
if(nva[i].valuelen > max_acc - acc)
|
||||
break;
|
||||
acc += nva[i].valuelen;
|
||||
}
|
||||
|
||||
if(i != nheader) {
|
||||
infof(conn->data, "http2_send: Warning: The cumulative length of all "
|
||||
"headers exceeds %zu bytes and that could cause the "
|
||||
"stream to be rejected.\n", max_acc);
|
||||
}
|
||||
}
|
||||
|
||||
h2_pri_spec(conn->data, &pri_spec);
|
||||
|
||||
switch(conn->data->set.httpreq) {
|
||||
@@ -1522,6 +1782,12 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(should_close_session(httpc)) {
|
||||
DEBUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
|
||||
*err = CURLE_HTTP2;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(stream->stream_id != -1) {
|
||||
/* If whole HEADERS frame was sent off to the underlying socket,
|
||||
the nghttp2 library calls data_source_read_callback. But only
|
||||
@@ -1575,6 +1841,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
|
||||
httpc->nread_inbuf = 0;
|
||||
|
||||
httpc->pause_stream_id = 0;
|
||||
httpc->drain_total = 0;
|
||||
|
||||
conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
|
||||
conn->httpversion = 20;
|
||||
@@ -1682,6 +1949,12 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
|
||||
return CURLE_HTTP2;
|
||||
}
|
||||
|
||||
if(should_close_session(httpc)) {
|
||||
DEBUGF(infof(data,
|
||||
"nghttp2_session_send(): nothing to do in this session\n"));
|
||||
return CURLE_HTTP2;
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
*/
|
||||
int Curl_http2_ver(char *p, size_t len);
|
||||
|
||||
const char *Curl_http2_strerror(uint32_t err);
|
||||
|
||||
CURLcode Curl_http2_init(struct connectdata *conn);
|
||||
void Curl_http2_init_state(struct UrlState *state);
|
||||
void Curl_http2_init_userset(struct UserDefined *set);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -80,7 +80,7 @@ static bool Curl_isxdigit(char digit)
|
||||
{
|
||||
return ( (digit >= 0x30 && digit <= 0x39) /* 0-9 */
|
||||
|| (digit >= 0x41 && digit <= 0x46) /* A-F */
|
||||
|| (digit >= 0x61 && digit <= 0x66) /* a-f */ ) ? TRUE : FALSE;
|
||||
|| (digit >= 0x61 && digit <= 0x66) /* a-f */) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
void Curl_httpchunk_init(struct connectdata *conn)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -26,11 +26,10 @@
|
||||
|
||||
#include "urldata.h"
|
||||
#include "rawstr.h"
|
||||
#include "curl_sasl.h"
|
||||
#include "vauth/vauth.h"
|
||||
#include "http_digest.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -65,7 +64,7 @@ CURLcode Curl_input_digest(struct connectdata *conn,
|
||||
while(*header && ISSPACE(*header))
|
||||
header++;
|
||||
|
||||
return Curl_sasl_decode_digest_http_message(header, digest);
|
||||
return Curl_auth_decode_digest_http_message(header, digest);
|
||||
}
|
||||
|
||||
CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
@@ -152,7 +151,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
if(!path)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
result = Curl_sasl_create_digest_http_message(data, userp, passwdp, request,
|
||||
result = Curl_auth_create_digest_http_message(data, userp, passwdp, request,
|
||||
path, digest, &response, &len);
|
||||
free(path);
|
||||
if(result)
|
||||
@@ -172,8 +171,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
|
||||
void Curl_digest_cleanup(struct SessionHandle *data)
|
||||
{
|
||||
Curl_sasl_digest_cleanup(&data->state.digest);
|
||||
Curl_sasl_digest_cleanup(&data->state.proxydigest);
|
||||
Curl_auth_digest_cleanup(&data->state.digest);
|
||||
Curl_auth_digest_cleanup(&data->state.proxydigest);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -22,19 +22,16 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
|
||||
#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "curl_gssapi.h"
|
||||
#include "rawstr.h"
|
||||
#include "curl_base64.h"
|
||||
#include "http_negotiate.h"
|
||||
#include "curl_sasl.h"
|
||||
#include "url.h"
|
||||
#include "curl_printf.h"
|
||||
#include "vauth/vauth.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -42,136 +39,77 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
||||
const char *header)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct negotiatedata *neg_ctx = proxy?&data->state.proxyneg:
|
||||
&data->state.negotiate;
|
||||
OM_uint32 major_status, minor_status, discard_st;
|
||||
gss_buffer_desc spn_token = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
|
||||
size_t len;
|
||||
size_t rawlen = 0;
|
||||
CURLcode result;
|
||||
|
||||
if(neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) {
|
||||
/* We finished successfully our part of authentication, but server
|
||||
* rejected it (since we're again here). Exit with an error since we
|
||||
* can't invent anything better */
|
||||
Curl_cleanup_negotiate(data);
|
||||
return CURLE_LOGIN_DENIED;
|
||||
/* Point to the username, password, service and host */
|
||||
const char *userp;
|
||||
const char *passwdp;
|
||||
const char *service;
|
||||
const char *host;
|
||||
|
||||
/* Point to the correct struct with this */
|
||||
struct negotiatedata *neg_ctx;
|
||||
|
||||
if(proxy) {
|
||||
userp = conn->proxyuser;
|
||||
passwdp = conn->proxypasswd;
|
||||
service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
|
||||
data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
|
||||
host = conn->proxy.name;
|
||||
neg_ctx = &data->state.proxyneg;
|
||||
}
|
||||
else {
|
||||
userp = conn->user;
|
||||
passwdp = conn->passwd;
|
||||
service = data->set.str[STRING_SERVICE_NAME] ?
|
||||
data->set.str[STRING_SERVICE_NAME] : "HTTP";
|
||||
host = conn->host.name;
|
||||
neg_ctx = &data->state.negotiate;
|
||||
}
|
||||
|
||||
if(!neg_ctx->server_name) {
|
||||
/* Generate our SPN */
|
||||
char *spn = Curl_sasl_build_gssapi_spn(
|
||||
proxy ? data->set.str[STRING_PROXY_SERVICE_NAME] :
|
||||
data->set.str[STRING_SERVICE_NAME],
|
||||
proxy ? conn->proxy.name : conn->host.name);
|
||||
if(!spn)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
/* Not set means empty */
|
||||
if(!userp)
|
||||
userp = "";
|
||||
|
||||
/* Populate the SPN structure */
|
||||
spn_token.value = spn;
|
||||
spn_token.length = strlen(spn);
|
||||
|
||||
/* Import the SPN */
|
||||
major_status = gss_import_name(&minor_status, &spn_token,
|
||||
GSS_C_NT_HOSTBASED_SERVICE,
|
||||
&neg_ctx->server_name);
|
||||
if(GSS_ERROR(major_status)) {
|
||||
Curl_gss_log_error(data, minor_status, "gss_import_name() failed: ");
|
||||
|
||||
free(spn);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
free(spn);
|
||||
}
|
||||
if(!passwdp)
|
||||
passwdp = "";
|
||||
|
||||
/* Obtain the input token, if any */
|
||||
header += strlen("Negotiate");
|
||||
while(*header && ISSPACE(*header))
|
||||
header++;
|
||||
|
||||
len = strlen(header);
|
||||
if(len > 0) {
|
||||
result = Curl_base64_decode(header, (unsigned char **)&input_token.value,
|
||||
&rawlen);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(!rawlen) {
|
||||
infof(data, "Negotiate handshake failure (empty challenge message)\n");
|
||||
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
if(!len) {
|
||||
/* Is this the first call in a new negotiation? */
|
||||
if(neg_ctx->context) {
|
||||
/* The server rejected our authentication and hasn't suppled any more
|
||||
negotiation mechanisms */
|
||||
return CURLE_LOGIN_DENIED;
|
||||
}
|
||||
|
||||
input_token.length = rawlen;
|
||||
|
||||
DEBUGASSERT(input_token.value != NULL);
|
||||
}
|
||||
|
||||
major_status = Curl_gss_init_sec_context(data,
|
||||
&minor_status,
|
||||
&neg_ctx->context,
|
||||
neg_ctx->server_name,
|
||||
&Curl_spnego_mech_oid,
|
||||
GSS_C_NO_CHANNEL_BINDINGS,
|
||||
&input_token,
|
||||
&output_token,
|
||||
TRUE,
|
||||
NULL);
|
||||
Curl_safefree(input_token.value);
|
||||
|
||||
neg_ctx->status = major_status;
|
||||
if(GSS_ERROR(major_status)) {
|
||||
if(output_token.value)
|
||||
gss_release_buffer(&discard_st, &output_token);
|
||||
Curl_gss_log_error(conn->data, minor_status,
|
||||
"gss_init_sec_context() failed: ");
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(!output_token.value || !output_token.length) {
|
||||
if(output_token.value)
|
||||
gss_release_buffer(&discard_st, &output_token);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
neg_ctx->output_token = output_token;
|
||||
|
||||
return CURLE_OK;
|
||||
/* Initilise the security context and decode our challenge */
|
||||
return Curl_auth_decode_spnego_message(data, userp, passwdp, service, host,
|
||||
header, neg_ctx);
|
||||
}
|
||||
|
||||
CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
|
||||
{
|
||||
struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
|
||||
struct negotiatedata *neg_ctx = proxy ? &conn->data->state.proxyneg :
|
||||
&conn->data->state.negotiate;
|
||||
char *encoded = NULL;
|
||||
char *base64 = NULL;
|
||||
size_t len = 0;
|
||||
char *userp;
|
||||
CURLcode result;
|
||||
OM_uint32 discard_st;
|
||||
|
||||
result = Curl_base64_encode(conn->data,
|
||||
neg_ctx->output_token.value,
|
||||
neg_ctx->output_token.length,
|
||||
&encoded, &len);
|
||||
if(result) {
|
||||
gss_release_buffer(&discard_st, &neg_ctx->output_token);
|
||||
neg_ctx->output_token.value = NULL;
|
||||
neg_ctx->output_token.length = 0;
|
||||
result = Curl_auth_create_spnego_message(conn->data, neg_ctx, &base64, &len);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
if(!encoded || !len) {
|
||||
gss_release_buffer(&discard_st, &neg_ctx->output_token);
|
||||
neg_ctx->output_token.value = NULL;
|
||||
neg_ctx->output_token.length = 0;
|
||||
return CURLE_REMOTE_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
|
||||
encoded);
|
||||
base64);
|
||||
|
||||
if(proxy) {
|
||||
Curl_safefree(conn->allocptr.proxyuserpwd);
|
||||
conn->allocptr.proxyuserpwd = userp;
|
||||
@@ -181,30 +119,15 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
|
||||
conn->allocptr.userpwd = userp;
|
||||
}
|
||||
|
||||
free(encoded);
|
||||
free(base64);
|
||||
|
||||
return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
|
||||
}
|
||||
|
||||
static void cleanup(struct negotiatedata *neg_ctx)
|
||||
{
|
||||
OM_uint32 minor_status;
|
||||
if(neg_ctx->context != GSS_C_NO_CONTEXT)
|
||||
gss_delete_sec_context(&minor_status, &neg_ctx->context, GSS_C_NO_BUFFER);
|
||||
|
||||
if(neg_ctx->output_token.value)
|
||||
gss_release_buffer(&minor_status, &neg_ctx->output_token);
|
||||
|
||||
if(neg_ctx->server_name != GSS_C_NO_NAME)
|
||||
gss_release_name(&minor_status, &neg_ctx->server_name);
|
||||
|
||||
memset(neg_ctx, 0, sizeof(*neg_ctx));
|
||||
}
|
||||
|
||||
void Curl_cleanup_negotiate(struct SessionHandle *data)
|
||||
{
|
||||
cleanup(&data->state.negotiate);
|
||||
cleanup(&data->state.proxyneg);
|
||||
Curl_auth_spnego_cleanup(&data->state.negotiate);
|
||||
Curl_auth_spnego_cleanup(&data->state.proxyneg);
|
||||
}
|
||||
|
||||
#endif /* HAVE_GSSAPI && !CURL_DISABLE_HTTP && USE_SPNEGO */
|
||||
#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
|
||||
|
||||
@@ -33,10 +33,6 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
|
||||
|
||||
void Curl_cleanup_negotiate(struct SessionHandle *data);
|
||||
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
#define GSS_ERROR(status) (status & 0x80000000)
|
||||
#endif
|
||||
|
||||
#endif /* USE_SPNEGO */
|
||||
|
||||
#endif /* HEADER_CURL_HTTP_NEGOTIATE_H */
|
||||
|
||||
@@ -1,302 +0,0 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, 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.haxx.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.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
|
||||
#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "rawstr.h"
|
||||
#include "warnless.h"
|
||||
#include "curl_base64.h"
|
||||
#include "curl_sasl.h"
|
||||
#include "http_negotiate.h"
|
||||
#include "curl_multibyte.h"
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
||||
const char *header)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
BYTE *input_token = NULL;
|
||||
SecBufferDesc out_buff_desc;
|
||||
SecBuffer out_sec_buff;
|
||||
SecBufferDesc in_buff_desc;
|
||||
SecBuffer in_sec_buff;
|
||||
SECURITY_STATUS status;
|
||||
unsigned long attrs;
|
||||
TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
|
||||
size_t len = 0, input_token_len = 0;
|
||||
CURLcode result;
|
||||
|
||||
/* Point to the username and password */
|
||||
const char *userp;
|
||||
const char *passwdp;
|
||||
|
||||
/* Point to the correct struct with this */
|
||||
struct negotiatedata *neg_ctx;
|
||||
|
||||
if(proxy) {
|
||||
userp = conn->proxyuser;
|
||||
passwdp = conn->proxypasswd;
|
||||
neg_ctx = &data->state.proxyneg;
|
||||
}
|
||||
else {
|
||||
userp = conn->user;
|
||||
passwdp = conn->passwd;
|
||||
neg_ctx = &data->state.negotiate;
|
||||
}
|
||||
|
||||
/* Not set means empty */
|
||||
if(!userp)
|
||||
userp = "";
|
||||
|
||||
if(!passwdp)
|
||||
passwdp = "";
|
||||
|
||||
if(neg_ctx->context && neg_ctx->status == SEC_E_OK) {
|
||||
/* We finished successfully our part of authentication, but server
|
||||
* rejected it (since we're again here). Exit with an error since we
|
||||
* can't invent anything better */
|
||||
Curl_cleanup_negotiate(data);
|
||||
return CURLE_LOGIN_DENIED;
|
||||
}
|
||||
|
||||
if(!neg_ctx->server_name) {
|
||||
/* Check proxy auth requested but no given proxy name */
|
||||
if(proxy && !conn->proxy.name)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
/* Generate our SPN */
|
||||
neg_ctx->server_name = Curl_sasl_build_spn(
|
||||
proxy ? data->set.str[STRING_PROXY_SERVICE_NAME] :
|
||||
data->set.str[STRING_SERVICE_NAME],
|
||||
proxy ? conn->proxy.name : conn->host.name);
|
||||
if(!neg_ctx->server_name)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(!neg_ctx->output_token) {
|
||||
PSecPkgInfo SecurityPackage;
|
||||
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
|
||||
TEXT(SP_NAME_NEGOTIATE),
|
||||
&SecurityPackage);
|
||||
if(status != SEC_E_OK)
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
|
||||
/* Allocate input and output buffers according to the max token size
|
||||
as indicated by the security package */
|
||||
neg_ctx->token_max = SecurityPackage->cbMaxToken;
|
||||
neg_ctx->output_token = malloc(neg_ctx->token_max);
|
||||
s_pSecFn->FreeContextBuffer(SecurityPackage);
|
||||
}
|
||||
|
||||
/* Obtain the input token, if any */
|
||||
header += strlen("Negotiate");
|
||||
while(*header && ISSPACE(*header))
|
||||
header++;
|
||||
|
||||
len = strlen(header);
|
||||
if(!len) {
|
||||
/* Is this the first call in a new negotiation? */
|
||||
if(neg_ctx->context) {
|
||||
/* The server rejected our authentication and hasn't suppled any more
|
||||
negotiation mechanisms */
|
||||
return CURLE_LOGIN_DENIED;
|
||||
}
|
||||
|
||||
/* We have to acquire credentials and allocate memory for the context */
|
||||
neg_ctx->credentials = malloc(sizeof(CredHandle));
|
||||
neg_ctx->context = malloc(sizeof(CtxtHandle));
|
||||
|
||||
if(!neg_ctx->credentials || !neg_ctx->context)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(userp && *userp) {
|
||||
/* Populate our identity structure */
|
||||
result = Curl_create_sspi_identity(userp, passwdp, &neg_ctx->identity);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Allow proper cleanup of the identity structure */
|
||||
neg_ctx->p_identity = &neg_ctx->identity;
|
||||
}
|
||||
else
|
||||
/* Use the current Windows user */
|
||||
neg_ctx->p_identity = NULL;
|
||||
|
||||
/* Acquire our credientials handle */
|
||||
neg_ctx->status =
|
||||
s_pSecFn->AcquireCredentialsHandle(NULL,
|
||||
(TCHAR *) TEXT(SP_NAME_NEGOTIATE),
|
||||
SECPKG_CRED_OUTBOUND, NULL,
|
||||
neg_ctx->p_identity, NULL, NULL,
|
||||
neg_ctx->credentials, &expiry);
|
||||
if(neg_ctx->status != SEC_E_OK)
|
||||
return CURLE_LOGIN_DENIED;
|
||||
}
|
||||
else {
|
||||
result = Curl_base64_decode(header,
|
||||
(unsigned char **)&input_token,
|
||||
&input_token_len);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(!input_token_len) {
|
||||
infof(data,
|
||||
"Negotiate handshake failure (empty challenge message)\n");
|
||||
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup the "output" security buffer */
|
||||
out_buff_desc.ulVersion = SECBUFFER_VERSION;
|
||||
out_buff_desc.cBuffers = 1;
|
||||
out_buff_desc.pBuffers = &out_sec_buff;
|
||||
out_sec_buff.BufferType = SECBUFFER_TOKEN;
|
||||
out_sec_buff.pvBuffer = neg_ctx->output_token;
|
||||
out_sec_buff.cbBuffer = curlx_uztoul(neg_ctx->token_max);
|
||||
|
||||
/* Setup the "input" security buffer if present */
|
||||
if(input_token) {
|
||||
in_buff_desc.ulVersion = SECBUFFER_VERSION;
|
||||
in_buff_desc.cBuffers = 1;
|
||||
in_buff_desc.pBuffers = &in_sec_buff;
|
||||
in_sec_buff.BufferType = SECBUFFER_TOKEN;
|
||||
in_sec_buff.pvBuffer = input_token;
|
||||
in_sec_buff.cbBuffer = curlx_uztoul(input_token_len);
|
||||
}
|
||||
|
||||
/* Generate our message */
|
||||
neg_ctx->status = s_pSecFn->InitializeSecurityContext(
|
||||
neg_ctx->credentials,
|
||||
input_token ? neg_ctx->context : NULL,
|
||||
neg_ctx->server_name,
|
||||
ISC_REQ_CONFIDENTIALITY,
|
||||
0,
|
||||
SECURITY_NATIVE_DREP,
|
||||
input_token ? &in_buff_desc : NULL,
|
||||
0,
|
||||
neg_ctx->context,
|
||||
&out_buff_desc,
|
||||
&attrs,
|
||||
&expiry);
|
||||
|
||||
free(input_token);
|
||||
|
||||
if(GSS_ERROR(neg_ctx->status))
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(neg_ctx->status == SEC_I_COMPLETE_NEEDED ||
|
||||
neg_ctx->status == SEC_I_COMPLETE_AND_CONTINUE) {
|
||||
neg_ctx->status = s_pSecFn->CompleteAuthToken(neg_ctx->context,
|
||||
&out_buff_desc);
|
||||
if(GSS_ERROR(neg_ctx->status))
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
|
||||
neg_ctx->output_token_length = out_sec_buff.cbBuffer;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
|
||||
{
|
||||
struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
|
||||
&conn->data->state.negotiate;
|
||||
char *encoded = NULL;
|
||||
size_t len = 0;
|
||||
char *userp;
|
||||
CURLcode result;
|
||||
|
||||
result = Curl_base64_encode(conn->data,
|
||||
(const char*)neg_ctx->output_token,
|
||||
neg_ctx->output_token_length,
|
||||
&encoded, &len);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(!len)
|
||||
return CURLE_REMOTE_ACCESS_DENIED;
|
||||
|
||||
userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
|
||||
encoded);
|
||||
|
||||
if(proxy) {
|
||||
Curl_safefree(conn->allocptr.proxyuserpwd);
|
||||
conn->allocptr.proxyuserpwd = userp;
|
||||
}
|
||||
else {
|
||||
Curl_safefree(conn->allocptr.userpwd);
|
||||
conn->allocptr.userpwd = userp;
|
||||
}
|
||||
|
||||
free(encoded);
|
||||
|
||||
return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
|
||||
}
|
||||
|
||||
static void cleanup(struct negotiatedata *neg_ctx)
|
||||
{
|
||||
/* Free our security context */
|
||||
if(neg_ctx->context) {
|
||||
s_pSecFn->DeleteSecurityContext(neg_ctx->context);
|
||||
free(neg_ctx->context);
|
||||
neg_ctx->context = NULL;
|
||||
}
|
||||
|
||||
/* Free our credentials handle */
|
||||
if(neg_ctx->credentials) {
|
||||
s_pSecFn->FreeCredentialsHandle(neg_ctx->credentials);
|
||||
free(neg_ctx->credentials);
|
||||
neg_ctx->credentials = NULL;
|
||||
}
|
||||
|
||||
/* Free our identity */
|
||||
Curl_sspi_free_identity(neg_ctx->p_identity);
|
||||
neg_ctx->p_identity = NULL;
|
||||
|
||||
/* Free the SPN and output token */
|
||||
Curl_safefree(neg_ctx->server_name);
|
||||
Curl_safefree(neg_ctx->output_token);
|
||||
|
||||
/* Reset any variables */
|
||||
neg_ctx->token_max = 0;
|
||||
}
|
||||
|
||||
void Curl_cleanup_negotiate(struct SessionHandle *data)
|
||||
{
|
||||
cleanup(&data->state.negotiate);
|
||||
cleanup(&data->state.proxyneg);
|
||||
}
|
||||
|
||||
#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
|
||||
|
||||
#endif /* USE_WINDOWS_SSPI */
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -28,7 +28,7 @@
|
||||
* NTLM details:
|
||||
*
|
||||
* http://davenport.sourceforge.net/ntlm.html
|
||||
* http://www.innovation.ch/java/ntlm.html
|
||||
* https://www.innovation.ch/java/ntlm.html
|
||||
*/
|
||||
|
||||
#define DEBUG_ME 0
|
||||
@@ -36,12 +36,10 @@
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "rawstr.h"
|
||||
#include "curl_ntlm.h"
|
||||
#include "curl_ntlm_msgs.h"
|
||||
#include "http_ntlm.h"
|
||||
#include "curl_ntlm_wb.h"
|
||||
#include "curl_sasl.h"
|
||||
#include "vauth/vauth.h"
|
||||
#include "url.h"
|
||||
#include "curl_printf.h"
|
||||
|
||||
#if defined(USE_NSS)
|
||||
#include "vtls/nssg.h"
|
||||
@@ -49,7 +47,8 @@
|
||||
#include "curl_sspi.h"
|
||||
#endif
|
||||
|
||||
/* The last #include files should be: */
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -77,7 +76,7 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
|
||||
header++;
|
||||
|
||||
if(*header) {
|
||||
result = Curl_sasl_decode_ntlm_type2_message(conn->data, header, ntlm);
|
||||
result = Curl_auth_decode_ntlm_type2_message(conn->data, header, ntlm);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
@@ -171,7 +170,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
|
||||
case NTLMSTATE_TYPE1:
|
||||
default: /* for the weird cases we (re)start here */
|
||||
/* Create a type-1 message */
|
||||
result = Curl_sasl_create_ntlm_type1_message(userp, passwdp, ntlm, &base64,
|
||||
result = Curl_auth_create_ntlm_type1_message(userp, passwdp, ntlm, &base64,
|
||||
&len);
|
||||
if(result)
|
||||
return result;
|
||||
@@ -191,7 +190,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
|
||||
|
||||
case NTLMSTATE_TYPE2:
|
||||
/* We already received the type-2 message, create a type-3 message */
|
||||
result = Curl_sasl_create_ntlm_type3_message(conn->data, userp, passwdp,
|
||||
result = Curl_auth_create_ntlm_type3_message(conn->data, userp, passwdp,
|
||||
ntlm, &base64, &len);
|
||||
if(result)
|
||||
return result;
|
||||
@@ -228,8 +227,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
|
||||
|
||||
void Curl_http_ntlm_cleanup(struct connectdata *conn)
|
||||
{
|
||||
Curl_sasl_ntlm_cleanup(&conn->ntlm);
|
||||
Curl_sasl_ntlm_cleanup(&conn->proxyntlm);
|
||||
Curl_auth_ntlm_cleanup(&conn->ntlm);
|
||||
Curl_auth_ntlm_cleanup(&conn->proxyntlm);
|
||||
|
||||
#if defined(NTLM_WB_ENABLED)
|
||||
Curl_ntlm_wb_cleanup(conn);
|
||||
@@ -35,11 +35,11 @@
|
||||
#include "progress.h"
|
||||
#include "non-ascii.h"
|
||||
#include "connect.h"
|
||||
#include "curl_printf.h"
|
||||
#include "curlx.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
CURLcode Curl_proxy_connect(struct connectdata *conn)
|
||||
@@ -49,6 +49,8 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
|
||||
/* for [protocol] tunneled through HTTP proxy */
|
||||
struct HTTP http_proxy;
|
||||
void *prot_save;
|
||||
const char *hostname;
|
||||
int remote_port;
|
||||
CURLcode result;
|
||||
|
||||
/* BLOCKING */
|
||||
@@ -67,8 +69,16 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
|
||||
memset(&http_proxy, 0, sizeof(http_proxy));
|
||||
conn->data->req.protop = &http_proxy;
|
||||
connkeep(conn, "HTTP proxy CONNECT");
|
||||
result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
|
||||
conn->host.name, conn->remote_port, FALSE);
|
||||
if(conn->bits.conn_to_host)
|
||||
hostname = conn->conn_to_host.name;
|
||||
else
|
||||
hostname = conn->host.name;
|
||||
if(conn->bits.conn_to_port)
|
||||
remote_port = conn->conn_to_port;
|
||||
else
|
||||
remote_port = conn->remote_port;
|
||||
result = Curl_proxyCONNECT(conn, FIRSTSOCKET, hostname,
|
||||
remote_port, FALSE);
|
||||
conn->data->req.protop = prot_save;
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
@@ -153,9 +163,14 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
const char *useragent="";
|
||||
const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ?
|
||||
"1.0" : "1.1";
|
||||
char *hostheader= /* host:port with IPv6 support */
|
||||
aprintf("%s%s%s:%hu", conn->bits.ipv6_ip?"[":"",
|
||||
hostname, conn->bits.ipv6_ip?"]":"",
|
||||
bool ipv6_ip = conn->bits.ipv6_ip;
|
||||
char *hostheader;
|
||||
|
||||
/* the hostname may be different */
|
||||
if(hostname != conn->host.name)
|
||||
ipv6_ip = (strchr(hostname, ':') != NULL);
|
||||
hostheader= /* host:port with IPv6 support */
|
||||
aprintf("%s%s%s:%hu", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
|
||||
remote_port);
|
||||
if(!hostheader) {
|
||||
Curl_add_buffer_free(req_buffer);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -53,10 +53,9 @@
|
||||
#include "inet_ntop.h"
|
||||
#include "strequal.h"
|
||||
#include "if2ip.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
@@ -80,10 +80,10 @@
|
||||
#include "rawstr.h"
|
||||
#include "curl_sasl.h"
|
||||
#include "warnless.h"
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/* Local API functions */
|
||||
@@ -364,7 +364,7 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
|
||||
a space and optionally some text as per RFC-3501 for the AUTHENTICATE and
|
||||
APPEND commands and as outlined in Section 4. Examples of RFC-4959 but
|
||||
some e-mail servers ignore this and only send a single + instead. */
|
||||
if(!imap->custom && ((len == 3 && !memcmp("+", line, 1)) ||
|
||||
if(imap && !imap->custom && ((len == 3 && !memcmp("+", line, 1)) ||
|
||||
(len >= 2 && !memcmp("+ ", line, 2)))) {
|
||||
switch(imapc->state) {
|
||||
/* States which are interested in continuation responses */
|
||||
@@ -1020,9 +1020,10 @@ static CURLcode imap_state_login_resp(struct connectdata *conn,
|
||||
return result;
|
||||
}
|
||||
|
||||
/* For LIST responses */
|
||||
static CURLcode imap_state_list_resp(struct connectdata *conn, int imapcode,
|
||||
imapstate instate)
|
||||
/* For LIST and SEARCH responses */
|
||||
static CURLcode imap_state_listsearch_resp(struct connectdata *conn,
|
||||
int imapcode,
|
||||
imapstate instate)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
char *line = conn->data->state.buffer;
|
||||
@@ -1249,31 +1250,6 @@ static CURLcode imap_state_append_final_resp(struct connectdata *conn,
|
||||
return result;
|
||||
}
|
||||
|
||||
/* For SEARCH responses */
|
||||
static CURLcode imap_state_search_resp(struct connectdata *conn, int imapcode,
|
||||
imapstate instate)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
char *line = conn->data->state.buffer;
|
||||
size_t len = strlen(line);
|
||||
|
||||
(void)instate; /* No use for this yet */
|
||||
|
||||
if(imapcode == '*') {
|
||||
/* Temporarily add the LF character back and send as body to the client */
|
||||
line[len] = '\n';
|
||||
result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
|
||||
line[len] = '\0';
|
||||
}
|
||||
else if(imapcode != 'O')
|
||||
result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */
|
||||
else
|
||||
/* End of DO phase */
|
||||
state(conn, IMAP_STOP);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode imap_statemach_act(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
@@ -1327,7 +1303,7 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
|
||||
break;
|
||||
|
||||
case IMAP_LIST:
|
||||
result = imap_state_list_resp(conn, imapcode, imapc->state);
|
||||
result = imap_state_listsearch_resp(conn, imapcode, imapc->state);
|
||||
break;
|
||||
|
||||
case IMAP_SELECT:
|
||||
@@ -1351,7 +1327,7 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
|
||||
break;
|
||||
|
||||
case IMAP_SEARCH:
|
||||
result = imap_state_search_resp(conn, imapcode, imapc->state);
|
||||
result = imap_state_listsearch_resp(conn, imapcode, imapc->state);
|
||||
break;
|
||||
|
||||
case IMAP_LOGOUT:
|
||||
@@ -1486,10 +1462,6 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
|
||||
(void)premature;
|
||||
|
||||
if(!imap)
|
||||
/* When the easy handle is removed from the multi interface while libcurl
|
||||
is still trying to resolve the host name, the IMAP struct is not yet
|
||||
initialized. However, the removal action calls Curl_done() which in
|
||||
turn calls this function, so we simply return success. */
|
||||
return CURLE_OK;
|
||||
|
||||
if(status) {
|
||||
@@ -1512,8 +1484,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
|
||||
|
||||
TODO: when the multi interface is used, this _really_ should be using
|
||||
the imap_multi_statemach function but we have no general support for
|
||||
non-blocking DONE operations, not in the multi state machine and with
|
||||
Curl_done() invokes on several places in the code!
|
||||
non-blocking DONE operations!
|
||||
*/
|
||||
if(!result)
|
||||
result = imap_block_statemach(conn);
|
||||
@@ -1825,6 +1796,7 @@ static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
|
||||
*/
|
||||
static char *imap_atom(const char *str, bool escape_only)
|
||||
{
|
||||
/* !checksrc! disable PARENBRACE 1 */
|
||||
const char atom_specials[] = "(){ %*]";
|
||||
const char *p1;
|
||||
char *p2;
|
||||
|
||||
@@ -32,9 +32,8 @@
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "curl_printf.h"
|
||||
|
||||
#include "inet_ntop.h"
|
||||
#include "curl_printf.h"
|
||||
|
||||
#define IN6ADDRSZ 16
|
||||
#define INADDRSZ 4
|
||||
@@ -57,10 +56,10 @@ static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
|
||||
|
||||
tmp[0] = '\0';
|
||||
(void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
|
||||
((int)((unsigned char)src[0])) & 0xff,
|
||||
((int)((unsigned char)src[1])) & 0xff,
|
||||
((int)((unsigned char)src[2])) & 0xff,
|
||||
((int)((unsigned char)src[3])) & 0xff);
|
||||
((int)((unsigned char)src[0])) & 0xff,
|
||||
((int)((unsigned char)src[1])) & 0xff,
|
||||
((int)((unsigned char)src[2])) & 0xff,
|
||||
((int)((unsigned char)src[3])) & 0xff);
|
||||
|
||||
len = strlen(tmp);
|
||||
if(len == 0 || len >= size) {
|
||||
|
||||
@@ -47,9 +47,9 @@
|
||||
#include "sendf.h"
|
||||
#include "curl_sec.h"
|
||||
#include "warnless.h"
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -152,7 +152,10 @@ krb5_auth(void *app_data, struct connectdata *conn)
|
||||
curl_socklen_t l = sizeof(conn->local_addr);
|
||||
struct SessionHandle *data = conn->data;
|
||||
CURLcode result;
|
||||
const char *service = "ftp", *srv_host = "host";
|
||||
const char *service = data->set.str[STRING_SERVICE_NAME] ?
|
||||
data->set.str[STRING_SERVICE_NAME] :
|
||||
"ftp";
|
||||
const char *srv_host = "host";
|
||||
gss_buffer_desc input_buffer, output_buffer, _gssresp, *gssresp;
|
||||
OM_uint32 maj, min;
|
||||
gss_name_t gssname;
|
||||
@@ -180,9 +183,9 @@ krb5_auth(void *app_data, struct connectdata *conn)
|
||||
/* this really shouldn't be repeated here, but can't help it */
|
||||
if(service == srv_host) {
|
||||
result = Curl_ftpsendf(conn, "AUTH GSSAPI");
|
||||
|
||||
if(result)
|
||||
return -2;
|
||||
|
||||
if(Curl_GetFTPResponse(&nread, conn, NULL))
|
||||
return -1;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -76,9 +76,8 @@
|
||||
#include "curl_base64.h"
|
||||
#include "rawstr.h"
|
||||
#include "connect.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -228,7 +227,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/* Get the URL scheme ( either ldap or ldaps ) */
|
||||
/* Get the URL scheme (either ldap or ldaps) */
|
||||
if(conn->given->flags & PROTOPT_SSL)
|
||||
ldap_ssl = 1;
|
||||
infof(data, "LDAP local: trying to establish %s connection\n",
|
||||
@@ -717,7 +716,7 @@ static int str2scope (const char *p)
|
||||
return LDAP_SCOPE_BASE;
|
||||
if(strequal(p, "sub"))
|
||||
return LDAP_SCOPE_SUBTREE;
|
||||
if(strequal( p, "subtree"))
|
||||
if(strequal(p, "subtree"))
|
||||
return LDAP_SCOPE_SUBTREE;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "llist.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "curl_md5.h"
|
||||
#include "curl_hmac.h"
|
||||
#include "warnless.h"
|
||||
|
||||
@@ -26,10 +26,12 @@
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "curl_printf.h"
|
||||
#include "urldata.h"
|
||||
|
||||
#define MEMDEBUG_NODEFINES /* don't redefine the standard functions */
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -28,10 +28,6 @@
|
||||
* as well as the library. Do not mix with library internals!
|
||||
*/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#define CURL_MT_LOGFNAME_BUFSIZE 512
|
||||
|
||||
#define logfile curl_debuglogfile
|
||||
@@ -57,17 +53,17 @@ CURL_EXTERN void curl_memlog(const char *format, ...);
|
||||
|
||||
/* file descriptor manipulators */
|
||||
CURL_EXTERN curl_socket_t curl_socket(int domain, int type, int protocol,
|
||||
int line , const char *source);
|
||||
int line, const char *source);
|
||||
CURL_EXTERN void curl_mark_sclose(curl_socket_t sockfd,
|
||||
int line , const char *source);
|
||||
int line, const char *source);
|
||||
CURL_EXTERN int curl_sclose(curl_socket_t sockfd,
|
||||
int line , const char *source);
|
||||
int line, const char *source);
|
||||
CURL_EXTERN curl_socket_t curl_accept(curl_socket_t s, void *a, void *alen,
|
||||
int line, const char *source);
|
||||
#ifdef HAVE_SOCKETPAIR
|
||||
CURL_EXTERN int curl_socketpair(int domain, int type, int protocol,
|
||||
curl_socket_t socket_vector[2],
|
||||
int line , const char *source);
|
||||
int line, const char *source);
|
||||
#endif
|
||||
|
||||
/* FILE functions */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1999 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1999 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -36,11 +36,6 @@
|
||||
*/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(DJGPP) && (DJGPP_MINOR < 4)
|
||||
#undef _MPRINTF_REPLACE /* don't use x_was_used() here */
|
||||
#endif
|
||||
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
#include "curl_memory.h"
|
||||
@@ -465,22 +460,24 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
|
||||
if(flags & FLAGS_WIDTHPARAM) {
|
||||
/* we have the width specified from a parameter, so we make that
|
||||
parameter's info setup properly */
|
||||
vto[i].width = width - 1;
|
||||
i = width - 1;
|
||||
vto[i].type = FORMAT_WIDTH;
|
||||
vto[i].flags = FLAGS_NEW;
|
||||
vto[i].precision = vto[i].width = 0; /* can't use width or precision
|
||||
of width! */
|
||||
long k = width - 1;
|
||||
vto[i].width = k;
|
||||
vto[k].type = FORMAT_WIDTH;
|
||||
vto[k].flags = FLAGS_NEW;
|
||||
/* can't use width or precision of width! */
|
||||
vto[k].width = 0;
|
||||
vto[k].precision = 0;
|
||||
}
|
||||
if(flags & FLAGS_PRECPARAM) {
|
||||
/* we have the precision specified from a parameter, so we make that
|
||||
parameter's info setup properly */
|
||||
vto[i].precision = precision - 1;
|
||||
i = precision - 1;
|
||||
vto[i].type = FORMAT_WIDTH;
|
||||
vto[i].flags = FLAGS_NEW;
|
||||
vto[i].precision = vto[i].width = 0; /* can't use width or precision
|
||||
of width! */
|
||||
long k = precision - 1;
|
||||
vto[i].precision = k;
|
||||
vto[k].type = FORMAT_WIDTH;
|
||||
vto[k].flags = FLAGS_NEW;
|
||||
/* can't use width or precision of width! */
|
||||
vto[k].width = 0;
|
||||
vto[k].precision = 0;
|
||||
}
|
||||
*endpos++ = fmt + 1; /* end of this sequence */
|
||||
}
|
||||
@@ -488,11 +485,15 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
|
||||
|
||||
/* Read the arg list parameters into our data list */
|
||||
for(i=0; i<max_param; i++) {
|
||||
if((i + 1 < max_param) && (vto[i + 1].type == FORMAT_WIDTH)) {
|
||||
/* Width/precision arguments must be read before the main argument
|
||||
* they are attached to
|
||||
*/
|
||||
vto[i + 1].data.num.as_signed = (mp_intmax_t)va_arg(arglist, int);
|
||||
/* Width/precision arguments must be read before the main argument
|
||||
they are attached to */
|
||||
if(vto[i].flags & FLAGS_WIDTHPARAM) {
|
||||
vto[vto[i].width].data.num.as_signed =
|
||||
(mp_intmax_t)va_arg(arglist, int);
|
||||
}
|
||||
if(vto[i].flags & FLAGS_PRECPARAM) {
|
||||
vto[vto[i].precision].data.num.as_signed =
|
||||
(mp_intmax_t)va_arg(arglist, int);
|
||||
}
|
||||
|
||||
switch (vto[i].type) {
|
||||
@@ -580,6 +581,11 @@ static int dprintf_formatf(
|
||||
|
||||
va_stack_t *p;
|
||||
|
||||
/* 'workend' points to the final buffer byte position, but with an extra
|
||||
byte as margin to avoid the (false?) warning Coverity gives us
|
||||
otherwise */
|
||||
char *workend = &work[sizeof(work) - 2];
|
||||
|
||||
/* Do the actual %-code parsing */
|
||||
dprintf_Pass1(format, vto, endpos, ap_save);
|
||||
|
||||
@@ -609,6 +615,8 @@ static int dprintf_formatf(
|
||||
/* Used to convert negative in positive. */
|
||||
mp_intmax_t signed_num;
|
||||
|
||||
char *w;
|
||||
|
||||
if(*f != '%') {
|
||||
/* This isn't a format spec, so write everything out until the next one
|
||||
OR end of string is reached. */
|
||||
@@ -645,16 +653,30 @@ static int dprintf_formatf(
|
||||
p = &vto[param];
|
||||
|
||||
/* pick up the specified width */
|
||||
if(p->flags & FLAGS_WIDTHPARAM)
|
||||
if(p->flags & FLAGS_WIDTHPARAM) {
|
||||
width = (long)vto[p->width].data.num.as_signed;
|
||||
param_num++; /* since the width is extracted from a parameter, we
|
||||
must skip that to get to the next one properly */
|
||||
if(width < 0) {
|
||||
/* "A negative field width is taken as a '-' flag followed by a
|
||||
positive field width." */
|
||||
width = -width;
|
||||
p->flags |= FLAGS_LEFT;
|
||||
p->flags &= ~FLAGS_PAD_NIL;
|
||||
}
|
||||
}
|
||||
else
|
||||
width = p->width;
|
||||
|
||||
/* pick up the specified precision */
|
||||
if(p->flags & FLAGS_PRECPARAM) {
|
||||
prec = (long)vto[p->precision].data.num.as_signed;
|
||||
param_num++; /* since the precision is extraced from a parameter, we
|
||||
param_num++; /* since the precision is extracted from a parameter, we
|
||||
must skip that to get to the next one properly */
|
||||
if(prec < 0)
|
||||
/* "A negative precision is taken as if the precision were
|
||||
omitted." */
|
||||
prec = -1;
|
||||
}
|
||||
else if(p->flags & FLAGS_PREC)
|
||||
prec = p->precision;
|
||||
@@ -715,72 +737,68 @@ static int dprintf_formatf(
|
||||
|
||||
number:
|
||||
/* Number of base BASE. */
|
||||
{
|
||||
char *workend = &work[sizeof(work) - 1];
|
||||
char *w;
|
||||
|
||||
/* Supply a default precision if none was given. */
|
||||
if(prec == -1)
|
||||
prec = 1;
|
||||
/* Supply a default precision if none was given. */
|
||||
if(prec == -1)
|
||||
prec = 1;
|
||||
|
||||
/* Put the number in WORK. */
|
||||
w = workend;
|
||||
while(num > 0) {
|
||||
*w-- = digits[num % base];
|
||||
num /= base;
|
||||
}
|
||||
width -= (long)(workend - w);
|
||||
prec -= (long)(workend - w);
|
||||
/* Put the number in WORK. */
|
||||
w = workend;
|
||||
while(num > 0) {
|
||||
*w-- = digits[num % base];
|
||||
num /= base;
|
||||
}
|
||||
width -= (long)(workend - w);
|
||||
prec -= (long)(workend - w);
|
||||
|
||||
if(is_alt && base == 8 && prec <= 0) {
|
||||
if(is_alt && base == 8 && prec <= 0) {
|
||||
*w-- = '0';
|
||||
--width;
|
||||
}
|
||||
|
||||
if(prec > 0) {
|
||||
width -= prec;
|
||||
while(prec-- > 0)
|
||||
*w-- = '0';
|
||||
--width;
|
||||
}
|
||||
}
|
||||
|
||||
if(prec > 0) {
|
||||
width -= prec;
|
||||
while(prec-- > 0)
|
||||
*w-- = '0';
|
||||
}
|
||||
if(is_alt && base == 16)
|
||||
width -= 2;
|
||||
|
||||
if(is_alt && base == 16)
|
||||
width -= 2;
|
||||
if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE))
|
||||
--width;
|
||||
|
||||
if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE))
|
||||
--width;
|
||||
|
||||
if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL))
|
||||
while(width-- > 0)
|
||||
OUTCHAR(' ');
|
||||
|
||||
if(is_neg)
|
||||
OUTCHAR('-');
|
||||
else if(p->flags & FLAGS_SHOWSIGN)
|
||||
OUTCHAR('+');
|
||||
else if(p->flags & FLAGS_SPACE)
|
||||
if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL))
|
||||
while(width-- > 0)
|
||||
OUTCHAR(' ');
|
||||
|
||||
if(is_alt && base == 16) {
|
||||
OUTCHAR('0');
|
||||
if(p->flags & FLAGS_UPPER)
|
||||
OUTCHAR('X');
|
||||
else
|
||||
OUTCHAR('x');
|
||||
}
|
||||
if(is_neg)
|
||||
OUTCHAR('-');
|
||||
else if(p->flags & FLAGS_SHOWSIGN)
|
||||
OUTCHAR('+');
|
||||
else if(p->flags & FLAGS_SPACE)
|
||||
OUTCHAR(' ');
|
||||
|
||||
if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL))
|
||||
while(width-- > 0)
|
||||
OUTCHAR('0');
|
||||
|
||||
/* Write the number. */
|
||||
while(++w <= workend) {
|
||||
OUTCHAR(*w);
|
||||
}
|
||||
|
||||
if(p->flags & FLAGS_LEFT)
|
||||
while(width-- > 0)
|
||||
OUTCHAR(' ');
|
||||
if(is_alt && base == 16) {
|
||||
OUTCHAR('0');
|
||||
if(p->flags & FLAGS_UPPER)
|
||||
OUTCHAR('X');
|
||||
else
|
||||
OUTCHAR('x');
|
||||
}
|
||||
|
||||
if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL))
|
||||
while(width-- > 0)
|
||||
OUTCHAR('0');
|
||||
|
||||
/* Write the number. */
|
||||
while(++w <= workend) {
|
||||
OUTCHAR(*w);
|
||||
}
|
||||
|
||||
if(p->flags & FLAGS_LEFT)
|
||||
while(width-- > 0)
|
||||
OUTCHAR(' ');
|
||||
break;
|
||||
|
||||
case FORMAT_STRING:
|
||||
@@ -809,7 +827,7 @@ static int dprintf_formatf(
|
||||
else
|
||||
len = strlen(str);
|
||||
|
||||
width -= (long)len;
|
||||
width -= (len > LONG_MAX) ? LONG_MAX : (long)len;
|
||||
|
||||
if(p->flags & FLAGS_ALT)
|
||||
OUTCHAR('"');
|
||||
|
||||
@@ -42,9 +42,9 @@
|
||||
#include "multihandle.h"
|
||||
#include "pipeline.h"
|
||||
#include "sigpipe.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
@@ -136,7 +136,7 @@ static void mstate(struct SessionHandle *data, CURLMstate state
|
||||
connection_id = data->easy_conn->connection_id;
|
||||
|
||||
infof(data,
|
||||
"STATE: %s => %s handle %p; line %d (connection #%ld) \n",
|
||||
"STATE: %s => %s handle %p; line %d (connection #%ld)\n",
|
||||
statename[oldstate], statename[data->mstate],
|
||||
(void *)data, lineno, connection_id);
|
||||
}
|
||||
@@ -484,6 +484,167 @@ static void debug_print_sock_hash(void *p)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Mark the connection as 'idle', or close it if the cache is full.
|
||||
Returns TRUE if the connection is kept, or FALSE if it was closed. */
|
||||
static bool
|
||||
ConnectionDone(struct SessionHandle *data, struct connectdata *conn)
|
||||
{
|
||||
/* data->multi->maxconnects can be negative, deal with it. */
|
||||
size_t maxconnects =
|
||||
(data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
|
||||
data->multi->maxconnects;
|
||||
struct connectdata *conn_candidate = NULL;
|
||||
|
||||
/* Mark the current connection as 'unused' */
|
||||
conn->inuse = FALSE;
|
||||
|
||||
if(maxconnects > 0 &&
|
||||
data->state.conn_cache->num_connections > maxconnects) {
|
||||
infof(data, "Connection cache is full, closing the oldest one.\n");
|
||||
|
||||
conn_candidate = Curl_oldest_idle_connection(data);
|
||||
|
||||
if(conn_candidate) {
|
||||
/* Set the connection's owner correctly */
|
||||
conn_candidate->data = data;
|
||||
|
||||
/* the winner gets the honour of being disconnected */
|
||||
(void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return (conn_candidate == conn) ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
static CURLcode multi_done(struct connectdata **connp,
|
||||
CURLcode status, /* an error if this is called
|
||||
after an error was detected */
|
||||
bool premature)
|
||||
{
|
||||
CURLcode result;
|
||||
struct connectdata *conn;
|
||||
struct SessionHandle *data;
|
||||
|
||||
DEBUGASSERT(*connp);
|
||||
|
||||
conn = *connp;
|
||||
data = conn->data;
|
||||
|
||||
DEBUGF(infof(data, "multi_done\n"));
|
||||
|
||||
if(data->state.done)
|
||||
/* Stop if multi_done() has already been called */
|
||||
return CURLE_OK;
|
||||
|
||||
Curl_getoff_all_pipelines(data, conn);
|
||||
|
||||
/* Cleanup possible redirect junk */
|
||||
free(data->req.newurl);
|
||||
data->req.newurl = NULL;
|
||||
free(data->req.location);
|
||||
data->req.location = NULL;
|
||||
|
||||
switch(status) {
|
||||
case CURLE_ABORTED_BY_CALLBACK:
|
||||
case CURLE_READ_ERROR:
|
||||
case CURLE_WRITE_ERROR:
|
||||
/* When we're aborted due to a callback return code it basically have to
|
||||
be counted as premature as there is trouble ahead if we don't. We have
|
||||
many callbacks and protocols work differently, we could potentially do
|
||||
this more fine-grained in the future. */
|
||||
premature = TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* this calls the protocol-specific function pointer previously set */
|
||||
if(conn->handler->done)
|
||||
result = conn->handler->done(conn, status, premature);
|
||||
else
|
||||
result = status;
|
||||
|
||||
if(CURLE_ABORTED_BY_CALLBACK != result) {
|
||||
/* avoid this if we already aborted by callback to avoid this calling
|
||||
another callback */
|
||||
CURLcode rc = Curl_pgrsDone(conn);
|
||||
if(!result && rc)
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
}
|
||||
|
||||
if((!premature &&
|
||||
conn->send_pipe->size + conn->recv_pipe->size != 0 &&
|
||||
!data->set.reuse_forbid &&
|
||||
!conn->bits.close)) {
|
||||
/* Stop if pipeline is not empty and we do not have to close
|
||||
connection. */
|
||||
DEBUGF(infof(data, "Connection still in use, no more multi_done now!\n"));
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
data->state.done = TRUE; /* called just now! */
|
||||
Curl_resolver_cancel(conn);
|
||||
|
||||
if(conn->dns_entry) {
|
||||
Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
|
||||
conn->dns_entry = NULL;
|
||||
}
|
||||
|
||||
/* if the transfer was completed in a paused state there can be buffered
|
||||
data left to write and then kill */
|
||||
free(data->state.tempwrite);
|
||||
data->state.tempwrite = NULL;
|
||||
|
||||
/* if data->set.reuse_forbid is TRUE, it means the libcurl client has
|
||||
forced us to close this connection. This is ignored for requests taking
|
||||
place in a NTLM authentication handshake
|
||||
|
||||
if conn->bits.close is TRUE, it means that the connection should be
|
||||
closed in spite of all our efforts to be nice, due to protocol
|
||||
restrictions in our or the server's end
|
||||
|
||||
if premature is TRUE, it means this connection was said to be DONE before
|
||||
the entire request operation is complete and thus we can't know in what
|
||||
state it is for re-using, so we're forced to close it. In a perfect world
|
||||
we can add code that keep track of if we really must close it here or not,
|
||||
but currently we have no such detail knowledge.
|
||||
*/
|
||||
|
||||
if((data->set.reuse_forbid
|
||||
#if defined(USE_NTLM)
|
||||
&& !(conn->ntlm.state == NTLMSTATE_TYPE2 ||
|
||||
conn->proxyntlm.state == NTLMSTATE_TYPE2)
|
||||
#endif
|
||||
) || conn->bits.close || premature) {
|
||||
CURLcode res2 = Curl_disconnect(conn, premature); /* close connection */
|
||||
|
||||
/* If we had an error already, make sure we return that one. But
|
||||
if we got a new error, return that. */
|
||||
if(!result && res2)
|
||||
result = res2;
|
||||
}
|
||||
else {
|
||||
/* the connection is no longer in use */
|
||||
if(ConnectionDone(data, conn)) {
|
||||
/* remember the most recently used connection */
|
||||
data->state.lastconnect = conn;
|
||||
|
||||
infof(data, "Connection #%ld to host %s left intact\n",
|
||||
conn->connection_id,
|
||||
conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname);
|
||||
}
|
||||
else
|
||||
data->state.lastconnect = NULL;
|
||||
}
|
||||
|
||||
*connp = NULL; /* to make the caller of this function better detect that
|
||||
this was either closed or handed over to the connection
|
||||
cache here, and therefore cannot be used from this point on
|
||||
*/
|
||||
Curl_free_request_state(data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
CURL *curl_handle)
|
||||
{
|
||||
@@ -529,8 +690,8 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
request but not received its response yet, we need to close
|
||||
connection. */
|
||||
connclose(data->easy_conn, "Removed with partial response");
|
||||
/* Set connection owner so that Curl_done() closes it.
|
||||
We can safely do this here since connection is killed. */
|
||||
/* Set connection owner so that the DONE function closes it. We can
|
||||
safely do this here since connection is killed. */
|
||||
data->easy_conn->data = easy;
|
||||
easy_owns_conn = TRUE;
|
||||
}
|
||||
@@ -548,26 +709,26 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
|
||||
if(data->easy_conn) {
|
||||
|
||||
/* we must call Curl_done() here (if we still "own it") so that we don't
|
||||
leave a half-baked one around */
|
||||
/* we must call multi_done() here (if we still own the connection) so that
|
||||
we don't leave a half-baked one around */
|
||||
if(easy_owns_conn) {
|
||||
|
||||
/* Curl_done() clears the conn->data field to lose the association
|
||||
/* multi_done() clears the conn->data field to lose the association
|
||||
between the easy handle and the connection
|
||||
|
||||
Note that this ignores the return code simply because there's
|
||||
nothing really useful to do with it anyway! */
|
||||
(void)Curl_done(&data->easy_conn, data->result, premature);
|
||||
(void)multi_done(&data->easy_conn, data->result, premature);
|
||||
}
|
||||
else
|
||||
/* Clear connection pipelines, if Curl_done above was not called */
|
||||
/* Clear connection pipelines, if multi_done above was not called */
|
||||
Curl_getoff_all_pipelines(data, data->easy_conn);
|
||||
}
|
||||
|
||||
Curl_wildcard_dtor(&data->wildcard);
|
||||
|
||||
/* destroy the timeout list that is held in the easy handle, do this *after*
|
||||
Curl_done() as that may actuall call Curl_expire that uses this */
|
||||
multi_done() as that may actually call Curl_expire that uses this */
|
||||
if(data->state.timeoutlist) {
|
||||
Curl_llist_destroy(data->state.timeoutlist, NULL);
|
||||
data->state.timeoutlist = NULL;
|
||||
@@ -990,6 +1151,139 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static CURLcode multi_reconnect_request(struct connectdata **connp)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn = *connp;
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
/* This was a re-use of a connection and we got a write error in the
|
||||
* DO-phase. Then we DISCONNECT this connection and have another attempt to
|
||||
* CONNECT and then DO again! The retry cannot possibly find another
|
||||
* connection to re-use, since we only keep one possible connection for
|
||||
* each. */
|
||||
|
||||
infof(data, "Re-used connection seems dead, get a new one\n");
|
||||
|
||||
connclose(conn, "Reconnect dead connection"); /* enforce close */
|
||||
result = multi_done(&conn, result, FALSE); /* we are so done with this */
|
||||
|
||||
/* conn may no longer be a good pointer, clear it to avoid mistakes by
|
||||
parent functions */
|
||||
*connp = NULL;
|
||||
|
||||
/*
|
||||
* We need to check for CURLE_SEND_ERROR here as well. This could happen
|
||||
* when the request failed on a FTP connection and thus multi_done() itself
|
||||
* tried to use the connection (again).
|
||||
*/
|
||||
if(!result || (CURLE_SEND_ERROR == result)) {
|
||||
bool async;
|
||||
bool protocol_done = TRUE;
|
||||
|
||||
/* Now, redo the connect and get a new connection */
|
||||
result = Curl_connect(data, connp, &async, &protocol_done);
|
||||
if(!result) {
|
||||
/* We have connected or sent away a name resolve query fine */
|
||||
|
||||
conn = *connp; /* setup conn to again point to something nice */
|
||||
if(async) {
|
||||
/* Now, if async is TRUE here, we need to wait for the name
|
||||
to resolve */
|
||||
result = Curl_resolver_wait_resolv(conn, NULL);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Resolved, continue with the connection */
|
||||
result = Curl_async_resolved(conn, &protocol_done);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_complete is called when the DO actions are complete.
|
||||
*
|
||||
* We init chunking and trailer bits to their default values here immediately
|
||||
* before receiving any header data for the current request in the pipeline.
|
||||
*/
|
||||
static void do_complete(struct connectdata *conn)
|
||||
{
|
||||
conn->data->req.chunk=FALSE;
|
||||
conn->data->req.maxfd = (conn->sockfd>conn->writesockfd?
|
||||
conn->sockfd:conn->writesockfd)+1;
|
||||
Curl_pgrsTime(conn->data, TIMER_PRETRANSFER);
|
||||
}
|
||||
|
||||
static CURLcode multi_do(struct connectdata **connp, bool *done)
|
||||
{
|
||||
CURLcode result=CURLE_OK;
|
||||
struct connectdata *conn = *connp;
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
if(conn->handler->do_it) {
|
||||
/* generic protocol-specific function pointer set in curl_connect() */
|
||||
result = conn->handler->do_it(conn, done);
|
||||
|
||||
/* This was formerly done in transfer.c, but we better do it here */
|
||||
if((CURLE_SEND_ERROR == result) && conn->bits.reuse) {
|
||||
/*
|
||||
* If the connection is using an easy handle, call reconnect
|
||||
* to re-establish the connection. Otherwise, let the multi logic
|
||||
* figure out how to re-establish the connection.
|
||||
*/
|
||||
if(!data->multi) {
|
||||
result = multi_reconnect_request(connp);
|
||||
|
||||
if(!result) {
|
||||
/* ... finally back to actually retry the DO phase */
|
||||
conn = *connp; /* re-assign conn since multi_reconnect_request
|
||||
creates a new connection */
|
||||
result = conn->handler->do_it(conn, done);
|
||||
}
|
||||
}
|
||||
else
|
||||
return result;
|
||||
}
|
||||
|
||||
if(!result && *done)
|
||||
/* do_complete must be called after the protocol-specific DO function */
|
||||
do_complete(conn);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* multi_do_more() is called during the DO_MORE multi state. It is basically a
|
||||
* second stage DO state which (wrongly) was introduced to support FTP's
|
||||
* second connection.
|
||||
*
|
||||
* TODO: A future libcurl should be able to work away this state.
|
||||
*
|
||||
* 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
|
||||
* DOING state there's more work to do!
|
||||
*/
|
||||
|
||||
static CURLcode multi_do_more(struct connectdata *conn, int *complete)
|
||||
{
|
||||
CURLcode result=CURLE_OK;
|
||||
|
||||
*complete = 0;
|
||||
|
||||
if(conn->handler->do_more)
|
||||
result = conn->handler->do_more(conn, complete);
|
||||
|
||||
if(!result && (*complete == 1))
|
||||
/* do_complete must be called after the protocol-specific DO function */
|
||||
do_complete(conn);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
struct timeval now,
|
||||
struct SessionHandle *data)
|
||||
@@ -1075,7 +1369,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
failf(data, "Operation timed out after %ld milliseconds with %"
|
||||
CURL_FORMAT_CURL_OFF_T " out of %"
|
||||
CURL_FORMAT_CURL_OFF_T " bytes received",
|
||||
Curl_tvdiff(k->now, data->progress.t_startsingle),
|
||||
Curl_tvdiff(now, data->progress.t_startsingle),
|
||||
k->bytecount, k->size);
|
||||
}
|
||||
else {
|
||||
@@ -1092,7 +1386,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
disconnect_conn = TRUE;
|
||||
}
|
||||
result = CURLE_OPERATION_TIMEDOUT;
|
||||
(void)Curl_done(&data->easy_conn, result, TRUE);
|
||||
(void)multi_done(&data->easy_conn, result, TRUE);
|
||||
/* Skip the statemachine and go directly to error handling section. */
|
||||
goto statemachine_end;
|
||||
}
|
||||
@@ -1170,9 +1464,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
{
|
||||
struct Curl_dns_entry *dns = NULL;
|
||||
struct connectdata *conn = data->easy_conn;
|
||||
const char *hostname;
|
||||
|
||||
if(conn->bits.proxy)
|
||||
hostname = conn->proxy.name;
|
||||
else if(conn->bits.conn_to_host)
|
||||
hostname = conn->conn_to_host.name;
|
||||
else
|
||||
hostname = conn->host.name;
|
||||
|
||||
/* check if we have the name resolved by now */
|
||||
dns = Curl_fetch_addr(conn, conn->host.name, (int)conn->port);
|
||||
dns = Curl_fetch_addr(conn, hostname, (int)conn->port);
|
||||
|
||||
if(dns) {
|
||||
#ifdef CURLRES_ASYNCH
|
||||
@@ -1180,7 +1482,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
conn->async.done = TRUE;
|
||||
#endif
|
||||
result = CURLE_OK;
|
||||
infof(data, "Hostname was found in DNS cache\n");
|
||||
infof(data, "Hostname '%s' was found in DNS cache\n", hostname);
|
||||
}
|
||||
|
||||
if(!dns)
|
||||
@@ -1237,7 +1539,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
/* connect back to proxy again */
|
||||
result = CURLE_OK;
|
||||
Curl_done(&data->easy_conn, CURLE_OK, FALSE);
|
||||
multi_done(&data->easy_conn, CURLE_OK, FALSE);
|
||||
multistate(data, CURLM_STATE_CONNECT);
|
||||
}
|
||||
else if(!result) {
|
||||
@@ -1281,7 +1583,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
else if(result) {
|
||||
/* failure detected */
|
||||
Curl_posttransfer(data);
|
||||
Curl_done(&data->easy_conn, result, TRUE);
|
||||
multi_done(&data->easy_conn, result, TRUE);
|
||||
disconnect_conn = TRUE;
|
||||
}
|
||||
break;
|
||||
@@ -1298,7 +1600,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
else if(result) {
|
||||
/* failure detected */
|
||||
Curl_posttransfer(data);
|
||||
Curl_done(&data->easy_conn, result, TRUE);
|
||||
multi_done(&data->easy_conn, result, TRUE);
|
||||
disconnect_conn = TRUE;
|
||||
}
|
||||
break;
|
||||
@@ -1322,9 +1624,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
}
|
||||
else {
|
||||
/* Perform the protocol's DO action */
|
||||
result = Curl_do(&data->easy_conn, &dophase_done);
|
||||
result = multi_do(&data->easy_conn, &dophase_done);
|
||||
|
||||
/* When Curl_do() returns failure, data->easy_conn might be NULL! */
|
||||
/* When multi_do() returns failure, data->easy_conn might be NULL! */
|
||||
|
||||
if(!result) {
|
||||
if(!dophase_done) {
|
||||
@@ -1333,7 +1635,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
struct WildcardData *wc = &data->wildcard;
|
||||
if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
|
||||
/* skip some states if it is important */
|
||||
Curl_done(&data->easy_conn, CURLE_OK, FALSE);
|
||||
multi_done(&data->easy_conn, CURLE_OK, FALSE);
|
||||
multistate(data, CURLM_STATE_DONE);
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
break;
|
||||
@@ -1380,7 +1682,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
retry = (newurl)?TRUE:FALSE;
|
||||
|
||||
Curl_posttransfer(data);
|
||||
drc = Curl_done(&data->easy_conn, result, FALSE);
|
||||
drc = multi_done(&data->easy_conn, result, FALSE);
|
||||
|
||||
/* When set to retry the connection, we must to go back to
|
||||
* the CONNECT state */
|
||||
@@ -1415,7 +1717,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
/* failure detected */
|
||||
Curl_posttransfer(data);
|
||||
if(data->easy_conn)
|
||||
Curl_done(&data->easy_conn, result, FALSE);
|
||||
multi_done(&data->easy_conn, result, FALSE);
|
||||
disconnect_conn = TRUE;
|
||||
}
|
||||
}
|
||||
@@ -1437,7 +1739,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
else {
|
||||
/* failure detected */
|
||||
Curl_posttransfer(data);
|
||||
Curl_done(&data->easy_conn, result, FALSE);
|
||||
multi_done(&data->easy_conn, result, FALSE);
|
||||
disconnect_conn = TRUE;
|
||||
}
|
||||
break;
|
||||
@@ -1446,10 +1748,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
/*
|
||||
* When we are connected, DO MORE and then go DO_DONE
|
||||
*/
|
||||
result = Curl_do_more(data->easy_conn, &control);
|
||||
result = multi_do_more(data->easy_conn, &control);
|
||||
|
||||
/* No need to remove this handle from the send pipeline here since that
|
||||
is done in Curl_done() */
|
||||
is done in multi_done() */
|
||||
if(!result) {
|
||||
if(control) {
|
||||
/* if positive, advance to DO_DONE
|
||||
@@ -1466,7 +1768,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
else {
|
||||
/* failure detected */
|
||||
Curl_posttransfer(data);
|
||||
Curl_done(&data->easy_conn, result, FALSE);
|
||||
multi_done(&data->easy_conn, result, FALSE);
|
||||
disconnect_conn = TRUE;
|
||||
}
|
||||
break;
|
||||
@@ -1504,7 +1806,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
result = Curl_speedcheck(data, now);
|
||||
|
||||
if(( (data->set.max_send_speed == 0) ||
|
||||
(data->progress.ulspeed < data->set.max_send_speed )) &&
|
||||
(data->progress.ulspeed < data->set.max_send_speed)) &&
|
||||
( (data->set.max_recv_speed == 0) ||
|
||||
(data->progress.dlspeed < data->set.max_recv_speed)))
|
||||
multistate(data, CURLM_STATE_PERFORM);
|
||||
@@ -1586,11 +1888,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
* happened in the data connection.
|
||||
*/
|
||||
|
||||
if(!(data->easy_conn->handler->flags & PROTOPT_DUAL))
|
||||
if(!(data->easy_conn->handler->flags & PROTOPT_DUAL) &&
|
||||
result != CURLE_HTTP2_STREAM)
|
||||
connclose(data->easy_conn, "Transfer returned error");
|
||||
|
||||
Curl_posttransfer(data);
|
||||
Curl_done(&data->easy_conn, result, FALSE);
|
||||
multi_done(&data->easy_conn, result, FALSE);
|
||||
}
|
||||
else if(done) {
|
||||
followtype follow=FOLLOW_NONE;
|
||||
@@ -1621,7 +1924,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
}
|
||||
else
|
||||
follow = FOLLOW_RETRY;
|
||||
result = Curl_done(&data->easy_conn, CURLE_OK, FALSE);
|
||||
result = multi_done(&data->easy_conn, CURLE_OK, FALSE);
|
||||
if(!result) {
|
||||
result = Curl_follow(data, newurl, follow);
|
||||
if(!result) {
|
||||
@@ -1671,14 +1974,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
Curl_multi_process_pending_handles(multi);
|
||||
|
||||
/* post-transfer command */
|
||||
res = Curl_done(&data->easy_conn, result, FALSE);
|
||||
res = multi_done(&data->easy_conn, result, FALSE);
|
||||
|
||||
/* allow a previously set error code take precedence */
|
||||
if(!result)
|
||||
result = res;
|
||||
|
||||
/*
|
||||
* If there are other handles on the pipeline, Curl_done won't set
|
||||
* If there are other handles on the pipeline, multi_done won't set
|
||||
* easy_conn to NULL. In such a case, curl_multi_remove_handle() can
|
||||
* access free'd data, if the connection is free'd and the handle
|
||||
* removed before we perform the processing in CURLM_STATE_COMPLETED
|
||||
@@ -1697,7 +2000,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
}
|
||||
|
||||
/* after we have DONE what we're supposed to do, go COMPLETED, and
|
||||
it doesn't matter what the Curl_done() returned! */
|
||||
it doesn't matter what the multi_done() returned! */
|
||||
multistate(data, CURLM_STATE_COMPLETED);
|
||||
break;
|
||||
|
||||
@@ -1813,27 +2116,12 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
data=multi->easyp;
|
||||
while(data) {
|
||||
CURLMcode result;
|
||||
struct WildcardData *wc = &data->wildcard;
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
if(data->set.wildcardmatch) {
|
||||
if(!wc->filelist) {
|
||||
CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
|
||||
if(ret)
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
sigpipe_ignore(data, &pipe_st);
|
||||
result = multi_runsingle(multi, now, data);
|
||||
sigpipe_restore(&pipe_st);
|
||||
|
||||
if(data->set.wildcardmatch) {
|
||||
/* destruct wildcard structures if it is needed */
|
||||
if(wc->state == CURLWC_DONE || result)
|
||||
Curl_wildcard_dtor(wc);
|
||||
}
|
||||
|
||||
if(result)
|
||||
returncode = result;
|
||||
|
||||
@@ -2184,7 +2472,7 @@ static CURLMcode add_next_timeout(struct timeval now,
|
||||
/* move over the timeout list for this specific handle and remove all
|
||||
timeouts that are now passed tense and store the next pending
|
||||
timeout in *tv */
|
||||
for(e = list->head; e; ) {
|
||||
for(e = list->head; e;) {
|
||||
struct curl_llist_element *n = e->next;
|
||||
long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
|
||||
if(diff <= 0)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -32,9 +32,9 @@
|
||||
#include "strequal.h"
|
||||
#include "strtok.h"
|
||||
#include "rawstr.h"
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -58,26 +58,26 @@ rtag_t gAllocTag = (rtag_t) NULL;
|
||||
NXMutex_t *gLibLock = (NXMutex_t *) NULL;
|
||||
|
||||
/* internal library function prototypes... */
|
||||
int DisposeLibraryData( void * );
|
||||
void DisposeThreadData( void * );
|
||||
int GetOrSetUpData( int id, libdata_t **data, libthreaddata_t **threaddata );
|
||||
int DisposeLibraryData(void *);
|
||||
void DisposeThreadData(void *);
|
||||
int GetOrSetUpData(int id, libdata_t **data, libthreaddata_t **threaddata);
|
||||
|
||||
|
||||
int _NonAppStart( void *NLMHandle,
|
||||
void *errorScreen,
|
||||
const char *cmdLine,
|
||||
const char *loadDirPath,
|
||||
size_t uninitializedDataLength,
|
||||
void *NLMFileHandle,
|
||||
int (*readRoutineP)( int conn,
|
||||
void *fileHandle, size_t offset,
|
||||
size_t nbytes,
|
||||
size_t *bytesRead,
|
||||
void *buffer ),
|
||||
int _NonAppStart(void *NLMHandle,
|
||||
void *errorScreen,
|
||||
const char *cmdLine,
|
||||
const char *loadDirPath,
|
||||
size_t uninitializedDataLength,
|
||||
void *NLMFileHandle,
|
||||
int (*readRoutineP)(int conn,
|
||||
void *fileHandle, size_t offset,
|
||||
size_t nbytes,
|
||||
size_t *bytesRead,
|
||||
void *buffer),
|
||||
size_t customDataOffset,
|
||||
size_t customDataSize,
|
||||
int messageCount,
|
||||
const char **messages )
|
||||
const char **messages)
|
||||
{
|
||||
NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0);
|
||||
|
||||
@@ -132,7 +132,7 @@ int _NonAppStart( void *NLMHandle,
|
||||
* Here we clean up any resources we allocated. Resource tags is a big part
|
||||
* of what we created, but NetWare doesn't ask us to free those.
|
||||
*/
|
||||
void _NonAppStop( void )
|
||||
void _NonAppStop(void)
|
||||
{
|
||||
(void) unregister_library(gLibId);
|
||||
NXMutexFree(gLibLock);
|
||||
@@ -149,13 +149,13 @@ void _NonAppStop( void )
|
||||
* we return a non-zero value. Right now, there isn't any reason not to allow
|
||||
* it.
|
||||
*/
|
||||
int _NonAppCheckUnload( void )
|
||||
int _NonAppCheckUnload(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetOrSetUpData(int id, libdata_t **appData,
|
||||
libthreaddata_t **threadData )
|
||||
libthreaddata_t **threadData)
|
||||
{
|
||||
int err;
|
||||
libdata_t *app_data;
|
||||
@@ -277,7 +277,7 @@ int GetOrSetUpData(int id, libdata_t **appData,
|
||||
return err;
|
||||
}
|
||||
|
||||
int DisposeLibraryData( void *data )
|
||||
int DisposeLibraryData(void *data)
|
||||
{
|
||||
if(data) {
|
||||
void *tenbytes = ((libdata_t *) data)->tenbytes;
|
||||
@@ -289,7 +289,7 @@ int DisposeLibraryData( void *data )
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DisposeThreadData( void *data )
|
||||
void DisposeThreadData(void *data)
|
||||
{
|
||||
if(data) {
|
||||
void *twentybytes = ((libthreaddata_t *) data)->twentybytes;
|
||||
@@ -303,7 +303,7 @@ void DisposeThreadData( void *data )
|
||||
/* For native CLib-based NLM seems we can do a bit more simple. */
|
||||
#include <nwthread.h>
|
||||
|
||||
int main ( void )
|
||||
int main (void)
|
||||
{
|
||||
/* initialize any globals here... */
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#ifdef __NOVELL_LIBC__
|
||||
/* For native LibC-based NLM we need to do nothing. */
|
||||
int netware_init ( void )
|
||||
int netware_init (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -45,7 +45,7 @@ NETDB_DEFINE_CONTEXT
|
||||
#include <arpa/inet.h>
|
||||
NETINET_DEFINE_CONTEXT
|
||||
|
||||
int netware_init ( void )
|
||||
int netware_init (void)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned int myHandle = GetNLMHandle();
|
||||
@@ -72,13 +72,13 @@ int netware_init ( void )
|
||||
}
|
||||
|
||||
/* dummy function to satisfy newer prelude */
|
||||
int __init_environment ( void )
|
||||
int __init_environment (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* dummy function to satisfy newer prelude */
|
||||
int __deinit_environment ( void )
|
||||
int __deinit_environment (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
|
||||
* Copyright (C) 2011 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2011 - 2016, 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
|
||||
@@ -46,9 +46,8 @@
|
||||
#include "curl_ldap.h"
|
||||
#include "curl_base64.h"
|
||||
#include "connect.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -34,10 +34,10 @@
|
||||
#include "multiif.h"
|
||||
#include "non-ascii.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
#ifdef USE_PINGPONG
|
||||
@@ -88,7 +88,7 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
|
||||
struct SessionHandle *data=conn->data;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(timeout_ms <=0 ) {
|
||||
if(timeout_ms <=0) {
|
||||
failf(data, "server response timeout");
|
||||
return CURLE_OPERATION_TIMEDOUT; /* already too little time */
|
||||
}
|
||||
|
||||
@@ -83,9 +83,9 @@
|
||||
#include "curl_sasl.h"
|
||||
#include "curl_md5.h"
|
||||
#include "warnless.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/* Local API functions */
|
||||
@@ -1166,10 +1166,6 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
|
||||
(void)premature;
|
||||
|
||||
if(!pop3)
|
||||
/* When the easy handle is removed from the multi interface while libcurl
|
||||
is still trying to resolve the host name, the POP3 struct is not yet
|
||||
initialized. However, the removal action calls Curl_done() which in
|
||||
turn calls this function, so we simply return success. */
|
||||
return CURLE_OK;
|
||||
|
||||
if(status) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -36,9 +36,8 @@
|
||||
#include "rawstr.h"
|
||||
#include "select.h"
|
||||
#include "connect.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
@@ -31,10 +31,11 @@
|
||||
#include "ssh.h"
|
||||
#include "multiif.h"
|
||||
#include "non-ascii.h"
|
||||
#include "curl_printf.h"
|
||||
#include "strerror.h"
|
||||
#include "select.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -120,6 +121,90 @@ static size_t convert_lineends(struct SessionHandle *data,
|
||||
}
|
||||
#endif /* CURL_DO_LINEEND_CONV */
|
||||
|
||||
#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
|
||||
static void pre_receive_plain(struct connectdata *conn, int num)
|
||||
{
|
||||
const curl_socket_t sockfd = conn->sock[num];
|
||||
struct postponed_data * const psnd = &(conn->postponed[num]);
|
||||
size_t bytestorecv = psnd->allocated_size - psnd->recv_size;
|
||||
/* WinSock will destroy unread received data if send() is
|
||||
failed.
|
||||
To avoid lossage of received data, recv() must be
|
||||
performed before every send() if any incoming data is
|
||||
available. However, skip this, if buffer is already full. */
|
||||
if((conn->handler->protocol&PROTO_FAMILY_HTTP) != 0 &&
|
||||
conn->recv[num] == Curl_recv_plain &&
|
||||
(!psnd->buffer || bytestorecv)) {
|
||||
const int readymask = Curl_socket_check(sockfd, CURL_SOCKET_BAD,
|
||||
CURL_SOCKET_BAD, 0);
|
||||
if(readymask != -1 && (readymask & CURL_CSELECT_IN) != 0) {
|
||||
/* Have some incoming data */
|
||||
if(!psnd->buffer) {
|
||||
/* Use buffer double default size for intermediate buffer */
|
||||
psnd->allocated_size = 2 * BUFSIZE;
|
||||
psnd->buffer = malloc(psnd->allocated_size);
|
||||
psnd->recv_size = 0;
|
||||
psnd->recv_processed = 0;
|
||||
#ifdef DEBUGBUILD
|
||||
psnd->bindsock = sockfd; /* Used only for DEBUGASSERT */
|
||||
#endif /* DEBUGBUILD */
|
||||
bytestorecv = psnd->allocated_size;
|
||||
}
|
||||
if(psnd->buffer) {
|
||||
ssize_t recvedbytes;
|
||||
DEBUGASSERT(psnd->bindsock == sockfd);
|
||||
recvedbytes = sread(sockfd, psnd->buffer + psnd->recv_size,
|
||||
bytestorecv);
|
||||
if(recvedbytes > 0)
|
||||
psnd->recv_size += recvedbytes;
|
||||
}
|
||||
else
|
||||
psnd->allocated_size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct postponed_data * const psnd = &(conn->postponed[num]);
|
||||
size_t copysize;
|
||||
if(!psnd->buffer)
|
||||
return 0;
|
||||
|
||||
DEBUGASSERT(psnd->allocated_size > 0);
|
||||
DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
|
||||
DEBUGASSERT(psnd->recv_processed <= psnd->recv_size);
|
||||
/* Check and process data that already received and storied in internal
|
||||
intermediate buffer */
|
||||
if(psnd->recv_size > psnd->recv_processed) {
|
||||
DEBUGASSERT(psnd->bindsock == conn->sock[num]);
|
||||
copysize = CURLMIN(len, psnd->recv_size - psnd->recv_processed);
|
||||
memcpy(buf, psnd->buffer + psnd->recv_processed, copysize);
|
||||
psnd->recv_processed += copysize;
|
||||
}
|
||||
else
|
||||
copysize = 0; /* buffer was allocated, but nothing was received */
|
||||
|
||||
/* Free intermediate buffer if it has no unprocessed data */
|
||||
if(psnd->recv_processed == psnd->recv_size) {
|
||||
free(psnd->buffer);
|
||||
psnd->buffer = NULL;
|
||||
psnd->allocated_size = 0;
|
||||
psnd->recv_size = 0;
|
||||
psnd->recv_processed = 0;
|
||||
#ifdef DEBUGBUILD
|
||||
psnd->bindsock = CURL_SOCKET_BAD;
|
||||
#endif /* DEBUGBUILD */
|
||||
}
|
||||
return (ssize_t)copysize;
|
||||
}
|
||||
#else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
|
||||
/* Use "do-nothing" macros instead of functions when workaround not used */
|
||||
#define pre_receive_plain(c,n) do {} WHILE_FALSE
|
||||
#define get_pre_recved(c,n,b,l) 0
|
||||
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
|
||||
|
||||
/* Curl_infof() is for info message along the way */
|
||||
|
||||
void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
|
||||
@@ -254,7 +339,23 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
|
||||
const void *mem, size_t len, CURLcode *code)
|
||||
{
|
||||
curl_socket_t sockfd = conn->sock[num];
|
||||
ssize_t bytes_written = swrite(sockfd, mem, len);
|
||||
ssize_t bytes_written;
|
||||
/* WinSock will destroy unread received data if send() is
|
||||
failed.
|
||||
To avoid lossage of received data, recv() must be
|
||||
performed before every send() if any incoming data is
|
||||
available. */
|
||||
pre_receive_plain(conn, num);
|
||||
|
||||
#ifdef MSG_FASTOPEN /* Linux */
|
||||
if(conn->bits.tcp_fastopen) {
|
||||
bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN,
|
||||
conn->ip_addr->ai_addr, conn->ip_addr->ai_addrlen);
|
||||
conn->bits.tcp_fastopen = FALSE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
bytes_written = swrite(sockfd, mem, len);
|
||||
|
||||
*code = CURLE_OK;
|
||||
if(-1 == bytes_written) {
|
||||
@@ -268,7 +369,8 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
|
||||
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
|
||||
due to its inability to send off data without blocking. We therefor
|
||||
treat both error codes the same here */
|
||||
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
|
||||
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) ||
|
||||
(EINPROGRESS == err)
|
||||
#endif
|
||||
) {
|
||||
/* this is just a case of EWOULDBLOCK */
|
||||
@@ -311,7 +413,16 @@ ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
|
||||
size_t len, CURLcode *code)
|
||||
{
|
||||
curl_socket_t sockfd = conn->sock[num];
|
||||
ssize_t nread = sread(sockfd, buf, len);
|
||||
ssize_t nread;
|
||||
/* Check and return data that already received and storied in internal
|
||||
intermediate buffer */
|
||||
nread = get_pre_recved(conn, num, buf, len);
|
||||
if(nread > 0) {
|
||||
*code = CURLE_OK;
|
||||
return nread;
|
||||
}
|
||||
|
||||
nread = sread(sockfd, buf, len);
|
||||
|
||||
*code = CURLE_OK;
|
||||
if(-1 == nread) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -71,14 +71,14 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
|
||||
/* this is a type this share will share */
|
||||
type = va_arg(param, int);
|
||||
share->specifier |= (1<<type);
|
||||
switch( type ) {
|
||||
switch(type) {
|
||||
case CURL_LOCK_DATA_DNS:
|
||||
break;
|
||||
|
||||
case CURL_LOCK_DATA_COOKIE:
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
|
||||
if(!share->cookies) {
|
||||
share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE );
|
||||
share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE);
|
||||
if(!share->cookies)
|
||||
res = CURLSHE_NOMEM;
|
||||
}
|
||||
@@ -114,7 +114,7 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
|
||||
/* this is a type this share will no longer share */
|
||||
type = va_arg(param, int);
|
||||
share->specifier &= ~(1<<type);
|
||||
switch( type ) {
|
||||
switch(type) {
|
||||
case CURL_LOCK_DATA_DNS:
|
||||
break;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "slist.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
|
||||
@@ -82,9 +82,9 @@
|
||||
#include "curl_gethostname.h"
|
||||
#include "curl_sasl.h"
|
||||
#include "warnless.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/* Local API functions */
|
||||
@@ -1204,10 +1204,6 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
|
||||
(void)premature;
|
||||
|
||||
if(!smtp || !pp->conn)
|
||||
/* When the easy handle is removed from the multi interface while libcurl
|
||||
is still trying to resolve the host name, the SMTP struct is not yet
|
||||
initialized. However, the removal action calls Curl_done() which in
|
||||
turn calls this function, so we simply return success. */
|
||||
return CURLE_OK;
|
||||
|
||||
if(status) {
|
||||
@@ -1262,8 +1258,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
|
||||
|
||||
TODO: when the multi interface is used, this _really_ should be using
|
||||
the smtp_multi_statemach function but we have no general support for
|
||||
non-blocking DONE operations, not in the multi state machine and with
|
||||
Curl_done() invokes on several places in the code!
|
||||
non-blocking DONE operations!
|
||||
*/
|
||||
result = smtp_block_statemach(conn);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -173,8 +173,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
|
||||
unsigned short ip[4];
|
||||
Curl_printable_address(hp, buf, sizeof(buf));
|
||||
|
||||
if(4 == sscanf( buf, "%hu.%hu.%hu.%hu",
|
||||
&ip[0], &ip[1], &ip[2], &ip[3])) {
|
||||
if(4 == sscanf(buf, "%hu.%hu.%hu.%hu",
|
||||
&ip[0], &ip[1], &ip[2], &ip[3])) {
|
||||
/* Set DSTIP */
|
||||
socksreq[4] = (unsigned char)ip[0];
|
||||
socksreq[5] = (unsigned char)ip[1];
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
|
||||
* Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2012 - 2016, 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
|
||||
@@ -32,9 +32,10 @@
|
||||
#include "timeval.h"
|
||||
#include "socks.h"
|
||||
#include "warnless.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
|
||||
@@ -120,7 +121,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
unsigned short us_length;
|
||||
char *user=NULL;
|
||||
unsigned char socksreq[4]; /* room for GSS-API exchange header only */
|
||||
char *serviceptr = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
|
||||
const char *serviceptr = data->set.str[STRING_PROXY_SERVICE_NAME] ?
|
||||
data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
|
||||
|
||||
/* GSS-API request looks like
|
||||
* +----+------+-----+----------------+
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
@@ -34,9 +34,9 @@
|
||||
#include "curl_sspi.h"
|
||||
#include "curl_multibyte.h"
|
||||
#include "warnless.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
@@ -70,7 +70,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
/* Needs GSS-API authentication */
|
||||
SECURITY_STATUS status;
|
||||
unsigned long sspi_ret_flags = 0;
|
||||
int gss_enc;
|
||||
unsigned char gss_enc;
|
||||
SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3];
|
||||
SecBufferDesc input_desc, output_desc, wrap_desc;
|
||||
SecPkgContext_Sizes sspi_sizes;
|
||||
@@ -83,7 +83,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
unsigned short us_length;
|
||||
unsigned long qop;
|
||||
unsigned char socksreq[4]; /* room for GSS-API exchange header only */
|
||||
char *service = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
|
||||
const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
|
||||
data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
|
||||
|
||||
/* GSS-API request looks like
|
||||
* +----+------+-----+----------------+
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1997 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1997 - 2016, 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
|
||||
@@ -55,7 +55,7 @@ int Curl_splayremovebyaddr(struct Curl_tree *t,
|
||||
#define Curl_splaycomparekeys(i,j) ( ((i.tv_sec) < (j.tv_sec)) ? -1 : \
|
||||
( ((i.tv_sec) > (j.tv_sec)) ? 1 : \
|
||||
( ((i.tv_usec) < (j.tv_usec)) ? -1 : \
|
||||
( ((i.tv_usec) > (j.tv_usec)) ? 1 : 0 ))))
|
||||
( ((i.tv_usec) > (j.tv_usec)) ? 1 : 0))))
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
void Curl_splayprint(struct Curl_tree * t, int d, char output);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -83,9 +83,10 @@
|
||||
#include "multiif.h"
|
||||
#include "select.h"
|
||||
#include "warnless.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
#ifdef WIN32
|
||||
@@ -362,6 +363,9 @@ static void state(struct connectdata *conn, sshstate nowstate)
|
||||
"SSH_SFTP_QUOTE_RENAME",
|
||||
"SSH_SFTP_QUOTE_RMDIR",
|
||||
"SSH_SFTP_QUOTE_UNLINK",
|
||||
"SSH_SFTP_QUOTE_STATVFS",
|
||||
"SSH_SFTP_GETINFO",
|
||||
"SSH_SFTP_FILETIME",
|
||||
"SSH_SFTP_TRANS_INIT",
|
||||
"SSH_SFTP_UPLOAD_INIT",
|
||||
"SSH_SFTP_CREATE_DIRS_INIT",
|
||||
@@ -414,7 +418,7 @@ static CURLcode ssh_getworkingpath(struct connectdata *conn,
|
||||
if(!working_path)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Check for /~/ , indicating relative to the user's home directory */
|
||||
/* Check for /~/, indicating relative to the user's home directory */
|
||||
if(conn->handler->protocol & CURLPROTO_SCP) {
|
||||
real_path = malloc(working_path_len+1);
|
||||
if(real_path == NULL) {
|
||||
@@ -1183,7 +1187,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
state(conn, SSH_SFTP_QUOTE);
|
||||
}
|
||||
else {
|
||||
state(conn, SSH_SFTP_TRANS_INIT);
|
||||
state(conn, SSH_SFTP_GETINFO);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1361,6 +1365,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
state(conn, SSH_SFTP_QUOTE_UNLINK);
|
||||
break;
|
||||
}
|
||||
else if(curl_strnequal(cmd, "statvfs ", 8)) {
|
||||
state(conn, SSH_SFTP_QUOTE_STATVFS);
|
||||
break;
|
||||
}
|
||||
|
||||
failf(data, "Unknown SFTP command");
|
||||
Curl_safefree(sshc->quote_path1);
|
||||
@@ -1372,7 +1380,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
}
|
||||
}
|
||||
if(!sshc->quote_item) {
|
||||
state(conn, SSH_SFTP_TRANS_INIT);
|
||||
state(conn, SSH_SFTP_GETINFO);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1391,7 +1399,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
sshc->nextstate = SSH_NO_STATE;
|
||||
}
|
||||
else {
|
||||
state(conn, SSH_SFTP_TRANS_INIT);
|
||||
state(conn, SSH_SFTP_GETINFO);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1611,6 +1619,87 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
state(conn, SSH_SFTP_NEXT_QUOTE);
|
||||
break;
|
||||
|
||||
case SSH_SFTP_QUOTE_STATVFS:
|
||||
{
|
||||
LIBSSH2_SFTP_STATVFS statvfs;
|
||||
rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1,
|
||||
curlx_uztoui(strlen(sshc->quote_path1)),
|
||||
&statvfs);
|
||||
|
||||
if(rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
break;
|
||||
}
|
||||
else if(rc != 0 && !sshc->acceptfail) {
|
||||
err = sftp_libssh2_last_error(sshc->sftp_session);
|
||||
Curl_safefree(sshc->quote_path1);
|
||||
failf(data, "statvfs command failed: %s", sftp_libssh2_strerror(err));
|
||||
state(conn, SSH_SFTP_CLOSE);
|
||||
sshc->nextstate = SSH_NO_STATE;
|
||||
sshc->actualcode = CURLE_QUOTE_ERROR;
|
||||
break;
|
||||
}
|
||||
else if(rc == 0) {
|
||||
char *tmp = aprintf("statvfs:\n"
|
||||
"f_bsize: %llu\n" "f_frsize: %llu\n"
|
||||
"f_blocks: %llu\n" "f_bfree: %llu\n"
|
||||
"f_bavail: %llu\n" "f_files: %llu\n"
|
||||
"f_ffree: %llu\n" "f_favail: %llu\n"
|
||||
"f_fsid: %llu\n" "f_flag: %llu\n"
|
||||
"f_namemax: %llu\n",
|
||||
statvfs.f_bsize, statvfs.f_frsize,
|
||||
statvfs.f_blocks, statvfs.f_bfree,
|
||||
statvfs.f_bavail, statvfs.f_files,
|
||||
statvfs.f_ffree, statvfs.f_favail,
|
||||
statvfs.f_fsid, statvfs.f_flag,
|
||||
statvfs.f_namemax);
|
||||
if(!tmp) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
state(conn, SSH_SFTP_CLOSE);
|
||||
sshc->nextstate = SSH_NO_STATE;
|
||||
break;
|
||||
}
|
||||
|
||||
result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
|
||||
free(tmp);
|
||||
if(result) {
|
||||
state(conn, SSH_SFTP_CLOSE);
|
||||
sshc->nextstate = SSH_NO_STATE;
|
||||
sshc->actualcode = result;
|
||||
}
|
||||
}
|
||||
state(conn, SSH_SFTP_NEXT_QUOTE);
|
||||
break;
|
||||
}
|
||||
|
||||
case SSH_SFTP_GETINFO:
|
||||
{
|
||||
if(data->set.get_filetime) {
|
||||
state(conn, SSH_SFTP_FILETIME);
|
||||
}
|
||||
else {
|
||||
state(conn, SSH_SFTP_TRANS_INIT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SSH_SFTP_FILETIME:
|
||||
{
|
||||
LIBSSH2_SFTP_ATTRIBUTES attrs;
|
||||
|
||||
rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
|
||||
curlx_uztoui(strlen(sftp_scp->path)),
|
||||
LIBSSH2_SFTP_STAT, &attrs);
|
||||
if(rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
break;
|
||||
}
|
||||
else if(rc == 0) {
|
||||
data->info.filetime = (long)attrs.mtime;
|
||||
}
|
||||
|
||||
state(conn, SSH_SFTP_TRANS_INIT);
|
||||
break;
|
||||
}
|
||||
|
||||
case SSH_SFTP_TRANS_INIT:
|
||||
if(data->set.upload)
|
||||
state(conn, SSH_SFTP_UPLOAD_INIT);
|
||||
@@ -2980,8 +3069,7 @@ static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
|
||||
|
||||
TODO: when the multi interface is used, this _really_ should be using
|
||||
the ssh_multi_statemach function but we have no general support for
|
||||
non-blocking DONE operations, not in the multi state machine and with
|
||||
Curl_done() invokes on several places in the code!
|
||||
non-blocking DONE operations!
|
||||
*/
|
||||
result = ssh_block_statemach(conn, FALSE);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,9 @@ typedef enum {
|
||||
SSH_SFTP_QUOTE_RENAME,
|
||||
SSH_SFTP_QUOTE_RMDIR,
|
||||
SSH_SFTP_QUOTE_UNLINK,
|
||||
SSH_SFTP_QUOTE_STATVFS,
|
||||
SSH_SFTP_GETINFO,
|
||||
SSH_SFTP_FILETIME,
|
||||
SSH_SFTP_TRANS_INIT,
|
||||
SSH_SFTP_UPLOAD_INIT,
|
||||
SSH_SFTP_CREATE_DIRS_INIT,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -19,7 +19,11 @@
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "strdup.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2004 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2004 - 2016, 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
|
||||
@@ -44,9 +44,9 @@
|
||||
#endif
|
||||
|
||||
#include "strerror.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
const char *
|
||||
@@ -305,6 +305,9 @@ curl_easy_strerror(CURLcode error)
|
||||
case CURLE_SSL_INVALIDCERTSTATUS:
|
||||
return "SSL server certificate status verification FAILED";
|
||||
|
||||
case CURLE_HTTP2_STREAM:
|
||||
return "Stream error in the HTTP/2 framing layer";
|
||||
|
||||
/* error codes not used by current libcurl */
|
||||
case CURLE_OBSOLETE20:
|
||||
case CURLE_OBSOLETE24:
|
||||
@@ -1076,14 +1079,13 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err)
|
||||
strncpy(outbuf, txt, outmax);
|
||||
else if(err == SEC_E_ILLEGAL_MESSAGE)
|
||||
snprintf(outbuf, outmax,
|
||||
"SEC_E_ILLEGAL_MESSAGE (0x%04X%04X) - This error usually occurs "
|
||||
"SEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually occurs "
|
||||
"when a fatal SSL/TLS alert is received (e.g. handshake failed). "
|
||||
"More detail may be available in the Windows System event log.",
|
||||
(err >> 16) & 0xffff, err & 0xffff);
|
||||
err);
|
||||
else {
|
||||
str = txtbuf;
|
||||
snprintf(txtbuf, sizeof(txtbuf), "%s (0x%04X%04X)",
|
||||
txt, (err >> 16) & 0xffff, err & 0xffff);
|
||||
snprintf(txtbuf, sizeof(txtbuf), "%s (0x%08X)", txt, err);
|
||||
txtbuf[sizeof(txtbuf)-1] = '\0';
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -51,7 +51,6 @@
|
||||
#include "telnet.h"
|
||||
#include "connect.h"
|
||||
#include "progress.h"
|
||||
#include "curl_printf.h"
|
||||
|
||||
#define TELOPTS
|
||||
#define TELCMDS
|
||||
@@ -62,7 +61,8 @@
|
||||
#include "rawstr.h"
|
||||
#include "warnless.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
typedef FARPROC WSOCK2_FUNC;
|
||||
static CURLcode check_wsock2 ( struct SessionHandle *data );
|
||||
static CURLcode check_wsock2 (struct SessionHandle *data);
|
||||
#endif
|
||||
|
||||
static
|
||||
@@ -198,7 +198,7 @@ const struct Curl_handler Curl_handler_telnet = {
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
static CURLcode
|
||||
check_wsock2 ( struct SessionHandle *data )
|
||||
check_wsock2(struct SessionHandle *data)
|
||||
{
|
||||
int err;
|
||||
WORD wVersionRequested;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -57,10 +57,10 @@
|
||||
#include "url.h"
|
||||
#include "rawstr.h"
|
||||
#include "speedcheck.h"
|
||||
#include "curl_printf.h"
|
||||
#include "select.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -312,14 +312,14 @@ static const char *tftp_option_get(const char *buf, size_t len,
|
||||
{
|
||||
size_t loc;
|
||||
|
||||
loc = Curl_strnlen( buf, len );
|
||||
loc = Curl_strnlen(buf, len);
|
||||
loc++; /* NULL term */
|
||||
|
||||
if(loc >= len)
|
||||
return NULL;
|
||||
*option = buf;
|
||||
|
||||
loc += Curl_strnlen( buf+loc, len-loc );
|
||||
loc += Curl_strnlen(buf+loc, len-loc);
|
||||
loc++; /* NULL term */
|
||||
|
||||
if(loc > len)
|
||||
@@ -352,7 +352,7 @@ static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
|
||||
if(checkprefix(option, TFTP_OPTION_BLKSIZE)) {
|
||||
long blksize;
|
||||
|
||||
blksize = strtol( value, NULL, 10 );
|
||||
blksize = strtol(value, NULL, 10);
|
||||
|
||||
if(!blksize) {
|
||||
failf(data, "invalid blocksize value in OACK packet");
|
||||
@@ -384,7 +384,7 @@ static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
|
||||
else if(checkprefix(option, TFTP_OPTION_TSIZE)) {
|
||||
long tsize = 0;
|
||||
|
||||
tsize = strtol( value, NULL, 10 );
|
||||
tsize = strtol(value, NULL, 10);
|
||||
infof(data, "%s (%ld)\n", "tsize parsed from OACK", tsize);
|
||||
|
||||
/* tsize should be ignored on upload: Who cares about the size of the
|
||||
@@ -405,7 +405,7 @@ static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
|
||||
static size_t tftp_option_add(tftp_state_data_t *state, size_t csize,
|
||||
char *buf, const char *option)
|
||||
{
|
||||
if(( strlen(option) + csize + 1 ) > (size_t)state->blksize)
|
||||
if(( strlen(option) + csize + 1) > (size_t)state->blksize)
|
||||
return 0;
|
||||
strcpy(buf, option);
|
||||
return strlen(option) + 1;
|
||||
@@ -514,7 +514,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
(char *)state->spacket.data+sbytes,
|
||||
TFTP_OPTION_BLKSIZE);
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes, buf );
|
||||
(char *)state->spacket.data+sbytes, buf);
|
||||
|
||||
/* add timeout option */
|
||||
snprintf(buf, sizeof(buf), "%d", state->retry_time);
|
||||
@@ -522,7 +522,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
(char *)state->spacket.data+sbytes,
|
||||
TFTP_OPTION_INTERVAL);
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes, buf );
|
||||
(char *)state->spacket.data+sbytes, buf);
|
||||
}
|
||||
|
||||
/* the typecase for the 3rd argument is mostly for systems that do
|
||||
@@ -960,7 +960,7 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
|
||||
/* alloc pkt buffers based on specified blksize */
|
||||
if(conn->data->set.tftp_blksize) {
|
||||
blksize = (int)conn->data->set.tftp_blksize;
|
||||
if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN )
|
||||
if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN)
|
||||
return CURLE_TFTP_ILLEGAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,9 +75,9 @@
|
||||
#include "multiif.h"
|
||||
#include "connect.h"
|
||||
#include "non-ascii.h"
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -694,7 +694,7 @@ static CURLcode readwrite_data(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
nread = (ssize_t) (k->maxdownload - k->bytecount);
|
||||
if(nread < 0 ) /* this should be unusual */
|
||||
if(nread < 0) /* this should be unusual */
|
||||
nread = 0;
|
||||
|
||||
k->keepon &= ~KEEP_RECV; /* we're done reading */
|
||||
@@ -779,7 +779,7 @@ static CURLcode readwrite_data(struct SessionHandle *data,
|
||||
return result;
|
||||
}
|
||||
|
||||
} /* if(! header and data to read ) */
|
||||
} /* if(!header and data to read) */
|
||||
|
||||
if(conn->handler->readwrite &&
|
||||
(excess > 0 && !conn->bits.stream_was_rewound)) {
|
||||
@@ -805,7 +805,7 @@ static CURLcode readwrite_data(struct SessionHandle *data,
|
||||
} while(data_pending(conn) && maxloops--);
|
||||
|
||||
if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) &&
|
||||
conn->bits.close ) {
|
||||
conn->bits.close) {
|
||||
/* When we've read the entire thing and the close bit is set, the server
|
||||
may now close the connection. If there's now any kind of sending going
|
||||
on from our side, we need to stop that immediately. */
|
||||
@@ -816,6 +816,20 @@ static CURLcode readwrite_data(struct SessionHandle *data,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode done_sending(struct connectdata *conn,
|
||||
struct SingleRequest *k)
|
||||
{
|
||||
k->keepon &= ~KEEP_SEND; /* we're done writing */
|
||||
|
||||
if(conn->bits.rewindaftersend) {
|
||||
CURLcode result = Curl_readrewind(conn);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Send data to upload to the server, when the socket is writable.
|
||||
*/
|
||||
@@ -887,14 +901,9 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
|
||||
break;
|
||||
}
|
||||
else if(nread<=0) {
|
||||
/* done */
|
||||
k->keepon &= ~KEEP_SEND; /* we're done writing */
|
||||
|
||||
if(conn->bits.rewindaftersend) {
|
||||
result = Curl_readrewind(conn);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
result = done_sending(conn, k);
|
||||
if(result)
|
||||
return result;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1004,8 +1013,9 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
|
||||
data->req.upload_present = 0; /* no more bytes left */
|
||||
|
||||
if(k->upload_done) {
|
||||
/* switch off writing, we're done! */
|
||||
k->keepon &= ~KEEP_SEND; /* we're done writing */
|
||||
result = done_sending(conn, k);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1375,6 +1385,16 @@ CURLcode Curl_pretransfer(struct SessionHandle *data)
|
||||
consider to be fine */
|
||||
data->state.authhost.picked &= data->state.authhost.want;
|
||||
data->state.authproxy.picked &= data->state.authproxy.want;
|
||||
|
||||
if(data->set.wildcardmatch) {
|
||||
struct WildcardData *wc = &data->wildcard;
|
||||
if(!wc->filelist) {
|
||||
result = Curl_wildcard_init(wc); /* init wildcard structures */
|
||||
if(result)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -1838,63 +1858,6 @@ CURLcode Curl_follow(struct SessionHandle *data,
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
}
|
||||
|
||||
CURLcode
|
||||
Curl_reconnect_request(struct connectdata **connp)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn = *connp;
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
/* This was a re-use of a connection and we got a write error in the
|
||||
* DO-phase. Then we DISCONNECT this connection and have another attempt to
|
||||
* CONNECT and then DO again! The retry cannot possibly find another
|
||||
* connection to re-use, since we only keep one possible connection for
|
||||
* each. */
|
||||
|
||||
infof(data, "Re-used connection seems dead, get a new one\n");
|
||||
|
||||
connclose(conn, "Reconnect dead connection"); /* enforce close */
|
||||
result = Curl_done(&conn, result, FALSE); /* we are so done with this */
|
||||
|
||||
/* conn may no longer be a good pointer, clear it to avoid mistakes by
|
||||
parent functions */
|
||||
*connp = NULL;
|
||||
|
||||
/*
|
||||
* According to bug report #1330310. We need to check for CURLE_SEND_ERROR
|
||||
* here as well. I figure this could happen when the request failed on a FTP
|
||||
* connection and thus Curl_done() itself tried to use the connection
|
||||
* (again). Slight Lack of feedback in the report, but I don't think this
|
||||
* extra check can do much harm.
|
||||
*/
|
||||
if(!result || (CURLE_SEND_ERROR == result)) {
|
||||
bool async;
|
||||
bool protocol_done = TRUE;
|
||||
|
||||
/* Now, redo the connect and get a new connection */
|
||||
result = Curl_connect(data, connp, &async, &protocol_done);
|
||||
if(!result) {
|
||||
/* We have connected or sent away a name resolve query fine */
|
||||
|
||||
conn = *connp; /* setup conn to again point to something nice */
|
||||
if(async) {
|
||||
/* Now, if async is TRUE here, we need to wait for the name
|
||||
to resolve */
|
||||
result = Curl_resolver_wait_resolv(conn, NULL);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Resolved, continue with the connection */
|
||||
result = Curl_async_resolved(conn, &protocol_done);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Returns CURLE_OK *and* sets '*url' if a request retry is wanted.
|
||||
|
||||
NOTE: that the *url is malloc()ed. */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -49,7 +49,6 @@ int Curl_single_getsock(const struct connectdata *conn,
|
||||
int numsocks);
|
||||
CURLcode Curl_readrewind(struct connectdata *conn);
|
||||
CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp);
|
||||
CURLcode Curl_reconnect_request(struct connectdata **connp);
|
||||
CURLcode Curl_retry_request(struct connectdata *conn, char **url);
|
||||
bool Curl_meets_timecondition(struct SessionHandle *data, time_t timeofdoc);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -37,9 +37,6 @@ void Curl_freeset(struct SessionHandle * data);
|
||||
CURLcode Curl_close(struct SessionHandle *data); /* opposite of curl_open() */
|
||||
CURLcode Curl_connect(struct SessionHandle *, struct connectdata **,
|
||||
bool *async, bool *protocol_connect);
|
||||
CURLcode Curl_do(struct connectdata **, bool *done);
|
||||
CURLcode Curl_do_more(struct connectdata *, int *completed);
|
||||
CURLcode Curl_done(struct connectdata **, CURLcode, bool premature);
|
||||
CURLcode Curl_disconnect(struct connectdata *, bool dead_connection);
|
||||
CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
|
||||
@@ -60,6 +57,8 @@ CURLcode Curl_addHandleToPipeline(struct SessionHandle *handle,
|
||||
struct curl_llist *pipeline);
|
||||
int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
|
||||
struct curl_llist *pipeline);
|
||||
struct connectdata *
|
||||
Curl_oldest_idle_connection(struct SessionHandle *data);
|
||||
/* remove the specified connection from all (possible) pipelines and related
|
||||
queues */
|
||||
void Curl_getoff_all_pipelines(struct SessionHandle *data,
|
||||
@@ -68,11 +67,6 @@ void Curl_getoff_all_pipelines(struct SessionHandle *data,
|
||||
void Curl_close_connections(struct SessionHandle *data);
|
||||
|
||||
#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
|
||||
#define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi
|
||||
service */
|
||||
#define CURL_DEFAULT_PROXY_SERVICE_NAME "HTTP" /* default negotiate proxy
|
||||
service */
|
||||
#define CURL_DEFAULT_SERVICE_NAME "HTTP" /* default negotiate service */
|
||||
|
||||
CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex);
|
||||
|
||||
|
||||
@@ -290,7 +290,6 @@ struct ssl_connect_data {
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_ssl_session ssn;
|
||||
int server_fd;
|
||||
mbedtls_x509_crt cacert;
|
||||
mbedtls_x509_crt clicert;
|
||||
@@ -302,7 +301,6 @@ struct ssl_connect_data {
|
||||
ctr_drbg_context ctr_drbg;
|
||||
entropy_context entropy;
|
||||
ssl_context ssl;
|
||||
ssl_session ssn;
|
||||
int server_fd;
|
||||
x509_crt cacert;
|
||||
x509_crt clicert;
|
||||
@@ -375,10 +373,12 @@ struct ssl_config_data {
|
||||
/* information stored about one single SSL session */
|
||||
struct curl_ssl_session {
|
||||
char *name; /* host name for which this ID was used */
|
||||
char *conn_to_host; /* host name for the connection (may be NULL) */
|
||||
void *sessionid; /* as returned from the SSL layer */
|
||||
size_t idsize; /* if known, otherwise 0 */
|
||||
long age; /* just a number, the higher the more recent */
|
||||
int remote_port; /* remote port to connect to */
|
||||
int remote_port; /* remote port */
|
||||
int conn_to_port; /* remote port for the connection (may be -1) */
|
||||
struct ssl_config_data ssl_config; /* setup for this session */
|
||||
};
|
||||
|
||||
@@ -464,7 +464,7 @@ struct negotiatedata {
|
||||
#ifdef HAVE_GSSAPI
|
||||
OM_uint32 status;
|
||||
gss_ctx_id_t context;
|
||||
gss_name_t server_name;
|
||||
gss_name_t spn;
|
||||
gss_buffer_desc output_token;
|
||||
#else
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
@@ -473,7 +473,7 @@ struct negotiatedata {
|
||||
CtxtHandle *context;
|
||||
SEC_WINNT_AUTH_IDENTITY identity;
|
||||
SEC_WINNT_AUTH_IDENTITY *p_identity;
|
||||
TCHAR *server_name;
|
||||
TCHAR *spn;
|
||||
size_t token_max;
|
||||
BYTE *output_token;
|
||||
size_t output_token_length;
|
||||
@@ -490,6 +490,10 @@ struct ConnectBits {
|
||||
/* always modify bits.close with the connclose() and connkeep() macros! */
|
||||
bool close; /* if set, we close the connection after this request */
|
||||
bool reuse; /* if set, this is a re-used connection */
|
||||
bool conn_to_host; /* if set, this connection has a "connect to host"
|
||||
that overrides the host in the URL */
|
||||
bool conn_to_port; /* if set, this connection has a "connect to port"
|
||||
that overrides the port in the URL (remote port) */
|
||||
bool proxy; /* if set, this transfer is done through a proxy - any type */
|
||||
bool httpproxy; /* if set, this transfer is done through a http proxy */
|
||||
bool user_passwd; /* do we use user+password for this connection? */
|
||||
@@ -538,6 +542,10 @@ struct ConnectBits {
|
||||
connection */
|
||||
bool type_set; /* type= was used in the URL */
|
||||
bool multiplex; /* connection is multiplexed */
|
||||
|
||||
bool tcp_fastopen; /* use TCP Fast Open */
|
||||
bool tls_enable_npn; /* TLS NPN extension? */
|
||||
bool tls_enable_alpn; /* TLS ALPN extension? */
|
||||
};
|
||||
|
||||
struct hostname {
|
||||
@@ -809,7 +817,7 @@ struct Curl_handler {
|
||||
url query strings (?foo=bar) ! */
|
||||
#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login credentials per
|
||||
request instead of per connection */
|
||||
|
||||
#define PROTOPT_ALPN_NPN (1<<8) /* set ALPN and/or NPN for this */
|
||||
|
||||
/* return the count of bytes sent, or -1 on error */
|
||||
typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
|
||||
@@ -825,6 +833,20 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
|
||||
size_t len, /* max amount to read */
|
||||
CURLcode *err); /* error to return */
|
||||
|
||||
#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
|
||||
struct postponed_data {
|
||||
char *buffer; /* Temporal store for received data during
|
||||
sending, must be freed */
|
||||
size_t allocated_size; /* Size of temporal store */
|
||||
size_t recv_size; /* Size of received data during sending */
|
||||
size_t recv_processed; /* Size of processed part of postponed data */
|
||||
#ifdef DEBUGBUILD
|
||||
curl_socket_t bindsock;/* Structure must be bound to specific socket,
|
||||
used only for DEBUGASSERT */
|
||||
#endif /* DEBUGBUILD */
|
||||
};
|
||||
#endif /* USE_RECV_BEFORE_SEND_WORKAROUND */
|
||||
|
||||
/*
|
||||
* The connectdata struct contains all fields and variables that should be
|
||||
* unique for an entire connection.
|
||||
@@ -874,10 +896,14 @@ struct connectdata {
|
||||
int socktype; /* SOCK_STREAM or SOCK_DGRAM */
|
||||
|
||||
struct hostname host;
|
||||
struct hostname conn_to_host; /* the host to connect to. valid only if
|
||||
bits.conn_to_host is set */
|
||||
struct hostname proxy;
|
||||
|
||||
long port; /* which port to use locally */
|
||||
int remote_port; /* what remote port to connect to, not the proxy port! */
|
||||
int remote_port; /* the remote port, not the proxy port! */
|
||||
int conn_to_port; /* the remote port to connect to. valid only if
|
||||
bits.conn_to_port is set */
|
||||
|
||||
/* 'primary_ip' and 'primary_port' get filled with peer's numerical
|
||||
ip address and port number whenever an outgoing connection is
|
||||
@@ -919,6 +945,9 @@ struct connectdata {
|
||||
Curl_recv *recv[2];
|
||||
Curl_send *send[2];
|
||||
|
||||
#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
|
||||
struct postponed_data postponed[2]; /* two buffers for two sockets */
|
||||
#endif /* USE_RECV_BEFORE_SEND_WORKAROUND */
|
||||
struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
|
||||
struct ssl_config_data ssl_config;
|
||||
bool tls_upgraded;
|
||||
@@ -1226,11 +1255,13 @@ struct UrlState {
|
||||
bytes / second */
|
||||
bool this_is_a_follow; /* this is a followed Location: request */
|
||||
|
||||
char *first_host; /* if set, this should be the host name that we will
|
||||
char *first_host; /* host name of the first (not followed) request.
|
||||
if set, this should be the host name that we will
|
||||
sent authorization to, no else. Used to make Location:
|
||||
following not keep sending user+password... This is
|
||||
strdup() data.
|
||||
*/
|
||||
int first_remote_port; /* remote port of the first (not followed) request */
|
||||
struct curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
|
||||
long sessionage; /* number of the most recent session */
|
||||
char *tempwrite; /* allocated buffer to keep data in when a write
|
||||
@@ -1314,9 +1345,9 @@ struct UrlState {
|
||||
curl_off_t infilesize; /* size of file to upload, -1 means unknown.
|
||||
Copied from set.filesize at start of operation */
|
||||
|
||||
int drain; /* Increased when this stream has data to read, even if its
|
||||
socket not necessarily is readable. Decreased when
|
||||
checked. */
|
||||
size_t drain; /* Increased when this stream has data to read, even if its
|
||||
socket is not necessarily is readable. Decreased when
|
||||
checked. */
|
||||
bool done; /* set to FALSE when Curl_do() is called and set to TRUE when
|
||||
Curl_done() is called, to prevent Curl_done() to get invoked
|
||||
twice when the multi interface is used. */
|
||||
@@ -1407,8 +1438,10 @@ enum dupstring {
|
||||
STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */
|
||||
#endif
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
STRING_SOCKS5_GSSAPI_SERVICE, /* GSSAPI service name */
|
||||
STRING_PROXY_SERVICE_NAME, /* Proxy service name */
|
||||
#endif
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
|
||||
defined(USE_SPNEGO)
|
||||
STRING_SERVICE_NAME, /* Service name */
|
||||
#endif
|
||||
STRING_MAIL_FROM,
|
||||
@@ -1526,6 +1559,8 @@ struct UserDefined {
|
||||
struct curl_slist *telnet_options; /* linked list of telnet options */
|
||||
struct curl_slist *resolve; /* list of names to add/remove from
|
||||
DNS cache */
|
||||
struct curl_slist *connect_to; /* list of host:port mappings to override
|
||||
the hostname and port to connect to */
|
||||
curl_TimeCond timecondition; /* kind of time/date comparison */
|
||||
time_t timevalue; /* what time to compare with */
|
||||
Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
|
||||
@@ -1573,7 +1608,6 @@ struct UserDefined {
|
||||
bool http_set_referer; /* is a custom referer used */
|
||||
bool http_auto_referer; /* set "correct" referer when following location: */
|
||||
bool opt_no_body; /* as set with CURLOPT_NOBODY */
|
||||
bool set_port; /* custom port number used */
|
||||
bool upload; /* upload request */
|
||||
enum CURL_NETRC_OPTION
|
||||
use_netrc; /* defined in include/curl.h */
|
||||
@@ -1613,7 +1647,7 @@ struct UserDefined {
|
||||
long allowed_protocols;
|
||||
long redir_protocols;
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
long socks5_gssapi_nec; /* flag to support nec socks5 server */
|
||||
bool socks5_gssapi_nec; /* Flag to support NEC SOCKS5 server */
|
||||
#endif
|
||||
struct curl_slist *mail_rcpt; /* linked list of mail recipients */
|
||||
bool sasl_ir; /* Enable/disable SASL initial response */
|
||||
@@ -1635,11 +1669,12 @@ struct UserDefined {
|
||||
bool tcp_keepalive; /* use TCP keepalives */
|
||||
long tcp_keepidle; /* seconds in idle before sending keepalive probe */
|
||||
long tcp_keepintvl; /* seconds between TCP keepalive probes */
|
||||
bool tcp_fastopen; /* use TCP Fast Open */
|
||||
|
||||
size_t maxconnects; /* Max idle connections in the connection cache */
|
||||
|
||||
bool ssl_enable_npn; /* TLS NPN extension? */
|
||||
bool ssl_enable_alpn; /* TLS ALPN extension? */
|
||||
bool ssl_enable_npn; /* TLS NPN extension? */
|
||||
bool ssl_enable_alpn; /* TLS ALPN extension? */
|
||||
bool path_as_is; /* allow dotdots? */
|
||||
bool pipewait; /* wait for pipe/multiplex status before starting a
|
||||
new connection */
|
||||
|
||||
157
project/jni/curl/lib/vauth/cleartext.c
Normal file
157
project/jni/curl/lib/vauth/cleartext.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, 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.haxx.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.
|
||||
*
|
||||
* RFC4616 PLAIN authentication
|
||||
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "urldata.h"
|
||||
|
||||
#include "vauth/vauth.h"
|
||||
#include "curl_base64.h"
|
||||
#include "curl_md5.h"
|
||||
#include "warnless.h"
|
||||
#include "strtok.h"
|
||||
#include "strequal.h"
|
||||
#include "rawstr.h"
|
||||
#include "sendf.h"
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
* Curl_auth_create_plain_message()
|
||||
*
|
||||
* This is used to generate an already encoded PLAIN message ready
|
||||
* for sending to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* userp [in] - The user name.
|
||||
* passdwp [in] - The user's password.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_create_plain_message(struct SessionHandle *data,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
CURLcode result;
|
||||
char *plainauth;
|
||||
size_t ulen;
|
||||
size_t plen;
|
||||
|
||||
ulen = strlen(userp);
|
||||
plen = strlen(passwdp);
|
||||
|
||||
plainauth = malloc(2 * ulen + plen + 2);
|
||||
if(!plainauth) {
|
||||
*outlen = 0;
|
||||
*outptr = NULL;
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Calculate the reply */
|
||||
memcpy(plainauth, userp, ulen);
|
||||
plainauth[ulen] = '\0';
|
||||
memcpy(plainauth + ulen + 1, userp, ulen);
|
||||
plainauth[2 * ulen + 1] = '\0';
|
||||
memcpy(plainauth + 2 * ulen + 2, passwdp, plen);
|
||||
|
||||
/* Base64 encode the reply */
|
||||
result = Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr,
|
||||
outlen);
|
||||
free(plainauth);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_create_login_message()
|
||||
*
|
||||
* This is used to generate an already encoded LOGIN message containing the
|
||||
* user name or password ready for sending to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* valuep [in] - The user name or user's password.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_create_login_message(struct SessionHandle *data,
|
||||
const char *valuep, char **outptr,
|
||||
size_t *outlen)
|
||||
{
|
||||
size_t vlen = strlen(valuep);
|
||||
|
||||
if(!vlen) {
|
||||
/* Calculate an empty reply */
|
||||
*outptr = strdup("=");
|
||||
if(*outptr) {
|
||||
*outlen = (size_t) 1;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
*outlen = 0;
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Base64 encode the value */
|
||||
return Curl_base64_encode(data, valuep, vlen, outptr, outlen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_create_external_message()
|
||||
*
|
||||
* This is used to generate an already encoded EXTERNAL message containing
|
||||
* the user name ready for sending to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* user [in] - The user name.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_create_external_message(struct SessionHandle *data,
|
||||
const char *user, char **outptr,
|
||||
size_t *outlen)
|
||||
{
|
||||
/* This is the same formatting as the login message */
|
||||
return Curl_auth_create_login_message(data, user, outptr, outlen);
|
||||
}
|
||||
138
project/jni/curl/lib/vauth/cram.c
Normal file
138
project/jni/curl/lib/vauth/cram.c
Normal file
@@ -0,0 +1,138 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, 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.haxx.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.
|
||||
*
|
||||
* RFC2195 CRAM-MD5 authentication
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "urldata.h"
|
||||
|
||||
#include "vauth/vauth.h"
|
||||
#include "curl_base64.h"
|
||||
#include "curl_hmac.h"
|
||||
#include "curl_md5.h"
|
||||
#include "warnless.h"
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
* Curl_auth_decode_cram_md5_message()
|
||||
*
|
||||
* This is used to decode an already encoded CRAM-MD5 challenge message.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* chlg64 [in] - The base64 encoded challenge message.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr,
|
||||
size_t *outlen)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
size_t chlg64len = strlen(chlg64);
|
||||
|
||||
*outptr = NULL;
|
||||
*outlen = 0;
|
||||
|
||||
/* Decode the challenge if necessary */
|
||||
if(chlg64len && *chlg64 != '=')
|
||||
result = Curl_base64_decode(chlg64, (unsigned char **) outptr, outlen);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_create_cram_md5_message()
|
||||
*
|
||||
* This is used to generate an already encoded CRAM-MD5 response message ready
|
||||
* for sending to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* chlg [in] - The challenge.
|
||||
* userp [in] - The user name.
|
||||
* passdwp [in] - The user's password.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_create_cram_md5_message(struct SessionHandle *data,
|
||||
const char *chlg,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
size_t chlglen = 0;
|
||||
HMAC_context *ctxt;
|
||||
unsigned char digest[MD5_DIGEST_LEN];
|
||||
char *response;
|
||||
|
||||
if(chlg)
|
||||
chlglen = strlen(chlg);
|
||||
|
||||
/* Compute the digest using the password as the key */
|
||||
ctxt = Curl_HMAC_init(Curl_HMAC_MD5,
|
||||
(const unsigned char *) passwdp,
|
||||
curlx_uztoui(strlen(passwdp)));
|
||||
if(!ctxt)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Update the digest with the given challenge */
|
||||
if(chlglen > 0)
|
||||
Curl_HMAC_update(ctxt, (const unsigned char *) chlg,
|
||||
curlx_uztoui(chlglen));
|
||||
|
||||
/* Finalise the digest */
|
||||
Curl_HMAC_final(ctxt, digest);
|
||||
|
||||
/* Generate the response */
|
||||
response = aprintf(
|
||||
"%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
userp, digest[0], digest[1], digest[2], digest[3], digest[4],
|
||||
digest[5], digest[6], digest[7], digest[8], digest[9], digest[10],
|
||||
digest[11], digest[12], digest[13], digest[14], digest[15]);
|
||||
if(!response)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Base64 encode the response */
|
||||
result = Curl_base64_encode(data, response, 0, outptr, outlen);
|
||||
|
||||
free(response);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* !CURL_DISABLE_CRYPTO_AUTH */
|
||||
883
project/jni/curl/lib/vauth/digest.c
Normal file
883
project/jni/curl/lib/vauth/digest.c
Normal file
@@ -0,0 +1,883 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, 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.haxx.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.
|
||||
*
|
||||
* RFC2831 DIGEST-MD5 authentication
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "vauth/vauth.h"
|
||||
#include "vauth/digest.h"
|
||||
#include "urldata.h"
|
||||
#include "curl_base64.h"
|
||||
#include "curl_hmac.h"
|
||||
#include "curl_md5.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "warnless.h"
|
||||
#include "strtok.h"
|
||||
#include "rawstr.h"
|
||||
#include "non-ascii.h" /* included for Curl_convert_... prototypes */
|
||||
#include "curl_printf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
#if !defined(USE_WINDOWS_SSPI)
|
||||
#define DIGEST_QOP_VALUE_AUTH (1 << 0)
|
||||
#define DIGEST_QOP_VALUE_AUTH_INT (1 << 1)
|
||||
#define DIGEST_QOP_VALUE_AUTH_CONF (1 << 2)
|
||||
|
||||
#define DIGEST_QOP_VALUE_STRING_AUTH "auth"
|
||||
#define DIGEST_QOP_VALUE_STRING_AUTH_INT "auth-int"
|
||||
#define DIGEST_QOP_VALUE_STRING_AUTH_CONF "auth-conf"
|
||||
|
||||
/* The CURL_OUTPUT_DIGEST_CONV macro below is for non-ASCII machines.
|
||||
It converts digest text to ASCII so the MD5 will be correct for
|
||||
what ultimately goes over the network.
|
||||
*/
|
||||
#define CURL_OUTPUT_DIGEST_CONV(a, b) \
|
||||
result = Curl_convert_to_network(a, (char *)b, strlen((const char*)b)); \
|
||||
if(result) { \
|
||||
free(b); \
|
||||
return result; \
|
||||
}
|
||||
#endif /* !USE_WINDOWS_SSPI */
|
||||
|
||||
bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
|
||||
const char **endptr)
|
||||
{
|
||||
int c;
|
||||
bool starts_with_quote = FALSE;
|
||||
bool escape = FALSE;
|
||||
|
||||
for(c = DIGEST_MAX_VALUE_LENGTH - 1; (*str && (*str != '=') && c--);)
|
||||
*value++ = *str++;
|
||||
*value = 0;
|
||||
|
||||
if('=' != *str++)
|
||||
/* eek, no match */
|
||||
return FALSE;
|
||||
|
||||
if('\"' == *str) {
|
||||
/* This starts with a quote so it must end with one as well! */
|
||||
str++;
|
||||
starts_with_quote = TRUE;
|
||||
}
|
||||
|
||||
for(c = DIGEST_MAX_CONTENT_LENGTH - 1; *str && c--; str++) {
|
||||
switch(*str) {
|
||||
case '\\':
|
||||
if(!escape) {
|
||||
/* possibly the start of an escaped quote */
|
||||
escape = TRUE;
|
||||
*content++ = '\\'; /* Even though this is an escape character, we still
|
||||
store it as-is in the target buffer */
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case ',':
|
||||
if(!starts_with_quote) {
|
||||
/* This signals the end of the content if we didn't get a starting
|
||||
quote and then we do "sloppy" parsing */
|
||||
c = 0; /* the end */
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
case '\n':
|
||||
/* end of string */
|
||||
c = 0;
|
||||
continue;
|
||||
|
||||
case '\"':
|
||||
if(!escape && starts_with_quote) {
|
||||
/* end of string */
|
||||
c = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
escape = FALSE;
|
||||
*content++ = *str;
|
||||
}
|
||||
|
||||
*content = 0;
|
||||
*endptr = str;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if !defined(USE_WINDOWS_SSPI)
|
||||
/* Convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/
|
||||
static void auth_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */
|
||||
unsigned char *dest) /* 33 bytes */
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 16; i++)
|
||||
snprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
|
||||
}
|
||||
|
||||
/* Perform quoted-string escaping as described in RFC2616 and its errata */
|
||||
static char *auth_digest_string_quoted(const char *source)
|
||||
{
|
||||
char *dest, *d;
|
||||
const char *s = source;
|
||||
size_t n = 1; /* null terminator */
|
||||
|
||||
/* Calculate size needed */
|
||||
while(*s) {
|
||||
++n;
|
||||
if(*s == '"' || *s == '\\') {
|
||||
++n;
|
||||
}
|
||||
++s;
|
||||
}
|
||||
|
||||
dest = malloc(n);
|
||||
if(dest) {
|
||||
s = source;
|
||||
d = dest;
|
||||
while(*s) {
|
||||
if(*s == '"' || *s == '\\') {
|
||||
*d++ = '\\';
|
||||
}
|
||||
*d++ = *s++;
|
||||
}
|
||||
*d = 0;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Retrieves the value for a corresponding key from the challenge string
|
||||
* returns TRUE if the key could be found, FALSE if it does not exists
|
||||
*/
|
||||
static bool auth_digest_get_key_value(const char *chlg,
|
||||
const char *key,
|
||||
char *value,
|
||||
size_t max_val_len,
|
||||
char end_char)
|
||||
{
|
||||
char *find_pos;
|
||||
size_t i;
|
||||
|
||||
find_pos = strstr(chlg, key);
|
||||
if(!find_pos)
|
||||
return FALSE;
|
||||
|
||||
find_pos += strlen(key);
|
||||
|
||||
for(i = 0; *find_pos && *find_pos != end_char && i < max_val_len - 1; ++i)
|
||||
value[i] = *find_pos++;
|
||||
value[i] = '\0';
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CURLcode auth_digest_get_qop_values(const char *options, int *value)
|
||||
{
|
||||
char *tmp;
|
||||
char *token;
|
||||
char *tok_buf;
|
||||
|
||||
/* Initialise the output */
|
||||
*value = 0;
|
||||
|
||||
/* Tokenise the list of qop values. Use a temporary clone of the buffer since
|
||||
strtok_r() ruins it. */
|
||||
tmp = strdup(options);
|
||||
if(!tmp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
token = strtok_r(tmp, ",", &tok_buf);
|
||||
while(token != NULL) {
|
||||
if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH))
|
||||
*value |= DIGEST_QOP_VALUE_AUTH;
|
||||
else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_INT))
|
||||
*value |= DIGEST_QOP_VALUE_AUTH_INT;
|
||||
else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_CONF))
|
||||
*value |= DIGEST_QOP_VALUE_AUTH_CONF;
|
||||
|
||||
token = strtok_r(NULL, ",", &tok_buf);
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* auth_decode_digest_md5_message()
|
||||
*
|
||||
* This is used internally to decode an already encoded DIGEST-MD5 challenge
|
||||
* message into the seperate attributes.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* chlg64 [in] - The base64 encoded challenge message.
|
||||
* nonce [in/out] - The buffer where the nonce will be stored.
|
||||
* nlen [in] - The length of the nonce buffer.
|
||||
* realm [in/out] - The buffer where the realm will be stored.
|
||||
* rlen [in] - The length of the realm buffer.
|
||||
* alg [in/out] - The buffer where the algorithm will be stored.
|
||||
* alen [in] - The length of the algorithm buffer.
|
||||
* qop [in/out] - The buffer where the qop-options will be stored.
|
||||
* qlen [in] - The length of the qop buffer.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
static CURLcode auth_decode_digest_md5_message(const char *chlg64,
|
||||
char *nonce, size_t nlen,
|
||||
char *realm, size_t rlen,
|
||||
char *alg, size_t alen,
|
||||
char *qop, size_t qlen)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
unsigned char *chlg = NULL;
|
||||
size_t chlglen = 0;
|
||||
size_t chlg64len = strlen(chlg64);
|
||||
|
||||
/* Decode the base-64 encoded challenge message */
|
||||
if(chlg64len && *chlg64 != '=') {
|
||||
result = Curl_base64_decode(chlg64, &chlg, &chlglen);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Ensure we have a valid challenge message */
|
||||
if(!chlg)
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
|
||||
/* Retrieve nonce string from the challenge */
|
||||
if(!auth_digest_get_key_value((char *) chlg, "nonce=\"", nonce, nlen,
|
||||
'\"')) {
|
||||
free(chlg);
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
/* Retrieve realm string from the challenge */
|
||||
if(!auth_digest_get_key_value((char *) chlg, "realm=\"", realm, rlen,
|
||||
'\"')) {
|
||||
/* Challenge does not have a realm, set empty string [RFC2831] page 6 */
|
||||
strcpy(realm, "");
|
||||
}
|
||||
|
||||
/* Retrieve algorithm string from the challenge */
|
||||
if(!auth_digest_get_key_value((char *) chlg, "algorithm=", alg, alen, ',')) {
|
||||
free(chlg);
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
/* Retrieve qop-options string from the challenge */
|
||||
if(!auth_digest_get_key_value((char *) chlg, "qop=\"", qop, qlen, '\"')) {
|
||||
free(chlg);
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
free(chlg);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_create_digest_md5_message()
|
||||
*
|
||||
* This is used to generate an already encoded DIGEST-MD5 response message
|
||||
* ready for sending to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* chlg64 [in] - The base64 encoded challenge message.
|
||||
* userp [in] - The user name.
|
||||
* passdwp [in] - The user's password.
|
||||
* service [in] - The service type such as http, smtp, pop or imap.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_create_digest_md5_message(struct SessionHandle *data,
|
||||
const char *chlg64,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
const char *service,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
size_t i;
|
||||
MD5_context *ctxt;
|
||||
char *response = NULL;
|
||||
unsigned char digest[MD5_DIGEST_LEN];
|
||||
char HA1_hex[2 * MD5_DIGEST_LEN + 1];
|
||||
char HA2_hex[2 * MD5_DIGEST_LEN + 1];
|
||||
char resp_hash_hex[2 * MD5_DIGEST_LEN + 1];
|
||||
char nonce[64];
|
||||
char realm[128];
|
||||
char algorithm[64];
|
||||
char qop_options[64];
|
||||
int qop_values;
|
||||
char cnonce[33];
|
||||
unsigned int entropy[4];
|
||||
char nonceCount[] = "00000001";
|
||||
char method[] = "AUTHENTICATE";
|
||||
char qop[] = DIGEST_QOP_VALUE_STRING_AUTH;
|
||||
char *spn = NULL;
|
||||
|
||||
/* Decode the challange message */
|
||||
result = auth_decode_digest_md5_message(chlg64, nonce, sizeof(nonce),
|
||||
realm, sizeof(realm),
|
||||
algorithm, sizeof(algorithm),
|
||||
qop_options, sizeof(qop_options));
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* We only support md5 sessions */
|
||||
if(strcmp(algorithm, "md5-sess") != 0)
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
|
||||
/* Get the qop-values from the qop-options */
|
||||
result = auth_digest_get_qop_values(qop_options, &qop_values);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* We only support auth quality-of-protection */
|
||||
if(!(qop_values & DIGEST_QOP_VALUE_AUTH))
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
|
||||
/* Generate 16 bytes of random data */
|
||||
entropy[0] = Curl_rand(data);
|
||||
entropy[1] = Curl_rand(data);
|
||||
entropy[2] = Curl_rand(data);
|
||||
entropy[3] = Curl_rand(data);
|
||||
|
||||
/* Convert the random data into a 32 byte hex string */
|
||||
snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x",
|
||||
entropy[0], entropy[1], entropy[2], entropy[3]);
|
||||
|
||||
/* So far so good, now calculate A1 and H(A1) according to RFC 2831 */
|
||||
ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
|
||||
if(!ctxt)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) userp,
|
||||
curlx_uztoui(strlen(userp)));
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) realm,
|
||||
curlx_uztoui(strlen(realm)));
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) passwdp,
|
||||
curlx_uztoui(strlen(passwdp)));
|
||||
Curl_MD5_final(ctxt, digest);
|
||||
|
||||
ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
|
||||
if(!ctxt)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) digest, MD5_DIGEST_LEN);
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) nonce,
|
||||
curlx_uztoui(strlen(nonce)));
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) cnonce,
|
||||
curlx_uztoui(strlen(cnonce)));
|
||||
Curl_MD5_final(ctxt, digest);
|
||||
|
||||
/* Convert calculated 16 octet hex into 32 bytes string */
|
||||
for(i = 0; i < MD5_DIGEST_LEN; i++)
|
||||
snprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]);
|
||||
|
||||
/* Generate our SPN */
|
||||
spn = Curl_auth_build_spn(service, realm, NULL);
|
||||
if(!spn)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Calculate H(A2) */
|
||||
ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
|
||||
if(!ctxt) {
|
||||
free(spn);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) method,
|
||||
curlx_uztoui(strlen(method)));
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) spn,
|
||||
curlx_uztoui(strlen(spn)));
|
||||
Curl_MD5_final(ctxt, digest);
|
||||
|
||||
for(i = 0; i < MD5_DIGEST_LEN; i++)
|
||||
snprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]);
|
||||
|
||||
/* Now calculate the response hash */
|
||||
ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
|
||||
if(!ctxt) {
|
||||
free(spn);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN);
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) nonce,
|
||||
curlx_uztoui(strlen(nonce)));
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
|
||||
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) nonceCount,
|
||||
curlx_uztoui(strlen(nonceCount)));
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) cnonce,
|
||||
curlx_uztoui(strlen(cnonce)));
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) qop,
|
||||
curlx_uztoui(strlen(qop)));
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
|
||||
|
||||
Curl_MD5_update(ctxt, (const unsigned char *) HA2_hex, 2 * MD5_DIGEST_LEN);
|
||||
Curl_MD5_final(ctxt, digest);
|
||||
|
||||
for(i = 0; i < MD5_DIGEST_LEN; i++)
|
||||
snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]);
|
||||
|
||||
/* Generate the response */
|
||||
response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\","
|
||||
"cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s,"
|
||||
"qop=%s",
|
||||
userp, realm, nonce,
|
||||
cnonce, nonceCount, spn, resp_hash_hex, qop);
|
||||
free(spn);
|
||||
if(!response)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Base64 encode the response */
|
||||
result = Curl_base64_encode(data, response, 0, outptr, outlen);
|
||||
|
||||
free(response);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_decode_digest_http_message()
|
||||
*
|
||||
* This is used to decode a HTTP DIGEST challenge message into the seperate
|
||||
* attributes.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* chlg [in] - The challenge message.
|
||||
* digest [in/out] - The digest data struct being used and modified.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
|
||||
struct digestdata *digest)
|
||||
{
|
||||
bool before = FALSE; /* got a nonce before */
|
||||
bool foundAuth = FALSE;
|
||||
bool foundAuthInt = FALSE;
|
||||
char *token = NULL;
|
||||
char *tmp = NULL;
|
||||
|
||||
/* If we already have received a nonce, keep that in mind */
|
||||
if(digest->nonce)
|
||||
before = TRUE;
|
||||
|
||||
/* Clean up any former leftovers and initialise to defaults */
|
||||
Curl_auth_digest_cleanup(digest);
|
||||
|
||||
for(;;) {
|
||||
char value[DIGEST_MAX_VALUE_LENGTH];
|
||||
char content[DIGEST_MAX_CONTENT_LENGTH];
|
||||
|
||||
/* Pass all additional spaces here */
|
||||
while(*chlg && ISSPACE(*chlg))
|
||||
chlg++;
|
||||
|
||||
/* Extract a value=content pair */
|
||||
if(Curl_auth_digest_get_pair(chlg, value, content, &chlg)) {
|
||||
if(Curl_raw_equal(value, "nonce")) {
|
||||
free(digest->nonce);
|
||||
digest->nonce = strdup(content);
|
||||
if(!digest->nonce)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else if(Curl_raw_equal(value, "stale")) {
|
||||
if(Curl_raw_equal(content, "true")) {
|
||||
digest->stale = TRUE;
|
||||
digest->nc = 1; /* we make a new nonce now */
|
||||
}
|
||||
}
|
||||
else if(Curl_raw_equal(value, "realm")) {
|
||||
free(digest->realm);
|
||||
digest->realm = strdup(content);
|
||||
if(!digest->realm)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else if(Curl_raw_equal(value, "opaque")) {
|
||||
free(digest->opaque);
|
||||
digest->opaque = strdup(content);
|
||||
if(!digest->opaque)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else if(Curl_raw_equal(value, "qop")) {
|
||||
char *tok_buf;
|
||||
/* Tokenize the list and choose auth if possible, use a temporary
|
||||
clone of the buffer since strtok_r() ruins it */
|
||||
tmp = strdup(content);
|
||||
if(!tmp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
token = strtok_r(tmp, ",", &tok_buf);
|
||||
while(token != NULL) {
|
||||
if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH)) {
|
||||
foundAuth = TRUE;
|
||||
}
|
||||
else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_INT)) {
|
||||
foundAuthInt = TRUE;
|
||||
}
|
||||
token = strtok_r(NULL, ",", &tok_buf);
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
|
||||
/* Select only auth or auth-int. Otherwise, ignore */
|
||||
if(foundAuth) {
|
||||
free(digest->qop);
|
||||
digest->qop = strdup(DIGEST_QOP_VALUE_STRING_AUTH);
|
||||
if(!digest->qop)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else if(foundAuthInt) {
|
||||
free(digest->qop);
|
||||
digest->qop = strdup(DIGEST_QOP_VALUE_STRING_AUTH_INT);
|
||||
if(!digest->qop)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
else if(Curl_raw_equal(value, "algorithm")) {
|
||||
free(digest->algorithm);
|
||||
digest->algorithm = strdup(content);
|
||||
if(!digest->algorithm)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(Curl_raw_equal(content, "MD5-sess"))
|
||||
digest->algo = CURLDIGESTALGO_MD5SESS;
|
||||
else if(Curl_raw_equal(content, "MD5"))
|
||||
digest->algo = CURLDIGESTALGO_MD5;
|
||||
else
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
else {
|
||||
/* Unknown specifier, ignore it! */
|
||||
}
|
||||
}
|
||||
else
|
||||
break; /* We're done here */
|
||||
|
||||
/* Pass all additional spaces here */
|
||||
while(*chlg && ISSPACE(*chlg))
|
||||
chlg++;
|
||||
|
||||
/* Allow the list to be comma-separated */
|
||||
if(',' == *chlg)
|
||||
chlg++;
|
||||
}
|
||||
|
||||
/* We had a nonce since before, and we got another one now without
|
||||
'stale=true'. This means we provided bad credentials in the previous
|
||||
request */
|
||||
if(before && !digest->stale)
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
|
||||
/* We got this header without a nonce, that's a bad Digest line! */
|
||||
if(!digest->nonce)
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_create_digest_http_message()
|
||||
*
|
||||
* This is used to generate a HTTP DIGEST response message ready for sending
|
||||
* to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* userp [in] - The user name.
|
||||
* passdwp [in] - The user's password.
|
||||
* request [in] - The HTTP request.
|
||||
* uripath [in] - The path of the HTTP uri.
|
||||
* digest [in/out] - The digest data struct being used and modified.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_create_digest_http_message(struct SessionHandle *data,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
const unsigned char *request,
|
||||
const unsigned char *uripath,
|
||||
struct digestdata *digest,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
CURLcode result;
|
||||
unsigned char md5buf[16]; /* 16 bytes/128 bits */
|
||||
unsigned char request_digest[33];
|
||||
unsigned char *md5this;
|
||||
unsigned char ha1[33]; /* 32 digits and 1 zero byte */
|
||||
unsigned char ha2[33]; /* 32 digits and 1 zero byte */
|
||||
char cnoncebuf[33];
|
||||
char *cnonce = NULL;
|
||||
size_t cnonce_sz = 0;
|
||||
char *userp_quoted;
|
||||
char *response = NULL;
|
||||
char *tmp = NULL;
|
||||
|
||||
if(!digest->nc)
|
||||
digest->nc = 1;
|
||||
|
||||
if(!digest->cnonce) {
|
||||
snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x",
|
||||
Curl_rand(data), Curl_rand(data),
|
||||
Curl_rand(data), Curl_rand(data));
|
||||
|
||||
result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf),
|
||||
&cnonce, &cnonce_sz);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
digest->cnonce = cnonce;
|
||||
}
|
||||
|
||||
/*
|
||||
If the algorithm is "MD5" or unspecified (which then defaults to MD5):
|
||||
|
||||
A1 = unq(username-value) ":" unq(realm-value) ":" passwd
|
||||
|
||||
If the algorithm is "MD5-sess" then:
|
||||
|
||||
A1 = H(unq(username-value) ":" unq(realm-value) ":" passwd) ":"
|
||||
unq(nonce-value) ":" unq(cnonce-value)
|
||||
*/
|
||||
|
||||
md5this = (unsigned char *)
|
||||
aprintf("%s:%s:%s", userp, digest->realm, passwdp);
|
||||
if(!md5this)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, md5this);
|
||||
free(md5this);
|
||||
auth_digest_md5_to_ascii(md5buf, ha1);
|
||||
|
||||
if(digest->algo == CURLDIGESTALGO_MD5SESS) {
|
||||
/* nonce and cnonce are OUTSIDE the hash */
|
||||
tmp = aprintf("%s:%s:%s", ha1, digest->nonce, digest->cnonce);
|
||||
if(!tmp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
CURL_OUTPUT_DIGEST_CONV(data, tmp); /* Convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, (unsigned char *) tmp);
|
||||
free(tmp);
|
||||
auth_digest_md5_to_ascii(md5buf, ha1);
|
||||
}
|
||||
|
||||
/*
|
||||
If the "qop" directive's value is "auth" or is unspecified, then A2 is:
|
||||
|
||||
A2 = Method ":" digest-uri-value
|
||||
|
||||
If the "qop" value is "auth-int", then A2 is:
|
||||
|
||||
A2 = Method ":" digest-uri-value ":" H(entity-body)
|
||||
|
||||
(The "Method" value is the HTTP request method as specified in section
|
||||
5.1.1 of RFC 2616)
|
||||
*/
|
||||
|
||||
md5this = (unsigned char *) aprintf("%s:%s", request, uripath);
|
||||
|
||||
if(digest->qop && Curl_raw_equal(digest->qop, "auth-int")) {
|
||||
/* We don't support auth-int for PUT or POST at the moment.
|
||||
TODO: replace md5 of empty string with entity-body for PUT/POST */
|
||||
unsigned char *md5this2 = (unsigned char *)
|
||||
aprintf("%s:%s", md5this, "d41d8cd98f00b204e9800998ecf8427e");
|
||||
free(md5this);
|
||||
md5this = md5this2;
|
||||
}
|
||||
|
||||
if(!md5this)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, md5this);
|
||||
free(md5this);
|
||||
auth_digest_md5_to_ascii(md5buf, ha2);
|
||||
|
||||
if(digest->qop) {
|
||||
md5this = (unsigned char *) aprintf("%s:%s:%08x:%s:%s:%s",
|
||||
ha1,
|
||||
digest->nonce,
|
||||
digest->nc,
|
||||
digest->cnonce,
|
||||
digest->qop,
|
||||
ha2);
|
||||
}
|
||||
else {
|
||||
md5this = (unsigned char *) aprintf("%s:%s:%s",
|
||||
ha1,
|
||||
digest->nonce,
|
||||
ha2);
|
||||
}
|
||||
|
||||
if(!md5this)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, md5this);
|
||||
free(md5this);
|
||||
auth_digest_md5_to_ascii(md5buf, request_digest);
|
||||
|
||||
/* For test case 64 (snooped from a Mozilla 1.3a request)
|
||||
|
||||
Authorization: Digest username="testuser", realm="testrealm", \
|
||||
nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca"
|
||||
|
||||
Digest parameters are all quoted strings. Username which is provided by
|
||||
the user will need double quotes and backslashes within it escaped. For
|
||||
the other fields, this shouldn't be an issue. realm, nonce, and opaque
|
||||
are copied as is from the server, escapes and all. cnonce is generated
|
||||
with web-safe characters. uri is already percent encoded. nc is 8 hex
|
||||
characters. algorithm and qop with standard values only contain web-safe
|
||||
characters.
|
||||
*/
|
||||
userp_quoted = auth_digest_string_quoted(userp);
|
||||
if(!userp_quoted)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(digest->qop) {
|
||||
response = aprintf("username=\"%s\", "
|
||||
"realm=\"%s\", "
|
||||
"nonce=\"%s\", "
|
||||
"uri=\"%s\", "
|
||||
"cnonce=\"%s\", "
|
||||
"nc=%08x, "
|
||||
"qop=%s, "
|
||||
"response=\"%s\"",
|
||||
userp_quoted,
|
||||
digest->realm,
|
||||
digest->nonce,
|
||||
uripath,
|
||||
digest->cnonce,
|
||||
digest->nc,
|
||||
digest->qop,
|
||||
request_digest);
|
||||
|
||||
if(Curl_raw_equal(digest->qop, "auth"))
|
||||
digest->nc++; /* The nc (from RFC) has to be a 8 hex digit number 0
|
||||
padded which tells to the server how many times you are
|
||||
using the same nonce in the qop=auth mode */
|
||||
}
|
||||
else {
|
||||
response = aprintf("username=\"%s\", "
|
||||
"realm=\"%s\", "
|
||||
"nonce=\"%s\", "
|
||||
"uri=\"%s\", "
|
||||
"response=\"%s\"",
|
||||
userp_quoted,
|
||||
digest->realm,
|
||||
digest->nonce,
|
||||
uripath,
|
||||
request_digest);
|
||||
}
|
||||
free(userp_quoted);
|
||||
if(!response)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Add the optional fields */
|
||||
if(digest->opaque) {
|
||||
/* Append the opaque */
|
||||
tmp = aprintf("%s, opaque=\"%s\"", response, digest->opaque);
|
||||
free(response);
|
||||
if(!tmp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
response = tmp;
|
||||
}
|
||||
|
||||
if(digest->algorithm) {
|
||||
/* Append the algorithm */
|
||||
tmp = aprintf("%s, algorithm=\"%s\"", response, digest->algorithm);
|
||||
free(response);
|
||||
if(!tmp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
response = tmp;
|
||||
}
|
||||
|
||||
/* Return the output */
|
||||
*outptr = response;
|
||||
*outlen = strlen(response);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_digest_cleanup()
|
||||
*
|
||||
* This is used to clean up the digest specific data.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* digest [in/out] - The digest data struct being cleaned up.
|
||||
*
|
||||
*/
|
||||
void Curl_auth_digest_cleanup(struct digestdata *digest)
|
||||
{
|
||||
Curl_safefree(digest->nonce);
|
||||
Curl_safefree(digest->cnonce);
|
||||
Curl_safefree(digest->realm);
|
||||
Curl_safefree(digest->opaque);
|
||||
Curl_safefree(digest->qop);
|
||||
Curl_safefree(digest->algorithm);
|
||||
|
||||
digest->nc = 0;
|
||||
digest->algo = CURLDIGESTALGO_MD5; /* default algorithm */
|
||||
digest->stale = FALSE; /* default means normal, not stale */
|
||||
}
|
||||
#endif /* !USE_WINDOWS_SSPI */
|
||||
|
||||
#endif /* CURL_DISABLE_CRYPTO_AUTH */
|
||||
43
project/jni/curl/lib/vauth/digest.h
Normal file
43
project/jni/curl/lib/vauth/digest.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef HEADER_CURL_DIGEST_H
|
||||
#define HEADER_CURL_DIGEST_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, 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.haxx.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.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
|
||||
#define DIGEST_MAX_VALUE_LENGTH 256
|
||||
#define DIGEST_MAX_CONTENT_LENGTH 1024
|
||||
|
||||
enum {
|
||||
CURLDIGESTALGO_MD5,
|
||||
CURLDIGESTALGO_MD5SESS
|
||||
};
|
||||
|
||||
/* This is used to extract the realm from a challenge message */
|
||||
bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
|
||||
const char **endptr);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_CURL_DIGEST_H */
|
||||
527
project/jni/curl/lib/vauth/digest_sspi.c
Normal file
527
project/jni/curl/lib/vauth/digest_sspi.c
Normal file
@@ -0,0 +1,527 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2014 - 2016, Steve Holme, <steve_holme@hotmail.com>.
|
||||
* Copyright (C) 2015, 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.haxx.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.
|
||||
*
|
||||
* RFC2831 DIGEST-MD5 authentication
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "vauth/vauth.h"
|
||||
#include "vauth/digest.h"
|
||||
#include "urldata.h"
|
||||
#include "curl_base64.h"
|
||||
#include "warnless.h"
|
||||
#include "curl_multibyte.h"
|
||||
#include "sendf.h"
|
||||
#include "strdup.h"
|
||||
#include "rawstr.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
* Curl_auth_create_digest_md5_message()
|
||||
*
|
||||
* This is used to generate an already encoded DIGEST-MD5 response message
|
||||
* ready for sending to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* chlg64 [in] - The base64 encoded challenge message.
|
||||
* userp [in] - The user name in the format User or Domain\User.
|
||||
* passdwp [in] - The user's password.
|
||||
* service [in] - The service type such as http, smtp, pop or imap.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_create_digest_md5_message(struct SessionHandle *data,
|
||||
const char *chlg64,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
const char *service,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
TCHAR *spn = NULL;
|
||||
size_t chlglen = 0;
|
||||
size_t token_max = 0;
|
||||
unsigned char *input_token = NULL;
|
||||
unsigned char *output_token = NULL;
|
||||
CredHandle credentials;
|
||||
CtxtHandle context;
|
||||
PSecPkgInfo SecurityPackage;
|
||||
SEC_WINNT_AUTH_IDENTITY identity;
|
||||
SEC_WINNT_AUTH_IDENTITY *p_identity;
|
||||
SecBuffer chlg_buf;
|
||||
SecBuffer resp_buf;
|
||||
SecBufferDesc chlg_desc;
|
||||
SecBufferDesc resp_desc;
|
||||
SECURITY_STATUS status;
|
||||
unsigned long attrs;
|
||||
TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
|
||||
|
||||
/* Decode the base-64 encoded challenge message */
|
||||
if(strlen(chlg64) && *chlg64 != '=') {
|
||||
result = Curl_base64_decode(chlg64, &input_token, &chlglen);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Ensure we have a valid challenge message */
|
||||
if(!input_token) {
|
||||
infof(data, "DIGEST-MD5 handshake failure (empty challenge message)\n");
|
||||
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
/* Query the security package for DigestSSP */
|
||||
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
|
||||
&SecurityPackage);
|
||||
if(status != SEC_E_OK) {
|
||||
free(input_token);
|
||||
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
}
|
||||
|
||||
token_max = SecurityPackage->cbMaxToken;
|
||||
|
||||
/* Release the package buffer as it is not required anymore */
|
||||
s_pSecFn->FreeContextBuffer(SecurityPackage);
|
||||
|
||||
/* Allocate our response buffer */
|
||||
output_token = malloc(token_max);
|
||||
if(!output_token) {
|
||||
free(input_token);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Generate our SPN */
|
||||
spn = Curl_auth_build_spn(service, data->easy_conn->host.name, NULL);
|
||||
if(!spn) {
|
||||
free(output_token);
|
||||
free(input_token);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(userp && *userp) {
|
||||
/* Populate our identity structure */
|
||||
result = Curl_create_sspi_identity(userp, passwdp, &identity);
|
||||
if(result) {
|
||||
free(spn);
|
||||
free(output_token);
|
||||
free(input_token);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Allow proper cleanup of the identity structure */
|
||||
p_identity = &identity;
|
||||
}
|
||||
else
|
||||
/* Use the current Windows user */
|
||||
p_identity = NULL;
|
||||
|
||||
/* Acquire our credentials handle */
|
||||
status = s_pSecFn->AcquireCredentialsHandle(NULL,
|
||||
(TCHAR *) TEXT(SP_NAME_DIGEST),
|
||||
SECPKG_CRED_OUTBOUND, NULL,
|
||||
p_identity, NULL, NULL,
|
||||
&credentials, &expiry);
|
||||
|
||||
if(status != SEC_E_OK) {
|
||||
Curl_sspi_free_identity(p_identity);
|
||||
free(spn);
|
||||
free(output_token);
|
||||
free(input_token);
|
||||
|
||||
return CURLE_LOGIN_DENIED;
|
||||
}
|
||||
|
||||
/* Setup the challenge "input" security buffer */
|
||||
chlg_desc.ulVersion = SECBUFFER_VERSION;
|
||||
chlg_desc.cBuffers = 1;
|
||||
chlg_desc.pBuffers = &chlg_buf;
|
||||
chlg_buf.BufferType = SECBUFFER_TOKEN;
|
||||
chlg_buf.pvBuffer = input_token;
|
||||
chlg_buf.cbBuffer = curlx_uztoul(chlglen);
|
||||
|
||||
/* Setup the response "output" security buffer */
|
||||
resp_desc.ulVersion = SECBUFFER_VERSION;
|
||||
resp_desc.cBuffers = 1;
|
||||
resp_desc.pBuffers = &resp_buf;
|
||||
resp_buf.BufferType = SECBUFFER_TOKEN;
|
||||
resp_buf.pvBuffer = output_token;
|
||||
resp_buf.cbBuffer = curlx_uztoul(token_max);
|
||||
|
||||
/* Generate our response message */
|
||||
status = s_pSecFn->InitializeSecurityContext(&credentials, NULL, spn,
|
||||
0, 0, 0, &chlg_desc, 0,
|
||||
&context, &resp_desc, &attrs,
|
||||
&expiry);
|
||||
|
||||
if(status == SEC_I_COMPLETE_NEEDED ||
|
||||
status == SEC_I_COMPLETE_AND_CONTINUE)
|
||||
s_pSecFn->CompleteAuthToken(&credentials, &resp_desc);
|
||||
else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
|
||||
s_pSecFn->FreeCredentialsHandle(&credentials);
|
||||
Curl_sspi_free_identity(p_identity);
|
||||
free(spn);
|
||||
free(output_token);
|
||||
free(input_token);
|
||||
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
|
||||
/* Base64 encode the response */
|
||||
result = Curl_base64_encode(data, (char *) output_token, resp_buf.cbBuffer,
|
||||
outptr, outlen);
|
||||
|
||||
/* Free our handles */
|
||||
s_pSecFn->DeleteSecurityContext(&context);
|
||||
s_pSecFn->FreeCredentialsHandle(&credentials);
|
||||
|
||||
/* Free the identity structure */
|
||||
Curl_sspi_free_identity(p_identity);
|
||||
|
||||
/* Free the SPN */
|
||||
free(spn);
|
||||
|
||||
/* Free the response buffer */
|
||||
free(output_token);
|
||||
|
||||
/* Free the decoded challenge message */
|
||||
free(input_token);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_override_sspi_http_realm()
|
||||
*
|
||||
* This is used to populate the domain in a SSPI identity structure
|
||||
* The realm is extracted from the challenge message and used as the
|
||||
* domain if it is not already explicitly set.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* chlg [in] - The challenge message.
|
||||
* identity [in/out] - The identity structure.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_override_sspi_http_realm(const char *chlg,
|
||||
SEC_WINNT_AUTH_IDENTITY *identity)
|
||||
{
|
||||
xcharp_u domain, dup_domain;
|
||||
|
||||
/* If domain is blank or unset, check challenge message for realm */
|
||||
if(!identity->Domain || !identity->DomainLength) {
|
||||
for(;;) {
|
||||
char value[DIGEST_MAX_VALUE_LENGTH];
|
||||
char content[DIGEST_MAX_CONTENT_LENGTH];
|
||||
|
||||
/* Pass all additional spaces here */
|
||||
while(*chlg && ISSPACE(*chlg))
|
||||
chlg++;
|
||||
|
||||
/* Extract a value=content pair */
|
||||
if(Curl_auth_digest_get_pair(chlg, value, content, &chlg)) {
|
||||
if(Curl_raw_equal(value, "realm")) {
|
||||
|
||||
/* Setup identity's domain and length */
|
||||
domain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *) content);
|
||||
if(!domain.tchar_ptr)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
dup_domain.tchar_ptr = _tcsdup(domain.tchar_ptr);
|
||||
if(!dup_domain.tchar_ptr) {
|
||||
Curl_unicodefree(domain.tchar_ptr);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
free(identity->Domain);
|
||||
identity->Domain = dup_domain.tbyte_ptr;
|
||||
identity->DomainLength = curlx_uztoul(_tcslen(dup_domain.tchar_ptr));
|
||||
dup_domain.tchar_ptr = NULL;
|
||||
|
||||
Curl_unicodefree(domain.tchar_ptr);
|
||||
}
|
||||
else {
|
||||
/* Unknown specifier, ignore it! */
|
||||
}
|
||||
}
|
||||
else
|
||||
break; /* We're done here */
|
||||
|
||||
/* Pass all additional spaces here */
|
||||
while(*chlg && ISSPACE(*chlg))
|
||||
chlg++;
|
||||
|
||||
/* Allow the list to be comma-separated */
|
||||
if(',' == *chlg)
|
||||
chlg++;
|
||||
}
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_decode_digest_http_message()
|
||||
*
|
||||
* This is used to decode a HTTP DIGEST challenge message into the seperate
|
||||
* attributes.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* chlg [in] - The challenge message.
|
||||
* digest [in/out] - The digest data struct being used and modified.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
|
||||
struct digestdata *digest)
|
||||
{
|
||||
size_t chlglen = strlen(chlg);
|
||||
|
||||
/* We had an input token before and we got another one now. This means we
|
||||
provided bad credentials in the previous request. */
|
||||
if(digest->input_token)
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
|
||||
/* Simply store the challenge for use later */
|
||||
digest->input_token = (BYTE *) Curl_memdup(chlg, chlglen);
|
||||
if(!digest->input_token)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
digest->input_token_len = chlglen;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_create_digest_http_message()
|
||||
*
|
||||
* This is used to generate a HTTP DIGEST response message ready for sending
|
||||
* to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* userp [in] - The user name in the format User or Domain\User.
|
||||
* passdwp [in] - The user's password.
|
||||
* request [in] - The HTTP request.
|
||||
* uripath [in] - The path of the HTTP uri.
|
||||
* digest [in/out] - The digest data struct being used and modified.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_create_digest_http_message(struct SessionHandle *data,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
const unsigned char *request,
|
||||
const unsigned char *uripath,
|
||||
struct digestdata *digest,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
size_t token_max;
|
||||
CredHandle credentials;
|
||||
CtxtHandle context;
|
||||
char *resp;
|
||||
BYTE *output_token;
|
||||
PSecPkgInfo SecurityPackage;
|
||||
SEC_WINNT_AUTH_IDENTITY identity;
|
||||
SEC_WINNT_AUTH_IDENTITY *p_identity;
|
||||
SecBuffer chlg_buf[3];
|
||||
SecBuffer resp_buf;
|
||||
SecBufferDesc chlg_desc;
|
||||
SecBufferDesc resp_desc;
|
||||
SECURITY_STATUS status;
|
||||
unsigned long attrs;
|
||||
TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
|
||||
TCHAR *spn;
|
||||
|
||||
(void) data;
|
||||
|
||||
/* Query the security package for DigestSSP */
|
||||
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
|
||||
&SecurityPackage);
|
||||
if(status != SEC_E_OK)
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
|
||||
token_max = SecurityPackage->cbMaxToken;
|
||||
|
||||
/* Release the package buffer as it is not required anymore */
|
||||
s_pSecFn->FreeContextBuffer(SecurityPackage);
|
||||
|
||||
/* Allocate the output buffer according to the max token size as indicated
|
||||
by the security package */
|
||||
output_token = malloc(token_max);
|
||||
if(!output_token)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(userp && *userp) {
|
||||
/* Populate our identity structure */
|
||||
if(Curl_create_sspi_identity(userp, passwdp, &identity))
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Populate our identity domain */
|
||||
if(Curl_override_sspi_http_realm((const char*) digest->input_token,
|
||||
&identity))
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Allow proper cleanup of the identity structure */
|
||||
p_identity = &identity;
|
||||
}
|
||||
else
|
||||
/* Use the current Windows user */
|
||||
p_identity = NULL;
|
||||
|
||||
/* Acquire our credentials handle */
|
||||
status = s_pSecFn->AcquireCredentialsHandle(NULL,
|
||||
(TCHAR *) TEXT(SP_NAME_DIGEST),
|
||||
SECPKG_CRED_OUTBOUND, NULL,
|
||||
p_identity, NULL, NULL,
|
||||
&credentials, &expiry);
|
||||
if(status != SEC_E_OK) {
|
||||
Curl_sspi_free_identity(p_identity);
|
||||
free(output_token);
|
||||
|
||||
return CURLE_LOGIN_DENIED;
|
||||
}
|
||||
|
||||
/* Setup the challenge "input" security buffer if present */
|
||||
chlg_desc.ulVersion = SECBUFFER_VERSION;
|
||||
chlg_desc.cBuffers = 3;
|
||||
chlg_desc.pBuffers = chlg_buf;
|
||||
chlg_buf[0].BufferType = SECBUFFER_TOKEN;
|
||||
chlg_buf[0].pvBuffer = digest->input_token;
|
||||
chlg_buf[0].cbBuffer = curlx_uztoul(digest->input_token_len);
|
||||
chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS;
|
||||
chlg_buf[1].pvBuffer = (void *) request;
|
||||
chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *) request));
|
||||
chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS;
|
||||
chlg_buf[2].pvBuffer = NULL;
|
||||
chlg_buf[2].cbBuffer = 0;
|
||||
|
||||
/* Setup the response "output" security buffer */
|
||||
resp_desc.ulVersion = SECBUFFER_VERSION;
|
||||
resp_desc.cBuffers = 1;
|
||||
resp_desc.pBuffers = &resp_buf;
|
||||
resp_buf.BufferType = SECBUFFER_TOKEN;
|
||||
resp_buf.pvBuffer = output_token;
|
||||
resp_buf.cbBuffer = curlx_uztoul(token_max);
|
||||
|
||||
spn = Curl_convert_UTF8_to_tchar((char *) uripath);
|
||||
if(!spn) {
|
||||
Curl_sspi_free_identity(p_identity);
|
||||
free(output_token);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Generate our reponse message */
|
||||
status = s_pSecFn->InitializeSecurityContext(&credentials, NULL,
|
||||
spn,
|
||||
ISC_REQ_USE_HTTP_STYLE, 0, 0,
|
||||
&chlg_desc, 0, &context,
|
||||
&resp_desc, &attrs, &expiry);
|
||||
Curl_unicodefree(spn);
|
||||
|
||||
if(status == SEC_I_COMPLETE_NEEDED ||
|
||||
status == SEC_I_COMPLETE_AND_CONTINUE)
|
||||
s_pSecFn->CompleteAuthToken(&credentials, &resp_desc);
|
||||
else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
|
||||
s_pSecFn->FreeCredentialsHandle(&credentials);
|
||||
|
||||
Curl_sspi_free_identity(p_identity);
|
||||
free(output_token);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
resp = malloc(resp_buf.cbBuffer + 1);
|
||||
if(!resp) {
|
||||
s_pSecFn->DeleteSecurityContext(&context);
|
||||
s_pSecFn->FreeCredentialsHandle(&credentials);
|
||||
|
||||
Curl_sspi_free_identity(p_identity);
|
||||
free(output_token);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Copy the generated reponse */
|
||||
memcpy(resp, resp_buf.pvBuffer, resp_buf.cbBuffer);
|
||||
resp[resp_buf.cbBuffer] = 0x00;
|
||||
|
||||
/* Return the response */
|
||||
*outptr = resp;
|
||||
*outlen = resp_buf.cbBuffer;
|
||||
|
||||
/* Free our handles */
|
||||
s_pSecFn->DeleteSecurityContext(&context);
|
||||
s_pSecFn->FreeCredentialsHandle(&credentials);
|
||||
|
||||
/* Free the identity structure */
|
||||
Curl_sspi_free_identity(p_identity);
|
||||
|
||||
/* Free the response buffer */
|
||||
free(output_token);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_digest_cleanup()
|
||||
*
|
||||
* This is used to clean up the digest specific data.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* digest [in/out] - The digest data struct being cleaned up.
|
||||
*
|
||||
*/
|
||||
void Curl_auth_digest_cleanup(struct digestdata *digest)
|
||||
{
|
||||
/* Free the input token */
|
||||
Curl_safefree(digest->input_token);
|
||||
|
||||
/* Reset any variables */
|
||||
digest->input_token_len = 0;
|
||||
}
|
||||
|
||||
#endif /* USE_WINDOWS_SSPI && !CURL_DISABLE_CRYPTO_AUTH */
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "vauth/vauth.h"
|
||||
#include "curl_sasl.h"
|
||||
#include "urldata.h"
|
||||
#include "curl_base64.h"
|
||||
@@ -41,25 +42,7 @@
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
* Curl_sasl_build_gssapi_spn()
|
||||
*
|
||||
* This is used to build a SPN string in the format service@instance.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* service [in] - The service type such as www, smtp, pop or imap.
|
||||
* instance [in] - The host name or realm.
|
||||
*
|
||||
* Returns a pointer to the newly allocated SPN.
|
||||
*/
|
||||
char *Curl_sasl_build_gssapi_spn(const char *service, const char *instance)
|
||||
{
|
||||
/* Generate and return our SPN */
|
||||
return aprintf("%s@%s", service, instance);
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_sasl_create_gssapi_user_message()
|
||||
* Curl_auth_create_gssapi_user_message()
|
||||
*
|
||||
* This is used to generate an already encoded GSSAPI (Kerberos V5) user token
|
||||
* message ready for sending to the recipient.
|
||||
@@ -69,7 +52,8 @@ char *Curl_sasl_build_gssapi_spn(const char *service, const char *instance)
|
||||
* data [in] - The session handle.
|
||||
* userp [in] - The user name.
|
||||
* passdwp [in] - The user's password.
|
||||
* service [in] - The service type such as www, smtp, pop or imap.
|
||||
* service [in] - The service type such as http, smtp, pop or imap.
|
||||
* host [in[ - The host name.
|
||||
* mutual_auth [in] - Flag specifing whether or not mutual authentication
|
||||
* is enabled.
|
||||
* chlg64 [in] - Pointer to the optional base64 encoded challenge
|
||||
@@ -81,10 +65,11 @@ char *Curl_sasl_build_gssapi_spn(const char *service, const char *instance)
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
|
||||
CURLcode Curl_auth_create_gssapi_user_message(struct SessionHandle *data,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
const char *service,
|
||||
const char *host,
|
||||
const bool mutual_auth,
|
||||
const char *chlg64,
|
||||
struct kerberos5data *krb5,
|
||||
@@ -93,9 +78,9 @@ CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
|
||||
CURLcode result = CURLE_OK;
|
||||
size_t chlglen = 0;
|
||||
unsigned char *chlg = NULL;
|
||||
OM_uint32 gss_status;
|
||||
OM_uint32 gss_major_status;
|
||||
OM_uint32 gss_minor_status;
|
||||
OM_uint32 major_status;
|
||||
OM_uint32 minor_status;
|
||||
OM_uint32 unused_status;
|
||||
gss_buffer_desc spn_token = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
|
||||
@@ -103,10 +88,9 @@ CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
|
||||
(void) userp;
|
||||
(void) passwdp;
|
||||
|
||||
if(krb5->context == GSS_C_NO_CONTEXT) {
|
||||
if(!krb5->spn) {
|
||||
/* Generate our SPN */
|
||||
char *spn = Curl_sasl_build_gssapi_spn(service,
|
||||
data->easy_conn->host.name);
|
||||
char *spn = Curl_auth_build_spn(service, NULL, host);
|
||||
if(!spn)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
@@ -115,10 +99,11 @@ CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
|
||||
spn_token.length = strlen(spn);
|
||||
|
||||
/* Import the SPN */
|
||||
gss_major_status = gss_import_name(&gss_minor_status, &spn_token,
|
||||
GSS_C_NT_HOSTBASED_SERVICE, &krb5->spn);
|
||||
if(GSS_ERROR(gss_major_status)) {
|
||||
Curl_gss_log_error(data, gss_minor_status, "gss_import_name() failed: ");
|
||||
major_status = gss_import_name(&minor_status, &spn_token,
|
||||
GSS_C_NT_HOSTBASED_SERVICE, &krb5->spn);
|
||||
if(GSS_ERROR(major_status)) {
|
||||
Curl_gss_log_error(data, "gss_import_name() failed: ",
|
||||
major_status, minor_status);
|
||||
|
||||
free(spn);
|
||||
|
||||
@@ -127,9 +112,10 @@ CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
|
||||
|
||||
free(spn);
|
||||
}
|
||||
else {
|
||||
|
||||
if(chlg64 && *chlg64) {
|
||||
/* Decode the base-64 encoded challenge message */
|
||||
if(strlen(chlg64) && *chlg64 != '=') {
|
||||
if(*chlg64 != '=') {
|
||||
result = Curl_base64_decode(chlg64, &chlg, &chlglen);
|
||||
if(result)
|
||||
return result;
|
||||
@@ -147,25 +133,26 @@ CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
|
||||
input_token.length = chlglen;
|
||||
}
|
||||
|
||||
gss_major_status = Curl_gss_init_sec_context(data,
|
||||
&gss_minor_status,
|
||||
&krb5->context,
|
||||
krb5->spn,
|
||||
&Curl_krb5_mech_oid,
|
||||
GSS_C_NO_CHANNEL_BINDINGS,
|
||||
&input_token,
|
||||
&output_token,
|
||||
mutual_auth,
|
||||
NULL);
|
||||
major_status = Curl_gss_init_sec_context(data,
|
||||
&minor_status,
|
||||
&krb5->context,
|
||||
krb5->spn,
|
||||
&Curl_krb5_mech_oid,
|
||||
GSS_C_NO_CHANNEL_BINDINGS,
|
||||
&input_token,
|
||||
&output_token,
|
||||
mutual_auth,
|
||||
NULL);
|
||||
|
||||
/* Free the decoded challenge as it is not required anymore */
|
||||
free(input_token.value);
|
||||
|
||||
if(GSS_ERROR(gss_major_status)) {
|
||||
if(GSS_ERROR(major_status)) {
|
||||
if(output_token.value)
|
||||
gss_release_buffer(&gss_status, &output_token);
|
||||
gss_release_buffer(&unused_status, &output_token);
|
||||
|
||||
Curl_gss_log_error(data, gss_minor_status,
|
||||
"gss_init_sec_context() failed: ");
|
||||
Curl_gss_log_error(data, "gss_init_sec_context() failed: ",
|
||||
major_status, minor_status);
|
||||
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
@@ -175,14 +162,19 @@ CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
|
||||
result = Curl_base64_encode(data, (char *) output_token.value,
|
||||
output_token.length, outptr, outlen);
|
||||
|
||||
gss_release_buffer(&gss_status, &output_token);
|
||||
gss_release_buffer(&unused_status, &output_token);
|
||||
}
|
||||
else if(mutual_auth) {
|
||||
*outptr = strdup("");
|
||||
if(!*outptr)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_sasl_create_gssapi_security_message()
|
||||
* Curl_auth_create_gssapi_security_message()
|
||||
*
|
||||
* This is used to generate an already encoded GSSAPI (Kerberos V5) security
|
||||
* token message ready for sending to the recipient.
|
||||
@@ -198,7 +190,7 @@ CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||
CURLcode Curl_auth_create_gssapi_security_message(struct SessionHandle *data,
|
||||
const char *chlg64,
|
||||
struct kerberos5data *krb5,
|
||||
char **outptr,
|
||||
@@ -209,9 +201,9 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||
size_t messagelen = 0;
|
||||
unsigned char *chlg = NULL;
|
||||
unsigned char *message = NULL;
|
||||
OM_uint32 gss_status;
|
||||
OM_uint32 gss_major_status;
|
||||
OM_uint32 gss_minor_status;
|
||||
OM_uint32 major_status;
|
||||
OM_uint32 minor_status;
|
||||
OM_uint32 unused_status;
|
||||
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
|
||||
unsigned int indata = 0;
|
||||
@@ -237,12 +229,12 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
/* Get the fully qualified username back from the context */
|
||||
gss_major_status = gss_inquire_context(&gss_minor_status, krb5->context,
|
||||
&username, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL);
|
||||
if(GSS_ERROR(gss_major_status)) {
|
||||
Curl_gss_log_error(data, gss_minor_status,
|
||||
"gss_inquire_context() failed: ");
|
||||
major_status = gss_inquire_context(&minor_status, krb5->context,
|
||||
&username, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL);
|
||||
if(GSS_ERROR(major_status)) {
|
||||
Curl_gss_log_error(data, "gss_inquire_context() failed: ",
|
||||
major_status, minor_status);
|
||||
|
||||
free(chlg);
|
||||
|
||||
@@ -250,10 +242,11 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
/* Convert the username from internal format to a displayable token */
|
||||
gss_major_status = gss_display_name(&gss_minor_status, username,
|
||||
&username_token, NULL);
|
||||
if(GSS_ERROR(gss_major_status)) {
|
||||
Curl_gss_log_error(data, gss_minor_status, "gss_display_name() failed: ");
|
||||
major_status = gss_display_name(&minor_status, username,
|
||||
&username_token, NULL);
|
||||
if(GSS_ERROR(major_status)) {
|
||||
Curl_gss_log_error(data, "gss_display_name() failed: ",
|
||||
major_status, minor_status);
|
||||
|
||||
free(chlg);
|
||||
|
||||
@@ -265,12 +258,13 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||
input_token.length = chlglen;
|
||||
|
||||
/* Decrypt the inbound challenge and obtain the qop */
|
||||
gss_major_status = gss_unwrap(&gss_minor_status, krb5->context, &input_token,
|
||||
&output_token, NULL, &qop);
|
||||
if(GSS_ERROR(gss_major_status)) {
|
||||
Curl_gss_log_error(data, gss_minor_status, "gss_unwrap() failed: ");
|
||||
major_status = gss_unwrap(&minor_status, krb5->context, &input_token,
|
||||
&output_token, NULL, &qop);
|
||||
if(GSS_ERROR(major_status)) {
|
||||
Curl_gss_log_error(data, "gss_unwrap() failed: ",
|
||||
major_status, minor_status);
|
||||
|
||||
gss_release_buffer(&gss_status, &username_token);
|
||||
gss_release_buffer(&unused_status, &username_token);
|
||||
free(chlg);
|
||||
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
@@ -280,7 +274,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||
if(output_token.length != 4) {
|
||||
infof(data, "GSSAPI handshake failure (invalid security data)\n");
|
||||
|
||||
gss_release_buffer(&gss_status, &username_token);
|
||||
gss_release_buffer(&unused_status, &username_token);
|
||||
free(chlg);
|
||||
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
@@ -288,7 +282,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||
|
||||
/* Copy the data out and free the challenge as it is not required anymore */
|
||||
memcpy(&indata, output_token.value, 4);
|
||||
gss_release_buffer(&gss_status, &output_token);
|
||||
gss_release_buffer(&unused_status, &output_token);
|
||||
free(chlg);
|
||||
|
||||
/* Extract the security layer */
|
||||
@@ -296,7 +290,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||
if(!(sec_layer & GSSAUTH_P_NONE)) {
|
||||
infof(data, "GSSAPI handshake failure (invalid security layer)\n");
|
||||
|
||||
gss_release_buffer(&gss_status, &username_token);
|
||||
gss_release_buffer(&unused_status, &username_token);
|
||||
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
@@ -314,14 +308,14 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||
messagelen = sizeof(outdata) + username_token.length + 1;
|
||||
message = malloc(messagelen);
|
||||
if(!message) {
|
||||
gss_release_buffer(&gss_status, &username_token);
|
||||
gss_release_buffer(&unused_status, &username_token);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Populate the message with the security layer, client supported receive
|
||||
message size and authorization identity including the 0x00 based
|
||||
terminator. Note: Dispite RFC4752 Section 3.1 stating "The authorization
|
||||
terminator. Note: Despite RFC4752 Section 3.1 stating "The authorization
|
||||
identity is not terminated with the zero-valued (%x00) octet." it seems
|
||||
necessary to include it. */
|
||||
outdata = htonl(max_size) | sec_layer;
|
||||
@@ -331,18 +325,19 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||
message[messagelen - 1] = '\0';
|
||||
|
||||
/* Free the username token as it is not required anymore */
|
||||
gss_release_buffer(&gss_status, &username_token);
|
||||
gss_release_buffer(&unused_status, &username_token);
|
||||
|
||||
/* Setup the "authentication data" security buffer */
|
||||
input_token.value = message;
|
||||
input_token.length = messagelen;
|
||||
|
||||
/* Encrypt the data */
|
||||
gss_major_status = gss_wrap(&gss_minor_status, krb5->context, 0,
|
||||
GSS_C_QOP_DEFAULT, &input_token, NULL,
|
||||
&output_token);
|
||||
if(GSS_ERROR(gss_major_status)) {
|
||||
Curl_gss_log_error(data, gss_minor_status, "gss_wrap() failed: ");
|
||||
major_status = gss_wrap(&minor_status, krb5->context, 0,
|
||||
GSS_C_QOP_DEFAULT, &input_token, NULL,
|
||||
&output_token);
|
||||
if(GSS_ERROR(major_status)) {
|
||||
Curl_gss_log_error(data, "gss_wrap() failed: ",
|
||||
major_status, minor_status);
|
||||
|
||||
free(message);
|
||||
|
||||
@@ -354,7 +349,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||
output_token.length, outptr, outlen);
|
||||
|
||||
/* Free the output buffer */
|
||||
gss_release_buffer(&gss_status, &output_token);
|
||||
gss_release_buffer(&unused_status, &output_token);
|
||||
|
||||
/* Free the message buffer */
|
||||
free(message);
|
||||
@@ -363,7 +358,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_sasl_gssapi_cleanup()
|
||||
* Curl_auth_gssapi_cleanup()
|
||||
*
|
||||
* This is used to clean up the GSSAPI (Kerberos V5) specific data.
|
||||
*
|
||||
@@ -372,7 +367,7 @@ CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||
* krb5 [in/out] - The Kerberos 5 data struct being cleaned up.
|
||||
*
|
||||
*/
|
||||
void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5)
|
||||
void Curl_auth_gssapi_cleanup(struct kerberos5data *krb5)
|
||||
{
|
||||
OM_uint32 minor_status;
|
||||
|
||||
496
project/jni/curl/lib/vauth/krb5_sspi.c
Normal file
496
project/jni/curl/lib/vauth/krb5_sspi.c
Normal file
@@ -0,0 +1,496 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2014 - 2016, Steve Holme, <steve_holme@hotmail.com>.
|
||||
*
|
||||
* 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.haxx.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.
|
||||
*
|
||||
* RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(USE_WINDOWS_SSPI) && defined(USE_KERBEROS5)
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "vauth/vauth.h"
|
||||
#include "urldata.h"
|
||||
#include "curl_base64.h"
|
||||
#include "warnless.h"
|
||||
#include "curl_multibyte.h"
|
||||
#include "sendf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
* Curl_auth_create_gssapi_user_message()
|
||||
*
|
||||
* This is used to generate an already encoded GSSAPI (Kerberos V5) user token
|
||||
* message ready for sending to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* userp [in] - The user name in the format User or Domain\User.
|
||||
* passdwp [in] - The user's password.
|
||||
* service [in] - The service type such as http, smtp, pop or imap.
|
||||
* host [in] - The host name.
|
||||
* mutual_auth [in] - Flag specifing whether or not mutual authentication
|
||||
* is enabled.
|
||||
* chlg64 [in] - The optional base64 encoded challenge message.
|
||||
* krb5 [in/out] - The Kerberos 5 data struct being used and modified.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_create_gssapi_user_message(struct SessionHandle *data,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
const char *service,
|
||||
const char *host,
|
||||
const bool mutual_auth,
|
||||
const char *chlg64,
|
||||
struct kerberos5data *krb5,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
size_t chlglen = 0;
|
||||
unsigned char *chlg = NULL;
|
||||
CtxtHandle context;
|
||||
PSecPkgInfo SecurityPackage;
|
||||
SecBuffer chlg_buf;
|
||||
SecBuffer resp_buf;
|
||||
SecBufferDesc chlg_desc;
|
||||
SecBufferDesc resp_desc;
|
||||
SECURITY_STATUS status;
|
||||
unsigned long attrs;
|
||||
TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
|
||||
|
||||
if(!krb5->spn) {
|
||||
/* Generate our SPN */
|
||||
krb5->spn = Curl_auth_build_spn(service, host, NULL);
|
||||
if(!krb5->spn)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(!krb5->output_token) {
|
||||
/* Query the security package for Kerberos */
|
||||
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
|
||||
TEXT(SP_NAME_KERBEROS),
|
||||
&SecurityPackage);
|
||||
if(status != SEC_E_OK) {
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
}
|
||||
|
||||
krb5->token_max = SecurityPackage->cbMaxToken;
|
||||
|
||||
/* Release the package buffer as it is not required anymore */
|
||||
s_pSecFn->FreeContextBuffer(SecurityPackage);
|
||||
|
||||
/* Allocate our response buffer */
|
||||
krb5->output_token = malloc(krb5->token_max);
|
||||
if(!krb5->output_token)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(!krb5->credentials) {
|
||||
/* Do we have credientials to use or are we using single sign-on? */
|
||||
if(userp && *userp) {
|
||||
/* Populate our identity structure */
|
||||
result = Curl_create_sspi_identity(userp, passwdp, &krb5->identity);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Allow proper cleanup of the identity structure */
|
||||
krb5->p_identity = &krb5->identity;
|
||||
}
|
||||
else
|
||||
/* Use the current Windows user */
|
||||
krb5->p_identity = NULL;
|
||||
|
||||
/* Allocate our credentials handle */
|
||||
krb5->credentials = malloc(sizeof(CredHandle));
|
||||
if(!krb5->credentials)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
memset(krb5->credentials, 0, sizeof(CredHandle));
|
||||
|
||||
/* Acquire our credentials handle */
|
||||
status = s_pSecFn->AcquireCredentialsHandle(NULL,
|
||||
(TCHAR *)
|
||||
TEXT(SP_NAME_KERBEROS),
|
||||
SECPKG_CRED_OUTBOUND, NULL,
|
||||
krb5->p_identity, NULL, NULL,
|
||||
krb5->credentials, &expiry);
|
||||
if(status != SEC_E_OK)
|
||||
return CURLE_LOGIN_DENIED;
|
||||
|
||||
/* Allocate our new context handle */
|
||||
krb5->context = malloc(sizeof(CtxtHandle));
|
||||
if(!krb5->context)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
memset(krb5->context, 0, sizeof(CtxtHandle));
|
||||
}
|
||||
|
||||
if(chlg64 && *chlg64) {
|
||||
/* Decode the base-64 encoded challenge message */
|
||||
if(*chlg64 != '=') {
|
||||
result = Curl_base64_decode(chlg64, &chlg, &chlglen);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Ensure we have a valid challenge message */
|
||||
if(!chlg) {
|
||||
infof(data, "GSSAPI handshake failure (empty challenge message)\n");
|
||||
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
/* Setup the challenge "input" security buffer */
|
||||
chlg_desc.ulVersion = SECBUFFER_VERSION;
|
||||
chlg_desc.cBuffers = 1;
|
||||
chlg_desc.pBuffers = &chlg_buf;
|
||||
chlg_buf.BufferType = SECBUFFER_TOKEN;
|
||||
chlg_buf.pvBuffer = chlg;
|
||||
chlg_buf.cbBuffer = curlx_uztoul(chlglen);
|
||||
}
|
||||
|
||||
/* Setup the response "output" security buffer */
|
||||
resp_desc.ulVersion = SECBUFFER_VERSION;
|
||||
resp_desc.cBuffers = 1;
|
||||
resp_desc.pBuffers = &resp_buf;
|
||||
resp_buf.BufferType = SECBUFFER_TOKEN;
|
||||
resp_buf.pvBuffer = krb5->output_token;
|
||||
resp_buf.cbBuffer = curlx_uztoul(krb5->token_max);
|
||||
|
||||
/* Generate our challenge-response message */
|
||||
status = s_pSecFn->InitializeSecurityContext(krb5->credentials,
|
||||
chlg ? krb5->context : NULL,
|
||||
krb5->spn,
|
||||
(mutual_auth ?
|
||||
ISC_REQ_MUTUAL_AUTH : 0),
|
||||
0, SECURITY_NATIVE_DREP,
|
||||
chlg ? &chlg_desc : NULL, 0,
|
||||
&context,
|
||||
&resp_desc, &attrs,
|
||||
&expiry);
|
||||
|
||||
/* Free the decoded challenge as it is not required anymore */
|
||||
free(chlg);
|
||||
|
||||
if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
|
||||
if(memcmp(&context, krb5->context, sizeof(context))) {
|
||||
s_pSecFn->DeleteSecurityContext(krb5->context);
|
||||
|
||||
memcpy(krb5->context, &context, sizeof(context));
|
||||
}
|
||||
|
||||
if(resp_buf.cbBuffer) {
|
||||
/* Base64 encode the response */
|
||||
result = Curl_base64_encode(data, (char *) resp_buf.pvBuffer,
|
||||
resp_buf.cbBuffer, outptr, outlen);
|
||||
}
|
||||
else if(mutual_auth) {
|
||||
*outptr = strdup("");
|
||||
if(!*outptr)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_create_gssapi_security_message()
|
||||
*
|
||||
* This is used to generate an already encoded GSSAPI (Kerberos V5) security
|
||||
* token message ready for sending to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* chlg64 [in] - The optional base64 encoded challenge message.
|
||||
* krb5 [in/out] - The Kerberos 5 data struct being used and modified.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_create_gssapi_security_message(struct SessionHandle *data,
|
||||
const char *chlg64,
|
||||
struct kerberos5data *krb5,
|
||||
char **outptr,
|
||||
size_t *outlen)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
size_t offset = 0;
|
||||
size_t chlglen = 0;
|
||||
size_t messagelen = 0;
|
||||
size_t appdatalen = 0;
|
||||
unsigned char *chlg = NULL;
|
||||
unsigned char *trailer = NULL;
|
||||
unsigned char *message = NULL;
|
||||
unsigned char *padding = NULL;
|
||||
unsigned char *appdata = NULL;
|
||||
SecBuffer input_buf[2];
|
||||
SecBuffer wrap_buf[3];
|
||||
SecBufferDesc input_desc;
|
||||
SecBufferDesc wrap_desc;
|
||||
unsigned long indata = 0;
|
||||
unsigned long outdata = 0;
|
||||
unsigned long qop = 0;
|
||||
unsigned long sec_layer = 0;
|
||||
unsigned long max_size = 0;
|
||||
SecPkgContext_Sizes sizes;
|
||||
SecPkgCredentials_Names names;
|
||||
SECURITY_STATUS status;
|
||||
char *user_name;
|
||||
|
||||
/* Decode the base-64 encoded input message */
|
||||
if(strlen(chlg64) && *chlg64 != '=') {
|
||||
result = Curl_base64_decode(chlg64, &chlg, &chlglen);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Ensure we have a valid challenge message */
|
||||
if(!chlg) {
|
||||
infof(data, "GSSAPI handshake failure (empty security message)\n");
|
||||
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
/* Get our response size information */
|
||||
status = s_pSecFn->QueryContextAttributes(krb5->context,
|
||||
SECPKG_ATTR_SIZES,
|
||||
&sizes);
|
||||
if(status != SEC_E_OK) {
|
||||
free(chlg);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Get the fully qualified username back from the context */
|
||||
status = s_pSecFn->QueryCredentialsAttributes(krb5->credentials,
|
||||
SECPKG_CRED_ATTR_NAMES,
|
||||
&names);
|
||||
if(status != SEC_E_OK) {
|
||||
free(chlg);
|
||||
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
|
||||
/* Setup the "input" security buffer */
|
||||
input_desc.ulVersion = SECBUFFER_VERSION;
|
||||
input_desc.cBuffers = 2;
|
||||
input_desc.pBuffers = input_buf;
|
||||
input_buf[0].BufferType = SECBUFFER_STREAM;
|
||||
input_buf[0].pvBuffer = chlg;
|
||||
input_buf[0].cbBuffer = curlx_uztoul(chlglen);
|
||||
input_buf[1].BufferType = SECBUFFER_DATA;
|
||||
input_buf[1].pvBuffer = NULL;
|
||||
input_buf[1].cbBuffer = 0;
|
||||
|
||||
/* Decrypt the inbound challenge and obtain the qop */
|
||||
status = s_pSecFn->DecryptMessage(krb5->context, &input_desc, 0, &qop);
|
||||
if(status != SEC_E_OK) {
|
||||
infof(data, "GSSAPI handshake failure (empty security message)\n");
|
||||
|
||||
free(chlg);
|
||||
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
/* Not 4 octets long so fail as per RFC4752 Section 3.1 */
|
||||
if(input_buf[1].cbBuffer != 4) {
|
||||
infof(data, "GSSAPI handshake failure (invalid security data)\n");
|
||||
|
||||
free(chlg);
|
||||
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
/* Copy the data out and free the challenge as it is not required anymore */
|
||||
memcpy(&indata, input_buf[1].pvBuffer, 4);
|
||||
s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer);
|
||||
free(chlg);
|
||||
|
||||
/* Extract the security layer */
|
||||
sec_layer = indata & 0x000000FF;
|
||||
if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) {
|
||||
infof(data, "GSSAPI handshake failure (invalid security layer)\n");
|
||||
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
/* Extract the maximum message size the server can receive */
|
||||
max_size = ntohl(indata & 0xFFFFFF00);
|
||||
if(max_size > 0) {
|
||||
/* The server has told us it supports a maximum receive buffer, however, as
|
||||
we don't require one unless we are encrypting data, we tell the server
|
||||
our receive buffer is zero. */
|
||||
max_size = 0;
|
||||
}
|
||||
|
||||
/* Allocate the trailer */
|
||||
trailer = malloc(sizes.cbSecurityTrailer);
|
||||
if(!trailer)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Convert the user name to UTF8 when operating with Unicode */
|
||||
user_name = Curl_convert_tchar_to_UTF8(names.sUserName);
|
||||
if(!user_name) {
|
||||
free(trailer);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Allocate our message */
|
||||
messagelen = sizeof(outdata) + strlen(user_name) + 1;
|
||||
message = malloc(messagelen);
|
||||
if(!message) {
|
||||
free(trailer);
|
||||
Curl_unicodefree(user_name);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Populate the message with the security layer, client supported receive
|
||||
message size and authorization identity including the 0x00 based
|
||||
terminator. Note: Despite RFC4752 Section 3.1 stating "The authorization
|
||||
identity is not terminated with the zero-valued (%x00) octet." it seems
|
||||
necessary to include it. */
|
||||
outdata = htonl(max_size) | sec_layer;
|
||||
memcpy(message, &outdata, sizeof(outdata));
|
||||
strcpy((char *) message + sizeof(outdata), user_name);
|
||||
Curl_unicodefree(user_name);
|
||||
|
||||
/* Allocate the padding */
|
||||
padding = malloc(sizes.cbBlockSize);
|
||||
if(!padding) {
|
||||
free(message);
|
||||
free(trailer);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Setup the "authentication data" security buffer */
|
||||
wrap_desc.ulVersion = SECBUFFER_VERSION;
|
||||
wrap_desc.cBuffers = 3;
|
||||
wrap_desc.pBuffers = wrap_buf;
|
||||
wrap_buf[0].BufferType = SECBUFFER_TOKEN;
|
||||
wrap_buf[0].pvBuffer = trailer;
|
||||
wrap_buf[0].cbBuffer = sizes.cbSecurityTrailer;
|
||||
wrap_buf[1].BufferType = SECBUFFER_DATA;
|
||||
wrap_buf[1].pvBuffer = message;
|
||||
wrap_buf[1].cbBuffer = curlx_uztoul(messagelen);
|
||||
wrap_buf[2].BufferType = SECBUFFER_PADDING;
|
||||
wrap_buf[2].pvBuffer = padding;
|
||||
wrap_buf[2].cbBuffer = sizes.cbBlockSize;
|
||||
|
||||
/* Encrypt the data */
|
||||
status = s_pSecFn->EncryptMessage(krb5->context, KERB_WRAP_NO_ENCRYPT,
|
||||
&wrap_desc, 0);
|
||||
if(status != SEC_E_OK) {
|
||||
free(padding);
|
||||
free(message);
|
||||
free(trailer);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Allocate the encryption (wrap) buffer */
|
||||
appdatalen = wrap_buf[0].cbBuffer + wrap_buf[1].cbBuffer +
|
||||
wrap_buf[2].cbBuffer;
|
||||
appdata = malloc(appdatalen);
|
||||
if(!appdata) {
|
||||
free(padding);
|
||||
free(message);
|
||||
free(trailer);
|
||||
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Populate the encryption buffer */
|
||||
memcpy(appdata, wrap_buf[0].pvBuffer, wrap_buf[0].cbBuffer);
|
||||
offset += wrap_buf[0].cbBuffer;
|
||||
memcpy(appdata + offset, wrap_buf[1].pvBuffer, wrap_buf[1].cbBuffer);
|
||||
offset += wrap_buf[1].cbBuffer;
|
||||
memcpy(appdata + offset, wrap_buf[2].pvBuffer, wrap_buf[2].cbBuffer);
|
||||
|
||||
/* Base64 encode the response */
|
||||
result = Curl_base64_encode(data, (char *) appdata, appdatalen, outptr,
|
||||
outlen);
|
||||
|
||||
/* Free all of our local buffers */
|
||||
free(appdata);
|
||||
free(padding);
|
||||
free(message);
|
||||
free(trailer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_gssapi_cleanup()
|
||||
*
|
||||
* This is used to clean up the GSSAPI (Kerberos V5) specific data.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* krb5 [in/out] - The Kerberos 5 data struct being cleaned up.
|
||||
*
|
||||
*/
|
||||
void Curl_auth_gssapi_cleanup(struct kerberos5data *krb5)
|
||||
{
|
||||
/* Free our security context */
|
||||
if(krb5->context) {
|
||||
s_pSecFn->DeleteSecurityContext(krb5->context);
|
||||
free(krb5->context);
|
||||
krb5->context = NULL;
|
||||
}
|
||||
|
||||
/* Free our credentials handle */
|
||||
if(krb5->credentials) {
|
||||
s_pSecFn->FreeCredentialsHandle(krb5->credentials);
|
||||
free(krb5->credentials);
|
||||
krb5->credentials = NULL;
|
||||
}
|
||||
|
||||
/* Free our identity */
|
||||
Curl_sspi_free_identity(krb5->p_identity);
|
||||
krb5->p_identity = NULL;
|
||||
|
||||
/* Free the SPN and output token */
|
||||
Curl_safefree(krb5->spn);
|
||||
Curl_safefree(krb5->output_token);
|
||||
|
||||
/* Reset any variables */
|
||||
krb5->token_max = 0;
|
||||
}
|
||||
|
||||
#endif /* USE_WINDOWS_SSPI && USE_KERBEROS5*/
|
||||
@@ -28,7 +28,7 @@
|
||||
* NTLM details:
|
||||
*
|
||||
* http://davenport.sourceforge.net/ntlm.html
|
||||
* http://www.innovation.ch/java/ntlm.html
|
||||
* https://www.innovation.ch/java/ntlm.html
|
||||
*/
|
||||
|
||||
#define DEBUG_ME 0
|
||||
@@ -49,8 +49,8 @@
|
||||
#endif
|
||||
|
||||
#define BUILDING_CURL_NTLM_MSGS_C
|
||||
#include "curl_ntlm_msgs.h"
|
||||
#include "curl_sasl.h"
|
||||
#include "vauth/vauth.h"
|
||||
#include "vauth/ntlm.h"
|
||||
#include "curl_endian.h"
|
||||
#include "curl_printf.h"
|
||||
|
||||
@@ -138,7 +138,9 @@ static void ntlm_print_flags(FILE *handle, unsigned long flags)
|
||||
static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
|
||||
{
|
||||
const char *p = buf;
|
||||
(void)handle;
|
||||
|
||||
(void) handle;
|
||||
|
||||
fprintf(stderr, "0x");
|
||||
while(len-- > 0)
|
||||
fprintf(stderr, "%02.2x", (unsigned int)*p++);
|
||||
@@ -215,7 +217,7 @@ static CURLcode ntlm_decode_type2_target(struct SessionHandle *data,
|
||||
*/
|
||||
|
||||
/*
|
||||
* Curl_sasl_decode_ntlm_type2_message()
|
||||
* Curl_auth_decode_ntlm_type2_message()
|
||||
*
|
||||
* This is used to decode an already encoded NTLM type-2 message. The message
|
||||
* is first decoded from a base64 string into a raw NTLM message and checked
|
||||
@@ -230,7 +232,7 @@ static CURLcode ntlm_decode_type2_target(struct SessionHandle *data,
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data,
|
||||
CURLcode Curl_auth_decode_ntlm_type2_message(struct SessionHandle *data,
|
||||
const char *type2msg,
|
||||
struct ntlmdata *ntlm)
|
||||
{
|
||||
@@ -327,7 +329,7 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length)
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_sasl_create_ntlm_type1_message()
|
||||
* Curl_auth_create_ntlm_type1_message()
|
||||
*
|
||||
* This is used to generate an already encoded NTLM type-1 message ready for
|
||||
* sending to the recipient using the appropriate compile time crypto API.
|
||||
@@ -343,7 +345,7 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length)
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
|
||||
CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
|
||||
const char *passwdp,
|
||||
struct ntlmdata *ntlm,
|
||||
char **outptr, size_t *outlen)
|
||||
@@ -376,7 +378,7 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
|
||||
(void)passwdp;
|
||||
|
||||
/* Clean up any former leftovers and initialise to defaults */
|
||||
Curl_sasl_ntlm_cleanup(ntlm);
|
||||
Curl_auth_ntlm_cleanup(ntlm);
|
||||
|
||||
#if USE_NTRESPONSES && USE_NTLM2SESSION
|
||||
#define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
|
||||
@@ -446,7 +448,7 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_sasl_create_ntlm_type3_message()
|
||||
* Curl_auth_create_ntlm_type3_message()
|
||||
*
|
||||
* This is used to generate an already encoded NTLM type-3 message ready for
|
||||
* sending to the recipient using the appropriate compile time crypto API.
|
||||
@@ -463,7 +465,7 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
|
||||
CURLcode Curl_auth_create_ntlm_type3_message(struct SessionHandle *data,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
struct ntlmdata *ntlm,
|
||||
@@ -813,9 +815,28 @@ CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
|
||||
/* Return with binary blob encoded into base64 */
|
||||
result = Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
|
||||
|
||||
Curl_sasl_ntlm_cleanup(ntlm);
|
||||
Curl_auth_ntlm_cleanup(ntlm);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_ntlm_cleanup()
|
||||
*
|
||||
* This is used to clean up the NTLM specific data.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* ntlm [in/out] - The NTLM data struct being cleaned up.
|
||||
*
|
||||
*/
|
||||
void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm)
|
||||
{
|
||||
/* Free the target info */
|
||||
Curl_safefree(ntlm->target_info);
|
||||
|
||||
/* Reset any variables */
|
||||
ntlm->target_info_len = 0;
|
||||
}
|
||||
|
||||
#endif /* USE_NTLM && !USE_WINDOWS_SSPI */
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef HEADER_CURL_NTLM_MSGS_H
|
||||
#define HEADER_CURL_NTLM_MSGS_H
|
||||
#ifndef HEADER_CURL_NTLM_H
|
||||
#define HEADER_CURL_NTLM_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@@ -140,4 +140,4 @@
|
||||
|
||||
#endif /* USE_NTLM */
|
||||
|
||||
#endif /* HEADER_CURL_NTLM_MSGS_H */
|
||||
#endif /* HEADER_CURL_NTLM_H */
|
||||
314
project/jni/curl/lib/vauth/ntlm_sspi.c
Normal file
314
project/jni/curl/lib/vauth/ntlm_sspi.c
Normal file
@@ -0,0 +1,314 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, 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.haxx.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.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(USE_WINDOWS_SSPI) && defined(USE_NTLM)
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "vauth/vauth.h"
|
||||
#include "urldata.h"
|
||||
#include "curl_base64.h"
|
||||
#include "warnless.h"
|
||||
#include "curl_multibyte.h"
|
||||
#include "sendf.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
* Curl_auth_create_ntlm_type1_message()
|
||||
*
|
||||
* This is used to generate an already encoded NTLM type-1 message ready for
|
||||
* sending to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* userp [in] - The user name in the format User or Domain\User.
|
||||
* passdwp [in] - The user's password.
|
||||
* ntlm [in/out] - The NTLM data struct being used and modified.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
|
||||
const char *passwdp,
|
||||
struct ntlmdata *ntlm,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
PSecPkgInfo SecurityPackage;
|
||||
SecBuffer type_1_buf;
|
||||
SecBufferDesc type_1_desc;
|
||||
SECURITY_STATUS status;
|
||||
unsigned long attrs;
|
||||
TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
|
||||
|
||||
/* Clean up any former leftovers and initialise to defaults */
|
||||
Curl_auth_ntlm_cleanup(ntlm);
|
||||
|
||||
/* Query the security package for NTLM */
|
||||
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM),
|
||||
&SecurityPackage);
|
||||
if(status != SEC_E_OK)
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
|
||||
ntlm->token_max = SecurityPackage->cbMaxToken;
|
||||
|
||||
/* Release the package buffer as it is not required anymore */
|
||||
s_pSecFn->FreeContextBuffer(SecurityPackage);
|
||||
|
||||
/* Allocate our output buffer */
|
||||
ntlm->output_token = malloc(ntlm->token_max);
|
||||
if(!ntlm->output_token)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(userp && *userp) {
|
||||
CURLcode result;
|
||||
|
||||
/* Populate our identity structure */
|
||||
result = Curl_create_sspi_identity(userp, passwdp, &ntlm->identity);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Allow proper cleanup of the identity structure */
|
||||
ntlm->p_identity = &ntlm->identity;
|
||||
}
|
||||
else
|
||||
/* Use the current Windows user */
|
||||
ntlm->p_identity = NULL;
|
||||
|
||||
/* Allocate our credentials handle */
|
||||
ntlm->credentials = malloc(sizeof(CredHandle));
|
||||
if(!ntlm->credentials)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
memset(ntlm->credentials, 0, sizeof(CredHandle));
|
||||
|
||||
/* Acquire our credentials handle */
|
||||
status = s_pSecFn->AcquireCredentialsHandle(NULL,
|
||||
(TCHAR *) TEXT(SP_NAME_NTLM),
|
||||
SECPKG_CRED_OUTBOUND, NULL,
|
||||
ntlm->p_identity, NULL, NULL,
|
||||
ntlm->credentials, &expiry);
|
||||
if(status != SEC_E_OK)
|
||||
return CURLE_LOGIN_DENIED;
|
||||
|
||||
/* Allocate our new context handle */
|
||||
ntlm->context = malloc(sizeof(CtxtHandle));
|
||||
if(!ntlm->context)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
memset(ntlm->context, 0, sizeof(CtxtHandle));
|
||||
|
||||
/* Setup the type-1 "output" security buffer */
|
||||
type_1_desc.ulVersion = SECBUFFER_VERSION;
|
||||
type_1_desc.cBuffers = 1;
|
||||
type_1_desc.pBuffers = &type_1_buf;
|
||||
type_1_buf.BufferType = SECBUFFER_TOKEN;
|
||||
type_1_buf.pvBuffer = ntlm->output_token;
|
||||
type_1_buf.cbBuffer = curlx_uztoul(ntlm->token_max);
|
||||
|
||||
/* Generate our type-1 message */
|
||||
status = s_pSecFn->InitializeSecurityContext(ntlm->credentials, NULL,
|
||||
(TCHAR *) TEXT(""),
|
||||
0, 0, SECURITY_NETWORK_DREP,
|
||||
NULL, 0,
|
||||
ntlm->context, &type_1_desc,
|
||||
&attrs, &expiry);
|
||||
if(status == SEC_I_COMPLETE_NEEDED ||
|
||||
status == SEC_I_COMPLETE_AND_CONTINUE)
|
||||
s_pSecFn->CompleteAuthToken(ntlm->context, &type_1_desc);
|
||||
else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED)
|
||||
return CURLE_RECV_ERROR;
|
||||
|
||||
/* Base64 encode the response */
|
||||
return Curl_base64_encode(NULL, (char *) ntlm->output_token,
|
||||
type_1_buf.cbBuffer, outptr, outlen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_decode_ntlm_type2_message()
|
||||
*
|
||||
* This is used to decode an already encoded NTLM type-2 message.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* type2msg [in] - The base64 encoded type-2 message.
|
||||
* ntlm [in/out] - The NTLM data struct being used and modified.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_decode_ntlm_type2_message(struct SessionHandle *data,
|
||||
const char *type2msg,
|
||||
struct ntlmdata *ntlm)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
unsigned char *type2 = NULL;
|
||||
size_t type2_len = 0;
|
||||
|
||||
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
(void) data;
|
||||
#endif
|
||||
|
||||
/* Decode the base-64 encoded type-2 message */
|
||||
if(strlen(type2msg) && *type2msg != '=') {
|
||||
result = Curl_base64_decode(type2msg, &type2, &type2_len);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Ensure we have a valid type-2 message */
|
||||
if(!type2) {
|
||||
infof(data, "NTLM handshake failure (empty type-2 message)\n");
|
||||
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
/* Simply store the challenge for use later */
|
||||
ntlm->input_token = type2;
|
||||
ntlm->input_token_len = type2_len;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_create_ntlm_type3_message()
|
||||
* Curl_auth_create_ntlm_type3_message()
|
||||
*
|
||||
* This is used to generate an already encoded NTLM type-3 message ready for
|
||||
* sending to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* userp [in] - The user name in the format User or Domain\User.
|
||||
* passdwp [in] - The user's password.
|
||||
* ntlm [in/out] - The NTLM data struct being used and modified.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_auth_create_ntlm_type3_message(struct SessionHandle *data,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
struct ntlmdata *ntlm,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
SecBuffer type_2_buf;
|
||||
SecBuffer type_3_buf;
|
||||
SecBufferDesc type_2_desc;
|
||||
SecBufferDesc type_3_desc;
|
||||
SECURITY_STATUS status;
|
||||
unsigned long attrs;
|
||||
TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
|
||||
|
||||
(void) passwdp;
|
||||
(void) userp;
|
||||
|
||||
/* Setup the type-2 "input" security buffer */
|
||||
type_2_desc.ulVersion = SECBUFFER_VERSION;
|
||||
type_2_desc.cBuffers = 1;
|
||||
type_2_desc.pBuffers = &type_2_buf;
|
||||
type_2_buf.BufferType = SECBUFFER_TOKEN;
|
||||
type_2_buf.pvBuffer = ntlm->input_token;
|
||||
type_2_buf.cbBuffer = curlx_uztoul(ntlm->input_token_len);
|
||||
|
||||
/* Setup the type-3 "output" security buffer */
|
||||
type_3_desc.ulVersion = SECBUFFER_VERSION;
|
||||
type_3_desc.cBuffers = 1;
|
||||
type_3_desc.pBuffers = &type_3_buf;
|
||||
type_3_buf.BufferType = SECBUFFER_TOKEN;
|
||||
type_3_buf.pvBuffer = ntlm->output_token;
|
||||
type_3_buf.cbBuffer = curlx_uztoul(ntlm->token_max);
|
||||
|
||||
/* Generate our type-3 message */
|
||||
status = s_pSecFn->InitializeSecurityContext(ntlm->credentials,
|
||||
ntlm->context,
|
||||
(TCHAR *) TEXT(""),
|
||||
0, 0, SECURITY_NETWORK_DREP,
|
||||
&type_2_desc,
|
||||
0, ntlm->context,
|
||||
&type_3_desc,
|
||||
&attrs, &expiry);
|
||||
if(status != SEC_E_OK) {
|
||||
infof(data, "NTLM handshake failure (type-3 message): Status=%x\n",
|
||||
status);
|
||||
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
|
||||
/* Base64 encode the response */
|
||||
result = Curl_base64_encode(data, (char *) ntlm->output_token,
|
||||
type_3_buf.cbBuffer, outptr, outlen);
|
||||
|
||||
Curl_auth_ntlm_cleanup(ntlm);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_auth_ntlm_cleanup()
|
||||
*
|
||||
* This is used to clean up the NTLM specific data.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* ntlm [in/out] - The NTLM data struct being cleaned up.
|
||||
*
|
||||
*/
|
||||
void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm)
|
||||
{
|
||||
/* Free our security context */
|
||||
if(ntlm->context) {
|
||||
s_pSecFn->DeleteSecurityContext(ntlm->context);
|
||||
free(ntlm->context);
|
||||
ntlm->context = NULL;
|
||||
}
|
||||
|
||||
/* Free our credentials handle */
|
||||
if(ntlm->credentials) {
|
||||
s_pSecFn->FreeCredentialsHandle(ntlm->credentials);
|
||||
free(ntlm->credentials);
|
||||
ntlm->credentials = NULL;
|
||||
}
|
||||
|
||||
/* Free our identity */
|
||||
Curl_sspi_free_identity(ntlm->p_identity);
|
||||
ntlm->p_identity = NULL;
|
||||
|
||||
/* Free the input and output tokens */
|
||||
Curl_safefree(ntlm->input_token);
|
||||
Curl_safefree(ntlm->output_token);
|
||||
|
||||
/* Reset any variables */
|
||||
ntlm->token_max = 0;
|
||||
}
|
||||
|
||||
#endif /* USE_WINDOWS_SSPI && USE_NTLM */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user