aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.Watcom2
-rw-r--r--lib/Makefile.inc10
-rw-r--r--lib/Makefile.m3287
-rw-r--r--lib/Makefile.netware54
-rw-r--r--lib/Makefile.vc650
-rw-r--r--lib/asyn-ares.c6
-rw-r--r--lib/asyn-thread.c27
-rw-r--r--lib/asyn.h6
-rw-r--r--lib/axtls.c38
-rw-r--r--lib/base64.c67
-rwxr-xr-xlib/checksrc.pl11
-rw-r--r--lib/config-amigaos.h3
-rw-r--r--lib/config-dos.h1
-rw-r--r--lib/config-mac.h1
-rw-r--r--lib/config-os400.h3
-rw-r--r--lib/config-riscos.h3
-rw-r--r--lib/config-vms.h3
-rw-r--r--lib/config-win32.h241
-rw-r--r--lib/config-win32ce.h3
-rw-r--r--lib/connect.c42
-rw-r--r--lib/connect.h12
-rw-r--r--lib/content_encoding.c35
-rw-r--r--lib/content_encoding.h10
-rw-r--r--lib/cookie.c352
-rw-r--r--lib/cookie.h16
-rw-r--r--lib/curl_addrinfo.c1
-rw-r--r--lib/curl_base64.h11
-rw-r--r--lib/curl_gethostname.c33
-rw-r--r--lib/curl_gethostname.h4
-rw-r--r--lib/curl_gssapi.c69
-rw-r--r--lib/curl_gssapi.h57
-rw-r--r--lib/curl_ntlm.c238
-rw-r--r--lib/curl_ntlm.h44
-rw-r--r--lib/curl_ntlm_core.c379
-rw-r--r--lib/curl_ntlm_core.h68
-rw-r--r--lib/curl_ntlm_msgs.c958
-rw-r--r--lib/curl_ntlm_msgs.h (renamed from lib/http_ntlm.h)65
-rw-r--r--lib/curl_ntlm_wb.c394
-rw-r--r--lib/curl_ntlm_wb.h37
-rw-r--r--lib/curl_rtmp.c6
-rw-r--r--lib/curl_threads.c1
-rw-r--r--lib/cyassl.c11
-rw-r--r--lib/cyassl.h3
-rw-r--r--lib/dict.c20
-rw-r--r--lib/easy.c45
-rw-r--r--lib/escape.c5
-rw-r--r--lib/file.c61
-rw-r--r--lib/fileinfo.c5
-rw-r--r--lib/formdata.c77
-rw-r--r--lib/ftp.c160
-rw-r--r--lib/ftplistparser.c2
-rw-r--r--lib/getenv.c4
-rw-r--r--lib/getinfo.c4
-rw-r--r--lib/gopher.c20
-rw-r--r--lib/gtls.c7
-rw-r--r--lib/gtls.h10
-rw-r--r--lib/hash.c26
-rw-r--r--lib/hostasyn.c6
-rw-r--r--lib/hostip.c10
-rw-r--r--lib/hostip4.c9
-rw-r--r--lib/hostip6.c8
-rw-r--r--lib/hostsyn.c6
-rw-r--r--lib/http.c503
-rw-r--r--lib/http_chunks.c13
-rw-r--r--lib/http_digest.c20
-rw-r--r--lib/http_digest.h9
-rw-r--r--lib/http_negotiate.c77
-rw-r--r--lib/http_negotiate_sspi.c51
-rw-r--r--lib/http_ntlm.c1329
-rw-r--r--lib/http_proxy.c1
-rw-r--r--lib/idn_win32.c22
-rw-r--r--lib/imap.c18
-rw-r--r--lib/inet_ntop.c2
-rw-r--r--lib/inet_pton.c2
-rw-r--r--lib/krb4.c45
-rw-r--r--lib/krb5.c70
-rw-r--r--lib/ldap.c38
-rw-r--r--lib/libcurl.imp4
-rw-r--r--lib/llist.c9
-rw-r--r--lib/md4.c1
-rw-r--r--lib/md5.c2
-rw-r--r--lib/memdebug.c86
-rw-r--r--lib/memdebug.h38
-rwxr-xr-xlib/mk-ca-bundle.pl51
-rw-r--r--lib/mprintf.c7
-rw-r--r--lib/multi.c221
-rw-r--r--lib/netrc.c4
-rw-r--r--lib/non-ascii.h6
-rw-r--r--lib/nonblock.c16
-rw-r--r--lib/nss.c310
-rw-r--r--lib/nssg.h10
-rw-r--r--lib/nwlib.c6
-rw-r--r--lib/nwos.c13
-rw-r--r--lib/openldap.c21
-rw-r--r--lib/parsedate.c8
-rw-r--r--lib/pingpong.c73
-rw-r--r--lib/pingpong.h16
-rw-r--r--lib/polarssl.c30
-rw-r--r--lib/polarssl.h4
-rw-r--r--lib/pop3.c15
-rw-r--r--lib/progress.c2
-rw-r--r--lib/qssl.c4
-rw-r--r--lib/qssl.h10
-rw-r--r--lib/rtsp.c2
-rw-r--r--lib/security.c43
-rw-r--r--lib/select.c23
-rw-r--r--lib/select.h18
-rw-r--r--lib/sendf.c20
-rw-r--r--lib/sendf.h6
-rw-r--r--lib/setup.h40
-rw-r--r--lib/setup_once.h33
-rw-r--r--lib/share.c52
-rw-r--r--lib/share.h8
-rw-r--r--lib/slist.c10
-rw-r--r--lib/smtp.c515
-rw-r--r--lib/smtp.h4
-rw-r--r--lib/socks.c46
-rw-r--r--lib/socks.h3
-rw-r--r--lib/socks_gssapi.c44
-rw-r--r--lib/socks_sspi.c29
-rw-r--r--lib/speedcheck.c12
-rw-r--r--lib/splay.h11
-rw-r--r--lib/ssh.c73
-rw-r--r--lib/sslgen.c63
-rw-r--r--lib/sslgen.h18
-rw-r--r--lib/ssluse.c35
-rw-r--r--lib/ssluse.h9
-rw-r--r--lib/strdup.c1
-rw-r--r--lib/strequal.c3
-rw-r--r--lib/strerror.c6
-rw-r--r--lib/strtok.c1
-rw-r--r--lib/strtoofft.c5
-rw-r--r--lib/telnet.c120
-rw-r--r--lib/tftp.c46
-rw-r--r--lib/transfer.c166
-rw-r--r--lib/url.c302
-rw-r--r--lib/url.h12
-rw-r--r--lib/urldata.h22
-rw-r--r--lib/version.c6
-rw-r--r--lib/warnless.c19
-rw-r--r--lib/warnless.h2
-rw-r--r--lib/wildcard.c1
142 files changed, 5372 insertions, 3571 deletions
diff --git a/lib/Makefile.Watcom b/lib/Makefile.Watcom
index a780bbb28..10906c942 100644
--- a/lib/Makefile.Watcom
+++ b/lib/Makefile.Watcom
@@ -89,7 +89,7 @@ ZLIB_ROOT = ..$(DS)..$(DS)zlib-1.2.5
!ifdef %libssh2_root
LIBSSH2_ROOT = $(%libssh2_root)
!else
-LIBSSH2_ROOT = ..$(DS)..$(DS)libssh2-1.2.8
+LIBSSH2_ROOT = ..$(DS)..$(DS)libssh2-1.3.0
!endif
!ifdef %librtmp_root
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index 04285b533..ec7f50537 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -14,7 +14,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
curl_fnmatch.c fileinfo.c ftplistparser.c wildcard.c krb5.c \
memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c multi.c \
content_encoding.c share.c http_digest.c md4.c md5.c curl_rand.c \
- http_negotiate.c http_ntlm.c inet_pton.c strtoofft.c strerror.c \
+ http_negotiate.c inet_pton.c strtoofft.c strerror.c \
hostasyn.c hostip4.c hostip6.c hostsyn.c inet_ntop.c parsedate.c \
select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c nss.c \
qssl.c rawstr.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \
@@ -22,7 +22,8 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
pingpong.c rtsp.c curl_threads.c warnless.c hmac.c polarssl.c \
curl_rtmp.c openldap.c curl_gethostname.c gopher.c axtls.c \
idn_win32.c http_negotiate_sspi.c cyassl.c http_proxy.c non-ascii.c \
- asyn-ares.c asyn-thread.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
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
@@ -30,11 +31,12 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
getinfo.h strequal.h krb4.h memdebug.h http_chunks.h curl_rand.h \
curl_fnmatch.h wildcard.h fileinfo.h ftplistparser.h strtok.h \
connect.h llist.h hash.h content_encoding.h share.h curl_md4.h \
- curl_md5.h http_digest.h http_negotiate.h http_ntlm.h inet_pton.h \
+ curl_md5.h http_digest.h http_negotiate.h inet_pton.h \
strtoofft.h strerror.h inet_ntop.h curlx.h curl_memory.h setup.h \
transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h gtls.h \
tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h nssg.h \
curl_base64.h rawstr.h curl_addrinfo.h curl_sspi.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 polarssl.h curl_rtmp.h curl_gethostname.h \
- gopher.h axtls.h cyassl.h http_proxy.h non-ascii.h asyn.h
+ gopher.h axtls.h cyassl.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
diff --git a/lib/Makefile.m32 b/lib/Makefile.m32
index 76171cb9b..140571653 100644
--- a/lib/Makefile.m32
+++ b/lib/Makefile.m32
@@ -1,7 +1,7 @@
-#########################################################################
+###########################################################################
#
-## Makefile for building libcurl.a with MingW32 (GCC-3.2 or later)
-## and optionally OpenSSL (0.9.8), libssh2 (1.2), zlib (1.2.5), librtmp (2.3)
+## Makefile for building libcurl.a with MingW (GCC-3.2 or later)
+## and optionally OpenSSL (0.9.8), libssh2 (1.3), zlib (1.2.5), librtmp (2.3)
##
## Usage: mingw32-make -f Makefile.m32 CFG=-feature1[-feature2][-feature3][...]
## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-sspi-winidn
@@ -9,10 +9,8 @@
## Hint: you can also set environment vars to control the build, f.e.:
## set ZLIB_PATH=c:/zlib-1.2.5
## set ZLIB=1
-##
-## Comments to: Troy Engel <tengel@sonic.net> or
-## Joern Hartroth <hartroth@acm.org>
-#########################################################################
+#
+###########################################################################
# Edit the path below to point to the base of your Zlib sources.
ifndef ZLIB_PATH
@@ -22,9 +20,18 @@ endif
ifndef OPENSSL_PATH
OPENSSL_PATH = ../../openssl-0.9.8r
endif
+ifndef OPENSSL_INCLUDE
+OPENSSL_INCLUDE = $(OPENSSL_PATH)/outinc
+endif
+ifndef OPENSSL_LIBPATH
+OPENSSL_LIBPATH = $(OPENSSL_PATH)/out
+endif
+ifndef OPENSSL_LIBS
+OPENSSL_LIBS = -leay32 -lssl32
+endif
# Edit the path below to point to the base of your LibSSH2 package.
ifndef LIBSSH2_PATH
-LIBSSH2_PATH = ../../libssh2-1.2.8
+LIBSSH2_PATH = ../../libssh2-1.3.0
endif
# Edit the path below to point to the base of your librtmp package.
ifndef LIBRTMP_PATH
@@ -45,22 +52,35 @@ ifndef LDAP_SDK
LDAP_SDK = c:/novell/ndk/cldapsdk/win32
endif
+PROOT = ..
+
# Edit the path below to point to the base of your c-ares package.
ifndef LIBCARES_PATH
-LIBCARES_PATH = ../ares
+LIBCARES_PATH = $(PROOT)/ares
+endif
+
+# Edit the var below to set to your architecture or set environment var.
+ifndef ARCH
+ARCH = w32
endif
CC = gcc
CFLAGS = -g -O2 -Wall
+CFLAGS += -fno-strict-aliasing
+ifeq ($(ARCH),w64)
+CFLAGS += -D_AMD64_
+endif
# comment LDFLAGS below to keep debug info
LDFLAGS = -s
AR = ar
RANLIB = ranlib
RC = windres
-RCFLAGS = --include-dir=../include -DDEBUGBUILD=0 -O COFF -i
-RM = del /q /f 2>NUL
+RCFLAGS = --include-dir=$(PROOT)/include -DDEBUGBUILD=0 -O COFF -i
STRIP = strip -g
+RM = del /q /f 2>NUL
+CP = copy
+
########################################################
## Nothing more to do below this line!
@@ -95,6 +115,9 @@ endif
ifeq ($(findstring -sspi,$(CFG)),-sspi)
SSPI = 1
endif
+ifeq ($(findstring -spnego,$(CFG)),-spnego)
+SPNEGO = 1
+endif
ifeq ($(findstring -ldaps,$(CFG)),-ldaps)
LDAPS = 1
endif
@@ -104,10 +127,11 @@ endif
INCLUDES = -I. -I../include
CFLAGS += -DBUILDING_LIBCURL
+
ifdef ARES
- INCLUDES += -I$(LIBCARES_PATH)
+ INCLUDES += -I"$(LIBCARES_PATH)"
CFLAGS += -DUSE_ARES
- DLL_LIBS += -L$(LIBCARES_PATH) -lcares
+ DLL_LIBS += -L"$(LIBCARES_PATH)" -lcares
libcurl_dll_DEPENDENCIES = $(LIBCARES_PATH)/libcares.a
endif
ifdef RTMP
@@ -118,37 +142,39 @@ endif
ifdef SSH2
INCLUDES += -I"$(LIBSSH2_PATH)/include" -I"$(LIBSSH2_PATH)/win32"
CFLAGS += -DUSE_LIBSSH2 -DHAVE_LIBSSH2_H
- DLL_LIBS += -L$(LIBSSH2_PATH)/win32 -lssh2
+ DLL_LIBS += -L"$(LIBSSH2_PATH)/win32" -lssh2
endif
ifdef SSL
- INCLUDES += -I"$(OPENSSL_PATH)/outinc" -I"$(OPENSSL_PATH)/outinc/openssl"
+ INCLUDES += -I"$(OPENSSL_INCLUDE)"
CFLAGS += -DUSE_SSLEAY -DUSE_OPENSSL -DHAVE_OPENSSL_ENGINE_H -DHAVE_OPENSSL_PKCS12_H \
-DHAVE_ENGINE_LOAD_BUILTIN_ENGINES -DOPENSSL_NO_KRB5 \
-DCURL_WANTS_CA_BUNDLE_ENV
- DLL_LIBS += -L$(OPENSSL_PATH)/out -leay32 -lssl32
+ DLL_LIBS += -L"$(OPENSSL_LIBPATH)" $(OPENSSL_LIBS)
endif
ifdef ZLIB
INCLUDES += -I"$(ZLIB_PATH)"
CFLAGS += -DHAVE_LIBZ -DHAVE_ZLIB_H
- DLL_LIBS += -L$(ZLIB_PATH) -lz
+ DLL_LIBS += -L"$(ZLIB_PATH)" -lz
endif
ifdef IDN
INCLUDES += -I"$(LIBIDN_PATH)/include"
CFLAGS += -DUSE_LIBIDN
- DLL_LIBS += -L$(LIBIDN_PATH)/lib -lidn
+ DLL_LIBS += -L"$(LIBIDN_PATH)/lib" -lidn
else
ifdef WINIDN
- INCLUDES += -I"$(WINIDN_PATH)/include"
- CFLAGS += -DHAVE_NORMALIZATION_H
CFLAGS += -DUSE_WIN32_IDN
+ CFLAGS += -DWANT_IDN_PROTOTYPES
DLL_LIBS += -L"$(WINIDN_PATH)" -lnormaliz
endif
endif
ifdef SSPI
CFLAGS += -DUSE_WINDOWS_SSPI
endif
+ifdef SPNEGO
+ CFLAGS += -DHAVE_SPNEGO
+endif
ifdef IPV6
- CFLAGS += -DENABLE_IPV6
+ CFLAGS += -DENABLE_IPV6 -D_WIN32_WINNT=0x0501
endif
ifdef LDAPS
CFLAGS += -DHAVE_LDAP_SSL
@@ -165,11 +191,10 @@ ifdef USE_LDAP_OPENLDAP
endif
ifndef USE_LDAP_NOVELL
ifndef USE_LDAP_OPENLDAP
-DLL_LIBS += -lwldap32
+ DLL_LIBS += -lwldap32
endif
endif
DLL_LIBS += -lws2_32
-COMPILE = $(CC) $(INCLUDES) $(CFLAGS)
# Makefile.inc provides the CSOURCES and HHEADERS defines
include Makefile.inc
@@ -183,7 +208,6 @@ libcurl_a_DEPENDENCIES := $(strip $(CSOURCES) $(HHEADERS))
RESOURCE = libcurl.res
-.SUFFIXES: .rc .res
all: $(libcurl_a_LIBRARY) $(libcurl_dll_LIBRARY)
@@ -200,20 +224,25 @@ $(libcurl_dll_LIBRARY): $(libcurl_a_OBJECTS) $(RESOURCE) $(libcurl_dll_DEPENDENC
$(CC) $(LDFLAGS) -shared -Wl,--out-implib,$(libcurl_dll_a_LIBRARY) \
-o $@ $(libcurl_a_OBJECTS) $(RESOURCE) $(DLL_LIBS)
-.c.o:
- $(COMPILE) -c $<
+%.o: %.c $(PROOT)/include/curl/curlbuild.h
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<
-.rc.res:
+%.res: %.rc
$(RC) $(RCFLAGS) $< -o $@
clean:
+ifeq "$(wildcard $(PROOT)/include/curl/curlbuild.h.dist)" "$(PROOT)/include/curl/curlbuild.h.dist"
+ -$(RM) $(subst /,\,$(PROOT)/include/curl/curlbuild.h)
+endif
-$(RM) $(libcurl_a_OBJECTS) $(RESOURCE)
distclean vclean: clean
-$(RM) $(libcurl_a_LIBRARY) $(libcurl_dll_LIBRARY) $(libcurl_dll_a_LIBRARY)
-FORCE: ;
-
$(LIBCARES_PATH)/libcares.a:
$(MAKE) -C $(LIBCARES_PATH) -f Makefile.m32
+$(PROOT)/include/curl/curlbuild.h:
+ @echo Creating $@
+ @$(CP) $(subst /,\,$@).dist $(subst /,\,$@)
+
diff --git a/lib/Makefile.netware b/lib/Makefile.netware
index 2cc7c9ecc..43fae2e7a 100644
--- a/lib/Makefile.netware
+++ b/lib/Makefile.netware
@@ -24,7 +24,7 @@ endif
# Edit the path below to point to the base of your LibSSH2 package.
ifndef LIBSSH2_PATH
-LIBSSH2_PATH = ../../libssh2-1.2.8
+LIBSSH2_PATH = ../../libssh2-1.3.0
endif
# Edit the path below to point to the base of your axTLS package.
@@ -42,6 +42,11 @@ ifndef LIBRTMP_PATH
LIBRTMP_PATH = ../../librtmp-2.3
endif
+# Edit the path below to point to the base of your fbopenssl package.
+ifndef FBOPENSSL_PATH
+FBOPENSSL_PATH = ../../fbopenssl-0.4
+endif
+
# Edit the path below to point to the base of your c-ares package.
ifndef LIBCARES_PATH
LIBCARES_PATH = ../ares
@@ -95,7 +100,7 @@ else
endif
PERL = perl
# Here you can find a native Win32 binary of the original awk:
-# http://www.gknw.net/development/prgtools/awk-20070501.zip
+# http://www.gknw.net/development/prgtools/awk-20100523.zip
AWK = awk
CP = cp -afv
MKDIR = mkdir
@@ -181,6 +186,43 @@ CURL_LIB = ../lib
INCLUDES = -I$(CURL_INC) -I$(CURL_LIB)
+ifeq ($(findstring -static,$(CFG)),-static)
+LINK_STATIC = 1
+endif
+ifeq ($(findstring -ares,$(CFG)),-ares)
+WITH_ARES = 1
+endif
+ifeq ($(findstring -rtmp,$(CFG)),-rtmp)
+WITH_RTMP = 1
+WITH_SSL = 1
+WITH_ZLIB = 1
+endif
+ifeq ($(findstring -ssh2,$(CFG)),-ssh2)
+WITH_SSH2 = 1
+WITH_SSL = 1
+WITH_ZLIB = 1
+endif
+ifeq ($(findstring -axtls,$(CFG)),-axtls)
+WITH_AXTLS = 1
+WITH_SSL =
+else
+ifeq ($(findstring -ssl,$(CFG)),-ssl)
+WITH_SSL = 1
+endif
+endif
+ifeq ($(findstring -zlib,$(CFG)),-zlib)
+WITH_ZLIB = 1
+endif
+ifeq ($(findstring -idn,$(CFG)),-idn)
+WITH_IDN = 1
+endif
+ifeq ($(findstring -spnego,$(CFG)),-spnego)
+WITH_SPNEGO = 1
+endif
+ifeq ($(findstring -ipv6,$(CFG)),-ipv6)
+ENABLE_IPV6 = 1
+endif
+
ifdef WITH_ARES
INCLUDES += -I$(LIBCARES_PATH)
LDLIBS += $(LIBCARES_PATH)/libcares.$(LIBEXT)
@@ -204,6 +246,10 @@ ifdef WITH_SSL
LDLIBS += $(OPENSSL_PATH)/out_nw_$(LIBARCH_L)/crypto.$(LIBEXT)
IMPORTS += GetProcessSwitchCount RunningProcess
INSTDEP += ca-bundle.crt
+ifdef WITH_SPNEGO
+ INCLUDES += -I$(FBOPENSSL_PATH)/include
+ LDLIBS += $(FBOPENSSL_PATH)/nw/fbopenssl.$(LIBEXT)
+endif
else
ifdef WITH_AXTLS
INCLUDES += -I$(AXTLS_PATH)/inc
@@ -498,6 +544,7 @@ endif
@echo $(DL)#define USE_MANUAL 1$(DL) >> $@
@echo $(DL)#define HAVE_ARPA_INET_H 1$(DL) >> $@
@echo $(DL)#define HAVE_ASSERT_H 1$(DL) >> $@
+ @echo $(DL)#define HAVE_ERRNO_H 1$(DL) >> $@
@echo $(DL)#define HAVE_ERR_H 1$(DL) >> $@
@echo $(DL)#define HAVE_FCNTL_H 1$(DL) >> $@
@echo $(DL)#define HAVE_GETHOSTBYADDR 1$(DL) >> $@
@@ -583,6 +630,9 @@ ifdef WITH_SSL
@echo $(DL)#define HAVE_LIBSSL 1$(DL) >> $@
@echo $(DL)#define HAVE_LIBCRYPTO 1$(DL) >> $@
@echo $(DL)#define OPENSSL_NO_KRB5 1$(DL) >> $@
+ifdef WITH_SPNEGO
+ @echo $(DL)#define HAVE_SPNEGO 1$(DL) >> $@
+endif
else
ifdef WITH_AXTLS
@echo $(DL)#define USE_AXTLS 1$(DL) >> $@
diff --git a/lib/Makefile.vc6 b/lib/Makefile.vc6
index a778801dc..fb7566660 100644
--- a/lib/Makefile.vc6
+++ b/lib/Makefile.vc6
@@ -20,6 +20,11 @@
#
#***************************************************************************
+# All files in the Makefile.vc* series are generated automatically from the
+# one made for MSVC version 6. Alas, if you want to do changes to any of the
+# fiels and send back to the project, edit the version six, make your diff and
+# mail curl-library.
+
###########################################################################
#
# Makefile for building libcurl with MSVC6
@@ -59,13 +64,14 @@
!INCLUDE ..\Makefile.msvc.names
-
-
-
!IFNDEF OPENSSL_PATH
OPENSSL_PATH = ../../openssl-0.9.8r
!ENDIF
+!IFNDEF LIBSSH2_PATH
+LIBSSH2_PATH = ../../libssh2-1.2.8
+!ENDIF
+
!IFNDEF ZLIB_PATH
ZLIB_PATH = ../../zlib-1.2.5
!ENDIF
@@ -100,6 +106,7 @@ WINDOWS_SDK_PATH = "$(PROGRAMFILES)\Microsoft SDK"
CCNODBG = cl.exe /O2 /DNDEBUG
CCDEBUG = cl.exe /Od /Gm /Zi /D_DEBUG /GZ
CFLAGSSSL = /DUSE_SSLEAY /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
+CFLAGSSSH2 = /DUSE_LIBSSH2 /DCURL_DISABLE_LDAP /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /I "$(LIBSSH2_PATH)/include"
CFLAGSZLIB = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)"
CFLAGS = /I. /I../include /nologo /W3 /GX /DWIN32 /YX /FD /c /DBUILDING_LIBCURL /D_BIND_TO_CURRENT_VCLIBS_VERSION=1
CFLAGSLIB = /DCURL_STATICLIB
@@ -220,6 +227,36 @@ CFGSET = TRUE
!ENDIF
######################
+# release-ssl-ssh2-zlib
+
+!IF "$(CFG)" == "release-ssl-ssh2-zlib"
+TARGET = $(LIB_NAME).lib
+DIROBJ = $(CFG)
+LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
+LFLAGSSSH2 = "/LIBPATH:$(LIBSSH2_PATH)"
+LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
+LNK = $(LNKLIB) $(LFLAGSSSL) $(LFLAGSSSH2) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
+CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSSSH2) $(CFLAGSZLIB) $(CFLAGSLIB)
+CFGSET = TRUE
+RESOURCE = $(LIBSSH2_PATH)/Release/src/libssh2.lib $(ZLIB_PATH)/zlib.lib
+!ENDIF
+
+######################
+# debug-ssl-ssh2-zlib
+
+!IF "$(CFG)" == "debug-ssl-ssh2-zlib"
+TARGET = $(LIB_NAME_DEBUG).lib
+DIROBJ = $(CFG)
+LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
+LFLAGSSSH2 = "/LIBPATH:$(LIBSSH2_PATH)"
+LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
+LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSSSL) $(LFLAGSSSH2) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
+CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSSSH2) $(CFLAGSZLIB) $(CFLAGSLIB)
+CFGSET = TRUE
+RESOURCE = $(LIBSSH2_PATH)/Release/src/libssh2.lib $(ZLIB_PATH)/zlib.lib
+!ENDIF
+
+######################
# release-dll
!IF "$(CFG)" == "release-dll"
@@ -418,6 +455,7 @@ RESOURCE = $(DIROBJ)\libcurl.res
!MESSAGE release-ssl - release static library with ssl
!MESSAGE release-zlib - release static library with zlib
!MESSAGE release-ssl-zlib - release static library with ssl and zlib
+!MESSAGE release-ssl-ssh2-zlib - release static library with ssl, ssh2 and zlib
!MESSAGE release-ssl-dll - release static library with dynamic ssl
!MESSAGE release-zlib-dll - release static library with dynamic zlib
!MESSAGE release-ssl-dll-zlib-dll - release static library with dynamic ssl and dynamic zlib
@@ -425,6 +463,7 @@ RESOURCE = $(DIROBJ)\libcurl.res
!MESSAGE release-dll-ssl-dll - release dynamic library with dynamic ssl
!MESSAGE release-dll-zlib-dll - release dynamic library with dynamic zlib
!MESSAGE release-dll-ssl-dll-zlib-dll - release dynamic library with dynamic ssl and dynamic zlib
+!MESSAGE debug-ssl-ssh2-zlib - debug static library with ssl, ssh2 and zlib
!MESSAGE debug - debug static library
!MESSAGE debug-ssl - debug static library with ssl
!MESSAGE debug-zlib - debug static library with zlib
@@ -467,6 +506,10 @@ X_OBJS= \
$(DIROBJ)\curl_fnmatch.obj \
$(DIROBJ)\curl_gethostname.obj \
$(DIROBJ)\curl_memrchr.obj \
+ $(DIROBJ)\curl_ntlm.obj \
+ $(DIROBJ)\curl_ntlm_core.obj \
+ $(DIROBJ)\curl_ntlm_msgs.obj \
+ $(DIROBJ)\curl_ntlm_wb.obj \
$(DIROBJ)\curl_rand.obj \
$(DIROBJ)\curl_rtmp.obj \
$(DIROBJ)\curl_sspi.obj \
@@ -494,7 +537,6 @@ X_OBJS= \
$(DIROBJ)\http_digest.obj \
$(DIROBJ)\http_negotiate.obj \
$(DIROBJ)\http_negotiate_sspi.obj \
- $(DIROBJ)\http_ntlm.obj \
$(DIROBJ)\http.obj \
$(DIROBJ)\http_proxy.obj \
$(DIROBJ)\if2ip.obj \
diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index 4165a451d..7f3bdf8a2 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -22,8 +22,6 @@
#include "setup.h"
-#include <string.h>
-
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
@@ -39,16 +37,12 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h> /* required for free() prototypes */
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
-#include <stdlib.h>
#endif
#ifdef HAVE_PROCESS_H
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index 3341686d9..38cde5df7 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -22,9 +22,6 @@
#include "setup.h"
-#include <string.h>
-#include <errno.h>
-
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -37,16 +34,12 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h> /* required for free() prototypes */
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
-#include <stdlib.h>
#endif
#if defined(USE_THREADS_POSIX)
@@ -421,7 +414,7 @@ static bool init_resolve_thread (struct connectdata *conn,
socket error string function can be used for this pupose. */
static const char *gai_strerror(int ecode)
{
- switch (ecode){
+ switch (ecode) {
case EAI_AGAIN:
return "The name could not be resolved at this time";
case EAI_BADFLAGS:
@@ -633,14 +626,28 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
int *waitp)
{
struct addrinfo hints;
+ struct in_addr in;
Curl_addrinfo *res;
int error;
char sbuf[NI_MAXSERV];
int pf = PF_INET;
+#ifdef CURLRES_IPV6
+ struct in6_addr in6;
+#endif /* CURLRES_IPV6 */
*waitp = 0; /* default to synchronous response */
-#ifndef CURLRES_IPV4
+ /* First check if this is an IPv4 address string */
+ if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
+ /* This is a dotted IP address 123.123.123.123-style */
+ return Curl_ip2addr(AF_INET, &in, hostname, port);
+
+#ifdef CURLRES_IPV6
+ /* check if this is an IPv6 address string */
+ if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0)
+ /* This is an IPv6 address literal */
+ return Curl_ip2addr(AF_INET6, &in6, hostname, port);
+
/*
* Check if a limited name resolve has been requested.
*/
@@ -660,7 +667,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
/* the stack seems to be a non-ipv6 one */
pf = PF_INET;
-#endif /* !CURLRES_IPV4 */
+#endif /* CURLRES_IPV6 */
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
diff --git a/lib/asyn.h b/lib/asyn.h
index 34f9c14c5..e7c1b886d 100644
--- a/lib/asyn.h
+++ b/lib/asyn.h
@@ -146,15 +146,15 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
#ifndef CURLRES_ASYNCH
/* convert these functions if an asynch resolver isn't used */
-#define Curl_resolver_cancel(x)
+#define Curl_resolver_cancel(x) Curl_nop_stmt
#define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
#define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST
#define Curl_resolver_getsock(x,y,z) 0
#define Curl_resolver_duphandle(x,y) CURLE_OK
#define Curl_resolver_init(x) CURLE_OK
#define Curl_resolver_global_init() CURLE_OK
-#define Curl_resolver_global_cleanup()
-#define Curl_resolver_cleanup(x)
+#define Curl_resolver_global_cleanup() Curl_nop_stmt
+#define Curl_resolver_cleanup(x) Curl_nop_stmt
#endif
#ifdef CURLRES_ASYNCH
diff --git a/lib/axtls.c b/lib/axtls.c
index ffbd1d4f3..e37aed50a 100644
--- a/lib/axtls.c
+++ b/lib/axtls.c
@@ -27,13 +27,11 @@
*/
#include "setup.h"
+
#ifdef USE_AXTLS
#include <axTLS/ssl.h>
#include "axtls.h"
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -58,7 +56,7 @@ static int SSL_read(SSL *ssl, void *buf, int num)
while((ret = ssl_read(ssl, &read_buf)) == SSL_OK);
- if(ret > SSL_OK){
+ if(ret > SSL_OK) {
memcpy(buf, read_buf, ret > num ? num : ret);
}
@@ -187,10 +185,10 @@ Curl_axtls_connect(struct connectdata *conn,
/* Load the trusted CA cert bundle file */
if(data->set.ssl.CAfile) {
if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
- != SSL_OK){
+ != SSL_OK) {
infof(data, "error reading ca cert file %s \n",
data->set.ssl.CAfile);
- if(data->set.ssl.verifypeer){
+ if(data->set.ssl.verifypeer) {
Curl_axtls_close(conn, sockindex);
return CURLE_SSL_CACERT_BADFILE;
}
@@ -208,13 +206,13 @@ Curl_axtls_connect(struct connectdata *conn,
*/
/* Load client certificate */
- if(data->set.str[STRING_CERT]){
+ if(data->set.str[STRING_CERT]) {
i=0;
/* Instead of trying to analyze cert type here, let axTLS try them all. */
- while(cert_types[i] != 0){
+ while(cert_types[i] != 0) {
ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
data->set.str[STRING_CERT], NULL);
- if(ssl_fcn_return == SSL_OK){
+ if(ssl_fcn_return == SSL_OK) {
infof(data, "successfully read cert file %s \n",
data->set.str[STRING_CERT]);
break;
@@ -222,7 +220,7 @@ Curl_axtls_connect(struct connectdata *conn,
i++;
}
/* Tried all cert types, none worked. */
- if(cert_types[i] == 0){
+ if(cert_types[i] == 0) {
failf(data, "%s is not x509 or pkcs12 format",
data->set.str[STRING_CERT]);
Curl_axtls_close(conn, sockindex);
@@ -233,13 +231,13 @@ Curl_axtls_connect(struct connectdata *conn,
/* Load client key.
If a pkcs12 file successfully loaded a cert, then there's nothing to do
because the key has already been loaded. */
- if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12){
+ if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) {
i=0;
/* Instead of trying to analyze key type here, let axTLS try them all. */
- while(key_types[i] != 0){
+ while(key_types[i] != 0) {
ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
data->set.str[STRING_KEY], NULL);
- if(ssl_fcn_return == SSL_OK){
+ if(ssl_fcn_return == SSL_OK) {
infof(data, "successfully read key file %s \n",
data->set.str[STRING_KEY]);
break;
@@ -247,7 +245,7 @@ Curl_axtls_connect(struct connectdata *conn,
i++;
}
/* Tried all key types, none worked. */
- if(key_types[i] == 0){
+ if(key_types[i] == 0) {
failf(data, "Failure: %s is not a supported key file",
data->set.str[STRING_KEY]);
Curl_axtls_close(conn, sockindex);
@@ -273,7 +271,7 @@ Curl_axtls_connect(struct connectdata *conn,
/* Check to make sure handshake was ok. */
ssl_fcn_return = ssl_handshake_status(ssl);
- if(ssl_fcn_return != SSL_OK){
+ if(ssl_fcn_return != SSL_OK) {
Curl_axtls_close(conn, sockindex);
ssl_display_error(ssl_fcn_return); /* goes to stdout. */
return map_error_to_curl(ssl_fcn_return);
@@ -285,8 +283,8 @@ Curl_axtls_connect(struct connectdata *conn,
*/
/* Verify server's certificate */
- if(data->set.ssl.verifypeer){
- if(ssl_verify_cert(ssl) != SSL_OK){
+ if(data->set.ssl.verifypeer) {
+ if(ssl_verify_cert(ssl) != SSL_OK) {
Curl_axtls_close(conn, sockindex);
failf(data, "server cert verify failed");
return CURLE_SSL_CONNECT_ERROR;
@@ -415,7 +413,7 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
nread = (ssize_t)SSL_read(conn->ssl[sockindex].ssl, buf,
sizeof(buf));
- if(nread < SSL_OK){
+ if(nread < SSL_OK) {
failf(data, "close notify alert not received during shutdown");
retval = -1;
}
@@ -447,13 +445,13 @@ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
infof(conn->data, " axtls_recv\n");
- if(connssl){
+ if(connssl) {
ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, (int)buffersize);
/* axTLS isn't terribly generous about error reporting */
/* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS
team approves proposed fix. */
- if(ret == -3 ){
+ if(ret == -3 ) {
Curl_axtls_close(conn, num);
}
else if(ret < 0) {
diff --git a/lib/base64.c b/lib/base64.c
index 0de1f0100..23ebb4aa9 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -24,9 +24,6 @@
#include "setup.h"
-#include <stdlib.h>
-#include <string.h>
-
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@@ -71,12 +68,19 @@ static void decodeQuantum(unsigned char *dest, const char *src)
/*
* Curl_base64_decode()
*
- * Given a base64 string at src, decode it and return an allocated memory in
- * the *outptr. Returns the length of the decoded data.
+ * Given a base64 NUL-terminated string at src, decode it and return a
+ * pointer in *outptr to a newly allocated memory area holding decoded
+ * data. Size of decoded data is returned in variable pointed by outlen.
+ *
+ * Returns CURLE_OK on success, otherwise specific error code. Function
+ * output shall not be considered valid unless CURLE_OK is returned.
+ *
+ * When decoded data length is 0, returns NULL in *outptr.
*
* @unittest: 1302
*/
-size_t Curl_base64_decode(const char *src, unsigned char **outptr)
+CURLcode Curl_base64_decode(const char *src,
+ unsigned char **outptr, size_t *outlen)
{
size_t length = 0;
size_t equalsTerm = 0;
@@ -87,6 +91,7 @@ size_t Curl_base64_decode(const char *src, unsigned char **outptr)
unsigned char *newstr;
*outptr = NULL;
+ *outlen = 0;
while((src[length] != '=') && src[length])
length++;
@@ -100,7 +105,7 @@ size_t Curl_base64_decode(const char *src, unsigned char **outptr)
/* Don't allocate a buffer if the decoded length is 0 */
if(numQuantums == 0)
- return 0;
+ return CURLE_OK;
rawlen = (numQuantums * 3) - equalsTerm;
@@ -108,7 +113,7 @@ size_t Curl_base64_decode(const char *src, unsigned char **outptr)
(which may be partially thrown out) and the zero terminator. */
newstr = malloc(rawlen+4);
if(!newstr)
- return 0;
+ return CURLE_OUT_OF_MEMORY;
*outptr = newstr;
@@ -127,23 +132,34 @@ size_t Curl_base64_decode(const char *src, unsigned char **outptr)
newstr[i] = lastQuantum[i];
newstr[i] = '\0'; /* zero terminate */
- return rawlen;
+
+ *outlen = rawlen; /* return size of decoded data */
+
+ return CURLE_OK;
}
/*
* Curl_base64_encode()
*
- * Returns the length of the newly created base64 string. The third argument
- * is a pointer to an allocated area holding the base64 data. If something
- * went wrong, 0 is returned.
+ * Given a pointer to an input buffer and an input size, encode it and
+ * return a pointer in *outptr to a newly allocated memory area holding
+ * encoded data. Size of encoded data is returned in variable pointed by
+ * outlen.
+ *
+ * Input length of 0 indicates input buffer holds a NUL-terminated string.
+ *
+ * Returns CURLE_OK on success, otherwise specific error code. Function
+ * output shall not be considered valid unless CURLE_OK is returned.
+ *
+ * When encoded data length is 0, returns NULL in *outptr.
*
* @unittest: 1302
*/
-size_t Curl_base64_encode(struct SessionHandle *data,
- const char *inputbuff, size_t insize,
- char **outptr)
+CURLcode Curl_base64_encode(struct SessionHandle *data,
+ const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen)
{
- CURLcode res;
+ CURLcode error;
unsigned char ibuf[3];
unsigned char obuf[4];
int i;
@@ -154,24 +170,25 @@ size_t Curl_base64_encode(struct SessionHandle *data,
const char *indata = inputbuff;
- *outptr = NULL; /* set to NULL in case of failure before we reach the end */
+ *outptr = NULL;
+ *outlen = 0;
if(0 == insize)
insize = strlen(indata);
base64data = output = malloc(insize*4/3+4);
if(NULL == output)
- return 0;
+ return CURLE_OUT_OF_MEMORY;
/*
* The base64 data needs to be created using the network encoding
* not the host encoding. And we can't change the actual input
* so we copy it to a buffer, translate it, and use that instead.
*/
- res = Curl_convert_clone(data, indata, insize, &convbuf);
- if(res) {
+ error = Curl_convert_clone(data, indata, insize, &convbuf);
+ if(error) {
free(output);
- return 0;
+ return error;
}
if(convbuf)
@@ -218,12 +235,14 @@ size_t Curl_base64_encode(struct SessionHandle *data,
}
output += 4;
}
- *output=0;
- *outptr = base64data; /* make it return the actual data memory */
+ *output = '\0';
+ *outptr = base64data; /* return pointer to new data, allocated memory */
if(convbuf)
free(convbuf);
- return strlen(base64data); /* return the length of the new data */
+ *outlen = strlen(base64data); /* return the length of the new data */
+
+ return CURLE_OK;
}
/* ---- End of Base64 Encoding ---- */
diff --git a/lib/checksrc.pl b/lib/checksrc.pl
index 5d369496a..9f5058ddb 100755
--- a/lib/checksrc.pl
+++ b/lib/checksrc.pl
@@ -62,7 +62,7 @@ while(1) {
next;
}
elsif($file =~ /-W(.*)/) {
- $wlist = $1;
+ $wlist .= " $1 ";
$file = shift @ARGV;
next;
}
@@ -79,7 +79,7 @@ if(!$file) {
}
do {
- if($file ne "$wlist") {
+ if("$wlist" !~ / $file /) {
my $fullname = $file;
$fullname = "$dir/$file" if ($fullname !~ '^\.?\.?/');
scanfile($fullname);
@@ -145,9 +145,14 @@ sub scanfile {
}
# check for "} else"
- if($l =~ /^(.*)\} else/) {
+ if($l =~ /^(.*)\} *else/) {
checkwarn($line, length($1), $file, $l, "else after closing brace on same line");
}
+ # check for "){"
+ if($l =~ /^(.*)\)\{/) {
+ checkwarn($line, length($1)+1, $file, $l, "missing space after close paren");
+ }
+
# check for open brace first on line but not first column
# only alert if previous line ended with a close paren and wasn't a cpp
# line
diff --git a/lib/config-amigaos.h b/lib/config-amigaos.h
index 99b96d656..1474ba915 100644
--- a/lib/config-amigaos.h
+++ b/lib/config-amigaos.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 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,6 +26,7 @@
#define HAVE_ARPA_INET_H 1
#define HAVE_CLOSESOCKET_CAMEL 1
+#define HAVE_ERRNO_H 1
#define HAVE_GETHOSTBYADDR 1
#define HAVE_INET_ADDR 1
#define HAVE_INTTYPES_H 1
diff --git a/lib/config-dos.h b/lib/config-dos.h
index 35d21aae2..694a30465 100644
--- a/lib/config-dos.h
+++ b/lib/config-dos.h
@@ -40,6 +40,7 @@
#define PACKAGE "curl"
#define HAVE_ARPA_INET_H 1
+#define HAVE_ERRNO_H 1
#define HAVE_FCNTL_H 1
#define HAVE_GETADDRINFO 1
#define HAVE_GETNAMEINFO 1
diff --git a/lib/config-mac.h b/lib/config-mac.h
index 80af84e52..72e8260d1 100644
--- a/lib/config-mac.h
+++ b/lib/config-mac.h
@@ -30,6 +30,7 @@
#define OS "mac"
+#define HAVE_ERRNO_H 1
#define HAVE_NETINET_IN_H 1
#define HAVE_SYS_SOCKET_H 1
#define HAVE_SYS_SELECT_H 1
diff --git a/lib/config-os400.h b/lib/config-os400.h
index 8dba1e4cd..4d2730928 100644
--- a/lib/config-os400.h
+++ b/lib/config-os400.h
@@ -97,6 +97,9 @@
/* Define if you have the <des.h> header file. */
#undef HAVE_DES_H
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H
+
/* Define if you have the <err.h> header file. */
#undef HAVE_ERR_H
diff --git a/lib/config-riscos.h b/lib/config-riscos.h
index 5ccf68124..127dbdb0a 100644
--- a/lib/config-riscos.h
+++ b/lib/config-riscos.h
@@ -92,6 +92,9 @@
/* Define if you have the <des.h> header file. */
#undef HAVE_DES_H
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H
+
/* Define if you have the <err.h> header file. */
#undef HAVE_ERR_H
diff --git a/lib/config-vms.h b/lib/config-vms.h
index e3844f83b..75c77d1b1 100644
--- a/lib/config-vms.h
+++ b/lib/config-vms.h
@@ -143,6 +143,9 @@
/* Define if you have the uname function. */
#define HAVE_UNAME 1
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
/* Define if you have the <err.h> header file. */
#define HAVE_ERR_H 1
diff --git a/lib/config-win32.h b/lib/config-win32.h
index 6768dda3c..cfbca9ca3 100644
--- a/lib/config-win32.h
+++ b/lib/config-win32.h
@@ -1,5 +1,5 @@
-#ifndef __LIB_CONFIG_WIN32_H
-#define __LIB_CONFIG_WIN32_H
+#ifndef HEADER_CURL_CONFIG_WIN32_H
+#define HEADER_CURL_CONFIG_WIN32_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -23,49 +23,57 @@
***************************************************************************/
/* ================================================================ */
-/* lib/config-win32.h - Hand crafted config file for Windows */
+/* Hand crafted config file for Windows */
/* ================================================================ */
/* ---------------------------------------------------------------- */
/* HEADER FILES */
/* ---------------------------------------------------------------- */
-/* Define if you have the <arpa/inet.h> header file. */
+/* Define if you have the <arpa/inet.h> header file. */
/* #define HAVE_ARPA_INET_H 1 */
-/* Define if you have the <assert.h> header file. */
+/* Define if you have the <assert.h> header file. */
#define HAVE_ASSERT_H 1
-/* Define if you have the <crypto.h> header file. */
+/* Define if you have the <crypto.h> header file. */
/* #define HAVE_CRYPTO_H 1 */
-/* Define if you have the <err.h> header file. */
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <err.h> header file. */
/* #define HAVE_ERR_H 1 */
-/* Define if you have the <fcntl.h> header file. */
+/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
-/* Define if you have the <getopt.h> header file. */
-/* #define HAVE_GETOPT_H 1 */
+/* Define if you have the <getopt.h> header file. */
+#if defined(__MINGW32__) || defined(__POCC__)
+#define HAVE_GETOPT_H 1
+#endif
-/* Define if you have the <io.h> header file. */
+/* Define if you have the <io.h> header file. */
#define HAVE_IO_H 1
-/* Define if you have the <limits.h> header file. */
+/* Define if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
-/* Define if you need the malloc.h header file even with stdlib.h */
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you need <malloc.h> header even with <stdlib.h> header file. */
#if !defined(__SALFORDC__) && !defined(__POCC__)
#define NEED_MALLOC_H 1
#endif
-/* Define if you have the <netdb.h> header file. */
+/* Define if you have the <netdb.h> header file. */
/* #define HAVE_NETDB_H 1 */
-/* Define if you have the <netinet/in.h> header file. */
+/* Define if you have the <netinet/in.h> header file. */
/* #define HAVE_NETINET_IN_H 1 */
-/* Define if you have the <process.h> header file. */
+/* Define if you have the <process.h> header file. */
#ifndef __SALFORDC__
#define HAVE_PROCESS_H 1
#endif
@@ -73,68 +81,68 @@
/* Define if you have the <signal.h> header file. */
#define HAVE_SIGNAL_H 1
-/* Define if you have the <sgtty.h> header file. */
+/* Define if you have the <sgtty.h> header file. */
/* #define HAVE_SGTTY_H 1 */
-/* Define if you have the <ssl.h> header file. */
+/* Define if you have the <ssl.h> header file. */
/* #define HAVE_SSL_H 1 */
-/* Define if you have the <stdlib.h> header file. */
+/* Define if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
-/* Define if you have the <sys/param.h> header file. */
+/* Define if you have the <sys/param.h> header file. */
/* #define HAVE_SYS_PARAM_H 1 */
-/* Define if you have the <sys/select.h> header file. */
+/* Define if you have the <sys/select.h> header file. */
/* #define HAVE_SYS_SELECT_H 1 */
-/* Define if you have the <sys/socket.h> header file. */
+/* Define if you have the <sys/socket.h> header file. */
/* #define HAVE_SYS_SOCKET_H 1 */
-/* Define if you have the <sys/sockio.h> header file. */
+/* Define if you have the <sys/sockio.h> header file. */
/* #define HAVE_SYS_SOCKIO_H 1 */
-/* Define if you have the <sys/stat.h> header file. */
+/* Define if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
-/* Define if you have the <sys/time.h> header file */
+/* Define if you have the <sys/time.h> header file. */
/* #define HAVE_SYS_TIME_H 1 */
-/* Define if you have the <sys/types.h> header file. */
+/* Define if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
-/* Define if you have the <sys/utime.h> header file. */
+/* Define if you have the <sys/utime.h> header file. */
#ifndef __BORLANDC__
#define HAVE_SYS_UTIME_H 1
#endif
-/* Define if you have the <termio.h> header file. */
+/* Define if you have the <termio.h> header file. */
/* #define HAVE_TERMIO_H 1 */
-/* Define if you have the <termios.h> header file. */
+/* Define if you have the <termios.h> header file. */
/* #define HAVE_TERMIOS_H 1 */
-/* Define if you have the <time.h> header file. */
+/* Define if you have the <time.h> header file. */
#define HAVE_TIME_H 1
-/* Define if you have the <unistd.h> header file. */
+/* Define if you have the <unistd.h> header file. */
#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__LCC__) || \
defined(__POCC__)
#define HAVE_UNISTD_H 1
#endif
-/* Define if you have the <windows.h> header file. */
+/* Define if you have the <windows.h> header file. */
#define HAVE_WINDOWS_H 1
-/* Define if you have the <winsock.h> header file. */
+/* Define if you have the <winsock.h> header file. */
#define HAVE_WINSOCK_H 1
-/* Define if you have the <winsock2.h> header file. */
+/* Define if you have the <winsock2.h> header file. */
#ifndef __SALFORDC__
#define HAVE_WINSOCK2_H 1
#endif
-/* Define if you have the <ws2tcpip.h> header file. */
+/* Define if you have the <ws2tcpip.h> header file. */
#ifndef __SALFORDC__
#define HAVE_WS2TCPIP_H 1
#endif
@@ -146,41 +154,44 @@
/* Define if sig_atomic_t is an available typedef. */
#define HAVE_SIG_ATOMIC_T 1
-/* Define if you have the ANSI C header files. */
+/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1
-/* Define if you can safely include both <sys/time.h> and <time.h>. */
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
/* #define TIME_WITH_SYS_TIME 1 */
/* ---------------------------------------------------------------- */
/* FUNCTIONS */
/* ---------------------------------------------------------------- */
-/* Define if you have the closesocket function. */
+/* Define if you have the closesocket function. */
#define HAVE_CLOSESOCKET 1
-/* Define if you don't have vprintf but do have _doprnt. */
+/* Define if you don't have vprintf but do have _doprnt. */
/* #define HAVE_DOPRNT 1 */
-/* Define if you have the gethostbyaddr function. */
+/* Define if you have the ftruncate function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define if you have the gethostbyaddr function. */
#define HAVE_GETHOSTBYADDR 1
-/* Define if you have the gethostname function. */
+/* Define if you have the gethostname function. */
#define HAVE_GETHOSTNAME 1
-/* Define if you have the getpass function. */
+/* Define if you have the getpass function. */
/* #define HAVE_GETPASS 1 */
-/* Define if you have the getservbyname function. */
+/* Define if you have the getservbyname function. */
#define HAVE_GETSERVBYNAME 1
-/* Define if you have the getprotobyname function. */
+/* Define if you have the getprotobyname function. */
#define HAVE_GETPROTOBYNAME
-/* Define if you have the gettimeofday function. */
+/* Define if you have the gettimeofday function. */
/* #define HAVE_GETTIMEOFDAY 1 */
-/* Define if you have the inet_addr function. */
+/* Define if you have the inet_addr function. */
#define HAVE_INET_ADDR 1
/* Define if you have the ioctlsocket function. */
@@ -189,35 +200,41 @@
/* Define if you have a working ioctlsocket FIONBIO function. */
#define HAVE_IOCTLSOCKET_FIONBIO 1
-/* Define if you have the perror function. */
+/* Define if you have the perror function. */
#define HAVE_PERROR 1
-/* Define if you have the RAND_screen function when using SSL */
+/* Define if you have the RAND_screen function when using SSL. */
#define HAVE_RAND_SCREEN 1
/* Define if you have the `RAND_status' function when using SSL. */
#define HAVE_RAND_STATUS 1
-/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function.
+/* Define if you have the `CRYPTO_cleanup_all_ex_data' function.
This is present in OpenSSL versions after 0.9.6b */
#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
-/* Define if you have the select function. */
+/* Define if you have the select function. */
#define HAVE_SELECT 1
-/* Define if you have the setvbuf function. */
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the setmode function. */
+#define HAVE_SETMODE 1
+
+/* Define if you have the setvbuf function. */
#define HAVE_SETVBUF 1
-/* Define if you have the socket function. */
+/* Define if you have the socket function. */
#define HAVE_SOCKET 1
-/* Define if you have the strcasecmp function. */
+/* Define if you have the strcasecmp function. */
/* #define HAVE_STRCASECMP 1 */
-/* Define if you have the strdup function. */
+/* Define if you have the strdup function. */
#define HAVE_STRDUP 1
-/* Define if you have the strftime function. */
+/* Define if you have the strftime function. */
#define HAVE_STRFTIME 1
/* Define if you have the stricmp function. */
@@ -229,21 +246,21 @@
/* Define if you have the strnicmp function. */
#define HAVE_STRNICMP 1
-/* Define if you have the strstr function. */
+/* Define if you have the strstr function. */
#define HAVE_STRSTR 1
-/* Define if you have the strtoll function. */
+/* Define if you have the strtoll function. */
#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__POCC__)
#define HAVE_STRTOLL 1
#endif
-/* Define if you have the tcgetattr function. */
+/* Define if you have the tcgetattr function. */
/* #define HAVE_TCGETATTR 1 */
-/* Define if you have the tcsetattr function. */
+/* Define if you have the tcsetattr function. */
/* #define HAVE_TCSETATTR 1 */
-/* Define if you have the utime function */
+/* Define if you have the utime function. */
#ifndef __BORLANDC__
#define HAVE_UTIME 1
#endif
@@ -330,13 +347,13 @@
/* TYPEDEF REPLACEMENTS */
/* ---------------------------------------------------------------- */
-/* Define this if in_addr_t is not an available 'typedefed' type */
+/* Define if in_addr_t is not an available 'typedefed' type. */
#define in_addr_t unsigned long
-/* Define as the return type of signal handlers (int or void). */
+/* Define to the return type of signal handlers (int or void). */
#define RETSIGTYPE void
-/* Define ssize_t if it is not an available 'typedefed' type */
+/* Define if ssize_t is not an available 'typedefed' type. */
#ifndef _SSIZE_T_DEFINED
# if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || \
defined(__POCC__) || \
@@ -354,19 +371,19 @@
/* TYPE SIZES */
/* ---------------------------------------------------------------- */
-/* The size of `int', as computed by sizeof. */
+/* Define to the size of `int', as computed by sizeof. */
#define SIZEOF_INT 4
-/* The size of `long double', as computed by sizeof. */
+/* Define to the size of `long double', as computed by sizeof. */
#define SIZEOF_LONG_DOUBLE 16
-/* The size of `long long', as computed by sizeof. */
+/* Define to the size of `long long', as computed by sizeof. */
/* #define SIZEOF_LONG_LONG 8 */
-/* The size of `short', as computed by sizeof. */
+/* Define to the size of `short', as computed by sizeof. */
#define SIZEOF_SHORT 2
-/* The size of `size_t', as computed by sizeof. */
+/* Define to the size of `size_t', as computed by sizeof. */
#if defined(_WIN64)
# define SIZEOF_SIZE_T 8
#else
@@ -377,14 +394,49 @@
/* STRUCT RELATED */
/* ---------------------------------------------------------------- */
-/* Define this if you have struct sockaddr_storage */
+/* Define if you have struct sockaddr_storage. */
#if !defined(__SALFORDC__) && !defined(__BORLANDC__)
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
#endif
-/* Define this if you have struct timeval */
+/* Define if you have struct timeval. */
#define HAVE_STRUCT_TIMEVAL 1
+/* Define if struct sockaddr_in6 has the sin6_scope_id member. */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* ---------------------------------------------------------------- */
+/* BSD-style lwIP TCP/IP stack SPECIFIC */
+/* ---------------------------------------------------------------- */
+
+/* Define to use BSD-style lwIP TCP/IP stack. */
+/* #define USE_LWIPSOCK 1 */
+
+#ifdef USE_LWIPSOCK
+# undef USE_WINSOCK
+# undef HAVE_WINSOCK_H
+# undef HAVE_WINSOCK2_H
+# undef HAVE_WS2TCPIP_H
+# undef HAVE_ERRNO_H
+# undef HAVE_GETHOSTNAME
+# undef HAVE_GETNAMEINFO
+# undef LWIP_POSIX_SOCKETS_IO_NAMES
+# undef RECV_TYPE_ARG1
+# undef RECV_TYPE_ARG3
+# undef SEND_TYPE_ARG1
+# undef SEND_TYPE_ARG3
+# define HAVE_FREEADDRINFO
+# define HAVE_GETADDRINFO
+# define HAVE_GETHOSTBYNAME
+# define HAVE_GETHOSTBYNAME_R
+# define HAVE_GETHOSTBYNAME_R_6
+# define LWIP_POSIX_SOCKETS_IO_NAMES 0
+# define RECV_TYPE_ARG1 int
+# define RECV_TYPE_ARG3 size_t
+# define SEND_TYPE_ARG1 int
+# define SEND_TYPE_ARG3 size_t
+#endif
+
/* ---------------------------------------------------------------- */
/* Watt-32 tcp/ip SPECIFIC */
/* ---------------------------------------------------------------- */
@@ -413,8 +465,11 @@
/* COMPILER SPECIFIC */
/* ---------------------------------------------------------------- */
-/* Undef keyword 'const' if it does not work. */
-/* #undef const */
+/* Define to nothing if compiler does not support 'const' qualifier. */
+/* #define const */
+
+/* Define to nothing if compiler does not support 'volatile' qualifier. */
+/* #define volatile */
/* Windows should not have HAVE_GMTIME_R defined */
/* #undef HAVE_GMTIME_R */
@@ -429,14 +484,14 @@
#define HAVE_LONGLONG 1
#endif
-/* Define to avoid VS2005 complaining about portable C functions */
+/* Define to avoid VS2005 complaining about portable C functions. */
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#define _CRT_SECURE_NO_DEPRECATE 1
#define _CRT_NONSTDC_NO_DEPRECATE 1
#endif
-/* VS2005 and later dafault size for time_t is 64-bit, unless */
-/* _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */
+/* VS2005 and later dafault size for time_t is 64-bit, unless
+ _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
# ifndef _USE_32BIT_TIME_T
# define SIZEOF_TIME_T 8
@@ -446,12 +501,13 @@
#endif
/* Officially, Microsoft's Windows SDK versions 6.X do not support Windows
- 2000 as a supported build target. VS2008 default installations provide an
- embedded Windows SDK v6.0A along with the claim that Windows 2000 is a
- valid build target for VS2008. Popular belief is that binaries built using
- Windows SDK versions 6.X and Windows 2000 as a build target are functional */
+ 2000 as a supported build target. VS2008 default installations provide
+ an embedded Windows SDK v6.0A along with the claim that Windows 2000 is
+ a valid build target for VS2008. Popular belief is that binaries built
+ with VS2008 using Windows SDK versions 6.X and Windows 2000 as a build
+ target are functional. */
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
-# define VS2008_MINIMUM_TARGET 0x0500
+# define VS2008_MIN_TARGET 0x0500
#endif
/* When no build target is specified VS2008 default build target is Windows
@@ -459,18 +515,18 @@
for VS2008 we will target the minimum Officially supported build target,
which happens to be Windows XP. */
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
-# define VS2008_DEFAULT_TARGET 0x0501
+# define VS2008_DEF_TARGET 0x0501
#endif
-/* VS2008 default target settings and minimum build target check */
+/* VS2008 default target settings and minimum build target check. */
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
# ifndef _WIN32_WINNT
-# define _WIN32_WINNT VS2008_DEFAULT_TARGET
+# define _WIN32_WINNT VS2008_DEF_TARGET
# endif
# ifndef WINVER
-# define WINVER VS2008_DEFAULT_TARGET
+# define WINVER VS2008_DEF_TARGET
# endif
-# if (_WIN32_WINNT < VS2008_MINIMUM_TARGET) || (WINVER < VS2008_MINIMUM_TARGET)
+# if (_WIN32_WINNT < VS2008_MIN_TARGET) || (WINVER < VS2008_MIN_TARGET)
# error VS2008 does not support Windows build targets prior to Windows 2000
# endif
#endif
@@ -549,13 +605,13 @@
/* ---------------------------------------------------------------- */
/*
- * Undefine both USE_ARES and USE_THREADS_WIN32 for synchronous DNS
+ * Undefine both USE_ARES and USE_THREADS_WIN32 for synchronous DNS.
*/
-/* Define USE_ARES to enable c-ares asynchronous DNS lookups */
+/* Define to enable c-ares asynchronous DNS lookups. */
/* #define USE_ARES 1 */
-/* Define USE_THREADS_WIN32 to enable threaded asynchronous DNS lookups */
+/* Define to enable threaded asynchronous DNS lookups. */
#define USE_THREADS_WIN32 1
#if defined(USE_ARES) && defined(USE_THREADS_WIN32)
@@ -597,10 +653,10 @@
#undef OS
#if defined(_M_IX86) || defined(__i386__) /* x86 (MSVC or gcc) */
#define OS "i386-pc-win32"
+#elif defined(_M_X64) || defined(__x86_64__) /* x86_64 (MSVC >=2005 or gcc) */
+#define OS "x86_64-pc-win32"
#elif defined(_M_IA64) /* Itanium */
#define OS "ia64-pc-win32"
-#elif defined(_M_X64) /* AMD64/EM64T - Not defined until MSVC 2005 */
-#define OS "amd64-pc-win32"
#else
#define OS "unknown-pc-win32"
#endif
@@ -608,8 +664,11 @@
/* Name of package */
#define PACKAGE "curl"
+/* If you want to build curl with the built-in manual */
+#define USE_MANUAL 1
+
#if defined(__POCC__) || (USE_IPV6)
# define ENABLE_IPV6 1
#endif
-#endif /* __LIB_CONFIG_WIN32_H */
+#endif /* HEADER_CURL_CONFIG_WIN32_H */
diff --git a/lib/config-win32ce.h b/lib/config-win32ce.h
index 872334286..1ade83fbe 100644
--- a/lib/config-win32ce.h
+++ b/lib/config-win32ce.h
@@ -39,6 +39,9 @@
/* Define if you have the <crypto.h> header file. */
/* #define HAVE_CRYPTO_H 1 */
+/* Define if you have the <errno.h> header file. */
+/* #define HAVE_ERRNO_H 1 */
+
/* Define if you have the <err.h> header file. */
/* #define HAVE_ERR_H 1 */
diff --git a/lib/connect.c b/lib/connect.c
index a9185978c..2a1876e71 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -22,9 +22,6 @@
#include "setup.h"
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -52,9 +49,6 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
#include <sys/filio.h>
@@ -68,10 +62,6 @@
#include <inet.h>
#endif
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@@ -669,7 +659,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
*connected = FALSE; /* a very negative world view is best */
- if(conn->bits.tcpconnect) {
+ if(conn->bits.tcpconnect[sockindex]) {
/* we are connected already! */
*connected = TRUE;
return CURLE_OK;
@@ -708,9 +698,10 @@ CURLcode Curl_is_connected(struct connectdata *conn,
if(code)
return code;
- conn->bits.tcpconnect = TRUE;
+ conn->bits.tcpconnect[sockindex] = TRUE;
*connected = TRUE;
- Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
+ if(sockindex == FIRSTSOCKET)
+ Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
Curl_verboseconnect(conn);
Curl_updateconninfo(conn, sockfd);
@@ -756,7 +747,7 @@ static void tcpnodelay(struct connectdata *conn,
#ifdef TCP_NODELAY
struct SessionHandle *data= conn->data;
curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay;
- int proto = IPPROTO_TCP;
+ int level = IPPROTO_TCP;
#if 0
/* The use of getprotobyname() is disabled since it isn't thread-safe on
@@ -768,10 +759,10 @@ static void tcpnodelay(struct connectdata *conn,
detected. */
struct protoent *pe = getprotobyname("tcp");
if(pe)
- proto = pe->p_proto;
+ level = pe->p_proto;
#endif
- if(setsockopt(sockfd, proto, TCP_NODELAY, (void *)&onoff,
+ if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
sizeof(onoff)) < 0)
infof(data, "Could not set TCP_NODELAY: %s\n",
Curl_strerror(conn, SOCKERRNO));
@@ -799,10 +790,10 @@ static void nosigpipe(struct connectdata *conn,
Curl_strerror(conn, SOCKERRNO));
}
#else
-#define nosigpipe(x,y)
+#define nosigpipe(x,y) Curl_nop_stmt
#endif
-#ifdef WIN32
+#ifdef USE_WINSOCK
/* When you run a program that uses the Windows Sockets API, you may
experience slow performance when you copy data to a TCP server.
@@ -845,7 +836,7 @@ singleipconnect(struct connectdata *conn,
{
struct Curl_sockaddr_ex addr;
int rc;
- int error;
+ int error = 0;
bool isconnected = FALSE;
struct SessionHandle *data = conn->data;
curl_socket_t sockfd;
@@ -916,11 +907,6 @@ singleipconnect(struct connectdata *conn,
Curl_persistconninfo(conn);
-#ifdef ENABLE_IPV6
- if(addr.family == AF_INET6)
- conn->bits.ipv6 = TRUE;
-#endif
-
if(data->set.tcp_nodelay)
tcpnodelay(conn, sockfd);
@@ -955,6 +941,8 @@ singleipconnect(struct connectdata *conn,
/* Connect TCP sockets, bind UDP */
if(!isconnected && (conn->socktype == SOCK_STREAM)) {
rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
+ if(-1 == rc)
+ error = SOCKERRNO;
conn->connecttime = Curl_tvnow();
if(conn->num_addr > 1)
Curl_expire(data, conn->timeoutms_per_addr);
@@ -963,8 +951,6 @@ singleipconnect(struct connectdata *conn,
rc = 0;
if(-1 == rc) {
- error = SOCKERRNO;
-
switch (error) {
case EINPROGRESS:
case EWOULDBLOCK:
@@ -1008,6 +994,10 @@ singleipconnect(struct connectdata *conn,
/* we are connected, awesome! */
*connected = TRUE; /* this is a true connect */
infof(data, "connected\n");
+#ifdef ENABLE_IPV6
+ conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
+#endif
+
Curl_updateconninfo(conn, sockfd);
*sockp = sockfd;
return CURLE_OK;
diff --git a/lib/connect.h b/lib/connect.h
index 3df9d970e..052549368 100644
--- a/lib/connect.h
+++ b/lib/connect.h
@@ -1,5 +1,5 @@
-#ifndef __CONNECT_H
-#define __CONNECT_H
+#ifndef HEADER_CURL_CONNECT_H
+#define HEADER_CURL_CONNECT_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -21,6 +21,7 @@
* KIND, either express or implied.
*
***************************************************************************/
+#include "setup.h"
#include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */
@@ -52,7 +53,7 @@ long Curl_timeleft(struct SessionHandle *data,
curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
struct connectdata **connp);
-#ifdef WIN32
+#ifdef USE_WINSOCK
/* When you run a program that uses the Windows Sockets API, you may
experience slow performance when you copy data to a TCP server.
@@ -64,10 +65,11 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
*/
void Curl_sndbufset(curl_socket_t sockfd);
#else
-#define Curl_sndbufset(y)
+#define Curl_sndbufset(y) Curl_nop_stmt
#endif
void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd);
void Curl_persistconninfo(struct connectdata *conn);
int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);
-#endif
+
+#endif /* HEADER_CURL_CONNECT_H */
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index 876115a32..3276ef988 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -24,9 +24,6 @@
#ifdef HAVE_LIBZ
-#include <stdlib.h>
-#include <string.h>
-
#include "urldata.h"
#include <curl/curl.h>
#include "sendf.h"
@@ -52,6 +49,21 @@
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define RESERVED 0xE0 /* bits 5..7: reserved */
+static voidpf
+zalloc_cb(voidpf opaque, unsigned int items, unsigned int size)
+{
+ (void) opaque;
+ /* not a typo, keep it calloc() */
+ return (voidpf) calloc(items, size);
+}
+
+static void
+zfree_cb(voidpf opaque, voidpf ptr)
+{
+ (void) opaque;
+ free(ptr);
+}
+
static CURLcode
process_zlib_error(struct connectdata *conn, z_stream *z)
{
@@ -161,11 +173,10 @@ Curl_unencode_deflate_write(struct connectdata *conn,
/* Initialize zlib? */
if(k->zlib_init == ZLIB_UNINIT) {
- z->zalloc = (alloc_func)Z_NULL;
- z->zfree = (free_func)Z_NULL;
- z->opaque = 0;
- z->next_in = NULL;
- z->avail_in = 0;
+ memset(z, 0, sizeof(z_stream));
+ z->zalloc = (alloc_func)zalloc_cb;
+ z->zfree = (free_func)zfree_cb;
+
if(inflateInit(z) != Z_OK)
return process_zlib_error(conn, z);
k->zlib_init = ZLIB_INIT;
@@ -272,11 +283,9 @@ Curl_unencode_gzip_write(struct connectdata *conn,
/* Initialize zlib? */
if(k->zlib_init == ZLIB_UNINIT) {
- z->zalloc = (alloc_func)Z_NULL;
- z->zfree = (free_func)Z_NULL;
- z->opaque = 0;
- z->next_in = NULL;
- z->avail_in = 0;
+ memset(z, 0, sizeof(z_stream));
+ z->zalloc = (alloc_func)zalloc_cb;
+ z->zfree = (free_func)zfree_cb;
if(strcmp(zlibVersion(), "1.2.0.4") >= 0) {
/* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
diff --git a/lib/content_encoding.h b/lib/content_encoding.h
index 3aff9d3c0..372da4a3b 100644
--- a/lib/content_encoding.h
+++ b/lib/content_encoding.h
@@ -1,5 +1,5 @@
-#ifndef __CURL_CONTENT_ENCODING_H
-#define __CURL_CONTENT_ENCODING_H
+#ifndef HEADER_CURL_CONTENT_ENCODING_H
+#define HEADER_CURL_CONTENT_ENCODING_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 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,7 +32,7 @@
void Curl_unencode_cleanup(struct connectdata *conn);
#else
#define ALL_CONTENT_ENCODINGS "identity"
-#define Curl_unencode_cleanup(x)
+#define Curl_unencode_cleanup(x) Curl_nop_stmt
#endif
CURLcode Curl_unencode_deflate_write(struct connectdata *conn,
@@ -45,4 +45,4 @@ Curl_unencode_gzip_write(struct connectdata *conn,
ssize_t nread);
-#endif
+#endif /* HEADER_CURL_CONTENT_ENCODING_H */
diff --git a/lib/cookie.c b/lib/cookie.c
index 7657da06e..41ccdbe34 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -81,9 +81,6 @@ Example set of cookies:
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
-#include <stdlib.h>
-#include <string.h>
-
#define _MPRINTF_REPLACE
#include <curl/mprintf.h>
@@ -129,7 +126,7 @@ static bool tailmatch(const char *little, const char *bigone)
if(littlelen > biglen)
return FALSE;
- return (bool)Curl_raw_equal(little, bigone+biglen-littlelen);
+ return Curl_raw_equal(little, bigone+biglen-littlelen) ? TRUE : FALSE;
}
/*
@@ -147,9 +144,9 @@ void Curl_cookie_loadfiles(struct SessionHandle *data)
data->set.cookiesession);
list = list->next;
}
- Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
curl_slist_free_all(data->change.cookielist); /* clean up list */
data->change.cookielist = NULL; /* don't do this again! */
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
}
@@ -209,7 +206,6 @@ Curl_cookie_add(struct SessionHandle *data,
if(httpheader) {
/* This line was read off a HTTP-header */
const char *ptr;
- const char *sep;
const char *semiptr;
char *what;
@@ -226,185 +222,186 @@ Curl_cookie_add(struct SessionHandle *data,
ptr = lineptr;
do {
- /* we have a <what>=<this> pair or a 'secure' word here */
- sep = strchr(ptr, '=');
- if(sep && (!semiptr || (semiptr>sep)) ) {
- /*
- * There is a = sign and if there was a semicolon too, which make sure
- * that the semicolon comes _after_ the equal sign.
- */
-
- name[0]=what[0]=0; /* init the buffers */
- if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;=]=%"
- MAX_COOKIE_LINE_TXT "[^;\r\n]",
- name, what)) {
- /* this is a <name>=<what> pair. We use strstore() below to properly
- deal with received cookie headers that have the same string
- property set more than once, and then we use the last one. */
-
- const char *whatptr;
-
- /* Strip off trailing whitespace from the 'what' */
- size_t len=strlen(what);
- while(len && ISBLANK(what[len-1])) {
- what[len-1]=0;
- len--;
- }
+ /* we have a <what>=<this> pair or a stand-alone word here */
+ name[0]=what[0]=0; /* init the buffers */
+ if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n =]=%"
+ MAX_COOKIE_LINE_TXT "[^;\r\n]",
+ name, what)) {
+ /* Use strstore() below to properly deal with received cookie
+ headers that have the same string property set more than once,
+ and then we use the last one. */
+ const char *whatptr;
+ bool done = FALSE;
+ bool sep;
+ size_t len=strlen(what);
+ const char *endofn = &ptr[ strlen(name) ];
+
+ /* skip trailing spaces in name */
+ while(*endofn && ISBLANK(*endofn))
+ endofn++;
+
+ /* name ends with a '=' ? */
+ sep = (*endofn == '=')?TRUE:FALSE;
+
+ /* Strip off trailing whitespace from the 'what' */
+ while(len && ISBLANK(what[len-1])) {
+ what[len-1]=0;
+ len--;
+ }
- /* Skip leading whitespace from the 'what' */
- whatptr=what;
- while(*whatptr && ISBLANK(*whatptr)) {
- whatptr++;
- }
+ /* Skip leading whitespace from the 'what' */
+ whatptr=what;
+ while(*whatptr && ISBLANK(*whatptr))
+ whatptr++;
- if(Curl_raw_equal("path", name)) {
- strstore(&co->path, whatptr);
- if(!co->path) {
- badcookie = TRUE; /* out of memory bad */
- break;
+ if(!len) {
+ /* this was a "<name>=" with no content, and we must allow
+ 'secure' and 'httponly' specified this weirdly */
+ done = TRUE;
+ if(Curl_raw_equal("secure", name))
+ co->secure = TRUE;
+ else if(Curl_raw_equal("httponly", name))
+ co->httponly = TRUE;
+ else if(sep)
+ /* there was a '=' so we're not done parsing this field */
+ done = FALSE;
+ }
+ if(done)
+ ;
+ else if(Curl_raw_equal("path", name)) {
+ strstore(&co->path, whatptr);
+ if(!co->path) {
+ badcookie = TRUE; /* out of memory bad */
+ break;
+ }
+ }
+ else if(Curl_raw_equal("domain", name)) {
+ /* note that this name may or may not have a preceding dot, but
+ we don't care about that, we treat the names the same anyway */
+
+ const char *domptr=whatptr;
+ const char *nextptr;
+ int dotcount=1;
+
+ /* Count the dots, we need to make sure that there are enough
+ of them. */
+
+ if('.' == whatptr[0])
+ /* don't count the initial dot, assume it */
+ domptr++;
+
+ do {
+ nextptr = strchr(domptr, '.');
+ if(nextptr) {
+ if(domptr != nextptr)
+ dotcount++;
+ domptr = nextptr+1;
}
+ } while(nextptr);
+
+ /* The original Netscape cookie spec defined that this domain name
+ MUST have three dots (or two if one of the seven holy TLDs),
+ but it seems that these kinds of cookies are in use "out there"
+ so we cannot be that strict. I've therefore lowered the check
+ to not allow less than two dots. */
+
+ if(dotcount < 2) {
+ /* Received and skipped a cookie with a domain using too few
+ dots. */
+ badcookie=TRUE; /* mark this as a bad cookie */
+ infof(data, "skipped cookie with illegal dotcount domain: %s\n",
+ whatptr);
}
- else if(Curl_raw_equal("domain", name)) {
- /* note that this name may or may not have a preceding dot, but
- we don't care about that, we treat the names the same anyway */
-
- const char *domptr=whatptr;
- const char *nextptr;
- int dotcount=1;
-
- /* Count the dots, we need to make sure that there are enough
- of them. */
+ else {
+ /* Now, we make sure that our host is within the given domain,
+ or the given domain is not valid and thus cannot be set. */
if('.' == whatptr[0])
- /* don't count the initial dot, assume it */
- domptr++;
-
- do {
- nextptr = strchr(domptr, '.');
- if(nextptr) {
- if(domptr != nextptr)
- dotcount++;
- domptr = nextptr+1;
+ whatptr++; /* ignore preceding dot */
+
+ if(!domain || tailmatch(whatptr, domain)) {
+ const char *tailptr=whatptr;
+ if(tailptr[0] == '.')
+ tailptr++;
+ strstore(&co->domain, tailptr); /* don't prefix w/dots
+ internally */
+ if(!co->domain) {
+ badcookie = TRUE;
+ break;
}
- } while(nextptr);
-
- /* The original Netscape cookie spec defined that this domain name
- MUST have three dots (or two if one of the seven holy TLDs),
- but it seems that these kinds of cookies are in use "out there"
- so we cannot be that strict. I've therefore lowered the check
- to not allow less than two dots. */
-
- if(dotcount < 2) {
- /* Received and skipped a cookie with a domain using too few
- dots. */
- badcookie=TRUE; /* mark this as a bad cookie */
- infof(data, "skipped cookie with illegal dotcount domain: %s\n",
- whatptr);
+ co->tailmatch=TRUE; /* we always do that if the domain name was
+ given */
}
else {
- /* Now, we make sure that our host is within the given domain,
- or the given domain is not valid and thus cannot be set. */
-
- if('.' == whatptr[0])
- whatptr++; /* ignore preceding dot */
-
- if(!domain || tailmatch(whatptr, domain)) {
- const char *tailptr=whatptr;
- if(tailptr[0] == '.')
- tailptr++;
- strstore(&co->domain, tailptr); /* don't prefix w/dots
- internally */
- if(!co->domain) {
- badcookie = TRUE;
- break;
- }
- co->tailmatch=TRUE; /* we always do that if the domain name was
- given */
- }
- else {
- /* we did not get a tailmatch and then the attempted set domain
- is not a domain to which the current host belongs. Mark as
- bad. */
- badcookie=TRUE;
- infof(data, "skipped cookie with bad tailmatch domain: %s\n",
- whatptr);
- }
- }
- }
- else if(Curl_raw_equal("version", name)) {
- strstore(&co->version, whatptr);
- if(!co->version) {
- badcookie = TRUE;
- break;
+ /* we did not get a tailmatch and then the attempted set domain
+ is not a domain to which the current host belongs. Mark as
+ bad. */
+ badcookie=TRUE;
+ infof(data, "skipped cookie with bad tailmatch domain: %s\n",
+ whatptr);
}
}
- else if(Curl_raw_equal("max-age", name)) {
- /* Defined in RFC2109:
-
- Optional. The Max-Age attribute defines the lifetime of the
- cookie, in seconds. The delta-seconds value is a decimal non-
- negative integer. After delta-seconds seconds elapse, the
- client should discard the cookie. A value of zero means the
- cookie should be discarded immediately.
-
- */
- strstore(&co->maxage, whatptr);
- if(!co->maxage) {
- badcookie = TRUE;
- break;
- }
- co->expires =
- strtol((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0],NULL,10)
- + (long)now;
+ }
+ else if(Curl_raw_equal("version", name)) {
+ strstore(&co->version, whatptr);
+ if(!co->version) {
+ badcookie = TRUE;
+ break;
}
- else if(Curl_raw_equal("expires", name)) {
- strstore(&co->expirestr, whatptr);
- if(!co->expirestr) {
- badcookie = TRUE;
- break;
- }
- /* Note that if the date couldn't get parsed for whatever reason,
- the cookie will be treated as a session cookie */
- co->expires = curl_getdate(what, &now);
-
- /* Session cookies have expires set to 0 so if we get that back
- from the date parser let's add a second to make it a
- non-session cookie */
- if(co->expires == 0)
- co->expires = 1;
- else if(co->expires < 0)
- co->expires = 0;
+ }
+ else if(Curl_raw_equal("max-age", name)) {
+ /* Defined in RFC2109:
+
+ Optional. The Max-Age attribute defines the lifetime of the
+ cookie, in seconds. The delta-seconds value is a decimal non-
+ negative integer. After delta-seconds seconds elapse, the
+ client should discard the cookie. A value of zero means the
+ cookie should be discarded immediately.
+
+ */
+ strstore(&co->maxage, whatptr);
+ if(!co->maxage) {
+ badcookie = TRUE;
+ break;
}
- else if(!co->name) {
- co->name = strdup(name);
- co->value = strdup(whatptr);
- if(!co->name || !co->value) {
- badcookie = TRUE;
- break;
- }
+ co->expires =
+ strtol((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0],NULL,10)
+ + (long)now;
+ }
+ else if(Curl_raw_equal("expires", name)) {
+ strstore(&co->expirestr, whatptr);
+ if(!co->expirestr) {
+ badcookie = TRUE;
+ break;
}
- /*
- else this is the second (or more) name we don't know
- about! */
+ /* Note that if the date couldn't get parsed for whatever reason,
+ the cookie will be treated as a session cookie */
+ co->expires = curl_getdate(what, &now);
+
+ /* Session cookies have expires set to 0 so if we get that back
+ from the date parser let's add a second to make it a
+ non-session cookie */
+ if(co->expires == 0)
+ co->expires = 1;
+ else if(co->expires < 0)
+ co->expires = 0;
}
- else {
- /* this is an "illegal" <what>=<this> pair */
+ else if(!co->name) {
+ co->name = strdup(name);
+ co->value = strdup(whatptr);
+ if(!co->name || !co->value) {
+ badcookie = TRUE;
+ break;
+ }
}
+ /*
+ else this is the second (or more) name we don't know
+ about! */
}
else {
- if(sscanf(ptr, "%" MAX_COOKIE_LINE_TXT "[^;\r\n]",
- what)) {
- if(Curl_raw_equal("secure", what)) {
- co->secure = TRUE;
- }
- else if(Curl_raw_equal("httponly", what)) {
- co->httponly = TRUE;
- }
- /* else,
- unsupported keyword without assign! */
-
- }
+ /* this is an "illegal" <what>=<this> pair */
}
+
if(!semiptr || !*semiptr) {
/* we already know there are no more cookies */
semiptr = NULL;
@@ -530,7 +527,7 @@ Curl_cookie_add(struct SessionHandle *data,
As far as I can see, it is set to true when the cookie says
.domain.com and to false when the domain is complete www.domain.com
*/
- co->tailmatch=(bool)Curl_raw_equal(ptr, "TRUE");
+ co->tailmatch = Curl_raw_equal(ptr, "TRUE")?TRUE:FALSE;
break;
case 2:
/* It turns out, that sometimes the file format allows the path
@@ -550,7 +547,7 @@ Curl_cookie_add(struct SessionHandle *data,
fields++; /* add a field and fall down to secure */
/* FALLTHROUGH */
case 3:
- co->secure = (bool)Curl_raw_equal(ptr, "TRUE");
+ co->secure = Curl_raw_equal(ptr, "TRUE")?TRUE:FALSE;
break;
case 4:
co->expires = curlx_strtoofft(ptr, NULL, 10);
@@ -1110,23 +1107,20 @@ struct curl_slist *Curl_cookie_list(struct SessionHandle *data)
c = data->cookies->cookies;
- beg = list;
while(c) {
/* fill the list with _all_ the cookies we know */
line = get_netscape_format(c);
- if(line == NULL) {
- curl_slist_free_all(beg);
+ if(!line) {
+ curl_slist_free_all(list);
return NULL;
}
- list = curl_slist_append(list, line);
+ beg = curl_slist_append(list, line);
free(line);
- if(list == NULL) {
- curl_slist_free_all(beg);
+ if(!beg) {
+ curl_slist_free_all(list);
return NULL;
}
- else if(beg == NULL) {
- beg = list;
- }
+ list = beg;
c = c->next;
}
@@ -1151,10 +1145,12 @@ void Curl_flush_cookies(struct SessionHandle *data, int cleanup)
data->set.str[STRING_COOKIEJAR]);
}
else {
- if(cleanup && data->change.cookielist)
+ if(cleanup && data->change.cookielist) {
/* since nothing is written, we can just free the list of cookie file
names */
curl_slist_free_all(data->change.cookielist); /* clean up list */
+ data->change.cookielist = NULL;
+ }
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
}
diff --git a/lib/cookie.h b/lib/cookie.h
index a950e359b..5997e4680 100644
--- a/lib/cookie.h
+++ b/lib/cookie.h
@@ -21,15 +21,7 @@
* KIND, either express or implied.
*
***************************************************************************/
-
-#include <stdio.h>
-#if defined(WIN32)
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#endif
+#include "setup.h"
#include <curl/curl.h>
@@ -95,10 +87,10 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies);
#if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES)
#define Curl_cookie_list(x) NULL
-#define Curl_cookie_loadfiles(x) do { } while (0)
+#define Curl_cookie_loadfiles(x) Curl_nop_stmt
#define Curl_cookie_init(x,y,z,w) NULL
-#define Curl_cookie_cleanup(x) do { } while (0)
-#define Curl_flush_cookies(x,y)
+#define Curl_cookie_cleanup(x) Curl_nop_stmt
+#define Curl_flush_cookies(x,y) Curl_nop_stmt
#else
void Curl_flush_cookies(struct SessionHandle *data, int cleanup);
void Curl_cookie_cleanup(struct CookieInfo *);
diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c
index 074bf17dc..bae403f95 100644
--- a/lib/curl_addrinfo.c
+++ b/lib/curl_addrinfo.c
@@ -40,7 +40,6 @@
#ifdef __VMS
# include <in.h>
# include <inet.h>
-# include <stdlib.h>
#endif
#if defined(NETWARE) && defined(__NOVELL_LIBC__)
diff --git a/lib/curl_base64.h b/lib/curl_base64.h
index 2498a0a22..6e200d2ec 100644
--- a/lib/curl_base64.h
+++ b/lib/curl_base64.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 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,10 +22,11 @@
*
***************************************************************************/
-size_t Curl_base64_encode(struct SessionHandle *data,
- const char *inputbuff, size_t insize,
- char **outptr);
+CURLcode Curl_base64_encode(struct SessionHandle *data,
+ const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen);
-size_t Curl_base64_decode(const char *src, unsigned char **outptr);
+CURLcode Curl_base64_decode(const char *src,
+ unsigned char **outptr, size_t *outlen);
#endif /* HEADER_CURL_BASE64_H */
diff --git a/lib/curl_gethostname.c b/lib/curl_gethostname.c
index 7f0bfed54..aafa45b59 100644
--- a/lib/curl_gethostname.c
+++ b/lib/curl_gethostname.c
@@ -32,12 +32,16 @@
* Curl_gethostname() is a wrapper around gethostname() which allows
* overriding the host name that the function would normally return.
* This capability is used by the test suite to verify exact matching
- * of NTLM authentication, which exercises libcurl's MD4 and DES code.
+ * of NTLM authentication, which exercises libcurl's MD4 and DES code
+ * as well as by the SMTP module when a hostname is not provided.
*
* For libcurl debug enabled builds host name overriding takes place
* when environment variable CURL_GETHOSTNAME is set, using the value
* held by the variable to override returned host name.
*
+ * Note: The function always returns the un-qualified hostname rather
+ * than being provider dependent.
+ *
* For libcurl shared library release builds the test suite preloads
* another shared library named libhostname using the LD_PRELOAD
* mechanism which intercepts, and might override, the gethostname()
@@ -58,6 +62,8 @@ int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) {
return -1;
#else
+ int err;
+ char* dot;
#ifdef DEBUGBUILD
@@ -65,17 +71,34 @@ int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) {
const char *force_hostname = getenv("CURL_GETHOSTNAME");
if(force_hostname) {
strncpy(name, force_hostname, namelen);
- name[namelen-1] = '\0';
- return 0;
+ err = 0;
+ }
+ else {
+ name[0] = '\0';
+ err = gethostname(name, namelen);
}
-#endif /* DEBUGBUILD */
+#else /* DEBUGBUILD */
/* The call to system's gethostname() might get intercepted by the
libhostname library when libcurl is built as a non-debug shared
library when running the test suite. */
- return gethostname(name, namelen);
+ name[0] = '\0';
+ err = gethostname(name, namelen);
+
+#endif
+
+ name[namelen - 1] = '\0';
+
+ if(err)
+ return err;
+
+ /* Truncate domain, leave only machine name */
+ dot = strchr(name, '.');
+ if(dot)
+ *dot = '\0';
+ return 0;
#endif
}
diff --git a/lib/curl_gethostname.h b/lib/curl_gethostname.h
index b8ecf88d6..48740f62a 100644
--- a/lib/curl_gethostname.h
+++ b/lib/curl_gethostname.h
@@ -22,6 +22,10 @@
*
***************************************************************************/
+/* Hostname buffer size */
+#define HOSTNAME_MAX 1024
+
+/* This returns the local machine's un-qualified hostname */
int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen);
#endif /* HEADER_CURL_GETHOSTNAME_H */
diff --git a/lib/curl_gssapi.c b/lib/curl_gssapi.c
new file mode 100644
index 000000000..b9c8ad0cf
--- /dev/null
+++ b/lib/curl_gssapi.c
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2011, 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.
+ *
+ * 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 "setup.h"
+
+#ifdef HAVE_GSSAPI
+
+#include "curl_gssapi.h"
+#include "sendf.h"
+
+OM_uint32 Curl_gss_init_sec_context(
+ struct SessionHandle *data,
+ OM_uint32 * minor_status,
+ gss_ctx_id_t * context,
+ gss_name_t target_name,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_buffer_t input_token,
+ gss_buffer_t output_token,
+ OM_uint32 * ret_flags)
+{
+ OM_uint32 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
+
+ if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_POLICY_FLAG) {
+#ifdef GSS_C_DELEG_POLICY_FLAG
+ req_flags |= GSS_C_DELEG_POLICY_FLAG;
+#else
+ infof(data, "warning: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not "
+ "compiled in\n");
+#endif
+ }
+
+ if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_FLAG)
+ req_flags |= GSS_C_DELEG_FLAG;
+
+ return gss_init_sec_context(minor_status,
+ GSS_C_NO_CREDENTIAL, /* cred_handle */
+ context,
+ target_name,
+ GSS_C_NO_OID, /* mech_type */
+ req_flags,
+ 0, /* time_req */
+ input_chan_bindings,
+ input_token,
+ NULL, /* actual_mech_type */
+ output_token,
+ ret_flags,
+ NULL /* time_rec */);
+}
+
+#endif /* HAVE_GSSAPI */
diff --git a/lib/curl_gssapi.h b/lib/curl_gssapi.h
new file mode 100644
index 000000000..fd4596b80
--- /dev/null
+++ b/lib/curl_gssapi.h
@@ -0,0 +1,57 @@
+#ifndef HEADER_CURL_GSSAPI_H
+#define HEADER_CURL_GSSAPI_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2011, 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.
+ *
+ * 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 "setup.h"
+#include "urldata.h"
+
+#ifdef HAVE_GSSAPI
+
+#ifdef HAVE_GSSGNU
+# include <gss.h>
+#elif defined HAVE_GSSMIT
+ /* MIT style */
+# include <gssapi/gssapi.h>
+# include <gssapi/gssapi_generic.h>
+# include <gssapi/gssapi_krb5.h>
+#else
+ /* Heimdal-style */
+# include <gssapi.h>
+#endif
+
+
+/* Common method for using gss api */
+
+OM_uint32 Curl_gss_init_sec_context(
+ struct SessionHandle *data,
+ OM_uint32 * minor_status,
+ gss_ctx_id_t * context,
+ gss_name_t target_name,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_buffer_t input_token,
+ gss_buffer_t output_token,
+ OM_uint32 * ret_flags);
+
+#endif /* HAVE_GSSAPI */
+
+#endif /* HEADER_CURL_GSSAPI_H */
diff --git a/lib/curl_ntlm.c b/lib/curl_ntlm.c
new file mode 100644
index 000000000..c7d67a0de
--- /dev/null
+++ b/lib/curl_ntlm.c
@@ -0,0 +1,238 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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.
+ *
+ * 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 "setup.h"
+
+#ifdef USE_NTLM
+
+/*
+ * NTLM details:
+ *
+ * http://davenport.sourceforge.net/ntlm.html
+ * http://www.innovation.ch/java/ntlm.html
+ */
+
+#define DEBUG_ME 0
+
+#include "urldata.h"
+#include "sendf.h"
+#include "rawstr.h"
+#include "curl_ntlm.h"
+#include "curl_ntlm_msgs.h"
+#include "curl_ntlm_wb.h"
+#include "url.h"
+#include "curl_memory.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#if defined(USE_NSS)
+#include "nssg.h"
+#elif defined(USE_WINDOWS_SSPI)
+#include "curl_sspi.h"
+#endif
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#if DEBUG_ME
+# define DEBUG_OUT(x) x
+#else
+# define DEBUG_OUT(x) Curl_nop_stmt
+#endif
+
+CURLcode Curl_input_ntlm(struct connectdata *conn,
+ bool proxy, /* if proxy or not */
+ const char *header) /* rest of the www-authenticate:
+ header */
+{
+ /* point to the correct struct with this */
+ struct ntlmdata *ntlm;
+ CURLcode result = CURLE_OK;
+
+#ifdef USE_NSS
+ result = Curl_nss_force_init(conn->data);
+ if(result)
+ return result;
+#endif
+
+ ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
+
+ /* skip initial whitespaces */
+ while(*header && ISSPACE(*header))
+ header++;
+
+ if(checkprefix("NTLM", header)) {
+ header += strlen("NTLM");
+
+ while(*header && ISSPACE(*header))
+ header++;
+
+ if(*header) {
+ result = Curl_ntlm_decode_type2_message(conn->data, header, ntlm);
+ if(CURLE_OK != result)
+ return result;
+
+ ntlm->state = NTLMSTATE_TYPE2; /* We got a type-2 message */
+ }
+ else {
+ if(ntlm->state >= NTLMSTATE_TYPE1) {
+ infof(conn->data, "NTLM handshake failure (internal error)\n");
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+
+ ntlm->state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
+ }
+ }
+
+ return result;
+}
+
+/*
+ * This is for creating ntlm header output
+ */
+CURLcode Curl_output_ntlm(struct connectdata *conn,
+ bool proxy)
+{
+ char *base64 = NULL;
+ size_t len = 0;
+ CURLcode error;
+
+ /* point to the address of the pointer that holds the string to send to the
+ server, which is for a plain host or for a HTTP proxy */
+ char **allocuserpwd;
+
+ /* point to the name and password for this */
+ const char *userp;
+ const char *passwdp;
+
+ /* point to the correct struct with this */
+ struct ntlmdata *ntlm;
+ struct auth *authp;
+
+ DEBUGASSERT(conn);
+ DEBUGASSERT(conn->data);
+
+#ifdef USE_NSS
+ if(CURLE_OK != Curl_nss_force_init(conn->data))
+ return CURLE_OUT_OF_MEMORY;
+#endif
+
+ if(proxy) {
+ allocuserpwd = &conn->allocptr.proxyuserpwd;
+ userp = conn->proxyuser;
+ passwdp = conn->proxypasswd;
+ ntlm = &conn->proxyntlm;
+ authp = &conn->data->state.authproxy;
+ }
+ else {
+ allocuserpwd = &conn->allocptr.userpwd;
+ userp = conn->user;
+ passwdp = conn->passwd;
+ ntlm = &conn->ntlm;
+ authp = &conn->data->state.authhost;
+ }
+ authp->done = FALSE;
+
+ /* not set means empty */
+ if(!userp)
+ userp = "";
+
+ if(!passwdp)
+ passwdp = "";
+
+#ifdef USE_WINDOWS_SSPI
+ if(s_hSecDll == NULL) {
+ /* not thread safe and leaks - use curl_global_init() to avoid */
+ CURLcode err = Curl_sspi_global_init();
+ if(s_hSecDll == NULL)
+ return err;
+ }
+#endif
+
+ switch(ntlm->state) {
+ case NTLMSTATE_TYPE1:
+ default: /* for the weird cases we (re)start here */
+ /* Create a type-1 message */
+ error = Curl_ntlm_create_type1_message(userp, passwdp, ntlm, &base64,
+ &len);
+
+ if(error)
+ return error;
+
+ if(base64) {
+ Curl_safefree(*allocuserpwd);
+ *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
+ proxy ? "Proxy-" : "",
+ base64);
+ DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
+ free(base64);
+ }
+ break;
+
+ case NTLMSTATE_TYPE2:
+ /* We already received the type-2 message, create a type-3 message */
+ error = Curl_ntlm_create_type3_message(conn->data, userp, passwdp,
+ ntlm, &base64, &len);
+ if(error)
+ return error;
+
+ if(base64) {
+ Curl_safefree(*allocuserpwd);
+ *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
+ proxy ? "Proxy-" : "",
+ base64);
+ DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
+ free(base64);
+
+ ntlm->state = NTLMSTATE_TYPE3; /* we send a type-3 */
+ authp->done = TRUE;
+ }
+ break;
+
+ case NTLMSTATE_TYPE3:
+ /* connection is already authenticated,
+ * don't send a header in future requests */
+ if(*allocuserpwd) {
+ free(*allocuserpwd);
+ *allocuserpwd = NULL;
+ }
+ authp->done = TRUE;
+ break;
+ }
+
+ return CURLE_OK;
+}
+
+void Curl_http_ntlm_cleanup(struct connectdata *conn)
+{
+#ifdef USE_WINDOWS_SSPI
+ Curl_ntlm_sspi_cleanup(&conn->ntlm);
+ Curl_ntlm_sspi_cleanup(&conn->proxyntlm);
+#elif defined(NTLM_WB_ENABLED)
+ Curl_ntlm_wb_cleanup(conn);
+#else
+ (void)conn;
+#endif
+}
+
+#endif /* USE_NTLM */
diff --git a/lib/curl_ntlm.h b/lib/curl_ntlm.h
new file mode 100644
index 000000000..b2783778b
--- /dev/null
+++ b/lib/curl_ntlm.h
@@ -0,0 +1,44 @@
+#ifndef HEADER_CURL_NTLM_H
+#define HEADER_CURL_NTLM_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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.
+ *
+ * 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 "setup.h"
+
+#ifdef USE_NTLM
+
+/* this is for ntlm header input */
+CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy,
+ const char *header);
+
+/* this is for creating ntlm header output */
+CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
+
+void Curl_http_ntlm_cleanup(struct connectdata *conn);
+
+#else
+
+#define Curl_http_ntlm_cleanup(a) Curl_nop_stmt
+
+#endif
+
+#endif /* HEADER_CURL_NTLM_H */
diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c
new file mode 100644
index 000000000..0be16b474
--- /dev/null
+++ b/lib/curl_ntlm_core.c
@@ -0,0 +1,379 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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.
+ *
+ * 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 "setup.h"
+
+#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI)
+
+/*
+ * NTLM details:
+ *
+ * http://davenport.sourceforge.net/ntlm.html
+ * http://www.innovation.ch/java/ntlm.html
+ */
+
+#ifdef USE_SSLEAY
+
+# ifdef USE_OPENSSL
+# include <openssl/des.h>
+# ifndef OPENSSL_NO_MD4
+# include <openssl/md4.h>
+# endif
+# include <openssl/md5.h>
+# include <openssl/ssl.h>
+# include <openssl/rand.h>
+# else
+# include <des.h>
+# ifndef OPENSSL_NO_MD4
+# include <md4.h>
+# endif
+# include <md5.h>
+# include <ssl.h>
+# include <rand.h>
+# endif
+# if (OPENSSL_VERSION_NUMBER < 0x00907001L)
+# define DES_key_schedule des_key_schedule
+# define DES_cblock des_cblock
+# define DES_set_odd_parity des_set_odd_parity
+# define DES_set_key des_set_key
+# define DES_ecb_encrypt des_ecb_encrypt
+# define DESKEY(x) x
+# define DESKEYARG(x) x
+# else
+# define DESKEYARG(x) *x
+# define DESKEY(x) &x
+# endif
+
+#elif defined(USE_GNUTLS)
+
+# include <gcrypt.h>
+# define MD5_DIGEST_LENGTH 16
+# define MD4_DIGEST_LENGTH 16
+
+#elif defined(USE_NSS)
+
+# include <nss.h>
+# include <pk11pub.h>
+# include <hasht.h>
+# include "curl_md4.h"
+# define MD5_DIGEST_LENGTH MD5_LENGTH
+
+#else
+# error "Can't compile NTLM support without a crypto library."
+#endif
+
+#include "urldata.h"
+#include "non-ascii.h"
+#include "rawstr.h"
+#include "curl_memory.h"
+#include "curl_ntlm_core.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifdef USE_SSLEAY
+/*
+ * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
+ * key schedule ks is also set.
+ */
+static void setup_des_key(const unsigned char *key_56,
+ DES_key_schedule DESKEYARG(ks))
+{
+ DES_cblock key;
+
+ key[0] = key_56[0];
+ key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
+ key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
+ key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
+ key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
+ key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
+ key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
+ key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
+
+ DES_set_odd_parity(&key);
+ DES_set_key(&key, ks);
+}
+
+#else /* defined(USE_SSLEAY) */
+
+/*
+ * Turns a 56 bit key into the 64 bit, odd parity key. Used by GnuTLS and NSS.
+ */
+static void extend_key_56_to_64(const unsigned char *key_56, char *key)
+{
+ key[0] = key_56[0];
+ key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
+ key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
+ key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
+ key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
+ key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
+ key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
+ key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
+}
+
+#if defined(USE_GNUTLS)
+
+/*
+ * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
+ */
+static void setup_des_key(const unsigned char *key_56,
+ gcry_cipher_hd_t *des)
+{
+ char key[8];
+ extend_key_56_to_64(key_56, key);
+ gcry_cipher_setkey(*des, key, 8);
+}
+
+#elif defined(USE_NSS)
+
+/*
+ * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using
+ * the expanded key. The caller is responsible for giving 64 bit of valid
+ * data is IN and (at least) 64 bit large buffer as OUT.
+ */
+static bool encrypt_des(const unsigned char *in, unsigned char *out,
+ const unsigned char *key_56)
+{
+ const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */
+ PK11SlotInfo *slot = NULL;
+ char key[8]; /* expanded 64 bit key */
+ SECItem key_item;
+ PK11SymKey *symkey = NULL;
+ SECItem *param = NULL;
+ PK11Context *ctx = NULL;
+ int out_len; /* not used, required by NSS */
+ bool rv = FALSE;
+
+ /* use internal slot for DES encryption (requires NSS to be initialized) */
+ slot = PK11_GetInternalKeySlot();
+ if(!slot)
+ return FALSE;
+
+ /* expand the 56 bit key to 64 bit and wrap by NSS */
+ extend_key_56_to_64(key_56, key);
+ key_item.data = (unsigned char *)key;
+ key_item.len = /* hard-wired */ 8;
+ symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT,
+ &key_item, NULL);
+ if(!symkey)
+ goto fail;
+
+ /* create DES encryption context */
+ param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL);
+ if(!param)
+ goto fail;
+ ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param);
+ if(!ctx)
+ goto fail;
+
+ /* perform the encryption */
+ if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8,
+ (unsigned char *)in, /* inbuflen */ 8)
+ && SECSuccess == PK11_Finalize(ctx))
+ rv = /* all OK */ TRUE;
+
+fail:
+ /* cleanup */
+ if(ctx)
+ PK11_DestroyContext(ctx, PR_TRUE);
+ if(symkey)
+ PK11_FreeSymKey(symkey);
+ if(param)
+ SECITEM_FreeItem(param, PR_TRUE);
+ PK11_FreeSlot(slot);
+ return rv;
+}
+
+#endif /* defined(USE_NSS) */
+
+#endif /* defined(USE_SSLEAY) */
+
+ /*
+ * takes a 21 byte array and treats it as 3 56-bit DES keys. The
+ * 8 byte plaintext is encrypted with each key and the resulting 24
+ * bytes are stored in the results array.
+ */
+void Curl_ntlm_core_lm_resp(const unsigned char *keys,
+ const unsigned char *plaintext,
+ unsigned char *results)
+{
+#ifdef USE_SSLEAY
+ DES_key_schedule ks;
+
+ setup_des_key(keys, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
+ DESKEY(ks), DES_ENCRYPT);
+
+ setup_des_key(keys + 7, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 8),
+ DESKEY(ks), DES_ENCRYPT);
+
+ setup_des_key(keys + 14, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16),
+ DESKEY(ks), DES_ENCRYPT);
+#elif defined(USE_GNUTLS)
+ gcry_cipher_hd_t des;
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(keys, &des);
+ gcry_cipher_encrypt(des, results, 8, plaintext, 8);
+ gcry_cipher_close(des);
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(keys + 7, &des);
+ gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8);
+ gcry_cipher_close(des);
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(keys + 14, &des);
+ gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
+ gcry_cipher_close(des);
+#elif defined(USE_NSS)
+ encrypt_des(plaintext, results, keys);
+ encrypt_des(plaintext, results + 8, keys + 7);
+ encrypt_des(plaintext, results + 16, keys + 14);
+#endif
+}
+
+/*
+ * Set up lanmanager hashed password
+ */
+void Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data,
+ const char *password,
+ unsigned char *lmbuffer /* 21 bytes */)
+{
+ CURLcode res;
+ unsigned char pw[14];
+ static const unsigned char magic[] = {
+ 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
+ };
+ size_t len = CURLMIN(strlen(password), 14);
+
+ Curl_strntoupper((char *)pw, password, len);
+ memset(&pw[len], 0, 14 - len);
+
+ /*
+ * The LanManager hashed password needs to be created using the
+ * password in the network encoding not the host encoding.
+ */
+ res = Curl_convert_to_network(data, (char *)pw, 14);
+ if(res)
+ return;
+
+ {
+ /* Create LanManager hashed password. */
+
+#ifdef USE_SSLEAY
+ DES_key_schedule ks;
+
+ setup_des_key(pw, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
+ DESKEY(ks), DES_ENCRYPT);
+
+ setup_des_key(pw + 7, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8),
+ DESKEY(ks), DES_ENCRYPT);
+#elif defined(USE_GNUTLS)
+ gcry_cipher_hd_t des;
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(pw, &des);
+ gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
+ gcry_cipher_close(des);
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(pw + 7, &des);
+ gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
+ gcry_cipher_close(des);
+#elif defined(USE_NSS)
+ encrypt_des(magic, lmbuffer, pw);
+ encrypt_des(magic, lmbuffer + 8, pw + 7);
+#endif
+
+ memset(lmbuffer + 16, 0, 21 - 16);
+ }
+}
+
+#if USE_NTRESPONSES
+static void ascii_to_unicode_le(unsigned char *dest, const char *src,
+ size_t srclen)
+{
+ size_t i;
+ for(i = 0; i < srclen; i++) {
+ dest[2 * i] = (unsigned char)src[i];
+ dest[2 * i + 1] = '\0';
+ }
+}
+
+/*
+ * Set up nt hashed passwords
+ */
+CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data,
+ const char *password,
+ unsigned char *ntbuffer /* 21 bytes */)
+{
+ size_t len = strlen(password);
+ unsigned char *pw = malloc(len * 2);
+ CURLcode result;
+ if(!pw)
+ return CURLE_OUT_OF_MEMORY;
+
+ ascii_to_unicode_le(pw, password, len);
+
+ /*
+ * The NT hashed password needs to be created using the password in the
+ * network encoding not the host encoding.
+ */
+ result = Curl_convert_to_network(data, (char *)pw, len * 2);
+ if(result)
+ return result;
+
+ {
+ /* Create NT hashed password. */
+#ifdef USE_SSLEAY
+ MD4_CTX MD4pw;
+ MD4_Init(&MD4pw);
+ MD4_Update(&MD4pw, pw, 2 * len);
+ MD4_Final(ntbuffer, &MD4pw);
+#elif defined(USE_GNUTLS)
+ gcry_md_hd_t MD4pw;
+ gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
+ gcry_md_write(MD4pw, pw, 2 * len);
+ memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
+ gcry_md_close(MD4pw);
+#elif defined(USE_NSS)
+ Curl_md4it(ntbuffer, pw, 2 * len);
+#endif
+
+ memset(ntbuffer + 16, 0, 21 - 16);
+ }
+
+ free(pw);
+
+ return CURLE_OK;
+}
+#endif /* USE_NTRESPONSES */
+
+#endif /* USE_NTLM && !USE_WINDOWS_SSPI */
diff --git a/lib/curl_ntlm_core.h b/lib/curl_ntlm_core.h
new file mode 100644
index 000000000..5615b3504
--- /dev/null
+++ b/lib/curl_ntlm_core.h
@@ -0,0 +1,68 @@
+#ifndef HEADER_CURL_NTLM_CORE_H
+#define HEADER_CURL_NTLM_CORE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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.
+ *
+ * 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 "setup.h"
+
+#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI)
+
+#ifdef USE_SSLEAY
+# if !defined(OPENSSL_VERSION_NUMBER) && \
+ !defined(HEADER_SSL_H) && !defined(HEADER_MD5_H)
+# error "curl_ntlm_core.h shall not be included before OpenSSL headers."
+# endif
+# ifdef OPENSSL_NO_MD4
+# define USE_NTRESPONSES 0
+# define USE_NTLM2SESSION 0
+# endif
+#endif
+
+/*
+ * Define USE_NTRESPONSES to 1 in order to make the type-3 message include
+ * the NT response message. Define USE_NTLM2SESSION to 1 in order to make
+ * the type-3 message include the NTLM2Session response message, requires
+ * USE_NTRESPONSES defined to 1.
+ */
+
+#ifndef USE_NTRESPONSES
+# define USE_NTRESPONSES 1
+# define USE_NTLM2SESSION 1
+#endif
+
+void Curl_ntlm_core_lm_resp(const unsigned char *keys,
+ const unsigned char *plaintext,
+ unsigned char *results);
+
+void Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data,
+ const char *password,
+ unsigned char *lmbuffer /* 21 bytes */);
+
+#if USE_NTRESPONSES
+CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data,
+ const char *password,
+ unsigned char *ntbuffer /* 21 bytes */);
+#endif
+
+#endif /* USE_NTLM && !USE_WINDOWS_SSPI */
+
+#endif /* HEADER_CURL_NTLM_CORE_H */
diff --git a/lib/curl_ntlm_msgs.c b/lib/curl_ntlm_msgs.c
new file mode 100644
index 000000000..bfd3e2814
--- /dev/null
+++ b/lib/curl_ntlm_msgs.c
@@ -0,0 +1,958 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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.
+ *
+ * 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 "setup.h"
+
+#ifdef USE_NTLM
+
+/*
+ * NTLM details:
+ *
+ * http://davenport.sourceforge.net/ntlm.html
+ * http://www.innovation.ch/java/ntlm.html
+ */
+
+#define DEBUG_ME 0
+
+#ifdef USE_SSLEAY
+
+# ifdef USE_OPENSSL
+# include <openssl/des.h>
+# ifndef OPENSSL_NO_MD4
+# include <openssl/md4.h>
+# endif
+# include <openssl/md5.h>
+# include <openssl/ssl.h>
+# include <openssl/rand.h>
+# else
+# include <des.h>
+# ifndef OPENSSL_NO_MD4
+# include <md4.h>
+# endif
+# include <md5.h>
+# include <ssl.h>
+# include <rand.h>
+# endif
+# include "ssluse.h"
+
+#elif defined(USE_GNUTLS)
+
+# include <gcrypt.h>
+# include "gtls.h"
+# define MD5_DIGEST_LENGTH 16
+# define MD4_DIGEST_LENGTH 16
+
+#elif defined(USE_NSS)
+
+# include <nss.h>
+# include <pk11pub.h>
+# include <hasht.h>
+# include "nssg.h"
+# include "curl_md4.h"
+# define MD5_DIGEST_LENGTH MD5_LENGTH
+
+#elif defined(USE_WINDOWS_SSPI)
+# include "curl_sspi.h"
+#else
+# error "Can't compile NTLM support without a crypto library."
+#endif
+
+#include "urldata.h"
+#include "non-ascii.h"
+#include "sendf.h"
+#include "curl_base64.h"
+#include "curl_ntlm_core.h"
+#include "curl_gethostname.h"
+#include "curl_memory.h"
+
+#define BUILDING_CURL_NTLM_MSGS_C
+#include "curl_ntlm_msgs.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* "NTLMSSP" signature is always in ASCII regardless of the platform */
+#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
+
+#define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
+#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \
+ (((x) >> 16) & 0xff), (((x) >> 24) & 0xff)
+
+#if DEBUG_ME
+# define DEBUG_OUT(x) x
+static void ntlm_print_flags(FILE *handle, unsigned long flags)
+{
+ if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
+ if(flags & NTLMFLAG_NEGOTIATE_OEM)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
+ if(flags & NTLMFLAG_REQUEST_TARGET)
+ fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
+ if(flags & (1<<3))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
+ if(flags & NTLMFLAG_NEGOTIATE_SIGN)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
+ if(flags & NTLMFLAG_NEGOTIATE_SEAL)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
+ if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
+ if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
+ if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
+ if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
+ if(flags & (1<<10))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
+ if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
+ if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
+ if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
+ if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
+ if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
+ if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
+ fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
+ if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
+ fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
+ if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
+ fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
+ if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
+ if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
+ fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
+ if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
+ fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
+ if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
+ fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
+ if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
+ if(flags & (1<<24))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
+ if(flags & (1<<25))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
+ if(flags & (1<<26))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
+ if(flags & (1<<27))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
+ if(flags & (1<<28))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
+ if(flags & NTLMFLAG_NEGOTIATE_128)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
+ if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
+ if(flags & NTLMFLAG_NEGOTIATE_56)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
+}
+
+static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
+{
+ const char *p = buf;
+ (void)handle;
+ fprintf(stderr, "0x");
+ while(len-- > 0)
+ fprintf(stderr, "%02.2x", (unsigned int)*p++);
+}
+#else
+# define DEBUG_OUT(x) Curl_nop_stmt
+#endif
+
+#ifndef USE_WINDOWS_SSPI
+/*
+ * This function converts from the little endian format used in the
+ * incoming package to whatever endian format we're using natively.
+ * Argument is a pointer to a 4 byte buffer.
+ */
+static unsigned int readint_le(unsigned char *buf)
+{
+ return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
+ ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
+}
+#endif
+
+/*
+ NTLM message structure notes:
+
+ A 'short' is a 'network short', a little-endian 16-bit unsigned value.
+
+ A 'long' is a 'network long', a little-endian, 32-bit unsigned value.
+
+ A 'security buffer' represents a triplet used to point to a buffer,
+ consisting of two shorts and one long:
+
+ 1. A 'short' containing the length of the buffer content in bytes.
+ 2. A 'short' containing the allocated space for the buffer in bytes.
+ 3. A 'long' containing the offset to the start of the buffer in bytes,
+ from the beginning of the NTLM message.
+*/
+
+/*
+ * Curl_ntlm_decode_type2_message()
+ *
+ * This is used to decode a ntlm type-2 message received from a: HTTP, SMTP
+ * or POP3 server. The message is first decoded from a base64 string into a
+ * raw ntlm message and checked for validity before the appropriate data for
+ * creating a type-3 message is written to the given ntlm data structure.
+ *
+ * Parameters:
+ *
+ * data [in] - Pointer to session handle.
+ * header [in] - Pointer to the input buffer.
+ * ntlm [in] - Pointer to ntlm data struct being used and modified.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data,
+ const char* header,
+ struct ntlmdata* ntlm)
+{
+#ifndef USE_WINDOWS_SSPI
+ static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
+#endif
+
+ /* NTLM type-2 message structure:
+
+ Index Description Content
+ 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
+ (0x4e544c4d53535000)
+ 8 NTLM Message Type long (0x02000000)
+ 12 Target Name security buffer
+ 20 Flags long
+ 24 Challenge 8 bytes
+ (32) Context 8 bytes (two consecutive longs) (*)
+ (40) Target Information security buffer (*)
+ (48) OS Version Structure 8 bytes (*)
+ 32 (48) (56) Start of data block (*)
+ (*) -> Optional
+ */
+
+ size_t size = 0;
+ unsigned char *buffer = NULL;
+ CURLcode error;
+
+#if defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_WINDOWS_SSPI)
+ (void)data;
+#endif
+
+ error = Curl_base64_decode(header, &buffer, &size);
+ if(error)
+ return error;
+
+ if(!buffer) {
+ infof(data, "NTLM handshake failure (unhandled condition)\n");
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+
+#ifdef USE_WINDOWS_SSPI
+ ntlm->type_2 = malloc(size + 1);
+ if(ntlm->type_2 == NULL) {
+ free(buffer);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ ntlm->n_type_2 = (unsigned long)size;
+ memcpy(ntlm->type_2, buffer, size);
+#else
+ ntlm->flags = 0;
+
+ if((size < 32) ||
+ (memcmp(buffer, NTLMSSP_SIGNATURE, 8) != 0) ||
+ (memcmp(buffer + 8, type2_marker, sizeof(type2_marker)) != 0)) {
+ /* This was not a good enough type-2 message */
+ free(buffer);
+ infof(data, "NTLM handshake failure (bad type-2 message)\n");
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+
+ ntlm->flags = readint_le(&buffer[20]);
+ memcpy(ntlm->nonce, &buffer[24], 8);
+
+ DEBUG_OUT({
+ fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
+ ntlm_print_flags(stderr, ntlm->flags);
+ fprintf(stderr, "\n nonce=");
+ ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
+ fprintf(stderr, "\n****\n");
+ fprintf(stderr, "**** Header %s\n ", header);
+ });
+#endif
+ free(buffer);
+
+ return CURLE_OK;
+}
+
+#ifdef USE_WINDOWS_SSPI
+void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm)
+{
+ if(ntlm->type_2) {
+ free(ntlm->type_2);
+ ntlm->type_2 = NULL;
+ }
+ if(ntlm->has_handles) {
+ s_pSecFn->DeleteSecurityContext(&ntlm->c_handle);
+ s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
+ ntlm->has_handles = 0;
+ }
+ if(ntlm->p_identity) {
+ if(ntlm->identity.User) free(ntlm->identity.User);
+ if(ntlm->identity.Password) free(ntlm->identity.Password);
+ if(ntlm->identity.Domain) free(ntlm->identity.Domain);
+ ntlm->p_identity = NULL;
+ }
+}
+#endif
+
+#ifndef USE_WINDOWS_SSPI
+/* copy the source to the destination and fill in zeroes in every
+ other destination byte! */
+static void unicodecpy(unsigned char *dest,
+ const char *src, size_t length)
+{
+ size_t i;
+ for(i = 0; i < length; i++) {
+ dest[2 * i] = (unsigned char)src[i];
+ dest[2 * i + 1] = '\0';
+ }
+}
+#endif
+
+/*
+ * Curl_ntlm_create_type1_message()
+ *
+ * This is used to generate an already encoded NTLM type-1 message ready
+ * for sending to the recipient, be it a: HTTP, SMTP or POP3 server,
+ * using the appropriate compile time crypo API.
+ *
+ * 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 adress 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_ntlm_create_type1_message(const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr,
+ size_t *outlen)
+{
+ /* NTLM type-1 message structure:
+
+ Index Description Content
+ 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
+ (0x4e544c4d53535000)
+ 8 NTLM Message Type long (0x01000000)
+ 12 Flags long
+ (16) Supplied Domain security buffer (*)
+ (24) Supplied Workstation security buffer (*)
+ (32) OS Version Structure 8 bytes (*)
+ (32) (40) Start of data block (*)
+ (*) -> Optional
+ */
+
+ unsigned char ntlmbuf[NTLM_BUFSIZE];
+ size_t size;
+
+#ifdef USE_WINDOWS_SSPI
+
+ SecBuffer buf;
+ SecBufferDesc desc;
+ SECURITY_STATUS status;
+ ULONG attrs;
+ const char *dest = "";
+ const char *user;
+ const char *domain = "";
+ size_t userlen = 0;
+ size_t domlen = 0;
+ size_t passwdlen = 0;
+ TimeStamp tsDummy; /* For Windows 9x compatibility of SSPI calls */
+
+ Curl_ntlm_sspi_cleanup(ntlm);
+
+ user = strchr(userp, '\\');
+ if(!user)
+ user = strchr(userp, '/');
+
+ if(user) {
+ domain = userp;
+ domlen = user - userp;
+ user++;
+ }
+ else {
+ user = userp;
+ domain = "";
+ domlen = 0;
+ }
+
+ if(user)
+ userlen = strlen(user);
+
+ if(passwdp)
+ passwdlen = strlen(passwdp);
+
+ if(userlen > 0) {
+ /* note: initialize all of this before doing the mallocs so that
+ * it can be cleaned up later without leaking memory.
+ */
+ ntlm->p_identity = &ntlm->identity;
+ memset(ntlm->p_identity, 0, sizeof(*ntlm->p_identity));
+ if((ntlm->identity.User = (unsigned char *)strdup(user)) == NULL)
+ return CURLE_OUT_OF_MEMORY;
+
+ ntlm->identity.UserLength = (unsigned long)userlen;
+ if((ntlm->identity.Password = (unsigned char *)strdup(passwdp)) == NULL)
+ return CURLE_OUT_OF_MEMORY;
+
+ ntlm->identity.PasswordLength = (unsigned long)strlen(passwdp);
+ if((ntlm->identity.Domain = malloc(domlen + 1)) == NULL)
+ return CURLE_OUT_OF_MEMORY;
+
+ strncpy((char *)ntlm->identity.Domain, domain, domlen);
+ ntlm->identity.Domain[domlen] = '\0';
+ ntlm->identity.DomainLength = (unsigned long)domlen;
+ ntlm->identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
+ }
+ else
+ ntlm->p_identity = NULL;
+
+ status = s_pSecFn->AcquireCredentialsHandleA(NULL, (void *)"NTLM",
+ SECPKG_CRED_OUTBOUND, NULL,
+ ntlm->p_identity, NULL, NULL,
+ &ntlm->handle, &tsDummy);
+ if(status != SEC_E_OK)
+ return CURLE_OUT_OF_MEMORY;
+
+ desc.ulVersion = SECBUFFER_VERSION;
+ desc.cBuffers = 1;
+ desc.pBuffers = &buf;
+ buf.cbBuffer = NTLM_BUFSIZE;
+ buf.BufferType = SECBUFFER_TOKEN;
+ buf.pvBuffer = ntlmbuf;
+
+ status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, NULL,
+ (void *)dest,
+ ISC_REQ_CONFIDENTIALITY |
+ ISC_REQ_REPLAY_DETECT |
+ ISC_REQ_CONNECTION,
+ 0, SECURITY_NETWORK_DREP,
+ NULL, 0,
+ &ntlm->c_handle, &desc,
+ &attrs, &tsDummy);
+
+ if(status == SEC_I_COMPLETE_AND_CONTINUE ||
+ status == SEC_I_CONTINUE_NEEDED)
+ s_pSecFn->CompleteAuthToken(&ntlm->c_handle, &desc);
+ else if(status != SEC_E_OK) {
+ s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
+ return CURLE_RECV_ERROR;
+ }
+
+ ntlm->has_handles = 1;
+ size = buf.cbBuffer;
+
+#else
+
+ const char *host = ""; /* empty */
+ const char *domain = ""; /* empty */
+ size_t hostlen = 0;
+ size_t domlen = 0;
+ size_t hostoff = 0;
+ size_t domoff = hostoff + hostlen; /* This is 0: remember that host and
+ domain are empty */
+ (void)userp;
+ (void)passwdp;
+ (void)ntlm;
+
+#if USE_NTLM2SESSION
+#define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
+#else
+#define NTLM2FLAG 0
+#endif
+ snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
+ NTLMSSP_SIGNATURE "%c"
+ "\x01%c%c%c" /* 32-bit type = 1 */
+ "%c%c%c%c" /* 32-bit NTLM flag field */
+ "%c%c" /* domain length */
+ "%c%c" /* domain allocated space */
+ "%c%c" /* domain name offset */
+ "%c%c" /* 2 zeroes */
+ "%c%c" /* host length */
+ "%c%c" /* host allocated space */
+ "%c%c" /* host name offset */
+ "%c%c" /* 2 zeroes */
+ "%s" /* host name */
+ "%s", /* domain string */
+ 0, /* trailing zero */
+ 0, 0, 0, /* part of type-1 long */
+
+ LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
+ NTLMFLAG_REQUEST_TARGET |
+ NTLMFLAG_NEGOTIATE_NTLM_KEY |
+ NTLM2FLAG |
+ NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
+ SHORTPAIR(domlen),
+ SHORTPAIR(domlen),
+ SHORTPAIR(domoff),
+ 0, 0,
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostoff),
+ 0, 0,
+ host, /* this is empty */
+ domain /* this is empty */);
+
+ /* Initial packet length */
+ size = 32 + hostlen + domlen;
+
+#endif
+
+ DEBUG_OUT({
+ fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
+ "0x%08.8x ",
+ LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
+ NTLMFLAG_REQUEST_TARGET |
+ NTLMFLAG_NEGOTIATE_NTLM_KEY |
+ NTLM2FLAG |
+ NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
+ NTLMFLAG_NEGOTIATE_OEM |
+ NTLMFLAG_REQUEST_TARGET |
+ NTLMFLAG_NEGOTIATE_NTLM_KEY |
+ NTLM2FLAG |
+ NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
+ ntlm_print_flags(stderr,
+ NTLMFLAG_NEGOTIATE_OEM |
+ NTLMFLAG_REQUEST_TARGET |
+ NTLMFLAG_NEGOTIATE_NTLM_KEY |
+ NTLM2FLAG |
+ NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
+ fprintf(stderr, "\n****\n");
+ });
+
+ /* Return with binary blob encoded into base64 */
+ return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
+}
+
+/*
+ * Curl_ntlm_create_type3_message()
+ *
+ * This is used to generate an already encoded NTLM type-3 message ready
+ * for sending to the recipient, be it a: HTTP, SMTP or POP3 server,
+ * using the appropriate compile time crypo API.
+ *
+ * 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 adress 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_ntlm_create_type3_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr,
+ size_t *outlen)
+{
+ /* NTLM type-3 message structure:
+
+ Index Description Content
+ 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
+ (0x4e544c4d53535000)
+ 8 NTLM Message Type long (0x03000000)
+ 12 LM/LMv2 Response security buffer
+ 20 NTLM/NTLMv2 Response security buffer
+ 28 Target Name security buffer
+ 36 User Name security buffer
+ 44 Workstation Name security buffer
+ (52) Session Key security buffer (*)
+ (60) Flags long (*)
+ (64) OS Version Structure 8 bytes (*)
+ 52 (64) (72) Start of data block
+ (*) -> Optional
+ */
+
+ unsigned char ntlmbuf[NTLM_BUFSIZE];
+ size_t size;
+
+#ifdef USE_WINDOWS_SSPI
+ const char *dest = "";
+ SecBuffer type_2;
+ SecBuffer type_3;
+ SecBufferDesc type_2_desc;
+ SecBufferDesc type_3_desc;
+ SECURITY_STATUS status;
+ ULONG attrs;
+ TimeStamp tsDummy; /* For Windows 9x compatibility of SSPI calls */
+
+ (void)passwdp;
+ (void)userp;
+ (void)data;
+
+ type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION;
+ type_2_desc.cBuffers = type_3_desc.cBuffers = 1;
+ type_2_desc.pBuffers = &type_2;
+ type_3_desc.pBuffers = &type_3;
+
+ type_2.BufferType = SECBUFFER_TOKEN;
+ type_2.pvBuffer = ntlm->type_2;
+ type_2.cbBuffer = ntlm->n_type_2;
+ type_3.BufferType = SECBUFFER_TOKEN;
+ type_3.pvBuffer = ntlmbuf;
+ type_3.cbBuffer = NTLM_BUFSIZE;
+
+ status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle,
+ &ntlm->c_handle,
+ (void *)dest,
+ ISC_REQ_CONFIDENTIALITY |
+ ISC_REQ_REPLAY_DETECT |
+ ISC_REQ_CONNECTION,
+ 0, SECURITY_NETWORK_DREP,
+ &type_2_desc,
+ 0, &ntlm->c_handle,
+ &type_3_desc,
+ &attrs, &tsDummy);
+ if(status != SEC_E_OK)
+ return CURLE_RECV_ERROR;
+
+ size = type_3.cbBuffer;
+
+ Curl_ntlm_sspi_cleanup(ntlm);
+
+#else
+ int lmrespoff;
+ unsigned char lmresp[24]; /* fixed-size */
+#if USE_NTRESPONSES
+ int ntrespoff;
+ unsigned char ntresp[24]; /* fixed-size */
+#endif
+ bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
+ char host[HOSTNAME_MAX + 1] = "";
+ const char *user;
+ const char *domain = "";
+ size_t hostoff = 0;
+ size_t useroff = 0;
+ size_t domoff = 0;
+ size_t hostlen = 0;
+ size_t userlen = 0;
+ size_t domlen = 0;
+ CURLcode res;
+
+ user = strchr(userp, '\\');
+ if(!user)
+ user = strchr(userp, '/');
+
+ if(user) {
+ domain = userp;
+ domlen = (user - domain);
+ user++;
+ }
+ else
+ user = userp;
+
+ if(user)
+ userlen = strlen(user);
+
+ /* Get the machine's un-qualified host name as NTLM doesn't like the fully
+ qualified domain name */
+ if(Curl_gethostname(host, sizeof(host))) {
+ infof(data, "gethostname() failed, continuing without!");
+ hostlen = 0;
+ }
+ else {
+ hostlen = strlen(host);
+ }
+
+ if(unicode) {
+ domlen = domlen * 2;
+ userlen = userlen * 2;
+ hostlen = hostlen * 2;
+ }
+
+#if USE_NTLM2SESSION
+ /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
+ if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
+ unsigned char ntbuffer[0x18];
+ unsigned char tmp[0x18];
+ unsigned char md5sum[MD5_DIGEST_LENGTH];
+ unsigned char entropy[8];
+
+ /* Need to create 8 bytes random data */
+#ifdef USE_SSLEAY
+ MD5_CTX MD5pw;
+ Curl_ossl_seed(data); /* Initiate the seed if not already done */
+ RAND_bytes(entropy, 8);
+#elif defined(USE_GNUTLS)
+ gcry_md_hd_t MD5pw;
+ Curl_gtls_seed(data); /* Initiate the seed if not already done */
+ gcry_randomize(entropy, 8, GCRY_STRONG_RANDOM);
+#elif defined(USE_NSS)
+ PK11Context *MD5pw;
+ unsigned int MD5len;
+ Curl_nss_seed(data); /* Initiate the seed if not already done */
+ PK11_GenerateRandom(entropy, 8);
+#endif
+
+ /* 8 bytes random data as challenge in lmresp */
+ memcpy(lmresp, entropy, 8);
+
+ /* Pad with zeros */
+ memset(lmresp + 8, 0, 0x10);
+
+ /* Fill tmp with challenge(nonce?) + entropy */
+ memcpy(tmp, &ntlm->nonce[0], 8);
+ memcpy(tmp + 8, entropy, 8);
+
+#ifdef USE_SSLEAY
+ MD5_Init(&MD5pw);
+ MD5_Update(&MD5pw, tmp, 16);
+ MD5_Final(md5sum, &MD5pw);
+#elif defined(USE_GNUTLS)
+ gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
+ gcry_md_write(MD5pw, tmp, MD5_DIGEST_LENGTH);
+ memcpy(md5sum, gcry_md_read (MD5pw, 0), MD5_DIGEST_LENGTH);
+ gcry_md_close(MD5pw);
+#elif defined(USE_NSS)
+ MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
+ PK11_DigestOp(MD5pw, tmp, 16);
+ PK11_DigestFinal(MD5pw, md5sum, &MD5len, MD5_DIGEST_LENGTH);
+ PK11_DestroyContext(MD5pw, PR_TRUE);
+#endif
+
+ /* We shall only use the first 8 bytes of md5sum, but the des
+ code in Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
+ if(CURLE_OUT_OF_MEMORY ==
+ Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer))
+ return CURLE_OUT_OF_MEMORY;
+ Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
+
+ /* End of NTLM2 Session code */
+ }
+ else
+#endif
+ {
+
+#if USE_NTRESPONSES
+ unsigned char ntbuffer[0x18];
+#endif
+ unsigned char lmbuffer[0x18];
+
+#if USE_NTRESPONSES
+ if(CURLE_OUT_OF_MEMORY ==
+ Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer))
+ return CURLE_OUT_OF_MEMORY;
+ Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
+#endif
+
+ Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer);
+ Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
+ /* A safer but less compatible alternative is:
+ * Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
+ * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
+ }
+
+ lmrespoff = 64; /* size of the message header */
+#if USE_NTRESPONSES
+ ntrespoff = lmrespoff + 0x18;
+ domoff = ntrespoff + 0x18;
+#else
+ domoff = lmrespoff + 0x18;
+#endif
+ useroff = domoff + domlen;
+ hostoff = useroff + userlen;
+
+ /* Create the big type-3 message binary blob */
+ size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
+ NTLMSSP_SIGNATURE "%c"
+ "\x03%c%c%c" /* 32-bit type = 3 */
+
+ "%c%c" /* LanManager length */
+ "%c%c" /* LanManager allocated space */
+ "%c%c" /* LanManager offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* NT-response length */
+ "%c%c" /* NT-response allocated space */
+ "%c%c" /* NT-response offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* domain length */
+ "%c%c" /* domain allocated space */
+ "%c%c" /* domain name offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* user length */
+ "%c%c" /* user allocated space */
+ "%c%c" /* user offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* host length */
+ "%c%c" /* host allocated space */
+ "%c%c" /* host offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* session key length (unknown purpose) */
+ "%c%c" /* session key allocated space (unknown purpose) */
+ "%c%c" /* session key offset (unknown purpose) */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c%c%c", /* flags */
+
+ /* domain string */
+ /* user string */
+ /* host string */
+ /* LanManager response */
+ /* NT response */
+
+ 0, /* zero termination */
+ 0, 0, 0, /* type-3 long, the 24 upper bits */
+
+ SHORTPAIR(0x18), /* LanManager response length, twice */
+ SHORTPAIR(0x18),
+ SHORTPAIR(lmrespoff),
+ 0x0, 0x0,
+
+#if USE_NTRESPONSES
+ SHORTPAIR(0x18), /* NT-response length, twice */
+ SHORTPAIR(0x18),
+ SHORTPAIR(ntrespoff),
+ 0x0, 0x0,
+#else
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+#endif
+ SHORTPAIR(domlen),
+ SHORTPAIR(domlen),
+ SHORTPAIR(domoff),
+ 0x0, 0x0,
+
+ SHORTPAIR(userlen),
+ SHORTPAIR(userlen),
+ SHORTPAIR(useroff),
+ 0x0, 0x0,
+
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostoff),
+ 0x0, 0x0,
+
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+
+ LONGQUARTET(ntlm->flags));
+
+ DEBUGASSERT(size == 64);
+ DEBUGASSERT(size == (size_t)lmrespoff);
+
+ /* We append the binary hashes */
+ if(size < (NTLM_BUFSIZE - 0x18)) {
+ memcpy(&ntlmbuf[size], lmresp, 0x18);
+ size += 0x18;
+ }
+
+ DEBUG_OUT({
+ fprintf(stderr, "**** TYPE3 header lmresp=");
+ ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
+ });
+
+#if USE_NTRESPONSES
+ if(size < (NTLM_BUFSIZE - 0x18)) {
+ DEBUGASSERT(size == (size_t)ntrespoff);
+ memcpy(&ntlmbuf[size], ntresp, 0x18);
+ size += 0x18;
+ }
+
+ DEBUG_OUT({
+ fprintf(stderr, "\n ntresp=");
+ ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18);
+ });
+
+#endif
+
+ DEBUG_OUT({
+ fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
+ LONGQUARTET(ntlm->flags), ntlm->flags);
+ ntlm_print_flags(stderr, ntlm->flags);
+ fprintf(stderr, "\n****\n");
+ });
+
+ /* Make sure that the domain, user and host strings fit in the
+ buffer before we copy them there. */
+ if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) {
+ failf(data, "user + domain + host name too big");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ DEBUGASSERT(size == domoff);
+ if(unicode)
+ unicodecpy(&ntlmbuf[size], domain, domlen / 2);
+ else
+ memcpy(&ntlmbuf[size], domain, domlen);
+
+ size += domlen;
+
+ DEBUGASSERT(size == useroff);
+ if(unicode)
+ unicodecpy(&ntlmbuf[size], user, userlen / 2);
+ else
+ memcpy(&ntlmbuf[size], user, userlen);
+
+ size += userlen;
+
+ DEBUGASSERT(size == hostoff);
+ if(unicode)
+ unicodecpy(&ntlmbuf[size], host, hostlen / 2);
+ else
+ memcpy(&ntlmbuf[size], host, hostlen);
+
+ size += hostlen;
+
+ /* Convert domain, user, and host to ASCII but leave the rest as-is */
+ res = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff],
+ size - domoff);
+ if(res)
+ return CURLE_CONV_FAILED;
+
+#endif
+
+ /* Return with binary blob encoded into base64 */
+ return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
+}
+
+#endif /* USE_NTLM */
diff --git a/lib/http_ntlm.h b/lib/curl_ntlm_msgs.h
index c7422d701..7acf7229f 100644
--- a/lib/http_ntlm.h
+++ b/lib/curl_ntlm_msgs.h
@@ -1,5 +1,5 @@
-#ifndef __HTTP_NTLM_H
-#define __HTTP_NTLM_H
+#ifndef HEADER_CURL_NTLM_MSGS_H
+#define HEADER_CURL_NTLM_MSGS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 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,26 +22,42 @@
*
***************************************************************************/
-typedef enum {
- CURLNTLM_NONE, /* not a ntlm */
- CURLNTLM_BAD, /* an ntlm, but one we don't like */
- CURLNTLM_FIRST, /* the first 401-reply we got with NTLM */
- CURLNTLM_FINE, /* an ntlm we act on */
-
- CURLNTLM_LAST /* last entry in this enum, don't use */
-} CURLntlm;
-
-/* this is for ntlm header input */
-CURLntlm Curl_input_ntlm(struct connectdata *conn, bool proxy,
- const char *header);
+#include "setup.h"
+
+#ifdef USE_NTLM
+
+/* This is to generate a base64 encoded NTLM type-1 message */
+CURLcode Curl_ntlm_create_type1_message(const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr,
+ size_t *outlen);
+
+/* This is to generate a base64 encoded NTLM type-3 message */
+CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr,
+ size_t *outlen);
+
+/* This is to decode a NTLM type-2 message */
+CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data,
+ const char* header,
+ struct ntlmdata* ntlm);
+
+/* This is to clean up the ntlm data structure */
+#ifdef USE_WINDOWS_SSPI
+void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm);
+#else
+#define Curl_ntlm_sspi_cleanup(x)
+#endif
-/* this is for creating ntlm header output */
-CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
+/* NTLM buffer fixed size, large enough for long user + host + domain */
+#define NTLM_BUFSIZE 1024
-void Curl_ntlm_cleanup(struct connectdata *conn);
-#ifndef USE_NTLM
-#define Curl_ntlm_cleanup(x)
-#endif
+/* Stuff only required for curl_ntlm_msgs.c */
+#ifdef BUILDING_CURL_NTLM_MSGS_C
/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */
@@ -146,4 +162,9 @@ void Curl_ntlm_cleanup(struct connectdata *conn);
#define NTLMFLAG_NEGOTIATE_56 (1<<31)
/* Indicates that 56-bit encryption is supported. */
-#endif
+
+#endif /* BUILDING_CURL_NTLM_MSGS_C */
+
+#endif /* USE_NTLM */
+
+#endif /* HEADER_CURL_NTLM_MSGS_H */
diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c
new file mode 100644
index 000000000..18d0d13f8
--- /dev/null
+++ b/lib/curl_ntlm_wb.c
@@ -0,0 +1,394 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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.
+ *
+ * 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 "setup.h"
+
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+
+/*
+ * NTLM details:
+ *
+ * http://davenport.sourceforge.net/ntlm.html
+ * http://www.innovation.ch/java/ntlm.html
+ */
+
+#define DEBUG_ME 0
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "select.h"
+#include "curl_ntlm_wb.h"
+#include "url.h"
+#include "strerror.h"
+#include "curl_memory.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#if DEBUG_ME
+# define DEBUG_OUT(x) x
+#else
+# define DEBUG_OUT(x) Curl_nop_stmt
+#endif
+
+/* Portable 'sclose_nolog' used only in child process instead of 'sclose'
+ to avoid fooling the socket leak detector */
+#if defined(HAVE_CLOSESOCKET)
+# define sclose_nolog(x) closesocket((x))
+#elif defined(HAVE_CLOSESOCKET_CAMEL)
+# define sclose_nolog(x) CloseSocket((x))
+#else
+# define sclose_nolog(x) close((x))
+#endif
+
+void Curl_ntlm_wb_cleanup(struct connectdata *conn)
+{
+ if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) {
+ sclose(conn->ntlm_auth_hlpr_socket);
+ conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
+ }
+
+ if(conn->ntlm_auth_hlpr_pid) {
+ int i;
+ for(i = 0; i < 4; i++) {
+ pid_t ret = waitpid(conn->ntlm_auth_hlpr_pid, NULL, WNOHANG);
+ if(ret == conn->ntlm_auth_hlpr_pid || errno == ECHILD)
+ break;
+ switch(i) {
+ case 0:
+ kill(conn->ntlm_auth_hlpr_pid, SIGTERM);
+ break;
+ case 1:
+ /* Give the process another moment to shut down cleanly before
+ bringing down the axe */
+ Curl_wait_ms(1);
+ break;
+ case 2:
+ kill(conn->ntlm_auth_hlpr_pid, SIGKILL);
+ break;
+ case 3:
+ break;
+ }
+ }
+ conn->ntlm_auth_hlpr_pid = 0;
+ }
+
+ Curl_safefree(conn->challenge_header);
+ conn->challenge_header = NULL;
+ Curl_safefree(conn->response_header);
+ conn->response_header = NULL;
+}
+
+static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
+{
+ curl_socket_t sockfds[2];
+ pid_t child_pid;
+ const char *username;
+ char *slash, *domain = NULL;
+ const char *ntlm_auth = NULL;
+ char *ntlm_auth_alloc = NULL;
+ int error;
+
+ /* Return if communication with ntlm_auth already set up */
+ if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD ||
+ conn->ntlm_auth_hlpr_pid)
+ return CURLE_OK;
+
+ username = userp;
+ slash = strpbrk(username, "\\/");
+ if(slash) {
+ if((domain = strdup(username)) == NULL)
+ return CURLE_OUT_OF_MEMORY;
+ slash = domain + (slash - username);
+ *slash = '\0';
+ username = username + (slash - domain) + 1;
+ }
+
+ /* For testing purposes, when DEBUGBUILD is defined and environment
+ variable CURL_NTLM_WB_FILE is set a fake_ntlm is used to perform
+ NTLM challenge/response which only accepts commands and output
+ strings pre-written in test case definitions */
+#ifdef DEBUGBUILD
+ ntlm_auth_alloc = curl_getenv("CURL_NTLM_WB_FILE");
+ if(ntlm_auth_alloc)
+ ntlm_auth = ntlm_auth_alloc;
+ else
+#endif
+ ntlm_auth = NTLM_WB_FILE;
+
+ if(access(ntlm_auth, X_OK) != 0) {
+ error = ERRNO;
+ failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s",
+ ntlm_auth, error, Curl_strerror(conn, error));
+ goto done;
+ }
+
+ if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
+ error = ERRNO;
+ failf(conn->data, "Could not open socket pair. errno %d: %s",
+ error, Curl_strerror(conn, error));
+ goto done;
+ }
+
+ child_pid = fork();
+ if(child_pid == -1) {
+ error = ERRNO;
+ sclose(sockfds[0]);
+ sclose(sockfds[1]);
+ failf(conn->data, "Could not fork. errno %d: %s",
+ error, Curl_strerror(conn, error));
+ goto done;
+ }
+ else if(!child_pid) {
+ /*
+ * child process
+ */
+
+ /* Don't use sclose in the child since it fools the socket leak detector */
+ sclose_nolog(sockfds[0]);
+ if(dup2(sockfds[1], STDIN_FILENO) == -1) {
+ error = ERRNO;
+ failf(conn->data, "Could not redirect child stdin. errno %d: %s",
+ error, Curl_strerror(conn, error));
+ exit(1);
+ }
+
+ if(dup2(sockfds[1], STDOUT_FILENO) == -1) {
+ error = ERRNO;
+ failf(conn->data, "Could not redirect child stdout. errno %d: %s",
+ error, Curl_strerror(conn, error));
+ exit(1);
+ }
+
+ if(domain)
+ execl(ntlm_auth, ntlm_auth,
+ "--helper-protocol", "ntlmssp-client-1",
+ "--use-cached-creds",
+ "--username", username,
+ "--domain", domain,
+ NULL);
+ else
+ execl(ntlm_auth, ntlm_auth,
+ "--helper-protocol", "ntlmssp-client-1",
+ "--use-cached-creds",
+ "--username", username,
+ NULL);
+
+ error = ERRNO;
+ sclose_nolog(sockfds[1]);
+ failf(conn->data, "Could not execl(). errno %d: %s",
+ error, Curl_strerror(conn, error));
+ exit(1);
+ }
+
+ sclose(sockfds[1]);
+ conn->ntlm_auth_hlpr_socket = sockfds[0];
+ conn->ntlm_auth_hlpr_pid = child_pid;
+ Curl_safefree(domain);
+ Curl_safefree(ntlm_auth_alloc);
+ return CURLE_OK;
+
+done:
+ Curl_safefree(domain);
+ Curl_safefree(ntlm_auth_alloc);
+ return CURLE_REMOTE_ACCESS_DENIED;
+}
+
+static CURLcode ntlm_wb_response(struct connectdata *conn,
+ const char *input, curlntlm state)
+{
+ ssize_t size;
+ char buf[200]; /* enough, type 1, 3 message length is less then 200 */
+ char *tmpbuf = buf;
+ size_t len_in = strlen(input), len_out = sizeof(buf);
+
+ while(len_in > 0) {
+ ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in);
+ if(written == -1) {
+ /* Interrupted by a signal, retry it */
+ if(errno == EINTR)
+ continue;
+ /* write failed if other errors happen */
+ goto done;
+ }
+ input += written;
+ len_in -= written;
+ }
+ /* Read one line */
+ while(len_out > 0) {
+ size = sread(conn->ntlm_auth_hlpr_socket, tmpbuf, len_out);
+ if(size == -1) {
+ if(errno == EINTR)
+ continue;
+ goto done;
+ }
+ else if(size == 0)
+ goto done;
+ else if(tmpbuf[size - 1] == '\n') {
+ tmpbuf[size - 1] = '\0';
+ goto wrfinish;
+ }
+ tmpbuf += size;
+ len_out -= size;
+ }
+ goto done;
+wrfinish:
+ /* Samba/winbind installed but not configured */
+ if(state == NTLMSTATE_TYPE1 &&
+ size == 3 &&
+ buf[0] == 'P' && buf[1] == 'W')
+ return CURLE_REMOTE_ACCESS_DENIED;
+ /* invalid response */
+ if(size < 4)
+ goto done;
+ if(state == NTLMSTATE_TYPE1 &&
+ (buf[0]!='Y' || buf[1]!='R' || buf[2]!=' '))
+ goto done;
+ if(state == NTLMSTATE_TYPE2 &&
+ (buf[0]!='K' || buf[1]!='K' || buf[2]!=' ') &&
+ (buf[0]!='A' || buf[1]!='F' || buf[2]!=' '))
+ goto done;
+
+ conn->response_header = aprintf("NTLM %.*s", size - 4, buf + 3);
+ return CURLE_OK;
+done:
+ return CURLE_REMOTE_ACCESS_DENIED;
+}
+
+/*
+ * This is for creating ntlm header output by delegating challenge/response
+ * to Samba's winbind daemon helper ntlm_auth.
+ */
+CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
+ bool proxy)
+{
+ /* point to the address of the pointer that holds the string to send to the
+ server, which is for a plain host or for a HTTP proxy */
+ char **allocuserpwd;
+ /* point to the name and password for this */
+ const char *userp;
+ /* point to the correct struct with this */
+ struct ntlmdata *ntlm;
+ struct auth *authp;
+
+ CURLcode res = CURLE_OK;
+ char *input;
+
+ DEBUGASSERT(conn);
+ DEBUGASSERT(conn->data);
+
+ if(proxy) {
+ allocuserpwd = &conn->allocptr.proxyuserpwd;
+ userp = conn->proxyuser;
+ ntlm = &conn->proxyntlm;
+ authp = &conn->data->state.authproxy;
+ }
+ else {
+ allocuserpwd = &conn->allocptr.userpwd;
+ userp = conn->user;
+ ntlm = &conn->ntlm;
+ authp = &conn->data->state.authhost;
+ }
+ authp->done = FALSE;
+
+ /* not set means empty */
+ if(!userp)
+ userp="";
+
+ switch(ntlm->state) {
+ case NTLMSTATE_TYPE1:
+ default:
+ /* Use Samba's 'winbind' daemon to support NTLM authentication,
+ * by delegating the NTLM challenge/response protocal to a helper
+ * in ntlm_auth.
+ * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html
+ * http://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html
+ * http://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html
+ * Preprocessor symbol 'NTLM_WB_ENABLED' is defined when this
+ * feature is enabled and 'NTLM_WB_FILE' symbol holds absolute
+ * filename of ntlm_auth helper.
+ * If NTLM authentication using winbind fails, go back to original
+ * request handling process.
+ */
+ /* Create communication with ntlm_auth */
+ res = ntlm_wb_init(conn, userp);
+ if(res)
+ return res;
+ res = ntlm_wb_response(conn, "YR\n", ntlm->state);
+ if(res)
+ return res;
+
+ Curl_safefree(*allocuserpwd);
+ *allocuserpwd = aprintf("%sAuthorization: %s\r\n",
+ proxy ? "Proxy-" : "",
+ conn->response_header);
+ DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
+ Curl_safefree(conn->response_header);
+ conn->response_header = NULL;
+ break;
+ case NTLMSTATE_TYPE2:
+ input = aprintf("TT %s", conn->challenge_header);
+ if(!input)
+ return CURLE_OUT_OF_MEMORY;
+ res = ntlm_wb_response(conn, input, ntlm->state);
+ free(input);
+ input = NULL;
+ if(res)
+ return res;
+
+ Curl_safefree(*allocuserpwd);
+ *allocuserpwd = aprintf("%sAuthorization: %s\r\n",
+ proxy ? "Proxy-" : "",
+ conn->response_header);
+ DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
+ ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
+ authp->done = TRUE;
+ Curl_ntlm_wb_cleanup(conn);
+ break;
+ case NTLMSTATE_TYPE3:
+ /* connection is already authenticated,
+ * don't send a header in future requests */
+ if(*allocuserpwd) {
+ free(*allocuserpwd);
+ *allocuserpwd=NULL;
+ }
+ authp->done = TRUE;
+ break;
+ }
+
+ return CURLE_OK;
+}
+
+#endif /* USE_NTLM && NTLM_WB_ENABLED */
diff --git a/lib/curl_ntlm_wb.h b/lib/curl_ntlm_wb.h
new file mode 100644
index 000000000..e3eaffe17
--- /dev/null
+++ b/lib/curl_ntlm_wb.h
@@ -0,0 +1,37 @@
+#ifndef HEADER_CURL_NTLM_WB_H
+#define HEADER_CURL_NTLM_WB_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, 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.
+ *
+ * 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 "setup.h"
+
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+
+/* this is for creating ntlm header output by delegating challenge/response
+ to Samba's winbind daemon helper ntlm_auth */
+CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy);
+
+void Curl_ntlm_wb_cleanup(struct connectdata *conn);
+
+#endif /* USE_NTLM && NTLM_WB_ENABLED */
+
+#endif /* HEADER_CURL_NTLM_WB_H */
diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c
index 44b7e1524..725b8f995 100644
--- a/lib/curl_rtmp.c
+++ b/lib/curl_rtmp.c
@@ -71,6 +71,7 @@ const struct Curl_handler Curl_handler_rtmp = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -90,6 +91,7 @@ const struct Curl_handler Curl_handler_rtmpt = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -109,6 +111,7 @@ const struct Curl_handler Curl_handler_rtmpe = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -128,6 +131,7 @@ const struct Curl_handler Curl_handler_rtmpte = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -147,6 +151,7 @@ const struct Curl_handler Curl_handler_rtmps = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -166,6 +171,7 @@ const struct Curl_handler Curl_handler_rtmpts = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
diff --git a/lib/curl_threads.c b/lib/curl_threads.c
index e9636440f..411ccc81d 100644
--- a/lib/curl_threads.c
+++ b/lib/curl_threads.c
@@ -19,6 +19,7 @@
* KIND, either express or implied.
*
***************************************************************************/
+
#include "setup.h"
#if defined(USE_THREADS_POSIX)
diff --git a/lib/cyassl.c b/lib/cyassl.c
index 81bcabaa1..cda18a8cb 100644
--- a/lib/cyassl.c
+++ b/lib/cyassl.c
@@ -27,16 +27,17 @@
*/
#include "setup.h"
+
#ifdef USE_CYASSL
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
-
#include "urldata.h"
#include "sendf.h"
#include "inet_pton.h"
@@ -412,7 +413,7 @@ int Curl_cyassl_init(void)
bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex)
{
if(conn->ssl[connindex].handle) /* SSL is in use */
- return (bool)(0 != SSL_pending(conn->ssl[connindex].handle));
+ return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
else
return FALSE;
}
diff --git a/lib/cyassl.h b/lib/cyassl.h
index a21592a28..56d68066f 100644
--- a/lib/cyassl.h
+++ b/lib/cyassl.h
@@ -21,6 +21,7 @@
* KIND, either express or implied.
*
***************************************************************************/
+#include "setup.h"
#ifdef USE_CYASSL
@@ -45,7 +46,7 @@ CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn,
/* API setup for CyaSSL */
#define curlssl_init Curl_cyassl_init
-#define curlssl_cleanup()
+#define curlssl_cleanup() Curl_nop_stmt
#define curlssl_connect Curl_cyassl_connect
#define curlssl_connect_nonblocking Curl_cyassl_connect_nonblocking
#define curlssl_session_free(x) Curl_cyassl_session_free(x)
diff --git a/lib/dict.c b/lib/dict.c
index 0baaeec3a..b326054d1 100644
--- a/lib/dict.c
+++ b/lib/dict.c
@@ -24,28 +24,18 @@
#ifndef CURL_DISABLE_DICT
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#ifdef WIN32
-#include <time.h>
-#include <io.h>
-#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
+#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef HAVE_NETDB_H
#include <netdb.h>
+#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
@@ -64,9 +54,6 @@
#include <sys/select.h>
#endif
-
-#endif
-
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
@@ -105,6 +92,7 @@ const struct Curl_handler Curl_handler_dict = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
diff --git a/lib/easy.c b/lib/easy.c
index ac037d266..60a55edf8 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -22,29 +22,12 @@
#include "setup.h"
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "strequal.h"
-
-#ifdef WIN32
-#include <time.h>
-#include <io.h>
-#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -65,8 +48,7 @@
#include <sys/param.h>
#endif
-#endif /* WIN32 ... */
-
+#include "strequal.h"
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
@@ -81,7 +63,7 @@
#include "easyif.h"
#include "select.h"
#include "sendf.h" /* for failf function prototype */
-#include "http_ntlm.h"
+#include "curl_ntlm.h"
#include "connect.h" /* for Curl_getconnectinfo */
#include "slist.h"
#include "curl_rand.h"
@@ -143,6 +125,8 @@ static CURLcode win32_init(void)
return CURLE_FAILED_INIT;
}
/* The Windows Sockets DLL is acceptable. Proceed. */
+#elif defined(USE_LWIPSOCK)
+ lwip_init();
#endif
#ifdef USE_WINDOWS_SSPI
@@ -692,16 +676,15 @@ CURL *curl_easy_duphandle(CURL *incurl)
if(outcurl) {
if(outcurl->state.connc &&
- (outcurl->state.connc->type == CONNCACHE_PRIVATE))
+ (outcurl->state.connc->type == CONNCACHE_PRIVATE)) {
Curl_rm_connc(outcurl->state.connc);
- if(outcurl->state.headerbuff)
- free(outcurl->state.headerbuff);
- if(outcurl->change.cookielist)
- curl_slist_free_all(outcurl->change.cookielist);
- if(outcurl->change.url)
- free(outcurl->change.url);
- if(outcurl->change.referer)
- free(outcurl->change.referer);
+ outcurl->state.connc = NULL;
+ }
+ curl_slist_free_all(outcurl->change.cookielist);
+ outcurl->change.cookielist = NULL;
+ Curl_safefree(outcurl->state.headerbuff);
+ Curl_safefree(outcurl->change.url);
+ Curl_safefree(outcurl->change.referer);
Curl_freeset(outcurl);
free(outcurl);
}
@@ -718,10 +701,10 @@ void curl_easy_reset(CURL *curl)
struct SessionHandle *data = (struct SessionHandle *)curl;
Curl_safefree(data->state.pathbuffer);
- data->state.pathbuffer=NULL;
+
+ data->state.path = NULL;
Curl_safefree(data->state.proto.generic);
- data->state.proto.generic=NULL;
/* zero out UserDefined data: */
Curl_freeset(data);
diff --git a/lib/escape.c b/lib/escape.c
index 5500a92bf..b0922bc93 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -24,12 +24,9 @@
* allocated string or NULL if an error occurred. */
#include "setup.h"
-#include <ctype.h>
+
#include <curl/curl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include "curl_memory.h"
#include "urldata.h"
#include "warnless.h"
diff --git a/lib/file.c b/lib/file.c
index 4f3ea1bb4..00d5fc09b 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -23,27 +23,13 @@
#include "setup.h"
#ifndef CURL_DISABLE_FILE
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#ifdef WIN32
-#include <time.h>
-#include <io.h>
-#include <fcntl.h>
-#else
+
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -68,8 +54,6 @@
#include <fcntl.h>
#endif
-#endif /* WIN32 */
-
#include "strtoofft.h"
#include "urldata.h"
#include <curl/curl.h>
@@ -83,6 +67,7 @@
#include "url.h"
#include "curl_memory.h"
#include "parsedate.h" /* for the week day and month names */
+#include "warnless.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@@ -109,6 +94,9 @@ static CURLcode file_do(struct connectdata *, bool *done);
static CURLcode file_done(struct connectdata *conn,
CURLcode status, bool premature);
static CURLcode file_connect(struct connectdata *conn, bool *done);
+static CURLcode file_disconnect(struct connectdata *conn,
+ bool dead_connection);
+
/*
* FILE scheme handler.
@@ -125,8 +113,9 @@ const struct Curl_handler Curl_handler_file = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
- ZERO_NULL, /* disconnect */
+ file_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
0, /* defport */
CURLPROTO_FILE, /* protocol */
@@ -222,10 +211,9 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
/* file is not a protocol that can deal with "persistancy" */
file = data->state.proto.file;
Curl_safefree(file->freepath);
+ file->path = NULL;
if(file->fd != -1)
close(file->fd);
- file->path = NULL;
- file->freepath = NULL;
file->fd = -1;
}
@@ -282,10 +270,31 @@ static CURLcode file_done(struct connectdata *conn,
struct FILEPROTO *file = conn->data->state.proto.file;
(void)status; /* not used */
(void)premature; /* not used */
- Curl_safefree(file->freepath);
- if(file->fd != -1)
- close(file->fd);
+ if(file) {
+ Curl_safefree(file->freepath);
+ file->path = NULL;
+ if(file->fd != -1)
+ close(file->fd);
+ file->fd = -1;
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode file_disconnect(struct connectdata *conn,
+ bool dead_connection)
+{
+ struct FILEPROTO *file = conn->data->state.proto.file;
+ (void)dead_connection; /* not used */
+
+ if(file) {
+ Curl_safefree(file->freepath);
+ file->path = NULL;
+ if(file->fd != -1)
+ close(file->fd);
+ file->fd = -1;
+ }
return CURLE_OK;
}
@@ -438,7 +447,6 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
curl_off_t expected_size=0;
bool fstated=FALSE;
ssize_t nread;
- size_t bytestoread;
struct SessionHandle *data = conn->data;
char *buf = data->state.buffer;
curl_off_t bytecount = 0;
@@ -560,7 +568,10 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
while(res == CURLE_OK) {
/* Don't fill a whole buffer if we want less than all data */
- bytestoread = (expected_size < BUFSIZE-1)?(size_t)expected_size:BUFSIZE-1;
+ size_t bytestoread =
+ (expected_size < CURL_OFF_T_C(BUFSIZE) - CURL_OFF_T_C(1)) ?
+ curlx_sotouz(expected_size) : BUFSIZE - 1;
+
nread = read(fd, buf, bytestoread);
if(nread > 0)
diff --git a/lib/fileinfo.c b/lib/fileinfo.c
index 5495f560d..4ffcbbe29 100644
--- a/lib/fileinfo.c
+++ b/lib/fileinfo.c
@@ -22,7 +22,6 @@
#include "setup.h"
-#include <stdlib.h>
#include "strdup.h"
#include "fileinfo.h"
@@ -49,9 +48,7 @@ void Curl_fileinfo_dtor(void *user, void *element)
if(!finfo)
return;
- if(finfo->b_data){
- free(finfo->b_data);
- }
+ Curl_safefree(finfo->b_data);
free(finfo);
}
diff --git a/lib/formdata.c b/lib/formdata.c
index aa5a79ac1..cbef51171 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -21,6 +21,7 @@
***************************************************************************/
#include "setup.h"
+
#include <curl/curl.h>
/* Length of the random boundary string. */
@@ -28,14 +29,10 @@
#if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY)
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <time.h>
#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
#include <libgen.h>
#endif
+
#include "urldata.h" /* for struct SessionHandle */
#include "formdata.h"
#include "curl_rand.h"
@@ -462,7 +459,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
if(current_form->flags & HTTPPOST_FILENAME) {
if(filename) {
if((current_form = AddFormInfo(strdup(filename),
- NULL, current_form)) == NULL)
+ NULL, current_form)) == NULL)
return_value = CURL_FORMADD_MEMORY;
}
else
@@ -487,46 +484,18 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
break;
}
- case CURLFORM_BUFFER:
- {
- const char *filename = array_state?array_value:
- va_arg(params, char *);
-
- if(current_form->value) {
- if(current_form->flags & HTTPPOST_BUFFER) {
- if(filename) {
- if((current_form = AddFormInfo(strdup(filename),
- NULL, current_form)) == NULL)
- return_value = CURL_FORMADD_MEMORY;
- }
- else
- return_value = CURL_FORMADD_NULL;
- }
- else
- return_value = CURL_FORMADD_OPTION_TWICE;
- }
- else {
- if(filename) {
- current_form->value = strdup(filename);
- if(!current_form->value)
- return_value = CURL_FORMADD_MEMORY;
- }
- else
- return_value = CURL_FORMADD_NULL;
- current_form->flags |= HTTPPOST_BUFFER;
- }
- break;
- }
-
case CURLFORM_BUFFERPTR:
- current_form->flags |= HTTPPOST_PTRBUFFER;
+ current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
if(current_form->buffer)
return_value = CURL_FORMADD_OPTION_TWICE;
else {
char *buffer =
array_state?array_value:va_arg(params, char *);
- if(buffer)
+ if(buffer) {
current_form->buffer = buffer; /* store for the moment */
+ current_form->value = buffer; /* make it non-NULL to be accepted
+ as fine */
+ }
else
return_value = CURL_FORMADD_NULL;
}
@@ -567,8 +536,8 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
if(current_form->flags & HTTPPOST_FILENAME) {
if(contenttype) {
if((current_form = AddFormInfo(NULL,
- strdup(contenttype),
- current_form)) == NULL)
+ strdup(contenttype),
+ current_form)) == NULL)
return_value = CURL_FORMADD_MEMORY;
}
else
@@ -606,6 +575,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
break;
}
case CURLFORM_FILENAME:
+ case CURLFORM_BUFFER:
{
const char *filename = array_state?array_value:
va_arg(params, char *);
@@ -622,6 +592,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
}
default:
return_value = CURL_FORMADD_UNKNOWN_OPTION;
+ break;
}
}
@@ -884,10 +855,11 @@ int curl_formget(struct curl_httppost *form, void *arg,
do {
nread = readfromfile(&temp, buffer, sizeof(buffer));
- if((nread == (size_t) -1) || (nread != append(arg, buffer, nread))) {
- if(temp.fp) {
+ if((nread == (size_t) -1) ||
+ (nread > sizeof(buffer)) ||
+ (nread != append(arg, buffer, nread))) {
+ if(temp.fp)
fclose(temp.fp);
- }
Curl_formclean(&data);
return -1;
}
@@ -925,7 +897,8 @@ void curl_formfree(struct curl_httppost *form)
if(!(form->flags & HTTPPOST_PTRNAME) && form->name)
free(form->name); /* free the name */
- if(!(form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_CALLBACK)) &&
+ if(!(form->flags &
+ (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) &&
form->contents)
free(form->contents); /* free the contents */
if(form->contenttype)
@@ -1297,22 +1270,24 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata )
return 0;
}
+/*
+ * readfromfile()
+ *
+ * The read callback that this function may use can return a value larger than
+ * 'size' (which then this function returns) that indicates a problem and it
+ * must be properly dealt with
+ */
static size_t readfromfile(struct Form *form, char *buffer,
size_t size)
{
size_t nread;
- bool callback = (bool)(form->data->type == FORM_CALLBACK);
+ bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE;
if(callback) {
if(form->fread_func == ZERO_NULL)
return 0;
else
nread = form->fread_func(buffer, 1, size, form->data->line);
-
- if(nread > size)
- /* the read callback can return a value larger than the buffer but
- treat any such as no data in this case */
- nread = 0;
}
else {
if(!form->fp) {
diff --git a/lib/ftp.c b/lib/ftp.c
index d758301f5..12b41ecc5 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -23,11 +23,6 @@
#include "setup.h"
#ifndef CURL_DISABLE_FTP
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -109,7 +104,7 @@
#endif
#ifdef CURL_DISABLE_VERBOSE_STRINGS
-#define ftp_pasv_verbose(a,b,c,d) do { } while(0)
+#define ftp_pasv_verbose(a,b,c,d) Curl_nop_stmt
#endif
/* Local API functions */
@@ -139,9 +134,10 @@ static CURLcode ftp_connect(struct connectdata *conn, bool *done);
static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection);
static CURLcode ftp_nextconnect(struct connectdata *conn);
static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done);
-static int ftp_getsock(struct connectdata *conn,
- curl_socket_t *socks,
+static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks,
int numsocks);
+static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
static CURLcode ftp_doing(struct connectdata *conn,
bool *dophase_done);
static CURLcode ftp_setup_connection(struct connectdata * conn);
@@ -176,6 +172,7 @@ const struct Curl_handler Curl_handler_ftp = {
ftp_doing, /* doing */
ftp_getsock, /* proto_getsock */
ftp_getsock, /* doing_getsock */
+ ftp_domore_getsock, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -201,6 +198,7 @@ const struct Curl_handler Curl_handler_ftps = {
ftp_doing, /* doing */
ftp_getsock, /* proto_getsock */
ftp_getsock, /* doing_getsock */
+ ftp_domore_getsock, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -227,6 +225,7 @@ static const struct Curl_handler Curl_handler_ftp_proxy = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -252,6 +251,7 @@ static const struct Curl_handler Curl_handler_ftps_proxy = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -279,7 +279,7 @@ static void freedirs(struct ftp_conn *ftpc)
{
int i;
if(ftpc->dirs) {
- for(i=0; i < ftpc->dirdepth; i++){
+ for(i=0; i < ftpc->dirdepth; i++) {
if(ftpc->dirs[i]) {
free(ftpc->dirs[i]);
ftpc->dirs[i]=NULL;
@@ -303,8 +303,8 @@ static void freedirs(struct ftp_conn *ftpc)
*/
static bool isBadFtpString(const char *string)
{
- return (bool)((NULL != strchr(string, '\r')) ||
- (NULL != strchr(string, '\n')));
+ return ((NULL != strchr(string, '\r')) ||
+ (NULL != strchr(string, '\n'))) ? TRUE : FALSE;
}
/***********************************************************************
@@ -639,6 +639,37 @@ static int ftp_getsock(struct connectdata *conn,
return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
}
+/* For the FTP "DO_MORE" phase only */
+static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks)
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if(!numsocks)
+ return GETSOCK_BLANK;
+
+ /* When in DO_MORE state, we could be either waiting for us to connect to a
+ remote site, or we could wait for that site to connect to us. Or just
+ handle ordinary commands.
+
+ When waiting for a connect, we will be in FTP_STOP state and then we wait
+ for the secondary socket to become writeable. If we're in another state,
+ we're still handling commands on the control (primary) connection.
+
+ */
+
+ switch(ftpc->state) {
+ case FTP_STOP:
+ break;
+ default:
+ return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
+ }
+
+ socks[0] = conn->sock[SECONDARYSOCKET];
+
+ return GETSOCK_READSOCK(0);
+}
+
/* This is called after the FTP_QUOTE state is passed.
ftp_state_cwd() sends the range of CWD commands to the server to change to
@@ -810,7 +841,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
host = addr;
else
host = hbuf; /* use the hbuf for host name */
- }else
+ }
+ else
/* there was only a port(-range) given, default the host */
host = NULL;
} /* data->set.ftpport */
@@ -857,7 +889,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
free(addr);
if(res == NULL) {
- failf(data, "Curl_resolv failed, we can not recover!");
+ failf(data, "failed to resolve the address provided to PORT: %s", host);
return CURLE_FTP_PORT_FAILED;
}
@@ -1004,8 +1036,16 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd],
sa->sa_family == AF_INET?1:2,
myhost, port);
- if(result)
+ if(result) {
+ failf(data, "Failure sending EPRT command: %s",
+ curl_easy_strerror(result));
+ Curl_closesocket(conn, portsock);
+ /* don't retry using PORT */
+ ftpc->count1 = PORT;
+ /* bail out */
+ state(conn, FTP_STOP);
return result;
+ }
break;
}
else if(PORT == fcmd) {
@@ -1025,8 +1065,14 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
snprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp);
- if(result)
+ if(result) {
+ failf(data, "Failure sending PORT command: %s",
+ curl_easy_strerror(result));
+ Curl_closesocket(conn, portsock);
+ /* bail out */
+ state(conn, FTP_STOP);
return result;
+ }
break;
}
}
@@ -1048,7 +1094,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
The *proper* fix is to make sure that the active connection from the
server is done in a non-blocking way. Currently, it is still BLOCKING.
*/
- conn->bits.tcpconnect = TRUE;
+ conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
state(conn, FTP_PORT);
return result;
@@ -1234,13 +1280,16 @@ static CURLcode ftp_state_post_listtype(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY;
}
- PPSENDF(&conn->proto.ftpc.pp, "%s",cmd);
+ result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd);
if(lstArg)
free(lstArg);
free(cmd);
+ if(result != CURLE_OK)
+ return result;
+
state(conn, FTP_LIST);
return result;
@@ -1708,7 +1757,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
if(result)
return result;
- conn->bits.tcpconnect = connected; /* simply TRUE or FALSE */
+ conn->bits.tcpconnect[SECONDARYSOCKET] = connected;
/*
* When this is used from the multi interface, this might've returned with
@@ -1746,6 +1795,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
break;
}
+ if(result)
+ return result;
+
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
/* FIX: this MUST wait for a proper connect first if 'connected' is
* FALSE */
@@ -1768,10 +1820,11 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
data->state.proto.ftp = ftp_save;
- if(CURLE_OK != result)
+ if(result)
return result;
}
+ conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
state(conn, FTP_STOP); /* this phase is completed */
@@ -2528,7 +2581,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if(ftpcode/100 == 2)
/* We have enabled SSL for the data connection! */
conn->ssl[SECONDARYSOCKET].use =
- (bool)(data->set.ftp_ssl != CURLUSESSL_CONTROL);
+ (data->set.ftp_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE;
/* FTP servers typically responds with 500 if they decide to reject
our 'P' request */
else if(data->set.ftp_ssl > CURLUSESSL_CONTROL)
@@ -2604,12 +2657,6 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
store++;
ptr++;
}
- if(ftpc->entrypath)
- free(ftpc->entrypath);
- ftpc->entrypath =dir; /* remember this */
- infof(data, "Entry path is '%s'\n", ftpc->entrypath);
- /* also save it where getinfo can access it: */
- data->state.most_recent_ftp_entrypath = ftpc->entrypath;
/* If the path name does not look like an absolute path (i.e.: it
does not start with a '/'), we probably need some server-dependent
@@ -2623,11 +2670,27 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if the path name looks strange to minimize overhead on other
systems. */
- if(!ftpc->server_os && ftpc->entrypath[0] != '/') {
- PPSENDF(&ftpc->pp, "SYST", NULL);
+ if(!ftpc->server_os && dir[0] != '/') {
+
+ result = Curl_pp_sendf(&ftpc->pp, "SYST", NULL);
+ if(result != CURLE_OK) {
+ free(dir);
+ return result;
+ }
+ Curl_safefree(ftpc->entrypath);
+ ftpc->entrypath = dir; /* remember this */
+ infof(data, "Entry path is '%s'\n", ftpc->entrypath);
+ /* also save it where getinfo can access it: */
+ data->state.most_recent_ftp_entrypath = ftpc->entrypath;
state(conn, FTP_SYST);
break;
}
+
+ Curl_safefree(ftpc->entrypath);
+ ftpc->entrypath = dir; /* remember this */
+ infof(data, "Entry path is '%s'\n", ftpc->entrypath);
+ /* also save it where getinfo can access it: */
+ data->state.most_recent_ftp_entrypath = ftpc->entrypath;
}
else {
/* couldn't get the path */
@@ -2657,19 +2720,28 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
for(store = os; *ptr && *ptr != ' ';)
*store++ = *ptr++;
*store = '\0'; /* zero terminate */
- ftpc->server_os = os;
/* Check for special servers here. */
- if(strequal(ftpc->server_os, "OS/400")) {
+ if(strequal(os, "OS/400")) {
/* Force OS400 name format 1. */
- PPSENDF(&ftpc->pp, "SITE NAMEFMT 1", NULL);
+ result = Curl_pp_sendf(&ftpc->pp, "SITE NAMEFMT 1", NULL);
+ if(result != CURLE_OK) {
+ free(os);
+ return result;
+ }
+ /* remember target server OS */
+ Curl_safefree(ftpc->server_os);
+ ftpc->server_os = os;
state(conn, FTP_NAMEFMT);
break;
}
- else {
- /* Nothing special for the target server. */
- }
+ else {
+ /* Nothing special for the target server. */
+ /* remember target server OS */
+ Curl_safefree(ftpc->server_os);
+ ftpc->server_os = os;
+ }
}
else {
/* Cannot identify server OS. Continue anyway and cross fingers. */
@@ -2820,7 +2892,7 @@ static CURLcode ftp_multi_statemach(struct connectdata *conn,
/* Check for the state outside of the Curl_socket_ready() return code checks
since at times we are in fact already in this state when this function
gets called. */
- *done = (bool)(ftpc->state == FTP_STOP);
+ *done = (ftpc->state == FTP_STOP) ? TRUE : FALSE;
return result;
}
@@ -2874,9 +2946,9 @@ static CURLcode ftp_init(struct connectdata *conn)
*/
ftp->user = conn->user;
ftp->passwd = conn->passwd;
- if(TRUE == isBadFtpString(ftp->user))
+ if(isBadFtpString(ftp->user))
return CURLE_URL_MALFORMAT;
- if(TRUE == isBadFtpString(ftp->passwd))
+ if(isBadFtpString(ftp->passwd))
return CURLE_URL_MALFORMAT;
conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
@@ -3478,7 +3550,7 @@ CURLcode ftp_perform(struct connectdata *conn,
result = ftp_easy_statemach(conn);
*dophase_done = TRUE; /* with the easy interface we are done here */
}
- *connected = conn->bits.tcpconnect;
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done)
DEBUGF(infof(conn->data, "DO phase is complete\n"));
@@ -3631,8 +3703,7 @@ static CURLcode wc_statemach(struct connectdata *conn)
strcat(tmp_path, finfo->filename);
/* switch default "state.pathbuffer" and tmp_path, good to see
ftp_parse_url_path function to understand this trick */
- if(conn->data->state.pathbuffer)
- free(conn->data->state.pathbuffer);
+ Curl_safefree(conn->data->state.pathbuffer);
conn->data->state.pathbuffer = tmp_path;
conn->data->state.path = tmp_path;
@@ -4099,12 +4170,13 @@ static CURLcode ftp_dophase_done(struct connectdata *conn,
/* called from multi.c while DOing */
static CURLcode ftp_doing(struct connectdata *conn,
- bool *dophase_done)
+ bool *dophase_done)
{
- CURLcode result;
- result = ftp_multi_statemach(conn, dophase_done);
+ CURLcode result = ftp_multi_statemach(conn, dophase_done);
- if(*dophase_done) {
+ if(result)
+ DEBUGF(infof(conn->data, "DO phase failed\n"));
+ else if(*dophase_done) {
result = ftp_dophase_done(conn, FALSE /* not connected */);
DEBUGF(infof(conn->data, "DO phase is complete\n"));
diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c
index a3fef3971..bbf6e9ef9 100644
--- a/lib/ftplistparser.c
+++ b/lib/ftplistparser.c
@@ -37,8 +37,6 @@
#include "setup.h"
-#include <time.h>
-
#include "ftplistparser.h"
#include "curl_fnmatch.h"
diff --git a/lib/getenv.c b/lib/getenv.c
index 36fbb7583..6b40dd68d 100644
--- a/lib/getenv.c
+++ b/lib/getenv.c
@@ -22,10 +22,6 @@
#include "setup.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
#ifdef __VMS
#include <unixlib.h>
#endif
diff --git a/lib/getinfo.c b/lib/getinfo.c
index bb289741a..aa7af2c86 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -27,10 +27,6 @@
#include "urldata.h"
#include "getinfo.h"
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
#include "curl_memory.h"
#include "sslgen.h"
#include "connect.h" /* Curl_getconnectinfo() */
diff --git a/lib/gopher.c b/lib/gopher.c
index b2d2689d1..b4efae8cc 100644
--- a/lib/gopher.c
+++ b/lib/gopher.c
@@ -24,28 +24,18 @@
#ifndef CURL_DISABLE_GOPHER
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#ifdef WIN32
-#include <time.h>
-#include <io.h>
-#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
+#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef HAVE_NETDB_H
#include <netdb.h>
+#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
@@ -64,9 +54,6 @@
#include <sys/select.h>
#endif
-
-#endif
-
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
@@ -110,6 +97,7 @@ const struct Curl_handler Curl_handler_gopher = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
diff --git a/lib/gtls.c b/lib/gtls.c
index a376fb0b9..7ca46c812 100644
--- a/lib/gtls.c
+++ b/lib/gtls.c
@@ -29,14 +29,13 @@
*/
#include "setup.h"
+
#ifdef USE_GNUTLS
+
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <gcrypt.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -477,8 +476,10 @@ gtls_connect_step1(struct connectdata *conn,
gnutls_transport_set_push_function(session, Curl_gtls_push);
gnutls_transport_set_pull_function(session, Curl_gtls_pull);
+#if GNUTLS_VERSION_NUMBER < 0x020c00
/* lowat must be set to zero when using custom push and pull functions. */
gnutls_transport_set_lowat(session, 0);
+#endif
/* This might be a reconnect, so we check for a session ID in the cache
to speed up things */
diff --git a/lib/gtls.h b/lib/gtls.h
index 6275b49a3..733122e6c 100644
--- a/lib/gtls.h
+++ b/lib/gtls.h
@@ -1,5 +1,5 @@
-#ifndef __GTLS_H
-#define __GTLS_H
+#ifndef HEADER_CURL_GTLS_H
+#define HEADER_CURL_GTLS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -22,8 +22,12 @@
*
***************************************************************************/
+#include "setup.h"
+
#ifdef USE_GNUTLS
+#include "urldata.h"
+
int Curl_gtls_init(void);
int Curl_gtls_cleanup(void);
CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex);
@@ -60,4 +64,4 @@ int Curl_gtls_seed(struct SessionHandle *data);
#define curlssl_data_pending(x,y) (x=x, y=y, 0)
#endif /* USE_GNUTLS */
-#endif
+#endif /* HEADER_CURL_GTLS_H */
diff --git a/lib/hash.c b/lib/hash.c
index 6c921e442..3704eea41 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -22,9 +22,6 @@
#include "setup.h"
-#include <string.h>
-#include <stdlib.h>
-
#include "hash.h"
#include "llist.h"
@@ -41,11 +38,14 @@ hash_element_dtor(void *user, void *element)
struct curl_hash *h = (struct curl_hash *) user;
struct curl_hash_element *e = (struct curl_hash_element *) element;
- if(e->key)
- free(e->key);
+ Curl_safefree(e->key);
- if(e->ptr)
+ if(e->ptr) {
h->dtor(e->ptr);
+ e->ptr = NULL;
+ }
+
+ e->key_len = 0;
free(e);
}
@@ -75,16 +75,22 @@ Curl_hash_init(struct curl_hash *h,
for(i = 0; i < slots; ++i) {
h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
if(!h->table[i]) {
- while(i--)
+ while(i--) {
Curl_llist_destroy(h->table[i], NULL);
+ h->table[i] = NULL;
+ }
free(h->table);
+ h->table = NULL;
+ h->slots = 0;
return 1; /* failure */
}
}
return 0; /* fine */
}
- else
+ else {
+ h->slots = 0;
return 1; /* failure */
+ }
}
struct curl_hash *
@@ -190,6 +196,7 @@ int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len)
he = le->ptr;
if(h->comp_func(he->key, he->key_len, key, key_len)) {
Curl_llist_remove(l, le, (void *) h);
+ --h->size;
return 0;
}
}
@@ -243,6 +250,9 @@ Curl_hash_clean(struct curl_hash *h)
}
free(h->table);
+ h->table = NULL;
+ h->size = 0;
+ h->slots = 0;
}
void
diff --git a/lib/hostasyn.c b/lib/hostasyn.c
index 50f6b01fb..771562fd1 100644
--- a/lib/hostasyn.c
+++ b/lib/hostasyn.c
@@ -22,8 +22,6 @@
#include "setup.h"
-#include <string.h>
-
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -36,16 +34,12 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h> /* required for free() prototypes */
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
-#include <stdlib.h>
#endif
#ifdef HAVE_PROCESS_H
diff --git a/lib/hostip.c b/lib/hostip.c
index 084ee86ac..d261a163a 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -22,8 +22,6 @@
#include "setup.h"
-#include <string.h>
-
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -36,16 +34,12 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h> /* required for free() prototypes */
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
-#include <stdlib.h>
#endif
#ifdef HAVE_SETJMP_H
@@ -560,6 +554,10 @@ int Curl_resolv_timeout(struct connectdata *conn,
*entry = NULL;
+ if(timeoutms < 0)
+ /* got an already expired timeout */
+ return CURLRESOLV_TIMEDOUT;
+
#ifdef USE_ALARM_TIMEOUT
if(data->set.no_signal)
/* Ignore the timeout when signals are disabled */
diff --git a/lib/hostip4.c b/lib/hostip4.c
index 67aefda29..1a5e26585 100644
--- a/lib/hostip4.c
+++ b/lib/hostip4.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 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,6 @@
#include "setup.h"
-#include <string.h>
-#include <errno.h>
-
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -37,16 +34,12 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h> /* required for free() prototypes */
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
-#include <stdlib.h>
#endif
#ifdef HAVE_PROCESS_H
diff --git a/lib/hostip6.c b/lib/hostip6.c
index b944401c5..8241cb4bc 100644
--- a/lib/hostip6.c
+++ b/lib/hostip6.c
@@ -22,8 +22,6 @@
#include "setup.h"
-#include <string.h>
-
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -36,16 +34,12 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h> /* required for free() prototypes */
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
-#include <stdlib.h>
#endif
#ifdef HAVE_PROCESS_H
@@ -160,7 +154,7 @@ static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
}
}
#else
-#define dump_addrinfo(x,y)
+#define dump_addrinfo(x,y) Curl_nop_stmt
#endif
/*
diff --git a/lib/hostsyn.c b/lib/hostsyn.c
index a5e97658e..b60188708 100644
--- a/lib/hostsyn.c
+++ b/lib/hostsyn.c
@@ -22,8 +22,6 @@
#include "setup.h"
-#include <string.h>
-
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -36,16 +34,12 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h> /* required for free() prototypes */
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
-#include <stdlib.h>
#endif
#ifdef HAVE_PROCESS_H
diff --git a/lib/http.c b/lib/http.c
index 56d263b91..f85cd6c55 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -23,32 +23,13 @@
#include "setup.h"
#ifndef CURL_DISABLE_HTTP
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#ifdef WIN32
-#include <time.h>
-#include <io.h>
-#else
+
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#ifdef HAVE_TIME_H
-#ifdef TIME_WITH_SYS_TIME
-#include <time.h>
-#endif
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -70,8 +51,6 @@
#include <sys/param.h>
#endif
-#endif
-
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
@@ -83,7 +62,8 @@
#include "strequal.h"
#include "sslgen.h"
#include "http_digest.h"
-#include "http_ntlm.h"
+#include "curl_ntlm.h"
+#include "curl_ntlm_wb.h"
#include "http_negotiate.h"
#include "url.h"
#include "share.h"
@@ -138,6 +118,7 @@ const struct Curl_handler Curl_handler_http = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
http_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -161,6 +142,7 @@ const struct Curl_handler Curl_handler_https = {
ZERO_NULL, /* doing */
https_getsock, /* proto_getsock */
http_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -252,11 +234,13 @@ static char *copy_header_value(const char *h)
*/
static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
{
- char *authorization;
- struct SessionHandle *data=conn->data;
+ size_t size = 0;
+ char *authorization = NULL;
+ struct SessionHandle *data = conn->data;
char **userp;
const char *user;
const char *pwd;
+ CURLcode error;
if(proxy) {
userp = &conn->allocptr.proxyuserpwd;
@@ -270,20 +254,24 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
}
snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
- if(Curl_base64_encode(data, data->state.buffer,
- strlen(data->state.buffer),
- &authorization) > 0) {
- if(*userp)
- free(*userp);
- *userp = aprintf( "%sAuthorization: Basic %s\r\n",
- proxy?"Proxy-":"",
- authorization);
- free(authorization);
- if(!*userp)
- return CURLE_OUT_OF_MEMORY;
- }
- else
+
+ error = Curl_base64_encode(data,
+ data->state.buffer, strlen(data->state.buffer),
+ &authorization, &size);
+ if(error)
+ return error;
+
+ if(!authorization)
+ return CURLE_REMOTE_ACCESS_DENIED;
+
+ Curl_safefree(*userp);
+ *userp = aprintf("%sAuthorization: Basic %s\r\n",
+ proxy?"Proxy-":"",
+ authorization);
+ free(authorization);
+ if(!*userp)
return CURLE_OUT_OF_MEMORY;
+
return CURLE_OK;
}
@@ -307,6 +295,8 @@ static bool pickoneauth(struct auth *pick)
pick->picked = CURLAUTH_DIGEST;
else if(avail & CURLAUTH_NTLM)
pick->picked = CURLAUTH_NTLM;
+ else if(avail & CURLAUTH_NTLM_WB)
+ pick->picked = CURLAUTH_NTLM_WB;
else if(avail & CURLAUTH_BASIC)
pick->picked = CURLAUTH_BASIC;
else {
@@ -393,15 +383,19 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
if((expectsend == -1) || (expectsend > bytessent)) {
/* There is still data left to send */
if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
- (data->state.authhost.picked == CURLAUTH_NTLM)) {
+ (data->state.authhost.picked == CURLAUTH_NTLM) ||
+ (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
+ (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
if(((expectsend - bytessent) < 2000) ||
(conn->ntlm.state != NTLMSTATE_NONE)) {
/* The NTLM-negotiation has started *OR* there is just a little (<2K)
data left to send, keep on sending. */
/* rewind data when completely done sending! */
- if(!conn->bits.authneg)
+ if(!conn->bits.authneg) {
conn->bits.rewindaftersend = TRUE;
+ infof(data, "Rewind stream after send\n");
+ }
return CURLE_OK;
}
@@ -554,6 +548,15 @@ output_auth_headers(struct connectdata *conn,
}
else
#endif
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+ if(authstatus->picked == CURLAUTH_NTLM_WB) {
+ auth="NTLM_WB";
+ result = Curl_output_ntlm_wb(conn, proxy);
+ if(result)
+ return result;
+ }
+ else
+#endif
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(authstatus->picked == CURLAUTH_DIGEST) {
auth="Digest";
@@ -587,7 +590,7 @@ output_auth_headers(struct connectdata *conn,
proxy?"Proxy":"Server", auth,
proxy?(conn->proxyuser?conn->proxyuser:""):
(conn->user?conn->user:""));
- authstatus->multi = (bool)(!authstatus->done);
+ authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
}
else
authstatus->multi = FALSE;
@@ -730,73 +733,73 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
*
*/
+ while(*start) {
#ifdef USE_HTTP_NEGOTIATE
- if(checkprefix("GSS-Negotiate", start) ||
- checkprefix("Negotiate", start)) {
- int neg;
- *availp |= CURLAUTH_GSSNEGOTIATE;
- authp->avail |= CURLAUTH_GSSNEGOTIATE;
-
- if(data->state.negotiate.state == GSS_AUTHSENT) {
- /* if we sent GSS authentication in the outgoing request and we get this
- back, we're in trouble */
- infof(data, "Authentication problem. Ignoring this.\n");
- data->state.authproblem = TRUE;
- }
- else {
- neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
- if(neg == 0) {
- DEBUGASSERT(!data->req.newurl);
- data->req.newurl = strdup(data->change.url);
- if(!data->req.newurl)
- return CURLE_OUT_OF_MEMORY;
- data->state.authproblem = FALSE;
- /* we received GSS auth info and we dealt with it fine */
- data->state.negotiate.state = GSS_AUTHRECV;
- }
- else {
+ if(checkprefix("GSS-Negotiate", start) ||
+ checkprefix("Negotiate", start)) {
+ int neg;
+ *availp |= CURLAUTH_GSSNEGOTIATE;
+ authp->avail |= CURLAUTH_GSSNEGOTIATE;
+
+ if(data->state.negotiate.state == GSS_AUTHSENT) {
+ /* if we sent GSS authentication in the outgoing request and we get
+ this back, we're in trouble */
+ infof(data, "Authentication problem. Ignoring this.\n");
data->state.authproblem = TRUE;
}
- }
- }
- else
-#endif
-#ifdef USE_NTLM
- /* NTLM support requires the SSL crypto libs */
- if(checkprefix("NTLM", start)) {
- *availp |= CURLAUTH_NTLM;
- authp->avail |= CURLAUTH_NTLM;
- if(authp->picked == CURLAUTH_NTLM) {
- /* NTLM authentication is picked and activated */
- CURLntlm ntlm =
- Curl_input_ntlm(conn, (bool)(httpcode == 407), start);
-
- if(CURLNTLM_BAD != ntlm)
+ else {
+ neg = Curl_input_negotiate(conn, (httpcode == 407)?TRUE:FALSE, start);
+ if(neg == 0) {
+ DEBUGASSERT(!data->req.newurl);
+ data->req.newurl = strdup(data->change.url);
+ if(!data->req.newurl)
+ return CURLE_OUT_OF_MEMORY;
data->state.authproblem = FALSE;
+ /* we received GSS auth info and we dealt with it fine */
+ data->state.negotiate.state = GSS_AUTHRECV;
+ }
else {
- infof(data, "Authentication problem. Ignoring this.\n");
data->state.authproblem = TRUE;
}
}
}
else
#endif
-#ifndef CURL_DISABLE_CRYPTO_AUTH
- if(checkprefix("Digest", start)) {
- if((authp->avail & CURLAUTH_DIGEST) != 0) {
- infof(data, "Ignoring duplicate digest auth header.\n");
- }
- else {
- CURLdigest dig;
- *availp |= CURLAUTH_DIGEST;
- authp->avail |= CURLAUTH_DIGEST;
-
- /* We call this function on input Digest headers even if Digest
- * authentication isn't activated yet, as we need to store the
- * incoming data from this header in case we are gonna use Digest. */
- dig = Curl_input_digest(conn, (bool)(httpcode == 407), start);
-
- if(CURLDIGEST_FINE != dig) {
+#ifdef USE_NTLM
+ /* NTLM support requires the SSL crypto libs */
+ if(checkprefix("NTLM", start)) {
+ *availp |= CURLAUTH_NTLM;
+ authp->avail |= CURLAUTH_NTLM;
+ if(authp->picked == CURLAUTH_NTLM ||
+ authp->picked == CURLAUTH_NTLM_WB) {
+ /* NTLM authentication is picked and activated */
+ CURLcode ntlm =
+ Curl_input_ntlm(conn, (httpcode == 407)?TRUE:FALSE, start);
+ if(CURLE_OK == ntlm) {
+ data->state.authproblem = FALSE;
+#ifdef NTLM_WB_ENABLED
+ if(authp->picked == CURLAUTH_NTLM_WB) {
+ *availp &= ~CURLAUTH_NTLM;
+ authp->avail &= ~CURLAUTH_NTLM;
+ *availp |= CURLAUTH_NTLM_WB;
+ authp->avail |= CURLAUTH_NTLM_WB;
+
+ /* Get the challenge-message which will be passed to
+ * ntlm_auth for generating the type 3 message later */
+ while(*start && ISSPACE(*start))
+ start++;
+ if(checkprefix("NTLM", start)) {
+ start += strlen("NTLM");
+ while(*start && ISSPACE(*start))
+ start++;
+ if(*start)
+ if((conn->challenge_header = strdup(start)) == NULL)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+#endif
+ }
+ else {
infof(data, "Authentication problem. Ignoring this.\n");
data->state.authproblem = TRUE;
}
@@ -804,19 +807,51 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
}
else
#endif
- if(checkprefix("Basic", start)) {
- *availp |= CURLAUTH_BASIC;
- authp->avail |= CURLAUTH_BASIC;
- if(authp->picked == CURLAUTH_BASIC) {
- /* We asked for Basic authentication but got a 40X back
- anyway, which basically means our name+password isn't
- valid. */
- authp->avail = CURLAUTH_NONE;
- infof(data, "Authentication problem. Ignoring this.\n");
- data->state.authproblem = TRUE;
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ if(checkprefix("Digest", start)) {
+ if((authp->avail & CURLAUTH_DIGEST) != 0) {
+ infof(data, "Ignoring duplicate digest auth header.\n");
+ }
+ else {
+ CURLdigest dig;
+ *availp |= CURLAUTH_DIGEST;
+ authp->avail |= CURLAUTH_DIGEST;
+
+ /* We call this function on input Digest headers even if Digest
+ * authentication isn't activated yet, as we need to store the
+ * incoming data from this header in case we are gonna use
+ * Digest. */
+ dig = Curl_input_digest(conn, (httpcode == 407)?TRUE:FALSE, start);
+
+ if(CURLDIGEST_FINE != dig) {
+ infof(data, "Authentication problem. Ignoring this.\n");
+ data->state.authproblem = TRUE;
+ }
+ }
}
- }
+ else
+#endif
+ if(checkprefix("Basic", start)) {
+ *availp |= CURLAUTH_BASIC;
+ authp->avail |= CURLAUTH_BASIC;
+ if(authp->picked == CURLAUTH_BASIC) {
+ /* We asked for Basic authentication but got a 40X back
+ anyway, which basically means our name+password isn't
+ valid. */
+ authp->avail = CURLAUTH_NONE;
+ infof(data, "Authentication problem. Ignoring this.\n");
+ data->state.authproblem = TRUE;
+ }
+ }
+ /* there may be multiple methods on one line, so keep reading */
+ while(*start && *start != ',') /* read up to the next comma */
+ start++;
+ if(*start == ',') /* if we're on a comma, skip it */
+ start++;
+ while(*start && ISSPACE(*start))
+ start++;
+ }
return CURLE_OK;
}
@@ -923,7 +958,7 @@ static size_t readmoredata(char *buffer,
return 0;
/* make sure that a HTTP request is never sent away chunked! */
- conn->data->req.forbidchunk = (bool)(http->sending == HTTPSEND_REQUEST);
+ conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
if(http->postsize <= (curl_off_t)fullsize) {
memcpy(buffer, http->postdata, (size_t)http->postsize);
@@ -1456,11 +1491,11 @@ CURLcode Curl_http_done(struct connectdata *conn,
static bool use_http_1_1(const struct SessionHandle *data,
const struct connectdata *conn)
{
- return (bool)((data->set.httpversion == CURL_HTTP_VERSION_1_1) ||
+ return ((data->set.httpversion == CURL_HTTP_VERSION_1_1) ||
((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
((conn->httpversion == 11) ||
((conn->httpversion != 10) &&
- (data->state.httpversion != 10)))));
+ (data->state.httpversion != 10))))) ? TRUE : FALSE;
}
/* check and possibly add an Expect: header */
@@ -1536,6 +1571,31 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
}
}
}
+ else {
+ ptr = strchr(headers->data, ';');
+ if(ptr) {
+
+ ptr++; /* pass the semicolon */
+ while(*ptr && ISSPACE(*ptr))
+ ptr++;
+
+ if(*ptr) {
+ /* this may be used for something else in the future */
+ }
+ else {
+ if(*(--ptr) == ';') {
+ CURLcode result;
+
+ /* send no-value custom header if terminated by semicolon */
+ *ptr = ':';
+ result = Curl_add_bufferf(req_buffer, "%s\r\n",
+ headers->data);
+ if(result)
+ return result;
+ }
+ }
+ }
+ }
headers = headers->next;
}
return CURLE_OK;
@@ -1615,7 +1675,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
curl_off_t included_body = 0;
const char *httpstring;
Curl_send_buffer *req_buffer;
- curl_off_t postsize; /* off_t type to be able to hold a large file size */
+ curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
int seekerr = CURL_SEEKFUNC_OK;
/* Always consider the DO phase done after this function call, even if there
@@ -1648,6 +1708,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(!data->state.first_host)
return CURLE_OUT_OF_MEMORY;
}
+ http->writebytecount = http->readbytecount = 0;
if((conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_FTP)) &&
data->set.upload) {
@@ -1754,8 +1815,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
else {
if((conn->handler->protocol&CURLPROTO_HTTP) &&
- data->set.upload &&
- (data->set.infilesize == -1)) {
+ data->set.upload &&
+ (data->set.infilesize == -1)) {
if(conn->bits.authneg)
/* don't enable chunked during auth neg */
;
@@ -1863,8 +1924,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
memcpy(newurl + newlen + (ptr - url),
ptr + currlen, /* copy the trailing zero byte too */
urllen - (ptr-url) - currlen + 1);
- if(data->change.url_alloc)
- free(data->change.url);
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
data->change.url = newurl;
data->change.url_alloc = TRUE;
}
@@ -1933,7 +1996,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
* This is meant to get the size of the present remote-file by itself.
* We don't support this now. Bail out!
*/
- data->state.resume_from = 0;
+ data->state.resume_from = 0;
}
if(data->state.resume_from && !data->state.this_is_a_follow) {
@@ -2024,17 +2087,17 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
curl_off_t total_expected_size=
data->state.resume_from + data->set.infilesize;
conn->allocptr.rangeline =
- aprintf("Content-Range: bytes %s%" FORMAT_OFF_T
- "/%" FORMAT_OFF_T "\r\n",
- data->state.range, total_expected_size-1,
- total_expected_size);
+ aprintf("Content-Range: bytes %s%" FORMAT_OFF_T
+ "/%" FORMAT_OFF_T "\r\n",
+ data->state.range, total_expected_size-1,
+ total_expected_size);
}
else {
/* Range was selected and then we just pass the incoming range and
append total size */
conn->allocptr.rangeline =
- aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n",
- data->state.range, data->set.infilesize);
+ aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n",
+ data->state.range, data->set.infilesize);
}
if(!conn->allocptr.rangeline)
return CURLE_OUT_OF_MEMORY;
@@ -2067,45 +2130,47 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(result)
return result;
- result = Curl_add_bufferf(req_buffer,
- "%s" /* ftp typecode (;type=x) */
- " HTTP/%s\r\n" /* HTTP version */
- "%s" /* proxyuserpwd */
- "%s" /* userpwd */
- "%s" /* range */
- "%s" /* user agent */
- "%s" /* host */
- "%s" /* accept */
- "%s" /* TE: */
- "%s" /* accept-encoding */
- "%s" /* referer */
- "%s" /* Proxy-Connection */
- "%s",/* transfer-encoding */
-
- ftp_typecode,
- httpstring,
- conn->allocptr.proxyuserpwd?
- conn->allocptr.proxyuserpwd:"",
- conn->allocptr.userpwd?conn->allocptr.userpwd:"",
- (data->state.use_range && conn->allocptr.rangeline)?
- conn->allocptr.rangeline:"",
- (data->set.str[STRING_USERAGENT] &&
- *data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)?
- conn->allocptr.uagent:"",
- (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */
- http->p_accept?http->p_accept:"",
- conn->allocptr.te?conn->allocptr.te:"",
- (data->set.str[STRING_ENCODING] &&
- *data->set.str[STRING_ENCODING] &&
- conn->allocptr.accept_encoding)?
- conn->allocptr.accept_encoding:"",
- (data->change.referer && conn->allocptr.ref)?
- conn->allocptr.ref:"" /* Referer: <data> */,
- (conn->bits.httpproxy &&
- !conn->bits.tunnel_proxy &&
- !Curl_checkheaders(data, "Proxy-Connection:"))?
- "Proxy-Connection: Keep-Alive\r\n":"",
- te
+ result =
+ Curl_add_bufferf(req_buffer,
+ "%s" /* ftp typecode (;type=x) */
+ " HTTP/%s\r\n" /* HTTP version */
+ "%s" /* proxyuserpwd */
+ "%s" /* userpwd */
+ "%s" /* range */
+ "%s" /* user agent */
+ "%s" /* host */
+ "%s" /* accept */
+ "%s" /* TE: */
+ "%s" /* accept-encoding */
+ "%s" /* referer */
+ "%s" /* Proxy-Connection */
+ "%s",/* transfer-encoding */
+
+ ftp_typecode,
+ httpstring,
+ conn->allocptr.proxyuserpwd?
+ conn->allocptr.proxyuserpwd:"",
+ conn->allocptr.userpwd?conn->allocptr.userpwd:"",
+ (data->state.use_range && conn->allocptr.rangeline)?
+ conn->allocptr.rangeline:"",
+ (data->set.str[STRING_USERAGENT] &&
+ *data->set.str[STRING_USERAGENT] &&
+ conn->allocptr.uagent)?
+ conn->allocptr.uagent:"",
+ (conn->allocptr.host?conn->allocptr.host:""),
+ http->p_accept?http->p_accept:"",
+ conn->allocptr.te?conn->allocptr.te:"",
+ (data->set.str[STRING_ENCODING] &&
+ *data->set.str[STRING_ENCODING] &&
+ conn->allocptr.accept_encoding)?
+ conn->allocptr.accept_encoding:"",
+ (data->change.referer && conn->allocptr.ref)?
+ conn->allocptr.ref:"" /* Referer: <data> */,
+ (conn->bits.httpproxy &&
+ !conn->bits.tunnel_proxy &&
+ !Curl_checkheaders(data, "Proxy-Connection:"))?
+ "Proxy-Connection: Keep-Alive\r\n":"",
+ te
);
/*
@@ -2130,8 +2195,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.cookiehost?
conn->allocptr.cookiehost:host,
data->state.path,
- (bool)(conn->handler->protocol&CURLPROTO_HTTPS?
- TRUE:FALSE));
+ (conn->handler->protocol&CURLPROTO_HTTPS)?
+ TRUE:FALSE);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
if(co) {
@@ -2145,8 +2210,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
break;
}
result = Curl_add_bufferf(req_buffer,
- "%s%s=%s", count?"; ":"",
- co->name, co->value);
+ "%s%s=%s", count?"; ":"",
+ co->name, co->value);
if(result)
break;
count++;
@@ -2160,8 +2225,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
result = Curl_add_bufferf(req_buffer, "Cookie: ");
if(CURLE_OK == result) {
result = Curl_add_bufferf(req_buffer, "%s%s",
- count?"; ":"",
- addcookies);
+ count?"; ":"",
+ addcookies);
count++;
}
}
@@ -2228,11 +2293,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
http->sending = HTTPSEND_BODY;
- if(!data->req.upload_chunky) {
+ if(!data->req.upload_chunky &&
+ !Curl_checkheaders(data, "Content-Length:")) {
/* only add Content-Length if not uploading chunked */
result = Curl_add_bufferf(req_buffer,
- "Content-Length: %" FORMAT_OFF_T "\r\n",
- http->postsize);
+ "Content-Length: %" FORMAT_OFF_T "\r\n",
+ http->postsize);
if(result)
return result;
}
@@ -2299,11 +2365,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
else
postsize = data->set.infilesize;
- if((postsize != -1) && !data->req.upload_chunky) {
+ if((postsize != -1) && !data->req.upload_chunky &&
+ !Curl_checkheaders(data, "Content-Length:")) {
/* only add Content-Length if not uploading chunked */
result = Curl_add_bufferf(req_buffer,
- "Content-Length: %" FORMAT_OFF_T "\r\n",
- postsize );
+ "Content-Length: %" FORMAT_OFF_T "\r\n",
+ postsize );
if(result)
return result;
}
@@ -2353,8 +2420,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */
result = Curl_add_bufferf(req_buffer,
- "Content-Length: %" FORMAT_OFF_T"\r\n",
- postsize);
+ "Content-Length: %" FORMAT_OFF_T"\r\n",
+ postsize);
if(result)
return result;
}
@@ -2404,7 +2471,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* We're not sending it 'chunked', append it to the request
already now to reduce the number if send() calls */
result = Curl_add_buffer(req_buffer, data->set.postfields,
- (size_t)postsize);
+ (size_t)postsize);
included_body = postsize;
}
else {
@@ -2412,10 +2479,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
if(CURLE_OK == result)
result = Curl_add_buffer(req_buffer, data->set.postfields,
- (size_t)postsize);
+ (size_t)postsize);
if(CURLE_OK == result)
result = Curl_add_buffer(req_buffer,
- "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
+ "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
/* CR LF 0 CR LF CR LF */
included_body = postsize + 7;
}
@@ -2451,7 +2518,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* Chunky upload is selected and we're negotiating auth still, send
end-of-data only */
result = Curl_add_buffer(req_buffer,
- "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
+ "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7);
/* CR LF 0 CR LF CR LF */
if(result)
return result;
@@ -2508,6 +2575,17 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
Curl_pgrsSetUploadCounter(data, http->writebytecount);
if(Curl_pgrsUpdate(conn))
result = CURLE_ABORTED_BY_CALLBACK;
+
+ if(http->writebytecount >= postsize) {
+ /* already sent the entire request body, mark the "upload" as
+ complete */
+ infof(data, "upload completely sent off: %" FORMAT_OFF_T " out of "
+ "%" FORMAT_OFF_T " bytes\n",
+ http->writebytecount, postsize);
+ data->req.upload_done = TRUE;
+ data->req.keepon &= ~KEEP_SEND; /* we're done writing */
+ data->req.exp100 = EXP100_SEND_DATA; /* already sent */
+ }
}
return result;
@@ -2547,7 +2625,7 @@ checkhttpprefix(struct SessionHandle *data,
head = head->next;
}
- if((rc != TRUE) && (checkprefix("HTTP/", s)))
+ if(!rc && (checkprefix("HTTP/", s)))
rc = TRUE;
#ifdef CURL_DOES_CONVERSIONS
@@ -2779,17 +2857,6 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
}
}
- if(417 == k->httpcode) {
- /*
- * we got: "417 Expectation Failed" this means:
- * we have made a HTTP call and our Expect Header
- * seems to cause a problem => abort the write operations
- * (or prevent them from starting).
- */
- k->exp100 = EXP100_FAILED;
- k->keepon &= ~KEEP_SEND;
- }
-
/*
* When all the headers have been parsed, see if we should give
* up and return an error.
@@ -2829,6 +2896,46 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
if(result)
return result;
+ if(k->httpcode >= 300) {
+ if((!conn->bits.authneg) && !conn->bits.close &&
+ !conn->bits.rewindaftersend) {
+ /*
+ * General treatment of errors when about to send data. Including :
+ * "417 Expectation Failed", while waiting for 100-continue.
+ *
+ * The check for close above is done simply because of something
+ * else has already deemed the connection to get closed then
+ * something else should've considered the big picture and we
+ * avoid this check.
+ *
+ * rewindaftersend indicates that something has told libcurl to
+ * continue sending even if it gets discarded
+ */
+
+ switch(data->set.httpreq) {
+ case HTTPREQ_PUT:
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ /* We got an error response. If this happened before the whole
+ * request body has been sent we stop sending and mark the
+ * connection for closure after we've read the entire response.
+ */
+ if(!k->upload_done) {
+ infof(data, "HTTP error before end of send, stop sending\n");
+ conn->bits.close = TRUE; /* close after this */
+ k->upload_done = TRUE;
+ k->keepon &= ~KEEP_SEND; /* don't send */
+ if(data->state.expect100header)
+ k->exp100 = EXP100_FAILED;
+ }
+ break;
+
+ default: /* default label present to avoid compiler warnings */
+ break;
+ }
+ }
+ }
+
if(conn->bits.rewindaftersend) {
/* We rewind after a complete send, so thus we continue
sending now */
@@ -2929,23 +3036,23 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
if(conn->handler->protocol & CURLPROTO_HTTP) {
nc = sscanf(HEADER1,
- " HTTP/%d.%d %3d",
- &httpversion_major,
- &conn->httpversion,
- &k->httpcode);
+ " HTTP/%d.%d %3d",
+ &httpversion_major,
+ &conn->httpversion,
+ &k->httpcode);
if(nc==3) {
conn->httpversion += 10 * httpversion_major;
}
else {
/* this is the real world, not a Nirvana
NCSA 1.5.x returns this crap when asked for HTTP/1.1
- */
+ */
nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
conn->httpversion = 10;
/* If user has set option HTTP200ALIASES,
compare header line against list of aliases
- */
+ */
if(!nc) {
if(checkhttpprefix(data, k->p)) {
nc = 1;
diff --git a/lib/http_chunks.c b/lib/http_chunks.c
index 93de1d968..d6a0bec13 100644
--- a/lib/http_chunks.c
+++ b/lib/http_chunks.c
@@ -19,15 +19,10 @@
* KIND, either express or implied.
*
***************************************************************************/
+
#include "setup.h"
#ifndef CURL_DISABLE_HTTP
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
#include "urldata.h" /* it includes http_chunks.h */
#include "sendf.h" /* for the client write stuff */
@@ -84,9 +79,9 @@
We avoid the use of isxdigit to accommodate non-ASCII hosts. */
static bool Curl_isxdigit(char digit)
{
- return (bool)( (digit >= 0x30 && digit <= 0x39) /* 0-9 */
- || (digit >= 0x41 && digit <= 0x46) /* A-F */
- || (digit >= 0x61 && digit <= 0x66) ); /* a-f */
+ return ( (digit >= 0x30 && digit <= 0x39) /* 0-9 */
+ || (digit >= 0x41 && digit <= 0x46) /* A-F */
+ || (digit >= 0x61 && digit <= 0x66) /* a-f */ ) ? TRUE : FALSE;
}
void Curl_httpchunk_init(struct connectdata *conn)
diff --git a/lib/http_digest.c b/lib/http_digest.c
index c3a39fcee..b41e62306 100644
--- a/lib/http_digest.c
+++ b/lib/http_digest.c
@@ -19,15 +19,10 @@
* KIND, either express or implied.
*
***************************************************************************/
+
#include "setup.h"
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
#include "urldata.h"
#include "sendf.h"
@@ -285,7 +280,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
unsigned char *ha1;
unsigned char ha2[33];/* 32 digits and 1 zero byte */
char cnoncebuf[7];
- char *cnonce;
+ char *cnonce = NULL;
+ size_t cnonce_sz = 0;
char *tmp = NULL;
struct timeval now;
@@ -348,10 +344,12 @@ CURLcode Curl_output_digest(struct connectdata *conn,
/* Generate a cnonce */
now = Curl_tvnow();
snprintf(cnoncebuf, sizeof(cnoncebuf), "%06ld", (long)now.tv_sec);
- if(Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), &cnonce))
- d->cnonce = cnonce;
- else
- return CURLE_OUT_OF_MEMORY;
+
+ rc = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf),
+ &cnonce, &cnonce_sz);
+ if(rc)
+ return rc;
+ d->cnonce = cnonce;
}
/*
diff --git a/lib/http_digest.h b/lib/http_digest.h
index 75fcba929..3b22ce10e 100644
--- a/lib/http_digest.h
+++ b/lib/http_digest.h
@@ -1,5 +1,5 @@
-#ifndef __HTTP_DIGEST_H
-#define __HTTP_DIGEST_H
+#ifndef HEADER_CURL_HTTP_DIGEST_H
+#define HEADER_CURL_HTTP_DIGEST_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -21,6 +21,7 @@
* KIND, either express or implied.
*
***************************************************************************/
+#include "setup.h"
typedef enum {
CURLDIGEST_NONE, /* not a digest */
@@ -50,7 +51,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
void Curl_digest_cleanup(struct SessionHandle *data);
#else
-#define Curl_digest_cleanup(x) do {} while(0)
+#define Curl_digest_cleanup(x) Curl_nop_stmt
#endif
-#endif
+#endif /* HEADER_CURL_HTTP_DIGEST_H */
diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c
index 5127e6480..4e68ab762 100644
--- a/lib/http_negotiate.c
+++ b/lib/http_negotiate.c
@@ -19,27 +19,25 @@
* KIND, either express or implied.
*
***************************************************************************/
+
#include "setup.h"
#ifdef HAVE_GSSAPI
#ifdef HAVE_OLD_GSSMIT
#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
+#define NCOMPAT 1
#endif
#ifndef CURL_DISABLE_HTTP
- /* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
#include "urldata.h"
#include "sendf.h"
+#include "curl_gssapi.h"
#include "rawstr.h"
#include "curl_base64.h"
#include "http_negotiate.h"
#include "curl_memory.h"
+#include "url.h"
#ifdef HAVE_SPNEGO
# include <spnegohelp.h>
@@ -134,15 +132,18 @@ log_gss_error(struct connectdata *conn, OM_uint32 error_status,
int Curl_input_negotiate(struct connectdata *conn, bool proxy,
const char *header)
{
- struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
- &conn->data->state.negotiate;
+ struct SessionHandle *data = conn->data;
+ struct negotiatedata *neg_ctx = proxy?&data->state.proxyneg:
+ &data->state.negotiate;
OM_uint32 major_status, minor_status, minor_status2;
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
int ret;
- size_t len, rawlen;
+ size_t len;
+ size_t rawlen = 0;
bool gss;
const char* protocol;
+ CURLcode error;
while(*header && ISSPACE(*header))
header++;
@@ -171,7 +172,7 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
/* 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(conn->data);
+ Curl_cleanup_negotiate(data);
return -1;
}
@@ -185,9 +186,9 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
len = strlen(header);
if(len > 0) {
- rawlen = Curl_base64_decode(header,
- (unsigned char **)&input_token.value);
- if(rawlen == 0)
+ error = Curl_base64_decode(header,
+ (unsigned char **)&input_token.value, &rawlen);
+ if(error || rawlen == 0)
return -1;
input_token.length = rawlen;
@@ -220,7 +221,7 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
NULL)) {
free(spnegoToken);
spnegoToken = NULL;
- infof(conn->data, "Parse SPNEGO Target Token failed\n");
+ infof(data, "Parse SPNEGO Target Token failed\n");
}
else {
free(input_token.value);
@@ -232,30 +233,25 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
input_token.length = mechTokenLength;
free(mechToken);
mechToken = NULL;
- infof(conn->data, "Parse SPNEGO Target Token succeeded\n");
+ infof(data, "Parse SPNEGO Target Token succeeded\n");
}
}
#endif
}
- major_status = gss_init_sec_context(&minor_status,
- GSS_C_NO_CREDENTIAL,
- &neg_ctx->context,
- neg_ctx->server_name,
- GSS_C_NO_OID,
- 0,
- 0,
- GSS_C_NO_CHANNEL_BINDINGS,
- &input_token,
- NULL,
- &output_token,
- NULL,
- NULL);
+ major_status = Curl_gss_init_sec_context(data,
+ &minor_status,
+ &neg_ctx->context,
+ neg_ctx->server_name,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &input_token,
+ &output_token,
+ NULL);
if(input_token.length > 0)
gss_release_buffer(&minor_status2, &input_token);
neg_ctx->status = major_status;
if(GSS_ERROR(major_status)) {
- /* Curl_cleanup_negotiate(conn->data) ??? */
+ /* Curl_cleanup_negotiate(data) ??? */
log_gss_error(conn, minor_status,
"gss_init_sec_context() failed: ");
return -1;
@@ -277,8 +273,9 @@ 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;
+ size_t len = 0;
char *userp;
+ CURLcode error;
#ifdef HAVE_SPNEGO /* Handle SPNEGO */
if(checkprefix("Negotiate", neg_ctx->protocol)) {
@@ -324,13 +321,21 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
}
}
#endif
- len = Curl_base64_encode(conn->data,
- neg_ctx->output_token.value,
- neg_ctx->output_token.length,
- &encoded);
+ error = Curl_base64_encode(conn->data,
+ neg_ctx->output_token.value,
+ neg_ctx->output_token.length,
+ &encoded, &len);
+ if(error) {
+ Curl_safefree(neg_ctx->output_token.value);
+ neg_ctx->output_token.value = NULL;
+ return error;
+ }
- if(len == 0)
- return CURLE_OUT_OF_MEMORY;
+ if(len == 0) {
+ Curl_safefree(neg_ctx->output_token.value);
+ neg_ctx->output_token.value = NULL;
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
userp = aprintf("%sAuthorization: %s %s\r\n", proxy ? "Proxy-" : "",
neg_ctx->protocol, encoded);
diff --git a/lib/http_negotiate_sspi.c b/lib/http_negotiate_sspi.c
index 809870168..08d016274 100644
--- a/lib/http_negotiate_sspi.c
+++ b/lib/http_negotiate_sspi.c
@@ -19,17 +19,12 @@
* KIND, either express or implied.
*
***************************************************************************/
+
#include "setup.h"
#ifdef USE_WINDOWS_SSPI
#ifndef CURL_DISABLE_HTTP
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
#include "urldata.h"
#include "sendf.h"
@@ -45,13 +40,16 @@
#include "memdebug.h"
static int
-get_gss_name(struct connectdata *conn, bool proxy, char *server)
+get_gss_name(struct connectdata *conn, bool proxy,
+ struct negotiatedata *neg_ctx)
{
- struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
- &conn->data->state.negotiate;
const char* service;
size_t length;
+ if(proxy && !conn->proxy.name)
+ /* proxy auth requested but no given proxy name, error out! */
+ return -1;
+
/* GSSAPI implementation by Globus (known as GSI) requires the name to be
of form "<service>/<fqdn>" instead of <service>@<fqdn> (ie. slash instead
of at-sign). Also GSI servers are often identified as 'host' not 'khttp'.
@@ -71,7 +69,7 @@ get_gss_name(struct connectdata *conn, bool proxy, char *server)
if(length + 1 > sizeof(neg_ctx->server_name))
return EMSGSIZE;
- snprintf(server, sizeof(neg_ctx->server_name), "%s/%s",
+ snprintf(neg_ctx->server_name, sizeof(neg_ctx->server_name), "%s/%s",
service, proxy ? conn->proxy.name : conn->host.name);
return 0;
@@ -84,7 +82,7 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
{
struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
&conn->data->state.negotiate;
- BYTE *input_token = 0;
+ BYTE *input_token = 0;
SecBufferDesc out_buff_desc;
SecBuffer out_sec_buff;
SecBufferDesc in_buff_desc;
@@ -96,6 +94,7 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
size_t len = 0, input_token_len = 0;
bool gss = FALSE;
const char* protocol;
+ CURLcode error;
while(*header && ISSPACE(*header))
header++;
@@ -129,9 +128,11 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
return -1;
}
- if(strlen(neg_ctx->server_name) == 0 &&
- (ret = get_gss_name(conn, proxy, neg_ctx->server_name)))
- return ret;
+ if(0 == strlen(neg_ctx->server_name)) {
+ ret = get_gss_name(conn, proxy, neg_ctx);
+ if(ret)
+ return ret;
+ }
if(!neg_ctx->output_token) {
PSecPkgInfo SecurityPackage;
@@ -176,9 +177,10 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
if(!input_token)
return -1;
- input_token_len = Curl_base64_decode(header,
- (unsigned char **)&input_token);
- if(input_token_len == 0)
+ error = Curl_base64_decode(header,
+ (unsigned char **)&input_token,
+ &input_token_len);
+ if(error || input_token_len == 0)
return -1;
}
@@ -238,16 +240,19 @@ 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;
+ size_t len = 0;
char *userp;
+ CURLcode error;
- len = Curl_base64_encode(conn->data,
- (const char*)neg_ctx->output_token,
- neg_ctx->output_token_length,
- &encoded);
+ error = Curl_base64_encode(conn->data,
+ (const char*)neg_ctx->output_token,
+ neg_ctx->output_token_length,
+ &encoded, &len);
+ if(error)
+ return error;
if(len == 0)
- return CURLE_OUT_OF_MEMORY;
+ return CURLE_REMOTE_ACCESS_DENIED;
userp = aprintf("%sAuthorization: %s %s\r\n", proxy ? "Proxy-" : "",
neg_ctx->protocol, encoded);
diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c
deleted file mode 100644
index c3ceadc35..000000000
--- a/lib/http_ntlm.c
+++ /dev/null
@@ -1,1329 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2011, 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.
- *
- * 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 "setup.h"
-
-/* NTLM details:
-
- http://davenport.sourceforge.net/ntlm.html
- http://www.innovation.ch/java/ntlm.html
-*/
-
-#ifndef CURL_DISABLE_HTTP
-#ifdef USE_NTLM
-
-#define DEBUG_ME 0
-
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#if (defined(NETWARE) && !defined(__NOVELL_LIBC__))
-#include <netdb.h>
-#endif
-
-#include "urldata.h"
-#include "non-ascii.h" /* for Curl_convert_... prototypes */
-#include "sendf.h"
-#include "rawstr.h"
-#include "curl_base64.h"
-#include "http_ntlm.h"
-#include "url.h"
-#include "curl_gethostname.h"
-#include "curl_memory.h"
-
-#define _MPRINTF_REPLACE /* use our functions only */
-#include <curl/mprintf.h>
-
-/* "NTLMSSP" signature is always in ASCII regardless of the platform */
-#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
-
-#ifdef USE_SSLEAY
-#include "ssluse.h"
-# ifdef USE_OPENSSL
-# include <openssl/des.h>
-# ifndef OPENSSL_NO_MD4
-# include <openssl/md4.h>
-# endif
-# include <openssl/md5.h>
-# include <openssl/ssl.h>
-# include <openssl/rand.h>
-# else
-# include <des.h>
-# ifndef OPENSSL_NO_MD4
-# include <md4.h>
-# endif
-# include <md5.h>
-# include <ssl.h>
-# include <rand.h>
-# endif
-
-#ifndef OPENSSL_VERSION_NUMBER
-#error "OPENSSL_VERSION_NUMBER not defined"
-#endif
-
-#if OPENSSL_VERSION_NUMBER < 0x00907001L
-#define DES_key_schedule des_key_schedule
-#define DES_cblock des_cblock
-#define DES_set_odd_parity des_set_odd_parity
-#define DES_set_key des_set_key
-#define DES_ecb_encrypt des_ecb_encrypt
-
-/* This is how things were done in the old days */
-#define DESKEY(x) x
-#define DESKEYARG(x) x
-#else
-/* Modern version */
-#define DESKEYARG(x) *x
-#define DESKEY(x) &x
-#endif
-
-#ifdef OPENSSL_NO_MD4
-/* This requires MD4, but OpenSSL was compiled without it */
-#define USE_NTRESPONSES 0
-#define USE_NTLM2SESSION 0
-#endif
-
-#elif defined(USE_GNUTLS)
-
-#include "gtls.h"
-#include <gcrypt.h>
-
-#define MD5_DIGEST_LENGTH 16
-#define MD4_DIGEST_LENGTH 16
-
-#elif defined(USE_NSS)
-
-#include "curl_md4.h"
-#include "nssg.h"
-#include <nss.h>
-#include <pk11pub.h>
-#include <hasht.h>
-#define MD5_DIGEST_LENGTH MD5_LENGTH
-
-#elif defined(USE_WINDOWS_SSPI)
-
-#include "curl_sspi.h"
-
-#else
-# error "Can't compile NTLM support without a crypto library."
-#endif
-
-/* The last #include file should be: */
-#include "memdebug.h"
-
-#ifndef USE_NTRESPONSES
-/* Define this to make the type-3 message include the NT response message */
-#define USE_NTRESPONSES 1
-
-/* Define this to make the type-3 message include the NTLM2Session response
- message, requires USE_NTRESPONSES. */
-#define USE_NTLM2SESSION 1
-#endif
-
-#ifndef USE_WINDOWS_SSPI
-/* this function converts from the little endian format used in the incoming
- package to whatever endian format we're using natively */
-static unsigned int readint_le(unsigned char *buf) /* must point to a
- 4 bytes buffer*/
-{
- return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
- ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
-}
-#endif
-
-#if DEBUG_ME
-# define DEBUG_OUT(x) x
-static void print_flags(FILE *handle, unsigned long flags)
-{
- if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
- if(flags & NTLMFLAG_NEGOTIATE_OEM)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
- if(flags & NTLMFLAG_REQUEST_TARGET)
- fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
- if(flags & (1<<3))
- fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
- if(flags & NTLMFLAG_NEGOTIATE_SIGN)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
- if(flags & NTLMFLAG_NEGOTIATE_SEAL)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
- if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
- if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
- if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
- if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
- if(flags & (1<<10))
- fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
- if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
- if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
- if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
- if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
- if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
- if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
- fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
- if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
- fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
- if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
- fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
- if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
- if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
- fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
- if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
- fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
- if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
- fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
- if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
- if(flags & (1<<24))
- fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
- if(flags & (1<<25))
- fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
- if(flags & (1<<26))
- fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
- if(flags & (1<<27))
- fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
- if(flags & (1<<28))
- fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
- if(flags & NTLMFLAG_NEGOTIATE_128)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
- if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
- if(flags & NTLMFLAG_NEGOTIATE_56)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
-}
-
-static void print_hex(FILE *handle, const char *buf, size_t len)
-{
- const char *p = buf;
- fprintf(stderr, "0x");
- while(len-- > 0)
- fprintf(stderr, "%02.2x", (unsigned int)*p++);
-}
-#else
-# define DEBUG_OUT(x)
-#endif
-
-/*
- (*) = A "security buffer" is a triplet consisting of two shorts and one
- long:
-
- 1. a 'short' containing the length of the buffer in bytes
- 2. a 'short' containing the allocated space for the buffer in bytes
- 3. a 'long' containing the offset to the start of the buffer from the
- beginning of the NTLM message, in bytes.
-*/
-
-
-CURLntlm Curl_input_ntlm(struct connectdata *conn,
- bool proxy, /* if proxy or not */
- const char *header) /* rest of the www-authenticate:
- header */
-{
- /* point to the correct struct with this */
- struct ntlmdata *ntlm;
-#ifndef USE_WINDOWS_SSPI
- static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
-#endif
-
-#ifdef USE_NSS
- if(CURLE_OK != Curl_nss_force_init(conn->data))
- return CURLNTLM_BAD;
-#endif
-
- ntlm = proxy?&conn->proxyntlm:&conn->ntlm;
-
- /* skip initial whitespaces */
- while(*header && ISSPACE(*header))
- header++;
-
- if(checkprefix("NTLM", header)) {
- header += strlen("NTLM");
-
- while(*header && ISSPACE(*header))
- header++;
-
- if(*header) {
- /* We got a type-2 message here:
-
- Index Description Content
- 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
- (0x4e544c4d53535000)
- 8 NTLM Message Type long (0x02000000)
- 12 Target Name security buffer(*)
- 20 Flags long
- 24 Challenge 8 bytes
- (32) Context (optional) 8 bytes (two consecutive longs)
- (40) Target Information (optional) security buffer(*)
- 32 (48) start of data block
- */
- size_t size;
- unsigned char *buffer;
- size = Curl_base64_decode(header, &buffer);
- if(!buffer)
- return CURLNTLM_BAD;
-
- ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
-
-#ifdef USE_WINDOWS_SSPI
- ntlm->type_2 = malloc(size+1);
- if(ntlm->type_2 == NULL) {
- free(buffer);
- return CURLE_OUT_OF_MEMORY;
- }
- ntlm->n_type_2 = size;
- memcpy(ntlm->type_2, buffer, size);
-#else
- ntlm->flags = 0;
-
- if((size < 32) ||
- (memcmp(buffer, NTLMSSP_SIGNATURE, 8) != 0) ||
- (memcmp(buffer+8, type2_marker, sizeof(type2_marker)) != 0)) {
- /* This was not a good enough type-2 message */
- free(buffer);
- return CURLNTLM_BAD;
- }
-
- ntlm->flags = readint_le(&buffer[20]);
- memcpy(ntlm->nonce, &buffer[24], 8);
-
- DEBUG_OUT({
- fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
- print_flags(stderr, ntlm->flags);
- fprintf(stderr, "\n nonce=");
- print_hex(stderr, (char *)ntlm->nonce, 8);
- fprintf(stderr, "\n****\n");
- fprintf(stderr, "**** Header %s\n ", header);
- });
-#endif
- free(buffer);
- }
- else {
- if(ntlm->state >= NTLMSTATE_TYPE1)
- return CURLNTLM_BAD;
-
- ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
- }
- }
- return CURLNTLM_FINE;
-}
-
-#ifndef USE_WINDOWS_SSPI
-
-#ifdef USE_SSLEAY
-/*
- * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
- * key schedule ks is also set.
- */
-static void setup_des_key(const unsigned char *key_56,
- DES_key_schedule DESKEYARG(ks))
-{
- DES_cblock key;
-
- key[0] = key_56[0];
- key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
- key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
- key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
- key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
- key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
- key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
- key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
-
- DES_set_odd_parity(&key);
- DES_set_key(&key, ks);
-}
-
-#else /* defined(USE_SSLEAY) */
-
-/*
- * Turns a 56 bit key into the 64 bit, odd parity key. Used by GnuTLS and NSS.
- */
-static void extend_key_56_to_64(const unsigned char *key_56, char *key)
-{
- key[0] = key_56[0];
- key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
- key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
- key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
- key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
- key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
- key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
- key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
-}
-
-#if defined(USE_GNUTLS)
-
-/*
- * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
- */
-static void setup_des_key(const unsigned char *key_56,
- gcry_cipher_hd_t *des)
-{
- char key[8];
- extend_key_56_to_64(key_56, key);
- gcry_cipher_setkey(*des, key, 8);
-}
-
-#elif defined(USE_NSS)
-
-/*
- * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using
- * the expanded key. The caller is responsible for giving 64 bit of valid
- * data is IN and (at least) 64 bit large buffer as OUT.
- */
-static bool encrypt_des(const unsigned char *in, unsigned char *out,
- const unsigned char *key_56)
-{
- const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */
- PK11SlotInfo *slot = NULL;
- char key[8]; /* expanded 64 bit key */
- SECItem key_item;
- PK11SymKey *symkey = NULL;
- SECItem *param = NULL;
- PK11Context *ctx = NULL;
- int out_len; /* not used, required by NSS */
- bool rv = FALSE;
-
- /* use internal slot for DES encryption (requires NSS to be initialized) */
- slot = PK11_GetInternalKeySlot();
- if(!slot)
- return FALSE;
-
- /* expand the 56 bit key to 64 bit and wrap by NSS */
- extend_key_56_to_64(key_56, key);
- key_item.data = (unsigned char *)key;
- key_item.len = /* hard-wired */ 8;
- symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT,
- &key_item, NULL);
- if(!symkey)
- goto fail;
-
- /* create DES encryption context */
- param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL);
- if(!param)
- goto fail;
- ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param);
- if(!ctx)
- goto fail;
-
- /* perform the encryption */
- if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8,
- (unsigned char *)in, /* inbuflen */ 8)
- && SECSuccess == PK11_Finalize(ctx))
- rv = /* all OK */ TRUE;
-
-fail:
- /* cleanup */
- if(ctx)
- PK11_DestroyContext(ctx, PR_TRUE);
- if(symkey)
- PK11_FreeSymKey(symkey);
- if(param)
- SECITEM_FreeItem(param, PR_TRUE);
- PK11_FreeSlot(slot);
- return rv;
-}
-
-#endif /* defined(USE_NSS) */
-
-#endif /* defined(USE_SSLEAY) */
-
- /*
- * takes a 21 byte array and treats it as 3 56-bit DES keys. The
- * 8 byte plaintext is encrypted with each key and the resulting 24
- * bytes are stored in the results array.
- */
-static void lm_resp(const unsigned char *keys,
- const unsigned char *plaintext,
- unsigned char *results)
-{
-#ifdef USE_SSLEAY
- DES_key_schedule ks;
-
- setup_des_key(keys, DESKEY(ks));
- DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
- DESKEY(ks), DES_ENCRYPT);
-
- setup_des_key(keys+7, DESKEY(ks));
- DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8),
- DESKEY(ks), DES_ENCRYPT);
-
- setup_des_key(keys+14, DESKEY(ks));
- DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
- DESKEY(ks), DES_ENCRYPT);
-#elif defined(USE_GNUTLS)
- gcry_cipher_hd_t des;
-
- gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
- setup_des_key(keys, &des);
- gcry_cipher_encrypt(des, results, 8, plaintext, 8);
- gcry_cipher_close(des);
-
- gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
- setup_des_key(keys+7, &des);
- gcry_cipher_encrypt(des, results+8, 8, plaintext, 8);
- gcry_cipher_close(des);
-
- gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
- setup_des_key(keys+14, &des);
- gcry_cipher_encrypt(des, results+16, 8, plaintext, 8);
- gcry_cipher_close(des);
-#elif defined(USE_NSS)
- encrypt_des(plaintext, results, keys);
- encrypt_des(plaintext, results+8, keys+7);
- encrypt_des(plaintext, results+16, keys+14);
-#endif
-}
-
-
-/*
- * Set up lanmanager hashed password
- */
-static void mk_lm_hash(struct SessionHandle *data,
- const char *password,
- unsigned char *lmbuffer /* 21 bytes */)
-{
- CURLcode res;
- unsigned char pw[14];
- static const unsigned char magic[] = {
- 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
- };
- size_t len = CURLMIN(strlen(password), 14);
-
- Curl_strntoupper((char *)pw, password, len);
- memset(&pw[len], 0, 14-len);
-
- /*
- * The LanManager hashed password needs to be created using the
- * password in the network encoding not the host encoding.
- */
- res = Curl_convert_to_network(data, (char *)pw, 14);
- if(res)
- return;
-
- {
- /* Create LanManager hashed password. */
-
-#ifdef USE_SSLEAY
- DES_key_schedule ks;
-
- setup_des_key(pw, DESKEY(ks));
- DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
- DESKEY(ks), DES_ENCRYPT);
-
- setup_des_key(pw+7, DESKEY(ks));
- DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
- DESKEY(ks), DES_ENCRYPT);
-#elif defined(USE_GNUTLS)
- gcry_cipher_hd_t des;
-
- gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
- setup_des_key(pw, &des);
- gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
- gcry_cipher_close(des);
-
- gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
- setup_des_key(pw+7, &des);
- gcry_cipher_encrypt(des, lmbuffer+8, 8, magic, 8);
- gcry_cipher_close(des);
-#elif defined(USE_NSS)
- encrypt_des(magic, lmbuffer, pw);
- encrypt_des(magic, lmbuffer+8, pw+7);
-#endif
-
- memset(lmbuffer + 16, 0, 21 - 16);
- }
-}
-
-#if USE_NTRESPONSES
-static void ascii_to_unicode_le(unsigned char *dest, const char *src,
- size_t srclen)
-{
- size_t i;
- for(i=0; i<srclen; i++) {
- dest[2*i] = (unsigned char)src[i];
- dest[2*i+1] = '\0';
- }
-}
-
-/*
- * Set up nt hashed passwords
- */
-static CURLcode mk_nt_hash(struct SessionHandle *data,
- const char *password,
- unsigned char *ntbuffer /* 21 bytes */)
-{
- size_t len = strlen(password);
- unsigned char *pw = malloc(len*2);
- CURLcode result;
- if(!pw)
- return CURLE_OUT_OF_MEMORY;
-
- ascii_to_unicode_le(pw, password, len);
-
- /*
- * The NT hashed password needs to be created using the password in the
- * network encoding not the host encoding.
- */
- result = Curl_convert_to_network(data, (char *)pw, len*2);
- if(result)
- return result;
-
- {
- /* Create NT hashed password. */
-#ifdef USE_SSLEAY
- MD4_CTX MD4pw;
- MD4_Init(&MD4pw);
- MD4_Update(&MD4pw, pw, 2*len);
- MD4_Final(ntbuffer, &MD4pw);
-#elif defined(USE_GNUTLS)
- gcry_md_hd_t MD4pw;
- gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
- gcry_md_write(MD4pw, pw, 2*len);
- memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
- gcry_md_close(MD4pw);
-#elif defined(USE_NSS)
- Curl_md4it(ntbuffer, pw, 2*len);
-#endif
-
- memset(ntbuffer + 16, 0, 21 - 16);
- }
-
- free(pw);
- return CURLE_OK;
-}
-#endif
-
-
-#endif
-
-#ifdef USE_WINDOWS_SSPI
-
-static void
-ntlm_sspi_cleanup(struct ntlmdata *ntlm)
-{
- if(ntlm->type_2) {
- free(ntlm->type_2);
- ntlm->type_2 = NULL;
- }
- if(ntlm->has_handles) {
- s_pSecFn->DeleteSecurityContext(&ntlm->c_handle);
- s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
- ntlm->has_handles = 0;
- }
- if(ntlm->p_identity) {
- if(ntlm->identity.User) free(ntlm->identity.User);
- if(ntlm->identity.Password) free(ntlm->identity.Password);
- if(ntlm->identity.Domain) free(ntlm->identity.Domain);
- ntlm->p_identity = NULL;
- }
-}
-
-#endif
-
-#define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
-#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
- (((x) >>16)&0xff), (((x)>>24) & 0xff)
-
-#define HOSTNAME_MAX 1024
-
-#ifndef USE_WINDOWS_SSPI
-/* copy the source to the destination and fill in zeroes in every
- other destination byte! */
-static void unicodecpy(unsigned char *dest,
- const char *src, size_t length)
-{
- size_t i;
- for(i=0; i<length; i++) {
- dest[2*i] = (unsigned char)src[i];
- dest[2*i+1] = '\0';
- }
-}
-#endif
-
-/* this is for creating ntlm header output */
-CURLcode Curl_output_ntlm(struct connectdata *conn,
- bool proxy)
-{
- const char *domain=""; /* empty */
- char host [HOSTNAME_MAX+ 1] = ""; /* empty */
-#ifndef USE_WINDOWS_SSPI
- size_t domlen = strlen(domain);
- size_t hostlen = strlen(host);
- size_t hostoff; /* host name offset */
- size_t domoff; /* domain name offset */
-#endif
- size_t size;
- char *base64=NULL;
- unsigned char ntlmbuf[1024]; /* enough, unless the user+host+domain is very
- long */
-
- /* point to the address of the pointer that holds the string to sent to the
- server, which is for a plain host or for a HTTP proxy */
- char **allocuserpwd;
-
- /* point to the name and password for this */
- const char *userp;
- const char *passwdp;
- /* point to the correct struct with this */
- struct ntlmdata *ntlm;
- struct auth *authp;
-
- DEBUGASSERT(conn);
- DEBUGASSERT(conn->data);
-
-#ifdef USE_NSS
- if(CURLE_OK != Curl_nss_force_init(conn->data))
- return CURLE_OUT_OF_MEMORY;
-#endif
-
- if(proxy) {
- allocuserpwd = &conn->allocptr.proxyuserpwd;
- userp = conn->proxyuser;
- passwdp = conn->proxypasswd;
- ntlm = &conn->proxyntlm;
- authp = &conn->data->state.authproxy;
- }
- else {
- allocuserpwd = &conn->allocptr.userpwd;
- userp = conn->user;
- passwdp = conn->passwd;
- ntlm = &conn->ntlm;
- authp = &conn->data->state.authhost;
- }
- authp->done = FALSE;
-
- /* not set means empty */
- if(!userp)
- userp="";
-
- if(!passwdp)
- passwdp="";
-
-#ifdef USE_WINDOWS_SSPI
- if(s_hSecDll == NULL) {
- /* not thread safe and leaks - use curl_global_init() to avoid */
- CURLcode err = Curl_sspi_global_init();
- if(s_hSecDll == NULL)
- return err;
- }
-#endif
-
- switch(ntlm->state) {
- case NTLMSTATE_TYPE1:
- default: /* for the weird cases we (re)start here */
-#ifdef USE_WINDOWS_SSPI
- {
- SecBuffer buf;
- SecBufferDesc desc;
- SECURITY_STATUS status;
- ULONG attrs;
- const char *user;
- int domlen;
- TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
-
- ntlm_sspi_cleanup(ntlm);
-
- user = strchr(userp, '\\');
- if(!user)
- user = strchr(userp, '/');
-
- if(user) {
- domain = userp;
- domlen = user - userp;
- user++;
- }
- else {
- user = userp;
- domain = "";
- domlen = 0;
- }
-
- if(user && *user) {
- /* note: initialize all of this before doing the mallocs so that
- * it can be cleaned up later without leaking memory.
- */
- ntlm->p_identity = &ntlm->identity;
- memset(ntlm->p_identity, 0, sizeof(*ntlm->p_identity));
- if((ntlm->identity.User = (unsigned char *)strdup(user)) == NULL)
- return CURLE_OUT_OF_MEMORY;
- ntlm->identity.UserLength = strlen(user);
- if((ntlm->identity.Password = (unsigned char *)strdup(passwdp)) == NULL)
- return CURLE_OUT_OF_MEMORY;
- ntlm->identity.PasswordLength = strlen(passwdp);
- if((ntlm->identity.Domain = malloc(domlen+1)) == NULL)
- return CURLE_OUT_OF_MEMORY;
- strncpy((char *)ntlm->identity.Domain, domain, domlen);
- ntlm->identity.Domain[domlen] = '\0';
- ntlm->identity.DomainLength = domlen;
- ntlm->identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
- }
- else {
- ntlm->p_identity = NULL;
- }
-
- if(s_pSecFn->AcquireCredentialsHandleA(
- NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity,
- NULL, NULL, &ntlm->handle, &tsDummy
- ) != SEC_E_OK) {
- return CURLE_OUT_OF_MEMORY;
- }
-
- desc.ulVersion = SECBUFFER_VERSION;
- desc.cBuffers = 1;
- desc.pBuffers = &buf;
- buf.cbBuffer = sizeof(ntlmbuf);
- buf.BufferType = SECBUFFER_TOKEN;
- buf.pvBuffer = ntlmbuf;
-
- status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, NULL,
- (char *) host,
- ISC_REQ_CONFIDENTIALITY |
- ISC_REQ_REPLAY_DETECT |
- ISC_REQ_CONNECTION,
- 0, SECURITY_NETWORK_DREP,
- NULL, 0,
- &ntlm->c_handle, &desc,
- &attrs, &tsDummy);
-
- if(status == SEC_I_COMPLETE_AND_CONTINUE ||
- status == SEC_I_CONTINUE_NEEDED) {
- s_pSecFn->CompleteAuthToken(&ntlm->c_handle, &desc);
- }
- else if(status != SEC_E_OK) {
- s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
- return CURLE_RECV_ERROR;
- }
-
- ntlm->has_handles = 1;
- size = buf.cbBuffer;
- }
-#else
- hostoff = 0;
- domoff = hostoff + hostlen; /* This is 0: remember that host and domain
- are empty */
-
- /* Create and send a type-1 message:
-
- Index Description Content
- 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
- (0x4e544c4d53535000)
- 8 NTLM Message Type long (0x01000000)
- 12 Flags long
- 16 Supplied Domain security buffer(*)
- 24 Supplied Workstation security buffer(*)
- 32 start of data block
-
- */
-#if USE_NTLM2SESSION
-#define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
-#else
-#define NTLM2FLAG 0
-#endif
- snprintf((char *)ntlmbuf, sizeof(ntlmbuf), NTLMSSP_SIGNATURE "%c"
- "\x01%c%c%c" /* 32-bit type = 1 */
- "%c%c%c%c" /* 32-bit NTLM flag field */
- "%c%c" /* domain length */
- "%c%c" /* domain allocated space */
- "%c%c" /* domain name offset */
- "%c%c" /* 2 zeroes */
- "%c%c" /* host length */
- "%c%c" /* host allocated space */
- "%c%c" /* host name offset */
- "%c%c" /* 2 zeroes */
- "%s" /* host name */
- "%s", /* domain string */
- 0, /* trailing zero */
- 0,0,0, /* part of type-1 long */
-
- LONGQUARTET(
- NTLMFLAG_NEGOTIATE_OEM|
- NTLMFLAG_REQUEST_TARGET|
- NTLMFLAG_NEGOTIATE_NTLM_KEY|
- NTLM2FLAG|
- NTLMFLAG_NEGOTIATE_ALWAYS_SIGN
- ),
- SHORTPAIR(domlen),
- SHORTPAIR(domlen),
- SHORTPAIR(domoff),
- 0,0,
- SHORTPAIR(hostlen),
- SHORTPAIR(hostlen),
- SHORTPAIR(hostoff),
- 0,0,
- host /* this is empty */, domain /* this is empty */);
-
- /* initial packet length */
- size = 32 + hostlen + domlen;
-#endif
-
- DEBUG_OUT({
- fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
- "0x%08.8x ",
- LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM|
- NTLMFLAG_REQUEST_TARGET|
- NTLMFLAG_NEGOTIATE_NTLM_KEY|
- NTLM2FLAG|
- NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
- NTLMFLAG_NEGOTIATE_OEM|
- NTLMFLAG_REQUEST_TARGET|
- NTLMFLAG_NEGOTIATE_NTLM_KEY|
- NTLM2FLAG|
- NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
- print_flags(stderr,
- NTLMFLAG_NEGOTIATE_OEM|
- NTLMFLAG_REQUEST_TARGET|
- NTLMFLAG_NEGOTIATE_NTLM_KEY|
- NTLM2FLAG|
- NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
- fprintf(stderr, "\n****\n");
- });
-
- /* now size is the size of the base64 encoded package size */
- size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
-
- if(size >0 ) {
- Curl_safefree(*allocuserpwd);
- *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
- proxy?"Proxy-":"",
- base64);
- DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
- free(base64);
- }
- else
- return CURLE_OUT_OF_MEMORY; /* FIX TODO */
-
- break;
-
- case NTLMSTATE_TYPE2:
- /* We received the type-2 message already, create a type-3 message:
-
- Index Description Content
- 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
- (0x4e544c4d53535000)
- 8 NTLM Message Type long (0x03000000)
- 12 LM/LMv2 Response security buffer(*)
- 20 NTLM/NTLMv2 Response security buffer(*)
- 28 Domain Name security buffer(*)
- 36 User Name security buffer(*)
- 44 Workstation Name security buffer(*)
- (52) Session Key (optional) security buffer(*)
- (60) Flags (optional) long
- 52 (64) start of data block
-
- */
-
- {
-#ifdef USE_WINDOWS_SSPI
- SecBuffer type_2, type_3;
- SecBufferDesc type_2_desc, type_3_desc;
- SECURITY_STATUS status;
- ULONG attrs;
- TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
-
- type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION;
- type_2_desc.cBuffers = type_3_desc.cBuffers = 1;
- type_2_desc.pBuffers = &type_2;
- type_3_desc.pBuffers = &type_3;
-
- type_2.BufferType = SECBUFFER_TOKEN;
- type_2.pvBuffer = ntlm->type_2;
- type_2.cbBuffer = ntlm->n_type_2;
- type_3.BufferType = SECBUFFER_TOKEN;
- type_3.pvBuffer = ntlmbuf;
- type_3.cbBuffer = sizeof(ntlmbuf);
-
- status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle,
- &ntlm->c_handle,
- (char *) host,
- ISC_REQ_CONFIDENTIALITY |
- ISC_REQ_REPLAY_DETECT |
- ISC_REQ_CONNECTION,
- 0, SECURITY_NETWORK_DREP,
- &type_2_desc,
- 0, &ntlm->c_handle,
- &type_3_desc,
- &attrs, &tsDummy);
-
- if(status != SEC_E_OK)
- return CURLE_RECV_ERROR;
-
- size = type_3.cbBuffer;
-
- ntlm_sspi_cleanup(ntlm);
-
-#else
- int lmrespoff;
- unsigned char lmresp[24]; /* fixed-size */
-#if USE_NTRESPONSES
- int ntrespoff;
- unsigned char ntresp[24]; /* fixed-size */
-#endif
- bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE)?TRUE:FALSE;
- size_t useroff;
- const char *user;
- size_t userlen;
- CURLcode res;
-
- user = strchr(userp, '\\');
- if(!user)
- user = strchr(userp, '/');
-
- if(user) {
- domain = userp;
- domlen = (user - domain);
- user++;
- }
- else
- user = userp;
- userlen = strlen(user);
-
- if(Curl_gethostname(host, HOSTNAME_MAX)) {
- infof(conn->data, "gethostname() failed, continuing without!");
- hostlen = 0;
- }
- else {
- /* If the workstation if configured with a full DNS name (i.e.
- * workstation.somewhere.net) gethostname() returns the fully qualified
- * name, which NTLM doesn't like.
- */
- char *dot = strchr(host, '.');
- if(dot)
- *dot = '\0';
- hostlen = strlen(host);
- }
-
- if(unicode) {
- domlen = domlen * 2;
- userlen = userlen * 2;
- hostlen = hostlen * 2;
- }
-
-#if USE_NTLM2SESSION
- /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
- if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
- unsigned char ntbuffer[0x18];
- unsigned char tmp[0x18];
- unsigned char md5sum[MD5_DIGEST_LENGTH];
- unsigned char entropy[8];
-
- /* Need to create 8 bytes random data */
-#ifdef USE_SSLEAY
- MD5_CTX MD5pw;
- Curl_ossl_seed(conn->data); /* Initiate the seed if not already done */
- RAND_bytes(entropy,8);
-#elif defined(USE_GNUTLS)
- gcry_md_hd_t MD5pw;
- Curl_gtls_seed(conn->data); /* Initiate the seed if not already done */
- gcry_randomize(entropy, 8, GCRY_STRONG_RANDOM);
-#elif defined(USE_NSS)
- PK11Context *MD5pw;
- unsigned int outlen;
- Curl_nss_seed(conn->data); /* Initiate the seed if not already done */
- PK11_GenerateRandom(entropy, 8);
-#endif
-
- /* 8 bytes random data as challenge in lmresp */
- memcpy(lmresp,entropy,8);
- /* Pad with zeros */
- memset(lmresp+8,0,0x10);
-
- /* Fill tmp with challenge(nonce?) + entropy */
- memcpy(tmp,&ntlm->nonce[0],8);
- memcpy(tmp+8,entropy,8);
-
-#ifdef USE_SSLEAY
- MD5_Init(&MD5pw);
- MD5_Update(&MD5pw, tmp, 16);
- MD5_Final(md5sum, &MD5pw);
-#elif defined(USE_GNUTLS)
- gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
- gcry_md_write(MD5pw, tmp, MD5_DIGEST_LENGTH);
- memcpy(md5sum, gcry_md_read (MD5pw, 0), MD5_DIGEST_LENGTH);
- gcry_md_close(MD5pw);
-#elif defined(USE_NSS)
- MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
- PK11_DigestOp(MD5pw, tmp, 16);
- PK11_DigestFinal(MD5pw, md5sum, &outlen, MD5_DIGEST_LENGTH);
- PK11_DestroyContext(MD5pw, PR_TRUE);
-#endif
-
- /* We shall only use the first 8 bytes of md5sum,
- but the des code in lm_resp only encrypt the first 8 bytes */
- if(mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY)
- return CURLE_OUT_OF_MEMORY;
- lm_resp(ntbuffer, md5sum, ntresp);
-
- /* End of NTLM2 Session code */
- }
- else
-#endif
- {
-
-#if USE_NTRESPONSES
- unsigned char ntbuffer[0x18];
-#endif
- unsigned char lmbuffer[0x18];
-
-#if USE_NTRESPONSES
- if(mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY)
- return CURLE_OUT_OF_MEMORY;
- lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
-#endif
-
- mk_lm_hash(conn->data, passwdp, lmbuffer);
- lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
- /* A safer but less compatible alternative is:
- * lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
- * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
- }
-
- lmrespoff = 64; /* size of the message header */
-#if USE_NTRESPONSES
- ntrespoff = lmrespoff + 0x18;
- domoff = ntrespoff + 0x18;
-#else
- domoff = lmrespoff + 0x18;
-#endif
- useroff = domoff + domlen;
- hostoff = useroff + userlen;
-
- /* Create the big type-3 message binary blob */
- size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf),
- NTLMSSP_SIGNATURE "%c"
- "\x03%c%c%c" /* type-3, 32 bits */
-
- "%c%c" /* LanManager length */
- "%c%c" /* LanManager allocated space */
- "%c%c" /* LanManager offset */
- "%c%c" /* 2 zeroes */
-
- "%c%c" /* NT-response length */
- "%c%c" /* NT-response allocated space */
- "%c%c" /* NT-response offset */
- "%c%c" /* 2 zeroes */
-
- "%c%c" /* domain length */
- "%c%c" /* domain allocated space */
- "%c%c" /* domain name offset */
- "%c%c" /* 2 zeroes */
-
- "%c%c" /* user length */
- "%c%c" /* user allocated space */
- "%c%c" /* user offset */
- "%c%c" /* 2 zeroes */
-
- "%c%c" /* host length */
- "%c%c" /* host allocated space */
- "%c%c" /* host offset */
- "%c%c" /* 2 zeroes */
-
- "%c%c" /* session key length (unknown purpose) */
- "%c%c" /* session key allocated space (unknown purpose) */
- "%c%c" /* session key offset (unknown purpose) */
- "%c%c" /* 2 zeroes */
-
- "%c%c%c%c" /* flags */
-
- /* domain string */
- /* user string */
- /* host string */
- /* LanManager response */
- /* NT response */
- ,
- 0, /* zero termination */
- 0,0,0, /* type-3 long, the 24 upper bits */
-
- SHORTPAIR(0x18), /* LanManager response length, twice */
- SHORTPAIR(0x18),
- SHORTPAIR(lmrespoff),
- 0x0, 0x0,
-
-#if USE_NTRESPONSES
- SHORTPAIR(0x18), /* NT-response length, twice */
- SHORTPAIR(0x18),
- SHORTPAIR(ntrespoff),
- 0x0, 0x0,
-#else
- 0x0, 0x0,
- 0x0, 0x0,
- 0x0, 0x0,
- 0x0, 0x0,
-#endif
- SHORTPAIR(domlen),
- SHORTPAIR(domlen),
- SHORTPAIR(domoff),
- 0x0, 0x0,
-
- SHORTPAIR(userlen),
- SHORTPAIR(userlen),
- SHORTPAIR(useroff),
- 0x0, 0x0,
-
- SHORTPAIR(hostlen),
- SHORTPAIR(hostlen),
- SHORTPAIR(hostoff),
- 0x0, 0x0,
-
- 0x0, 0x0,
- 0x0, 0x0,
- 0x0, 0x0,
- 0x0, 0x0,
-
- LONGQUARTET(ntlm->flags));
- DEBUGASSERT(size==64);
-
- DEBUGASSERT(size == (size_t)lmrespoff);
- /* We append the binary hashes */
- if(size < (sizeof(ntlmbuf) - 0x18)) {
- memcpy(&ntlmbuf[size], lmresp, 0x18);
- size += 0x18;
- }
-
- DEBUG_OUT({
- fprintf(stderr, "**** TYPE3 header lmresp=");
- print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
- });
-
-#if USE_NTRESPONSES
- if(size < (sizeof(ntlmbuf) - 0x18)) {
- DEBUGASSERT(size == (size_t)ntrespoff);
- memcpy(&ntlmbuf[size], ntresp, 0x18);
- size += 0x18;
- }
-
- DEBUG_OUT({
- fprintf(stderr, "\n ntresp=");
- print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18);
- });
-
-#endif
-
- DEBUG_OUT({
- fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
- LONGQUARTET(ntlm->flags), ntlm->flags);
- print_flags(stderr, ntlm->flags);
- fprintf(stderr, "\n****\n");
- });
-
-
- /* Make sure that the domain, user and host strings fit in the target
- buffer before we copy them there. */
- if(size + userlen + domlen + hostlen >= sizeof(ntlmbuf)) {
- failf(conn->data, "user + domain + host name too big");
- return CURLE_OUT_OF_MEMORY;
- }
-
- DEBUGASSERT(size == domoff);
- if(unicode)
- unicodecpy(&ntlmbuf[size], domain, domlen/2);
- else
- memcpy(&ntlmbuf[size], domain, domlen);
-
- size += domlen;
-
- DEBUGASSERT(size == useroff);
- if(unicode)
- unicodecpy(&ntlmbuf[size], user, userlen/2);
- else
- memcpy(&ntlmbuf[size], user, userlen);
-
- size += userlen;
-
- DEBUGASSERT(size == hostoff);
- if(unicode)
- unicodecpy(&ntlmbuf[size], host, hostlen/2);
- else
- memcpy(&ntlmbuf[size], host, hostlen);
-
- size += hostlen;
-
- /* convert domain, user, and host to ASCII but leave the rest as-is */
- res = Curl_convert_to_network(conn->data, (char *)&ntlmbuf[domoff],
- size-domoff);
- if(res)
- return CURLE_CONV_FAILED;
-
-#endif
-
- /* convert the binary blob into base64 */
- size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
-
- if(size >0 ) {
- Curl_safefree(*allocuserpwd);
- *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
- proxy?"Proxy-":"",
- base64);
- DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
- free(base64);
- }
- else
- return CURLE_OUT_OF_MEMORY; /* FIX TODO */
-
- ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
- authp->done = TRUE;
- }
- break;
-
- case NTLMSTATE_TYPE3:
- /* connection is already authenticated,
- * don't send a header in future requests */
- if(*allocuserpwd) {
- free(*allocuserpwd);
- *allocuserpwd=NULL;
- }
- authp->done = TRUE;
- break;
- }
-
- return CURLE_OK;
-}
-
-
-void
-Curl_ntlm_cleanup(struct connectdata *conn)
-{
-#ifdef USE_WINDOWS_SSPI
- ntlm_sspi_cleanup(&conn->ntlm);
- ntlm_sspi_cleanup(&conn->proxyntlm);
-#else
- (void)conn;
-#endif
-}
-
-
-#endif /* USE_NTLM */
-#endif /* !CURL_DISABLE_HTTP */
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index 9fa832e4d..f3b02c975 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -27,6 +27,7 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+
#include "urldata.h"
#include <curl/curl.h>
#include "http_proxy.h"
diff --git a/lib/idn_win32.c b/lib/idn_win32.c
index 96d3f0959..70286c0fd 100644
--- a/lib/idn_win32.c
+++ b/lib/idn_win32.c
@@ -19,13 +19,15 @@
* KIND, either express or implied.
*
***************************************************************************/
-/***************************************************************************
- * IDN Implementation using windows native APIs
- * Pierre Joye <pierre@php.net>
- ***************************************************************************/
-#if defined(WIN32) && defined(USE_WIN32_IDN)
-#include <windows.h>
-#include <stdio.h>
+
+ /*
+ * IDN conversions using Windows kernel32 and normaliz libraries.
+ */
+
+#include "setup.h"
+
+#ifdef USE_WIN32_IDN
+
#include <tchar.h>
#ifdef WANT_IDN_PROTOTYPES
@@ -121,7 +123,5 @@ int curl_win32_ascii_to_idn(const char *in, size_t in_len, char **out_utf8)
}
return 1;
}
-#else
-typedef int dummy; /* because ISO C forbids an empty translation unit! */
-#endif
- /* WIN32 */
+
+#endif /* USE_WIN32_IDN */
diff --git a/lib/imap.c b/lib/imap.c
index b135443d3..986b79a56 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -26,11 +26,6 @@
#include "setup.h"
#ifndef CURL_DISABLE_IMAP
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -124,6 +119,7 @@ const struct Curl_handler Curl_handler_imap = {
imap_doing, /* doing */
imap_getsock, /* proto_getsock */
imap_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
imap_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -149,6 +145,7 @@ const struct Curl_handler Curl_handler_imaps = {
imap_doing, /* doing */
imap_getsock, /* proto_getsock */
imap_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
imap_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -174,6 +171,7 @@ static const struct Curl_handler Curl_handler_imap_proxy = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -199,6 +197,7 @@ static const struct Curl_handler Curl_handler_imaps_proxy = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -215,9 +214,6 @@ static const struct Curl_handler Curl_handler_imaps_proxy = {
*
* Sends the formated string as an IMAP command to a server
*
- * NOTE: we build the command in a fixed-length buffer, which sets length
- * restrictions on the command!
- *
* Designed to never block.
*/
static CURLcode imapsendf(struct connectdata *conn,
@@ -343,7 +339,7 @@ static void imap_to_imaps(struct connectdata *conn)
conn->handler = &Curl_handler_imaps;
}
#else
-#define imap_to_imaps(x)
+#define imap_to_imaps(x) Curl_nop_stmt
#endif
/* for STARTTLS responses */
@@ -638,7 +634,7 @@ static CURLcode imap_multi_statemach(struct connectdata *conn,
else
result = Curl_pp_multi_statemach(&imapc->pp);
- *done = (bool)(imapc->state == IMAP_STOP);
+ *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;
return result;
}
@@ -846,7 +842,7 @@ CURLcode imap_perform(struct connectdata *conn,
result = imap_easy_statemach(conn);
*dophase_done = TRUE; /* with the easy interface we are done here */
}
- *connected = conn->bits.tcpconnect;
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done)
DEBUGF(infof(conn->data, "DO phase is complete\n"));
diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c
index 34cae801a..1bb97443b 100644
--- a/lib/inet_ntop.c
+++ b/lib/inet_ntop.c
@@ -34,8 +34,6 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#include <string.h>
-#include <errno.h>
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
diff --git a/lib/inet_pton.c b/lib/inet_pton.c
index d08c7c666..021f48d52 100644
--- a/lib/inet_pton.c
+++ b/lib/inet_pton.c
@@ -32,8 +32,6 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#include <string.h>
-#include <errno.h>
#include "inet_pton.h"
diff --git a/lib/krb4.c b/lib/krb4.c
index 7da47f31f..b53a6104c 100644
--- a/lib/krb4.c
+++ b/lib/krb4.c
@@ -44,11 +44,9 @@
#ifndef CURL_DISABLE_FTP
#ifdef HAVE_KRB4
-#include <stdlib.h>
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
-#include <string.h>
#include <krb.h>
#include <des.h>
@@ -203,7 +201,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
int ret;
char *p;
unsigned char *ptr;
- size_t len;
+ size_t len = 0;
KTEXT_ST adat;
MSG_DAT msg_data;
int checksum;
@@ -214,6 +212,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
int l = sizeof(conn->local_addr);
struct SessionHandle *data = conn->data;
CURLcode result;
+ size_t base64_sz = 0;
if(getsockname(conn->sock[FIRSTSOCKET],
(struct sockaddr *)LOCAL_ADDR, &l) < 0)
@@ -249,8 +248,10 @@ krb4_auth(void *app_data, struct connectdata *conn)
}
#endif
- if(Curl_base64_encode(conn->data, (char *)adat.dat, adat.length, &p) < 1) {
- Curl_failf(data, "Out of memory base64-encoding");
+ result = Curl_base64_encode(conn->data, (char *)adat.dat, adat.length,
+ &p, &base64_sz);
+ if(result) {
+ Curl_failf(data, "base64-encoding: %s", curl_easy_strerror(result));
return AUTH_CONTINUE;
}
@@ -264,7 +265,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
if(Curl_GetFTPResponse(&nread, conn, NULL))
return -1;
- if(data->state.buffer[0] != '2'){
+ if(data->state.buffer[0] != '2') {
Curl_failf(data, "Server didn't accept auth data");
return AUTH_ERROR;
}
@@ -275,10 +276,15 @@ krb4_auth(void *app_data, struct connectdata *conn)
return AUTH_ERROR;
}
p += 5;
- len = Curl_base64_decode(p, &ptr);
+ result = Curl_base64_decode(p, &ptr, &len);
+ if(result) {
+ Curl_failf(data, "base64-decoding: %s", curl_easy_strerror(result));
+ return AUTH_ERROR;
+ }
if(len > sizeof(adat.dat)-1) {
free(ptr);
- len=0;
+ ptr = NULL;
+ len = 0;
}
if(!len || !ptr) {
Curl_failf(data, "Failed to decode base64 from server");
@@ -332,11 +338,12 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
char *name;
char *p;
char passwd[100];
- size_t tmp;
+ size_t tmp = 0;
ssize_t nread;
enum protection_level save;
CURLcode result;
unsigned char *ptr;
+ size_t base64_sz = 0;
save = krb4_set_command_prot(conn, PROT_PRIVATE);
@@ -349,7 +356,7 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
if(result)
return result;
- if(conn->data->state.buffer[0] != '3'){
+ if(conn->data->state.buffer[0] != '3') {
krb4_set_command_prot(conn, save);
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
@@ -362,10 +369,15 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
}
p += 2;
- tmp = Curl_base64_decode(p, &ptr);
+ result = Curl_base64_decode(p, &ptr, &tmp);
+ if(result) {
+ Curl_failf(conn->data, "base64-decoding: %s", curl_easy_strerror(result));
+ return result;
+ }
if(tmp >= sizeof(tkt.dat)) {
free(ptr);
- tmp=0;
+ ptr = NULL;
+ tmp = 0;
}
if(!tmp || !ptr) {
Curl_failf(conn->data, "Failed to decode base64 in reply");
@@ -406,11 +418,12 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
memset(key, 0, sizeof(key));
memset(schedule, 0, sizeof(schedule));
memset(passwd, 0, sizeof(passwd));
- if(Curl_base64_encode(conn->data, (char *)tktcopy.dat, tktcopy.length, &p)
- < 1) {
- failf(conn->data, "Out of memory base64-encoding.");
+ result = Curl_base64_encode(conn->data, (char *)tktcopy.dat, tktcopy.length,
+ &p, &base64_sz);
+ if(result) {
+ Curl_failf(conn->data, "base64-encoding: %s", curl_easy_strerror(result));
krb4_set_command_prot(conn, save);
- return CURLE_OUT_OF_MEMORY;
+ return result;
}
memset (tktcopy.dat, 0, tktcopy.length);
diff --git a/lib/krb5.c b/lib/krb5.c
index f128d515f..96938dd6e 100644
--- a/lib/krb5.c
+++ b/lib/krb5.c
@@ -39,29 +39,17 @@
#ifdef HAVE_OLD_GSSMIT
#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
+#define NCOMPAT 1
#endif
-#include <stdlib.h>
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
-#include <string.h>
-
-#ifdef HAVE_GSSGNU
-# include <gss.h>
-#elif defined HAVE_GSSMIT
- /* MIT style */
-# include <gssapi/gssapi.h>
-# include <gssapi/gssapi_generic.h>
-# include <gssapi/gssapi_krb5.h>
-#else
- /* Heimdal-style */
-# include <gssapi.h>
-#endif
#include "urldata.h"
#include "curl_base64.h"
#include "ftp.h"
+#include "curl_gssapi.h"
#include "sendf.h"
#include "krb4.h"
#include "curl_memory.h"
@@ -94,16 +82,16 @@ krb5_check_prot(void *app_data, int level)
}
static int
-krb5_decode(void *app_data, void *buf, int len, int level,
- struct connectdata *conn)
+krb5_decode(void *app_data, void *buf, int len,
+ int level UNUSED_PARAM,
+ struct connectdata *conn UNUSED_PARAM)
{
gss_ctx_id_t *context = app_data;
OM_uint32 maj, min;
gss_buffer_desc enc, dec;
- /* shut gcc up */
- level = 0;
- conn = NULL;
+ (void)level;
+ (void)conn;
enc.value = buf;
enc.length = len;
@@ -133,7 +121,7 @@ krb5_overhead(void *app_data, int level, int len)
static int
krb5_encode(void *app_data, const void *from, int length, int level, void **to,
- struct connectdata *conn)
+ struct connectdata *conn UNUSED_PARAM)
{
gss_ctx_id_t *context = app_data;
gss_buffer_desc dec, enc;
@@ -184,6 +172,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
gss_name_t gssname;
gss_ctx_id_t *context = app_data;
struct gss_channel_bindings_struct chan;
+ size_t base64_sz = 0;
if(getsockname(conn->sock[FIRSTSOCKET],
(struct sockaddr *)LOCAL_ADDR, &l) < 0)
@@ -201,7 +190,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
chan.application_data.value = NULL;
/* this loop will execute twice (once for service, once for host) */
- while(1) {
+ for(;;) {
/* this really shouldn't be repeated here, but can't help it */
if(service == srv_host) {
result = Curl_ftpsendf(conn, "AUTH GSSAPI");
@@ -242,19 +231,14 @@ krb5_auth(void *app_data, struct connectdata *conn)
taken care by a final gss_release_buffer. */
gss_release_buffer(&min, &output_buffer);
ret = AUTH_OK;
- maj = gss_init_sec_context(&min,
- GSS_C_NO_CREDENTIAL,
- context,
- gssname,
- GSS_C_NO_OID,
- GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
- 0,
- &chan,
- gssresp,
- NULL,
- &output_buffer,
- NULL,
- NULL);
+ maj = Curl_gss_init_sec_context(data,
+ &min,
+ context,
+ gssname,
+ &chan,
+ gssresp,
+ &output_buffer,
+ NULL);
if(gssresp) {
free(_gssresp.value);
@@ -268,9 +252,10 @@ krb5_auth(void *app_data, struct connectdata *conn)
}
if(output_buffer.length != 0) {
- if(Curl_base64_encode(data, (char *)output_buffer.value,
- output_buffer.length, &p) < 1) {
- Curl_infof(data, "Out of memory base64-encoding\n");
+ result = Curl_base64_encode(data, (char *)output_buffer.value,
+ output_buffer.length, &p, &base64_sz);
+ if(result) {
+ Curl_infof(data,"base64-encoding: %s\n", curl_easy_strerror(result));
ret = AUTH_CONTINUE;
break;
}
@@ -289,7 +274,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
break;
}
- if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3'){
+ if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3') {
Curl_infof(data, "Server didn't accept auth data\n");
ret = AUTH_ERROR;
break;
@@ -298,10 +283,11 @@ krb5_auth(void *app_data, struct connectdata *conn)
p = data->state.buffer + 4;
p = strstr(p, "ADAT=");
if(p) {
- _gssresp.length = Curl_base64_decode(p + 5, (unsigned char **)
- &_gssresp.value);
- if(_gssresp.length < 1) {
- Curl_failf(data, "Out of memory base64-encoding\n");
+ result = Curl_base64_decode(p + 5,
+ (unsigned char **)&_gssresp.value,
+ &_gssresp.length);
+ if(result) {
+ Curl_failf(data,"base64-decoding: %s", curl_easy_strerror(result));
ret = AUTH_CONTINUE;
break;
}
diff --git a/lib/ldap.c b/lib/ldap.c
index 62a9ffc19..737847649 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -35,14 +35,6 @@
* OpenLDAP library versions, USE_OPENLDAP shall not be defined.
*/
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <errno.h>
-
#ifdef CURL_LDAP_WIN /* Use Windows LDAP implementation. */
# include <winldap.h>
# ifndef LDAP_VENDOR_NAME
@@ -113,11 +105,11 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp);
#define LDAP_TRACE(x) do { \
_ldap_trace ("%u: ", __LINE__); \
_ldap_trace x; \
- } while(0)
+ } WHILE_FALSE
static void _ldap_trace (const char *fmt, ...);
#else
- #define LDAP_TRACE(x) ((void)0)
+ #define LDAP_TRACE(x) Curl_nop_stmt
#endif
@@ -138,6 +130,7 @@ const struct Curl_handler Curl_handler_ldap = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -162,6 +155,7 @@ const struct Curl_handler Curl_handler_ldaps = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -184,9 +178,9 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
struct SessionHandle *data=conn->data;
int ldap_proto = LDAP_VERSION3;
int ldap_ssl = 0;
- char *val_b64;
- size_t val_b64_sz;
- curl_off_t dlsize=0;
+ char *val_b64 = NULL;
+ size_t val_b64_sz = 0;
+ curl_off_t dlsize = 0;
#ifdef LDAP_OPT_NETWORK_TIMEOUT
struct timeval ldap_timeout = {10,0}; /* 10 sec connection/search timeout */
#endif
@@ -413,10 +407,20 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
(char *)attribute +
(strlen((char *)attribute) - 7)) == 0)) {
/* Binary attribute, encode to base64. */
- val_b64_sz = Curl_base64_encode(data,
- vals[i]->bv_val,
- vals[i]->bv_len,
- &val_b64);
+ CURLcode error = Curl_base64_encode(data,
+ vals[i]->bv_val,
+ vals[i]->bv_len,
+ &val_b64,
+ &val_b64_sz);
+ if(error) {
+ ldap_value_free_len(vals);
+ ldap_memfree(attribute);
+ ldap_memfree(dn);
+ if(ber)
+ ber_free(ber, 0);
+ status = error;
+ goto quit;
+ }
if(val_b64_sz > 0) {
Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz);
free(val_b64);
diff --git a/lib/libcurl.imp b/lib/libcurl.imp
index 74943afa7..7c99a9468 100644
--- a/lib/libcurl.imp
+++ b/lib/libcurl.imp
@@ -9,6 +9,8 @@
curl_easy_init,
curl_easy_pause,
curl_easy_perform,
+ curl_easy_recv,
+ curl_easy_send,
curl_easy_setopt,
curl_escape,
curl_unescape,
@@ -38,6 +40,8 @@
curl_multi_perform,
curl_multi_cleanup,
curl_multi_info_read,
+ curl_multi_setopt,
+ curl_multi_timeout,
curl_free,
curl_version_info,
curl_share_init,
diff --git a/lib/llist.c b/lib/llist.c
index 8b4bc7f20..a302e32d5 100644
--- a/lib/llist.c
+++ b/lib/llist.c
@@ -22,9 +22,6 @@
#include "setup.h"
-#include <string.h>
-#include <stdlib.h>
-
#include "llist.h"
#include "curl_memory.h"
@@ -49,7 +46,7 @@ Curl_llist_alloc(curl_llist_dtor dtor)
struct curl_llist *list;
list = malloc(sizeof(struct curl_llist));
- if(NULL == list)
+ if(!list)
return NULL;
llist_init(list, dtor);
@@ -134,6 +131,10 @@ Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
list->dtor(user, e->ptr);
+ e->ptr = NULL;
+ e->prev = NULL;
+ e->next = NULL;
+
free(e);
--list->size;
diff --git a/lib/md4.c b/lib/md4.c
index 84c520210..828ce6277 100644
--- a/lib/md4.c
+++ b/lib/md4.c
@@ -27,7 +27,6 @@
#ifdef USE_NSS
#include "curl_md4.h"
-#include <string.h>
typedef unsigned int UINT4;
diff --git a/lib/md5.c b/lib/md5.c
index 8abcb2b1d..f26e02752 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -24,8 +24,6 @@
#ifndef CURL_DISABLE_CRYPTO_AUTH
-#include <string.h>
-
#include "curl_md5.h"
#include "curl_hmac.h"
diff --git a/lib/memdebug.c b/lib/memdebug.c
index 69e204b6a..0b81621cb 100644
--- a/lib/memdebug.c
+++ b/lib/memdebug.c
@@ -32,10 +32,6 @@
#define _MPRINTF_REPLACE
#include <curl/mprintf.h>
#include "urldata.h"
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -46,12 +42,59 @@
#include "memdebug.h"
#ifndef HAVE_ASSERT_H
-# define assert(x) do { } while (0)
+# define assert(x) Curl_nop_stmt
+#endif
+
+/*
+ * Until 2011-08-17 libcurl's Memory Tracking feature also performed
+ * automatic malloc and free filling operations using 0xA5 and 0x13
+ * values. Our own preinitialization of dynamically allocated memory
+ * might be useful when not using third party memory debuggers, but
+ * on the other hand this would fool memory debuggers into thinking
+ * that all dynamically allocated memory is properly initialized.
+ *
+ * As a default setting, libcurl's Memory Tracking feature no longer
+ * performs preinitialization of dynamically allocated memory on its
+ * own. If you know what you are doing, and really want to retain old
+ * behavior, you can achieve this compiling with preprocessor symbols
+ * CURL_MT_MALLOC_FILL and CURL_MT_FREE_FILL defined with appropriate
+ * values.
+ */
+
+#ifdef CURL_MT_MALLOC_FILL
+# if (CURL_MT_MALLOC_FILL < 0) || (CURL_MT_MALLOC_FILL > 0xff)
+# error "invalid CURL_MT_MALLOC_FILL or out of range"
+# endif
+#endif
+
+#ifdef CURL_MT_FREE_FILL
+# if (CURL_MT_FREE_FILL < 0) || (CURL_MT_FREE_FILL > 0xff)
+# error "invalid CURL_MT_FREE_FILL or out of range"
+# endif
+#endif
+
+#if defined(CURL_MT_MALLOC_FILL) && defined(CURL_MT_FREE_FILL)
+# if (CURL_MT_MALLOC_FILL == CURL_MT_FREE_FILL)
+# error "CURL_MT_MALLOC_FILL same as CURL_MT_FREE_FILL"
+# endif
+#endif
+
+#ifdef CURL_MT_MALLOC_FILL
+# define mt_malloc_fill(buf,len) memset((buf), CURL_MT_MALLOC_FILL, (len))
+#else
+# define mt_malloc_fill(buf,len) Curl_nop_stmt
+#endif
+
+#ifdef CURL_MT_FREE_FILL
+# define mt_free_fill(buf,len) memset((buf), CURL_MT_FREE_FILL, (len))
+#else
+# define mt_free_fill(buf,len) Curl_nop_stmt
#endif
struct memdebug {
size_t size;
union {
+ curl_off_t o;
double d;
void * p;
} mem[1];
@@ -76,7 +119,7 @@ static long memsize = 0; /* set number of mallocs allowed */
void curl_memdebug(const char *logname)
{
if(!logfile) {
- if(logname)
+ if(logname && *logname)
logfile = fopen(logname, "w");
else
logfile = stderr;
@@ -144,7 +187,7 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source)
mem = (Curl_cmalloc)(size);
if(mem) {
/* fill memory with junk */
- memset(mem->mem, 0xA5, wantedsize);
+ mt_malloc_fill(mem->mem, wantedsize);
mem->size = wantedsize;
}
@@ -170,12 +213,9 @@ void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
user_size = wanted_size * wanted_elements;
size = sizeof(struct memdebug) + user_size;
- mem = (Curl_cmalloc)(size);
- if(mem) {
- /* fill memory with zeroes */
- memset(mem->mem, 0, user_size);
+ mem = (Curl_ccalloc)(1, size);
+ if(mem)
mem->size = user_size;
- }
if(source)
curl_memlog("MEM %s:%d calloc(%zu,%zu) = %p\n",
@@ -264,8 +304,8 @@ void curl_dofree(void *ptr, int line, const char *source)
# pragma warning(pop)
#endif
- /* destroy */
- memset(mem->mem, 0x13, mem->size);
+ /* destroy */
+ mt_free_fill(mem->mem, mem->size);
/* free for real */
(Curl_cfree)(mem);
@@ -289,6 +329,24 @@ curl_socket_t curl_socket(int domain, int type, int protocol,
return sockfd;
}
+#ifdef HAVE_SOCKETPAIR
+int curl_socketpair(int domain, int type, int protocol,
+ curl_socket_t socket_vector[2],
+ int line, const char *source)
+{
+ const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
+ "FD %s:%d socketpair() = %d %d\n" :
+ (sizeof(curl_socket_t) == sizeof(long)) ?
+ "FD %s:%d socketpair() = %ld %ld\n" :
+ "FD %s:%d socketpair() = %zd %zd\n" ;
+
+ int res = socketpair(domain, type, protocol, socket_vector);
+ if(source && (0 == res))
+ curl_memlog(fmt, source, line, socket_vector[0], socket_vector[1]);
+ return res;
+}
+#endif
+
curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen,
int line, const char *source)
{
diff --git a/lib/memdebug.h b/lib/memdebug.h
index 77a4f4774..1e02645f9 100644
--- a/lib/memdebug.h
+++ b/lib/memdebug.h
@@ -1,6 +1,6 @@
+#ifndef HEADER_CURL_MEMDEBUG_H
+#define HEADER_CURL_MEMDEBUG_H
#ifdef CURLDEBUG
-#ifndef _CURL_MEMDEBUG_H
-#define _CURL_MEMDEBUG_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -32,14 +32,11 @@
#include <curl/curl.h>
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
-#include <stdio.h>
+
+#define CURL_MT_LOGFNAME_BUFSIZE 512
#define logfile curl_debuglogfile
@@ -66,6 +63,11 @@ CURL_EXTERN int curl_sclose(curl_socket_t sockfd,
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);
+#endif
/* FILE functions */
CURL_EXTERN FILE *curl_fopen(const char *file, const char *mode, int line,
@@ -91,6 +93,10 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
#undef accept /* for those with accept as a macro */
#define accept(sock,addr,len)\
curl_accept(sock,addr,len,__LINE__,__FILE__)
+#ifdef HAVE_SOCKETPAIR
+#define socketpair(domain,type,protocol,socket_vector)\
+ curl_socketpair(domain,type,protocol,socket_vector,__LINE__,__FILE__)
+#endif
#ifdef HAVE_GETADDRINFO
#if defined(getaddrinfo) && defined(__osf__)
@@ -133,9 +139,23 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
#endif /* MEMDEBUG_NODEFINES */
-#endif /* _CURL_MEMDEBUG_H */
#endif /* CURLDEBUG */
+/*
+** Following section applies even when CURLDEBUG is not defined.
+*/
+
#ifndef fake_sclose
-#define fake_sclose(x)
+#define fake_sclose(x) Curl_nop_stmt
#endif
+
+/*
+ * Curl_safefree defined as a macro to allow MemoryTracking feature
+ * to log free() calls at same location where Curl_safefree is used.
+ * This macro also assigns NULL to given pointer when free'd.
+ */
+
+#define Curl_safefree(ptr) \
+ do {if((ptr)) {free((ptr)); (ptr) = NULL;}} WHILE_FALSE
+
+#endif /* HEADER_CURL_MEMDEBUG_H */
diff --git a/lib/mk-ca-bundle.pl b/lib/mk-ca-bundle.pl
index 231762e60..189ed01b6 100755
--- a/lib/mk-ca-bundle.pl
+++ b/lib/mk-ca-bundle.pl
@@ -40,7 +40,7 @@ my $url = 'http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/
# If the OpenSSL commandline is not in search path you can configure it here!
my $openssl = 'openssl';
-my $version = '1.15';
+my $version = '1.16';
getopts('bhilnqtuv');
@@ -77,15 +77,13 @@ my $resp;
unless ($opt_n and -e $txt) {
print "Downloading '$txt' ...\n" if (!$opt_q);
-
my $ua = new LWP::UserAgent(agent => "$0/$version");
$ua->env_proxy();
$resp = $ua->mirror($url, $txt);
-}
-
-if ($resp && $resp->code eq '304') {
+ if ($resp && $resp->code eq '304') {
print "Not modified\n" unless $opt_q;
exit 0;
+ }
}
my $currentdate = scalar gmtime($resp ? $resp->last_modified : (stat($txt))[9]);
@@ -124,6 +122,7 @@ close(CRT) or die "Couldn't close $crt: $!";
print "Processing '$txt' ...\n" if (!$opt_q);
my $caname;
my $certnum = 0;
+my $skipnum = 0;
open(TXT,"$txt") or die "Couldn't open $txt: $!";
while (<TXT>) {
if (/\*\*\*\*\* BEGIN LICENSE BLOCK \*\*\*\*\*/) {
@@ -147,6 +146,7 @@ while (<TXT>) {
if (/^CKA_LABEL\s+[A-Z0-9]+\s+\"(.*)\"/) {
$caname = $1;
}
+ my $untrusted = 0;
if (/^CKA_VALUE MULTILINE_OCTAL/) {
my $data;
while (<TXT>) {
@@ -158,28 +158,37 @@ while (<TXT>) {
$data .= chr(oct);
}
}
- my $pem = "-----BEGIN CERTIFICATE-----\n"
- . MIME::Base64::encode($data)
- . "-----END CERTIFICATE-----\n";
- open(CRT, ">>$crt") or die "Couldn't open $crt: $!";
- print CRT "\n$caname\n";
- print CRT ("=" x length($caname) . "\n");
- if (!$opt_t) {
- print CRT $pem;
+ while (<TXT>) {
+ last if (/^#$/);
+ $untrusted = 1 if (/^CKA_TRUST_SERVER_AUTH\s+CK_TRUST\s+CKT_NSS_NOT_TRUSTED$/
+ or /^CKA_TRUST_SERVER_AUTH\s+CK_TRUST\s+CKT_NSS_TRUST_UNKNOWN$/);
}
- close(CRT) or die "Couldn't close $crt: $!";
- if ($opt_t) {
- open(TMP, "|$openssl x509 -md5 -fingerprint -text -inform PEM >> $crt") or die "Couldn't open openssl pipe: $!";
- print TMP $pem;
- close(TMP) or die "Couldn't close openssl pipe: $!";
+ if ($untrusted) {
+ $skipnum ++;
+ } else {
+ my $pem = "-----BEGIN CERTIFICATE-----\n"
+ . MIME::Base64::encode($data)
+ . "-----END CERTIFICATE-----\n";
+ open(CRT, ">>$crt") or die "Couldn't open $crt: $!";
+ print CRT "\n$caname\n";
+ print CRT ("=" x length($caname) . "\n");
+ if (!$opt_t) {
+ print CRT $pem;
+ }
+ close(CRT) or die "Couldn't close $crt: $!";
+ if ($opt_t) {
+ open(TMP, "|$openssl x509 -md5 -fingerprint -text -inform PEM >> $crt") or die "Couldn't open openssl pipe: $!";
+ print TMP $pem;
+ close(TMP) or die "Couldn't close openssl pipe: $!";
+ }
+ print "Parsing: $caname\n" if ($opt_v);
+ $certnum ++;
}
- print "Parsing: $caname\n" if ($opt_v);
- $certnum ++;
}
}
close(TXT) or die "Couldn't close $txt: $!";
unlink $txt if ($opt_u);
-print "Done ($certnum CA certs processed).\n" if (!$opt_q);
+print "Done ($certnum CA certs processed, $skipnum untrusted skipped).\n" if (!$opt_q);
exit;
diff --git a/lib/mprintf.c b/lib/mprintf.c
index dd7a1e09b..0990f4024 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -36,11 +36,6 @@
*/
#include "setup.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <string.h>
#if defined(DJGPP) && (DJGPP_MINOR < 4)
#undef _MPRINTF_REPLACE /* don't use x_was_used() here */
@@ -108,7 +103,7 @@ static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
done++; \
else \
return done; /* return immediately on failure */ \
- } while(0)
+ } WHILE_FALSE
/* Data type to read from the arglist */
typedef enum {
diff --git a/lib/multi.c b/lib/multi.c
index aee190cea..6e4ec37a8 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -41,6 +41,7 @@
#include "sendf.h"
#include "timeval.h"
#include "http.h"
+#include "select.h"
#include "warnless.h"
#define _MPRINTF_REPLACE /* use our functions only */
@@ -124,9 +125,9 @@ struct Curl_one_easy {
#define CURL_MULTI_HANDLE 0x000bab1e
#define GOOD_MULTI_HANDLE(x) \
- ((x)&&(((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
+ ((x) && (((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
#define GOOD_EASY_HANDLE(x) \
- (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER)
+ ((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER))
/* This is the struct known as CURLM on the outside */
struct Curl_multi {
@@ -134,7 +135,7 @@ struct Curl_multi {
this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */
long type;
- /* We have a linked list with easy handles */
+ /* We have a doubly-linked circular list with easy handles */
struct Curl_one_easy easy;
int num_easy; /* amount of entries in the linked list above. */
@@ -424,12 +425,13 @@ CURLM *curl_multi_init(void)
return (CURLM *) multi;
error:
- if(multi->sockhash)
- Curl_hash_destroy(multi->sockhash);
- if(multi->hostcache)
- Curl_hash_destroy(multi->hostcache);
- if(multi->connc)
- Curl_rm_connc(multi->connc);
+
+ Curl_hash_destroy(multi->sockhash);
+ multi->sockhash = NULL;
+ Curl_hash_destroy(multi->hostcache);
+ multi->hostcache = NULL;
+ Curl_rm_connc(multi->connc);
+ multi->connc = NULL;
free(multi);
return NULL;
@@ -438,11 +440,12 @@ CURLM *curl_multi_init(void)
CURLMcode curl_multi_add_handle(CURLM *multi_handle,
CURL *easy_handle)
{
- struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct curl_llist *timeoutlist;
struct Curl_one_easy *easy;
struct closure *cl;
- struct closure *prev=NULL;
- struct SessionHandle *data = easy_handle;
+ struct closure *prev = NULL;
+ struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
+ struct SessionHandle *data = (struct SessionHandle *)easy_handle;
/* First, make some basic checks that the CURLM handle is a good handle */
if(!GOOD_MULTI_HANDLE(multi))
@@ -452,39 +455,74 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
if(!GOOD_EASY_HANDLE(easy_handle))
return CURLM_BAD_EASY_HANDLE;
- /* Prevent users to add the same handle more than once! */
- if(((struct SessionHandle *)easy_handle)->multi)
+ /* Prevent users from adding same easy handle more than
+ once and prevent adding to more than one multi stack */
+ if(data->multi)
/* possibly we should create a new unique error code for this condition */
return CURLM_BAD_EASY_HANDLE;
- data->state.timeoutlist = Curl_llist_alloc(multi_freetimeout);
- if(!data->state.timeoutlist)
+ /* We want the connection cache to have plenty of room. Before we supported
+ the shared cache every single easy handle had 5 entries in their cache
+ by default. */
+ if(((multi->num_easy + 1) * 4) > multi->connc->num) {
+ long newmax = (multi->num_easy + 1) * 4;
+
+ if(multi->maxconnects && (newmax > multi->maxconnects))
+ /* don't grow beyond the allowed size */
+ newmax = multi->maxconnects;
+
+ if(newmax > multi->connc->num) {
+ /* we only do this is we can in fact grow the cache */
+ CURLcode res = Curl_ch_connc(data, multi->connc, newmax);
+ if(res)
+ return CURLM_OUT_OF_MEMORY;
+ }
+ }
+
+ /* Allocate and initialize timeout list for easy handle */
+ timeoutlist = Curl_llist_alloc(multi_freetimeout);
+ if(!timeoutlist)
return CURLM_OUT_OF_MEMORY;
- /* Now, time to add an easy handle to the multi stack */
+ /* Allocate new node for the doubly-linked circular list of
+ Curl_one_easy structs that holds pointers to easy handles */
easy = calloc(1, sizeof(struct Curl_one_easy));
- if(!easy)
+ if(!easy) {
+ Curl_llist_destroy(timeoutlist, NULL);
return CURLM_OUT_OF_MEMORY;
+ }
+
+ /*
+ ** No failure allowed in this function beyond this point. And
+ ** no modification of easy nor multi handle allowed before this
+ ** except for potential multi's connection cache growing which
+ ** won't be undone in this function no matter what.
+ */
+
+ /* Make easy handle use timeout list initialized above */
+ data->state.timeoutlist = timeoutlist;
+ timeoutlist = NULL;
+ /* Remove handle from the list of 'closure handles' in case it is there */
cl = multi->closure;
while(cl) {
struct closure *next = cl->next;
- if(cl->easy_handle == (struct SessionHandle *)easy_handle) {
- /* remove this handle from the closure list */
+ if(cl->easy_handle == data) {
+ /* Remove node from list */
free(cl);
if(prev)
prev->next = next;
else
multi->closure = next;
- break; /* no need to continue since this handle can only be present once
- in the list */
+ /* No need to continue, handle can only be present once in the list */
+ break;
}
prev = cl;
cl = next;
}
/* set the easy handle */
- easy->easy_handle = easy_handle;
+ easy->easy_handle = data;
multistate(easy, CURLM_STATE_INIT);
/* set the back pointer to one_easy to assist in removal */
@@ -505,25 +543,21 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
easy->easy_handle->dns.hostcachetype = HCACHE_MULTI;
}
- if(easy->easy_handle->state.connc) {
- if(easy->easy_handle->state.connc->type == CONNCACHE_PRIVATE) {
- /* kill old private version */
- Curl_rm_connc(easy->easy_handle->state.connc);
- /* point out our shared one instead */
- easy->easy_handle->state.connc = multi->connc;
- }
- /* else it is already using multi? */
+ /* On a multi stack the connection cache, owned by the multi handle,
+ is shared between all easy handles within the multi handle. */
+ if(easy->easy_handle->state.connc &&
+ (easy->easy_handle->state.connc->type == CONNCACHE_PRIVATE)) {
+ /* kill old private connection cache */
+ Curl_rm_connc(easy->easy_handle->state.connc);
+ easy->easy_handle->state.connc = NULL;
}
- else
- /* point out our shared one */
- easy->easy_handle->state.connc = multi->connc;
-
- /* Make sure the type is setup correctly */
+ /* Point now to this multi's connection cache */
+ easy->easy_handle->state.connc = multi->connc;
easy->easy_handle->state.connc->type = CONNCACHE_MULTI;
- /* This adds the new entry at the back of the list
- to try and maintain a FIFO queue so the pipelined
- requests are in order. */
+ /* This adds the new entry at the 'end' of the doubly-linked circular
+ list of Curl_one_easy structs to try and maintain a FIFO queue so
+ the pipelined requests are in order. */
/* We add this new entry last in the list. We make our 'next' point to the
'first' struct and our 'prev' point to the previous 'prev' */
@@ -537,6 +571,7 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
the new node */
easy->prev->next = easy;
+ /* make the SessionHandle refer back to this multi handle */
Curl_easy_addmulti(easy_handle, multi_handle);
/* make the SessionHandle struct refer back to this struct */
@@ -553,27 +588,6 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
/* increase the node-counter */
multi->num_easy++;
- if((multi->num_easy * 4) > multi->connc->num) {
- /* We want the connection cache to have plenty room. Before we supported
- the shared cache every single easy handle had 5 entries in their cache
- by default. */
- long newmax = multi->num_easy * 4;
-
- if(multi->maxconnects && (multi->maxconnects < newmax))
- /* don't grow beyond the allowed size */
- newmax = multi->maxconnects;
-
- if(newmax > multi->connc->num) {
- /* we only do this is we can in fact grow the cache */
- CURLcode res = Curl_ch_connc(easy_handle, multi->connc, newmax);
- if(res != CURLE_OK) {
- /* FIXME: may need to do more cleanup here */
- curl_multi_remove_handle(multi_handle, easy_handle);
- return CURLM_OUT_OF_MEMORY;
- }
- }
- }
-
/* increase the alive-counter */
multi->num_alive++;
@@ -628,9 +642,10 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
easy = data->multi_pos;
if(easy) {
- bool premature = (bool)(easy->state < CURLM_STATE_COMPLETED);
- bool easy_owns_conn = (bool)(easy->easy_conn &&
- (easy->easy_conn->data == easy->easy_handle));
+ bool premature = (easy->state < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
+ bool easy_owns_conn = (easy->easy_conn &&
+ (easy->easy_conn->data == easy->easy_handle)) ?
+ TRUE : FALSE;
/* If the 'state' is not INIT or COMPLETED, we might need to do something
nice to put the easy_handle in a good known state when this returns. */
@@ -801,20 +816,12 @@ static int waitconnect_getsock(struct connectdata *conn,
}
static int domore_getsock(struct connectdata *conn,
- curl_socket_t *sock,
+ curl_socket_t *socks,
int numsocks)
{
- if(!numsocks)
- return GETSOCK_BLANK;
-
- /* When in DO_MORE state, we could be either waiting for us
- to connect to a remote site, or we could wait for that site
- to connect to us. It makes a difference in the way: if we
- connect to the site we wait for the socket to become writable, if
- the site connects to us we wait for it to become readable */
- sock[0] = conn->sock[SECONDARYSOCKET];
-
- return GETSOCK_WRITESOCK(0);
+ if(conn && conn->handler->domore_getsock)
+ return conn->handler->domore_getsock(conn, socks, numsocks);
+ return GETSOCK_BLANK;
}
/* returns bitmapped flags for this handle and its sockets */
@@ -906,11 +913,11 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
curl_socket_t s = CURL_SOCKET_BAD;
- if(bitmap & GETSOCK_READSOCK(i)) {
+ if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
FD_SET(sockbunch[i], read_fd_set);
s = sockbunch[i];
}
- if(bitmap & GETSOCK_WRITESOCK(i)) {
+ if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
FD_SET(sockbunch[i], write_fd_set);
s = sockbunch[i];
}
@@ -952,8 +959,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data = easy->easy_handle;
do {
- /* this is a do-while loop just to allow a break to skip to the end
- of it */
+ /* this is a single-iteration do-while loop just to allow a
+ break to skip to the end of it */
bool disconnect_conn = FALSE;
/* Handle the case when the pipe breaks, i.e., the connection
@@ -1039,7 +1046,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* Add this handle to the send or pend pipeline */
easy->result = addHandleToSendOrPendPipeline(data,
easy->easy_conn);
- if(CURLE_OK == easy->result) {
+ if(CURLE_OK != easy->result)
+ disconnect_conn = TRUE;
+ else {
if(async)
/* We're now waiting for an asynchronous name lookup */
multistate(easy, CURLM_STATE_WAITRESOLVE);
@@ -1282,7 +1291,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
disconnect_conn = TRUE;
}
else
- retry = (bool)(newurl?TRUE:FALSE);
+ retry = (newurl)?TRUE:FALSE;
Curl_posttransfer(data);
drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
@@ -1481,14 +1490,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
Curl_posttransfer(data);
Curl_done(&easy->easy_conn, easy->result, FALSE);
}
- else if(TRUE == done) {
+ else if(done) {
char *newurl = NULL;
bool retry = FALSE;
followtype follow=FOLLOW_NONE;
easy->result = Curl_retry_request(easy->easy_conn, &newurl);
if(!easy->result)
- retry = (bool)(newurl?TRUE:FALSE);
+ retry = (newurl)?TRUE:FALSE;
/* call this even if the readwrite function returned error */
Curl_posttransfer(data);
@@ -1537,8 +1546,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
newurl = data->req.location;
data->req.location = NULL;
easy->result = Curl_follow(data, newurl, FOLLOW_FAKE);
- if(easy->result)
+ if(easy->result) {
+ disconnect_conn = TRUE;
free(newurl);
+ }
}
multistate(easy, CURLM_STATE_DONE);
@@ -1615,7 +1626,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
return CURLM_INTERNAL_ERROR;
}
- if(CURLM_STATE_COMPLETED > easy->state) {
+ if(easy->state < CURLM_STATE_COMPLETED) {
if(CURLE_OK != easy->result) {
/*
* If an error was returned, and we aren't in completed state now,
@@ -1639,25 +1650,37 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
easy->easy_conn->done_pipe);
/* Check if we can move pending requests to send pipe */
checkPendPipeline(easy->easy_conn);
- }
- if(disconnect_conn) {
- /* disconnect properly */
- Curl_disconnect(easy->easy_conn, /* dead_connection */ FALSE);
+ if(disconnect_conn) {
+ /* disconnect properly */
+ Curl_disconnect(easy->easy_conn, /* dead_connection */ FALSE);
- /* This is where we make sure that the easy_conn pointer is reset.
- We don't have to do this in every case block above where a
- failure is detected */
- easy->easy_conn = NULL;
+ /* This is where we make sure that the easy_conn pointer is reset.
+ We don't have to do this in every case block above where a
+ failure is detected */
+ easy->easy_conn = NULL;
+ }
+ }
+ else if(easy->state == CURLM_STATE_CONNECT) {
+ /* Curl_connect() failed */
+ (void)Curl_posttransfer(data);
}
multistate(easy, CURLM_STATE_COMPLETED);
}
/* if there's still a connection to use, call the progress function */
- else if(easy->easy_conn && Curl_pgrsUpdate(easy->easy_conn))
- easy->result = CURLE_ABORTED_BY_CALLBACK;
+ else if(easy->easy_conn && Curl_pgrsUpdate(easy->easy_conn)) {
+ /* aborted due to progress callback return code must close the
+ connection */
+ easy->easy_conn->bits.close = TRUE;
+
+ /* if not yet in DONE state, go there, otherwise COMPLETED */
+ multistate(easy, (easy->state < CURLM_STATE_DONE)?
+ CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
}
- } while(0);
+ } WHILE_FALSE; /* just to break out from! */
if(CURLM_STATE_COMPLETED == easy->state) {
if(data->dns.hostcachetype == HCACHE_MULTI) {
@@ -1787,9 +1810,11 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
}
Curl_rm_connc(multi->connc);
+ multi->connc = NULL;
/* remove the pending list of messages */
Curl_llist_destroy(multi->msglist, NULL);
+ multi->msglist = NULL;
/* remove all easy handles */
easy = multi->easy.next;
@@ -2213,7 +2238,7 @@ CURLMcode curl_multi_setopt(CURLM *multi_handle,
multi->socket_userp = va_arg(param, void *);
break;
case CURLMOPT_PIPELINING:
- multi->pipelining_enabled = (bool)(0 != va_arg(param, long));
+ multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
case CURLMOPT_TIMERFUNCTION:
multi->timer_cb = va_arg(param, curl_multi_timer_callback);
@@ -2478,7 +2503,7 @@ static bool isHandleAtHead(struct SessionHandle *handle,
{
struct curl_llist_element *curr = pipeline->head;
if(curr)
- return (bool)(curr->ptr == handle);
+ return (curr->ptr == handle) ? TRUE : FALSE;
return FALSE;
}
diff --git a/lib/netrc.c b/lib/netrc.c
index 5541a2f29..6764b974d 100644
--- a/lib/netrc.c
+++ b/lib/netrc.c
@@ -22,10 +22,6 @@
#include "setup.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
diff --git a/lib/non-ascii.h b/lib/non-ascii.h
index 4e303dff8..6dcbe0044 100644
--- a/lib/non-ascii.h
+++ b/lib/non-ascii.h
@@ -51,9 +51,9 @@ CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
CURLcode Curl_convert_form(struct SessionHandle *data, struct FormData *form);
#else
#define Curl_convert_clone(a,b,c,d) ((void)a, CURLE_OK)
-#define Curl_convert_init(x)
-#define Curl_convert_setup(x)
-#define Curl_convert_close(x)
+#define Curl_convert_init(x) Curl_nop_stmt
+#define Curl_convert_setup(x) Curl_nop_stmt
+#define Curl_convert_close(x) Curl_nop_stmt
#define Curl_convert_to_network(a,b,c) ((void)a, CURLE_OK)
#define Curl_convert_from_network(a,b,c) ((void)a, CURLE_OK)
#define Curl_convert_from_utf8(a,b,c) ((void)a, CURLE_OK)
diff --git a/lib/nonblock.c b/lib/nonblock.c
index cd819506c..529ce8bca 100644
--- a/lib/nonblock.c
+++ b/lib/nonblock.c
@@ -34,9 +34,6 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
#include <sys/filio.h>
@@ -65,7 +62,7 @@ int curlx_nonblock(curl_socket_t sockfd, /* operate on this */
/* most recent unix versions */
int flags;
flags = fcntl(sockfd, F_GETFL, 0);
- if(FALSE != nonblock)
+ if(nonblock)
return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
else
return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));
@@ -73,26 +70,25 @@ int curlx_nonblock(curl_socket_t sockfd, /* operate on this */
#elif defined(HAVE_IOCTL_FIONBIO)
/* older unix versions */
- int flags;
- flags = nonblock;
+ int flags = nonblock ? 1 : 0;
return ioctl(sockfd, FIONBIO, &flags);
#elif defined(HAVE_IOCTLSOCKET_FIONBIO)
/* Windows */
- unsigned long flags;
- flags = nonblock;
+ unsigned long flags = nonblock ? 1UL : 0UL;
return ioctlsocket(sockfd, FIONBIO, &flags);
#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO)
/* Amiga */
- return IoctlSocket(sockfd, FIONBIO, (long)nonblock);
+ long flags = nonblock ? 1L : 0L;
+ return IoctlSocket(sockfd, FIONBIO, flags);
#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK)
/* BeOS */
- long b = nonblock ? 1 : 0;
+ long b = nonblock ? 1L : 0L;
return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
#else
diff --git a/lib/nss.c b/lib/nss.c
index 3dc0ba61c..f63d9718b 100644
--- a/lib/nss.c
+++ b/lib/nss.c
@@ -27,9 +27,6 @@
#include "setup.h"
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -95,7 +92,7 @@ typedef struct {
ptr->type = (_type); \
ptr->pValue = (_val); \
ptr->ulValueLen = (_len); \
-} while(0)
+} WHILE_FALSE
#define CERT_NewTempCertificate __CERT_NewTempCertificate
@@ -281,17 +278,16 @@ static int is_file(const char *filename)
return 0;
}
-/* Return on heap allocated filename/nickname of a certificate. The returned
- * string should be later deallocated using free(). *is_nickname is set to
- * TRUE if the given string is treated as nickname; FALSE if the given string
- * is treated as file name.
+/* Check if the given string is filename or nickname of a certificate. If the
+ * given string is recognized as filename, return NULL. If the given string is
+ * recognized as nickname, return a duplicated string. The returned string
+ * should be later deallocated using free(). If the OOM failure occurs, we
+ * return NULL, too.
*/
-static char *fmt_nickname(struct SessionHandle *data, enum dupstring cert_kind,
- bool *is_nickname)
+static char* dup_nickname(struct SessionHandle *data, enum dupstring cert_kind)
{
const char *str = data->set.str[cert_kind];
const char *n;
- *is_nickname = TRUE;
if(!is_file(str))
/* no such file exists, use the string as nickname */
@@ -306,10 +302,7 @@ static char *fmt_nickname(struct SessionHandle *data, enum dupstring cert_kind,
}
/* we'll use the PEM reader to read the certificate from file */
- *is_nickname = FALSE;
-
- n++; /* skip last slash */
- return aprintf("PEM Token #%d:%s", 1, n);
+ return NULL;
}
#ifdef HAVE_PK11_CREATEGENERICOBJECT
@@ -326,6 +319,9 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
CK_BBOOL ckfalse = CK_FALSE;
CK_ATTRIBUTE attrs[/* max count of attributes */ 4];
int attr_cnt = 0;
+ CURLcode err = (cacert)
+ ? CURLE_SSL_CACERT_BADFILE
+ : CURLE_SSL_CERTPROBLEM;
const int slot_id = (cacert) ? 0 : 1;
char *slot_name = aprintf("PEM Token #%d", slot_id);
@@ -335,7 +331,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
slot = PK11_FindSlotByName(slot_name);
free(slot_name);
if(!slot)
- return CURLE_SSL_CERTPROBLEM;
+ return err;
PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class));
PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
@@ -350,13 +346,17 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE);
PK11_FreeSlot(slot);
if(!obj)
- return CURLE_SSL_CERTPROBLEM;
+ return err;
if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) {
PK11_DestroyGenericObject(obj);
return CURLE_OUT_OF_MEMORY;
}
+ if(!cacert && CKO_CERTIFICATE == obj_class)
+ /* store reference to a client certificate */
+ ssl->obj_clicert = obj;
+
return CURLE_OK;
}
@@ -371,76 +371,43 @@ static void nss_destroy_object(void *user, void *ptr)
}
#endif
-static int nss_load_cert(struct ssl_connect_data *ssl,
- const char *filename, PRBool cacert)
+static CURLcode nss_load_cert(struct ssl_connect_data *ssl,
+ const char *filename, PRBool cacert)
{
-#ifdef HAVE_PK11_CREATEGENERICOBJECT
- /* All CA and trust objects go into slot 0. Other slots are used
- * for storing certificates.
- */
- const int slot_id = (cacert) ? 0 : 1;
-#endif
- CERTCertificate *cert;
- char *nickname = NULL;
- char *n = NULL;
+ CURLcode err = (cacert)
+ ? CURLE_SSL_CACERT_BADFILE
+ : CURLE_SSL_CERTPROBLEM;
- /* If there is no slash in the filename it is assumed to be a regular
- * NSS nickname.
- */
- if(is_file(filename)) {
- n = strrchr(filename, '/');
+#ifdef HAVE_PK11_CREATEGENERICOBJECT
+ /* libnsspem.so leaks memory if the requested file does not exist. For more
+ * details, go to <https://bugzilla.redhat.com/734760>. */
+ if(is_file(filename))
+ err = nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert);
+
+ if(CURLE_OK == err && !cacert) {
+ /* we have successfully loaded a client certificate */
+ CERTCertificate *cert;
+ char *nickname = NULL;
+ char *n = strrchr(filename, '/');
if(n)
n++;
- if(!mod)
- return 1;
- }
- else {
- /* A nickname from the NSS internal database */
- if(cacert)
- return 0; /* You can't specify an NSS CA nickname this way */
- nickname = strdup(filename);
- if(!nickname)
- return 0;
- goto done;
- }
-
-#ifdef HAVE_PK11_CREATEGENERICOBJECT
- nickname = aprintf("PEM Token #%d:%s", slot_id, n);
- if(!nickname)
- return 0;
-
- if(CURLE_OK != nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert)) {
- free(nickname);
- return 0;
- }
-#else
- /* We don't have PK11_CreateGenericObject but a file-based cert was passed
- * in. We need to fail.
- */
- return 0;
-#endif
+ /* The following undocumented magic helps to avoid a SIGSEGV on call
+ * of PK11_ReadRawAttribute() from SelectClientCert() when using an
+ * immature version of libnsspem.so. For more details, go to
+ * <https://bugzilla.redhat.com/733685>. */
+ nickname = aprintf("PEM Token #1:%s", n);
+ if(nickname) {
+ cert = PK11_FindCertFromNickname(nickname, NULL);
+ if(cert)
+ CERT_DestroyCertificate(cert);
- done:
- /* Double-check that the certificate or nickname requested exists in
- * either the token or the NSS certificate database.
- */
- if(!cacert) {
- cert = PK11_FindCertFromNickname((char *)nickname, NULL);
-
- /* An invalid nickname was passed in */
- if(cert == NULL) {
free(nickname);
- PR_SetError(SEC_ERROR_UNKNOWN_CERT, 0);
- return 0;
}
-
- CERT_DestroyCertificate(cert);
}
+#endif
- free(nickname);
-
- return 1;
+ return err;
}
/* add given CRL to cache if it is not already there */
@@ -529,23 +496,23 @@ fail:
return SECFailure;
}
-static int nss_load_key(struct connectdata *conn, int sockindex,
- char *key_file)
+static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
+ char *key_file)
{
#ifdef HAVE_PK11_CREATEGENERICOBJECT
PK11SlotInfo *slot;
SECStatus status;
struct ssl_connect_data *ssl = conn->ssl;
- (void)sockindex; /* unused */
- if(CURLE_OK != nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE)) {
+ CURLcode rv = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE);
+ if(CURLE_OK != rv) {
PR_SetError(SEC_ERROR_BAD_KEY, 0);
- return 0;
+ return rv;
}
slot = PK11_FindSlotByName("PEM Token #1");
if(!slot)
- return 0;
+ return CURLE_SSL_CERTPROBLEM;
/* This will force the token to be seen as re-inserted */
SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
@@ -554,16 +521,18 @@ static int nss_load_key(struct connectdata *conn, int sockindex,
status = PK11_Authenticate(slot, PR_TRUE,
conn->data->set.str[STRING_KEY_PASSWD]);
PK11_FreeSlot(slot);
- return (SECSuccess == status) ? 1 : 0;
+ return (SECSuccess == status)
+ ? CURLE_OK
+ : CURLE_SSL_CERTPROBLEM;
#else
/* If we don't have PK11_CreateGenericObject then we can't load a file-based
* key.
*/
(void)conn; /* unused */
(void)key_file; /* unused */
- (void)sockindex; /* unused */
- return 0;
+ return CURLE_SSL_CERTPROBLEM;
#endif
+ (void)sockindex; /* unused */
}
static int display_error(struct connectdata *conn, PRInt32 err,
@@ -582,34 +551,37 @@ static int display_error(struct connectdata *conn, PRInt32 err,
return 0; /* The caller will print a generic error */
}
-static int cert_stuff(struct connectdata *conn,
- int sockindex, char *cert_file, char *key_file)
+static CURLcode cert_stuff(struct connectdata *conn, int sockindex,
+ char *cert_file, char *key_file)
{
struct SessionHandle *data = conn->data;
- int rv = 0;
+ CURLcode rv;
if(cert_file) {
rv = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE);
- if(!rv) {
+ if(CURLE_OK != rv) {
if(!display_error(conn, PR_GetError(), cert_file))
failf(data, "Unable to load client cert %d.", PR_GetError());
- return 0;
+
+ return rv;
}
}
+
if(key_file || (is_file(cert_file))) {
if(key_file)
rv = nss_load_key(conn, sockindex, key_file);
else
/* In case the cert file also has the key */
rv = nss_load_key(conn, sockindex, cert_file);
- if(!rv) {
+ if(CURLE_OK != rv) {
if(!display_error(conn, PR_GetError(), key_file))
failf(data, "Unable to load client key %d.", PR_GetError());
- return 0;
+ return rv;
}
}
- return 1;
+
+ return CURLE_OK;
}
static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg)
@@ -776,7 +748,6 @@ static SECStatus check_issuer_cert(PRFileDesc *sock,
cert_issuer = CERT_FindCertIssuer(cert,PR_Now(),certUsageObjectSigner);
proto_win = SSL_RevealPinArg(sock);
- issuer = NULL;
issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win);
if((!cert_issuer) || (!issuer))
@@ -800,44 +771,51 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
struct CERTCertificateStr **pRetCert,
struct SECKEYPrivateKeyStr **pRetKey)
{
- static const char pem_nickname[] = "PEM Token #1";
- const char *pem_slotname = pem_nickname;
-
struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
struct SessionHandle *data = connssl->data;
const char *nickname = connssl->client_nickname;
- if(mod && nickname &&
- 0 == strncmp(nickname, pem_nickname, /* length of "PEM Token" */ 9)) {
-
+#ifdef HAVE_PK11_CREATEGENERICOBJECT
+ if(connssl->obj_clicert) {
/* use the cert/key provided by PEM reader */
- PK11SlotInfo *slot;
+ static const char pem_slotname[] = "PEM Token #1";
+ SECItem cert_der = { 0, NULL, 0 };
void *proto_win = SSL_RevealPinArg(sock);
- *pRetKey = NULL;
- *pRetCert = PK11_FindCertFromNickname(nickname, proto_win);
- if(NULL == *pRetCert) {
- failf(data, "NSS: client certificate not found: %s", nickname);
+ PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname);
+ if(NULL == slot) {
+ failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
return SECFailure;
}
- slot = PK11_FindSlotByName(pem_slotname);
- if(NULL == slot) {
- failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
+ if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE,
+ &cert_der) != SECSuccess) {
+ failf(data, "NSS: CKA_VALUE not found in PK11 generic object");
+ PK11_FreeSlot(slot);
+ return SECFailure;
+ }
+
+ *pRetCert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win);
+ SECITEM_FreeItem(&cert_der, PR_FALSE);
+ if(NULL == *pRetCert) {
+ failf(data, "NSS: client certificate from file not found");
+ PK11_FreeSlot(slot);
return SECFailure;
}
*pRetKey = PK11_FindPrivateKeyFromCert(slot, *pRetCert, NULL);
PK11_FreeSlot(slot);
if(NULL == *pRetKey) {
- failf(data, "NSS: private key not found for certificate: %s", nickname);
+ failf(data, "NSS: private key from file not found");
+ CERT_DestroyCertificate(*pRetCert);
return SECFailure;
}
- infof(data, "NSS: client certificate: %s\n", nickname);
+ infof(data, "NSS: client certificate from file\n");
display_cert_info(data, *pRetCert);
return SECSuccess;
}
+#endif
/* use the default NSS hook */
if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames,
@@ -898,10 +876,42 @@ isTLSIntoleranceError(PRInt32 err)
}
}
-static CURLcode init_nss(struct SessionHandle *data)
+static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir)
+{
+ if(NSS_IsInitialized())
+ return CURLE_OK;
+
+ if(cert_dir) {
+ SECStatus rv;
+ const bool use_sql = NSS_VersionCheck("3.12.0");
+ char *certpath = aprintf("%s%s", use_sql ? "sql:" : "", cert_dir);
+ if(!certpath)
+ return CURLE_OUT_OF_MEMORY;
+
+ infof(data, "Initializing NSS with certpath: %s\n", certpath);
+ rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY);
+ free(certpath);
+
+ if(rv == SECSuccess)
+ return CURLE_OK;
+
+ infof(data, "Unable to initialize NSS database\n");
+ }
+
+ infof(data, "Initializing NSS with certpath: none\n");
+ if(NSS_NoDB_Init(NULL) == SECSuccess)
+ return CURLE_OK;
+
+ infof(data, "Unable to initialize NSS\n");
+ return CURLE_SSL_CACERT_BADFILE;
+}
+
+static CURLcode nss_init(struct SessionHandle *data)
{
char *cert_dir;
struct_stat st;
+ CURLcode rv;
+
if(initialized)
return CURLE_OK;
@@ -922,31 +932,14 @@ static CURLcode init_nss(struct SessionHandle *data)
}
}
- if(!NSS_IsInitialized()) {
- SECStatus rv;
- initialized = 1;
- infof(data, "Initializing NSS with certpath: %s\n",
- cert_dir ? cert_dir : "none");
- if(!cert_dir) {
- rv = NSS_NoDB_Init(NULL);
- }
- else {
- char *certpath =
- PR_smprintf("%s%s", NSS_VersionCheck("3.12.0") ? "sql:" : "",
- cert_dir);
- rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY);
- PR_smprintf_free(certpath);
- }
- if(rv != SECSuccess) {
- infof(data, "Unable to initialize NSS database\n");
- initialized = 0;
- return CURLE_SSL_CACERT_BADFILE;
- }
- }
+ rv = nss_init_core(data, cert_dir);
+ if(rv)
+ return rv;
if(num_enabled_ciphers() == 0)
NSS_SetDomesticPolicy();
+ initialized = 1;
return CURLE_OK;
}
@@ -981,7 +974,7 @@ CURLcode Curl_nss_force_init(struct SessionHandle *data)
}
PR_Lock(nss_initlock);
- rv = init_nss(data);
+ rv = nss_init(data);
PR_Unlock(nss_initlock);
return rv;
}
@@ -1064,6 +1057,7 @@ void Curl_nss_close(struct connectdata *conn, int sockindex)
/* destroy all NSS objects in order to avoid failure of NSS shutdown */
Curl_llist_destroy(connssl->obj_list, NULL);
connssl->obj_list = NULL;
+ connssl->obj_clicert = NULL;
#endif
PR_Close(connssl->handle);
connssl->handle = NULL;
@@ -1111,8 +1105,11 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
const char *cafile = data->set.ssl.CAfile;
const char *capath = data->set.ssl.CApath;
- if(cafile && !nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE))
- return CURLE_SSL_CACERT_BADFILE;
+ if(cafile) {
+ CURLcode rv = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
+ if(CURLE_OK != rv)
+ return rv;
+ }
if(capath) {
struct_stat st;
@@ -1132,7 +1129,7 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
- if(!nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE))
+ if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE))
/* This is purposefully tolerant of errors so non-PEM files can
* be in the same directory */
infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath);
@@ -1184,7 +1181,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
/* FIXME. NSS doesn't support multiple databases open at the same time. */
PR_Lock(nss_initlock);
- curlerr = init_nss(conn->data);
+ curlerr = nss_init(conn->data);
if(CURLE_OK != curlerr) {
PR_Unlock(nss_initlock);
goto error;
@@ -1327,16 +1324,21 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
}
if(data->set.str[STRING_CERT]) {
- bool is_nickname;
- char *nickname = fmt_nickname(data, STRING_CERT, &is_nickname);
- if(!nickname)
- return CURLE_OUT_OF_MEMORY;
-
- if(!is_nickname && !cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
- data->set.str[STRING_KEY])) {
- /* failf() is already done in cert_stuff() */
- free(nickname);
- return CURLE_SSL_CERTPROBLEM;
+ char *nickname = dup_nickname(data, STRING_CERT);
+ if(nickname) {
+ /* we are not going to use libnsspem.so to read the client cert */
+#ifdef HAVE_PK11_CREATEGENERICOBJECT
+ connssl->obj_clicert = NULL;
+#endif
+ }
+ else {
+ CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
+ data->set.str[STRING_KEY]);
+ if(CURLE_OK != rv) {
+ /* failf() is already done in cert_stuff() */
+ curlerr = rv;
+ goto error;
+ }
}
/* store the nickname for SelectClientCert() called during handshake */
@@ -1395,16 +1397,12 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
if(data->set.str[STRING_SSL_ISSUERCERT]) {
SECStatus ret = SECFailure;
- bool is_nickname;
- char *nickname = fmt_nickname(data, STRING_SSL_ISSUERCERT, &is_nickname);
- if(!nickname)
- return CURLE_OUT_OF_MEMORY;
-
- if(is_nickname)
+ char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT);
+ if(nickname) {
/* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */
ret = check_issuer_cert(connssl->handle, nickname);
-
- free(nickname);
+ free(nickname);
+ }
if(SECFailure == ret) {
infof(data,"SSL certificate issuer check failed\n");
diff --git a/lib/nssg.h b/lib/nssg.h
index 438d5a636..4d7df5efa 100644
--- a/lib/nssg.h
+++ b/lib/nssg.h
@@ -1,5 +1,5 @@
-#ifndef __NSSG_H
-#define __NSSG_H
+#ifndef HEADER_CURL_NSSG_H
+#define HEADER_CURL_NSSG_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -21,6 +21,7 @@
* KIND, either express or implied.
*
***************************************************************************/
+#include "setup.h"
#ifdef USE_NSS
/*
@@ -28,6 +29,7 @@
*/
#include "urldata.h"
+
CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex);
CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
int sockindex,
@@ -55,7 +57,7 @@ CURLcode Curl_nss_force_init(struct SessionHandle *data);
#define curlssl_connect Curl_nss_connect
/* NSS has its own session ID cache */
-#define curlssl_session_free(x)
+#define curlssl_session_free(x) Curl_nop_stmt
#define curlssl_close_all Curl_nss_close_all
#define curlssl_close Curl_nss_close
/* NSS has no shutdown function provided and thus always fail */
@@ -68,4 +70,4 @@ CURLcode Curl_nss_force_init(struct SessionHandle *data);
#define curlssl_data_pending(x,y) (x=x, y=y, 0)
#endif /* USE_NSS */
-#endif
+#endif /* HEADER_CURL_NSSG_H */
diff --git a/lib/nwlib.c b/lib/nwlib.c
index f9c8a4298..c87ca0d29 100644
--- a/lib/nwlib.c
+++ b/lib/nwlib.c
@@ -20,14 +20,12 @@
*
***************************************************************************/
-#ifdef NETWARE /* Novell NetWare */
+#include "setup.h"
-#include <stdlib.h>
+#ifdef NETWARE /* Novell NetWare */
#ifdef __NOVELL_LIBC__
/* For native LibC-based NLM we need to register as a real lib. */
-#include <errno.h>
-#include <string.h>
#include <library.h>
#include <netware.h>
#include <screen.h>
diff --git a/lib/nwos.c b/lib/nwos.c
index ac365124f..bd695b3f9 100644
--- a/lib/nwos.c
+++ b/lib/nwos.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 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,9 +20,9 @@
*
***************************************************************************/
-#ifdef NETWARE /* Novell NetWare */
+#include "setup.h"
-#include <stdlib.h>
+#ifdef NETWARE /* Novell NetWare */
#ifdef __NOVELL_LIBC__
/* For native LibC-based NLM we need to do nothing. */
@@ -34,7 +34,6 @@ int netware_init ( void )
#else /* __NOVELL_LIBC__ */
/* For native CLib-based NLM we need to initialize the LONG namespace. */
-#include <stdio.h>
#include <nwnspace.h>
#include <nwthread.h>
#include <nwadv.h>
@@ -86,10 +85,4 @@ int __deinit_environment ( void )
#endif /* __NOVELL_LIBC__ */
-#else /* NETWARE */
-
-#ifdef __POCC__
-# pragma warn(disable:2024) /* Disable warning #2024: Empty input file */
-#endif
-
#endif /* NETWARE */
diff --git a/lib/openldap.c b/lib/openldap.c
index 69523cb37..e5a3369a1 100644
--- a/lib/openldap.c
+++ b/lib/openldap.c
@@ -83,6 +83,7 @@ const struct Curl_handler Curl_handler_ldap = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ldap_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -107,6 +108,7 @@ const struct Curl_handler Curl_handler_ldaps = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ldap_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -544,12 +546,21 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
}
}
if(binary || binval) {
- char *val_b64;
+ char *val_b64 = NULL;
+ size_t val_b64_sz = 0;
/* Binary value, encode to base64. */
- size_t val_b64_sz = Curl_base64_encode(data,
- bvals[i].bv_val,
- bvals[i].bv_len,
- &val_b64);
+ CURLcode error = Curl_base64_encode(data,
+ bvals[i].bv_val,
+ bvals[i].bv_len,
+ &val_b64,
+ &val_b64_sz);
+ if(error) {
+ ber_memfree(bvals);
+ ber_free(ber, 0);
+ ldap_msgfree(result);
+ *err = error;
+ return -1;
+ }
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
data->req.bytecount += 2;
if(val_b64_sz > 0) {
diff --git a/lib/parsedate.c b/lib/parsedate.c
index 62f1a4181..ec60e78e7 100644
--- a/lib/parsedate.c
+++ b/lib/parsedate.c
@@ -72,14 +72,8 @@
20040911 +0200
*/
-#include "setup.h"
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h> /* for strtol() */
-#endif
+#include "setup.h"
#include <curl/curl.h>
#include "rawstr.h"
diff --git a/lib/pingpong.c b/lib/pingpong.c
index 23ab69fb2..84ce88148 100644
--- a/lib/pingpong.c
+++ b/lib/pingpong.c
@@ -177,9 +177,6 @@ void Curl_pp_init(struct pingpong *pp)
* the string should not have any CRLF appended, as this function will
* append the necessary things itself.
*
- * NOTE: we build the command in a fixed-length buffer, which sets length
- * restrictions on the command!
- *
* made to never block
*/
CURLcode Curl_pp_vsendf(struct pingpong *pp,
@@ -187,12 +184,10 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
va_list args)
{
ssize_t bytes_written;
-/* may still not be big enough for some krb5 tokens */
-#define SBUF_SIZE 1024
- char s[SBUF_SIZE];
size_t write_len;
- char *sptr=s;
- CURLcode res = CURLE_OK;
+ char *fmt_crlf;
+ char *s;
+ CURLcode error;
struct connectdata *conn = pp->conn;
struct SessionHandle *data = conn->data;
@@ -200,55 +195,64 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
enum protection_level data_sec = conn->data_prot;
#endif
- vsnprintf(s, SBUF_SIZE-3, fmt, args);
+ DEBUGASSERT(pp->sendleft == 0);
+ DEBUGASSERT(pp->sendsize == 0);
+ DEBUGASSERT(pp->sendthis == NULL);
+
+ fmt_crlf = aprintf("%s\r\n", fmt); /* append a trailing CRLF */
+ if(!fmt_crlf)
+ return CURLE_OUT_OF_MEMORY;
- strcat(s, "\r\n"); /* append a trailing CRLF */
+ s = vaprintf(fmt_crlf, args); /* trailing CRLF appended */
+ free(fmt_crlf);
+ if(!s)
+ return CURLE_OUT_OF_MEMORY;
- bytes_written=0;
+ bytes_written = 0;
write_len = strlen(s);
Curl_pp_init(pp);
- res = Curl_convert_to_network(data, s, write_len);
+ error = Curl_convert_to_network(data, s, write_len);
/* Curl_convert_to_network calls failf if unsuccessful */
- if(res)
- return res;
+ if(error) {
+ free(s);
+ return error;
+ }
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
conn->data_prot = PROT_CMD;
#endif
- res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
- &bytes_written);
+ error = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len,
+ &bytes_written);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
conn->data_prot = data_sec;
#endif
- if(CURLE_OK != res)
- return res;
+ if(error) {
+ free(s);
+ return error;
+ }
if(conn->data->set.verbose)
Curl_debug(conn->data, CURLINFO_HEADER_OUT,
- sptr, (size_t)bytes_written, conn);
+ s, (size_t)bytes_written, conn);
if(bytes_written != (ssize_t)write_len) {
- /* the whole chunk was not sent, store the rest of the data */
- write_len -= bytes_written;
- sptr += bytes_written;
- pp->sendthis = malloc(write_len);
- if(pp->sendthis) {
- memcpy(pp->sendthis, sptr, write_len);
- pp->sendsize = pp->sendleft = write_len;
- }
- else {
- failf(data, "out of memory");
- res = CURLE_OUT_OF_MEMORY;
- }
+ /* the whole chunk was not sent, keep it around and adjust sizes */
+ pp->sendthis = s;
+ pp->sendsize = write_len;
+ pp->sendleft = write_len - bytes_written;
}
- else
+ else {
+ free(s);
+ pp->sendthis = NULL;
+ pp->sendleft = pp->sendsize = 0;
pp->response = Curl_tvnow();
+ }
- return res;
+ return CURLE_OK;
}
@@ -260,9 +264,6 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
* the string should not have any CRLF appended, as this function will
* append the necessary things itself.
*
- * NOTE: we build the command in a fixed-length buffer, which sets length
- * restrictions on the command!
- *
* made to never block
*/
CURLcode Curl_pp_sendf(struct pingpong *pp,
diff --git a/lib/pingpong.h b/lib/pingpong.h
index cbbff8f3e..1d104cfbc 100644
--- a/lib/pingpong.h
+++ b/lib/pingpong.h
@@ -1,5 +1,5 @@
-#ifndef __PINGPONG_H
-#define __PINGPONG_H
+#ifndef HEADER_CURL_PINGPONG_H
+#define HEADER_CURL_PINGPONG_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 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,8 +22,6 @@
*
***************************************************************************/
-#include <stdarg.h>
-
#include "setup.h"
#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_FTP) || \
@@ -100,9 +98,6 @@ long Curl_pp_state_timeout(struct pingpong *pp);
* the string should not have any CRLF appended, as this function will
* append the necessary things itself.
*
- * NOTE: we build the command in a fixed-length buffer, which sets length
- * restrictions on the command!
- *
* made to never block
*/
CURLcode Curl_pp_sendf(struct pingpong *pp,
@@ -116,9 +111,6 @@ CURLcode Curl_pp_sendf(struct pingpong *pp,
* the string should not have any CRLF appended, as this function will
* append the necessary things itself.
*
- * NOTE: we build the command in a fixed-length buffer, which sets length
- * restrictions on the command!
- *
* made to never block
*/
CURLcode Curl_pp_vsendf(struct pingpong *pp,
@@ -144,4 +136,4 @@ CURLcode Curl_pp_disconnect(struct pingpong *pp);
int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks,
int numsocks);
-#endif /* __PINGPONG_H */
+#endif /* HEADER_CURL_PINGPONG_H */
diff --git a/lib/polarssl.c b/lib/polarssl.c
index 2e70a28d5..09446f995 100644
--- a/lib/polarssl.c
+++ b/lib/polarssl.c
@@ -27,11 +27,9 @@
*/
#include "setup.h"
+
#ifdef USE_POLARSSL
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -41,6 +39,15 @@
#include <polarssl/havege.h>
#include <polarssl/certs.h>
#include <polarssl/x509.h>
+#include <polarssl/version.h>
+
+#if POLARSSL_VERSION_NUMBER<0x01000000
+/*
+ Earlier versions of polarssl had no WANT_READ or WANT_WRITE, only TRY_AGAIN
+*/
+#define POLARSSL_ERR_NET_WANT_READ POLARSSL_ERR_NET_TRY_AGAIN
+#define POLARSSL_ERR_NET_WANT_WRITE POLARSSL_ERR_NET_TRY_AGAIN
+#endif
#include "urldata.h"
#include "sendf.h"
@@ -188,8 +195,12 @@ Curl_polarssl_connect(struct connectdata *conn,
net_recv, &conn->sock[sockindex],
net_send, &conn->sock[sockindex]);
- ssl_set_ciphers(&conn->ssl[sockindex].ssl, ssl_default_ciphers);
+#if POLARSSL_VERSION_NUMBER<0x01000000
+ ssl_set_ciphers(&conn->ssl[sockindex].ssl, ssl_default_ciphers);
+#else
+ ssl_set_ciphersuites(&conn->ssl[sockindex].ssl, ssl_default_ciphersuites);
+#endif
if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) {
memcpy(&conn->ssl[sockindex].ssn, old_session, old_session_size);
infof(data, "PolarSSL re-using session\n");
@@ -224,7 +235,8 @@ Curl_polarssl_connect(struct connectdata *conn,
for(;;) {
if(!(ret = ssl_handshake(&conn->ssl[sockindex].ssl)))
break;
- else if(ret != POLARSSL_ERR_NET_TRY_AGAIN) {
+ else if(ret != POLARSSL_ERR_NET_WANT_READ &&
+ ret != POLARSSL_ERR_NET_WANT_WRITE) {
failf(data, "ssl_handshake returned -0x%04X", -ret);
return CURLE_SSL_CONNECT_ERROR;
}
@@ -254,7 +266,11 @@ Curl_polarssl_connect(struct connectdata *conn,
}
infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
+#if POLARSSL_VERSION_NUMBER<0x01000000
ssl_get_cipher(&conn->ssl[sockindex].ssl));
+#else
+ ssl_get_ciphersuite_name(&conn->ssl[sockindex].ssl));
+#endif
ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
@@ -318,7 +334,7 @@ static ssize_t polarssl_send(struct connectdata *conn,
(unsigned char *)mem, len);
if(ret < 0) {
- *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ?
+ *curlcode = (ret == POLARSSL_ERR_NET_WANT_WRITE) ?
CURLE_AGAIN : CURLE_SEND_ERROR;
ret = -1;
}
@@ -356,7 +372,7 @@ static ssize_t polarssl_recv(struct connectdata *conn,
if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
return 0;
- *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ?
+ *curlcode = (ret == POLARSSL_ERR_NET_WANT_READ) ?
CURLE_AGAIN : CURLE_RECV_ERROR;
return -1;
}
diff --git a/lib/polarssl.h b/lib/polarssl.h
index 9e983aac9..91f63afbf 100644
--- a/lib/polarssl.h
+++ b/lib/polarssl.h
@@ -20,8 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
- * $Id: polarssl.h,v 1.10 2009-02-12 20:48:43 danf Exp $
***************************************************************************/
+#include "setup.h"
#ifdef USE_POLARSSL
@@ -40,7 +40,7 @@ int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex);
/* API setup for PolarSSL */
#define curlssl_init() (1)
-#define curlssl_cleanup()
+#define curlssl_cleanup() Curl_nop_stmt
#define curlssl_connect Curl_polarssl_connect
#define curlssl_session_free(x) Curl_polarssl_session_free(x)
#define curlssl_close_all Curl_polarssl_close_all
diff --git a/lib/pop3.c b/lib/pop3.c
index dc5a1c2fa..cb70679c5 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -27,11 +27,6 @@
#include "setup.h"
#ifndef CURL_DISABLE_POP3
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -124,6 +119,7 @@ const struct Curl_handler Curl_handler_pop3 = {
pop3_doing, /* doing */
pop3_getsock, /* proto_getsock */
pop3_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
pop3_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -149,6 +145,7 @@ const struct Curl_handler Curl_handler_pop3s = {
pop3_doing, /* doing */
pop3_getsock, /* proto_getsock */
pop3_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
pop3_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -174,6 +171,7 @@ static const struct Curl_handler Curl_handler_pop3_proxy = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -199,6 +197,7 @@ static const struct Curl_handler Curl_handler_pop3s_proxy = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -285,7 +284,7 @@ static void pop3_to_pop3s(struct connectdata *conn)
conn->handler = &Curl_handler_pop3s;
}
#else
-#define pop3_to_pop3s(x)
+#define pop3_to_pop3s(x) Curl_nop_stmt
#endif
/* for STARTTLS responses */
@@ -575,7 +574,7 @@ static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done)
struct pop3_conn *pop3c = &conn->proto.pop3c;
CURLcode result = Curl_pp_multi_statemach(&pop3c->pp);
- *done = (bool)(pop3c->state == POP3_STOP);
+ *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE;
return result;
}
@@ -792,7 +791,7 @@ CURLcode pop3_perform(struct connectdata *conn,
result = pop3_easy_statemach(conn);
*dophase_done = TRUE; /* with the easy interface we are done here */
}
- *connected = conn->bits.tcpconnect;
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done)
DEBUGF(infof(conn->data, "DO phase is complete\n"));
diff --git a/lib/progress.c b/lib/progress.c
index 8655dc4c2..1514e1edd 100644
--- a/lib/progress.c
+++ b/lib/progress.c
@@ -201,6 +201,8 @@ void Curl_pgrsStartNow(struct SessionHandle *data)
{
data->progress.speeder_c = 0; /* reset the progress meter display */
data->progress.start = Curl_tvnow();
+ /* clear all bits except HIDE and HEADERS_OUT */
+ data->progress.flags &= PGRS_HIDE|PGRS_HEADERS_OUT;
}
void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, curl_off_t size)
diff --git a/lib/qssl.c b/lib/qssl.c
index 60ea6da23..172df3141 100644
--- a/lib/qssl.c
+++ b/lib/qssl.c
@@ -23,9 +23,9 @@
#include "setup.h"
#ifdef USE_QSOSSL
+
#include <qsossl.h>
-#include <errno.h>
-#include <string.h>
+
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
diff --git a/lib/qssl.h b/lib/qssl.h
index bd195ff7b..a523cb1f3 100644
--- a/lib/qssl.h
+++ b/lib/qssl.h
@@ -1,5 +1,5 @@
-#ifndef __QSSL_H
-#define __QSSL_H
+#ifndef HEADER_CURL_QSSL_H
+#define HEADER_CURL_QSSL_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -21,6 +21,7 @@
* KIND, either express or implied.
*
***************************************************************************/
+#include "setup.h"
/*
* This header should only be needed to get included by sslgen.c and qssl.c
@@ -45,7 +46,7 @@ int Curl_qsossl_check_cxn(struct connectdata * cxn);
#define curlssl_connect Curl_qsossl_connect
/* No session handling for QsoSSL */
-#define curlssl_session_free(x)
+#define curlssl_session_free(x) Curl_nop_stmt
#define curlssl_close_all Curl_qsossl_close_all
#define curlssl_close Curl_qsossl_close
#define curlssl_shutdown(x,y) Curl_qsossl_shutdown(x,y)
@@ -56,4 +57,5 @@ int Curl_qsossl_check_cxn(struct connectdata * cxn);
#define curlssl_check_cxn(x) Curl_qsossl_check_cxn(x)
#define curlssl_data_pending(x,y) 0
#endif /* USE_QSOSSL */
-#endif
+
+#endif /* HEADER_CURL_QSSL_H */
diff --git a/lib/rtsp.c b/lib/rtsp.c
index 3ce8ad51e..5d62ac7c7 100644
--- a/lib/rtsp.c
+++ b/lib/rtsp.c
@@ -113,6 +113,7 @@ const struct Curl_handler Curl_handler_rtsp = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
rtsp_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtsp_disconnect, /* disconnect */
rtsp_rtp_readwrite, /* readwrite */
@@ -294,6 +295,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
case RTSPREQ_GET_PARAMETER:
/* GET_PARAMETER's no_body status is determined later */
p_request = "GET_PARAMETER";
+ data->set.opt_no_body = FALSE;
break;
case RTSPREQ_SET_PARAMETER:
p_request = "SET_PARAMETER";
diff --git a/lib/security.c b/lib/security.c
index 010a5504e..536d7c229 100644
--- a/lib/security.c
+++ b/lib/security.c
@@ -46,9 +46,6 @@
#ifndef CURL_DISABLE_FTP
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
-#include <stdarg.h>
-#include <string.h>
-
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
@@ -57,6 +54,10 @@
#include <unistd.h>
#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
#include "urldata.h"
#include "curl_base64.h"
#include "curl_memory.h"
@@ -64,6 +65,7 @@
#include "ftp.h"
#include "sendf.h"
#include "rawstr.h"
+#include "warnless.h"
/* The last #include file should be: */
#include "memdebug.h"
@@ -283,12 +285,13 @@ static ssize_t sec_recv(struct connectdata *conn, int sockindex,
static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
const char *from, int length)
{
- size_t bytes;
- size_t htonl_bytes;
- char *buffer;
+ int bytes, htonl_bytes; /* 32-bit integers for htonl */
+ char *buffer = NULL;
char *cmd_buffer;
+ size_t cmd_size = 0;
+ CURLcode error;
enum protection_level prot_level = conn->data_prot;
- bool iscmd = prot_level == PROT_CMD;
+ bool iscmd = (prot_level == PROT_CMD)?TRUE:FALSE;
DEBUGASSERT(prot_level > PROT_NONE && prot_level < PROT_LAST);
@@ -300,9 +303,17 @@ static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
}
bytes = conn->mech->encode(conn->app_data, from, length, prot_level,
(void**)&buffer, conn);
+ if(!buffer || bytes <= 0)
+ return; /* error */
+
if(iscmd) {
- bytes = Curl_base64_encode(conn->data, buffer, bytes, &cmd_buffer);
- if(bytes > 0) {
+ error = Curl_base64_encode(conn->data, buffer, curlx_sitouz(bytes),
+ &cmd_buffer, &cmd_size);
+ if(error) {
+ free(buffer);
+ return; /* error */
+ }
+ if(cmd_size > 0) {
static const char *enc = "ENC ";
static const char *mic = "MIC ";
if(prot_level == PROT_PRIVATE)
@@ -310,7 +321,7 @@ static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
else
socket_write(conn, fd, mic, 4);
- socket_write(conn, fd, cmd_buffer, bytes);
+ socket_write(conn, fd, cmd_buffer, cmd_size);
socket_write(conn, fd, "\r\n", 2);
infof(conn->data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic,
cmd_buffer);
@@ -320,7 +331,7 @@ static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
else {
htonl_bytes = htonl(bytes);
socket_write(conn, fd, &htonl_bytes, sizeof(htonl_bytes));
- socket_write(conn, fd, buffer, bytes);
+ socket_write(conn, fd, buffer, curlx_sitouz(bytes));
}
free(buffer);
}
@@ -365,14 +376,20 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer,
int decoded_len;
char *buf;
int ret_code;
+ size_t decoded_sz = 0;
+ CURLcode error;
DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
- decoded_len = Curl_base64_decode(buffer + 4, (unsigned char **)&buf);
- if(decoded_len <= 0) {
+ error = Curl_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz);
+ if(error || decoded_sz == 0)
+ return -1;
+
+ if(decoded_sz > (size_t)INT_MAX) {
free(buf);
return -1;
}
+ decoded_len = curlx_uztosi(decoded_sz);
decoded_len = conn->mech->decode(conn->app_data, buf, decoded_len,
level, conn);
diff --git a/lib/select.c b/lib/select.c
index 8f6541dee..6cecbf701 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -25,9 +25,6 @@
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
#if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
#error "We can't compile without select() or poll() support."
@@ -49,20 +46,6 @@
#include "select.h"
#include "warnless.h"
-/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1] */
-
-#if defined(USE_WINSOCK) || defined(TPF)
-#define VERIFY_SOCK(x) do { } while(0)
-#else
-#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
-#define VERIFY_SOCK(x) do { \
- if(!VALID_SOCK(x)) { \
- SET_SOCKERRNO(EINVAL); \
- return -1; \
- } \
-} while(0)
-#endif
-
/* Convenience local macros */
#define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
@@ -93,7 +76,7 @@
* -1 = system call error, invalid timeout value, or interrupted
* 0 = specified timeout has elapsed
*/
-static int wait_ms(int timeout_ms)
+int Curl_wait_ms(int timeout_ms)
{
#if !defined(MSDOS) && !defined(USE_WINSOCK)
#ifndef HAVE_POLL_FINE
@@ -180,7 +163,7 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd,
int ret;
if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) {
- r = wait_ms((int)timeout_ms);
+ r = Curl_wait_ms((int)timeout_ms);
return r;
}
@@ -364,7 +347,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
}
}
if(fds_none) {
- r = wait_ms((int)timeout_ms);
+ r = Curl_wait_ms(timeout_ms);
return r;
}
diff --git a/lib/select.h b/lib/select.h
index e012c63f3..56729a3b2 100644
--- a/lib/select.h
+++ b/lib/select.h
@@ -89,9 +89,27 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd,
int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);
+int Curl_wait_ms(int timeout_ms);
+
#ifdef TPF
int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
fd_set* excepts, struct timeval* tv);
#endif
+/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1], which
+ unfortunately makes it impossible for us to easily check if they're valid
+*/
+#if defined(USE_WINSOCK) || defined(TPF)
+#define VALID_SOCK(x) 1
+#define VERIFY_SOCK(x) Curl_nop_stmt
+#else
+#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
+#define VERIFY_SOCK(x) do { \
+ if(!VALID_SOCK(x)) { \
+ SET_SOCKERRNO(EINVAL); \
+ return -1; \
+ } \
+} WHILE_FALSE
+#endif
+
#endif /* __SELECT_H */
diff --git a/lib/sendf.c b/lib/sendf.c
index 0172ae7c3..847090be3 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -22,11 +22,6 @@
#include "setup.h"
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <errno.h>
-
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> /* required for send() & recv() prototypes */
#endif
@@ -55,7 +50,6 @@
#define Curl_sec_read(a,b,c,d) -1
#endif
-#include <string.h>
#include "curl_memory.h"
#include "strerror.h"
@@ -79,7 +73,7 @@ static size_t convert_lineends(struct SessionHandle *data,
return(size);
}
- if(data->state.prev_block_had_trailing_cr == TRUE) {
+ if(data->state.prev_block_had_trailing_cr) {
/* The previous block of incoming data
had a trailing CR, which was turned into a LF. */
if(*startPtr == '\n') {
@@ -533,17 +527,17 @@ CURLcode Curl_read_plain(curl_socket_t sockfd,
* Returns a regular CURLcode value.
*/
CURLcode Curl_read(struct connectdata *conn, /* connection data */
- curl_socket_t sockfd, /* read from this socket */
- char *buf, /* store read data here */
- size_t sizerequested, /* max amount to read */
- ssize_t *n) /* amount bytes read */
+ curl_socket_t sockfd, /* read from this socket */
+ char *buf, /* store read data here */
+ size_t sizerequested, /* max amount to read */
+ ssize_t *n) /* amount bytes read */
{
CURLcode curlcode = CURLE_RECV_ERROR;
ssize_t nread = 0;
size_t bytesfromsocket = 0;
char *buffertofill = NULL;
- bool pipelining = (bool)(conn->data->multi &&
- Curl_multi_canPipeline(conn->data->multi));
+ bool pipelining = (conn->data->multi &&
+ Curl_multi_canPipeline(conn->data->multi)) ? TRUE : FALSE;
/* Set 'num' to 0 or 1, depending on which socket that has been sent here.
If it is the second socket, we set num to 1. Otherwise to 0. This lets
diff --git a/lib/sendf.h b/lib/sendf.h
index 8f0ea24d7..39911d016 100644
--- a/lib/sendf.h
+++ b/lib/sendf.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 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 @@ void Curl_failf(struct SessionHandle *, const char *fmt, ...);
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
#if defined(HAVE_VARIADIC_MACROS_C99)
-#define infof(...) do { } while (0)
+#define infof(...) Curl_nop_stmt
#elif defined(HAVE_VARIADIC_MACROS_GCC)
-#define infof(x...) do { } while (0)
+#define infof(x...) Curl_nop_stmt
#else
#define infof (void)
#endif
diff --git a/lib/setup.h b/lib/setup.h
index 1e96c76dd..84c9b1feb 100644
--- a/lib/setup.h
+++ b/lib/setup.h
@@ -251,6 +251,12 @@
# endif
#endif
+#ifdef USE_LWIPSOCK
+# include <lwip/init.h>
+# include <lwip/sockets.h>
+# include <lwip/netdb.h>
+#endif
+
#ifdef HAVE_EXTRA_STRICMP_H
# include <extra/stricmp.h>
#endif
@@ -279,7 +285,6 @@
#ifdef HAVE_ASSERT_H
#include <assert.h>
#endif
-#include <errno.h>
#ifdef __TANDEM /* for nsr-tandem-nsk systems */
#include <floss.h>
@@ -563,6 +568,7 @@ int netware_init(void);
#define USE_HTTP_NEGOTIATE
#endif
+/* Single point where USE_NTLM definition might be done */
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_NTLM)
#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) || \
defined(USE_GNUTLS) || defined(USE_NSS)
@@ -580,6 +586,15 @@ int netware_init(void);
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
+/* Provide a mechanism to silence picky compilers, such as gcc 4.6+.
+ Parameters should of course normally not be unused, but for example when we
+ have multiple implementations of the same interface it may happen. */
+#ifndef __GNUC__
+#define UNUSED_PARAM /*NOTHING*/
+#else
+#define UNUSED_PARAM __attribute__((unused))
+#endif
+
/*
* Include macros and defines that should only be processed once.
*/
@@ -588,4 +603,27 @@ int netware_init(void);
#include "setup_once.h"
#endif
+/*
+ * Definition of our NOP statement Object-like macro
+ */
+
+#ifndef Curl_nop_stmt
+# define Curl_nop_stmt do { } WHILE_FALSE
+#endif
+
+/*
+ * Ensure that Winsock and lwIP TCP/IP stacks are not mixed.
+ */
+
+#if defined(__LWIP_OPT_H__)
+# if defined(SOCKET) || \
+ defined(USE_WINSOCK) || \
+ defined(HAVE_ERRNO_H) || \
+ defined(HAVE_WINSOCK_H) || \
+ defined(HAVE_WINSOCK2_H) || \
+ defined(HAVE_WS2TCPIP_H)
+# error "Winsock and lwIP TCP/IP stack definitions shall not coexist!"
+# endif
+#endif
+
#endif /* HEADER_CURL_LIB_SETUP_H */
diff --git a/lib/setup_once.h b/lib/setup_once.h
index b449807db..8bdb472df 100644
--- a/lib/setup_once.h
+++ b/lib/setup_once.h
@@ -42,7 +42,10 @@
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
+
+#ifdef HAVE_ERRNO_H
#include <errno.h>
+#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -254,10 +257,13 @@ struct timeval {
#define ISPRINT(x) (isprint((int) ((unsigned char)x)))
#define ISUPPER(x) (isupper((int) ((unsigned char)x)))
#define ISLOWER(x) (islower((int) ((unsigned char)x)))
+#define ISASCII(x) (isascii((int) ((unsigned char)x)))
#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \
(((unsigned char)x) == '\t'))
+#define TOLOWER(x) (tolower((int) ((unsigned char)x)))
+
/*
* 'bool' exists on platforms with <stdbool.h>, i.e. C99 platforms.
@@ -300,6 +306,27 @@ struct timeval {
/*
+ * Macro WHILE_FALSE may be used to build single-iteration do-while loops,
+ * avoiding compiler warnings. Mostly intended for other macro definitions.
+ */
+
+#define WHILE_FALSE while(0)
+
+#if defined(_MSC_VER) && !defined(__POCC__)
+# undef WHILE_FALSE
+# if (_MSC_VER < 1500)
+# define WHILE_FALSE while(1, 0)
+# else
+# define WHILE_FALSE \
+__pragma(warning(push)) \
+__pragma(warning(disable:4127)) \
+while(0) \
+__pragma(warning(pop))
+# endif
+#endif
+
+
+/*
* Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type.
*/
@@ -336,7 +363,7 @@ typedef int sig_atomic_t;
#ifdef DEBUGBUILD
#define DEBUGF(x) x
#else
-#define DEBUGF(x) do { } while (0)
+#define DEBUGF(x) do { } WHILE_FALSE
#endif
@@ -347,7 +374,7 @@ typedef int sig_atomic_t;
#if defined(DEBUGBUILD) && defined(HAVE_ASSERT_H)
#define DEBUGASSERT(x) assert(x)
#else
-#define DEBUGASSERT(x) do { } while (0)
+#define DEBUGASSERT(x) do { } WHILE_FALSE
#endif
@@ -487,5 +514,5 @@ typedef int sig_atomic_t;
#define ZERO_NULL 0
-#endif /* __SETUP_ONCE_H */
+#endif /* __SETUP_ONCE_H */
diff --git a/lib/share.c b/lib/share.c
index 33dcecf4c..71c2ef308 100644
--- a/lib/share.c
+++ b/lib/share.c
@@ -21,12 +21,11 @@
***************************************************************************/
#include "setup.h"
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
+
#include <curl/curl.h>
#include "urldata.h"
#include "share.h"
+#include "sslgen.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -74,17 +73,32 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
}
break;
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
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 );
if(!share->cookies)
return CURLSHE_NOMEM;
}
break;
-#endif /* CURL_DISABLE_HTTP */
+#else /* CURL_DISABLE_HTTP */
+ return CURLSHE_NOT_BUILT_IN;
+#endif
+
+ case CURL_LOCK_DATA_SSL_SESSION:
+#ifdef USE_SSL
+ if(!share->sslsession) {
+ share->nsslsession = 8;
+ share->sslsession = calloc(share->nsslsession,
+ sizeof(struct curl_ssl_session));
+ if(!share->sslsession)
+ return CURLSHE_NOMEM;
+ }
+ break;
+#else
+ return CURLSHE_NOT_BUILT_IN;
+#endif
- case CURL_LOCK_DATA_SSL_SESSION: /* not supported (yet) */
case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */
default:
@@ -104,17 +118,28 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
}
break;
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
case CURL_LOCK_DATA_COOKIE:
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
if(share->cookies) {
Curl_cookie_cleanup(share->cookies);
share->cookies = NULL;
}
break;
-#endif /* CURL_DISABLE_HTTP */
+#else /* CURL_DISABLE_HTTP */
+ return CURLSHE_NOT_BUILT_IN;
+#endif
case CURL_LOCK_DATA_SSL_SESSION:
+#ifdef USE_SSL
+ if(share->sslsession) {
+ free(share->sslsession);
+ share->sslsession = NULL;
+ share->nsslsession = 0;
+ }
break;
+#else
+ return CURLSHE_NOT_BUILT_IN;
+#endif
case CURL_LOCK_DATA_CONNECT:
break;
@@ -169,8 +194,19 @@ curl_share_cleanup(CURLSH *sh)
share->hostcache = NULL;
}
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
if(share->cookies)
Curl_cookie_cleanup(share->cookies);
+#endif
+
+#ifdef USE_SSL
+ if(share->sslsession) {
+ unsigned int i;
+ for(i = 0; i < share->nsslsession; ++i)
+ Curl_ssl_kill_session(&(share->sslsession[i]));
+ free(share->sslsession);
+ }
+#endif
if(share->unlockfunc)
share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
diff --git a/lib/share.h b/lib/share.h
index ea8e233d2..c9546567d 100644
--- a/lib/share.h
+++ b/lib/share.h
@@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 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,6 +26,7 @@
#include "setup.h"
#include <curl/curl.h>
#include "cookie.h"
+#include "urldata.h"
/* SalfordC says "A structure member may not be volatile". Hence:
*/
@@ -45,7 +46,12 @@ struct Curl_share {
void *clientdata;
struct curl_hash *hostcache;
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
struct CookieInfo *cookies;
+#endif
+
+ struct curl_ssl_session *sslsession;
+ unsigned int nsslsession;
};
CURLSHcode Curl_share_lock (struct SessionHandle *, curl_lock_data,
diff --git a/lib/slist.c b/lib/slist.c
index e2006f4be..4ddebb609 100644
--- a/lib/slist.c
+++ b/lib/slist.c
@@ -22,11 +22,6 @@
#include "setup.h"
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-
-#include <string.h>
#include "curl_memory.h"
#include "slist.h"
@@ -124,10 +119,7 @@ void curl_slist_free_all(struct curl_slist *list)
item = list;
do {
next = item->next;
-
- if(item->data) {
- free(item->data);
- }
+ Curl_safefree(item->data);
free(item);
item = next;
} while(next);
diff --git a/lib/smtp.c b/lib/smtp.c
index 1626ae7da..8835b07a5 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -29,11 +29,6 @@
#include "setup.h"
#ifndef CURL_DISABLE_SMTP
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -90,6 +85,7 @@
#include "curl_md5.h"
#include "curl_hmac.h"
#include "curl_gethostname.h"
+#include "curl_ntlm_msgs.h"
#include "warnless.h"
#include "http_proxy.h"
@@ -116,7 +112,6 @@ static CURLcode smtp_doing(struct connectdata *conn,
static CURLcode smtp_setup_connection(struct connectdata * conn);
static CURLcode smtp_state_upgrade_tls(struct connectdata *conn);
-
/*
* SMTP protocol handler.
*/
@@ -132,6 +127,7 @@ const struct Curl_handler Curl_handler_smtp = {
smtp_doing, /* doing */
smtp_getsock, /* proto_getsock */
smtp_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
smtp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -140,7 +136,6 @@ const struct Curl_handler Curl_handler_smtp = {
PROTOPT_CLOSEACTION /* flags */
};
-
#ifdef USE_SSL
/*
* SMTPS protocol handler.
@@ -157,6 +152,7 @@ const struct Curl_handler Curl_handler_smtps = {
smtp_doing, /* doing */
smtp_getsock, /* proto_getsock */
smtp_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
smtp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -182,6 +178,7 @@ static const struct Curl_handler Curl_handler_smtp_proxy = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -190,7 +187,6 @@ static const struct Curl_handler Curl_handler_smtp_proxy = {
PROTOPT_NONE /* flags */
};
-
#ifdef USE_SSL
/*
* HTTP-proxyed SMTPS protocol handler.
@@ -207,6 +203,7 @@ static const struct Curl_handler Curl_handler_smtps_proxy = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -217,7 +214,6 @@ static const struct Curl_handler Curl_handler_smtps_proxy = {
#endif
#endif
-
/* Function that checks for an ending smtp status code at the start of the
given string.
As a side effect, it also flags allowed authentication mechanisms according
@@ -272,6 +268,8 @@ static int smtp_endofresp(struct pingpong *pp, int *resp)
smtpc->authmechs |= SMTP_AUTH_GSSAPI;
else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8))
smtpc->authmechs |= SMTP_AUTH_EXTERNAL;
+ else if(wordlen == 4 && !memcmp(line, "NTLM", 4))
+ smtpc->authmechs |= SMTP_AUTH_NTLM;
line += wordlen;
len -= wordlen;
@@ -288,7 +286,7 @@ static void state(struct connectdata *conn,
struct smtp_conn *smtpc = &conn->proto.smtpc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
- static const char * const names[]={
+ static const char * const names[] = {
"STOP",
"SERVERGREET",
"EHLO",
@@ -299,6 +297,8 @@ static void state(struct connectdata *conn,
"AUTHLOGIN",
"AUTHPASSWD",
"AUTHCRAM",
+ "AUTHNTLM",
+ "AUTHNTLM_TYPE2MSG",
"AUTH",
"MAIL",
"RCPT",
@@ -320,6 +320,8 @@ static CURLcode smtp_state_ehlo(struct connectdata *conn)
struct smtp_conn *smtpc = &conn->proto.smtpc;
smtpc->authmechs = 0; /* No known authentication mechanisms yet. */
+ smtpc->authused = 0; /* Clear the authentication mechanism used
+ for esmtp connections */
/* send EHLO */
result = Curl_pp_sendf(&smtpc->pp, "EHLO %s", smtpc->domain);
@@ -336,6 +338,9 @@ static CURLcode smtp_state_helo(struct connectdata *conn)
CURLcode result;
struct smtp_conn *smtpc = &conn->proto.smtpc;
+ smtpc->authused = 0; /* No authentication mechanism used in smtp
+ connections */
+
/* send HELO */
result = Curl_pp_sendf(&smtpc->pp, "HELO %s", smtpc->domain);
@@ -346,7 +351,8 @@ static CURLcode smtp_state_helo(struct connectdata *conn)
return CURLE_OK;
}
-static size_t smtp_auth_plain_data(struct connectdata * conn, char * * outptr)
+static CURLcode smtp_auth_plain_data(struct connectdata *conn,
+ char **outptr, size_t *outlen)
{
char plainauth[2 * MAX_CURL_USER_LENGTH + MAX_CURL_PASSWORD_LENGTH];
size_t ulen;
@@ -355,8 +361,11 @@ static size_t smtp_auth_plain_data(struct connectdata * conn, char * * outptr)
ulen = strlen(conn->user);
plen = strlen(conn->passwd);
- if(2 * ulen + plen + 2 > sizeof plainauth)
- return 0;
+ if(2 * ulen + plen + 2 > sizeof plainauth) {
+ *outlen = 0;
+ *outptr = NULL;
+ return CURLE_OUT_OF_MEMORY; /* plainauth too small */
+ }
memcpy(plainauth, conn->user, ulen);
plainauth[ulen] = '\0';
@@ -364,89 +373,108 @@ static size_t smtp_auth_plain_data(struct connectdata * conn, char * * outptr)
plainauth[2 * ulen + 1] = '\0';
memcpy(plainauth + 2 * ulen + 2, conn->passwd, plen);
return Curl_base64_encode(conn->data, plainauth, 2 * ulen + plen + 2,
- outptr);
+ outptr, outlen);
}
-static size_t smtp_auth_login_user(struct connectdata * conn, char * * outptr)
+static CURLcode smtp_auth_login_user(struct connectdata *conn,
+ char **outptr, size_t *outlen)
{
- size_t ulen;
-
- ulen = strlen(conn->user);
+ size_t ulen = strlen(conn->user);
if(!ulen) {
*outptr = strdup("=");
- return *outptr? 1: 0;
+ if(*outptr) {
+ *outlen = (size_t) 1;
+ return CURLE_OK;
+ }
+ *outlen = 0;
+ return CURLE_OUT_OF_MEMORY;
}
- return Curl_base64_encode(conn->data, conn->user, ulen, outptr);
+ return Curl_base64_encode(conn->data, conn->user, ulen, outptr, outlen);
+}
+
+#ifdef USE_NTLM
+static CURLcode smtp_auth_ntlm_type1_message(struct connectdata *conn,
+ char **outptr, size_t *outlen)
+{
+ return Curl_ntlm_create_type1_message(conn->user, conn->passwd,
+ &conn->ntlm, outptr, outlen);
}
+#endif
static CURLcode smtp_authenticate(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct smtp_conn *smtpc = &conn->proto.smtpc;
- char * initresp;
- const char * mech;
- size_t l;
- smtpstate state1;
- smtpstate state2;
-
- if(!conn->bits.user_passwd)
- state(conn, SMTP_STOP); /* End of connect phase. */
- else {
- initresp = (char *) NULL;
- l = 1;
+ char *initresp = NULL;
+ const char *mech = NULL;
+ size_t len = 0;
+ smtpstate state1 = SMTP_STOP;
+ smtpstate state2 = SMTP_STOP;
+
+ /* Check we have a username and password to authenticate with and end the
+ connect phase if we don't. */
+ if(!conn->bits.user_passwd) {
+ state(conn, SMTP_STOP);
- /* Check supported authentication mechanisms by decreasing order of
- preference. */
- mech = (const char *) NULL; /* Avoid compiler warnings. */
- state1 = SMTP_STOP;
- state2 = SMTP_STOP;
+ return result;
+ }
+ /* Check supported authentication mechanisms by decreasing order of
+ security. */
#ifndef CURL_DISABLE_CRYPTO_AUTH
- if(smtpc->authmechs & SMTP_AUTH_CRAM_MD5) {
- mech = "CRAM-MD5";
- state1 = SMTP_AUTHCRAM;
- }
- else
+ if(smtpc->authmechs & SMTP_AUTH_CRAM_MD5) {
+ mech = "CRAM-MD5";
+ state1 = SMTP_AUTHCRAM;
+ smtpc->authused = SMTP_AUTH_CRAM_MD5;
+ }
+ else
#endif
- if(smtpc->authmechs & SMTP_AUTH_PLAIN) {
- mech = "PLAIN";
- state1 = SMTP_AUTHPLAIN;
- state2 = SMTP_AUTH;
- l = smtp_auth_plain_data(conn, &initresp);
- }
- else if(smtpc->authmechs & SMTP_AUTH_LOGIN) {
- mech = "LOGIN";
- state1 = SMTP_AUTHLOGIN;
- state2 = SMTP_AUTHPASSWD;
- l = smtp_auth_login_user(conn, &initresp);
- }
- else {
- infof(conn->data, "No known auth mechanisms supported!\n");
- result = CURLE_LOGIN_DENIED; /* Other mechanisms not supported. */
- }
+#ifdef USE_NTLM
+ if(smtpc->authmechs & SMTP_AUTH_NTLM) {
+ mech = "NTLM";
+ state1 = SMTP_AUTHNTLM;
+ state2 = SMTP_AUTHNTLM_TYPE2MSG;
+ smtpc->authused = SMTP_AUTH_NTLM;
+ result = smtp_auth_ntlm_type1_message(conn, &initresp, &len);
+ }
+ else
+#endif
+ if(smtpc->authmechs & SMTP_AUTH_LOGIN) {
+ mech = "LOGIN";
+ state1 = SMTP_AUTHLOGIN;
+ state2 = SMTP_AUTHPASSWD;
+ smtpc->authused = SMTP_AUTH_LOGIN;
+ result = smtp_auth_login_user(conn, &initresp, &len);
+ }
+ else if(smtpc->authmechs & SMTP_AUTH_PLAIN) {
+ mech = "PLAIN";
+ state1 = SMTP_AUTHPLAIN;
+ state2 = SMTP_AUTH;
+ smtpc->authused = SMTP_AUTH_PLAIN;
+ result = smtp_auth_plain_data(conn, &initresp, &len);
+ }
+ else {
+ infof(conn->data, "No known auth mechanisms supported!\n");
+ result = CURLE_LOGIN_DENIED; /* Other mechanisms not supported. */
+ }
- if(!result) {
- if(!l)
- result = CURLE_OUT_OF_MEMORY;
- else if(initresp &&
- l + strlen(mech) <= 512 - 8) { /* AUTH <mech> ...<crlf> */
- result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp);
- free(initresp);
+ if(!result) {
+ if(initresp &&
+ strlen(mech) + len <= 512 - 8) { /* AUTH <mech> ...<crlf> */
+ result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp);
- if(!result)
- state(conn, state2);
- }
- else {
- Curl_safefree(initresp);
-
- result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech);
+ if(!result)
+ state(conn, state2);
+ }
+ else {
+ result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech);
- if(!result)
- state(conn, state1);
- }
+ if(!result)
+ state(conn, state1);
}
+ Curl_safefree(initresp);
}
return result;
@@ -466,7 +494,7 @@ static void smtp_to_smtps(struct connectdata *conn)
conn->handler = &Curl_handler_smtps;
}
#else
-#define smtp_to_smtps(x)
+#define smtp_to_smtps(x) Curl_nop_stmt
#endif
/* for STARTTLS responses */
@@ -499,6 +527,7 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
}
}
}
+
return result;
}
@@ -566,6 +595,7 @@ static CURLcode smtp_state_helo_resp(struct connectdata *conn,
/* end the connect phase */
state(conn, SMTP_STOP);
}
+
return result;
}
@@ -576,8 +606,8 @@ static CURLcode smtp_state_authplain_resp(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
- size_t l;
- char * plainauth;
+ size_t len = 0;
+ char *plainauth = NULL;
(void)instate; /* no use for this yet */
@@ -586,16 +616,16 @@ static CURLcode smtp_state_authplain_resp(struct connectdata *conn,
result = CURLE_LOGIN_DENIED;
}
else {
- l = smtp_auth_plain_data(conn, &plainauth);
+ result = smtp_auth_plain_data(conn, &plainauth, &len);
- if(!l)
- result = CURLE_OUT_OF_MEMORY;
- else {
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", plainauth);
- free(plainauth);
+ if(!result) {
+ if(plainauth) {
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", plainauth);
- if(!result)
- state(conn, SMTP_AUTH);
+ if(!result)
+ state(conn, SMTP_AUTH);
+ }
+ Curl_safefree(plainauth);
}
}
@@ -609,8 +639,8 @@ static CURLcode smtp_state_authlogin_resp(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
- size_t l;
- char * authuser;
+ size_t len = 0;
+ char *authuser = NULL;
(void)instate; /* no use for this yet */
@@ -619,16 +649,16 @@ static CURLcode smtp_state_authlogin_resp(struct connectdata *conn,
result = CURLE_LOGIN_DENIED;
}
else {
- l = smtp_auth_login_user(conn, &authuser);
+ result = smtp_auth_login_user(conn, &authuser, &len);
- if(!l)
- result = CURLE_OUT_OF_MEMORY;
- else {
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authuser);
- free(authuser);
+ if(!result) {
+ if(authuser) {
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authuser);
- if(!result)
- state(conn, SMTP_AUTHPASSWD);
+ if(!result)
+ state(conn, SMTP_AUTHPASSWD);
+ }
+ Curl_safefree(authuser);
}
}
@@ -643,8 +673,8 @@ static CURLcode smtp_state_authpasswd_resp(struct connectdata *conn,
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t plen;
- size_t l;
- char *authpasswd;
+ size_t len = 0;
+ char *authpasswd = NULL;
(void)instate; /* no use for this yet */
@@ -658,16 +688,16 @@ static CURLcode smtp_state_authpasswd_resp(struct connectdata *conn,
if(!plen)
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "=");
else {
- l = Curl_base64_encode(data, conn->passwd, plen, &authpasswd);
+ result = Curl_base64_encode(data, conn->passwd, plen, &authpasswd, &len);
- if(!l)
- result = CURLE_OUT_OF_MEMORY;
- else {
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authpasswd);
- free(authpasswd);
+ if(!result) {
+ if(authpasswd) {
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authpasswd);
- if(!result)
- state(conn, SMTP_AUTH);
+ if(!result)
+ state(conn, SMTP_AUTH);
+ }
+ Curl_safefree(authpasswd);
}
}
}
@@ -687,9 +717,9 @@ static CURLcode smtp_state_authcram_resp(struct connectdata *conn,
char * chlg64 = data->state.buffer;
unsigned char * chlg;
size_t chlglen;
- size_t l;
- char * rplyb64;
- HMAC_context * ctxt;
+ size_t len = 0;
+ char *rplyb64 = NULL;
+ HMAC_context *ctxt;
unsigned char digest[16];
char reply[MAX_CURL_USER_LENGTH + 32 /* 2 * size of MD5 digest */ + 1];
@@ -708,17 +738,17 @@ static CURLcode smtp_state_authcram_resp(struct connectdata *conn,
chlglen = 0;
if(*chlg64 != '=') {
- for(l = strlen(chlg64); l--;)
- if(chlg64[l] != '\r' && chlg64[l] != '\n' && chlg64[l] != ' ' &&
- chlg64[l] != '\t')
+ for(len = strlen(chlg64); len--;)
+ if(chlg64[len] != '\r' && chlg64[len] != '\n' && chlg64[len] != ' ' &&
+ chlg64[len] != '\t')
break;
- if(++l) {
- chlg64[l] = '\0';
+ if(++len) {
+ chlg64[len] = '\0';
- chlglen = Curl_base64_decode(chlg64, &chlg);
- if(!chlglen)
- return CURLE_OUT_OF_MEMORY;
+ result = Curl_base64_decode(chlg64, &chlg, &chlglen);
+ if(result)
+ return result;
}
}
@@ -728,17 +758,14 @@ static CURLcode smtp_state_authcram_resp(struct connectdata *conn,
(unsigned int)(strlen(conn->passwd)));
if(!ctxt) {
- if(chlg)
- free(chlg);
-
+ Curl_safefree(chlg);
return CURLE_OUT_OF_MEMORY;
}
if(chlglen > 0)
Curl_HMAC_update(ctxt, chlg, (unsigned int)(chlglen));
- if(chlg)
- free(chlg);
+ Curl_safefree(chlg);
Curl_HMAC_final(ctxt, digest);
@@ -751,21 +778,94 @@ static CURLcode smtp_state_authcram_resp(struct connectdata *conn,
digest[12], digest[13], digest[14], digest[15]);
/* Encode it to base64 and send it. */
- l = Curl_base64_encode(data, reply, 0, &rplyb64);
+ result = Curl_base64_encode(data, reply, 0, &rplyb64, &len);
+
+ if(!result) {
+ if(rplyb64) {
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64);
+
+ if(!result)
+ state(conn, SMTP_AUTH);
+ }
+ Curl_safefree(rplyb64);
+ }
+
+ return result;
+}
+
+#endif
- if(!l)
- result = CURLE_OUT_OF_MEMORY;
+#ifdef USE_NTLM
+/* for the AUTH NTLM (without initial response) response. */
+static CURLcode smtp_state_auth_ntlm_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *type1msg = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
else {
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64);
- free(rplyb64);
+ result = smtp_auth_ntlm_type1_message(conn, &type1msg, &len);
- if(!result)
- state(conn, SMTP_AUTH);
+ if(!result) {
+ if(type1msg) {
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", type1msg);
+
+ if(!result)
+ state(conn, SMTP_AUTHNTLM_TYPE2MSG);
+ }
+ Curl_safefree(type1msg);
+ }
}
return result;
}
+/* for the NTLM type-2 response (sent in reponse to our type-1 message). */
+static CURLcode smtp_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *type3msg = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ result = Curl_ntlm_decode_type2_message(data, data->state.buffer + 4,
+ &conn->ntlm);
+ if(!result) {
+ result = Curl_ntlm_create_type3_message(conn->data, conn->user,
+ conn->passwd, &conn->ntlm,
+ &type3msg, &len);
+ if(!result) {
+ if(type3msg) {
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", type3msg);
+
+ if(!result)
+ state(conn, SMTP_AUTH);
+ }
+ Curl_safefree(type3msg);
+ }
+ }
+ }
+
+ return result;
+}
#endif
/* for final responses to AUTH sequences. */
@@ -791,20 +891,49 @@ static CURLcode smtp_state_auth_resp(struct connectdata *conn,
/* start the DO phase */
static CURLcode smtp_mail(struct connectdata *conn)
{
+ char *from = NULL;
+ char *size = NULL;
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
+ /* calculate the FROM parameter */
+ if(!data->set.str[STRING_MAIL_FROM])
+ /* null reverse-path, RFC-2821, sect. 3.7 */
+ from = strdup("<>");
+ else if(data->set.str[STRING_MAIL_FROM][0] == '<')
+ from = aprintf("%s", data->set.str[STRING_MAIL_FROM]);
+ else
+ from = aprintf("<%s>", data->set.str[STRING_MAIL_FROM]);
+
+ if(!from)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* calculate the optional SIZE parameter */
+ if(conn->data->set.infilesize > 0) {
+ size = aprintf("%" FORMAT_OFF_T, data->set.infilesize);
+
+ if(!size) {
+ Curl_safefree(from);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
/* send MAIL FROM */
- if(data->set.str[STRING_MAIL_FROM][0] == '<')
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "MAIL FROM:%s",
- data->set.str[STRING_MAIL_FROM]);
+ if(!size)
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "MAIL FROM:%s", from);
else
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "MAIL FROM:<%s>",
- data->set.str[STRING_MAIL_FROM]);
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "MAIL FROM:%s SIZE=%s",
+ from, size);
+
+ Curl_safefree(size);
+ Curl_safefree(from);
+
if(result)
return result;
state(conn, SMTP_MAIL);
+
return result;
}
@@ -824,6 +953,7 @@ static CURLcode smtp_rcpt_to(struct connectdata *conn)
if(!result)
state(conn, SMTP_RCPT);
}
+
return result;
}
@@ -884,6 +1014,7 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn,
state(conn, SMTP_DATA);
}
+
return result;
}
@@ -924,6 +1055,7 @@ static CURLcode smtp_state_postdata_resp(struct connectdata *conn,
result = CURLE_RECV_ERROR;
state(conn, SMTP_STOP);
+
return result;
}
@@ -931,7 +1063,7 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
{
CURLcode result;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
- struct SessionHandle *data=conn->data;
+ struct SessionHandle *data = conn->data;
int smtpcode;
struct smtp_conn *smtpc = &conn->proto.smtpc;
struct pingpong *pp = &smtpc->pp;
@@ -993,6 +1125,17 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
break;
#endif
+#ifdef USE_NTLM
+ case SMTP_AUTHNTLM:
+ result = smtp_state_auth_ntlm_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTHNTLM_TYPE2MSG:
+ result = smtp_state_auth_ntlm_type2msg_resp(conn, smtpcode,
+ smtpc->state);
+ break;
+#endif
+
case SMTP_AUTH:
result = smtp_state_auth_resp(conn, smtpcode, smtpc->state);
break;
@@ -1021,6 +1164,7 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
break;
}
}
+
return result;
}
@@ -1036,7 +1180,7 @@ static CURLcode smtp_multi_statemach(struct connectdata *conn,
else
result = Curl_pp_multi_statemach(&smtpc->pp);
- *done = (bool)(smtpc->state == SMTP_STOP);
+ *done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE;
return result;
}
@@ -1087,20 +1231,20 @@ static CURLcode smtp_init(struct connectdata *conn)
* smtp_connect() should do everything that is to be considered a part of
* the connection phase.
*
- * The variable 'done' points to will be TRUE if the protocol-layer connect
- * phase is done when this function returns, or FALSE is not. When called as
- * a part of the easy interface, it will always be TRUE.
+ * The variable pointed to by 'done' will be TRUE if the protocol-layer
+ * connect phase is done when this function returns, or FALSE if not. When
+ * called as a part of the easy interface, it will always be TRUE.
*/
static CURLcode smtp_connect(struct connectdata *conn,
bool *done) /* see description above */
{
CURLcode result;
struct smtp_conn *smtpc = &conn->proto.smtpc;
- struct SessionHandle *data=conn->data;
- struct pingpong *pp=&smtpc->pp;
+ struct SessionHandle *data = conn->data;
+ struct pingpong *pp = &smtpc->pp;
const char *path = conn->data->state.path;
int len;
- char localhost[1024 + 1];
+ char localhost[HOSTNAME_MAX + 1];
*done = FALSE; /* default to not done yet */
@@ -1204,7 +1348,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
{
struct SessionHandle *data = conn->data;
struct FTP *smtp = data->state.proto.smtp;
- CURLcode result=CURLE_OK;
+ CURLcode result = CURLE_OK;
ssize_t bytes_written;
(void)premature;
@@ -1234,7 +1378,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
if(status == CURLE_OK) {
struct smtp_conn *smtpc = &conn->proto.smtpc;
- struct pingpong *pp= &smtpc->pp;
+ struct pingpong *pp = &smtpc->pp;
pp->response = Curl_tvnow(); /* timeout relative now */
state(conn, SMTP_POSTDATA);
@@ -1268,7 +1412,7 @@ CURLcode smtp_perform(struct connectdata *conn,
bool *dophase_done)
{
/* this is SMTP and no proxy */
- CURLcode result=CURLE_OK;
+ CURLcode result = CURLE_OK;
DEBUGF(infof(conn->data, "DO phase starts\n"));
@@ -1292,7 +1436,7 @@ CURLcode smtp_perform(struct connectdata *conn,
result = smtp_easy_statemach(conn);
*dophase_done = TRUE; /* with the easy interface we are done here */
}
- *connected = conn->bits.tcpconnect;
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done)
DEBUGF(infof(conn->data, "DO phase is complete\n"));
@@ -1361,9 +1505,10 @@ static CURLcode smtp_quit(struct connectdata *conn)
* Disconnect from an SMTP server. Cleanup protocol-specific per-connection
* resources. BLOCKING.
*/
-static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode smtp_disconnect(struct connectdata *conn,
+ bool dead_connection)
{
- struct smtp_conn *smtpc= &conn->proto.smtpc;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
/* We cannot send quit unconditionally. If this connection is stale or
bad in any way, sending quit and waiting around here will make the
@@ -1377,6 +1522,13 @@ static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection)
Curl_pp_disconnect(&smtpc->pp);
+#ifdef USE_NTLM
+ /* Cleanup the ntlm structure */
+ if(smtpc->authused == SMTP_AUTH_NTLM) {
+ Curl_ntlm_sspi_cleanup(&conn->ntlm);
+ }
+#endif
+
/* This won't already be freed in some error cases */
Curl_safefree(smtpc->domain);
smtpc->domain = NULL;
@@ -1389,7 +1541,7 @@ static CURLcode smtp_dophase_done(struct connectdata *conn,
bool connected)
{
struct FTP *smtp = conn->data->state.proto.smtp;
- struct smtp_conn *smtpc= &conn->proto.smtpc;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
(void)connected;
if(smtp->transfer != FTPTRANSFER_BODY)
@@ -1404,7 +1556,7 @@ static CURLcode smtp_dophase_done(struct connectdata *conn,
/* called from multi.c while DOing */
static CURLcode smtp_doing(struct connectdata *conn,
- bool *dophase_done)
+ bool *dophase_done)
{
CURLcode result;
result = smtp_multi_statemach(conn, dophase_done);
@@ -1414,6 +1566,7 @@ static CURLcode smtp_doing(struct connectdata *conn,
DEBUGF(infof(conn->data, "DO phase is complete\n"));
}
+
return result;
}
@@ -1428,10 +1581,10 @@ static CURLcode smtp_doing(struct connectdata *conn,
*/
static
CURLcode smtp_regular_transfer(struct connectdata *conn,
- bool *dophase_done)
+ bool *dophase_done)
{
- CURLcode result=CURLE_OK;
- bool connected=FALSE;
+ CURLcode result = CURLE_OK;
+ bool connected = FALSE;
struct SessionHandle *data = conn->data;
data->req.size = -1; /* make sure this is unknown at this point */
@@ -1458,7 +1611,7 @@ CURLcode smtp_regular_transfer(struct connectdata *conn,
return result;
}
-static CURLcode smtp_setup_connection(struct connectdata * conn)
+static CURLcode smtp_setup_connection(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
@@ -1505,42 +1658,43 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
struct SessionHandle *data = conn->data;
if(data->state.scratch == NULL)
- data->state.scratch = malloc(2*BUFSIZE);
+ data->state.scratch = malloc(2 * BUFSIZE);
if(data->state.scratch == NULL) {
failf (data, "Failed to alloc scratch buffer!");
return CURLE_OUT_OF_MEMORY;
}
/* This loop can be improved by some kind of Boyer-Moore style of
approach but that is saved for later... */
- for(i = 0, si = 0; i < nread; i++, si++) {
- ssize_t left = nread - i;
-
- if(left>= (ssize_t)(SMTP_EOB_LEN-smtpc->eob)) {
- if(!memcmp(SMTP_EOB+smtpc->eob, &data->req.upload_fromhere[i],
- SMTP_EOB_LEN-smtpc->eob)) {
- /* It matched, copy the replacement data to the target buffer
- instead. Note that the replacement does not contain the
- trailing CRLF but we instead continue to match on that one
- to deal with repeated sequences. Like CRLF.CRLF.CRLF etc
- */
- memcpy(&data->state.scratch[si], SMTP_EOB_REPL,
- SMTP_EOB_REPL_LEN);
- si+=SMTP_EOB_REPL_LEN-1; /* minus one since the for() increments
- it */
- i+=SMTP_EOB_LEN-smtpc->eob-1-2;
- smtpc->eob = 0; /* start over */
- continue;
- }
+ for(i = 0, si = 0; i < nread; i++) {
+
+ if(SMTP_EOB[smtpc->eob] == data->req.upload_fromhere[i])
+ smtpc->eob++;
+ else if(smtpc->eob) {
+ /* previously a substring matched, output that first */
+ memcpy(&data->state.scratch[si], SMTP_EOB, smtpc->eob);
+ si += smtpc->eob;
+
+ /* then compare the first byte */
+ if(SMTP_EOB[0] == data->req.upload_fromhere[i])
+ smtpc->eob = 1;
+ else
+ smtpc->eob = 0;
}
- else if(!memcmp(SMTP_EOB+smtpc->eob, &data->req.upload_fromhere[i],
- left)) {
- /* the last piece of the data matches the EOB so we can't send that
- until we know the rest of it */
- smtpc->eob += left;
- break;
+
+ if(SMTP_EOB_LEN == smtpc->eob) {
+ /* It matched, copy the replacement data to the target buffer
+ instead. Note that the replacement does not contain the
+ trailing CRLF but we instead continue to match on that one
+ to deal with repeated sequences. Like CRLF.CRLF.CRLF etc
+ */
+ memcpy(&data->state.scratch[si], SMTP_EOB_REPL,
+ SMTP_EOB_REPL_LEN);
+ si += SMTP_EOB_REPL_LEN;
+ smtpc->eob = 2; /* start over at two bytes */
}
+ else if(!smtpc->eob)
+ data->state.scratch[si++] = data->req.upload_fromhere[i];
- data->state.scratch[si] = data->req.upload_fromhere[i];
} /* for() */
if(si != nread) {
@@ -1553,6 +1707,7 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
/* set the new amount too */
data->req.upload_present = nread;
}
+
return CURLE_OK;
}
diff --git a/lib/smtp.h b/lib/smtp.h
index bc4b91eaa..144d49615 100644
--- a/lib/smtp.h
+++ b/lib/smtp.h
@@ -40,6 +40,8 @@ typedef enum {
SMTP_AUTHLOGIN,
SMTP_AUTHPASSWD,
SMTP_AUTHCRAM,
+ SMTP_AUTHNTLM,
+ SMTP_AUTHNTLM_TYPE2MSG,
SMTP_AUTH,
SMTP_MAIL, /* MAIL FROM */
SMTP_RCPT, /* RCPT TO */
@@ -57,6 +59,7 @@ struct smtp_conn {
size_t eob; /* number of bytes of the EOB (End Of Body) that has been
received thus far */
unsigned int authmechs; /* Accepted authentication methods. */
+ unsigned int authused; /* Authentication method used for the connection */
smtpstate state; /* always use smtp.c:state() to change state! */
struct curl_slist *rcpt;
bool ssldone; /* is connect() over SSL done? only relevant in multi mode */
@@ -69,6 +72,7 @@ struct smtp_conn {
#define SMTP_AUTH_DIGEST_MD5 0x0008
#define SMTP_AUTH_GSSAPI 0x0010
#define SMTP_AUTH_EXTERNAL 0x0020
+#define SMTP_AUTH_NTLM 0x0040
extern const struct Curl_handler Curl_handler_smtp;
extern const struct Curl_handler Curl_handler_smtps;
diff --git a/lib/socks.c b/lib/socks.c
index 82293019b..b382de798 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -23,11 +23,7 @@
#include "setup.h"
#if !defined(CURL_DISABLE_PROXY) || defined(USE_WINDOWS_SSPI)
-#include <string.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -60,28 +56,21 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
curl_socket_t sockfd, /* read from this socket */
char *buf, /* store read data here */
ssize_t buffersize, /* max amount to read */
- ssize_t *n, /* amount bytes read */
- long conn_timeout) /* timeout for data wait
- relative to
- conn->created */
+ ssize_t *n) /* amount bytes read */
{
ssize_t nread;
ssize_t allread = 0;
int result;
- struct timeval tvnow;
- long conntime;
+ long timeleft;
*n = 0;
for(;;) {
- tvnow = Curl_tvnow();
- /* calculating how long connection is establishing */
- conntime = Curl_tvdiff(tvnow, conn->created);
- if(conntime > conn_timeout) {
+ timeleft = Curl_timeleft(conn->data, NULL, TRUE);
+ if(timeleft < 0) {
/* we already got the timeout */
result = CURLE_OPERATION_TIMEDOUT;
break;
}
- if(Curl_socket_ready(sockfd, CURL_SOCKET_BAD,
- conn_timeout - conntime) <= 0) {
+ if(Curl_socket_ready(sockfd, CURL_SOCKET_BAD, timeleft) <= 0) {
result = ~CURLE_OK;
break;
}
@@ -133,13 +122,9 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
int result;
CURLcode code;
curl_socket_t sock = conn->sock[sockindex];
- long timeout;
struct SessionHandle *data = conn->data;
- /* get timeout */
- timeout = Curl_timeleft(data, NULL, TRUE);
-
- if(timeout < 0) {
+ if(Curl_timeleft(data, NULL, TRUE) < 0) {
/* time-out, bail out, go home */
failf(data, "Connection time-out");
return CURLE_OPERATION_TIMEDOUT;
@@ -264,7 +249,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
/* Receive response */
result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize,
- &actualread, timeout);
+ &actualread);
if((result != CURLE_OK) || (actualread != packetsize)) {
failf(data, "Failed to receive SOCKS4 connect request ack.");
return CURLE_COULDNT_CONNECT;
@@ -299,10 +284,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
/* Result */
switch(socksreq[1]) {
case 90:
- if(protocol4a)
- infof(data, "SOCKS4a request granted.\n");
- else
- infof(data, "SOCKS4 request granted.\n");
+ infof(data, "SOCKS4%s request granted.\n", protocol4a?"a":"");
break;
case 91:
failf(data,
@@ -386,7 +368,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
curl_socket_t sock = conn->sock[sockindex];
struct SessionHandle *data = conn->data;
long timeout;
- bool socks5_resolve_local = (bool)(conn->proxytype == CURLPROXY_SOCKS5);
+ bool socks5_resolve_local = (conn->proxytype == CURLPROXY_SOCKS5)?TRUE:FALSE;
const size_t hostname_len = strlen(hostname);
ssize_t packetsize = 0;
@@ -466,8 +448,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
curlx_nonblock(sock, FALSE);
- result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread,
- timeout);
+ result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
if((result != CURLE_OK) || (actualread != 2)) {
failf(data, "Unable to receive initial SOCKS5 response.");
return CURLE_COULDNT_CONNECT;
@@ -527,8 +508,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
return CURLE_COULDNT_CONNECT;
}
- result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread,
- timeout);
+ result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
if((result != CURLE_OK) || (actualread != 2)) {
failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
return CURLE_COULDNT_CONNECT;
@@ -664,7 +644,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
else
#endif
result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize,
- &actualread, timeout);
+ &actualread);
if((result != CURLE_OK) || (actualread != packetsize)) {
failf(data, "Failed to receive SOCKS5 connect request ack.");
return CURLE_COULDNT_CONNECT;
@@ -720,7 +700,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
if(packetsize > 10) {
packetsize -= 10;
result = Curl_blockread_all(conn, sock, (char *)&socksreq[10],
- packetsize, &actualread, timeout);
+ packetsize, &actualread);
if((result != CURLE_OK) || (actualread != packetsize)) {
failf(data, "Failed to receive SOCKS5 connect request ack.");
return CURLE_COULDNT_CONNECT;
diff --git a/lib/socks.h b/lib/socks.h
index 42b8080b0..fc4cc7f02 100644
--- a/lib/socks.h
+++ b/lib/socks.h
@@ -39,8 +39,7 @@ int Curl_blockread_all(struct connectdata *conn,
curl_socket_t sockfd,
char *buf,
ssize_t buffersize,
- ssize_t *n,
- long conn_timeout);
+ ssize_t *n);
/*
* This function logs in to a SOCKS4(a) proxy and sends the specifics to the
diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c
index 653306cce..d23a944d7 100644
--- a/lib/socks_gssapi.c
+++ b/lib/socks_gssapi.c
@@ -27,16 +27,13 @@
#ifdef HAVE_GSSAPI
#ifdef HAVE_OLD_GSSMIT
#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
+#define NCOMPAT 1
#endif
#ifndef gss_nt_service_name
#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
#endif
-#include <string.h>
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
+#include "curl_gssapi.h"
#include "urldata.h"
#include "sendf.h"
#include "connect.h"
@@ -121,7 +118,6 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
ssize_t actualread;
ssize_t written;
int result;
- long timeout;
OM_uint32 gss_major_status, gss_minor_status, gss_status;
OM_uint32 gss_ret_flags;
int gss_conf_state, gss_enc;
@@ -137,9 +133,6 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
unsigned char socksreq[4]; /* room for gssapi exchange header only */
char *serviceptr = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
- /* get timeout */
- timeout = Curl_timeleft(data, NULL, TRUE);
-
/* GSSAPI request looks like
* +----+------+-----+----------------+
* |VER | MTYP | LEN | TOKEN |
@@ -183,19 +176,14 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
/* As long as we need to keep sending some context info, and there's no */
/* errors, keep sending it... */
for(;;) {
- gss_major_status = gss_init_sec_context(&gss_minor_status,
- GSS_C_NO_CREDENTIAL,
- &gss_context, server,
- GSS_C_NULL_OID,
- GSS_C_MUTUAL_FLAG |
- GSS_C_REPLAY_FLAG,
- 0,
- NULL,
- gss_token,
- NULL,
- &gss_send_token,
- &gss_ret_flags,
- NULL);
+ gss_major_status = Curl_gss_init_sec_context(data,
+ &gss_minor_status,
+ &gss_context,
+ server,
+ NULL,
+ gss_token,
+ &gss_send_token,
+ &gss_ret_flags);
if(gss_token != GSS_C_NO_BUFFER)
gss_release_buffer(&gss_status, &gss_recv_token);
@@ -253,8 +241,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
* +----+------+-----+----------------+
*/
- result=Curl_blockread_all(conn, sock, (char *)socksreq, 4,
- &actualread, timeout);
+ result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
if(result != CURLE_OK || actualread != 4) {
failf(data, "Failed to receive GSSAPI authentication response.");
gss_release_name(&gss_status, &server);
@@ -294,8 +281,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
}
result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
- gss_recv_token.length,
- &actualread, timeout);
+ gss_recv_token.length, &actualread);
if(result != CURLE_OK || actualread != us_length) {
failf(data, "Failed to receive GSSAPI authentication token.");
@@ -452,8 +438,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
gss_release_buffer(&gss_status, &gss_w_token);
}
- result=Curl_blockread_all(conn, sock, (char *)socksreq, 4,
- &actualread, timeout);
+ result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
if(result != CURLE_OK || actualread != 4) {
failf(data, "Failed to receive GSSAPI encryption response.");
gss_delete_sec_context(&gss_status, &gss_context, NULL);
@@ -485,8 +470,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_OUT_OF_MEMORY;
}
result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
- gss_recv_token.length,
- &actualread, timeout);
+ gss_recv_token.length, &actualread);
if(result != CURLE_OK || actualread != us_length) {
failf(data, "Failed to receive GSSAPI encryptrion type.");
diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c
index 6d42af3a5..d96a82e8a 100644
--- a/lib/socks_sspi.c
+++ b/lib/socks_sspi.c
@@ -20,17 +20,10 @@
*
***************************************************************************/
-
#include "setup.h"
#ifdef USE_WINDOWS_SSPI
-#include <string.h>
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
#include "urldata.h"
#include "sendf.h"
#include "connect.h"
@@ -167,7 +160,6 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
ssize_t actualread;
ssize_t written;
int result;
- long timeout;
/* Needs GSSAPI authentication */
SECURITY_STATUS sspi_major_status, sspi_minor_status=0;
unsigned long sspi_ret_flags=0;
@@ -186,9 +178,6 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
unsigned char socksreq[4]; /* room for gssapi exchange header only */
char *service = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
- /* get timeout */
- timeout = Curl_timeleft(data, NULL, TRUE);
-
/* GSSAPI request looks like
* +----+------+-----+----------------+
* |VER | MTYP | LEN | TOKEN |
@@ -283,7 +272,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
}
if(check_sspi_err(data,sspi_major_status,sspi_minor_status,
- "InitializeSecurityContextA") ){
+ "InitializeSecurityContextA") ) {
free(service_name);
service_name=NULL;
s_pSecFn->FreeCredentialsHandle(&cred_handle);
@@ -344,8 +333,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
* +----+------+-----+----------------+
*/
- result=Curl_blockread_all(conn, sock, (char *)socksreq, 4,
- &actualread, timeout);
+ result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
if(result != CURLE_OK || actualread != 4) {
failf(data, "Failed to receive SSPI authentication response.");
free(service_name);
@@ -390,8 +378,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_OUT_OF_MEMORY;
}
result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer,
- sspi_recv_token.cbBuffer,
- &actualread, timeout);
+ sspi_recv_token.cbBuffer, &actualread);
if(result != CURLE_OK || actualread != us_length) {
failf(data, "Failed to receive SSPI authentication token.");
@@ -416,7 +403,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
&names);
s_pSecFn->FreeCredentialsHandle(&cred_handle);
if(check_sspi_err(data,sspi_major_status,sspi_minor_status,
- "QueryCredentialAttributes") ){
+ "QueryCredentialAttributes") ) {
s_pSecFn->DeleteSecurityContext(&sspi_context);
s_pSecFn->FreeContextBuffer(names.sUserName);
failf(data, "Failed to determine user name.");
@@ -499,7 +486,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
sspi_w_token[1].cbBuffer = 1;
sspi_w_token[1].pvBuffer = malloc(1);
- if(!sspi_w_token[1].pvBuffer){
+ if(!sspi_w_token[1].pvBuffer) {
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
s_pSecFn->DeleteSecurityContext(&sspi_context);
return CURLE_OUT_OF_MEMORY;
@@ -592,8 +579,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
}
- result=Curl_blockread_all(conn, sock, (char *)socksreq, 4,
- &actualread, timeout);
+ result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
if(result != CURLE_OK || actualread != 4) {
failf(data, "Failed to receive SSPI encryption response.");
s_pSecFn->DeleteSecurityContext(&sspi_context);
@@ -626,8 +612,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
}
result=Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer,
- sspi_w_token[0].cbBuffer,
- &actualread, timeout);
+ sspi_w_token[0].cbBuffer, &actualread);
if(result != CURLE_OK || actualread != us_length) {
failf(data, "Failed to receive SSPI encryption type.");
diff --git a/lib/speedcheck.c b/lib/speedcheck.c
index 56ac34aef..ca2323f57 100644
--- a/lib/speedcheck.c
+++ b/lib/speedcheck.c
@@ -22,9 +22,6 @@
#include "setup.h"
-#include <stdio.h>
-#include <string.h>
-
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
@@ -44,12 +41,12 @@ CURLcode Curl_speedcheck(struct SessionHandle *data,
(Curl_tvlong(data->state.keeps_speed) != 0) &&
(data->progress.current_speed < data->set.low_speed_limit)) {
long howlong = Curl_tvdiff(now, data->state.keeps_speed);
+ long nextcheck = (data->set.low_speed_time * 1000) - howlong;
/* We are now below the "low speed limit". If we are below it
for "low speed time" seconds we consider that enough reason
to abort the download. */
-
- if((howlong/1000) > data->set.low_speed_time) {
+ if(nextcheck <= 0) {
/* we have been this slow for long enough, now die */
failf(data,
"Operation too slow. "
@@ -58,7 +55,10 @@ CURLcode Curl_speedcheck(struct SessionHandle *data,
data->set.low_speed_time);
return CURLE_OPERATION_TIMEDOUT;
}
- Curl_expire(data, howlong);
+ else {
+ /* wait complete low_speed_time */
+ Curl_expire(data, nextcheck);
+ }
}
else {
/* we keep up the required speed all right */
diff --git a/lib/splay.h b/lib/splay.h
index 832e4e2bb..49a6dec41 100644
--- a/lib/splay.h
+++ b/lib/splay.h
@@ -1,5 +1,5 @@
-#ifndef __SPLAY_H
-#define __SPLAY_H
+#ifndef HEADER_CURL_SPLAY_H
+#define HEADER_CURL_SPLAY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1997 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1997 - 2011, 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,7 @@
* KIND, either express or implied.
*
***************************************************************************/
+#include "setup.h"
struct Curl_tree {
struct Curl_tree *smaller; /* smaller node */
@@ -59,7 +60,7 @@ int Curl_splayremovebyaddr(struct Curl_tree *t,
#ifdef DEBUGBUILD
void Curl_splayprint(struct Curl_tree * t, int d, char output);
#else
-#define Curl_splayprint(x,y,z)
+#define Curl_splayprint(x,y,z) Curl_nop_stmt
#endif
-#endif
+#endif /* HEADER_CURL_SPLAY_H */
diff --git a/lib/ssh.c b/lib/ssh.c
index 1c14b34d5..a9e4c56e4 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -25,11 +25,7 @@
#include "setup.h"
#ifdef USE_LIBSSH2
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
+
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
@@ -45,11 +41,6 @@
#include <fcntl.h>
#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-
-#ifndef WIN32
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -69,7 +60,6 @@
#include <in.h>
#include <inet.h>
#endif
-#endif /* !WIN32 */
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
@@ -108,6 +98,11 @@
/* The last #include file should be: */
#include "memdebug.h"
+#ifdef WIN32
+# undef PATH_MAX
+# define PATH_MAX MAX_PATH
+#endif
+
#ifndef PATH_MAX
#define PATH_MAX 1024 /* just an extra precaution since there are systems that
have their definition hidden well */
@@ -170,6 +165,7 @@ const struct Curl_handler Curl_handler_scp = {
scp_doing, /* doing */
ssh_getsock, /* proto_getsock */
ssh_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ssh_perform_getsock, /* perform_getsock */
scp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -194,6 +190,7 @@ const struct Curl_handler Curl_handler_sftp = {
sftp_doing, /* doing */
ssh_getsock, /* proto_getsock */
ssh_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ssh_perform_getsock, /* perform_getsock */
sftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -649,6 +646,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
const char *fingerprint;
#endif /* CURL_LIBSSH2_DEBUG */
const char *host_public_key_md5;
+ char *new_readdir_line;
int rc = LIBSSH2_ERROR_NONE, i;
int err;
int seekerr = CURL_SEEKFUNC_OK;
@@ -1581,7 +1579,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
SEEK_SET);
}
- if(seekerr != CURL_SEEKFUNC_OK){
+ if(seekerr != CURL_SEEKFUNC_OK) {
if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
failf(data, "Could not seek stream");
@@ -1864,10 +1862,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
Curl_safefree(sshc->readdir_linkPath);
sshc->readdir_linkPath = NULL;
- sshc->readdir_line = realloc(sshc->readdir_line,
- sshc->readdir_totalLen + 4 +
- sshc->readdir_len);
- if(!sshc->readdir_line) {
+
+ new_readdir_line = realloc(sshc->readdir_line,
+ sshc->readdir_totalLen + 4 +
+ sshc->readdir_len);
+ if(!new_readdir_line) {
+ Curl_safefree(sshc->readdir_line);
+ sshc->readdir_line = NULL;
Curl_safefree(sshc->readdir_filename);
sshc->readdir_filename = NULL;
Curl_safefree(sshc->readdir_longentry);
@@ -1876,6 +1877,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
+ sshc->readdir_line = new_readdir_line;
sshc->readdir_currLen += snprintf(sshc->readdir_line +
sshc->readdir_currLen,
@@ -2388,10 +2390,39 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
sshc->ssh_session = NULL;
}
+
+ /* worst-case scenario cleanup */
+
+ DEBUGASSERT(sshc->ssh_session == NULL);
+ DEBUGASSERT(sshc->ssh_channel == NULL);
+ DEBUGASSERT(sshc->sftp_session == NULL);
+ DEBUGASSERT(sshc->sftp_handle == NULL);
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ DEBUGASSERT(sshc->kh == NULL);
+#endif
+
+ Curl_safefree(sshc->rsa_pub);
+ Curl_safefree(sshc->rsa);
+
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+
+ Curl_safefree(sshc->homedir);
+
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+ Curl_safefree(sshc->readdir_line);
+ Curl_safefree(sshc->readdir_linkPath);
+
+ /* the code we are about to return */
+ result = sshc->actualcode;
+
+ memset(sshc, 0, sizeof(struct ssh_conn));
+
conn->bits.close = TRUE;
+ sshc->state = SSH_SESSION_FREE; /* current */
sshc->nextstate = SSH_NO_STATE;
state(conn, SSH_STOP);
- result = sshc->actualcode;
break;
case SSH_QUIT:
@@ -2488,7 +2519,7 @@ static void ssh_block2waitfor(struct connectdata *conn, bool block)
}
#else
/* no libssh2 directional support so we simply don't know */
-#define ssh_block2waitfor(x,y)
+#define ssh_block2waitfor(x,y) Curl_nop_stmt
#endif
/* called repeatedly until done from multi.c */
@@ -2500,7 +2531,7 @@ static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
implementation */
result = ssh_statemach_act(conn, &block);
- *done = (bool)(sshc->state == SSH_STOP);
+ *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
ssh_block2waitfor(conn, block);
return result;
@@ -2706,7 +2737,7 @@ CURLcode scp_perform(struct connectdata *conn,
result = ssh_easy_statemach(conn, FALSE);
*dophase_done = TRUE; /* with the easy interface we are done here */
}
- *connected = conn->bits.tcpconnect;
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
DEBUGF(infof(conn->data, "DO phase is complete\n"));
@@ -2913,7 +2944,7 @@ CURLcode sftp_perform(struct connectdata *conn,
result = ssh_easy_statemach(conn, FALSE);
*dophase_done = TRUE; /* with the easy interface we are done here */
}
- *connected = conn->bits.tcpconnect;
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
DEBUGF(infof(conn->data, "DO phase is complete\n"));
diff --git a/lib/sslgen.c b/lib/sslgen.c
index 779d9e9c3..3b7340244 100644
--- a/lib/sslgen.c
+++ b/lib/sslgen.c
@@ -43,9 +43,6 @@
#include "setup.h"
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -65,6 +62,7 @@
#include "url.h"
#include "curl_memory.h"
#include "progress.h"
+#include "share.h"
/* The last #include file should be: */
#include "memdebug.h"
@@ -72,10 +70,10 @@ static bool safe_strequal(char* str1, char* str2)
{
if(str1 && str2)
/* both pointers point to something then compare them */
- return (bool)(0 != Curl_raw_equal(str1, str2));
+ return (0 != Curl_raw_equal(str1, str2)) ? TRUE : FALSE;
else
/* if both pointers are NULL then treat them as equal */
- return (bool)(!str1 && !str2);
+ return (!str1 && !str2) ? TRUE : FALSE;
}
bool
@@ -213,7 +211,7 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
/* mark this is being ssl requested from here on. */
conn->ssl[sockindex].use = TRUE;
res = curlssl_connect_nonblocking(conn, sockindex, done);
- if(!res && *done == TRUE)
+ if(!res && *done)
Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
return res;
#else
@@ -239,6 +237,10 @@ int Curl_ssl_getsessionid(struct connectdata *conn,
/* session ID re-use is disabled */
return TRUE;
+ /* Lock for reading if shared */
+ if(data->share && data->share->sslsession == data->state.session)
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SHARED);
+
for(i=0; i< data->set.ssl.numsessions; i++) {
check = &data->state.session[i];
if(!check->sessionid)
@@ -257,13 +259,19 @@ int Curl_ssl_getsessionid(struct connectdata *conn,
}
}
*ssl_sessionid = NULL;
+
+ /* Unlock for reading */
+ if(data->share && data->share->sslsession == data->state.session)
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
+
+
return TRUE;
}
/*
* Kill a single session ID entry in the cache.
*/
-static int kill_session(struct curl_ssl_session *session)
+int Curl_ssl_kill_session(struct curl_ssl_session *session)
{
if(session->sessionid) {
/* defensive check */
@@ -291,14 +299,23 @@ static int kill_session(struct curl_ssl_session *session)
void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
{
int i;
- for(i=0; i< conn->data->set.ssl.numsessions; i++) {
- struct curl_ssl_session *check = &conn->data->state.session[i];
+ struct SessionHandle *data=conn->data;
+
+ if(data->share && data->share->sslsession == data->state.session)
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION,
+ CURL_LOCK_ACCESS_SINGLE);
+
+ for(i=0; i< data->set.ssl.numsessions; i++) {
+ struct curl_ssl_session *check = &data->state.session[i];
if(check->sessionid == ssl_sessionid) {
- kill_session(check);
+ Curl_ssl_kill_session(check);
break;
}
}
+
+ if(data->share && data->share->sslsession == data->state.session)
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
}
/*
@@ -328,6 +345,10 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
/* Now we should add the session ID and the host name to the cache, (remove
the oldest if necessary) */
+ /* If using shared SSL session, lock! */
+ if(data->share && data->share->sslsession == data->state.session)
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
+
/* find an empty slot for us, or find the oldest */
for(i=1; (i<data->set.ssl.numsessions) &&
data->state.session[i].sessionid; i++) {
@@ -338,7 +359,7 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
}
if(i == data->set.ssl.numsessions)
/* cache is full, we must "kill" the oldest entry! */
- kill_session(store);
+ Curl_ssl_kill_session(store);
else
store = &data->state.session[i]; /* use this slot */
@@ -352,6 +373,11 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
store->name = clone_host; /* clone host name */
store->remote_port = conn->remote_port; /* port number */
+
+ /* Unlock */
+ if(data->share && data->share->sslsession == data->state.session)
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
+
if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) {
store->sessionid = NULL; /* let caller free sessionid */
free(clone_host);
@@ -366,14 +392,20 @@ void Curl_ssl_close_all(struct SessionHandle *data)
{
long i;
/* kill the session ID cache */
- if(data->state.session) {
+ if(data->state.session &&
+ !(data->share && data->share->sslsession == data->state.session)) {
+
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
+
for(i=0; i< data->set.ssl.numsessions; i++)
/* the single-killer function handles empty table slots */
- kill_session(&data->state.session[i]);
+ Curl_ssl_kill_session(&data->state.session[i]);
/* free the cache data */
free(data->state.session);
data->state.session = NULL;
+
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
}
curlssl_close_all(data);
@@ -472,9 +504,12 @@ void Curl_ssl_free_certinfo(struct SessionHandle *data)
struct curl_certinfo *ci = &data->info.certs;
if(ci->num_of_certs) {
/* free all individual lists used */
- for(i=0; i<ci->num_of_certs; i++)
+ for(i=0; i<ci->num_of_certs; i++) {
curl_slist_free_all(ci->certinfo[i]);
+ ci->certinfo[i] = NULL;
+ }
free(ci->certinfo); /* free the actual array too */
+ ci->certinfo = NULL;
ci->num_of_certs = 0;
}
}
diff --git a/lib/sslgen.h b/lib/sslgen.h
index b0a0fab12..516817618 100644
--- a/lib/sslgen.h
+++ b/lib/sslgen.h
@@ -1,5 +1,5 @@
-#ifndef __SSLGEN_H
-#define __SSLGEN_H
+#ifndef HEADER_CURL_SSLGEN_H
+#define HEADER_CURL_SSLGEN_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -21,6 +21,7 @@
* KIND, either express or implied.
*
***************************************************************************/
+#include "setup.h"
bool Curl_ssl_config_matches(struct ssl_config_data* data,
struct ssl_config_data* needle);
@@ -63,6 +64,8 @@ int Curl_ssl_getsessionid(struct connectdata *conn,
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
void *ssl_sessionid,
size_t idsize);
+/* Kill a single session ID entry in the cache */
+int Curl_ssl_kill_session(struct curl_ssl_session *session);
/* delete a session from the cache */
void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);
@@ -71,10 +74,10 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);
#else
/* When SSL support is not present, just define away these function calls */
#define Curl_ssl_init() 1
-#define Curl_ssl_cleanup() do { } while (0)
+#define Curl_ssl_cleanup() Curl_nop_stmt
#define Curl_ssl_connect(x,y) CURLE_NOT_BUILT_IN
-#define Curl_ssl_close_all(x)
-#define Curl_ssl_close(x,y)
+#define Curl_ssl_close_all(x) Curl_nop_stmt
+#define Curl_ssl_close(x,y) Curl_nop_stmt
#define Curl_ssl_shutdown(x,y) CURLE_NOT_BUILT_IN
#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN
#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN
@@ -85,8 +88,9 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);
#define Curl_ssl_version(x,y) 0
#define Curl_ssl_data_pending(x,y) 0
#define Curl_ssl_check_cxn(x) 0
-#define Curl_ssl_free_certinfo(x)
+#define Curl_ssl_free_certinfo(x) Curl_nop_stmt
#define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN
+#define Curl_ssl_kill_session(x) 0
#endif
-#endif /* USE_SSL */
+#endif /* HEADER_CURL_SSLGEN_H */
diff --git a/lib/ssluse.c b/lib/ssluse.c
index 5bdc536a3..d65fd98b9 100644
--- a/lib/ssluse.c
+++ b/lib/ssluse.c
@@ -32,9 +32,6 @@
#include "setup.h"
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
@@ -123,7 +120,7 @@
/* 0.9.6 didn't have X509_STORE_set_flags() */
#define HAVE_X509_STORE_SET_FLAGS 1
#else
-#define X509_STORE_set_flags(x,y)
+#define X509_STORE_set_flags(x,y) Curl_nop_stmt
#endif
/*
@@ -169,14 +166,14 @@ static int passwd_callback(char *buf, int num, int verify
#define seed_enough(x) rand_enough()
static bool rand_enough(void)
{
- return (bool)(0 != RAND_status());
+ return (0 != RAND_status()) ? TRUE : FALSE;
}
#else
#define seed_enough(x) rand_enough(x)
static bool rand_enough(int nread)
{
/* this is a very silly decision to make */
- return (bool)(nread > 500);
+ return (nread > 500) ? TRUE : FALSE;
}
#endif
@@ -813,18 +810,16 @@ struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data)
{
struct curl_slist *list = NULL;
#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
- struct curl_slist *beg = NULL;
+ struct curl_slist *beg;
ENGINE *e;
for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) {
- list = curl_slist_append(list, ENGINE_get_id(e));
- if(list == NULL) {
- curl_slist_free_all(beg);
+ beg = curl_slist_append(list, ENGINE_get_id(e));
+ if(!beg) {
+ curl_slist_free_all(list);
return NULL;
}
- else if(beg == NULL) {
- beg = list;
- }
+ list = beg;
}
#endif
(void) data;
@@ -1410,7 +1405,7 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
# define use_sni(x) sni = (x)
#else
-# define use_sni(x) do { } while (0)
+# define use_sni(x) Curl_nop_stmt
#endif
static CURLcode
@@ -1492,6 +1487,10 @@ ossl_connect_step1(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
+#ifdef SSL_MODE_RELEASE_BUFFERS
+ SSL_CTX_set_mode(connssl->ctx, SSL_MODE_RELEASE_BUFFERS);
+#endif
+
#ifdef SSL_CTRL_SET_MSG_CALLBACK
if(data->set.fdebug && data->set.verbose) {
/* the SSL trace callback is only used for verbose logging so we only
@@ -1856,15 +1855,15 @@ static CURLcode push_certinfo_len(struct SessionHandle *data,
equivalent of curl_slist_append but doesn't strdup() the given data as
like in this place the extra malloc/free is totally pointless */
nl = curl_slist_append(ci->certinfo[certnum], output);
+ free(output);
if(!nl) {
curl_slist_free_all(ci->certinfo[certnum]);
+ ci->certinfo[certnum] = NULL;
res = CURLE_OUT_OF_MEMORY;
}
else
ci->certinfo[certnum] = nl;
- free(output);
-
return res;
}
@@ -1918,7 +1917,7 @@ do { \
pubkey_show(data, _num, #_type, #_name, (unsigned char*)bufp, len); \
} \
} \
-} while(0)
+} WHILE_FALSE
static int X509V3_ext(struct SessionHandle *data,
int certnum,
@@ -2563,7 +2562,7 @@ bool Curl_ossl_data_pending(const struct connectdata *conn,
{
if(conn->ssl[connindex].handle)
/* SSL is in use */
- return (bool)(0 != SSL_pending(conn->ssl[connindex].handle));
+ return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
else
return FALSE;
}
diff --git a/lib/ssluse.h b/lib/ssluse.h
index 2ac0ad2ec..732ec7c72 100644
--- a/lib/ssluse.h
+++ b/lib/ssluse.h
@@ -1,5 +1,5 @@
-#ifndef __SSLUSE_H
-#define __SSLUSE_H
+#ifndef HEADER_CURL_SSLUSE_H
+#define HEADER_CURL_SSLUSE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -22,12 +22,15 @@
*
***************************************************************************/
+#include "setup.h"
+
#ifdef USE_SSLEAY
/*
* This header should only be needed to get included by sslgen.c and ssluse.c
*/
#include "urldata.h"
+
CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex);
CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
int sockindex,
@@ -81,4 +84,4 @@ bool Curl_ossl_data_pending(const struct connectdata *conn,
#define curlssl_data_pending(x,y) Curl_ossl_data_pending(x,y)
#endif /* USE_SSLEAY */
-#endif /* __SSLUSE_H */
+#endif /* HEADER_CURL_SSLUSE_H */
diff --git a/lib/strdup.c b/lib/strdup.c
index a3107cff7..02d480c26 100644
--- a/lib/strdup.c
+++ b/lib/strdup.c
@@ -21,6 +21,7 @@
***************************************************************************/
#include "setup.h"
+
#include "strdup.h"
#ifndef HAVE_STRDUP
diff --git a/lib/strequal.c b/lib/strequal.c
index 15896b9fd..89ad8a6e8 100644
--- a/lib/strequal.c
+++ b/lib/strequal.c
@@ -22,9 +22,6 @@
#include "setup.h"
-#include <string.h>
-#include <ctype.h>
-
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
diff --git a/lib/strerror.c b/lib/strerror.c
index 0a883421e..fcb617cf2 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -34,9 +34,6 @@
#endif
#include <curl/curl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
#ifdef USE_LIBIDN
#include <idna.h>
@@ -387,6 +384,9 @@ curl_share_strerror(CURLSHcode error)
case CURLSHE_NOMEM:
return "Out of memory";
+ case CURLSHE_NOT_BUILT_IN:
+ return "Feature not enabled in this library";
+
case CURLSHE_LAST:
break;
}
diff --git a/lib/strtok.c b/lib/strtok.c
index 91c254156..94eac0e64 100644
--- a/lib/strtok.c
+++ b/lib/strtok.c
@@ -24,7 +24,6 @@
#ifndef HAVE_STRTOK_R
#include <stddef.h>
-#include <string.h>
#include "strtok.h"
diff --git a/lib/strtoofft.c b/lib/strtoofft.c
index 55a6ffd0d..c61459de8 100644
--- a/lib/strtoofft.c
+++ b/lib/strtoofft.c
@@ -21,6 +21,7 @@
***************************************************************************/
#include "setup.h"
+
#include "strtoofft.h"
/*
@@ -32,15 +33,11 @@
*/
#ifdef NEED_CURL_STRTOLL
-#include <stdlib.h>
-#include <ctype.h>
-#include <errno.h>
/* Range tests can be used for alphanum decoding if characters are consecutive,
like in ASCII. Else an array is scanned. Determine this condition now. */
#if('9' - '0') != 9 || ('Z' - 'A') != 25 || ('z' - 'a') != 25
-#include <string.h>
#define NO_RANGE_TEST
diff --git a/lib/telnet.c b/lib/telnet.c
index 80592d27e..59094b674 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -23,28 +23,19 @@
#include "setup.h"
#ifndef CURL_DISABLE_TELNET
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#if defined(WIN32)
-#include <time.h>
-#include <io.h>
-#else
+
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
+#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef HAVE_NETDB_H
#include <netdb.h>
+#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
@@ -59,8 +50,6 @@
#include <sys/param.h>
#endif
-#endif /* WIN32 */
-
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
@@ -99,7 +88,7 @@
#define CURL_SB_LEN(x) (x->subend - x->subpointer)
#ifdef CURL_DISABLE_VERBOSE_STRINGS
-#define printoption(a,b,c,d) do { } while(0)
+#define printoption(a,b,c,d) Curl_nop_stmt
#endif
#ifdef USE_WINSOCK
@@ -193,6 +182,7 @@ const struct Curl_handler Curl_handler_telnet = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -774,18 +764,24 @@ static void printsub(struct SessionHandle *data,
static CURLcode check_telnet_options(struct connectdata *conn)
{
struct curl_slist *head;
+ struct curl_slist *beg;
char option_keyword[128];
char option_arg[256];
- char *buf;
struct SessionHandle *data = conn->data;
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
+ CURLcode result = CURLE_OK;
/* Add the user name as an environment variable if it
was given on the command line */
if(conn->bits.user_passwd) {
snprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
- tn->telnet_vars = curl_slist_append(tn->telnet_vars, option_arg);
-
+ beg = curl_slist_append(tn->telnet_vars, option_arg);
+ if(!beg) {
+ curl_slist_free_all(tn->telnet_vars);
+ tn->telnet_vars = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ tn->telnet_vars = beg;
tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
}
@@ -811,24 +807,33 @@ static CURLcode check_telnet_options(struct connectdata *conn)
/* Environment variable */
if(Curl_raw_equal(option_keyword, "NEW_ENV")) {
- buf = strdup(option_arg);
- if(!buf)
- return CURLE_OUT_OF_MEMORY;
- tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf);
+ beg = curl_slist_append(tn->telnet_vars, option_arg);
+ if(!beg) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ tn->telnet_vars = beg;
tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
continue;
}
failf(data, "Unknown telnet option %s", head->data);
- return CURLE_UNKNOWN_TELNET_OPTION;
+ result = CURLE_UNKNOWN_TELNET_OPTION;
+ break;
}
else {
failf(data, "Syntax error in telnet option: %s", head->data);
- return CURLE_TELNET_OPTION_SYNTAX;
+ result = CURLE_TELNET_OPTION_SYNTAX;
+ break;
}
}
- return CURLE_OK;
+ if(result) {
+ curl_slist_free_all(tn->telnet_vars);
+ tn->telnet_vars = NULL;
+ }
+
+ return result;
}
/*
@@ -1120,6 +1125,7 @@ static CURLcode telnet_done(struct connectdata *conn,
(void)premature; /* not used */
curl_slist_free_all(tn->telnet_vars);
+ tn->telnet_vars = NULL;
free(conn->data->state.proto.telnet);
conn->data->state.proto.telnet = NULL;
@@ -1238,13 +1244,6 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
return CURLE_FAILED_INIT;
}
- /* The get the Windows file handle for stdin */
- stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
-
- /* Create the list of objects to wait for */
- objs[0] = event_handle;
- objs[1] = stdin_handle;
-
/* Tell winsock what events we want to listen to */
if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) ==
SOCKET_ERROR) {
@@ -1253,9 +1252,17 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
return CURLE_OK;
}
+ /* The get the Windows file handle for stdin */
+ stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
+
+ /* Create the list of objects to wait for */
+ objs[0] = event_handle;
+ objs[1] = stdin_handle;
+
/* If stdin_handle is a pipe, use PeekNamedPipe() method to check it,
else use the old WaitForMultipleObjects() way */
- if(GetFileType(stdin_handle) == FILE_TYPE_PIPE) {
+ if(GetFileType(stdin_handle) == FILE_TYPE_PIPE ||
+ data->set.is_fread_set) {
/* Don't wait for stdin_handle, just wait for event_handle */
obj_count = 1;
/* Check stdin_handle per 100 milliseconds */
@@ -1273,20 +1280,41 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
case WAIT_TIMEOUT:
{
for(;;) {
- if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, &readfile_read, NULL)) {
- keepon = FALSE;
- code = CURLE_READ_ERROR;
- break;
+ if(obj_count == 1) {
+ /* read from user-supplied method */
+ code = (int)conn->fread_func(buf, 1, BUFSIZE - 1, conn->fread_in);
+ if(code == CURL_READFUNC_ABORT) {
+ keepon = FALSE;
+ code = CURLE_READ_ERROR;
+ break;
+ }
+
+ if(code == CURL_READFUNC_PAUSE)
+ break;
+
+ if(code == 0) /* no bytes */
+ break;
+
+ readfile_read = code; /* fall thru with number of bytes read */
}
+ else {
+ /* read from stdin */
+ if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL,
+ &readfile_read, NULL)) {
+ keepon = FALSE;
+ code = CURLE_READ_ERROR;
+ break;
+ }
- if(!readfile_read)
- break;
+ if(!readfile_read)
+ break;
- if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
- &readfile_read, NULL)) {
- keepon = FALSE;
- code = CURLE_READ_ERROR;
- break;
+ if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
+ &readfile_read, NULL)) {
+ keepon = FALSE;
+ code = CURLE_READ_ERROR;
+ break;
+ }
}
code = send_telnet_data(conn, buf, readfile_read);
@@ -1375,7 +1403,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
/* We called WSACreateEvent, so call WSACloseEvent */
- if(close_event_func(event_handle) == FALSE) {
+ if(!close_event_func(event_handle)) {
infof(data,"WSACloseEvent failed (%d)", SOCKERRNO);
}
diff --git a/lib/tftp.c b/lib/tftp.c
index 46b3ecfcb..9b44a9b3d 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -23,27 +23,19 @@
#include "setup.h"
#ifndef CURL_DISABLE_TFTP
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#if defined(WIN32)
-#include <time.h>
-#include <io.h>
-#else
+
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
+#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef HAVE_NETDB_H
#include <netdb.h>
+#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
@@ -58,8 +50,6 @@
#include <sys/param.h>
#endif
-#endif /* WIN32 */
-
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
@@ -194,6 +184,7 @@ const struct Curl_handler Curl_handler_tftp = {
tftp_doing, /* doing */
tftp_getsock, /* proto_getsock */
tftp_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
tftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -216,7 +207,7 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
{
time_t maxtime, timeout;
long timeout_ms;
- bool start = (bool)(state->state == TFTP_STATE_START);
+ bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE;
time(&state->start_time);
@@ -258,11 +249,11 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
state->max_time = state->start_time+maxtime;
- /* Set per-block timeout to 10% of total */
- timeout = maxtime/10 ;
+ /* Set per-block timeout to total */
+ timeout = maxtime;
- /* Average reposting an ACK after 15 seconds */
- state->retry_max = (int)timeout/15;
+ /* Average reposting an ACK after 5 seconds */
+ state->retry_max = (int)timeout/5;
}
/* But bound the total number */
if(state->retry_max<3)
@@ -601,15 +592,10 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
/* Is this the block we expect? */
rblock = getrpacketblock(&state->rpacket);
if(NEXT_BLOCKNUM(state->block) != rblock) {
- /* No, log it, up the retry count and fail if over the limit */
+ /* No, log it */
infof(data,
- "Received unexpected DATA packet block %d\n", rblock);
- state->retries++;
- if(state->retries > state->retry_max) {
- failf(data, "tftp_rx: giving up waiting for block %d",
- NEXT_BLOCKNUM(state->block));
- return CURLE_TFTP_ILLEGAL;
- }
+ "Received unexpected DATA packet block %d, expecting block %d\n",
+ rblock, NEXT_BLOCKNUM(state->block));
break;
}
/* This is the expected block. Reset counters and ACK it. */
@@ -627,7 +613,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
}
/* Check if completed (That is, a less than full packet is received) */
- if(state->rbytes < (ssize_t)state->blksize+4){
+ if(state->rbytes < (ssize_t)state->blksize+4) {
state->state = TFTP_STATE_FIN;
}
else {
@@ -1344,7 +1330,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
result = tftp_state_machine(state, event);
if(result != CURLE_OK)
return(result);
- *done = (bool)(state->state == TFTP_STATE_FIN);
+ *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
if(*done)
/* Tell curl we're done */
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
@@ -1366,7 +1352,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
result = tftp_state_machine(state, state->event);
if(result != CURLE_OK)
return(result);
- *done = (bool)(state->state == TFTP_STATE_FIN);
+ *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
if(*done)
/* Tell curl we're done */
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
diff --git a/lib/transfer.c b/lib/transfer.c
index 94cd6d6f9..413a28082 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -22,31 +22,16 @@
#include "setup.h"
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <errno.h>
-
#include "strtoofft.h"
#include "strequal.h"
#include "rawstr.h"
-#ifdef WIN32
-#include <time.h>
-#include <io.h>
-#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -78,8 +63,6 @@
#error "We can't compile without socket() support!"
#endif
-#endif /* WIN32 */
-
#include "urldata.h"
#include <curl/curl.h>
#include "netrc.h"
@@ -95,7 +78,7 @@
#include "getinfo.h"
#include "sslgen.h"
#include "http_digest.h"
-#include "http_ntlm.h"
+#include "curl_ntlm.h"
#include "http_negotiate.h"
#include "share.h"
#include "curl_memory.h"
@@ -186,11 +169,12 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
const char *endofline_native;
const char *endofline_network;
int hexlen;
+
+ if(
#ifdef CURL_DO_LINEEND_CONV
- if((data->set.crlf) || (data->set.prefer_ascii)) {
-#else
- if(data->set.crlf) {
-#endif /* CURL_DO_LINEEND_CONV */
+ (data->set.prefer_ascii) ||
+#endif
+ (data->set.crlf)) {
/* \n will become \r\n later on */
endofline_native = "\n";
endofline_network = "\x0a";
@@ -302,7 +286,7 @@ CURLcode Curl_readrewind(struct connectdata *conn)
else {
/* If no CURLOPT_READFUNCTION is used, we know that we operate on a
given FILE * stream and we can actually attempt to rewind that
- ourself with fseek() */
+ ourselves with fseek() */
if(data->set.fread_func == (curl_read_callback)fread) {
if(-1 != fseek(data->set.in, 0, SEEK_SET))
/* successful rewind */
@@ -446,7 +430,7 @@ static CURLcode readwrite_data(struct SessionHandle *data,
*didwhat |= KEEP_RECV;
/* indicates data of zero size, i.e. empty file */
- is_empty_data = (bool)((nread == 0) && (k->bodywrites == 0));
+ is_empty_data = ((nread == 0) && (k->bodywrites == 0)) ? TRUE : FALSE;
/* NUL terminate, allowing string ops to be used */
if(0 < nread || is_empty_data) {
@@ -522,7 +506,6 @@ static CURLcode readwrite_data(struct SessionHandle *data,
is non-headers. */
if(k->str && !k->header && (nread > 0 || is_empty_data)) {
-
#ifndef CURL_DISABLE_HTTP
if(0 == k->bodywrites && !is_empty_data) {
/* These checks are only made the first time we are about to
@@ -570,9 +553,10 @@ static CURLcode readwrite_data(struct SessionHandle *data,
}
} /* we have a time condition */
- } /* this is HTTP */
+ } /* this is HTTP or RTSP */
} /* this is the first time we write a body part */
#endif /* CURL_DISABLE_HTTP */
+
k->bodywrites++;
/* pass data to the debug function before it gets "dechunked" */
@@ -606,7 +590,7 @@ static CURLcode readwrite_data(struct SessionHandle *data,
failf(data, "Failed writing data");
return CURLE_WRITE_ERROR;
}
- failf(data, "Received problem %d in the chunky parser", (int)res);
+ failf(data, "Problem (%d) in the Chunked-Encoded data", (int)res);
return CURLE_RECV_ERROR;
}
else if(CHUNKE_STOP == res) {
@@ -816,6 +800,9 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
/*
* We loop here to do the READ and SEND loop until we run out of
* data to send or until we get EWOULDBLOCK back
+ *
+ * FIXME: above comment is misleading. Currently no looping is
+ * actually done in do-while loop below.
*/
do {
@@ -892,13 +879,12 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
#endif /* CURL_DISABLE_SMTP */
/* convert LF to CRLF if so asked */
- if((!sending_http_headers) &&
+ if((!sending_http_headers) && (
#ifdef CURL_DO_LINEEND_CONV
- /* always convert if we're FTPing in ASCII mode */
- ((data->set.crlf) || (data->set.prefer_ascii))) {
-#else
- (data->set.crlf)) {
+ /* always convert if we're FTPing in ASCII mode */
+ (data->set.prefer_ascii) ||
#endif
+ (data->set.crlf))) {
if(data->state.scratch == NULL)
data->state.scratch = malloc(2*BUFSIZE);
if(data->state.scratch == NULL) {
@@ -988,7 +974,7 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
Curl_pgrsSetUploadCounter(data, k->writebytecount);
- } while(0); /* just to break out from! */
+ } WHILE_FALSE; /* just to break out from! */
return CURLE_OK;
}
@@ -1043,6 +1029,12 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if(result || *done)
return result;
}
+ else if(k->keepon & KEEP_RECV) {
+ DEBUGF(infof(data, "additional stuff not fine %s:%d: %d %d\n",
+ __FILE__, __LINE__,
+ select_res & CURL_CSELECT_IN,
+ conn->bits.stream_was_rewound));
+ }
/* If we still have writing to do, we check if we have a writable socket. */
if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) {
@@ -1136,7 +1128,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
(conn->chunk.state != CHUNK_STOP)) {
/*
* In chunked mode, return an error if the connection is closed prior to
- * the empty (terminiating) chunk is read.
+ * the empty (terminating) chunk is read.
*
* The condition above used to check for
* conn->proto.http->chunk.datasize != 0 which is true after reading
@@ -1151,8 +1143,8 @@ CURLcode Curl_readwrite(struct connectdata *conn,
}
/* Now update the "done" boolean we return */
- *done = (bool)(0 == (k->keepon&(KEEP_RECV|KEEP_SEND|
- KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)));
+ *done = (0 == (k->keepon&(KEEP_RECV|KEEP_SEND|
+ KEEP_RECV_PAUSE|KEEP_SEND_PAUSE))) ? TRUE : FALSE;
return CURLE_OK;
}
@@ -1213,11 +1205,11 @@ int Curl_single_getsock(const struct connectdata *conn,
/*
* Determine optimum sleep time based on configured rate, current rate,
* and packet size.
- * Returns value in mili-seconds.
+ * Returns value in milliseconds.
*
* The basic idea is to adjust the desired rate up/down in this method
* based on whether we are running too slow or too fast. Then, calculate
- * how many miliseconds to wait for the next packet to achieve this new
+ * how many milliseconds to wait for the next packet to achieve this new
* rate.
*/
long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
@@ -1243,7 +1235,7 @@ long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
rate_bps += rate_bps >> 6;
}
- /* Determine number of miliseconds to wait until we do
+ /* Determine number of milliseconds to wait until we do
* the next packet at the adjusted rate. We should wait
* longer when using larger packets, for instance.
*/
@@ -1448,8 +1440,10 @@ static CURLcode loadhostpairs(struct SessionHandle *data)
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
- if(!dns)
+ if(!dns) {
+ Curl_freeaddrinfo(addr);
return CURLE_OUT_OF_MEMORY;
+ }
}
}
data->change.resolve = NULL; /* dealt with now */
@@ -1613,7 +1607,7 @@ static bool is_absolute_url(const char *url)
char prot[16]; /* URL protocol string storage */
char letter; /* used for a silly sscanf */
- return (bool)(2 == sscanf(url, "%15[^?&/:]://%c", prot, &letter));
+ return (2 == sscanf(url, "%15[^?&/:]://%c", prot, &letter)) ? TRUE : FALSE;
}
/*
@@ -1705,26 +1699,37 @@ static char *concat_url(const char *base, const char *relurl)
}
}
else {
- /* We got a new absolute path for this server, cut off from the
- first slash */
- pathsep = strchr(protsep, '/');
- if(pathsep) {
- /* When people use badly formatted URLs, such as
- "http://www.url.com?dir=/home/daniel" we must not use the first
- slash, if there's a ?-letter before it! */
- char *sep = strchr(protsep, '?');
- if(sep && (sep < pathsep))
- pathsep = sep;
- *pathsep=0;
+ /* We got a new absolute path for this server */
+
+ if((relurl[0] == '/') && (relurl[1] == '/')) {
+ /* the new URL starts with //, just keep the protocol part from the
+ original one */
+ *protsep=0;
+ useurl = &relurl[2]; /* we keep the slashes from the original, so we
+ skip the new ones */
}
else {
- /* There was no slash. Now, since we might be operating on a badly
- formatted URL, such as "http://www.url.com?id=2380" which doesn't
- use a slash separator as it is supposed to, we need to check for a
- ?-letter as well! */
- pathsep = strchr(protsep, '?');
- if(pathsep)
+ /* cut off the original URL from the first slash, or deal with URLs
+ without slash */
+ pathsep = strchr(protsep, '/');
+ if(pathsep) {
+ /* When people use badly formatted URLs, such as
+ "http://www.url.com?dir=/home/daniel" we must not use the first
+ slash, if there's a ?-letter before it! */
+ char *sep = strchr(protsep, '?');
+ if(sep && (sep < pathsep))
+ pathsep = sep;
*pathsep=0;
+ }
+ else {
+ /* There was no slash. Now, since we might be operating on a badly
+ formatted URL, such as "http://www.url.com?id=2380" which doesn't
+ use a slash separator as it is supposed to, we need to check for a
+ ?-letter as well! */
+ pathsep = strchr(protsep, '?');
+ if(pathsep)
+ *pathsep=0;
+ }
}
}
@@ -1737,8 +1742,8 @@ static char *concat_url(const char *base, const char *relurl)
urllen = strlen(url_clone);
- newest = malloc( urllen + 1 + /* possible slash */
- newlen + 1 /* zero byte */);
+ newest = malloc(urllen + 1 + /* possible slash */
+ newlen + 1 /* zero byte */);
if(!newest) {
free(url_clone); /* don't leak this */
@@ -1801,15 +1806,14 @@ CURLcode Curl_follow(struct SessionHandle *data,
when we get the next URL. We pick the ->url field, which may or may
not be 100% correct */
- if(data->change.referer_alloc)
- /* If we already have an allocated referer, free this first */
- free(data->change.referer);
+ if(data->change.referer_alloc) {
+ Curl_safefree(data->change.referer);
+ data->change.referer_alloc = FALSE;
+ }
data->change.referer = strdup(data->change.url);
- if(!data->change.referer) {
- data->change.referer_alloc = FALSE;
+ if(!data->change.referer)
return CURLE_OUT_OF_MEMORY;
- }
data->change.referer_alloc = TRUE; /* yes, free this later */
}
}
@@ -1856,12 +1860,13 @@ CURLcode Curl_follow(struct SessionHandle *data,
if(disallowport)
data->state.allow_port = FALSE;
- if(data->change.url_alloc)
- free(data->change.url);
- else
- data->change.url_alloc = TRUE; /* the URL is allocated */
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
data->change.url = newurl;
+ data->change.url_alloc = TRUE;
newurl = NULL; /* don't free! */
infof(data, "Issue another request to this URL: '%s'\n", data->change.url);
@@ -1889,19 +1894,18 @@ CURLcode Curl_follow(struct SessionHandle *data,
case 301: /* Moved Permanently */
/* (quote from RFC2616, section 10.3.2):
*
- * Note: When automatically redirecting a POST request after receiving a
- * 301 status code, some existing HTTP/1.0 user agents will erroneously
- * change it into a GET request.
+ * When automatically redirecting a POST request after receiving a 301
+ * status code, some existing HTTP/1.0 user agents will erroneously change
+ * it into a GET request.
*
* ----
*
- * Warning: Because most of importants user agents do this obvious RFC2616
- * violation, many webservers expect this misbehavior. So these servers
- * often answers to a POST request with an error page. To be sure that
- * libcurl gets the page that most user agents would get, libcurl has to
- * force GET.
+ * As most of the important user agents do this obvious RFC2616 violation,
+ * many webservers expect this. So these servers often answers to a POST
+ * request with an error page. To be sure that libcurl gets the page that
+ * most user agents would get, libcurl has to force GET.
*
- * This behaviour can be overridden with CURLOPT_POSTREDIR.
+ * This behavior can be overridden with CURLOPT_POSTREDIR.
*/
if((data->set.httpreq == HTTPREQ_POST
|| data->set.httpreq == HTTPREQ_POST_FORM)
@@ -1929,7 +1933,7 @@ CURLcode Curl_follow(struct SessionHandle *data,
302 status code may be used instead, since most user agents react
to a 302 response as described here for 303.
- This behaviour can be overriden with CURLOPT_POSTREDIR
+ This behavior can be overridden with CURLOPT_POSTREDIR
*/
if((data->set.httpreq == HTTPREQ_POST
|| data->set.httpreq == HTTPREQ_POST_FORM)
@@ -2092,7 +2096,7 @@ CURLcode Curl_retry_request(struct connectdata *conn,
transferred! */
if(data->state.proto.http->writebytecount)
- Curl_readrewind(conn);
+ return Curl_readrewind(conn);
}
return CURLE_OK;
}
diff --git a/lib/url.c b/lib/url.c
index c5b642fde..40dcd1568 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -20,30 +20,14 @@
*
***************************************************************************/
-/* -- WIN32 approved -- */
-
#include "setup.h"
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <errno.h>
-
-#ifdef WIN32
-#include <time.h>
-#include <io.h>
-#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -73,8 +57,6 @@
#error "We can't compile without socket() support!"
#endif
-#endif /* WIN32 */
-
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
@@ -137,7 +119,8 @@ int curl_win32_idn_to_ascii(const char *in, char **out);
#include "url.h"
#include "connect.h"
#include "inet_ntop.h"
-#include "http_ntlm.h"
+#include "curl_ntlm.h"
+#include "curl_ntlm_wb.h"
#include "socks.h"
#include "curl_rtmp.h"
#include "gopher.h"
@@ -153,6 +136,7 @@ int curl_win32_idn_to_ascii(const char *in, char **out);
static long ConnectionKillOne(struct SessionHandle *data);
static void conn_free(struct connectdata *conn);
static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
+static CURLcode do_init(struct connectdata *conn);
/*
* Protocol table.
@@ -262,6 +246,7 @@ static const struct Curl_handler Curl_handler_dummy = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
@@ -270,12 +255,6 @@ static const struct Curl_handler Curl_handler_dummy = {
PROTOPT_NONE /* flags */
};
-void Curl_safefree(void *ptr)
-{
- if(ptr)
- free(ptr);
-}
-
static void close_connections(struct SessionHandle *data)
{
/* Loop through all open connections and kill them one by one */
@@ -298,10 +277,7 @@ static CURLcode setstropt(char **charp, char * s)
/* Release the previous storage at `charp' and replace by a dynamic storage
copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
- if(*charp) {
- free(*charp);
- *charp = (char *) NULL;
- }
+ Curl_safefree(*charp);
if(s) {
s = strdup(s);
@@ -480,6 +456,7 @@ CURLcode Curl_close(struct SessionHandle *data)
/* free the connection cache if allocated privately */
Curl_rm_connc(data->state.connc);
+ data->state.connc = NULL;
}
}
@@ -501,6 +478,8 @@ CURLcode Curl_close(struct SessionHandle *data)
/* Free the pathbuffer */
Curl_safefree(data->state.pathbuffer);
+ data->state.path = NULL;
+
Curl_safefree(data->state.proto.generic);
/* Close down all open SSL info and sessions */
@@ -509,11 +488,17 @@ CURLcode Curl_close(struct SessionHandle *data)
Curl_safefree(data->state.scratch);
Curl_ssl_free_certinfo(data);
- if(data->change.referer_alloc)
- free(data->change.referer);
+ if(data->change.referer_alloc) {
+ Curl_safefree(data->change.referer);
+ data->change.referer_alloc = FALSE;
+ }
+ data->change.referer = NULL;
- if(data->change.url_alloc)
- free(data->change.url);
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+ data->change.url = NULL;
Curl_safefree(data->state.headerbuff);
@@ -640,13 +625,19 @@ CURLcode Curl_ch_connc(struct SessionHandle *data,
curl_multi_cleanup(). */
void Curl_rm_connc(struct conncache *c)
{
+ if(!c)
+ return;
+
if(c->connects) {
long i;
- for(i = 0; i < c->num; ++i)
+ for(i = 0; i < c->num; ++i) {
conn_free(c->connects[i]);
-
+ c->connects[i] = NULL;
+ }
free(c->connects);
+ c->connects = NULL;
}
+ c->num = 0;
free(c);
}
@@ -844,7 +835,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
{
/* remember we want this enabled */
long use_cache = va_arg(param, long);
- data->set.global_dns_cache = (bool)(0 != use_cache);
+ data->set.global_dns_cache = (0 != use_cache)?TRUE:FALSE;
}
break;
case CURLOPT_SSL_CIPHER_LIST:
@@ -880,33 +871,33 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* When this transfer is done, it must not be left to be reused by a
* subsequent transfer but shall be closed immediately.
*/
- data->set.reuse_forbid = (bool)(0 != va_arg(param, long));
+ data->set.reuse_forbid = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_FRESH_CONNECT:
/*
* This transfer shall not use a previously cached connection but
* should be made with a fresh new connect!
*/
- data->set.reuse_fresh = (bool)(0 != va_arg(param, long));
+ data->set.reuse_fresh = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_VERBOSE:
/*
* Verbose means infof() calls that give a lot of information about
* the connection and transfer procedures as well as internal choices.
*/
- data->set.verbose = (bool)(0 != va_arg(param, long));
+ data->set.verbose = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_HEADER:
/*
* Set to include the header in the general data output stream.
*/
- data->set.include_header = (bool)(0 != va_arg(param, long));
+ data->set.include_header = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_NOPROGRESS:
/*
* Shut off the internal supported progress meter
*/
- data->set.hide_progress = (bool)(0 != va_arg(param, long));
+ data->set.hide_progress = (0 != va_arg(param, long))?TRUE:FALSE;
if(data->set.hide_progress)
data->progress.flags |= PGRS_HIDE;
else
@@ -916,14 +907,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* Do not include the body part in the output data stream.
*/
- data->set.opt_no_body = (bool)(0 != va_arg(param, long));
+ data->set.opt_no_body = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_FAILONERROR:
/*
* Don't output the >=300 error code HTML-page, but instead only
* return error.
*/
- data->set.http_fail_on_error = (bool)(0 != va_arg(param, long));
+ data->set.http_fail_on_error = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_UPLOAD:
case CURLOPT_PUT:
@@ -931,7 +922,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* We want to sent data to the remote host. If this is HTTP, that equals
* using the PUT request.
*/
- data->set.upload = (bool)(0 != va_arg(param, long));
+ data->set.upload = (0 != va_arg(param, long))?TRUE:FALSE;
if(data->set.upload) {
/* If this is HTTP, PUT is what's needed to "upload" */
data->set.httpreq = HTTPREQ_PUT;
@@ -947,7 +938,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* Try to get the file time of the remote document. The time will
* later (possibly) become available using curl_easy_getinfo().
*/
- data->set.get_filetime = (bool)(0 != va_arg(param, long));
+ data->set.get_filetime = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_FTP_CREATE_MISSING_DIRS:
/*
@@ -988,13 +979,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* An option that changes the command to one that asks for a list
* only, no file info details.
*/
- data->set.ftp_list_only = (bool)(0 != va_arg(param, long));
+ data->set.ftp_list_only = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_APPEND:
/*
* We want to upload and append to an existing file.
*/
- data->set.ftp_append = (bool)(0 != va_arg(param, long));
+ data->set.ftp_append = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_FTP_FILEMETHOD:
/*
@@ -1022,7 +1013,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
*
* Transfer using ASCII (instead of BINARY).
*/
- data->set.prefer_ascii = (bool)(0 != va_arg(param, long));
+ data->set.prefer_ascii = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_TIMECONDITION:
/*
@@ -1051,7 +1042,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* Switch on automatic referer that gets set if curl follows locations.
*/
- data->set.http_auto_referer = (bool)(0 != va_arg(param, long));
+ data->set.http_auto_referer = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_ACCEPT_ENCODING:
@@ -1071,14 +1062,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
break;
case CURLOPT_TRANSFER_ENCODING:
- data->set.http_transfer_encoding = (bool)(0 != va_arg(param, long));
+ data->set.http_transfer_encoding = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_FOLLOWLOCATION:
/*
* Follow Location: header hints on a HTTP-server.
*/
- data->set.http_follow_location = (bool)(0 != va_arg(param, long));
+ data->set.http_follow_location = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_UNRESTRICTED_AUTH:
@@ -1087,7 +1078,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* hostname changed.
*/
data->set.http_disable_hostname_check_before_authentication =
- (bool)(0 != va_arg(param, long));
+ (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_MAXREDIRS:
@@ -1109,8 +1100,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* other - POST is kept as POST after 301 and 302
*/
long postRedir = va_arg(param, long);
- data->set.post301 = (bool)((postRedir & CURL_REDIR_POST_301)?TRUE:FALSE);
- data->set.post302 = (bool)((postRedir & CURL_REDIR_POST_302)?TRUE:FALSE);
+ data->set.post301 = (postRedir & CURL_REDIR_POST_301)?TRUE:FALSE;
+ data->set.post302 = (postRedir & CURL_REDIR_POST_302)?TRUE:FALSE;
}
break;
@@ -1231,7 +1222,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* String to set in the HTTP Referer: field.
*/
if(data->change.referer_alloc) {
- free(data->change.referer);
+ Curl_safefree(data->change.referer);
data->change.referer_alloc = FALSE;
}
result = setstropt(&data->set.str[STRING_SET_REFERER],
@@ -1280,10 +1271,11 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/* append the cookie file name to the list of file names, and deal with
them later */
cl = curl_slist_append(data->change.cookielist, argptr);
-
- if(!cl)
+ if(!cl) {
+ curl_slist_free_all(data->change.cookielist);
+ data->change.cookielist = NULL;
return CURLE_OUT_OF_MEMORY;
-
+ }
data->change.cookielist = cl; /* store the list for later use */
}
break;
@@ -1319,7 +1311,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* We run mostly with the original cookie spec, as hardly anyone implements
* anything else.
*/
- data->set.cookiesession = (bool)(0 != va_arg(param, long));
+ data->set.cookiesession = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_COOKIELIST:
@@ -1394,8 +1386,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/* the DIGEST_IE bit is only used to set a special marker, for all the
rest we need to handle it as normal DIGEST */
- data->state.authhost.iestyle = (bool)((auth & CURLAUTH_DIGEST_IE)?
- TRUE:FALSE);
+ data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE)?TRUE:FALSE;
if(auth & CURLAUTH_DIGEST_IE) {
auth |= CURLAUTH_DIGEST; /* set standard digest bit */
@@ -1404,7 +1395,10 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/* switch off bits we can't support */
#ifndef USE_NTLM
- auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
+ auth &= ~CURLAUTH_NTLM; /* no NTLM support */
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#elif !defined(NTLM_WB_ENABLED)
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
#endif
#ifndef USE_HTTP_NEGOTIATE
auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI or
@@ -1437,7 +1431,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* Tunnel operations through the proxy instead of normal proxy use
*/
- data->set.tunnel_thru_httpproxy = (bool)(0 != va_arg(param, long));
+ data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_PROXYPORT:
@@ -1456,8 +1450,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/* the DIGEST_IE bit is only used to set a special marker, for all the
rest we need to handle it as normal DIGEST */
- data->state.authproxy.iestyle = (bool)((auth & CURLAUTH_DIGEST_IE)?
- TRUE:FALSE);
+ data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE)?TRUE:FALSE;
if(auth & CURLAUTH_DIGEST_IE) {
auth |= CURLAUTH_DIGEST; /* set standard digest bit */
@@ -1465,7 +1458,10 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
}
/* switch off bits we can't support */
#ifndef USE_NTLM
- auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
+ auth &= ~CURLAUTH_NTLM; /* no NTLM support */
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#elif !defined(NTLM_WB_ENABLED)
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
#endif
#ifndef USE_HTTP_NEGOTIATE
auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI or
@@ -1531,7 +1527,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* set flag for nec socks5 support
*/
- data->set.socks5_gssapi_nec = (bool)(0 != va_arg(param, long));
+ data->set.socks5_gssapi_nec = (0 != va_arg(param, long))?TRUE:FALSE;
break;
#endif
@@ -1560,19 +1556,20 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
*/
result = setstropt(&data->set.str[STRING_FTPPORT],
va_arg(param, char *));
- data->set.ftp_use_port = (bool)(NULL != data->set.str[STRING_FTPPORT]);
+ data->set.ftp_use_port = (NULL != data->set.str[STRING_FTPPORT]) ?
+ TRUE:FALSE;
break;
case CURLOPT_FTP_USE_EPRT:
- data->set.ftp_use_eprt = (bool)(0 != va_arg(param, long));
+ data->set.ftp_use_eprt = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_FTP_USE_EPSV:
- data->set.ftp_use_epsv = (bool)(0 != va_arg(param, long));
+ data->set.ftp_use_epsv = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_FTP_USE_PRET:
- data->set.ftp_use_pret = (bool)(0 != va_arg(param, long));
+ data->set.ftp_use_pret = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_FTP_SSL_CCC:
@@ -1584,7 +1581,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
* bypass of the IP address in PASV responses.
*/
- data->set.ftp_skip_ip = (bool)(0 != va_arg(param, long));
+ data->set.ftp_skip_ip = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_INFILE:
@@ -1642,8 +1639,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
*/
if(data->change.url_alloc) {
/* the already set URL is allocated, free it first! */
- free(data->change.url);
- data->change.url_alloc=FALSE;
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
}
result = setstropt(&data->set.str[STRING_SET_URL],
va_arg(param, char *));
@@ -1954,7 +1951,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* Kludgy option to enable CRLF conversions. Subject for removal.
*/
- data->set.crlf = (bool)(0 != va_arg(param, long));
+ data->set.crlf = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_INTERFACE:
@@ -1983,7 +1980,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
*/
result = setstropt(&data->set.str[STRING_KRB_LEVEL],
va_arg(param, char *));
- data->set.krb = (bool)(NULL != data->set.str[STRING_KRB_LEVEL]);
+ data->set.krb = (NULL != data->set.str[STRING_KRB_LEVEL])?TRUE:FALSE;
+ break;
+ case CURLOPT_GSSAPI_DELEGATION:
+ /*
+ * GSSAPI credential delegation
+ */
+ data->set.gssapi_delegation = va_arg(param, long);
break;
case CURLOPT_SSL_VERIFYPEER:
/*
@@ -2015,7 +2018,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->set.ssl.fsslctxp = va_arg(param, void *);
break;
case CURLOPT_CERTINFO:
- data->set.ssl.certinfo = (bool)(0 != va_arg(param, long));
+ data->set.ssl.certinfo = (0 != va_arg(param, long))?TRUE:FALSE;
break;
#endif
case CURLOPT_CAINFO:
@@ -2075,7 +2078,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* The application asks not to set any signal() or alarm() handlers,
* even when using a timeout.
*/
- data->set.no_signal = (bool)(0 != va_arg(param, long));
+ data->set.no_signal = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_SHARE:
@@ -2092,8 +2095,15 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->dns.hostcachetype = HCACHE_NONE;
}
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
if(data->share->cookies == data->cookies)
data->cookies = NULL;
+#endif
+
+ if(data->share->sslsession == data->state.session) {
+ data->state.session = NULL;
+ data->set.ssl.numsessions = 0;
+ }
data->share->dirty--;
@@ -2126,6 +2136,10 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->cookies = data->share->cookies;
}
#endif /* CURL_DISABLE_HTTP */
+ if(data->share->sslsession) {
+ data->set.ssl.numsessions = data->share->nsslsession;
+ data->state.session = data->share->sslsession;
+ }
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
}
@@ -2179,7 +2193,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* Enable or disable TCP_NODELAY, which will disable/enable the Nagle
* algorithm
*/
- data->set.tcp_nodelay = (bool)(0 != va_arg(param, long));
+ data->set.tcp_nodelay = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_FTP_ACCOUNT:
@@ -2188,14 +2202,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
break;
case CURLOPT_IGNORE_CONTENT_LENGTH:
- data->set.ignorecl = (bool)(0 != va_arg(param, long));
+ data->set.ignorecl = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_CONNECT_ONLY:
/*
* No data transfer, set up connection and let application use the socket
*/
- data->set.connect_only = (bool)(0 != va_arg(param, long));
+ data->set.connect_only = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_FTP_ALTERNATIVE_TO_USER:
@@ -2248,7 +2262,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
break;
case CURLOPT_SSL_SESSIONID_CACHE:
- data->set.ssl.sessionid = (bool)(0 != va_arg(param, long));
+ data->set.ssl.sessionid = (0 != va_arg(param, long))?TRUE:FALSE;
break;
#ifdef USE_LIBSSH2
@@ -2309,14 +2323,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* disable libcurl transfer encoding is used
*/
- data->set.http_te_skip = (bool)(0 == va_arg(param, long));
+ data->set.http_te_skip = (0 == va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_HTTP_CONTENT_DECODING:
/*
* raw data passed to the application when content encoding is used
*/
- data->set.http_ce_skip = (bool)(0 == va_arg(param, long));
+ data->set.http_ce_skip = (0 == va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_NEW_FILE_PERMS:
@@ -2478,7 +2492,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
break;
case CURLOPT_WILDCARDMATCH:
- data->set.wildcardmatch = (bool)(0 != va_arg(param, long));
+ data->set.wildcardmatch = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_CHUNK_BGN_FUNCTION:
data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
@@ -2543,6 +2557,10 @@ static void conn_free(struct connectdata *conn)
if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+ Curl_ntlm_wb_cleanup(conn);
+#endif
+
Curl_safefree(conn->user);
Curl_safefree(conn->passwd);
Curl_safefree(conn->proxyuser);
@@ -2567,6 +2585,11 @@ static void conn_free(struct connectdata *conn)
Curl_llist_destroy(conn->pend_pipe, NULL);
Curl_llist_destroy(conn->done_pipe, NULL);
+ conn->send_pipe = NULL;
+ conn->recv_pipe = NULL;
+ conn->pend_pipe = NULL;
+ conn->done_pipe = NULL;
+
Curl_safefree(conn->localdev);
Curl_free_ssl_config(&conn->ssl_config);
@@ -2621,7 +2644,7 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
if(has_host_ntlm || has_proxy_ntlm) {
data->state.authproblem = FALSE;
- Curl_ntlm_cleanup(conn);
+ Curl_http_ntlm_cleanup(conn);
}
}
@@ -2773,11 +2796,11 @@ static struct SessionHandle* gethandleathead(struct curl_llist *pipeline)
void Curl_getoff_all_pipelines(struct SessionHandle *data,
struct connectdata *conn)
{
- bool recv_head = (bool)(conn->readchannel_inuse &&
- (gethandleathead(conn->recv_pipe) == data));
+ bool recv_head = (conn->readchannel_inuse &&
+ (gethandleathead(conn->recv_pipe) == data)) ? TRUE : FALSE;
- bool send_head = (bool)(conn->writechannel_inuse &&
- (gethandleathead(conn->send_pipe) == data));
+ bool send_head = (conn->writechannel_inuse &&
+ (gethandleathead(conn->send_pipe) == data)) ? TRUE : FALSE;
if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head)
conn->readchannel_inuse = FALSE;
@@ -3002,7 +3025,8 @@ ConnectionExists(struct SessionHandle *data,
}
if((needle->handler->protocol & CURLPROTO_FTP) ||
((needle->handler->protocol & CURLPROTO_HTTP) &&
- (data->state.authhost.want==CURLAUTH_NTLM))) {
+ ((data->state.authhost.want==CURLAUTH_NTLM) ||
+ (data->state.authhost.want==CURLAUTH_NTLM_WB)))) {
/* This is FTP or HTTP+NTLM, verify that we're using the same name
and password as well */
if(!strequal(needle->user, check->user) ||
@@ -3203,8 +3227,13 @@ static CURLcode ConnectPlease(struct SessionHandle *data,
/* All is cool, we store the current information */
conn->ip_addr = addr;
- if(*connected)
+ if(*connected) {
result = Curl_connected_proxy(conn);
+ if(!result) {
+ conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
+ Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
+ }
+ }
}
if(result)
@@ -3297,7 +3326,7 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
*protocol_done = FALSE;
- if(conn->bits.tcpconnect && conn->bits.protoconnstart) {
+ if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
/* We already are connected, get back. This may happen when the connect
worked fine in the first call, like when we connect to a local server
or proxy. Note that we don't know if the protocol is actually done.
@@ -3310,7 +3339,7 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
return CURLE_OK;
}
- if(!conn->bits.tcpconnect) {
+ if(!conn->bits.tcpconnect[FIRSTSOCKET]) {
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
Curl_verboseconnect(conn);
@@ -3504,18 +3533,20 @@ static struct connectdata *allocate_conn(struct SessionHandle *data)
#else /* CURL_DISABLE_PROXY */
- conn->bits.proxy = (bool)(data->set.str[STRING_PROXY] &&
- *data->set.str[STRING_PROXY]);
- conn->bits.httpproxy = (bool)(conn->bits.proxy &&
- (conn->proxytype == CURLPROXY_HTTP ||
- conn->proxytype == CURLPROXY_HTTP_1_0));
+ /* note that these two proxy bits are now just on what looks to be
+ requested, they may be altered down the road */
+ conn->bits.proxy = (data->set.str[STRING_PROXY] &&
+ *data->set.str[STRING_PROXY])?TRUE:FALSE;
+ conn->bits.httpproxy = (conn->bits.proxy &&
+ (conn->proxytype == CURLPROXY_HTTP ||
+ conn->proxytype == CURLPROXY_HTTP_1_0))?TRUE:FALSE;
conn->bits.proxy_user_passwd =
- (bool)(NULL != data->set.str[STRING_PROXYUSERNAME]);
+ (NULL != data->set.str[STRING_PROXYUSERNAME])?TRUE:FALSE;
conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
#endif /* CURL_DISABLE_PROXY */
- conn->bits.user_passwd = (bool)(NULL != data->set.str[STRING_USERNAME]);
+ conn->bits.user_passwd = (NULL != data->set.str[STRING_USERNAME])?TRUE:FALSE;
conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
@@ -3524,6 +3555,13 @@ static struct connectdata *allocate_conn(struct SessionHandle *data)
conn->ip_version = data->set.ipver;
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+ conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
+ conn->ntlm_auth_hlpr_pid = 0;
+ conn->challenge_header = NULL;
+ conn->response_header = NULL;
+#endif
+
if(data->multi && Curl_multi_canPipeline(data->multi) &&
!conn->master_buffer) {
/* Allocate master_buffer to be used for pipelining */
@@ -3566,6 +3604,12 @@ static struct connectdata *allocate_conn(struct SessionHandle *data)
Curl_llist_destroy(conn->recv_pipe, NULL);
Curl_llist_destroy(conn->pend_pipe, NULL);
Curl_llist_destroy(conn->done_pipe, NULL);
+
+ conn->send_pipe = NULL;
+ conn->recv_pipe = NULL;
+ conn->pend_pipe = NULL;
+ conn->done_pipe = NULL;
+
Curl_safefree(conn->master_buffer);
Curl_safefree(conn->localdev);
Curl_safefree(conn);
@@ -3852,7 +3896,7 @@ static CURLcode setup_range(struct SessionHandle *data)
else
s->range = strdup(data->set.str[STRING_SET_RANGE]);
- s->rangestringalloc = (bool)(s->range?TRUE:FALSE);
+ s->rangestringalloc = (s->range)?TRUE:FALSE;
if(!s->range)
return CURLE_OUT_OF_MEMORY;
@@ -4392,8 +4436,10 @@ static CURLcode parse_remote_port(struct SessionHandle *data,
if(!url)
return CURLE_OUT_OF_MEMORY;
- if(data->change.url_alloc)
- free(data->change.url);
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
data->change.url = url;
data->change.url_alloc = TRUE;
@@ -4617,11 +4663,12 @@ static void reuse_conn(struct connectdata *old_conn,
/* host can change, when doing keepalive with a proxy ! */
if(conn->bits.proxy) {
- free(conn->host.rawalloc);
+ Curl_safefree(conn->host.rawalloc);
conn->host=old_conn->host;
}
else
- free(old_conn->host.rawalloc); /* free the newly allocated name buffer */
+ /* free the newly allocated name buffer */
+ Curl_safefree(old_conn->host.rawalloc);
/* persist connection info in session handle */
Curl_persistconninfo(conn);
@@ -4633,10 +4680,17 @@ static void reuse_conn(struct connectdata *old_conn,
Curl_safefree(old_conn->passwd);
Curl_safefree(old_conn->proxyuser);
Curl_safefree(old_conn->proxypasswd);
+
Curl_llist_destroy(old_conn->send_pipe, NULL);
Curl_llist_destroy(old_conn->recv_pipe, NULL);
Curl_llist_destroy(old_conn->pend_pipe, NULL);
Curl_llist_destroy(old_conn->done_pipe, NULL);
+
+ old_conn->send_pipe = NULL;
+ old_conn->recv_pipe = NULL;
+ old_conn->pend_pipe = NULL;
+ old_conn->done_pipe = NULL;
+
Curl_safefree(old_conn->master_buffer);
}
@@ -4713,14 +4767,19 @@ static CURLcode create_conn(struct SessionHandle *data,
*/
Curl_safefree(data->state.pathbuffer);
+ data->state.path = NULL;
+
data->state.pathbuffer = malloc(urllen+2);
if(NULL == data->state.pathbuffer)
return CURLE_OUT_OF_MEMORY; /* really bad error */
data->state.path = data->state.pathbuffer;
conn->host.rawalloc = malloc(urllen+2);
- if(NULL == conn->host.rawalloc)
+ if(NULL == conn->host.rawalloc) {
+ Curl_safefree(data->state.pathbuffer);
+ data->state.path = NULL;
return CURLE_OUT_OF_MEMORY;
+ }
conn->host.name = conn->host.rawalloc;
conn->host.name[0] = 0;
@@ -4745,6 +4804,11 @@ static CURLcode create_conn(struct SessionHandle *data,
return CURLE_OUT_OF_MEMORY;
}
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+
data->change.url = reurl;
data->change.url_alloc = TRUE; /* free this later */
}
@@ -4821,6 +4885,8 @@ static CURLcode create_conn(struct SessionHandle *data,
conn->bits.httpproxy = TRUE;
#endif
}
+ else
+ conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
conn->bits.proxy = TRUE;
}
else {
@@ -4862,7 +4928,7 @@ static CURLcode create_conn(struct SessionHandle *data,
/* Setup a "faked" transfer that'll do nothing */
if(CURLE_OK == result) {
conn->data = data;
- conn->bits.tcpconnect = TRUE; /* we are "connected */
+ conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
ConnectionStore(data, conn);
@@ -4970,6 +5036,9 @@ static CURLcode create_conn(struct SessionHandle *data,
ConnectionStore(data, conn);
}
+ /* Setup and init stuff before DO starts, in preparing for the transfer. */
+ do_init(conn);
+
/*
* Setup whatever necessary for a resumed transfer
*/
@@ -5007,7 +5076,7 @@ static CURLcode create_conn(struct SessionHandle *data,
CURLcode Curl_setup_conn(struct connectdata *conn,
bool *protocol_done)
{
- CURLcode result=CURLE_OK;
+ CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
Curl_pgrsTime(data, TIMER_NAMELOOKUP);
@@ -5053,13 +5122,19 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
result = ConnectPlease(data, conn, &connected);
+ if(result && !conn->ip_addr) {
+ /* transport connection failure not related with authentication */
+ conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
+ return result;
+ }
+
if(connected) {
result = Curl_protocol_connect(conn, protocol_done);
if(CURLE_OK == result)
- conn->bits.tcpconnect = TRUE;
+ conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
}
else
- conn->bits.tcpconnect = FALSE;
+ conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
/* if the connection was closed by the server while exchanging
authentication informations, retry with the new set
@@ -5078,7 +5153,7 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
else {
Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
- conn->bits.tcpconnect = TRUE;
+ conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
*protocol_done = TRUE;
Curl_verboseconnect(conn);
Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
@@ -5316,9 +5391,6 @@ CURLcode Curl_do(struct connectdata **connp, bool *done)
struct connectdata *conn = *connp;
struct SessionHandle *data = conn->data;
- /* setup and init stuff before DO starts, in preparing for the transfer */
- do_init(conn);
-
if(conn->handler->do_it) {
/* generic protocol-specific function pointer set in curl_connect() */
result = conn->handler->do_it(conn, done);
diff --git a/lib/url.h b/lib/url.h
index 8a5434cef..8947627d5 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -1,5 +1,5 @@
-#ifndef __URL_H
-#define __URL_H
+#ifndef HEADER_CURL_URL_H
+#define HEADER_CURL_URL_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -21,8 +21,7 @@
* KIND, either express or implied.
*
***************************************************************************/
-
-#include <stdarg.h> /* to make sure we have ap_list */
+#include "setup.h"
/*
* Prototypes for library-wide functions provided by url.c
@@ -44,7 +43,6 @@ 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);
CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done);
-void Curl_safefree(void *ptr);
CURLcode Curl_setup_conn(struct connectdata *conn,
bool *protocol_done);
@@ -88,10 +86,10 @@ void Curl_reset_reqproto(struct connectdata *conn);
CURLcode Curl_connected_proxy(struct connectdata *conn);
#ifdef CURL_DISABLE_VERBOSE_STRINGS
-#define Curl_verboseconnect(x) do { } while (0)
+#define Curl_verboseconnect(x) Curl_nop_stmt
#else
void Curl_verboseconnect(struct connectdata *conn);
#endif
-#endif
+#endif /* HEADER_CURL_URL_H */
diff --git a/lib/urldata.h b/lib/urldata.h
index d256968db..5b3dc059e 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -273,6 +273,7 @@ struct ssl_connect_data {
struct SessionHandle *data;
#ifdef HAVE_PK11_CREATEGENERICOBJECT
struct curl_llist *obj_list;
+ PK11GenericObject *obj_clicert;
#endif
#endif /* USE_NSS */
#ifdef USE_QSOSSL
@@ -360,7 +361,7 @@ struct ntlmdata {
SEC_WINNT_AUTH_IDENTITY *p_identity;
int has_handles;
void *type_2;
- int n_type_2;
+ unsigned long n_type_2;
#else
unsigned int flags;
unsigned char nonce[8];
@@ -411,7 +412,7 @@ struct ConnectBits {
bool do_more; /* this is set TRUE if the ->curl_do_more() function is
supposed to be called, after ->curl_do() */
- bool tcpconnect; /* the TCP layer (or similar) is connected, this is set
+ bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set
the first time on the first connect function call */
bool protoconnstart;/* the protocol layer has STARTED its operation after
the TCP layer connect */
@@ -670,6 +671,12 @@ struct Curl_handler {
curl_socket_t *socks,
int numsocks);
+ /* Called from the multi interface during the DO_MORE phase, and it should
+ then return a proper fd set */
+ int (*domore_getsock)(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
/* Called from the multi interface during the DO_DONE, PERFORM and
WAITPERFORM phases, and it should then return a proper fd set. Not setting
this will make libcurl use the generic default one. */
@@ -905,6 +912,14 @@ struct connectdata {
single requests! */
struct ntlmdata proxyntlm; /* NTLM data for proxy */
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+ /* used for communication with Samba's winbind daemon helper ntlm_auth */
+ curl_socket_t ntlm_auth_hlpr_socket;
+ pid_t ntlm_auth_hlpr_pid;
+ char* challenge_header;
+ char* response_header;
+#endif
+
char syserr_buf [256]; /* buffer for Curl_strerror() */
#ifdef CURLRES_ASYNCH
@@ -1517,6 +1532,9 @@ struct UserDefined {
curl_fnmatch_callback fnmatch; /* callback to decide which file corresponds
to pattern (e.g. if WILDCARDMATCH is on) */
void *fnmatch_data;
+
+ long gssapi_delegation; /* GSSAPI credential delegation, see the
+ documentation of CURLOPT_GSSAPI_DELEGATION */
};
struct Names {
diff --git a/lib/version.c b/lib/version.c
index c471dc106..c56ad3962 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -22,9 +22,6 @@
#include "setup.h"
-#include <string.h>
-#include <stdio.h>
-
#include <curl/curl.h>
#include "urldata.h"
#include "sslgen.h"
@@ -243,6 +240,9 @@ static curl_version_info_data version_info = {
#ifdef USE_NTLM
| CURL_VERSION_NTLM
#endif
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+ | CURL_VERSION_NTLM_WB
+#endif
#ifdef USE_WINDOWS_SSPI
| CURL_VERSION_SSPI
#endif
diff --git a/lib/warnless.c b/lib/warnless.c
index 37d15ce87..0f5fb5f4d 100644
--- a/lib/warnless.c
+++ b/lib/warnless.c
@@ -268,6 +268,25 @@ size_t curlx_sotouz(curl_off_t sonum)
#endif
}
+/*
+** signed int to unsigned size_t
+*/
+
+size_t curlx_sitouz(int sinum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(sinum >= 0);
+ return (size_t) sinum;
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
#if defined(__INTEL_COMPILER) && defined(__unix__)
int curlx_FD_ISSET(int fd, fd_set *fdset)
diff --git a/lib/warnless.h b/lib/warnless.h
index 9ac59ac29..27cf57c31 100644
--- a/lib/warnless.h
+++ b/lib/warnless.h
@@ -38,6 +38,8 @@ ssize_t curlx_uztosz(size_t uznum);
size_t curlx_sotouz(curl_off_t sonum);
+size_t curlx_sitouz(int sinum);
+
#if defined(__INTEL_COMPILER) && defined(__unix__)
int curlx_FD_ISSET(int fd, fd_set *fdset);
diff --git a/lib/wildcard.c b/lib/wildcard.c
index 9fe5d5135..6f4c7380c 100644
--- a/lib/wildcard.c
+++ b/lib/wildcard.c
@@ -21,6 +21,7 @@
***************************************************************************/
#include "setup.h"
+
#include "wildcard.h"
#include "llist.h"
#include "fileinfo.h"