Compare commits
219 Commits
curl-7_37_
...
curl-7_38_
Author | SHA1 | Date | |
---|---|---|---|
![]() |
202aa9f775 | ||
![]() |
9636fc2588 | ||
![]() |
a76825a5ef | ||
![]() |
8a75dbeb23 | ||
![]() |
1ccfabb66d | ||
![]() |
40bcd5447c | ||
![]() |
4455f1f599 | ||
![]() |
9e6c3638e6 | ||
![]() |
fa50d9d96d | ||
![]() |
38ced24ad1 | ||
![]() |
921a0c22a6 | ||
![]() |
af45542cfe | ||
![]() |
55f8b03948 | ||
![]() |
55d6cba5e1 | ||
![]() |
3963adca3d | ||
![]() |
6beb0eeea1 | ||
![]() |
8acbb074f8 | ||
![]() |
be83356e5e | ||
![]() |
797d56cbd8 | ||
![]() |
9ee502ac6b | ||
![]() |
ed285ae5c9 | ||
![]() |
436a841354 | ||
![]() |
4a6fa4c204 | ||
![]() |
c25cd9094b | ||
![]() |
21db158722 | ||
![]() |
e40197315d | ||
![]() |
fd1ce3856a | ||
![]() |
c6ee182bd4 | ||
![]() |
4989695ec3 | ||
![]() |
0b48d1c821 | ||
![]() |
9e50d8f8bc | ||
![]() |
a6c48c8be7 | ||
![]() |
3c8c873252 | ||
![]() |
4901ec2324 | ||
![]() |
e608324f9f | ||
![]() |
0c14b31df4 | ||
![]() |
0426670f0a | ||
![]() |
cacdc27f52 | ||
![]() |
09b5a99816 | ||
![]() |
4c134bcfce | ||
![]() |
2434a4e88d | ||
![]() |
c9a981778d | ||
![]() |
367b784738 | ||
![]() |
7bff23b166 | ||
![]() |
accbbd7dc3 | ||
![]() |
889de6b285 | ||
![]() |
1d30f40950 | ||
![]() |
1cd5008bba | ||
![]() |
da933ee29d | ||
![]() |
d4a4a42cb3 | ||
![]() |
11bb05ba48 | ||
![]() |
0072422576 | ||
![]() |
dfd821c738 | ||
![]() |
ee40b6882d | ||
![]() |
36a7638073 | ||
![]() |
2603618831 | ||
![]() |
b17b4b4a4a | ||
![]() |
f646e9075f | ||
![]() |
ba8795083f | ||
![]() |
06de7d6936 | ||
![]() |
febcfab23d | ||
![]() |
1269df2e3b | ||
![]() |
dda86f386d | ||
![]() |
7320e53d9e | ||
![]() |
118977f19d | ||
![]() |
88c17d5587 | ||
![]() |
73a1a639a7 | ||
![]() |
8f4da2965e | ||
![]() |
14aa8f0c11 | ||
![]() |
898808fa8c | ||
![]() |
a20da5523e | ||
![]() |
5be48639b1 | ||
![]() |
1a073a20db | ||
![]() |
63a0bd4270 | ||
![]() |
98633c2a19 | ||
![]() |
bdfc75e751 | ||
![]() |
da23624b57 | ||
![]() |
30f2d0c0b3 | ||
![]() |
f854130b7b | ||
![]() |
2f2d84033b | ||
![]() |
b1341b3068 | ||
![]() |
23d52ca4a7 | ||
![]() |
437b9ba46f | ||
![]() |
f6e15d25a3 | ||
![]() |
75be5a6681 | ||
![]() |
c4410c85ab | ||
![]() |
97f6049bc2 | ||
![]() |
29240cb5c1 | ||
![]() |
7679cb3fa8 | ||
![]() |
0574196acb | ||
![]() |
14b3a2e4c3 | ||
![]() |
5663272435 | ||
![]() |
03f368d94c | ||
![]() |
96034c4a51 | ||
![]() |
078d1fbf2b | ||
![]() |
9eba83c156 | ||
![]() |
0187c9e11d | ||
![]() |
472d1d8e05 | ||
![]() |
629f52843f | ||
![]() |
c126bac153 | ||
![]() |
cff0757c31 | ||
![]() |
b5c56190b2 | ||
![]() |
4b491c675f | ||
![]() |
3ec253532e | ||
![]() |
215f932e49 | ||
![]() |
076c0ab683 | ||
![]() |
57b53918d1 | ||
![]() |
fc5a5a4f07 | ||
![]() |
01368d395c | ||
![]() |
cb1f18661a | ||
![]() |
97d2e4bd75 | ||
![]() |
33a95659e2 | ||
![]() |
35b078b29a | ||
![]() |
2384c11ff1 | ||
![]() |
4c4a188a22 | ||
![]() |
cd6ecf6a89 | ||
![]() |
d804ff0d6b | ||
![]() |
343befa44b | ||
![]() |
72945b856e | ||
![]() |
d01e30431c | ||
![]() |
ff5dcb8df2 | ||
![]() |
f187372f0a | ||
![]() |
1b69122810 | ||
![]() |
e9b4a96975 | ||
![]() |
37f0e8a32c | ||
![]() |
b91e97eabd | ||
![]() |
cda4aaba4d | ||
![]() |
ea864fb24d | ||
![]() |
5908ce5115 | ||
![]() |
159c3aafd8 | ||
![]() |
df739784e5 | ||
![]() |
03d34b683d | ||
![]() |
dc61480c54 | ||
![]() |
f05e1a991a | ||
![]() |
7ceada43af | ||
![]() |
26393a97b2 | ||
![]() |
7d2f61f66a | ||
![]() |
40e13829af | ||
![]() |
f719a97e12 | ||
![]() |
6c6983f477 | ||
![]() |
c399f6eeb2 | ||
![]() |
f8a8ed73fe | ||
![]() |
f8af8606a5 | ||
![]() |
524833e155 | ||
![]() |
5b37db44a3 | ||
![]() |
0e452a02f1 | ||
![]() |
ea6d371e7c | ||
![]() |
7efff86639 | ||
![]() |
67920e1516 | ||
![]() |
4d4dd7aea0 | ||
![]() |
cac1dd58a8 | ||
![]() |
595f5f0e43 | ||
![]() |
e4f6adb023 | ||
![]() |
8da2124060 | ||
![]() |
b9f6ca1d32 | ||
![]() |
05e81222d4 | ||
![]() |
7bb4c8cadb | ||
![]() |
f8f2188888 | ||
![]() |
0c23ec232b | ||
![]() |
a439e438f3 | ||
![]() |
028a408d57 | ||
![]() |
3d5be801b9 | ||
![]() |
1aa6418af9 | ||
![]() |
524bb823c9 | ||
![]() |
2c1db913f7 | ||
![]() |
01a0168806 | ||
![]() |
0e811d8c59 | ||
![]() |
df52f3500c | ||
![]() |
f0369223cd | ||
![]() |
16cb818a74 | ||
![]() |
8dfd22089c | ||
![]() |
37faf55e17 | ||
![]() |
30b093f6fc | ||
![]() |
f3bd3deddd | ||
![]() |
6543f6e36c | ||
![]() |
2fab0d45a9 | ||
![]() |
dc7a598126 | ||
![]() |
5828e886e6 | ||
![]() |
c56aa6f121 | ||
![]() |
e1b13eba75 | ||
![]() |
aae4e4bf70 | ||
![]() |
9c1cf96664 | ||
![]() |
821d4a1e55 | ||
![]() |
4e11bd156e | ||
![]() |
64010d603c | ||
![]() |
c31dec7f98 | ||
![]() |
5b22c47ca9 | ||
![]() |
8efc11a0c1 | ||
![]() |
2cd0c2d244 | ||
![]() |
05a887ebfa | ||
![]() |
81cd24adb8 | ||
![]() |
713f96ee0c | ||
![]() |
cc52d776dd | ||
![]() |
a8206adcad | ||
![]() |
3cad5ab77a | ||
![]() |
eed1c63c70 | ||
![]() |
e38ba43014 | ||
![]() |
46750c39bd | ||
![]() |
5128672731 | ||
![]() |
eda12bcff8 | ||
![]() |
a4cece3d47 | ||
![]() |
d242839af8 | ||
![]() |
6f8046f7a4 | ||
![]() |
c6e7cbb94e | ||
![]() |
12bf451ca4 | ||
![]() |
af46c96d65 | ||
![]() |
2856027e59 | ||
![]() |
fb93fa9216 | ||
![]() |
da172b0dde | ||
![]() |
6ffc113ceb | ||
![]() |
1abc42b26c | ||
![]() |
d19dfa974c | ||
![]() |
3de576efda | ||
![]() |
6bc76194e8 | ||
![]() |
f78ae415d2 | ||
![]() |
59431c242b | ||
![]() |
9ad282b1ae | ||
![]() |
223612afa2 | ||
![]() |
9008f3d564 |
@@ -19,21 +19,17 @@ macro(CURL_CHECK_C_SOURCE_COMPILES SOURCE VAR)
|
|||||||
if(${ARGC} GREATER 2)
|
if(${ARGC} GREATER 2)
|
||||||
# then add the third argument as a message
|
# then add the third argument as a message
|
||||||
set(message "${ARGV2} (${VAR})")
|
set(message "${ARGV2} (${VAR})")
|
||||||
endif(${ARGC} GREATER 2)
|
endif()
|
||||||
set(MACRO_CHECK_FUNCTION_DEFINITIONS
|
set(MACRO_CHECK_FUNCTION_DEFINITIONS
|
||||||
"-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
|
"-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
|
||||||
if(CMAKE_REQUIRED_LIBRARIES)
|
if(CMAKE_REQUIRED_LIBRARIES)
|
||||||
set(CURL_CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES
|
set(CURL_CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES
|
||||||
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
|
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
|
||||||
else(CMAKE_REQUIRED_LIBRARIES)
|
endif()
|
||||||
set(CURL_CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES)
|
|
||||||
endif(CMAKE_REQUIRED_LIBRARIES)
|
|
||||||
if(CMAKE_REQUIRED_INCLUDES)
|
if(CMAKE_REQUIRED_INCLUDES)
|
||||||
set(CURL_CHECK_C_SOURCE_COMPILES_ADD_INCLUDES
|
set(CURL_CHECK_C_SOURCE_COMPILES_ADD_INCLUDES
|
||||||
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
|
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
|
||||||
else(CMAKE_REQUIRED_INCLUDES)
|
endif()
|
||||||
set(CURL_CHECK_C_SOURCE_COMPILES_ADD_INCLUDES)
|
|
||||||
endif(CMAKE_REQUIRED_INCLUDES)
|
|
||||||
set(src "")
|
set(src "")
|
||||||
foreach(def ${EXTRA_DEFINES})
|
foreach(def ${EXTRA_DEFINES})
|
||||||
set(src "${src}#define ${def} 1\n")
|
set(src "${src}#define ${def} 1\n")
|
||||||
@@ -63,13 +59,13 @@ macro(CURL_CHECK_C_SOURCE_COMPILES SOURCE VAR)
|
|||||||
"Performing C SOURCE FILE Test ${message} succeded with the following output:\n"
|
"Performing C SOURCE FILE Test ${message} succeded with the following output:\n"
|
||||||
"${OUTPUT}\n"
|
"${OUTPUT}\n"
|
||||||
"Source file was:\n${src}\n")
|
"Source file was:\n${src}\n")
|
||||||
else(${VAR})
|
else()
|
||||||
message(STATUS "Performing Test ${message} - Failed")
|
message(STATUS "Performing Test ${message} - Failed")
|
||||||
set(${VAR} "" CACHE INTERNAL "Test ${message}")
|
set(${VAR} "" CACHE INTERNAL "Test ${message}")
|
||||||
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||||
"Performing C SOURCE FILE Test ${message} failed with the following output:\n"
|
"Performing C SOURCE FILE Test ${message} failed with the following output:\n"
|
||||||
"${OUTPUT}\n"
|
"${OUTPUT}\n"
|
||||||
"Source file was:\n${src}\n")
|
"Source file was:\n${src}\n")
|
||||||
endif(${VAR})
|
endif()
|
||||||
endif("${VAR}" MATCHES "^${VAR}$" OR "${VAR}" MATCHES "UNKNOWN")
|
endif()
|
||||||
endmacro(CURL_CHECK_C_SOURCE_COMPILES)
|
endmacro()
|
||||||
|
35
CMake/FindLibSSH2.cmake
Normal file
35
CMake/FindLibSSH2.cmake
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# - Try to find the libssh2 library
|
||||||
|
# Once done this will define
|
||||||
|
#
|
||||||
|
# LIBSSH2_FOUND - system has the libssh2 library
|
||||||
|
# LIBSSH2_INCLUDE_DIR - the libssh2 include directory
|
||||||
|
# LIBSSH2_LIBRARY - the libssh2 library name
|
||||||
|
|
||||||
|
if (LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
|
||||||
|
set(LibSSH2_FIND_QUIETLY TRUE)
|
||||||
|
endif (LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
|
||||||
|
|
||||||
|
FIND_PATH(LIBSSH2_INCLUDE_DIR libssh2.h
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(LIBSSH2_LIBRARY NAMES ssh2
|
||||||
|
)
|
||||||
|
|
||||||
|
if(LIBSSH2_INCLUDE_DIR)
|
||||||
|
file(STRINGS "${LIBSSH2_INCLUDE_DIR}/libssh2.h" libssh2_version_str REGEX "^#define[\t ]+LIBSSH2_VERSION_NUM[\t ]+0x[0-9][0-9][0-9][0-9][0-9][0-9].*")
|
||||||
|
|
||||||
|
string(REGEX REPLACE "^.*LIBSSH2_VERSION_NUM[\t ]+0x([0-9][0-9]).*$" "\\1" LIBSSH2_VERSION_MAJOR "${libssh2_version_str}")
|
||||||
|
string(REGEX REPLACE "^.*LIBSSH2_VERSION_NUM[\t ]+0x[0-9][0-9]([0-9][0-9]).*$" "\\1" LIBSSH2_VERSION_MINOR "${libssh2_version_str}")
|
||||||
|
string(REGEX REPLACE "^.*LIBSSH2_VERSION_NUM[\t ]+0x[0-9][0-9][0-9][0-9]([0-9][0-9]).*$" "\\1" LIBSSH2_VERSION_PATCH "${libssh2_version_str}")
|
||||||
|
|
||||||
|
string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_MAJOR "${LIBSSH2_VERSION_MAJOR}")
|
||||||
|
string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_MINOR "${LIBSSH2_VERSION_MINOR}")
|
||||||
|
string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_PATCH "${LIBSSH2_VERSION_PATCH}")
|
||||||
|
|
||||||
|
set(LIBSSH2_VERSION "${LIBSSH2_VERSION_MAJOR}.${LIBSSH2_VERSION_MINOR}.${LIBSSH2_VERSION_PATCH}")
|
||||||
|
endif(LIBSSH2_INCLUDE_DIR)
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibSSH2 DEFAULT_MSG LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY )
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY LIBSSH2_VERSION_MAJOR LIBSSH2_VERSION_MINOR LIBSSH2_VERSION_PATCH LIBSSH2_VERSION)
|
@@ -1,21 +0,0 @@
|
|||||||
# Extension of the standard FindOpenSSL.cmake
|
|
||||||
# Adds OPENSSL_INCLUDE_DIRS and libeay32
|
|
||||||
include("${CMAKE_ROOT}/Modules/FindOpenSSL.cmake")
|
|
||||||
|
|
||||||
# starting 2.8 it is better to use standard modules
|
|
||||||
if(CMAKE_MAJOR_VERSION EQUAL "2" AND CMAKE_MINOR_VERSION LESS "8")
|
|
||||||
# Bill Hoffman told that libeay32 is necessary for him:
|
|
||||||
find_library(SSL_LIBEAY NAMES libeay32)
|
|
||||||
|
|
||||||
if(OPENSSL_FOUND)
|
|
||||||
if(SSL_LIBEAY)
|
|
||||||
list(APPEND OPENSSL_LIBRARIES ${SSL_LIBEAY})
|
|
||||||
else()
|
|
||||||
set(OPENSSL_FOUND FALSE)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif() # if (CMAKE_MAJOR_VERSION EQUAL "2" AND CMAKE_MINOR_VERSION LESS "8")
|
|
||||||
|
|
||||||
if(OPENSSL_FOUND)
|
|
||||||
set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
|
|
||||||
endif()
|
|
@@ -1,10 +0,0 @@
|
|||||||
# Locate zlib
|
|
||||||
include("${CMAKE_ROOT}/Modules/FindZLIB.cmake")
|
|
||||||
|
|
||||||
# starting 2.8 it is better to use standard modules
|
|
||||||
if(CMAKE_MAJOR_VERSION EQUAL "2" AND CMAKE_MINOR_VERSION LESS "8")
|
|
||||||
find_library(ZLIB_LIBRARY_DEBUG NAMES zd zlibd zdlld zlib1d )
|
|
||||||
if(ZLIB_FOUND AND ZLIB_LIBRARY_DEBUG)
|
|
||||||
set( ZLIB_LIBRARIES optimized "${ZLIB_LIBRARY}" debug ${ZLIB_LIBRARY_DEBUG})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
89
CMake/Macros.cmake
Normal file
89
CMake/Macros.cmake
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#File defines convenience macros for available feature testing
|
||||||
|
|
||||||
|
# This macro checks if the symbol exists in the library and if it
|
||||||
|
# does, it prepends library to the list.
|
||||||
|
macro(CHECK_LIBRARY_EXISTS_CONCAT LIBRARY SYMBOL VARIABLE)
|
||||||
|
check_library_exists("${LIBRARY};${CURL_LIBS}" ${SYMBOL} "${CMAKE_LIBRARY_PATH}"
|
||||||
|
${VARIABLE})
|
||||||
|
if(${VARIABLE})
|
||||||
|
set(CURL_LIBS ${LIBRARY} ${CURL_LIBS})
|
||||||
|
endif(${VARIABLE})
|
||||||
|
endmacro(CHECK_LIBRARY_EXISTS_CONCAT)
|
||||||
|
|
||||||
|
# Check if header file exists and add it to the list.
|
||||||
|
macro(CHECK_INCLUDE_FILE_CONCAT FILE VARIABLE)
|
||||||
|
check_include_file("${FILE}" ${VARIABLE})
|
||||||
|
if(${VARIABLE})
|
||||||
|
set(CURL_INCLUDES ${CURL_INCLUDES} ${FILE})
|
||||||
|
set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D${VARIABLE}")
|
||||||
|
endif(${VARIABLE})
|
||||||
|
endmacro(CHECK_INCLUDE_FILE_CONCAT)
|
||||||
|
|
||||||
|
# For other curl specific tests, use this macro.
|
||||||
|
macro(CURL_INTERNAL_TEST CURL_TEST)
|
||||||
|
if("${CURL_TEST}" MATCHES "^${CURL_TEST}$")
|
||||||
|
set(MACRO_CHECK_FUNCTION_DEFINITIONS
|
||||||
|
"-D${CURL_TEST} ${CURL_TEST_DEFINES} ${CMAKE_REQUIRED_FLAGS}")
|
||||||
|
if(CMAKE_REQUIRED_LIBRARIES)
|
||||||
|
set(CURL_TEST_ADD_LIBRARIES
|
||||||
|
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
|
||||||
|
endif(CMAKE_REQUIRED_LIBRARIES)
|
||||||
|
|
||||||
|
message(STATUS "Performing Curl Test ${CURL_TEST}")
|
||||||
|
try_compile(${CURL_TEST}
|
||||||
|
${CMAKE_BINARY_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c
|
||||||
|
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
|
||||||
|
"${CURL_TEST_ADD_LIBRARIES}"
|
||||||
|
OUTPUT_VARIABLE OUTPUT)
|
||||||
|
if(${CURL_TEST})
|
||||||
|
set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}")
|
||||||
|
message(STATUS "Performing Curl Test ${CURL_TEST} - Success")
|
||||||
|
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
|
||||||
|
"Performing Curl Test ${CURL_TEST} passed with the following output:\n"
|
||||||
|
"${OUTPUT}\n")
|
||||||
|
else(${CURL_TEST})
|
||||||
|
message(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
|
||||||
|
set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
|
||||||
|
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||||
|
"Performing Curl Test ${CURL_TEST} failed with the following output:\n"
|
||||||
|
"${OUTPUT}\n")
|
||||||
|
endif(${CURL_TEST})
|
||||||
|
endif("${CURL_TEST}" MATCHES "^${CURL_TEST}$")
|
||||||
|
endmacro(CURL_INTERNAL_TEST)
|
||||||
|
|
||||||
|
macro(CURL_INTERNAL_TEST_RUN CURL_TEST)
|
||||||
|
if("${CURL_TEST}_COMPILE" MATCHES "^${CURL_TEST}_COMPILE$")
|
||||||
|
set(MACRO_CHECK_FUNCTION_DEFINITIONS
|
||||||
|
"-D${CURL_TEST} ${CMAKE_REQUIRED_FLAGS}")
|
||||||
|
if(CMAKE_REQUIRED_LIBRARIES)
|
||||||
|
set(CURL_TEST_ADD_LIBRARIES
|
||||||
|
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
|
||||||
|
endif(CMAKE_REQUIRED_LIBRARIES)
|
||||||
|
|
||||||
|
message(STATUS "Performing Curl Test ${CURL_TEST}")
|
||||||
|
try_run(${CURL_TEST} ${CURL_TEST}_COMPILE
|
||||||
|
${CMAKE_BINARY_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c
|
||||||
|
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
|
||||||
|
"${CURL_TEST_ADD_LIBRARIES}"
|
||||||
|
OUTPUT_VARIABLE OUTPUT)
|
||||||
|
if(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
|
||||||
|
set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}")
|
||||||
|
message(STATUS "Performing Curl Test ${CURL_TEST} - Success")
|
||||||
|
else(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
|
||||||
|
message(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
|
||||||
|
set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
|
||||||
|
file(APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
|
||||||
|
"Performing Curl Test ${CURL_TEST} failed with the following output:\n"
|
||||||
|
"${OUTPUT}")
|
||||||
|
if(${CURL_TEST}_COMPILE)
|
||||||
|
file(APPEND
|
||||||
|
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
|
||||||
|
"There was a problem running this test\n")
|
||||||
|
endif(${CURL_TEST}_COMPILE)
|
||||||
|
file(APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
|
||||||
|
"\n\n")
|
||||||
|
endif(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
|
||||||
|
endif("${CURL_TEST}_COMPILE" MATCHES "^${CURL_TEST}_COMPILE$")
|
||||||
|
endmacro(CURL_INTERNAL_TEST_RUN)
|
@@ -21,6 +21,9 @@ if(HAVE_WINDOWS_H)
|
|||||||
set(EXTRA_DEFINES ${EXTRA_DEFINES}
|
set(EXTRA_DEFINES ${EXTRA_DEFINES}
|
||||||
"__unused7\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#define __unused3")
|
"__unused7\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#define __unused3")
|
||||||
set(signature_call_conv "PASCAL")
|
set(signature_call_conv "PASCAL")
|
||||||
|
if(HAVE_LIBWS2_32)
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ws2_32)
|
||||||
|
endif()
|
||||||
else(HAVE_WINDOWS_H)
|
else(HAVE_WINDOWS_H)
|
||||||
add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
|
add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
|
||||||
add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
|
add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
|
||||||
|
331
CMakeLists.txt
331
CMakeLists.txt
@@ -38,9 +38,10 @@
|
|||||||
# To check:
|
# To check:
|
||||||
# (From Daniel Stenberg) The cmake build selected to run gcc with -fPIC on my box while the plain configure script did not.
|
# (From Daniel Stenberg) The cmake build selected to run gcc with -fPIC on my box while the plain configure script did not.
|
||||||
# (From Daniel Stenberg) The gcc command line use neither -g nor any -O options. As a developer, I also treasure our configure scripts's --enable-debug option that sets a long range of "picky" compiler options.
|
# (From Daniel Stenberg) The gcc command line use neither -g nor any -O options. As a developer, I also treasure our configure scripts's --enable-debug option that sets a long range of "picky" compiler options.
|
||||||
cmake_minimum_required(VERSION 2.6.2 FATAL_ERROR)
|
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
|
||||||
include(Utilities)
|
include(Utilities)
|
||||||
|
include(Macros)
|
||||||
|
|
||||||
project( CURL C )
|
project( CURL C )
|
||||||
|
|
||||||
@@ -133,6 +134,19 @@ mark_as_advanced(CURL_DISABLE_HTTP)
|
|||||||
option(CURL_DISABLE_LDAPS "to disable LDAPS" OFF)
|
option(CURL_DISABLE_LDAPS "to disable LDAPS" OFF)
|
||||||
mark_as_advanced(CURL_DISABLE_LDAPS)
|
mark_as_advanced(CURL_DISABLE_LDAPS)
|
||||||
|
|
||||||
|
option(CURL_DISABLE_RTSP "to disable RTSP" OFF)
|
||||||
|
mark_as_advanced(CURL_DISABLE_RTSP)
|
||||||
|
option(CURL_DISABLE_PROXY "to disable proxy" OFF)
|
||||||
|
mark_as_advanced(CURL_DISABLE_PROXY)
|
||||||
|
option(CURL_DISABLE_POP3 "to disable POP3" OFF)
|
||||||
|
mark_as_advanced(CURL_DISABLE_POP3)
|
||||||
|
option(CURL_DISABLE_IMAP "to disable IMAP" OFF)
|
||||||
|
mark_as_advanced(CURL_DISABLE_IMAP)
|
||||||
|
option(CURL_DISABLE_SMTP "to disable SMTP" OFF)
|
||||||
|
mark_as_advanced(CURL_DISABLE_SMTP)
|
||||||
|
option(CURL_DISABLE_GOPHER "to disable Gopher" OFF)
|
||||||
|
mark_as_advanced(CURL_DISABLE_GOPHER)
|
||||||
|
|
||||||
if(HTTP_ONLY)
|
if(HTTP_ONLY)
|
||||||
set(CURL_DISABLE_FTP ON)
|
set(CURL_DISABLE_FTP ON)
|
||||||
set(CURL_DISABLE_LDAP ON)
|
set(CURL_DISABLE_LDAP ON)
|
||||||
@@ -141,6 +155,11 @@ if(HTTP_ONLY)
|
|||||||
set(CURL_DISABLE_DICT ON)
|
set(CURL_DISABLE_DICT ON)
|
||||||
set(CURL_DISABLE_FILE ON)
|
set(CURL_DISABLE_FILE ON)
|
||||||
set(CURL_DISABLE_TFTP ON)
|
set(CURL_DISABLE_TFTP ON)
|
||||||
|
set(CURL_DISABLE_RTSP ON)
|
||||||
|
set(CURL_DISABLE_POP3 ON)
|
||||||
|
set(CURL_DISABLE_IMAP ON)
|
||||||
|
set(CURL_DISABLE_SMTP ON)
|
||||||
|
set(CURL_DISABLE_GOPHER ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(CURL_DISABLE_COOKIES "to disable cookies support" OFF)
|
option(CURL_DISABLE_COOKIES "to disable cookies support" OFF)
|
||||||
@@ -177,22 +196,13 @@ include (CheckIncludeFiles)
|
|||||||
include (CheckLibraryExists)
|
include (CheckLibraryExists)
|
||||||
include (CheckSymbolExists)
|
include (CheckSymbolExists)
|
||||||
include (CheckTypeSize)
|
include (CheckTypeSize)
|
||||||
|
include (CheckCSourceCompiles)
|
||||||
|
|
||||||
# On windows preload settings
|
# On windows preload settings
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake)
|
include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
# This macro checks if the symbol exists in the library and if it
|
|
||||||
# does, it prepends library to the list.
|
|
||||||
macro(CHECK_LIBRARY_EXISTS_CONCAT LIBRARY SYMBOL VARIABLE)
|
|
||||||
check_library_exists("${LIBRARY};${CURL_LIBS}" ${SYMBOL} "${CMAKE_LIBRARY_PATH}"
|
|
||||||
${VARIABLE})
|
|
||||||
if(${VARIABLE})
|
|
||||||
set(CURL_LIBS ${LIBRARY} ${CURL_LIBS})
|
|
||||||
endif(${VARIABLE})
|
|
||||||
endmacro(CHECK_LIBRARY_EXISTS_CONCAT)
|
|
||||||
|
|
||||||
# Check for all needed libraries
|
# Check for all needed libraries
|
||||||
check_library_exists_concat("dl" dlopen HAVE_LIBDL)
|
check_library_exists_concat("dl" dlopen HAVE_LIBDL)
|
||||||
check_library_exists_concat("socket" connect HAVE_LIBSOCKET)
|
check_library_exists_concat("socket" connect HAVE_LIBSOCKET)
|
||||||
@@ -209,37 +219,120 @@ if(NOT NOT_NEED_LIBNSL)
|
|||||||
check_library_exists_concat("nsl" gethostbyname HAVE_LIBNSL)
|
check_library_exists_concat("nsl" gethostbyname HAVE_LIBNSL)
|
||||||
endif(NOT NOT_NEED_LIBNSL)
|
endif(NOT NOT_NEED_LIBNSL)
|
||||||
|
|
||||||
check_library_exists_concat("ws2_32" getch HAVE_LIBWS2_32)
|
|
||||||
check_library_exists_concat("winmm" getch HAVE_LIBWINMM)
|
|
||||||
check_library_exists("wldap32" cldap_open "" HAVE_WLDAP32)
|
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(CURL_DEFAULT_DISABLE_LDAP OFF)
|
check_library_exists_concat("ws2_32" getch HAVE_LIBWS2_32)
|
||||||
# some windows compilers do not have wldap32
|
check_library_exists_concat("winmm" getch HAVE_LIBWINMM)
|
||||||
if(NOT HAVE_WLDAP32)
|
|
||||||
set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE)
|
|
||||||
message(STATUS "wldap32 not found CURL_DISABLE_LDAP set ON")
|
|
||||||
option(CURL_LDAP_WIN "Use Windows LDAP implementation" OFF)
|
|
||||||
else()
|
|
||||||
option(CURL_LDAP_WIN "Use Windows LDAP implementation" ON)
|
|
||||||
endif()
|
|
||||||
mark_as_advanced(CURL_LDAP_WIN)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT CURL_DISABLE_LDAP)
|
||||||
|
|
||||||
# IF(NOT CURL_SPECIAL_LIBZ)
|
if(WIN32)
|
||||||
# CHECK_LIBRARY_EXISTS_CONCAT("z" inflateEnd HAVE_LIBZ)
|
option(CURL_LDAP_WIN "Use Windows LDAP implementation" ON)
|
||||||
# ENDIF(NOT CURL_SPECIAL_LIBZ)
|
if(CURL_LDAP_WIN)
|
||||||
|
check_library_exists("wldap32" cldap_open "" HAVE_WLDAP32)
|
||||||
|
if(NOT HAVE_WLDAP32)
|
||||||
|
set(CURL_LDAP_WIN OFF)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(CMAKE_USE_OPENLDAP "Use OpenLDAP code." OFF)
|
||||||
|
mark_as_advanced(CMAKE_USE_OPENLDAP)
|
||||||
|
set(CMAKE_LDAP_LIB "ldap" CACHE STRING "Name or full path to ldap library")
|
||||||
|
set(CMAKE_LBER_LIB "lber" CACHE STRING "Name or full path to lber library")
|
||||||
|
|
||||||
|
if(CMAKE_USE_OPENLDAP AND CURL_LDAP_WIN)
|
||||||
|
message(FATAL_ERROR "Cannot use CURL_LDAP_WIN and CMAKE_USE_OPENLDAP at the same time")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Now that we know, we're not using windows LDAP...
|
||||||
|
if(NOT CURL_LDAP_WIN)
|
||||||
|
# Check for LDAP
|
||||||
|
check_library_exists_concat(${CMAKE_LDAP_LIB} ldap_init HAVE_LIBLDAP)
|
||||||
|
check_library_exists_concat(${CMAKE_LBER_LIB} ber_init HAVE_LIBLBER)
|
||||||
|
else()
|
||||||
|
check_include_file_concat("winldap.h" HAVE_WINLDAP_H)
|
||||||
|
check_include_file_concat("winber.h" HAVE_WINBER_H)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_LDAP_INCLUDE_DIR "" CACHE STRING "Path to LDAP include directory")
|
||||||
|
if(CMAKE_LDAP_INCLUDE_DIR)
|
||||||
|
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_LDAP_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
check_include_file_concat("ldap.h" HAVE_LDAP_H)
|
||||||
|
check_include_file_concat("lber.h" HAVE_LBER_H)
|
||||||
|
|
||||||
|
if(NOT HAVE_LDAP_H)
|
||||||
|
message(STATUS "LDAP_H not found CURL_DISABLE_LDAP set ON")
|
||||||
|
set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE)
|
||||||
|
elseif(NOT HAVE_LIBLDAP)
|
||||||
|
message(STATUS "LDAP library '${CMAKE_LDAP_LIB}' not found CURL_DISABLE_LDAP set ON")
|
||||||
|
set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE)
|
||||||
|
else()
|
||||||
|
if(CMAKE_USE_OPENLDAP)
|
||||||
|
set(USE_OPENLDAP ON)
|
||||||
|
endif()
|
||||||
|
if(CMAKE_LDAP_INCLUDE_DIR)
|
||||||
|
include_directories(${CMAKE_LDAP_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
set(NEED_LBER_H ON)
|
||||||
|
set(_HEADER_LIST)
|
||||||
|
if(HAVE_WINDOWS_H)
|
||||||
|
list(APPEND _HEADER_LIST "windows.h")
|
||||||
|
endif()
|
||||||
|
if(HAVE_SYS_TYPES_H)
|
||||||
|
list(APPEND _HEADER_LIST "sys/types.h")
|
||||||
|
endif()
|
||||||
|
list(APPEND _HEADER_LIST "ldap.h")
|
||||||
|
|
||||||
|
set(_SRC_STRING "")
|
||||||
|
foreach(_HEADER ${_HEADER_LIST})
|
||||||
|
set(_INCLUDE_STRING "${_INCLUDE_STRING}#include <${_HEADER}>\n")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(_SRC_STRING
|
||||||
|
"
|
||||||
|
${_INCLUDE_STRING}
|
||||||
|
int main(int argc, char ** argv)
|
||||||
|
{
|
||||||
|
BerValue *bvp = NULL;
|
||||||
|
BerElement *bep = ber_init(bvp);
|
||||||
|
ber_free(bep, 1);
|
||||||
|
return 0;
|
||||||
|
}"
|
||||||
|
)
|
||||||
|
set(CMAKE_REQUIRED_DEFINITIONS "-DLDAP_DEPRECATED=1" "-DWIN32_LEAN_AND_MEAN")
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_LDAP_LIB})
|
||||||
|
if(HAVE_LIBLBER)
|
||||||
|
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB})
|
||||||
|
endif()
|
||||||
|
check_c_source_compiles("${_SRC_STRING}" NOT_NEED_LBER_H)
|
||||||
|
|
||||||
|
if(NOT_NEED_LBER_H)
|
||||||
|
set(NEED_LBER_H OFF)
|
||||||
|
else()
|
||||||
|
set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DNEED_LBER_H")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# No ldap, no ldaps.
|
||||||
|
if(CURL_DISABLE_LDAP)
|
||||||
|
if(NOT CURL_DISABLE_LDAPS)
|
||||||
|
message(STATUS "LDAP needs to be enabled to support LDAPS")
|
||||||
|
set(CURL_DISABLE_LDAPS ON CACHE BOOL "" FORCE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CURL_DISABLE_LDAPS)
|
||||||
|
check_include_file_concat("ldap_ssl.h" HAVE_LDAP_SSL_H)
|
||||||
|
check_include_file_concat("ldapssl.h" HAVE_LDAPSSL_H)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Check for idn
|
# Check for idn
|
||||||
check_library_exists_concat("idn" idna_to_ascii_lz HAVE_LIBIDN)
|
check_library_exists_concat("idn" idna_to_ascii_lz HAVE_LIBIDN)
|
||||||
|
|
||||||
# Check for LDAP
|
|
||||||
check_library_exists_concat("ldap" ldap_init HAVE_LIBLDAP)
|
|
||||||
# if(NOT HAVE_LIBLDAP)
|
|
||||||
# SET(CURL_DISABLE_LDAP ON)
|
|
||||||
# endif(NOT HAVE_LIBLDAP)
|
|
||||||
|
|
||||||
# Check for symbol dlopen (same as HAVE_LIBDL)
|
# Check for symbol dlopen (same as HAVE_LIBDL)
|
||||||
check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)
|
check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)
|
||||||
|
|
||||||
@@ -250,7 +343,7 @@ option(CURL_ZLIB "Set to ON to enable building cURL with zlib support." ON)
|
|||||||
set(HAVE_LIBZ OFF)
|
set(HAVE_LIBZ OFF)
|
||||||
set(HAVE_ZLIB_H OFF)
|
set(HAVE_ZLIB_H OFF)
|
||||||
set(HAVE_ZLIB OFF)
|
set(HAVE_ZLIB OFF)
|
||||||
if(CURL_ZLIB) # AND CURL_CONFIG_HAS_BEEN_RUN_BEFORE
|
if(CURL_ZLIB)
|
||||||
find_package(ZLIB QUIET)
|
find_package(ZLIB QUIET)
|
||||||
if(ZLIB_FOUND)
|
if(ZLIB_FOUND)
|
||||||
set(HAVE_ZLIB_H ON)
|
set(HAVE_ZLIB_H ON)
|
||||||
@@ -262,37 +355,70 @@ endif()
|
|||||||
|
|
||||||
option(CMAKE_USE_OPENSSL "Use OpenSSL code. Experimental" ON)
|
option(CMAKE_USE_OPENSSL "Use OpenSSL code. Experimental" ON)
|
||||||
mark_as_advanced(CMAKE_USE_OPENSSL)
|
mark_as_advanced(CMAKE_USE_OPENSSL)
|
||||||
|
|
||||||
|
set(USE_SSLEAY OFF)
|
||||||
|
set(USE_OPENSSL OFF)
|
||||||
|
set(HAVE_LIBCRYPTO OFF)
|
||||||
|
set(HAVE_LIBSSL OFF)
|
||||||
|
|
||||||
if(CMAKE_USE_OPENSSL)
|
if(CMAKE_USE_OPENSSL)
|
||||||
|
|
||||||
set(USE_SSLEAY OFF)
|
|
||||||
set(USE_OPENSSL OFF)
|
|
||||||
set(HAVE_LIBCRYPTO OFF)
|
|
||||||
set(HAVE_LIBSSL OFF)
|
|
||||||
|
|
||||||
find_package(OpenSSL)
|
find_package(OpenSSL)
|
||||||
if(OPENSSL_FOUND)
|
if(OPENSSL_FOUND)
|
||||||
list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES})
|
list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES})
|
||||||
list(APPEND CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
|
||||||
set(USE_SSLEAY ON)
|
set(USE_SSLEAY ON)
|
||||||
set(USE_OPENSSL ON)
|
set(USE_OPENSSL ON)
|
||||||
set(HAVE_LIBCRYPTO ON)
|
set(HAVE_LIBCRYPTO ON)
|
||||||
set(HAVE_LIBSSL ON)
|
set(HAVE_LIBSSL ON)
|
||||||
|
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||||
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
|
check_include_file_concat("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H)
|
||||||
|
check_include_file_concat("openssl/engine.h" HAVE_OPENSSL_ENGINE_H)
|
||||||
|
check_include_file_concat("openssl/err.h" HAVE_OPENSSL_ERR_H)
|
||||||
|
check_include_file_concat("openssl/pem.h" HAVE_OPENSSL_PEM_H)
|
||||||
|
check_include_file_concat("openssl/pkcs12.h" HAVE_OPENSSL_PKCS12_H)
|
||||||
|
check_include_file_concat("openssl/rsa.h" HAVE_OPENSSL_RSA_H)
|
||||||
|
check_include_file_concat("openssl/ssl.h" HAVE_OPENSSL_SSL_H)
|
||||||
|
check_include_file_concat("openssl/x509.h" HAVE_OPENSSL_X509_H)
|
||||||
|
check_include_file_concat("openssl/rand.h" HAVE_OPENSSL_RAND_H)
|
||||||
endif(OPENSSL_FOUND)
|
endif(OPENSSL_FOUND)
|
||||||
endif(CMAKE_USE_OPENSSL)
|
endif(CMAKE_USE_OPENSSL)
|
||||||
|
|
||||||
|
#libSSH2
|
||||||
|
option(CMAKE_USE_LIBSSH2 "Use libSSH2" ON)
|
||||||
|
mark_as_advanced(CMAKE_USE_LIBSSH2)
|
||||||
|
set(USE_LIBSSH2 OFF)
|
||||||
|
set(HAVE_LIBSSH2 OFF)
|
||||||
|
set(HAVE_LIBSSH2_H OFF)
|
||||||
|
|
||||||
|
if(CMAKE_USE_LIBSSH2)
|
||||||
|
find_package(LibSSH2)
|
||||||
|
if(LIBSSH2_FOUND)
|
||||||
|
list(APPEND CURL_LIBS ${LIBSSH2_LIBRARY})
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ${LIBSSH2_LIBRARY})
|
||||||
|
set(CMAKE_REQUIRED_INCLUDES "${LIBSSH2_INCLUDE_DIR}")
|
||||||
|
set(HAVE_LIBSSH2 ON)
|
||||||
|
set(USE_LIBSSH2 ON)
|
||||||
|
|
||||||
|
# find_package has already found the headers
|
||||||
|
set(HAVE_LIBSSH2_H ON)
|
||||||
|
set(CURL_INCLUDES ${CURL_INCLUDES} "${LIBSSH2_INCLUDE_DIR}/libssh2.h")
|
||||||
|
set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DHAVE_LIBSSH2_H")
|
||||||
|
|
||||||
|
# now check for specific libssh2 symbols as they were added in different versions
|
||||||
|
set(CMAKE_EXTRA_INCLUDE_FILES "libssh2.h")
|
||||||
|
check_function_exists(libssh2_version HAVE_LIBSSH2_VERSION)
|
||||||
|
check_function_exists(libssh2_init HAVE_LIBSSH2_INIT)
|
||||||
|
check_function_exists(libssh2_exit HAVE_LIBSSH2_EXIT)
|
||||||
|
check_function_exists(libssh2_scp_send64 HAVE_LIBSSH2_SCP_SEND64)
|
||||||
|
check_function_exists(libssh2_session_handshake HAVE_LIBSSH2_SESSION_HANDSHAKE)
|
||||||
|
set(CMAKE_EXTRA_INCLUDE_FILES "")
|
||||||
|
|
||||||
|
endif(LIBSSH2_FOUND)
|
||||||
|
endif(CMAKE_USE_LIBSSH2)
|
||||||
|
|
||||||
# If we have features.h, then do the _BSD_SOURCE magic
|
# If we have features.h, then do the _BSD_SOURCE magic
|
||||||
check_include_file("features.h" HAVE_FEATURES_H)
|
check_include_file("features.h" HAVE_FEATURES_H)
|
||||||
|
|
||||||
# Check if header file exists and add it to the list.
|
|
||||||
macro(CHECK_INCLUDE_FILE_CONCAT FILE VARIABLE)
|
|
||||||
check_include_files("${CURL_INCLUDES};${FILE}" ${VARIABLE})
|
|
||||||
if(${VARIABLE})
|
|
||||||
set(CURL_INCLUDES ${CURL_INCLUDES} ${FILE})
|
|
||||||
set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D${VARIABLE}")
|
|
||||||
endif(${VARIABLE})
|
|
||||||
endmacro(CHECK_INCLUDE_FILE_CONCAT)
|
|
||||||
|
|
||||||
|
|
||||||
# Check for header files
|
# Check for header files
|
||||||
if(NOT UNIX)
|
if(NOT UNIX)
|
||||||
check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H)
|
check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H)
|
||||||
@@ -336,24 +462,13 @@ check_include_file_concat("ifaddrs.h" HAVE_IFADDRS_H)
|
|||||||
check_include_file_concat("io.h" HAVE_IO_H)
|
check_include_file_concat("io.h" HAVE_IO_H)
|
||||||
check_include_file_concat("krb.h" HAVE_KRB_H)
|
check_include_file_concat("krb.h" HAVE_KRB_H)
|
||||||
check_include_file_concat("libgen.h" HAVE_LIBGEN_H)
|
check_include_file_concat("libgen.h" HAVE_LIBGEN_H)
|
||||||
check_include_file_concat("libssh2.h" HAVE_LIBSSH2_H)
|
|
||||||
check_include_file_concat("limits.h" HAVE_LIMITS_H)
|
check_include_file_concat("limits.h" HAVE_LIMITS_H)
|
||||||
check_include_file_concat("locale.h" HAVE_LOCALE_H)
|
check_include_file_concat("locale.h" HAVE_LOCALE_H)
|
||||||
check_include_file_concat("net/if.h" HAVE_NET_IF_H)
|
check_include_file_concat("net/if.h" HAVE_NET_IF_H)
|
||||||
check_include_file_concat("netdb.h" HAVE_NETDB_H)
|
check_include_file_concat("netdb.h" HAVE_NETDB_H)
|
||||||
check_include_file_concat("netinet/in.h" HAVE_NETINET_IN_H)
|
check_include_file_concat("netinet/in.h" HAVE_NETINET_IN_H)
|
||||||
check_include_file_concat("netinet/tcp.h" HAVE_NETINET_TCP_H)
|
check_include_file_concat("netinet/tcp.h" HAVE_NETINET_TCP_H)
|
||||||
if(CMAKE_USE_OPENSSL AND OPENSSL_FOUND)
|
|
||||||
check_include_file_concat("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H)
|
|
||||||
check_include_file_concat("openssl/engine.h" HAVE_OPENSSL_ENGINE_H)
|
|
||||||
check_include_file_concat("openssl/err.h" HAVE_OPENSSL_ERR_H)
|
|
||||||
check_include_file_concat("openssl/pem.h" HAVE_OPENSSL_PEM_H)
|
|
||||||
check_include_file_concat("openssl/pkcs12.h" HAVE_OPENSSL_PKCS12_H)
|
|
||||||
check_include_file_concat("openssl/rsa.h" HAVE_OPENSSL_RSA_H)
|
|
||||||
check_include_file_concat("openssl/ssl.h" HAVE_OPENSSL_SSL_H)
|
|
||||||
check_include_file_concat("openssl/x509.h" HAVE_OPENSSL_X509_H)
|
|
||||||
check_include_file_concat("openssl/rand.h" HAVE_OPENSSL_RAND_H)
|
|
||||||
endif(CMAKE_USE_OPENSSL AND OPENSSL_FOUND)
|
|
||||||
check_include_file_concat("pem.h" HAVE_PEM_H)
|
check_include_file_concat("pem.h" HAVE_PEM_H)
|
||||||
check_include_file_concat("poll.h" HAVE_POLL_H)
|
check_include_file_concat("poll.h" HAVE_POLL_H)
|
||||||
check_include_file_concat("pwd.h" HAVE_PWD_H)
|
check_include_file_concat("pwd.h" HAVE_PWD_H)
|
||||||
@@ -382,25 +497,13 @@ check_include_file_concat("stddef.h" HAVE_STDDEF_H)
|
|||||||
check_include_file_concat("dlfcn.h" HAVE_DLFCN_H)
|
check_include_file_concat("dlfcn.h" HAVE_DLFCN_H)
|
||||||
check_include_file_concat("malloc.h" HAVE_MALLOC_H)
|
check_include_file_concat("malloc.h" HAVE_MALLOC_H)
|
||||||
check_include_file_concat("memory.h" HAVE_MEMORY_H)
|
check_include_file_concat("memory.h" HAVE_MEMORY_H)
|
||||||
check_include_file_concat("ldap.h" HAVE_LDAP_H)
|
|
||||||
check_include_file_concat("netinet/if_ether.h" HAVE_NETINET_IF_ETHER_H)
|
check_include_file_concat("netinet/if_ether.h" HAVE_NETINET_IF_ETHER_H)
|
||||||
check_include_file_concat("stdint.h" HAVE_STDINT_H)
|
check_include_file_concat("stdint.h" HAVE_STDINT_H)
|
||||||
check_include_file_concat("sockio.h" HAVE_SOCKIO_H)
|
check_include_file_concat("sockio.h" HAVE_SOCKIO_H)
|
||||||
check_include_file_concat("sys/utsname.h" HAVE_SYS_UTSNAME_H)
|
check_include_file_concat("sys/utsname.h" HAVE_SYS_UTSNAME_H)
|
||||||
check_include_file_concat("idna.h" HAVE_IDNA_H)
|
check_include_file_concat("idna.h" HAVE_IDNA_H)
|
||||||
|
|
||||||
if(NOT HAVE_LDAP_H)
|
|
||||||
message(STATUS "LDAP_H not found CURL_DISABLE_LDAP set ON")
|
|
||||||
set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# No ldap, no ldaps.
|
|
||||||
if(CURL_DISABLE_LDAP)
|
|
||||||
if(NOT CURL_DISABLE_LDAPS)
|
|
||||||
message(STATUS "LDAP needs to be enabled to support LDAPS")
|
|
||||||
set(CURL_DISABLE_LDAPS ON CACHE BOOL "" FORCE)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
check_type_size(size_t SIZEOF_SIZE_T)
|
check_type_size(size_t SIZEOF_SIZE_T)
|
||||||
check_type_size(ssize_t SIZEOF_SSIZE_T)
|
check_type_size(ssize_t SIZEOF_SSIZE_T)
|
||||||
@@ -574,76 +677,12 @@ if(NOT HAVE_STRICMP)
|
|||||||
set(HAVE_LDAP_URL_PARSE 1)
|
set(HAVE_LDAP_URL_PARSE 1)
|
||||||
endif(NOT HAVE_STRICMP)
|
endif(NOT HAVE_STRICMP)
|
||||||
|
|
||||||
# For other curl specific tests, use this macro.
|
|
||||||
macro(CURL_INTERNAL_TEST CURL_TEST)
|
|
||||||
if("${CURL_TEST}" MATCHES "^${CURL_TEST}$")
|
|
||||||
set(MACRO_CHECK_FUNCTION_DEFINITIONS
|
|
||||||
"-D${CURL_TEST} ${CURL_TEST_DEFINES} ${CMAKE_REQUIRED_FLAGS}")
|
|
||||||
if(CMAKE_REQUIRED_LIBRARIES)
|
|
||||||
set(CURL_TEST_ADD_LIBRARIES
|
|
||||||
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
|
|
||||||
endif(CMAKE_REQUIRED_LIBRARIES)
|
|
||||||
|
|
||||||
message(STATUS "Performing Curl Test ${CURL_TEST}")
|
|
||||||
try_compile(${CURL_TEST}
|
|
||||||
${CMAKE_BINARY_DIR}
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c
|
|
||||||
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
|
|
||||||
"${CURL_TEST_ADD_LIBRARIES}"
|
|
||||||
OUTPUT_VARIABLE OUTPUT)
|
|
||||||
if(${CURL_TEST})
|
|
||||||
set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}")
|
|
||||||
message(STATUS "Performing Curl Test ${CURL_TEST} - Success")
|
|
||||||
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
|
|
||||||
"Performing Curl Test ${CURL_TEST} passed with the following output:\n"
|
|
||||||
"${OUTPUT}\n")
|
|
||||||
else(${CURL_TEST})
|
|
||||||
message(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
|
|
||||||
set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
|
|
||||||
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
|
||||||
"Performing Curl Test ${CURL_TEST} failed with the following output:\n"
|
|
||||||
"${OUTPUT}\n")
|
|
||||||
endif(${CURL_TEST})
|
|
||||||
endif("${CURL_TEST}" MATCHES "^${CURL_TEST}$")
|
|
||||||
endmacro(CURL_INTERNAL_TEST)
|
|
||||||
|
|
||||||
macro(CURL_INTERNAL_TEST_RUN CURL_TEST)
|
|
||||||
if("${CURL_TEST}_COMPILE" MATCHES "^${CURL_TEST}_COMPILE$")
|
|
||||||
set(MACRO_CHECK_FUNCTION_DEFINITIONS
|
|
||||||
"-D${CURL_TEST} ${CMAKE_REQUIRED_FLAGS}")
|
|
||||||
if(CMAKE_REQUIRED_LIBRARIES)
|
|
||||||
set(CURL_TEST_ADD_LIBRARIES
|
|
||||||
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
|
|
||||||
endif(CMAKE_REQUIRED_LIBRARIES)
|
|
||||||
|
|
||||||
message(STATUS "Performing Curl Test ${CURL_TEST}")
|
|
||||||
try_run(${CURL_TEST} ${CURL_TEST}_COMPILE
|
|
||||||
${CMAKE_BINARY_DIR}
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c
|
|
||||||
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
|
|
||||||
"${CURL_TEST_ADD_LIBRARIES}"
|
|
||||||
OUTPUT_VARIABLE OUTPUT)
|
|
||||||
if(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
|
|
||||||
set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}")
|
|
||||||
message(STATUS "Performing Curl Test ${CURL_TEST} - Success")
|
|
||||||
else(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
|
|
||||||
message(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
|
|
||||||
set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
|
|
||||||
file(APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
|
|
||||||
"Performing Curl Test ${CURL_TEST} failed with the following output:\n"
|
|
||||||
"${OUTPUT}")
|
|
||||||
if(${CURL_TEST}_COMPILE)
|
|
||||||
file(APPEND
|
|
||||||
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
|
|
||||||
"There was a problem running this test\n")
|
|
||||||
endif(${CURL_TEST}_COMPILE)
|
|
||||||
file(APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
|
|
||||||
"\n\n")
|
|
||||||
endif(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
|
|
||||||
endif("${CURL_TEST}_COMPILE" MATCHES "^${CURL_TEST}_COMPILE$")
|
|
||||||
endmacro(CURL_INTERNAL_TEST_RUN)
|
|
||||||
|
|
||||||
# Do curl specific tests
|
# Do curl specific tests
|
||||||
|
if(HAVE_LIBWS2_32)
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ws2_32)
|
||||||
|
endif()
|
||||||
foreach(CURL_TEST
|
foreach(CURL_TEST
|
||||||
HAVE_FCNTL_O_NONBLOCK
|
HAVE_FCNTL_O_NONBLOCK
|
||||||
HAVE_IOCTLSOCKET
|
HAVE_IOCTLSOCKET
|
||||||
@@ -835,14 +874,14 @@ endif(MSVC)
|
|||||||
function(SETUP_CURL_DEPENDENCIES TARGET_NAME)
|
function(SETUP_CURL_DEPENDENCIES TARGET_NAME)
|
||||||
if(CURL_ZLIB AND ZLIB_FOUND)
|
if(CURL_ZLIB AND ZLIB_FOUND)
|
||||||
include_directories(${ZLIB_INCLUDE_DIR})
|
include_directories(${ZLIB_INCLUDE_DIR})
|
||||||
#ADD_DEFINITIONS( -DHAVE_ZLIB_H -DHAVE_ZLIB -DHAVE_LIBZ )
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_USE_OPENSSL AND OPENSSL_FOUND)
|
if(CMAKE_USE_OPENSSL AND OPENSSL_FOUND)
|
||||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||||
endif()
|
endif()
|
||||||
if(CMAKE_USE_OPENSSL AND CURL_CONFIG_HAS_BEEN_RUN_BEFORE)
|
|
||||||
#ADD_DEFINITIONS( -DUSE_SSLEAY )
|
if(CMAKE_USE_LIBSSH2 AND LIBSSH2_FOUND)
|
||||||
|
include_directories(${LIBSSH2_INCLUDE_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${TARGET_NAME} ${CURL_LIBS})
|
target_link_libraries(${TARGET_NAME} ${CURL_LIBS})
|
||||||
|
@@ -24,10 +24,9 @@ AUTOMAKE_OPTIONS = foreign
|
|||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
CMAKE_DIST = CMakeLists.txt CMake/CMakeConfigurableFile.in \
|
CMAKE_DIST = CMakeLists.txt CMake/CMakeConfigurableFile.in \
|
||||||
CMake/CurlCheckCSourceCompiles.cmake CMake/CurlCheckCSourceRuns.cmake \
|
CMake/CurlCheckCSourceCompiles.cmake CMake/CurlCheckCSourceRuns.cmake \
|
||||||
CMake/CurlTests.c CMake/FindOpenSSL.cmake CMake/FindZLIB.cmake \
|
CMake/CurlTests.c CMake/OtherTests.cmake CMake/Platforms/WindowsCache.cmake \
|
||||||
CMake/OtherTests.cmake CMake/Platforms/WindowsCache.cmake \
|
|
||||||
CMake/Utilities.cmake include/curl/curlbuild.h.cmake
|
CMake/Utilities.cmake include/curl/curlbuild.h.cmake
|
||||||
|
|
||||||
VC6_LIBTMPL = projects/Windows/VC6/lib/libcurl.tmpl
|
VC6_LIBTMPL = projects/Windows/VC6/lib/libcurl.tmpl
|
||||||
|
186
RELEASE-NOTES
186
RELEASE-NOTES
@@ -1,67 +1,92 @@
|
|||||||
Curl and libcurl 7.37.1
|
Curl and libcurl 7.38.0
|
||||||
|
|
||||||
Public curl releases: 140
|
Public curl releases: 141
|
||||||
Command line options: 162
|
Command line options: 162
|
||||||
curl_easy_setopt() options: 208
|
curl_easy_setopt() options: 208
|
||||||
Public functions in libcurl: 58
|
Public functions in libcurl: 58
|
||||||
Contributors: 1155
|
Contributors: 1216
|
||||||
|
|
||||||
This release includes the following changes:
|
This release includes the following changes:
|
||||||
|
|
||||||
o bits.close: introduce connection close tracking
|
o CURLE_HTTP2 is a new error code
|
||||||
o darwinssl: Add support for --cacert
|
o CURLAUTH_NEGOTIATE is a new auth define
|
||||||
o polarssl: add ALPN support
|
o CURL_VERSION_GSSAPI is a new capability bit
|
||||||
o docs: Added new option man pages
|
o no longer use fbopenssl for anything
|
||||||
|
o schannel: use CryptGenRandom for random numbers
|
||||||
|
o axtls: define curlssl_random using axTLS's PRNG
|
||||||
|
o cyassl: use RNG_GenerateBlock to generate a good random number
|
||||||
|
o findprotocol: show unsupported protocol within quotes
|
||||||
|
o version: detect and show LibreSSL
|
||||||
|
o version: detect and show BoringSSL
|
||||||
|
o imap/pop3/smtp: Kerberos (SASL GSSAPI) authentication via Windows SSPI
|
||||||
|
o http2: requires nghttp2 0.6.0 or later
|
||||||
|
|
||||||
This release includes the following bugfixes:
|
This release includes the following bugfixes:
|
||||||
|
|
||||||
o build: Fixed incorrect reference to curl_setup.h in Visual Studio files
|
o CVE-2014-3613: cookie leak with IP address as domain [25]
|
||||||
o build: Use $(TargetDir) and $(TargetName) macros for .pdb and .lib output
|
o CVE-2014-3620: cookie leak for TLDs [26]
|
||||||
o curl.1: clarify that -u can't specify a user with colon [1]
|
|
||||||
o openssl: Fix uninitialized variable use in NPN callback
|
o fix a build failure on Debian when NSS support is enabled [1]
|
||||||
o curl_easy_reset: reset the URL [2]
|
o HTTP/2: fixed compiler warnings when built disabled [2]
|
||||||
o curl_version_info.3: returns a pointer to a static struct
|
o cyassl: return the correct error code on no CA cert
|
||||||
o url-parser: only use if_nametoindex if detected by configure [3]
|
o http: Deprecate GSS-Negotiate macros due to bad naming
|
||||||
o select: with winsock, avoid passing unsupported arguments to select() [4]
|
o http: Fixed Negotiate: authentication
|
||||||
o gnutls: don't use deprecated type names anymore
|
o multi: Improve proxy CONNECT performance (regression) [3]
|
||||||
o gnutls: allow building with nghttp2 but without ALPN support
|
o ntlm_wb: Avoid invoking ntlm_auth helper with empty username
|
||||||
o tests: Fix portability issue with the tftpd server
|
o ntlm_wb: Fix hard-coded limit on NTLM auth packet size
|
||||||
o curl_sasl_sspi: Fixed corrupt hostname in DIGEST-MD5 SPN
|
o url.c: use the preferred symbol name: *READDATA [4]
|
||||||
o curl_sasl: extended native DIGEST-MD5 cnonce to be a 32-byte hex string
|
o smtp: fixed a segfault during test 1320 torture test
|
||||||
o random: use Curl_rand() for proper random data [5]
|
o cyassl: made it compile with version 2.0.6 again
|
||||||
o Curl_ossl_init: call OPENSSL_config for initing engines [6]
|
o nss: do not check the version of NSS at run time
|
||||||
o config-win32.h: Updated for VC12 [7]
|
o c-ares: fix build without IPv6 support [5]
|
||||||
o winbuild: Don't USE_WINSSL when WITH_SSL is being used
|
o HTTP/2: use base64url encoding [6]
|
||||||
o getinfo: HTTP CONNECT code not reset between transfers [8]
|
o SSPI Negotiate: Fix 3 memory leaks
|
||||||
o Curl_rand: Use a fake entropy for debug builds when CURL_ENTROPY set
|
o libtest: fixed duplicated line in Makefile [7]
|
||||||
o http2: avoid segfault when using the plain-text http2
|
o conncache: fix compiler warning [8]
|
||||||
o conncache: move the connection counter to the cache struct
|
o openssl: make ossl_send return CURLE_OK better
|
||||||
o http2: better return code error checking
|
o HTTP/2: Support expect: 100-continue
|
||||||
o curlbuild: fix GCC build on SPARC systems without configure script
|
o HTTP/2: Fix infinite loop in readwrite_data()
|
||||||
o tool_metalink: Support polarssl as digest provider
|
o parsedate: fix the return code for an overflow edge condition
|
||||||
o curl.h: reverse the enum/define setup for old symbols
|
o darwinssl: don't use strtok()
|
||||||
o curl.h: moved two really old deprecated symbols
|
o http_negotiate_sspi: Fixed specific username and password not working [9]
|
||||||
o curl.h: renamed CURLOPT_DEPRECATEDx to CURLOPT_OBSOLETEx
|
o openssl: replace call to OPENSSL_config [10]
|
||||||
o buildconf: do not search tools in current directory.
|
o http2: show the received header for better debugging
|
||||||
o OS400: make it compilable again. Make RPG binding up to date
|
o HTTP/2: Move :authority before non-pseudo header fields
|
||||||
o nss: do not abort on connection failure (failing tests 305 and 404)
|
o HTTP/2: Reset promised stream, not its associated stream
|
||||||
o nss: make the fallback to SSLv3 work again
|
o HTTP/2: added some more logging for debugging stream problems
|
||||||
o tool: prevent valgrind from reporting possibly lost memory (nss only)
|
o ntlm: Added support for SSPI package info query
|
||||||
o progress callback: skip last callback update on errors [9]
|
o ntlm: Fixed hard coded buffer for SSPI based auth packet generation
|
||||||
o nss: fix a memory leak when CURLOPT_CRLFILE is used
|
o sasl_sspi: Fixed memory leak with not releasing Package Info struct
|
||||||
o compiler warnings: potentially uninitialized variables [10]
|
o sasl_sspi: Fixed SPN not being converted to wchar under Unicode builds
|
||||||
o url.c: Fixed memory leak on OOM
|
o sasl: Use a dynamic buffer for DIGEST-MD5 SPN generation
|
||||||
o gnutls: ignore invalid certificate dates with VERIFYPEER disabled
|
o http_negotiate_sspi: Use a dynamic buffer for SPN generation
|
||||||
o gnutls: fix SRP support with versions of GnuTLS from 2.99.0
|
o sasl_sspi: Fixed missing free of challenge buffer on SPN failure
|
||||||
o gnutls: fixed a couple of uninitialized variable references
|
o sasl_sspi: Fixed hard coded buffer for response generation
|
||||||
o gnutls: fixed compilation against versions < 2.12.0
|
o Curl_poll + Curl_wait_ms: fix timeout return value
|
||||||
o build: Fixed overridden compiler PDB settings in VC7 to VC12
|
o docs/SSLCERTS: update the section about NSS database
|
||||||
o ntlm_wb: Fixed buffer size not being large enough for NTLMv2 sessions [11]
|
o create_conn: prune dead connections [11]
|
||||||
o netrc: don't abort if home dir cannot be found
|
o openssl: fix version report for the 0.9.8 branch
|
||||||
o netrc: fixed thread safety problem by using getpwuid_r if available
|
o mk-ca-bundle.pl: switched to using hg.mozilla.org [12]
|
||||||
o cookie: avoid mutex deadlock [12]
|
o http: fix the Content-Range: parser [13]
|
||||||
o configure: respect host tool prefix for krb5-config
|
o Curl_disconnect: don't free the URL [14]
|
||||||
o gnutls: handle IP address in cert name check
|
o win32: Fixed WinSock 2 #if [15]
|
||||||
|
o NTLM: ignore CURLOPT_FORBID_REUSE during NTLM HTTP auth
|
||||||
|
o curl.1: clarify --limit-rate's effect on both directions [16]
|
||||||
|
o disconnect: don't touch easy-related state on disconnects [17]
|
||||||
|
o Cmake: big cleanup and numerous fixes
|
||||||
|
o HTTP/2: supports draft-14 - moved :headers before the non-psuedo headers
|
||||||
|
o HTTP/2: Reset promised stream, not its associated stream
|
||||||
|
o configure.ac: Add support for recent GSS-API implementations for HP-UX
|
||||||
|
o CONNECT: close proxy connections that fail [18]
|
||||||
|
o CURLOPT_NOBODY.3: clarify this option is for downloads [19]
|
||||||
|
o darwinssl: fix CA certificate checking using PEM format [20]
|
||||||
|
o resolve: cache lookup for async resolvers [21]
|
||||||
|
o low-speed-limit: avoid timeout flood [22]
|
||||||
|
o polarssl: implement CURLOPT_SSLVERSION [23]
|
||||||
|
o multi: convert CURLM_STATE_CONNECT_PEND handling to a list [24]
|
||||||
|
o curl_multi_cleanup: remove superfluous NULL assigns
|
||||||
|
o polarssl: support CURLOPT_CAPATH / --capath
|
||||||
|
o progress: size_dl/size_ul are always >= 0, and clear "KNOWN" properly
|
||||||
|
|
||||||
This release includes the following known bugs:
|
This release includes the following known bugs:
|
||||||
|
|
||||||
@@ -70,26 +95,43 @@ This release includes the following known bugs:
|
|||||||
This release would not have looked like this without help, code, reports and
|
This release would not have looked like this without help, code, reports and
|
||||||
advice from friends like these:
|
advice from friends like these:
|
||||||
|
|
||||||
Alessandro Ghedini, Brad Spencer, Chris Young, Colin Hogben, Dan Fandrich,
|
Alessandro Ghedini, Andre Heinecke, Anthon Pang, Askar Safin, Brandon Casey,
|
||||||
Daniel Stenberg, David Woodhouse, Dimitrios Siganos, Fabian Frank,
|
Catalin Patulea, Dan Fandrich, Daniel Stenberg, Dave Reisner, David Meyer,
|
||||||
Glen A Johnson Jr., Hubert Kario, Jeff Pohlmeyer, Jonathan Cardoso Machado,
|
David Shaw, David Woodhouse, Dimitrios Siganos, Ed Morley, Fabian Keil,
|
||||||
Kamil Dudka, Lindley French, Marcel Raad, Michał Górny, Nick Zitzmann,
|
Florian Weimer, Frank Gevaerts, Frank Meier, Haris Okanovic, Jakub Zakrzewski,
|
||||||
Patrick Monnerat, Ray Satiro, Steve Holme, Tatsuhiro Tsujikawa,
|
Jan Ehrhardt, John Coffey, Jonatan Vela, Jose Alf, Kamil Dudka,
|
||||||
Vilmos Nebehaj, Yousuke Kimoto, Dmitry Falko
|
Leonardo Rosati, Marcel Raad, Michael Osipov, Michael Wallner, Paras S,
|
||||||
|
Patrick Monnerat, Paul Saab, Peter Wang, Rafaël Carré, Sergey Nikulov,
|
||||||
|
Spork Schivago, Steve Holme, Tatsuhiro Tsujikawa, Tim Ruehsen, Toby Peterson,
|
||||||
|
Vilmos Nebehaj,
|
||||||
|
|
||||||
Thanks! (and sorry if I forgot to mention someone)
|
Thanks! (and sorry if I forgot to mention someone)
|
||||||
|
|
||||||
References to bug reports and discussions on issues:
|
References to bug reports and discussions on issues:
|
||||||
|
|
||||||
[1] = http://curl.haxx.se/bug/view.cgi?id=1375
|
[1] = http://curl.haxx.se/mail/lib-2014-07/0209.html
|
||||||
[2] = http://curl.haxx.se/mail/lib-2014-05/0235.html
|
[2] = http://curl.haxx.se/mail/lib-2014-07/0202.html
|
||||||
[3] = http://curl.haxx.se/mail/lib-2014-05/0260.html
|
[3] = http://curl.haxx.se/bug/view.cgi?id=1397
|
||||||
[4] = http://curl.haxx.se/mail/lib-2014-05/0278.html
|
[4] = http://curl.haxx.se/bug/view.cgi?id=1398
|
||||||
[5] = http://curl.haxx.se/mail/lib-2014-06/0001.html
|
[5] = http://curl.haxx.se/mail/lib-2014-07/0337.html
|
||||||
[6] = http://curl.haxx.se/mail/lib-2014-06/0003.html
|
[6] = https://github.com/tatsuhiro-t/nghttp2/issues/62
|
||||||
[7] = http://curl.haxx.se/bug/view.cgi?id=1378
|
[7] = https://github.com/bagder/curl/pull/105
|
||||||
[8] = http://curl.haxx.se/bug/view.cgi?id=1380
|
[8] = http://curl.haxx.se/bug/view.cgi?id=1399
|
||||||
[9] = http://curl.haxx.se/mail/lib-2014-06/0062.html
|
[9] = http://curl.haxx.se/mail/lib-2014-06/0224.html
|
||||||
[10] = http://curl.haxx.se/bug/view.cgi?id=1391
|
[10] = http://curl.haxx.se/bug/view.cgi?id=1401
|
||||||
[11] = http://curl.haxx.se/mail/lib-2014-07/0103.html
|
[11] = http://curl.haxx.se/mail/lib-2014-06/0189.html
|
||||||
[12] = http://curl.haxx.se/mail/lib-2014-02/0184.html
|
[12] = http://curl.haxx.se/bug/view.cgi?id=1409
|
||||||
|
[13] = http://curl.haxx.se/mail/lib-2014-06/0221.html
|
||||||
|
[14] = http://curl.haxx.se/mail/lib-2014-08/0148.html
|
||||||
|
[15] = http://curl.haxx.se/mail/lib-2014-08/0155.html
|
||||||
|
[16] = http://curl.haxx.se/bug/view.cgi?id=1414
|
||||||
|
[17] = http://curl.haxx.se/mail/lib-2014-08/0148.html
|
||||||
|
[18] = http://curl.haxx.se/bug/view.cgi?id=1381
|
||||||
|
[19] = http://curl.haxx.se/mail/lib-2014-08/0236.html
|
||||||
|
[20] = https://github.com/bagder/curl/pull/115
|
||||||
|
[21] = https://github.com/bagder/curl/pull/112
|
||||||
|
[22] = http://curl.haxx.se/mail/lib-2014-06/0235.html
|
||||||
|
[23] = http://curl.haxx.se/bug/view.cgi?id=1419
|
||||||
|
[24] = http://curl.haxx.se/mail/lib-2014-07/0206.html
|
||||||
|
[25] = http://curl.haxx.se/docs/adv_20140910A.html
|
||||||
|
[26] = http://curl.haxx.se/docs/adv_20140910B.html
|
||||||
|
88
configure.ac
88
configure.ac
@@ -151,7 +151,6 @@ dnl initialize all the info variables
|
|||||||
curl_ssh_msg="no (--with-libssh2)"
|
curl_ssh_msg="no (--with-libssh2)"
|
||||||
curl_zlib_msg="no (--with-zlib)"
|
curl_zlib_msg="no (--with-zlib)"
|
||||||
curl_gss_msg="no (--with-gssapi)"
|
curl_gss_msg="no (--with-gssapi)"
|
||||||
curl_spnego_msg="no (--with-spnego)"
|
|
||||||
curl_tls_srp_msg="no (--enable-tls-srp)"
|
curl_tls_srp_msg="no (--enable-tls-srp)"
|
||||||
curl_res_msg="default (--enable-ares / --enable-threaded-resolver)"
|
curl_res_msg="default (--enable-ares / --enable-threaded-resolver)"
|
||||||
curl_ipv6_msg="no (--enable-ipv6)"
|
curl_ipv6_msg="no (--enable-ipv6)"
|
||||||
@@ -1134,41 +1133,6 @@ no)
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
dnl **********************************************************************
|
|
||||||
dnl Check for FBopenssl(SPNEGO) libraries
|
|
||||||
dnl **********************************************************************
|
|
||||||
|
|
||||||
AC_ARG_WITH(spnego,
|
|
||||||
AC_HELP_STRING([--with-spnego=DIR],
|
|
||||||
[Specify location of SPNEGO library fbopenssl]), [
|
|
||||||
SPNEGO_ROOT="$withval"
|
|
||||||
if test x"$SPNEGO_ROOT" != xno; then
|
|
||||||
want_spnego="yes"
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([if SPNEGO support is requested])
|
|
||||||
if test x"$want_spnego" = xyes; then
|
|
||||||
|
|
||||||
if test X"$SPNEGO_ROOT" = Xyes; then
|
|
||||||
AC_MSG_ERROR([FBOpenSSL libs and/or directories were not found where specified!])
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
else
|
|
||||||
if test -z "$SPNEGO_LIB_DIR"; then
|
|
||||||
LDFLAGS="$LDFLAGS -L$SPNEGO_ROOT -lfbopenssl"
|
|
||||||
else
|
|
||||||
LDFLAGS="$LDFLAGS $SPNEGO_LIB_DIR"
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
AC_DEFINE(HAVE_SPNEGO, 1,
|
|
||||||
[Define this if you have the SPNEGO library fbopenssl])
|
|
||||||
curl_spnego_msg="enabled"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl **********************************************************************
|
dnl **********************************************************************
|
||||||
dnl Check for GSS-API libraries
|
dnl Check for GSS-API libraries
|
||||||
dnl **********************************************************************
|
dnl **********************************************************************
|
||||||
@@ -1284,7 +1248,7 @@ else
|
|||||||
fi
|
fi
|
||||||
if test x"$want_gss" = xyes; then
|
if test x"$want_gss" = xyes; then
|
||||||
AC_DEFINE(HAVE_GSSAPI, 1, [if you have GSS-API libraries])
|
AC_DEFINE(HAVE_GSSAPI, 1, [if you have GSS-API libraries])
|
||||||
|
HAVE_GSSAPI=1
|
||||||
curl_gss_msg="enabled (MIT Kerberos/Heimdal)"
|
curl_gss_msg="enabled (MIT Kerberos/Heimdal)"
|
||||||
|
|
||||||
if test -n "$gnu_gss"; then
|
if test -n "$gnu_gss"; then
|
||||||
@@ -1296,12 +1260,6 @@ if test x"$want_gss" = xyes; then
|
|||||||
*-*-darwin*)
|
*-*-darwin*)
|
||||||
LIBS="-lgssapi_krb5 -lresolv $LIBS"
|
LIBS="-lgssapi_krb5 -lresolv $LIBS"
|
||||||
;;
|
;;
|
||||||
*-hp-hpux*)
|
|
||||||
if test "$GSSAPI_ROOT" != "yes"; then
|
|
||||||
LDFLAGS="$LDFLAGS -L$GSSAPI_ROOT/lib$libsuff"
|
|
||||||
fi
|
|
||||||
LIBS="-lgss $LIBS"
|
|
||||||
;;
|
|
||||||
*)
|
*)
|
||||||
if test -n "$host_alias" -a -f "$GSSAPI_ROOT/bin/$host_alias-krb5-config"; then
|
if test -n "$host_alias" -a -f "$GSSAPI_ROOT/bin/$host_alias-krb5-config"; then
|
||||||
dnl krb5-config doesn't have --libs-only-L or similar, put everything
|
dnl krb5-config doesn't have --libs-only-L or similar, put everything
|
||||||
@@ -1313,11 +1271,22 @@ if test x"$want_gss" = xyes; then
|
|||||||
dnl into LIBS
|
dnl into LIBS
|
||||||
gss_libs=`$GSSAPI_ROOT/bin/krb5-config --libs gssapi`
|
gss_libs=`$GSSAPI_ROOT/bin/krb5-config --libs gssapi`
|
||||||
LIBS="$gss_libs $LIBS"
|
LIBS="$gss_libs $LIBS"
|
||||||
elif test "$GSSAPI_ROOT" != "yes"; then
|
|
||||||
LDFLAGS="$LDFLAGS -L$GSSAPI_ROOT/lib$libsuff"
|
|
||||||
LIBS="-lgssapi $LIBS"
|
|
||||||
else
|
else
|
||||||
LIBS="-lgssapi $LIBS"
|
case $host in
|
||||||
|
*-hp-hpux*)
|
||||||
|
gss_libname="gss"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
gss_libname="gssapi"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test "$GSSAPI_ROOT" != "yes"; then
|
||||||
|
LDFLAGS="$LDFLAGS -L$GSSAPI_ROOT/lib$libsuff"
|
||||||
|
LIBS="-l$gss_libname $LIBS"
|
||||||
|
else
|
||||||
|
LIBS="-l$gss_libname $LIBS"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -2114,6 +2083,10 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
|
|||||||
if test "x$USE_NSS" = "xyes"; then
|
if test "x$USE_NSS" = "xyes"; then
|
||||||
AC_MSG_NOTICE([detected NSS version $version])
|
AC_MSG_NOTICE([detected NSS version $version])
|
||||||
|
|
||||||
|
dnl needed when linking the curl tool without USE_EXPLICIT_LIB_DEPS
|
||||||
|
NSS_LIBS=$addlib
|
||||||
|
AC_SUBST([NSS_LIBS])
|
||||||
|
|
||||||
dnl when shared libs were found in a path that the run-time
|
dnl when shared libs were found in a path that the run-time
|
||||||
dnl linker doesn't search through, we need to add it to
|
dnl linker doesn't search through, we need to add it to
|
||||||
dnl LD_LIBRARY_PATH to prevent further configure tests to fail
|
dnl LD_LIBRARY_PATH to prevent further configure tests to fail
|
||||||
@@ -2787,7 +2760,7 @@ if test X"$want_h2" != Xno; then
|
|||||||
CPPFLAGS="$CPPFLAGS $CPP_H2"
|
CPPFLAGS="$CPPFLAGS $CPP_H2"
|
||||||
LIBS="$LIB_H2 $LIBS"
|
LIBS="$LIB_H2 $LIBS"
|
||||||
|
|
||||||
AC_CHECK_LIB(nghttp2, nghttp2_session_client_new,
|
AC_CHECK_LIB(nghttp2, nghttp2_session_callbacks_set_send_callback,
|
||||||
[
|
[
|
||||||
AC_CHECK_HEADERS(nghttp2/nghttp2.h,
|
AC_CHECK_HEADERS(nghttp2/nghttp2.h,
|
||||||
curl_h2_msg="enabled (nghttp2)"
|
curl_h2_msg="enabled (nghttp2)"
|
||||||
@@ -3388,8 +3361,18 @@ fi
|
|||||||
if test "x$USE_WINDOWS_SSPI" = "x1"; then
|
if test "x$USE_WINDOWS_SSPI" = "x1"; then
|
||||||
SUPPORT_FEATURES="$SUPPORT_FEATURES SSPI"
|
SUPPORT_FEATURES="$SUPPORT_FEATURES SSPI"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "x$HAVE_GSSAPI" = "x1"; then
|
||||||
|
SUPPORT_FEATURES="$SUPPORT_FEATURES GSS-API"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$CURL_DISABLE_CRYPTO_AUTH" != "x1" -a \
|
||||||
|
\( "x$HAVE_GSSAPI" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1" \); then
|
||||||
|
SUPPORT_FEATURES="$SUPPORT_FEATURES SPNEGO"
|
||||||
|
fi
|
||||||
|
|
||||||
if test "x$CURL_DISABLE_HTTP" != "x1" -a \
|
if test "x$CURL_DISABLE_HTTP" != "x1" -a \
|
||||||
"x$CURL_DISABLE_CRYPTO_AUTH" != "x1"; then
|
"x$CURL_DISABLE_CRYPTO_AUTH" != "x1"; then
|
||||||
if test "x$USE_SSLEAY" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1" \
|
if test "x$USE_SSLEAY" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1" \
|
||||||
-o "x$GNUTLS_ENABLED" = "x1" -o "x$NSS_ENABLED" = "x1" \
|
-o "x$GNUTLS_ENABLED" = "x1" -o "x$NSS_ENABLED" = "x1" \
|
||||||
-o "x$DARWINSSL_ENABLED" = "x1"; then
|
-o "x$DARWINSSL_ENABLED" = "x1"; then
|
||||||
@@ -3406,12 +3389,6 @@ fi
|
|||||||
if test "x$USE_NGHTTP2" = "x1"; then
|
if test "x$USE_NGHTTP2" = "x1"; then
|
||||||
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
|
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
|
||||||
fi
|
fi
|
||||||
if test "x$curl_spnego_msg" = "xenabled"; then
|
|
||||||
SUPPORT_FEATURES="$SUPPORT_FEATURES SPNEGO"
|
|
||||||
fi
|
|
||||||
if test "x$want_gss" = "xyes"; then
|
|
||||||
SUPPORT_FEATURES="$SUPPORT_FEATURES GSS-API"
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_SUBST(SUPPORT_FEATURES)
|
AC_SUBST(SUPPORT_FEATURES)
|
||||||
|
|
||||||
@@ -3560,7 +3537,6 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
|
|||||||
SSH support: ${curl_ssh_msg}
|
SSH support: ${curl_ssh_msg}
|
||||||
zlib support: ${curl_zlib_msg}
|
zlib support: ${curl_zlib_msg}
|
||||||
GSS-API support: ${curl_gss_msg}
|
GSS-API support: ${curl_gss_msg}
|
||||||
SPNEGO support: ${curl_spnego_msg}
|
|
||||||
TLS-SRP support: ${curl_tls_srp_msg}
|
TLS-SRP support: ${curl_tls_srp_msg}
|
||||||
resolver: ${curl_res_msg}
|
resolver: ${curl_res_msg}
|
||||||
ipv6 support: ${curl_ipv6_msg}
|
ipv6 support: ${curl_ipv6_msg}
|
||||||
|
@@ -39,12 +39,12 @@ fi
|
|||||||
# sort all unique names
|
# sort all unique names
|
||||||
# awk them into RELEASE-NOTES format
|
# awk them into RELEASE-NOTES format
|
||||||
git log $start..HEAD | \
|
git log $start..HEAD | \
|
||||||
egrep '(Author|Commit|by):' | \
|
egrep -i '(Author|Commit|by):' | \
|
||||||
cut -d: -f2- | \
|
cut -d: -f2- | \
|
||||||
cut '-d<' -f1 | \
|
cut '-d<' -f1 | \
|
||||||
sed -e 's/^ //' -e 's/ $//g' | \
|
sed -e 's/^ //' -e 's/ $//g' | \
|
||||||
grep ' ' | \
|
grep ' ' | \
|
||||||
sort -u |
|
sort -fu |
|
||||||
awk '{
|
awk '{
|
||||||
num++;
|
num++;
|
||||||
n = sprintf("%s%s%s,", n, length(n)?" ":"", $0);
|
n = sprintf("%s%s%s,", n, length(n)?" ":"", $0);
|
||||||
|
39
docs/FAQ
39
docs/FAQ
@@ -80,6 +80,7 @@ FAQ
|
|||||||
4.17 Non-functional connect timeouts on Windows
|
4.17 Non-functional connect timeouts on Windows
|
||||||
4.18 file:// URLs containing drive letters (Windows, NetWare)
|
4.18 file:// URLs containing drive letters (Windows, NetWare)
|
||||||
4.19 Why doesn't cURL return an error when the network cable is unplugged?
|
4.19 Why doesn't cURL return an error when the network cable is unplugged?
|
||||||
|
4.20 curl doesn't return error for HTTP non-200 responses!
|
||||||
|
|
||||||
5. libcurl Issues
|
5. libcurl Issues
|
||||||
5.1 Is libcurl thread-safe?
|
5.1 Is libcurl thread-safe?
|
||||||
@@ -136,11 +137,11 @@ FAQ
|
|||||||
POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, TELNET and TFTP.
|
POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, TELNET and TFTP.
|
||||||
|
|
||||||
libcurl supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading,
|
libcurl supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading,
|
||||||
kerberos, HTTP form based upload, proxies, cookies, user+password
|
Kerberos, SPNEGO, HTTP form based upload, proxies, cookies, user+password
|
||||||
authentication, file transfer resume, http proxy tunneling and more!
|
authentication, file transfer resume, http proxy tunneling and more!
|
||||||
|
|
||||||
libcurl is highly portable, it builds and works identically on numerous
|
libcurl is highly portable, it builds and works identically on numerous
|
||||||
platforms, including Solaris, NetBSD, FreeBSD, OpenBSD, Darwin, HPUX,
|
platforms, including Solaris, NetBSD, FreeBSD, OpenBSD, Darwin, HP-UX,
|
||||||
IRIX, AIX, Tru64, Linux, UnixWare, HURD, Windows, Amiga, OS/2, BeOS, Mac
|
IRIX, AIX, Tru64, Linux, UnixWare, HURD, Windows, Amiga, OS/2, BeOS, Mac
|
||||||
OS X, Ultrix, QNX, OpenVMS, RISC OS, Novell NetWare, DOS, Symbian, OSF,
|
OS X, Ultrix, QNX, OpenVMS, RISC OS, Novell NetWare, DOS, Symbian, OSF,
|
||||||
Android, Minix, IBM TPF and more...
|
Android, Minix, IBM TPF and more...
|
||||||
@@ -238,10 +239,10 @@ FAQ
|
|||||||
1.6 What do you get for making curl?
|
1.6 What do you get for making curl?
|
||||||
|
|
||||||
Project cURL is entirely free and open. No person gets paid for developing
|
Project cURL is entirely free and open. No person gets paid for developing
|
||||||
(lib)curl on full or even part time. We do this voluntarily on our spare
|
curl on full time. We do this voluntarily, mostly on spare time.
|
||||||
time. Occasionally companies pay individual developers to work on curl, but
|
Occasionally companies pay individual developers to work on curl, but that's
|
||||||
that's up to each company and developer. It is not controlled by nor
|
up to each company and developer. It is not controlled by nor supervised in
|
||||||
supervised in any way by the project.
|
any way by the project.
|
||||||
|
|
||||||
We still get help from companies. Haxx provides web site, bandwidth, mailing
|
We still get help from companies. Haxx provides web site, bandwidth, mailing
|
||||||
lists etc, sourceforge.net hosts project services we take advantage from,
|
lists etc, sourceforge.net hosts project services we take advantage from,
|
||||||
@@ -1086,7 +1087,31 @@ FAQ
|
|||||||
immediately if its lone network connection goes down. That can be achieved
|
immediately if its lone network connection goes down. That can be achieved
|
||||||
by having the application monitor the network connection on its own using an
|
by having the application monitor the network connection on its own using an
|
||||||
OS-specific mechanism, then signalling libcurl to abort (see also item 5.13).
|
OS-specific mechanism, then signalling libcurl to abort (see also item 5.13).
|
||||||
|
|
||||||
|
4.20 curl doesn't return error for HTTP non-200 responses!
|
||||||
|
|
||||||
|
Correct. Unless you use -f (--fail).
|
||||||
|
|
||||||
|
When doing HTTP transfers, curl will perform exactly what you're asking it
|
||||||
|
to do and if successful it will not return an error. You can use curl to
|
||||||
|
test your web server's "file not found" page (that gets 404 back), you can
|
||||||
|
use it to check your authentication protected web pages (that get a 401
|
||||||
|
back) and so on.
|
||||||
|
|
||||||
|
The specific HTTP response code does not constitute a problem or error for
|
||||||
|
curl. It simply sends and delivers HTTP as you asked and if that worked,
|
||||||
|
everything is fine and dandy. The response code is generally providing more
|
||||||
|
higher level error information that curl doesn't care about. The error was
|
||||||
|
not in the HTTP transfer.
|
||||||
|
|
||||||
|
If you want your command line to treat error codes in the 400 and up range
|
||||||
|
as errors and thus return a non-zero value and possibly show an error
|
||||||
|
message, curl has a dedicated option for that: -f (CURLOPT_FAILONERROR in
|
||||||
|
libcurl speak).
|
||||||
|
|
||||||
|
You can also use the -w option and the variable %{response_code} to extract
|
||||||
|
the exact response code that was return in the response.
|
||||||
|
|
||||||
|
|
||||||
5. libcurl Issues
|
5. libcurl Issues
|
||||||
|
|
||||||
|
@@ -28,7 +28,7 @@ libcurl
|
|||||||
- selectable network interface for outgoing traffic
|
- selectable network interface for outgoing traffic
|
||||||
- IPv6 support on unix and Windows
|
- IPv6 support on unix and Windows
|
||||||
- persistent connections
|
- persistent connections
|
||||||
- socks5 support
|
- socks 4 + 5 support, with or without local name resolving
|
||||||
- supports user name and password in proxy environment variables
|
- supports user name and password in proxy environment variables
|
||||||
- operations through proxy "tunnel" (using CONNECT)
|
- operations through proxy "tunnel" (using CONNECT)
|
||||||
- support for large files (>2GB and >4GB) during upload and download
|
- support for large files (>2GB and >4GB) during upload and download
|
||||||
@@ -45,8 +45,8 @@ HTTP
|
|||||||
- POST
|
- POST
|
||||||
- Pipelining
|
- Pipelining
|
||||||
- multipart formpost (RFC1867-style)
|
- multipart formpost (RFC1867-style)
|
||||||
- authentication: Basic, Digest, NTLM (*9), GSS-Negotiate/Negotiate (*3) and
|
- authentication: Basic, Digest, NTLM (*9) and Negotiate (SPNEGO) (*3)
|
||||||
SPNEGO (*4) to server and proxy
|
to server and proxy
|
||||||
- resume (both GET and PUT)
|
- resume (both GET and PUT)
|
||||||
- follow redirects
|
- follow redirects
|
||||||
- maximum amount of redirects to follow
|
- maximum amount of redirects to follow
|
||||||
@@ -64,6 +64,7 @@ HTTP
|
|||||||
- Content-Encoding support for deflate and gzip
|
- Content-Encoding support for deflate and gzip
|
||||||
- "Transfer-Encoding: chunked" support in uploads
|
- "Transfer-Encoding: chunked" support in uploads
|
||||||
- data compression (*12)
|
- data compression (*12)
|
||||||
|
- HTTP/2 (*4)
|
||||||
|
|
||||||
HTTPS (*1)
|
HTTPS (*1)
|
||||||
- (all the HTTP features)
|
- (all the HTTP features)
|
||||||
@@ -77,7 +78,7 @@ FTP
|
|||||||
- download
|
- download
|
||||||
- authentication
|
- authentication
|
||||||
- kerberos4 (*5)
|
- kerberos4 (*5)
|
||||||
- kerberos5 (*3)
|
- Kerberos 5 (*14)
|
||||||
- active/passive using PORT, EPRT, PASV or EPSV
|
- active/passive using PORT, EPRT, PASV or EPSV
|
||||||
- single file size information (compare to HTTP HEAD)
|
- single file size information (compare to HTTP HEAD)
|
||||||
- 'type=' URL support
|
- 'type=' URL support
|
||||||
@@ -179,8 +180,9 @@ FOOTNOTES
|
|||||||
*1 = requires OpenSSL, GnuTLS, NSS, yassl, axTLS, PolarSSL, WinSSL (native
|
*1 = requires OpenSSL, GnuTLS, NSS, yassl, axTLS, PolarSSL, WinSSL (native
|
||||||
Windows), Secure Transport (native iOS/OS X) or qssl (native IBM i)
|
Windows), Secure Transport (native iOS/OS X) or qssl (native IBM i)
|
||||||
*2 = requires OpenLDAP
|
*2 = requires OpenLDAP
|
||||||
*3 = requires a GSSAPI-compliant library, such as Heimdal or similar
|
*3 = requires a GSS-API implementation (such as Heimdal or MIT Kerberos) or
|
||||||
*4 = requires FBopenssl
|
SSPI (native Windows)
|
||||||
|
*4 = requires nghttp2 and possibly a recent TLS library
|
||||||
*5 = requires a krb4 library, such as the MIT one or similar
|
*5 = requires a krb4 library, such as the MIT one or similar
|
||||||
*6 = requires c-ares
|
*6 = requires c-ares
|
||||||
*7 = requires OpenSSL, NSS, qssl, WinSSL or Secure Transport; GnuTLS, for
|
*7 = requires OpenSSL, NSS, qssl, WinSSL or Secure Transport; GnuTLS, for
|
||||||
@@ -194,3 +196,4 @@ FOOTNOTES
|
|||||||
*12 = requires libz
|
*12 = requires libz
|
||||||
*13 = requires libmetalink, and either an Apple or Microsoft operating
|
*13 = requires libmetalink, and either an Apple or Microsoft operating
|
||||||
system, or OpenSSL, or GnuTLS, or NSS
|
system, or OpenSSL, or GnuTLS, or NSS
|
||||||
|
*14 = requires a GSS-API implementation (such as Heimdal or MIT Kerberos)
|
||||||
|
253
docs/HISTORY
253
docs/HISTORY
@@ -4,23 +4,31 @@
|
|||||||
| (__| |_| | _ <| |___
|
| (__| |_| | _ <| |___
|
||||||
\___|\___/|_| \_\_____|
|
\___|\___/|_| \_\_____|
|
||||||
|
|
||||||
How cURL Became Like This
|
How cURL Became Like This
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Towards the end of 1996, Daniel Stenberg was spending time writing an IRC bot
|
||||||
Towards the end of 1996, Daniel Stenberg came up with the idea to make
|
for an Amiga related channel on EFnet. He then came up with the idea to make
|
||||||
currency-exchange calculations available to Internet Relay Chat (IRC)
|
currency-exchange calculations available to Internet Relay Chat (IRC)
|
||||||
users. All the necessary data are published on the Web; he just needed to
|
users. All the necessary data are published on the Web; he just needed to
|
||||||
automate their retrieval.
|
automate their retrieval.
|
||||||
|
|
||||||
Daniel simply adopted an existing command-line open-source tool, httpget, that
|
Daniel simply adopted an existing command-line open-source tool, httpget, that
|
||||||
Brazilian Rafael Sagula had written and recently release version 0.1 of. After
|
Brazilian Rafael Sagula had written and recently release version 0.1 of. After
|
||||||
a few minor adjustments, it did just what he needed. HttpGet 1.0 was released
|
a few minor adjustments, it did just what he needed.
|
||||||
on April 8th 1997 with brand new HTTP proxy support.
|
|
||||||
|
1997
|
||||||
|
----
|
||||||
|
|
||||||
|
HttpGet 1.0 was released on April 8th 1997 with brand new HTTP proxy support.
|
||||||
|
|
||||||
We soon found and fixed support for getting currencies over GOPHER. Once FTP
|
We soon found and fixed support for getting currencies over GOPHER. Once FTP
|
||||||
download support was added, the name of the project was changed and urlget 2.0
|
download support was added, the name of the project was changed and urlget 2.0
|
||||||
was released in August 1997. The http-only days were already passed.
|
was released in August 1997. The http-only days were already passed.
|
||||||
|
|
||||||
|
1998
|
||||||
|
----
|
||||||
|
|
||||||
The project slowly grew bigger. When upload capabilities were added and the
|
The project slowly grew bigger. When upload capabilities were added and the
|
||||||
name once again was misleading, a second name change was made and on March 20,
|
name once again was misleading, a second name change was made and on March 20,
|
||||||
1998 curl 4 was released. (The version numbering from the previous names was
|
1998 curl 4 was released. (The version numbering from the previous names was
|
||||||
@@ -33,33 +41,39 @@ was revealed to us much later.)
|
|||||||
|
|
||||||
SSL support was added, powered by the SSLeay library.
|
SSL support was added, powered by the SSLeay library.
|
||||||
|
|
||||||
August 1998, first announcement of curl on freshmeat.net.
|
August, first announcement of curl on freshmeat.net.
|
||||||
|
|
||||||
October 1998, with the curl 4.9 release and the introduction of cookie
|
October, with the curl 4.9 release and the introduction of cookie support,
|
||||||
support, curl was no longer released under the GPL license. Now we're at 4000
|
curl was no longer released under the GPL license. Now we're at 4000 lines of
|
||||||
lines of code, we switched over to the MPL license to restrict the effects of
|
code, we switched over to the MPL license to restrict the effects of
|
||||||
"copyleft".
|
"copyleft".
|
||||||
|
|
||||||
November 1998, configure script and reported successful compiles on several
|
November, configure script and reported successful compiles on several
|
||||||
major operating systems. The never-quite-understood -F option was added and
|
major operating systems. The never-quite-understood -F option was added and
|
||||||
curl could now simulate quite a lot of a browser. TELNET support was added.
|
curl could now simulate quite a lot of a browser. TELNET support was added.
|
||||||
|
|
||||||
Curl 5 was released in December 1998 and introduced the first ever curl man
|
Curl 5 was released in December 1998 and introduced the first ever curl man
|
||||||
page. People started making Linux RPM packages out of it.
|
page. People started making Linux RPM packages out of it.
|
||||||
|
|
||||||
January 1999, DICT support added.
|
1999
|
||||||
|
----
|
||||||
|
|
||||||
|
January, DICT support added.
|
||||||
|
|
||||||
OpenSSL took over where SSLeay was abandoned.
|
OpenSSL took over where SSLeay was abandoned.
|
||||||
|
|
||||||
May 1999, first Debian package.
|
May, first Debian package.
|
||||||
|
|
||||||
August 1999, LDAP:// and FILE:// support added. The curl web site gets 1300
|
August, LDAP:// and FILE:// support added. The curl web site gets 1300 visits
|
||||||
visits weekly.
|
weekly.
|
||||||
|
|
||||||
Released curl 6.0 in September. 15000 lines of code.
|
Released curl 6.0 in September. 15000 lines of code.
|
||||||
|
|
||||||
December 28 1999, added the project on Sourceforge and started using its
|
December 28, added the project on Sourceforge and started using its services
|
||||||
services for managing the project.
|
for managing the project.
|
||||||
|
|
||||||
|
2000
|
||||||
|
----
|
||||||
|
|
||||||
Spring 2000, major internal overhaul to provide a suitable library interface.
|
Spring 2000, major internal overhaul to provide a suitable library interface.
|
||||||
The first non-beta release was named 7.1 and arrived in August. This offered
|
The first non-beta release was named 7.1 and arrived in August. This offered
|
||||||
@@ -67,19 +81,22 @@ the easy interface and turned out to be the beginning of actually getting
|
|||||||
other software and programs to get based on and powered by libcurl. Almost
|
other software and programs to get based on and powered by libcurl. Almost
|
||||||
20000 lines of code.
|
20000 lines of code.
|
||||||
|
|
||||||
August 2000, the curl web site gets 4000 visits weekly.
|
August, the curl web site gets 4000 visits weekly.
|
||||||
|
|
||||||
The PHP guys adopted libcurl already the same month, when the first ever third
|
The PHP guys adopted libcurl already the same month, when the first ever third
|
||||||
party libcurl binding showed up. CURL has been a supported module in PHP since
|
party libcurl binding showed up. CURL has been a supported module in PHP since
|
||||||
the release of PHP 4.0.2. This would soon get followers. More than 16
|
the release of PHP 4.0.2. This would soon get followers. More than 16
|
||||||
different bindings exist at the time of this writing.
|
different bindings exist at the time of this writing.
|
||||||
|
|
||||||
September 2000, kerberos4 support was added.
|
September, kerberos4 support was added.
|
||||||
|
|
||||||
In November 2000 started the work on a test suite for curl. It was later
|
In November started the work on a test suite for curl. It was later re-written
|
||||||
re-written from scratch again. The libcurl major SONAME number was set to 1.
|
from scratch again. The libcurl major SONAME number was set to 1.
|
||||||
|
|
||||||
January 2001, Daniel released curl 7.5.2 under a new license again: MIT (or
|
2001
|
||||||
|
----
|
||||||
|
|
||||||
|
January, Daniel released curl 7.5.2 under a new license again: MIT (or
|
||||||
MPL). The MIT license is extremely liberal and can be used combined with GPL
|
MPL). The MIT license is extremely liberal and can be used combined with GPL
|
||||||
in other projects. This would finally put an end to the "complaints" from
|
in other projects. This would finally put an end to the "complaints" from
|
||||||
people involved in GPLed projects that previously were prohibited from using
|
people involved in GPLed projects that previously were prohibited from using
|
||||||
@@ -92,17 +109,20 @@ code. The libcurl major SONAME number was bumped to 2 due to this overhaul.
|
|||||||
|
|
||||||
The first experimental ftps:// support was added in March 2001.
|
The first experimental ftps:// support was added in March 2001.
|
||||||
|
|
||||||
August 2001. curl is bundled in Mac OS X, 10.1. It was already becoming more
|
August. curl is bundled in Mac OS X, 10.1. It was already becoming more and
|
||||||
and more of a standard utility of Linux distributions and a regular in the BSD
|
more of a standard utility of Linux distributions and a regular in the BSD
|
||||||
ports collections. The curl web site gets 8000 visits weekly. Curl Corporation
|
ports collections. The curl web site gets 8000 visits weekly. Curl Corporation
|
||||||
contacted Daniel to discuss "the name issue". After Daniel's reply, they have
|
contacted Daniel to discuss "the name issue". After Daniel's reply, they have
|
||||||
never since got in touch again.
|
never since got in touch again.
|
||||||
|
|
||||||
September 2001, libcurl 7.9 introduces cookie jar and curl_formadd(). During
|
September, libcurl 7.9 introduces cookie jar and curl_formadd(). During the
|
||||||
the forthcoming 7.9.x releases, we introduced the multi interface slowly and
|
forthcoming 7.9.x releases, we introduced the multi interface slowly and
|
||||||
without much whistles.
|
without much whistles.
|
||||||
|
|
||||||
June 2002, the curl web site gets 13000 visits weekly. curl and libcurl is
|
2002
|
||||||
|
----
|
||||||
|
|
||||||
|
June, the curl web site gets 13000 visits weekly. curl and libcurl is
|
||||||
35000 lines of code. Reported successful compiles on more than 40 combinations
|
35000 lines of code. Reported successful compiles on more than 40 combinations
|
||||||
of CPUs and operating systems.
|
of CPUs and operating systems.
|
||||||
|
|
||||||
@@ -111,134 +131,145 @@ impossible. Around 5000 downloaded packages each week from the main site gives
|
|||||||
a hint, but the packages are mirrored extensively, bundled with numerous OS
|
a hint, but the packages are mirrored extensively, bundled with numerous OS
|
||||||
distributions and otherwise retrieved as part of other software.
|
distributions and otherwise retrieved as part of other software.
|
||||||
|
|
||||||
September 2002, with the release of curl 7.10 it is released under the MIT
|
September, with the release of curl 7.10 it is released under the MIT license
|
||||||
license only.
|
only.
|
||||||
|
|
||||||
January 2003. Started working on the distributed curl tests. The autobuilds.
|
2003
|
||||||
|
----
|
||||||
|
|
||||||
February 2003, the curl site averages at 20000 visits weekly. At any given
|
January. Started working on the distributed curl tests. The autobuilds.
|
||||||
moment, there's an average of 3 people browsing the curl.haxx.se site.
|
|
||||||
|
February, the curl site averages at 20000 visits weekly. At any given moment,
|
||||||
|
there's an average of 3 people browsing the curl.haxx.se site.
|
||||||
|
|
||||||
Multiple new authentication schemes are supported: Digest (May), NTLM (June)
|
Multiple new authentication schemes are supported: Digest (May), NTLM (June)
|
||||||
and Negotiate (June).
|
and Negotiate (June).
|
||||||
|
|
||||||
November 2003: curl 7.10.8 is released. 45000 lines of code. ~55000 unique
|
November: curl 7.10.8 is released. 45000 lines of code. ~55000 unique visitors
|
||||||
visitors to the curl.haxx.se site. Five official web mirrors.
|
to the curl.haxx.se site. Five official web mirrors.
|
||||||
|
|
||||||
December 2003, full-fledged SSL for FTP is supported.
|
December, full-fledged SSL for FTP is supported.
|
||||||
|
|
||||||
January 2004: curl 7.11.0 introduced large file support.
|
2004
|
||||||
|
----
|
||||||
|
|
||||||
June 2004:
|
January: curl 7.11.0 introduced large file support.
|
||||||
|
|
||||||
curl 7.12.0 introduced IDN support. 10 official web mirrors.
|
June: curl 7.12.0 introduced IDN support. 10 official web mirrors.
|
||||||
|
|
||||||
This release bumped the major SONAME to 3 due to the removal of the
|
This release bumped the major SONAME to 3 due to the removal of the
|
||||||
curl_formparse() function
|
curl_formparse() function
|
||||||
|
|
||||||
August 2004:
|
August: Curl and libcurl 7.12.1
|
||||||
Curl and libcurl 7.12.1
|
|
||||||
|
|
||||||
Public curl release number: 82
|
Public curl release number: 82
|
||||||
Releases counted from the very beginning: 109
|
Releases counted from the very beginning: 109
|
||||||
Available command line options: 96
|
Available command line options: 96
|
||||||
Available curl_easy_setopt() options: 120
|
Available curl_easy_setopt() options: 120
|
||||||
Number of public functions in libcurl: 36
|
Number of public functions in libcurl: 36
|
||||||
Amount of public web site mirrors: 12
|
Amount of public web site mirrors: 12
|
||||||
Number of known libcurl bindings: 26
|
Number of known libcurl bindings: 26
|
||||||
|
|
||||||
April 2005:
|
2005
|
||||||
|
----
|
||||||
|
|
||||||
GnuTLS can now optionally be used for the secure layer when curl is built.
|
April. GnuTLS can now optionally be used for the secure layer when curl is
|
||||||
|
built.
|
||||||
|
|
||||||
September 2005:
|
September: TFTP support was added.
|
||||||
|
|
||||||
TFTP support was added.
|
More than 100,000 unique visitors of the curl web site. 25 mirrors.
|
||||||
|
|
||||||
More than 100,000 unique visitors of the curl web site. 25 mirrors.
|
December: security vulnerability: libcurl URL Buffer Overflow
|
||||||
|
|
||||||
December 2005:
|
2006
|
||||||
|
----
|
||||||
|
|
||||||
security vulnerability: libcurl URL Buffer Overflow
|
January. We dropped support for Gopher. We found bugs in the implementation
|
||||||
|
that turned out having been introduced years ago, so with the conclusion that
|
||||||
|
nobody had found out in all this time we removed it instead of fixing it.
|
||||||
|
|
||||||
January 2006:
|
March: security vulnerability: libcurl TFTP Packet Buffer Overflow
|
||||||
|
|
||||||
We dropped support for Gopher. We found bugs in the implementation that
|
April: Added the multi_socket() API
|
||||||
turned out having been introduced years ago, so with the conclusion that
|
|
||||||
nobody had found out in all this time we removed it instead of fixing it.
|
|
||||||
|
|
||||||
March 2006:
|
September: The major SONAME number for libcurl was bumped to 4 due to the
|
||||||
|
removal of ftp third party transfer support.
|
||||||
|
|
||||||
security vulnerability: libcurl TFTP Packet Buffer Overflow
|
November: Added SCP and SFTP support
|
||||||
|
|
||||||
April 2006:
|
2007
|
||||||
|
----
|
||||||
|
|
||||||
Added the multi_socket() API
|
February: Added support for the Mozilla NSS library to do the SSL/TLS stuff
|
||||||
|
|
||||||
September 2006:
|
July: security vulnerability: libcurl GnuTLS insufficient cert verification
|
||||||
|
|
||||||
The major SONAME number for libcurl was bumped to 4 due to the removal of
|
2008
|
||||||
ftp third party transfer support.
|
----
|
||||||
|
|
||||||
November 2006:
|
November:
|
||||||
|
|
||||||
Added SCP and SFTP support
|
Command line options: 128
|
||||||
|
curl_easy_setopt() options: 158
|
||||||
February 2007:
|
Public functions in libcurl: 58
|
||||||
|
Known libcurl bindings: 37
|
||||||
Added support for the Mozilla NSS library to do the SSL/TLS stuff
|
Contributors: 683
|
||||||
|
|
||||||
July 2007:
|
|
||||||
|
|
||||||
security vulnerability: libcurl GnuTLS insufficient cert verification
|
|
||||||
|
|
||||||
November 2008:
|
|
||||||
|
|
||||||
Command line options: 128
|
|
||||||
curl_easy_setopt() options: 158
|
|
||||||
Public functions in libcurl: 58
|
|
||||||
Known libcurl bindings: 37
|
|
||||||
Contributors: 683
|
|
||||||
|
|
||||||
145,000 unique visitors. >100 GB downloaded.
|
145,000 unique visitors. >100 GB downloaded.
|
||||||
|
|
||||||
March 2009:
|
2009
|
||||||
|
----
|
||||||
|
|
||||||
security vulnerability: libcurl Arbitrary File Access
|
March: security vulnerability: libcurl Arbitrary File Access
|
||||||
|
|
||||||
August 2009:
|
August: security vulnerability: libcurl embedded zero in cert name
|
||||||
|
|
||||||
security vulnerability: libcurl embedded zero in cert name
|
December: Added support for IMAP, POP3 and SMTP
|
||||||
|
|
||||||
December 2009:
|
2010
|
||||||
|
----
|
||||||
|
|
||||||
Added support for IMAP, POP3 and SMTP
|
January: Added support for RTSP
|
||||||
|
|
||||||
January 2010:
|
February: security vulnerability: libcurl data callback excessive length
|
||||||
|
|
||||||
Added support for RTSP
|
March: The project switched over to use git (hosted by github) instead of CVS
|
||||||
|
for source code control
|
||||||
|
|
||||||
February 2010:
|
May: Added support for RTMP
|
||||||
|
|
||||||
security vulnerability: libcurl data callback excessive length
|
Added support for PolarSSL to do the SSL/TLS stuff
|
||||||
|
|
||||||
March 2010:
|
August:
|
||||||
|
|
||||||
The project switched over to use git instead of CVS for source code control
|
Public curl releases: 117
|
||||||
|
Command line options: 138
|
||||||
May 2010:
|
curl_easy_setopt() options: 180
|
||||||
|
Public functions in libcurl: 58
|
||||||
Added support for RTMP
|
Known libcurl bindings: 39
|
||||||
|
Contributors: 808
|
||||||
Added support for PolarSSL to do the SSL/TLS stuff
|
|
||||||
|
|
||||||
August 2010:
|
|
||||||
|
|
||||||
Public curl releases: 117
|
|
||||||
Command line options: 138
|
|
||||||
curl_easy_setopt() options: 180
|
|
||||||
Public functions in libcurl: 58
|
|
||||||
Known libcurl bindings: 39
|
|
||||||
Contributors: 808
|
|
||||||
|
|
||||||
Gopher support added (re-added actually)
|
Gopher support added (re-added actually)
|
||||||
|
|
||||||
|
2012
|
||||||
|
----
|
||||||
|
|
||||||
|
July: Added support for Schannel (native Windows TLS backend) and Darwin SSL
|
||||||
|
(Native Mac OS X and iOS TLS backend).
|
||||||
|
|
||||||
|
Supports metalink
|
||||||
|
|
||||||
|
October: SSH-agent support.
|
||||||
|
|
||||||
|
2013
|
||||||
|
----
|
||||||
|
|
||||||
|
February: Cleaned up internals to always uses the "multi" non-blocking
|
||||||
|
approach internally and only expose the blocking API with a wrapper.
|
||||||
|
|
||||||
|
September: First small steps on supporting HTTP/2 with nghttp2.
|
||||||
|
|
||||||
|
October: Removed krb4 support.
|
||||||
|
|
||||||
|
December: Happy eyeballs.
|
||||||
|
@@ -47,6 +47,7 @@ Portability
|
|||||||
axTLS 1.2.7
|
axTLS 1.2.7
|
||||||
PolarSSL 1.3.0
|
PolarSSL 1.3.0
|
||||||
Heimdal ?
|
Heimdal ?
|
||||||
|
nghttp2 0.6.0
|
||||||
|
|
||||||
On systems where configure runs, we aim at working on them all - if they have
|
On systems where configure runs, we aim at working on them all - if they have
|
||||||
a suitable C compiler. On systems that don't run configure, we strive to keep
|
a suitable C compiler. On systems that don't run configure, we strive to keep
|
||||||
|
@@ -51,10 +51,6 @@ may have been fixed since this was written!
|
|||||||
any file at all. Like when using FTP.
|
any file at all. Like when using FTP.
|
||||||
http://curl.haxx.se/bug/view.cgi?id=1063
|
http://curl.haxx.se/bug/view.cgi?id=1063
|
||||||
|
|
||||||
77. CURLOPT_FORBID_REUSE on a handle prevents NTLM from working since it
|
|
||||||
"abuses" the underlying connection re-use system and if connections are
|
|
||||||
forced to close they break the NTLM support.
|
|
||||||
|
|
||||||
76. The SOCKET type in Win64 is 64 bits large (and thus so is curl_socket_t on
|
76. The SOCKET type in Win64 is 64 bits large (and thus so is curl_socket_t on
|
||||||
that platform), and long is only 32 bits. It makes it impossible for
|
that platform), and long is only 32 bits. It makes it impossible for
|
||||||
curl_easy_getinfo() to return a socket properly with the CURLINFO_LASTSOCKET
|
curl_easy_getinfo() to return a socket properly with the CURLINFO_LASTSOCKET
|
||||||
@@ -216,9 +212,9 @@ may have been fixed since this was written!
|
|||||||
acknowledged after the actual TCP connect (during the SOCKS "negotiate"
|
acknowledged after the actual TCP connect (during the SOCKS "negotiate"
|
||||||
phase).
|
phase).
|
||||||
|
|
||||||
10. To get HTTP Negotiate authentication to work fine, you need to provide a
|
10. To get HTTP Negotiate (SPNEGO) authentication to work fine, you need to
|
||||||
(fake) user name (this concerns both curl and the lib) because the code
|
provide a (fake) user name (this concerns both curl and the lib) because the
|
||||||
wrongly only considers authentication if there's a user name provided.
|
code wrongly only considers authentication if there's a user name provided.
|
||||||
http://curl.haxx.se/bug/view.cgi?id=440 How?
|
http://curl.haxx.se/bug/view.cgi?id=440 How?
|
||||||
http://curl.haxx.se/mail/lib-2004-08/0182.html
|
http://curl.haxx.se/mail/lib-2004-08/0182.html
|
||||||
|
|
||||||
|
@@ -94,12 +94,6 @@ GNU GSS http://www.gnu.org/software/gss/
|
|||||||
may not distribute binary curl packages that uses this if you build
|
may not distribute binary curl packages that uses this if you build
|
||||||
curl to also link and use any Original BSD licensed libraries!
|
curl to also link and use any Original BSD licensed libraries!
|
||||||
|
|
||||||
fbopenssl
|
|
||||||
|
|
||||||
(Used for SPNEGO support) Unclear license. Based on its name, I assume
|
|
||||||
that it uses the OpenSSL license and thus shares the same issues as
|
|
||||||
described for OpenSSL above.
|
|
||||||
|
|
||||||
libidn http://josefsson.org/libidn/
|
libidn http://josefsson.org/libidn/
|
||||||
|
|
||||||
(Used for IDNA support) Uses the GNU Lesser General Public
|
(Used for IDNA support) Uses the GNU Lesser General Public
|
||||||
|
@@ -14,6 +14,7 @@ MAIL ETIQUETTE
|
|||||||
1.5 Moderation of new posters
|
1.5 Moderation of new posters
|
||||||
1.6 Handling trolls and spam
|
1.6 Handling trolls and spam
|
||||||
1.7 How to unsubscribe
|
1.7 How to unsubscribe
|
||||||
|
1.8 I posted, now what?
|
||||||
|
|
||||||
2. Sending mail
|
2. Sending mail
|
||||||
2.1 Reply or New Mail
|
2.1 Reply or New Mail
|
||||||
@@ -125,6 +126,42 @@ MAIL ETIQUETTE
|
|||||||
You NEVER EVER email the mailing list requesting someone else to get you off
|
You NEVER EVER email the mailing list requesting someone else to get you off
|
||||||
the list.
|
the list.
|
||||||
|
|
||||||
|
1.8 I posted, now what?
|
||||||
|
|
||||||
|
If you aren't subscribed with the exact same email address that you used to
|
||||||
|
send the email, your post will just be silently discarded.
|
||||||
|
|
||||||
|
If you posted for the first time to the mailing list, you first need to wait
|
||||||
|
for an administrator to allow your email to go through. This normally
|
||||||
|
happens very quickly but in case we're asleep, you may have to wait a few
|
||||||
|
hours.
|
||||||
|
|
||||||
|
Once your email goes through it is sent out to several hundred or even
|
||||||
|
thousand recipients. Your email may cover an area that not that many people
|
||||||
|
know about or are interested in. Or possibly the person who knows about it
|
||||||
|
is on vacation or under a very heavy work load right now. You have to wait
|
||||||
|
for a response and you must not expect to get a response at all, but
|
||||||
|
hopefully you get an answer within a couple of days.
|
||||||
|
|
||||||
|
You do yourself and all of us a service when you include as many details as
|
||||||
|
possible already in your first email. Mention your operating system and
|
||||||
|
environment. Tell us which curl version you're using and tell us what you
|
||||||
|
did, what happened and what you expected would happen. Preferably, show us
|
||||||
|
what you did in details enough to allow others to help point out the problem
|
||||||
|
or repeat the same steps in their places.
|
||||||
|
|
||||||
|
Failing to include details will only delay responses and make people respond
|
||||||
|
and ask for the details and you have to send a follow-up email that includes
|
||||||
|
them.
|
||||||
|
|
||||||
|
Expect the responses to primarily help YOU debug the issue, or ask you
|
||||||
|
questions that can lead you or others towards a solution or explanation to
|
||||||
|
whatever you experience.
|
||||||
|
|
||||||
|
If you are a repeat offender to the guidelines outlined in this document,
|
||||||
|
chances are that people will ignore you at will and your chances to get
|
||||||
|
responses will greatly diminish.
|
||||||
|
|
||||||
|
|
||||||
2. Sending mail
|
2. Sending mail
|
||||||
|
|
||||||
|
@@ -108,10 +108,10 @@ USING PASSWORDS
|
|||||||
curl -u name:passwd http://machine.domain/full/path/to/file
|
curl -u name:passwd http://machine.domain/full/path/to/file
|
||||||
|
|
||||||
HTTP offers many different methods of authentication and curl supports
|
HTTP offers many different methods of authentication and curl supports
|
||||||
several: Basic, Digest, NTLM and Negotiate. Without telling which method to
|
several: Basic, Digest, NTLM and Negotiate (SPNEGO). Without telling which
|
||||||
use, curl defaults to Basic. You can also ask curl to pick the most secure
|
method to use, curl defaults to Basic. You can also ask curl to pick the
|
||||||
ones out of the ones that the server accepts for the given URL, by using
|
most secure ones out of the ones that the server accepts for the given URL,
|
||||||
--anyauth.
|
by using --anyauth.
|
||||||
|
|
||||||
NOTE! According to the URL specification, HTTP URLs can not contain a user
|
NOTE! According to the URL specification, HTTP URLs can not contain a user
|
||||||
and password, so that style will not work when using curl via a proxy, even
|
and password, so that style will not work when using curl via a proxy, even
|
||||||
|
@@ -89,3 +89,15 @@ announcement.
|
|||||||
mentioned.
|
mentioned.
|
||||||
|
|
||||||
[1] = http://oss-security.openwall.org/wiki/mailing-lists/distros
|
[1] = http://oss-security.openwall.org/wiki/mailing-lists/distros
|
||||||
|
|
||||||
|
CURL-SECURITY (at haxx dot se)
|
||||||
|
|
||||||
|
Who is on this list? There are a couple of criteria you must meet, and then we
|
||||||
|
might ask you to join the list or you can ask to join it. It really isn't very
|
||||||
|
formal. We basically only require that you have a long-term presence in the
|
||||||
|
curl project and you have shown an understanding for the project and its way
|
||||||
|
of working. You must've been around for a good while and you should have no
|
||||||
|
plans in vanishing in the near future.
|
||||||
|
|
||||||
|
We do not make the list of partipants public mostly because it tends to vary
|
||||||
|
somewhat over time and a list somewhere will only risk getting outdated.
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
Peer SSL Certificate Verification
|
Peer SSL Certificate Verification
|
||||||
=================================
|
=================================
|
||||||
|
|
||||||
(NOTE: If libcurl was built with Schannel or Secure Transport support, then
|
(NOTE: If libcurl was built with Schannel or Secure Transport support, then
|
||||||
this does not apply to you. Scroll down for details on how the OS-native
|
this does not apply to you. Scroll down for details on how the OS-native
|
||||||
@@ -26,13 +26,13 @@ impersonating your favorite site, and you want to transfer files from this
|
|||||||
server, do one of the following:
|
server, do one of the following:
|
||||||
|
|
||||||
1. Tell libcurl to *not* verify the peer. With libcurl you disable this with
|
1. Tell libcurl to *not* verify the peer. With libcurl you disable this with
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
|
`curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);`
|
||||||
|
|
||||||
With the curl command line tool, you disable this with -k/--insecure.
|
With the curl command line tool, you disable this with -k/--insecure.
|
||||||
|
|
||||||
2. Get a CA certificate that can verify the remote server and use the proper
|
2. Get a CA certificate that can verify the remote server and use the proper
|
||||||
option to point out this CA cert for verification when connecting. For
|
option to point out this CA cert for verification when connecting. For
|
||||||
libcurl hackers: curl_easy_setopt(curl, CURLOPT_CAPATH, capath);
|
libcurl hackers: `curl_easy_setopt(curl, CURLOPT_CAPATH, capath);`
|
||||||
|
|
||||||
With the curl command line tool: --cacert [file]
|
With the curl command line tool: --cacert [file]
|
||||||
|
|
||||||
@@ -46,32 +46,32 @@ server, do one of the following:
|
|||||||
If you use Internet Explorer, this is one way to get extract the CA cert
|
If you use Internet Explorer, this is one way to get extract the CA cert
|
||||||
for a particular server:
|
for a particular server:
|
||||||
|
|
||||||
o View the certificate by double-clicking the padlock
|
- View the certificate by double-clicking the padlock
|
||||||
o Find out where the CA certificate is kept (Certificate>
|
- Find out where the CA certificate is kept (Certificate>
|
||||||
Authority Information Access>URL)
|
Authority Information Access>URL)
|
||||||
o Get a copy of the crt file using curl
|
- Get a copy of the crt file using curl
|
||||||
o Convert it from crt to PEM using the openssl tool:
|
- Convert it from crt to PEM using the openssl tool:
|
||||||
openssl x509 -inform DES -in yourdownloaded.crt \
|
openssl x509 -inform DES -in yourdownloaded.crt \
|
||||||
-out outcert.pem -text
|
-out outcert.pem -text
|
||||||
o Append the 'outcert.pem' to the CA cert bundle or use it stand-alone
|
- Append the 'outcert.pem' to the CA cert bundle or use it stand-alone
|
||||||
as described below.
|
as described below.
|
||||||
|
|
||||||
If you use the 'openssl' tool, this is one way to get extract the CA cert
|
If you use the 'openssl' tool, this is one way to get extract the CA cert
|
||||||
for a particular server:
|
for a particular server:
|
||||||
|
|
||||||
o openssl s_client -connect xxxxx.com:443 |tee logfile
|
- `openssl s_client -connect xxxxx.com:443 |tee logfile`
|
||||||
o type "QUIT", followed by the "ENTER" key
|
- type "QUIT", followed by the "ENTER" key
|
||||||
o The certificate will have "BEGIN CERTIFICATE" and "END CERTIFICATE"
|
- The certificate will have "BEGIN CERTIFICATE" and "END CERTIFICATE"
|
||||||
markers.
|
markers.
|
||||||
o If you want to see the data in the certificate, you can do: "openssl
|
- If you want to see the data in the certificate, you can do: "openssl
|
||||||
x509 -inform PEM -in certfile -text -out certdata" where certfile is
|
x509 -inform PEM -in certfile -text -out certdata" where certfile is
|
||||||
the cert you extracted from logfile. Look in certdata.
|
the cert you extracted from logfile. Look in certdata.
|
||||||
o If you want to trust the certificate, you can append it to your
|
- If you want to trust the certificate, you can append it to your
|
||||||
cert_bundle or use it stand-alone as described. Just remember that the
|
cert bundle or use it stand-alone as described. Just remember that the
|
||||||
security is no better than the way you obtained the certificate.
|
security is no better than the way you obtained the certificate.
|
||||||
|
|
||||||
4. If you're using the curl command line tool, you can specify your own CA
|
4. If you're using the curl command line tool, you can specify your own CA
|
||||||
cert path by setting the environment variable CURL_CA_BUNDLE to the path
|
cert path by setting the environment variable `CURL_CA_BUNDLE` to the path
|
||||||
of your choice.
|
of your choice.
|
||||||
|
|
||||||
If you're using the curl command line tool on Windows, curl will search
|
If you're using the curl command line tool on Windows, curl will search
|
||||||
@@ -86,9 +86,7 @@ server, do one of the following:
|
|||||||
5. Get a better/different/newer CA cert bundle! One option is to extract the
|
5. Get a better/different/newer CA cert bundle! One option is to extract the
|
||||||
one a recent Firefox browser uses by running 'make ca-bundle' in the curl
|
one a recent Firefox browser uses by running 'make ca-bundle' in the curl
|
||||||
build tree root, or possibly download a version that was generated this
|
build tree root, or possibly download a version that was generated this
|
||||||
way for you:
|
way for you: [CA Extract](http://curl.haxx.se/docs/caextract.html)
|
||||||
|
|
||||||
http://curl.haxx.se/docs/caextract.html
|
|
||||||
|
|
||||||
Neglecting to use one of the above methods when dealing with a server using a
|
Neglecting to use one of the above methods when dealing with a server using a
|
||||||
certificate that isn't signed by one of the certificates in the installed CA
|
certificate that isn't signed by one of the certificates in the installed CA
|
||||||
@@ -96,32 +94,26 @@ cert bundle, will cause SSL to report an error ("certificate verify failed")
|
|||||||
during the handshake and SSL will then refuse further communication with that
|
during the handshake and SSL will then refuse further communication with that
|
||||||
server.
|
server.
|
||||||
|
|
||||||
Peer SSL Certificate Verification with NSS
|
Peer SSL Certificate Verification with NSS
|
||||||
==========================================
|
==========================================
|
||||||
|
|
||||||
If libcurl was built with NSS support, then depending on the OS distribution,
|
If libcurl was built with NSS support, then depending on the OS distribution,
|
||||||
it is probably required to take some additional steps to use the system-wide CA
|
it is probably required to take some additional steps to use the system-wide CA
|
||||||
cert db. RedHat ships with an additional module, libnsspem.so, which enables
|
cert db. RedHat ships with an additional module, libnsspem.so, which enables
|
||||||
NSS to read the OpenSSL PEM CA bundle. This library is missing in OpenSuSE, and
|
NSS to read the OpenSSL PEM CA bundle. This library is missing in OpenSuSE, and
|
||||||
without it, NSS can only work with its own internal formats. NSS also has a new
|
without it, NSS can only work with its own internal formats. NSS also has a new
|
||||||
database format: https://wiki.mozilla.org/NSS_Shared_DB
|
[database format](https://wiki.mozilla.org/NSS_Shared_DB).
|
||||||
|
|
||||||
Starting with version 7.19.7, libcurl will check for the NSS version it runs,
|
Starting with version 7.19.7, libcurl automatically adds the 'sql:' prefix to
|
||||||
and automatically add the 'sql:' prefix to the certdb directory (either the
|
the certdb directory (either the hardcoded default /etc/pki/nssdb or the
|
||||||
hardcoded default /etc/pki/nssdb or the directory configured with SSL_DIR
|
directory configured with SSL_DIR environment variable). To check which certdb
|
||||||
environment variable) if version 3.12.0 or later is detected. To check which
|
format your distribution provides, examine the default certdb location:
|
||||||
certdb format your distribution provides, examine the default
|
/etc/pki/nssdb; the new certdb format can be identified by the filenames
|
||||||
certdb location: /etc/pki/nssdb; the new certdb format can be identified by
|
cert9.db, key4.db, pkcs11.txt; filenames of older versions are cert8.db,
|
||||||
the filenames cert9.db, key4.db, pkcs11.txt; filenames of older versions are
|
key3.db, secmod.db.
|
||||||
cert8.db, key3.db, modsec.db.
|
|
||||||
|
|
||||||
Usually these cert databases are empty, but NSS also has built-in CAs which are
|
Peer SSL Certificate Verification with Schannel and Secure Transport
|
||||||
provided through a shared library, libnssckbi.so; if you want to use these
|
====================================================================
|
||||||
built-in CAs, then create a symlink to libnssckbi.so in /etc/pki/nssdb:
|
|
||||||
ln -s /usr/lib[64]/libnssckbi.so /etc/pki/nssdb/libnssckbi.so
|
|
||||||
|
|
||||||
Peer SSL Certificate Verification with Schannel and Secure Transport
|
|
||||||
====================================================================
|
|
||||||
|
|
||||||
If libcurl was built with Schannel (Microsoft's TLS/SSL engine) or Secure
|
If libcurl was built with Schannel (Microsoft's TLS/SSL engine) or Secure
|
||||||
Transport (Apple's TLS/SSL engine) support, then libcurl will still perform
|
Transport (Apple's TLS/SSL engine) support, then libcurl will still perform
|
||||||
|
74
docs/THANKS
74
docs/THANKS
@@ -22,7 +22,7 @@ Alan Pinstein
|
|||||||
Albert Chin-A-Young
|
Albert Chin-A-Young
|
||||||
Albert Choy
|
Albert Choy
|
||||||
Ale Vesely
|
Ale Vesely
|
||||||
Alejandro Alvarez
|
Alejandro Alvarez Ayllon
|
||||||
Aleksandar Milivojevic
|
Aleksandar Milivojevic
|
||||||
Aleksey Tulinov
|
Aleksey Tulinov
|
||||||
Alessandro Ghedini
|
Alessandro Ghedini
|
||||||
@@ -48,6 +48,7 @@ Alexey Zakhlestin
|
|||||||
Alexis Carvalho
|
Alexis Carvalho
|
||||||
Alfred Gebert
|
Alfred Gebert
|
||||||
Allen Pulsifer
|
Allen Pulsifer
|
||||||
|
Alona Rossen
|
||||||
Amol Pattekar
|
Amol Pattekar
|
||||||
Amr Shahin
|
Amr Shahin
|
||||||
Anatoli Tubman
|
Anatoli Tubman
|
||||||
@@ -55,6 +56,7 @@ Anders Gustafsson
|
|||||||
Anders Havn
|
Anders Havn
|
||||||
Andi Jahja
|
Andi Jahja
|
||||||
Andre Guibert de Bruet
|
Andre Guibert de Bruet
|
||||||
|
Andre Heinecke
|
||||||
Andreas Damm
|
Andreas Damm
|
||||||
Andreas Faerber
|
Andreas Faerber
|
||||||
Andreas Farber
|
Andreas Farber
|
||||||
@@ -66,6 +68,7 @@ Andreas Schuldei
|
|||||||
Andreas Wurf
|
Andreas Wurf
|
||||||
Andrei Benea
|
Andrei Benea
|
||||||
Andrei Cipu
|
Andrei Cipu
|
||||||
|
Andrei Kurushin
|
||||||
Andrej E Baranov
|
Andrej E Baranov
|
||||||
Andres Garcia
|
Andres Garcia
|
||||||
Andrew Benham
|
Andrew Benham
|
||||||
@@ -83,6 +86,7 @@ Andy Cedilnik
|
|||||||
Andy Serpa
|
Andy Serpa
|
||||||
Andy Tsouladze
|
Andy Tsouladze
|
||||||
Angus Mackay
|
Angus Mackay
|
||||||
|
Anthon Pang
|
||||||
Anthony Bryan
|
Anthony Bryan
|
||||||
Anthony G. Basile
|
Anthony G. Basile
|
||||||
Antoine Calando
|
Antoine Calando
|
||||||
@@ -97,6 +101,8 @@ Arnaud Ebalard
|
|||||||
Arthur Murray
|
Arthur Murray
|
||||||
Arve Knudsen
|
Arve Knudsen
|
||||||
Arvid Norberg
|
Arvid Norberg
|
||||||
|
Ask Bjørn Hansen
|
||||||
|
Askar Safin
|
||||||
Ates Goral
|
Ates Goral
|
||||||
Augustus Saunders
|
Augustus Saunders
|
||||||
Avery Fay
|
Avery Fay
|
||||||
@@ -116,6 +122,7 @@ Benbuck Nason
|
|||||||
Benjamin Gerard
|
Benjamin Gerard
|
||||||
Benjamin Gilbert
|
Benjamin Gilbert
|
||||||
Benjamin Johnson
|
Benjamin Johnson
|
||||||
|
Benoit Neil
|
||||||
Benoit Sigoure
|
Benoit Sigoure
|
||||||
Bernard Leak
|
Bernard Leak
|
||||||
Bernhard Reutner-Fischer
|
Bernhard Reutner-Fischer
|
||||||
@@ -138,6 +145,7 @@ Brad Hards
|
|||||||
Brad King
|
Brad King
|
||||||
Brad Spencer
|
Brad Spencer
|
||||||
Bradford Bruce
|
Bradford Bruce
|
||||||
|
Brandon Casey
|
||||||
Brandon Wang
|
Brandon Wang
|
||||||
Brendan Jurd
|
Brendan Jurd
|
||||||
Brent Beardsley
|
Brent Beardsley
|
||||||
@@ -157,6 +165,7 @@ Camille Moncelier
|
|||||||
Caolan McNamara
|
Caolan McNamara
|
||||||
Carsten Lange
|
Carsten Lange
|
||||||
Casey O'Donnell
|
Casey O'Donnell
|
||||||
|
Catalin Patulea
|
||||||
Cedric Deltheil
|
Cedric Deltheil
|
||||||
Chad Monroe
|
Chad Monroe
|
||||||
Chandrakant Bagul
|
Chandrakant Bagul
|
||||||
@@ -173,6 +182,7 @@ Chris Gaukroger
|
|||||||
Chris Maltby
|
Chris Maltby
|
||||||
Chris Mumford
|
Chris Mumford
|
||||||
Chris Smowton
|
Chris Smowton
|
||||||
|
Chris Young
|
||||||
Christian Grothoff
|
Christian Grothoff
|
||||||
Christian Hägele
|
Christian Hägele
|
||||||
Christian Krause
|
Christian Krause
|
||||||
@@ -195,6 +205,7 @@ Clifford Wolf
|
|||||||
Cody Jones
|
Cody Jones
|
||||||
Cody Mack
|
Cody Mack
|
||||||
Colby Ranger
|
Colby Ranger
|
||||||
|
Colin Blair
|
||||||
Colin Hogben
|
Colin Hogben
|
||||||
Colin Watson
|
Colin Watson
|
||||||
Colm Buckley
|
Colm Buckley
|
||||||
@@ -254,6 +265,7 @@ David Kimdon
|
|||||||
David Lang
|
David Lang
|
||||||
David LeBlanc
|
David LeBlanc
|
||||||
David McCreedy
|
David McCreedy
|
||||||
|
David Meyer
|
||||||
David Odin
|
David Odin
|
||||||
David Phillips
|
David Phillips
|
||||||
David Rosenstrauch
|
David Rosenstrauch
|
||||||
@@ -267,6 +279,7 @@ David Woodhouse
|
|||||||
David Wright
|
David Wright
|
||||||
David Yan
|
David Yan
|
||||||
Dengminwen
|
Dengminwen
|
||||||
|
Dennis Clarke
|
||||||
Derek Higgins
|
Derek Higgins
|
||||||
Detlef Schmier
|
Detlef Schmier
|
||||||
Didier Brisebourg
|
Didier Brisebourg
|
||||||
@@ -275,6 +288,7 @@ Dilyan Palauzov
|
|||||||
Dima Barsky
|
Dima Barsky
|
||||||
Dima Tisnek
|
Dima Tisnek
|
||||||
Dimitre Dimitrov
|
Dimitre Dimitrov
|
||||||
|
Dimitrios Siganos
|
||||||
Dimitris Sarris
|
Dimitris Sarris
|
||||||
Dinar
|
Dinar
|
||||||
Dirk Eddelbuettel
|
Dirk Eddelbuettel
|
||||||
@@ -282,6 +296,7 @@ Dirk Manske
|
|||||||
Dmitri Shubin
|
Dmitri Shubin
|
||||||
Dmitriy Sergeyev
|
Dmitriy Sergeyev
|
||||||
Dmitry Bartsevich
|
Dmitry Bartsevich
|
||||||
|
Dmitry Falko
|
||||||
Dmitry Kurochkin
|
Dmitry Kurochkin
|
||||||
Dmitry Popov
|
Dmitry Popov
|
||||||
Dmitry Rechkin
|
Dmitry Rechkin
|
||||||
@@ -297,13 +312,13 @@ Douglas R. Horner
|
|||||||
Douglas Steinwand
|
Douglas Steinwand
|
||||||
Dov Murik
|
Dov Murik
|
||||||
Duane Cathey
|
Duane Cathey
|
||||||
Duncan
|
|
||||||
Duncan Mac-Vicar Prett
|
Duncan Mac-Vicar Prett
|
||||||
Dustin Boswell
|
Dustin Boswell
|
||||||
Dylan Ellicott
|
Dylan Ellicott
|
||||||
Dylan Salisbury
|
Dylan Salisbury
|
||||||
Early Ehlinger
|
Early Ehlinger
|
||||||
Ebenezer Ikonne
|
Ebenezer Ikonne
|
||||||
|
Ed Morley
|
||||||
Edin Kadribasic
|
Edin Kadribasic
|
||||||
Eduard Bloch
|
Eduard Bloch
|
||||||
Edward Rudd
|
Edward Rudd
|
||||||
@@ -333,8 +348,10 @@ Eric Wong
|
|||||||
Eric Young
|
Eric Young
|
||||||
Erick Nuwendam
|
Erick Nuwendam
|
||||||
Erik Johansson
|
Erik Johansson
|
||||||
|
Ernest Beinrohr
|
||||||
Erwan Legrand
|
Erwan Legrand
|
||||||
Erwin Authried
|
Erwin Authried
|
||||||
|
Ethan Glasser Camp
|
||||||
Eugene Kotlyarov
|
Eugene Kotlyarov
|
||||||
Evan Jordan
|
Evan Jordan
|
||||||
Evgeny Turnaev
|
Evgeny Turnaev
|
||||||
@@ -348,6 +365,7 @@ Felix Yan
|
|||||||
Felix von Leitner
|
Felix von Leitner
|
||||||
Feng Tu
|
Feng Tu
|
||||||
Florian Schoppmann
|
Florian Schoppmann
|
||||||
|
Florian Weimer
|
||||||
Forrest Cahoon
|
Forrest Cahoon
|
||||||
Francois Charlier
|
Francois Charlier
|
||||||
Frank Hempel
|
Frank Hempel
|
||||||
@@ -357,6 +375,7 @@ Frank Meier
|
|||||||
Frank Ticheler
|
Frank Ticheler
|
||||||
Frank Van Uffelen
|
Frank Van Uffelen
|
||||||
František Kučera
|
František Kučera
|
||||||
|
François Charlier
|
||||||
Fred Machado
|
Fred Machado
|
||||||
Fred New
|
Fred New
|
||||||
Fred Noz
|
Fred Noz
|
||||||
@@ -390,6 +409,7 @@ Gilles Blanc
|
|||||||
Gisle Vanem
|
Gisle Vanem
|
||||||
Giuseppe Attardi
|
Giuseppe Attardi
|
||||||
Giuseppe D'Ambrosio
|
Giuseppe D'Ambrosio
|
||||||
|
Glen A Johnson Jr.
|
||||||
Glen Nakamura
|
Glen Nakamura
|
||||||
Glen Scott
|
Glen Scott
|
||||||
Glenn Sheridan
|
Glenn Sheridan
|
||||||
@@ -400,14 +420,17 @@ Grant Erickson
|
|||||||
Greg Hewgill
|
Greg Hewgill
|
||||||
Greg Morse
|
Greg Morse
|
||||||
Greg Onufer
|
Greg Onufer
|
||||||
|
Greg Pratt
|
||||||
Greg Zavertnik
|
Greg Zavertnik
|
||||||
Grigory Entin
|
Grigory Entin
|
||||||
Guenole Bescon
|
Guenole Bescon
|
||||||
Guenter Knauf
|
Guenter Knauf
|
||||||
Guido Berhoerster
|
Guido Berhoerster
|
||||||
Guillaume Arluison
|
Guillaume Arluison
|
||||||
|
Gunter Knauf
|
||||||
Gustaf Hui
|
Gustaf Hui
|
||||||
Gwenole Beauchesne
|
Gwenole Beauchesne
|
||||||
|
Gökhan Şengün
|
||||||
Götz Babin-Ebell
|
Götz Babin-Ebell
|
||||||
Hamish Mackenzie
|
Hamish Mackenzie
|
||||||
Hang Kin Lau
|
Hang Kin Lau
|
||||||
@@ -416,12 +439,14 @@ Hanno Kranzhoff
|
|||||||
Hans Steegers
|
Hans Steegers
|
||||||
Hans-Jurgen May
|
Hans-Jurgen May
|
||||||
Hardeep Singh
|
Hardeep Singh
|
||||||
|
Haris Okanovic
|
||||||
Harshal Pradhan
|
Harshal Pradhan
|
||||||
Hauke Duden
|
Hauke Duden
|
||||||
He Qin
|
He Qin
|
||||||
Heikki Korpela
|
Heikki Korpela
|
||||||
Heinrich Ko
|
Heinrich Ko
|
||||||
Heinrich Schaefer
|
Heinrich Schaefer
|
||||||
|
Helwing Lutz
|
||||||
Hendrik Visage
|
Hendrik Visage
|
||||||
Henrik Storner
|
Henrik Storner
|
||||||
Henry Ludemann
|
Henry Ludemann
|
||||||
@@ -457,6 +482,7 @@ Jacky Lam
|
|||||||
Jacob Meuser
|
Jacob Meuser
|
||||||
Jacob Moshenko
|
Jacob Moshenko
|
||||||
Jad Chamcham
|
Jad Chamcham
|
||||||
|
Jakub Zakrzewski
|
||||||
James Bursa
|
James Bursa
|
||||||
James Cheng
|
James Cheng
|
||||||
James Clancy
|
James Clancy
|
||||||
@@ -476,6 +502,7 @@ Jan Schaumann
|
|||||||
Jan Van Boghout
|
Jan Van Boghout
|
||||||
Jared Jennings
|
Jared Jennings
|
||||||
Jared Lundell
|
Jared Lundell
|
||||||
|
Jari Aalto
|
||||||
Jari Sundell
|
Jari Sundell
|
||||||
Jason Glasgow
|
Jason Glasgow
|
||||||
Jason Liu
|
Jason Liu
|
||||||
@@ -490,7 +517,7 @@ Jean-Claude Chauve
|
|||||||
Jean-Francois Bertrand
|
Jean-Francois Bertrand
|
||||||
Jean-Louis Lemaire
|
Jean-Louis Lemaire
|
||||||
Jean-Marc Ranger
|
Jean-Marc Ranger
|
||||||
Jean-Noel Rouvignac
|
Jean-Noël Rouvignac
|
||||||
Jean-Philippe Barrette-LaPierre
|
Jean-Philippe Barrette-LaPierre
|
||||||
Jeff Connelly
|
Jeff Connelly
|
||||||
Jeff Hodges
|
Jeff Hodges
|
||||||
@@ -500,11 +527,11 @@ Jeff Lawson
|
|||||||
Jeff Phillips
|
Jeff Phillips
|
||||||
Jeff Pohlmeyer
|
Jeff Pohlmeyer
|
||||||
Jeff Weber
|
Jeff Weber
|
||||||
Jeffrey Pohlmeyer
|
|
||||||
Jeremy Friesner
|
Jeremy Friesner
|
||||||
Jeremy Huddleston
|
Jeremy Huddleston
|
||||||
Jeroen Koekkoek
|
Jeroen Koekkoek
|
||||||
Jerome Muffat-Meridol
|
Jerome Muffat-Meridol
|
||||||
|
Jerome Robert
|
||||||
Jerome Vouillon
|
Jerome Vouillon
|
||||||
Jerry Krinock
|
Jerry Krinock
|
||||||
Jerry Wu
|
Jerry Wu
|
||||||
@@ -529,7 +556,9 @@ Johan Anderson
|
|||||||
Johan Nilsson
|
Johan Nilsson
|
||||||
Johan van Selst
|
Johan van Selst
|
||||||
Johannes Bauer
|
Johannes Bauer
|
||||||
|
Johannes Ernst
|
||||||
John Bradshaw
|
John Bradshaw
|
||||||
|
John Coffey
|
||||||
John Crow
|
John Crow
|
||||||
John Dennis
|
John Dennis
|
||||||
John Dunn
|
John Dunn
|
||||||
@@ -540,6 +569,7 @@ John Joseph Bachir
|
|||||||
John Kelly
|
John Kelly
|
||||||
John Lask
|
John Lask
|
||||||
John Lightsey
|
John Lightsey
|
||||||
|
John Malmberg
|
||||||
John Marino
|
John Marino
|
||||||
John McGowan
|
John McGowan
|
||||||
John P. McCaskey
|
John P. McCaskey
|
||||||
@@ -556,9 +586,12 @@ Jon Turner
|
|||||||
Jonas Forsman
|
Jonas Forsman
|
||||||
Jonas Schnelli
|
Jonas Schnelli
|
||||||
Jonatan Lander
|
Jonatan Lander
|
||||||
|
Jonatan Vela
|
||||||
|
Jonathan Cardoso Machado
|
||||||
Jonathan Hseu
|
Jonathan Hseu
|
||||||
Jonathan Nieder
|
Jonathan Nieder
|
||||||
Jongki Suwandi
|
Jongki Suwandi
|
||||||
|
Jose Alf
|
||||||
Jose Kahan
|
Jose Kahan
|
||||||
Josef Wolf
|
Josef Wolf
|
||||||
Josh Kapell
|
Josh Kapell
|
||||||
@@ -624,6 +657,7 @@ Lachlan O'Dea
|
|||||||
Larry Campbell
|
Larry Campbell
|
||||||
Larry Fahnoe
|
Larry Fahnoe
|
||||||
Larry Lin
|
Larry Lin
|
||||||
|
Larry Stone
|
||||||
Lars Buitinck
|
Lars Buitinck
|
||||||
Lars Gustafsson
|
Lars Gustafsson
|
||||||
Lars J. Aas
|
Lars J. Aas
|
||||||
@@ -639,9 +673,11 @@ Len Krause
|
|||||||
Lenaic Lefever
|
Lenaic Lefever
|
||||||
Lenny Rachitsky
|
Lenny Rachitsky
|
||||||
Leon Winter
|
Leon Winter
|
||||||
|
Leonardo Rosati
|
||||||
Liam Healy
|
Liam Healy
|
||||||
Lijo Antony
|
Lijo Antony
|
||||||
Linas Vepstas
|
Linas Vepstas
|
||||||
|
Lindley French
|
||||||
Ling Thio
|
Ling Thio
|
||||||
Linus Nielsen Feltzing
|
Linus Nielsen Feltzing
|
||||||
Lisa Xu
|
Lisa Xu
|
||||||
@@ -652,12 +688,14 @@ Loren Kirkby
|
|||||||
Luca Altea
|
Luca Altea
|
||||||
Luca Alteas
|
Luca Alteas
|
||||||
Lucas Adamski
|
Lucas Adamski
|
||||||
|
Ludek Finstrle
|
||||||
Ludovico Cavedon
|
Ludovico Cavedon
|
||||||
Lukasz Czekierda
|
Lukasz Czekierda
|
||||||
Luke Amery
|
Luke Amery
|
||||||
Luke Call
|
Luke Call
|
||||||
Luke Dashjr
|
Luke Dashjr
|
||||||
Luong Dinh Dung
|
Luong Dinh Dung
|
||||||
|
Lyndon Hill
|
||||||
Maciej Karpiuk
|
Maciej Karpiuk
|
||||||
Maciej Puzio
|
Maciej Puzio
|
||||||
Maciej W. Rozycki
|
Maciej W. Rozycki
|
||||||
@@ -713,6 +751,7 @@ Mateusz Loskot
|
|||||||
Mathias Axelsson
|
Mathias Axelsson
|
||||||
Mats Lidell
|
Mats Lidell
|
||||||
Matt Arsenault
|
Matt Arsenault
|
||||||
|
Matt Ford
|
||||||
Matt Kraai
|
Matt Kraai
|
||||||
Matt Veenstra
|
Matt Veenstra
|
||||||
Matt Witherspoon
|
Matt Witherspoon
|
||||||
@@ -748,10 +787,12 @@ Michael Stillwell
|
|||||||
Michael Wallner
|
Michael Wallner
|
||||||
Michal Bonino
|
Michal Bonino
|
||||||
Michal Gorny
|
Michal Gorny
|
||||||
Michal Kowalczyk
|
|
||||||
Michal Marek
|
Michal Marek
|
||||||
|
Michał Górny
|
||||||
|
Michał Kowalczyk
|
||||||
Michele Bini
|
Michele Bini
|
||||||
Miguel Angel
|
Miguel Angel
|
||||||
|
Miguel Diaz
|
||||||
Mihai Ionescu
|
Mihai Ionescu
|
||||||
Mikael Johansson
|
Mikael Johansson
|
||||||
Mikael Sennerholm
|
Mikael Sennerholm
|
||||||
@@ -760,12 +801,14 @@ Mike Crowe
|
|||||||
Mike Dobbs
|
Mike Dobbs
|
||||||
Mike Giancola
|
Mike Giancola
|
||||||
Mike Hasselberg
|
Mike Hasselberg
|
||||||
|
Mike Henshaw
|
||||||
Mike Hommey
|
Mike Hommey
|
||||||
Mike Mio
|
Mike Mio
|
||||||
Mike Power
|
Mike Power
|
||||||
Mike Protts
|
Mike Protts
|
||||||
Mike Revi
|
Mike Revi
|
||||||
Miklos Nemeth
|
Miklos Nemeth
|
||||||
|
Miroslav Spousta
|
||||||
Mitz Wark
|
Mitz Wark
|
||||||
Mohamed Lrhazi
|
Mohamed Lrhazi
|
||||||
Mohammad AlSaleh
|
Mohammad AlSaleh
|
||||||
@@ -803,11 +846,12 @@ Nodak Sodak
|
|||||||
Norbert Frese
|
Norbert Frese
|
||||||
Norbert Novotny
|
Norbert Novotny
|
||||||
Ofer
|
Ofer
|
||||||
|
Ola Mork
|
||||||
Olaf Flebbe
|
Olaf Flebbe
|
||||||
Olaf Stueben
|
|
||||||
Olaf Stüben
|
Olaf Stüben
|
||||||
Oliver Gondža
|
Oliver Gondža
|
||||||
Oliver Kuckertz
|
Oliver Kuckertz
|
||||||
|
Oliver Schindler
|
||||||
Olivier Berger
|
Olivier Berger
|
||||||
Oren Tirosh
|
Oren Tirosh
|
||||||
Ori Avtalion
|
Ori Avtalion
|
||||||
@@ -818,10 +862,12 @@ Paolo Piacentini
|
|||||||
Paras Sethia
|
Paras Sethia
|
||||||
Pascal Terjan
|
Pascal Terjan
|
||||||
Pasha Kuznetsov
|
Pasha Kuznetsov
|
||||||
|
Pasi Karkkainen
|
||||||
Pat Ray
|
Pat Ray
|
||||||
Patrice Guerin
|
Patrice Guerin
|
||||||
Patricia Muscalu
|
Patricia Muscalu
|
||||||
Patrick Bihan-Faou
|
Patrick Bihan-Faou
|
||||||
|
Patrick McManus
|
||||||
Patrick Monnerat
|
Patrick Monnerat
|
||||||
Patrick Scott
|
Patrick Scott
|
||||||
Patrick Smith
|
Patrick Smith
|
||||||
@@ -836,6 +882,7 @@ Paul Marquis
|
|||||||
Paul Moore
|
Paul Moore
|
||||||
Paul Nolan
|
Paul Nolan
|
||||||
Paul Querna
|
Paul Querna
|
||||||
|
Paul Saab
|
||||||
Pavel Cenek
|
Pavel Cenek
|
||||||
Pavel Orehov
|
Pavel Orehov
|
||||||
Pavel Raiskup
|
Pavel Raiskup
|
||||||
@@ -858,6 +905,7 @@ Peter Su
|
|||||||
Peter Sylvester
|
Peter Sylvester
|
||||||
Peter Todd
|
Peter Todd
|
||||||
Peter Verhas
|
Peter Verhas
|
||||||
|
Peter Wang
|
||||||
Peter Wullinger
|
Peter Wullinger
|
||||||
Peteris Krumins
|
Peteris Krumins
|
||||||
Petr Bahula
|
Petr Bahula
|
||||||
@@ -889,6 +937,7 @@ Quinn Slack
|
|||||||
Radu Simionescu
|
Radu Simionescu
|
||||||
Rafa Muyo
|
Rafa Muyo
|
||||||
Rafael Sagula
|
Rafael Sagula
|
||||||
|
Rafaël Carré
|
||||||
Rainer Canavan
|
Rainer Canavan
|
||||||
Rainer Jung
|
Rainer Jung
|
||||||
Rainer Koenig
|
Rainer Koenig
|
||||||
@@ -901,6 +950,7 @@ Randy McMurchy
|
|||||||
Ravi Pratap
|
Ravi Pratap
|
||||||
Ray Dassen
|
Ray Dassen
|
||||||
Ray Pekowski
|
Ray Pekowski
|
||||||
|
Ray Satiro
|
||||||
Reinout van Schouwen
|
Reinout van Schouwen
|
||||||
Remi Gacogne
|
Remi Gacogne
|
||||||
Renato Botelho
|
Renato Botelho
|
||||||
@@ -921,6 +971,7 @@ Richard Clayton
|
|||||||
Richard Cooper
|
Richard Cooper
|
||||||
Richard Gorton
|
Richard Gorton
|
||||||
Richard Michael
|
Richard Michael
|
||||||
|
Richard Moore
|
||||||
Richard Prescott
|
Richard Prescott
|
||||||
Richard Silverman
|
Richard Silverman
|
||||||
Rick Jones
|
Rick Jones
|
||||||
@@ -944,6 +995,7 @@ Robin Johnson
|
|||||||
Robin Kay
|
Robin Kay
|
||||||
Robson Braga Araujo
|
Robson Braga Araujo
|
||||||
Rodney Simmons
|
Rodney Simmons
|
||||||
|
Rodric Glaser
|
||||||
Rodrigo Silva
|
Rodrigo Silva
|
||||||
Roland Blom
|
Roland Blom
|
||||||
Roland Krikava
|
Roland Krikava
|
||||||
@@ -952,6 +1004,7 @@ Rolland Dudemaine
|
|||||||
Roman Koifman
|
Roman Koifman
|
||||||
Roman Mamedov
|
Roman Mamedov
|
||||||
Romulo A. Ceccon
|
Romulo A. Ceccon
|
||||||
|
Ron Parker
|
||||||
Ron Zapp
|
Ron Zapp
|
||||||
Rosimildo da Silva
|
Rosimildo da Silva
|
||||||
Roy Shan
|
Roy Shan
|
||||||
@@ -978,6 +1031,7 @@ Santhana Todatry
|
|||||||
Saqib Ali
|
Saqib Ali
|
||||||
Sara Golemon
|
Sara Golemon
|
||||||
Saran Neti
|
Saran Neti
|
||||||
|
Sascha Swiercy
|
||||||
Saul good
|
Saul good
|
||||||
Scott Bailey
|
Scott Bailey
|
||||||
Scott Barrett
|
Scott Barrett
|
||||||
@@ -1008,6 +1062,7 @@ Song Ma
|
|||||||
Sonia Subramanian
|
Sonia Subramanian
|
||||||
Spacen Jasset
|
Spacen Jasset
|
||||||
Spiridonoff A.V
|
Spiridonoff A.V
|
||||||
|
Spork Schivago
|
||||||
Stadler Stephan
|
Stadler Stephan
|
||||||
Stan van de Burgt
|
Stan van de Burgt
|
||||||
Stanislav Ivochkin
|
Stanislav Ivochkin
|
||||||
@@ -1017,6 +1072,7 @@ Stefan Neis
|
|||||||
Stefan Teleman
|
Stefan Teleman
|
||||||
Stefan Tomanek
|
Stefan Tomanek
|
||||||
Stefan Ulrich
|
Stefan Ulrich
|
||||||
|
Steinar H. Gunderson
|
||||||
Stephan Bergmann
|
Stephan Bergmann
|
||||||
Stephen Collyer
|
Stephen Collyer
|
||||||
Stephen Kick
|
Stephen Kick
|
||||||
@@ -1036,6 +1092,7 @@ Steven Gu
|
|||||||
Steven M. Schweda
|
Steven M. Schweda
|
||||||
Steven Parkes
|
Steven Parkes
|
||||||
Stoned Elipot
|
Stoned Elipot
|
||||||
|
Sune Ahlgren
|
||||||
Sven Anders
|
Sven Anders
|
||||||
Sven Neuhaus
|
Sven Neuhaus
|
||||||
Sven Wegener
|
Sven Wegener
|
||||||
@@ -1064,6 +1121,7 @@ Tim Harder
|
|||||||
Tim Heckman
|
Tim Heckman
|
||||||
Tim Newsome
|
Tim Newsome
|
||||||
Tim Sneddon
|
Tim Sneddon
|
||||||
|
Tim Starling
|
||||||
Timo Sirainen
|
Timo Sirainen
|
||||||
Tinus van den Berg
|
Tinus van den Berg
|
||||||
Tobias Markus
|
Tobias Markus
|
||||||
@@ -1136,6 +1194,7 @@ Wez Furlong
|
|||||||
Wilfredo Sanchez
|
Wilfredo Sanchez
|
||||||
Will Dietz
|
Will Dietz
|
||||||
Willem Sparreboom
|
Willem Sparreboom
|
||||||
|
William Ahern
|
||||||
Wojciech Zwiefka
|
Wojciech Zwiefka
|
||||||
Wouter Van Rooy
|
Wouter Van Rooy
|
||||||
Wu Yongzheng
|
Wu Yongzheng
|
||||||
@@ -1144,10 +1203,12 @@ Yaakov Selkowitz
|
|||||||
Yamada Yasuharu
|
Yamada Yasuharu
|
||||||
Yang Tse
|
Yang Tse
|
||||||
Yarram Sunil
|
Yarram Sunil
|
||||||
|
Yasuharu Yamada
|
||||||
Yehezkel Horowitz
|
Yehezkel Horowitz
|
||||||
Yehoshua Hershberg
|
Yehoshua Hershberg
|
||||||
Yi Huang
|
Yi Huang
|
||||||
Yingwei Liu
|
Yingwei Liu
|
||||||
|
Yousuke Kimoto
|
||||||
Yukihiro Kawada
|
Yukihiro Kawada
|
||||||
Yuriy Sosov
|
Yuriy Sosov
|
||||||
Yves Arrouye
|
Yves Arrouye
|
||||||
@@ -1159,3 +1220,4 @@ Zvi Har'El
|
|||||||
nk
|
nk
|
||||||
swalkaus at yahoo.com
|
swalkaus at yahoo.com
|
||||||
tommink[at]post.pl
|
tommink[at]post.pl
|
||||||
|
Никита Дорохин
|
||||||
|
23
docs/TODO
23
docs/TODO
@@ -33,6 +33,7 @@
|
|||||||
4.3 Earlier bad letter detection
|
4.3 Earlier bad letter detection
|
||||||
4.4 REST for large files
|
4.4 REST for large files
|
||||||
4.5 ASCII support
|
4.5 ASCII support
|
||||||
|
4.6 GSSAPI via Windows SSPI
|
||||||
|
|
||||||
5. HTTP
|
5. HTTP
|
||||||
5.1 Better persistency for HTTP 1.0
|
5.1 Better persistency for HTTP 1.0
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
5.3 Rearrange request header order
|
5.3 Rearrange request header order
|
||||||
5.4 SPDY
|
5.4 SPDY
|
||||||
5.5 auth= in URLs
|
5.5 auth= in URLs
|
||||||
|
5.6 Digest via Windows SSPI
|
||||||
|
|
||||||
6. TELNET
|
6. TELNET
|
||||||
6.1 ditch stdin
|
6.1 ditch stdin
|
||||||
@@ -80,6 +82,7 @@
|
|||||||
|
|
||||||
14. SASL
|
14. SASL
|
||||||
14.1 Other authentication mechanisms
|
14.1 Other authentication mechanisms
|
||||||
|
14.2 GSSAPI via GSS-API libraries
|
||||||
|
|
||||||
15. Client
|
15. Client
|
||||||
15.1 sync
|
15.1 sync
|
||||||
@@ -251,6 +254,12 @@
|
|||||||
FTP ASCII transfers do not follow RFC959. They don't convert the data
|
FTP ASCII transfers do not follow RFC959. They don't convert the data
|
||||||
accordingly.
|
accordingly.
|
||||||
|
|
||||||
|
4.6 GSSAPI via Windows SSPI
|
||||||
|
|
||||||
|
In addition to currently supporting the SASL GSSAPI mechanism (Kerberos V5)
|
||||||
|
via third-party GSS-API libraries, such as Heimdal or MIT Kerberos, also add
|
||||||
|
support for GSSAPI authentication via Windows SSPI.
|
||||||
|
|
||||||
5. HTTP
|
5. HTTP
|
||||||
|
|
||||||
5.1 Better persistency for HTTP 1.0
|
5.1 Better persistency for HTTP 1.0
|
||||||
@@ -296,6 +305,12 @@
|
|||||||
|
|
||||||
Additionally this should be implemented for proxy base URLs as well.
|
Additionally this should be implemented for proxy base URLs as well.
|
||||||
|
|
||||||
|
5.6 Digest via Windows SSPI
|
||||||
|
|
||||||
|
libcurl already supports HTTP Digest Authentication via native routines as well
|
||||||
|
as SASL Digest via both Windows SSPI and native routines. In addition to this
|
||||||
|
libcurl should also support HTTP Digest Authentication via Windows SSPI.
|
||||||
|
|
||||||
6. TELNET
|
6. TELNET
|
||||||
|
|
||||||
6.1 ditch stdin
|
6.1 ditch stdin
|
||||||
@@ -440,7 +455,13 @@ to provide the data to send.
|
|||||||
|
|
||||||
14.1 Other authentication mechanisms
|
14.1 Other authentication mechanisms
|
||||||
|
|
||||||
Add support for GSSAPI to SMTP, POP3 and IMAP.
|
Add support for other authentication mechanisms such as EXTERNAL, OLP,
|
||||||
|
GSS-SPNEGO and others.
|
||||||
|
|
||||||
|
14.2 GSSAPI via GSS-API libraries
|
||||||
|
|
||||||
|
Add support for GSSAPI authentication via third-party GSS-API libraries, such
|
||||||
|
as Heimdal and MIT Kerberos.
|
||||||
|
|
||||||
15. Client
|
15. Client
|
||||||
|
|
||||||
|
76
docs/curl.1
76
docs/curl.1
@@ -20,7 +20,7 @@
|
|||||||
.\" *
|
.\" *
|
||||||
.\" **************************************************************************
|
.\" **************************************************************************
|
||||||
.\"
|
.\"
|
||||||
.TH curl 1 "27 July 2012" "Curl 7.27.0" "Curl Manual"
|
.TH curl 1 "2 Aug 2014" "Curl 7.38.0" "Curl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl \- transfer a URL
|
curl \- transfer a URL
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -699,6 +699,10 @@ See also the \fI-A, --user-agent\fP and \fI-e, --referer\fP options.
|
|||||||
Starting in 7.37.0, you need \fI--proxy-header\fP to send custom headers
|
Starting in 7.37.0, you need \fI--proxy-header\fP to send custom headers
|
||||||
intended for a proxy.
|
intended for a proxy.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
\&# curl -H "X-First-Name: Joe" http://192.168.0.1/
|
||||||
|
|
||||||
This option can be used multiple times to add/replace/remove multiple headers.
|
This option can be used multiple times to add/replace/remove multiple headers.
|
||||||
.IP "--hostpubmd5 <md5>"
|
.IP "--hostpubmd5 <md5>"
|
||||||
(SCP/SFTP) Pass a string containing 32 hexadecimal digits. The string should
|
(SCP/SFTP) Pass a string containing 32 hexadecimal digits. The string should
|
||||||
@@ -827,9 +831,8 @@ If this option is used several times, the last one will be used.
|
|||||||
should be one of 'clear', 'safe', 'confidential', or 'private'. Should you use
|
should be one of 'clear', 'safe', 'confidential', or 'private'. Should you use
|
||||||
a level that is not one of these, 'private' will instead be used.
|
a level that is not one of these, 'private' will instead be used.
|
||||||
|
|
||||||
This option requires a library built with kerberos4 or GSSAPI
|
This option requires a library built with kerberos4 support. This is not
|
||||||
(GSS-Negotiate) support. This is not very common. Use \fI-V, --version\fP to
|
very common. Use \fI-V, --version\fP to see if your curl supports it.
|
||||||
see if your curl supports it.
|
|
||||||
|
|
||||||
If this option is used several times, the last one will be used.
|
If this option is used several times, the last one will be used.
|
||||||
.IP "-l, --list-only"
|
.IP "-l, --list-only"
|
||||||
@@ -866,6 +869,10 @@ When curl follows a redirect and the request is not a plain GET (for example
|
|||||||
POST or PUT), it will do the following request with a GET if the HTTP response
|
POST or PUT), it will do the following request with a GET if the HTTP response
|
||||||
was 301, 302, or 303. If the response code was any other 3xx code, curl will
|
was 301, 302, or 303. If the response code was any other 3xx code, curl will
|
||||||
re-send the following request using the same unmodified method.
|
re-send the following request using the same unmodified method.
|
||||||
|
|
||||||
|
You can tell curl to not change the non-GET request method to GET after a 30x
|
||||||
|
response by using the dedicated options for that: \fI--post301\fP,
|
||||||
|
\fI--post302\fP and \fI-post303\fP.
|
||||||
.IP "--libcurl <file>"
|
.IP "--libcurl <file>"
|
||||||
Append this option to any ordinary curl command line, and you will get a
|
Append this option to any ordinary curl command line, and you will get a
|
||||||
libcurl-using C source code written to the file that does the equivalent
|
libcurl-using C source code written to the file that does the equivalent
|
||||||
@@ -874,9 +881,10 @@ of what your command-line operation does!
|
|||||||
If this option is used several times, the last given file name will be
|
If this option is used several times, the last given file name will be
|
||||||
used. (Added in 7.16.1)
|
used. (Added in 7.16.1)
|
||||||
.IP "--limit-rate <speed>"
|
.IP "--limit-rate <speed>"
|
||||||
Specify the maximum transfer rate you want curl to use. This feature is useful
|
Specify the maximum transfer rate you want curl to use - for both downloads
|
||||||
if you have a limited pipe and you'd like your transfer not to use your entire
|
and uploads. This feature is useful if you have a limited pipe and you'd like
|
||||||
bandwidth.
|
your transfer not to use your entire bandwidth. To make it slower than it
|
||||||
|
otherwise would be.
|
||||||
|
|
||||||
The given speed is measured in bytes/second, unless a suffix is appended.
|
The given speed is measured in bytes/second, unless a suffix is appended.
|
||||||
Appending 'k' or 'K' will count the number as kilobytes, 'm' or M' makes it
|
Appending 'k' or 'K' will count the number as kilobytes, 'm' or M' makes it
|
||||||
@@ -1024,18 +1032,13 @@ Very similar to \fI--netrc\fP, but this option makes the .netrc usage
|
|||||||
\fBoptional\fP and not mandatory as the \fI--netrc\fP option does.
|
\fBoptional\fP and not mandatory as the \fI--netrc\fP option does.
|
||||||
|
|
||||||
.IP "--negotiate"
|
.IP "--negotiate"
|
||||||
(HTTP) Enables GSS-Negotiate authentication. The GSS-Negotiate method was
|
(HTTP) Enables Negotiate (SPNEGO) authentication.
|
||||||
designed by Microsoft and is used in their web applications. It is primarily
|
|
||||||
meant as a support for Kerberos5 authentication but may be also used along
|
|
||||||
with another authentication method. For more information see IETF draft
|
|
||||||
draft-brezak-spnego-http-04.txt.
|
|
||||||
|
|
||||||
If you want to enable Negotiate for your proxy authentication, then use
|
If you want to enable Negotiate (SPNEGO) for proxy authentication, then use
|
||||||
\fI--proxy-negotiate\fP.
|
\fI--proxy-negotiate\fP.
|
||||||
|
|
||||||
This option requires a library built with GSSAPI support. This is
|
This option requires a library built with GSS-API or SSPI support. Use \fI-V,
|
||||||
not very common. Use \fI-V, --version\fP to see if your version supports
|
--version\fP to see if your curl supports GSS-API/SSPI and SPNEGO.
|
||||||
GSS-Negotiate.
|
|
||||||
|
|
||||||
When using this option, you must also provide a fake \fI-u, --user\fP option to
|
When using this option, you must also provide a fake \fI-u, --user\fP option to
|
||||||
activate the authentication code properly. Sending a '-u :' is enough as the
|
activate the authentication code properly. Sending a '-u :' is enough as the
|
||||||
@@ -1254,8 +1257,8 @@ the default authentication method curl uses with proxies.
|
|||||||
Tells curl to use HTTP Digest authentication when communicating with the given
|
Tells curl to use HTTP Digest authentication when communicating with the given
|
||||||
proxy. Use \fI--digest\fP for enabling HTTP Digest with a remote host.
|
proxy. Use \fI--digest\fP for enabling HTTP Digest with a remote host.
|
||||||
.IP "--proxy-negotiate"
|
.IP "--proxy-negotiate"
|
||||||
Tells curl to use HTTP Negotiate authentication when communicating
|
Tells curl to use HTTP Negotiate (SPNEGO) authentication when communicating
|
||||||
with the given proxy. Use \fI--negotiate\fP for enabling HTTP Negotiate
|
with the given proxy. Use \fI--negotiate\fP for enabling HTTP Negotiate (SPNEGO)
|
||||||
with a remote host. (Added in 7.17.1)
|
with a remote host. (Added in 7.17.1)
|
||||||
.IP "--proxy-ntlm"
|
.IP "--proxy-ntlm"
|
||||||
Tells curl to use HTTP NTLM authentication when communicating with the given
|
Tells curl to use HTTP NTLM authentication when communicating with the given
|
||||||
@@ -1518,7 +1521,7 @@ sockd/proxy-name --socks5 proxy-name \fI--socks5-gssapi-service\fP
|
|||||||
sockd/real-name would use sockd/real-name for cases where the proxy-name does
|
sockd/real-name would use sockd/real-name for cases where the proxy-name does
|
||||||
not match the principal name. (Added in 7.19.4).
|
not match the principal name. (Added in 7.19.4).
|
||||||
.IP "--socks5-gssapi-nec"
|
.IP "--socks5-gssapi-nec"
|
||||||
As part of the gssapi negotiation a protection mode is negotiated. RFC 1961
|
As part of the GSS-API negotiation a protection mode is negotiated. RFC 1961
|
||||||
says in section 4.3/4.4 it should be protected, but the NEC reference
|
says in section 4.3/4.4 it should be protected, but the NEC reference
|
||||||
implementation does not. The option \fI--socks5-gssapi-nec\fP allows the
|
implementation does not. The option \fI--socks5-gssapi-nec\fP allows the
|
||||||
unprotected exchange of the protection mode negotiation. (Added in 7.19.4).
|
unprotected exchange of the protection mode negotiation. (Added in 7.19.4).
|
||||||
@@ -1633,17 +1636,31 @@ The user name and passwords are split up on the first colon, which makes it
|
|||||||
impossible to use a colon in the user name with this option. The password can,
|
impossible to use a colon in the user name with this option. The password can,
|
||||||
still.
|
still.
|
||||||
|
|
||||||
If you use an SSPI-enabled curl binary and perform NTLM authentication, you
|
When using Kerberos V5 with a Windows based server you should include the
|
||||||
can force curl to select the user name and password from your environment by
|
Windows domain name in the user name, in order for the server to succesfully
|
||||||
specifying a single colon with this option: "-u :".
|
obtain a Kerberos Ticket. If you don't then the initial authentication
|
||||||
|
handshake may fail.
|
||||||
|
|
||||||
|
When using NTLM, the user name can be specified simply as the user name,
|
||||||
|
without the domain, if there is a single domain and forest in your setup
|
||||||
|
for example.
|
||||||
|
|
||||||
|
To specify the domain name use either Down-Level Logon Name or UPN (User
|
||||||
|
Principal Name) formats. For example, EXAMPLE\\user and user@example.com
|
||||||
|
respectively.
|
||||||
|
|
||||||
|
If you use a Windows SSPI-enabled curl binary and perform Kerberos V5,
|
||||||
|
Negotiate or NTLM authentication then you can tell curl to select the user
|
||||||
|
name and password from your environment by specifying a single colon with this
|
||||||
|
option: "-u :".
|
||||||
|
|
||||||
If this option is used several times, the last one will be used.
|
If this option is used several times, the last one will be used.
|
||||||
.IP "-U, --proxy-user <user:password>"
|
.IP "-U, --proxy-user <user:password>"
|
||||||
Specify the user name and password to use for proxy authentication.
|
Specify the user name and password to use for proxy authentication.
|
||||||
|
|
||||||
If you use an SSPI-enabled curl binary and do NTLM authentication, you can
|
If you use a Windows SSPI-enabled curl binary and do either Negotiate or NTLM
|
||||||
force curl to pick up the user name and password from your environment by
|
authentication then you can tell curl to select the user name and password
|
||||||
simply specifying a single colon with this option: "-U :".
|
from your environment by specifying a single colon with this option: "-U :".
|
||||||
|
|
||||||
If this option is used several times, the last one will be used.
|
If this option is used several times, the last one will be used.
|
||||||
.IP "--url <URL>"
|
.IP "--url <URL>"
|
||||||
@@ -1917,22 +1934,21 @@ HTTPS and FTPS are supported.
|
|||||||
Automatic decompression of compressed files over HTTP is supported.
|
Automatic decompression of compressed files over HTTP is supported.
|
||||||
.IP "NTLM"
|
.IP "NTLM"
|
||||||
NTLM authentication is supported.
|
NTLM authentication is supported.
|
||||||
.IP "GSS-Negotiate"
|
|
||||||
Negotiate authentication and krb5 for FTP is supported.
|
|
||||||
.IP "Debug"
|
.IP "Debug"
|
||||||
This curl uses a libcurl built with Debug. This enables more error-tracking
|
This curl uses a libcurl built with Debug. This enables more error-tracking
|
||||||
and memory debugging etc. For curl-developers only!
|
and memory debugging etc. For curl-developers only!
|
||||||
.IP "AsynchDNS"
|
.IP "AsynchDNS"
|
||||||
This curl uses asynchronous name resolves.
|
This curl uses asynchronous name resolves.
|
||||||
.IP "SPNEGO"
|
.IP "SPNEGO"
|
||||||
SPNEGO Negotiate authentication is supported.
|
SPNEGO authentication is supported.
|
||||||
.IP "Largefile"
|
.IP "Largefile"
|
||||||
This curl supports transfers of large files, files larger than 2GB.
|
This curl supports transfers of large files, files larger than 2GB.
|
||||||
.IP "IDN"
|
.IP "IDN"
|
||||||
This curl supports IDN - international domain names.
|
This curl supports IDN - international domain names.
|
||||||
|
.IP "GSS-API"
|
||||||
|
GSS-API is supported.
|
||||||
.IP "SSPI"
|
.IP "SSPI"
|
||||||
SSPI is supported. If you use NTLM and set a blank user name, curl will
|
SSPI is supported.
|
||||||
authenticate with your current user and password.
|
|
||||||
.IP "TLS-SRP"
|
.IP "TLS-SRP"
|
||||||
SRP (Secure Remote Password) authentication is supported for TLS.
|
SRP (Secure Remote Password) authentication is supported for TLS.
|
||||||
.IP "Metalink"
|
.IP "Metalink"
|
||||||
|
@@ -148,9 +148,6 @@ endif
|
|||||||
ifeq ($(findstring -sspi,$(CFG)),-sspi)
|
ifeq ($(findstring -sspi,$(CFG)),-sspi)
|
||||||
SSPI = 1
|
SSPI = 1
|
||||||
endif
|
endif
|
||||||
ifeq ($(findstring -spnego,$(CFG)),-spnego)
|
|
||||||
SPNEGO = 1
|
|
||||||
endif
|
|
||||||
ifeq ($(findstring -ldaps,$(CFG)),-ldaps)
|
ifeq ($(findstring -ldaps,$(CFG)),-ldaps)
|
||||||
LDAPS = 1
|
LDAPS = 1
|
||||||
endif
|
endif
|
||||||
@@ -230,9 +227,6 @@ ifdef SSPI
|
|||||||
CFLAGS += -DUSE_SCHANNEL
|
CFLAGS += -DUSE_SCHANNEL
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
ifdef SPNEGO
|
|
||||||
CFLAGS += -DHAVE_SPNEGO
|
|
||||||
endif
|
|
||||||
ifdef IPV6
|
ifdef IPV6
|
||||||
CFLAGS += -DENABLE_IPV6 -D_WIN32_WINNT=0x0501
|
CFLAGS += -DENABLE_IPV6 -D_WIN32_WINNT=0x0501
|
||||||
endif
|
endif
|
||||||
|
@@ -211,9 +211,6 @@ endif
|
|||||||
ifeq ($(findstring -idn,$(CFG)),-idn)
|
ifeq ($(findstring -idn,$(CFG)),-idn)
|
||||||
WITH_IDN = 1
|
WITH_IDN = 1
|
||||||
endif
|
endif
|
||||||
ifeq ($(findstring -spnego,$(CFG)),-spnego)
|
|
||||||
WITH_SPNEGO = 1
|
|
||||||
endif
|
|
||||||
ifeq ($(findstring -ipv6,$(CFG)),-ipv6)
|
ifeq ($(findstring -ipv6,$(CFG)),-ipv6)
|
||||||
ENABLE_IPV6 = 1
|
ENABLE_IPV6 = 1
|
||||||
endif
|
endif
|
||||||
@@ -247,10 +244,6 @@ ifdef WITH_SSL
|
|||||||
LDLIBS += $(OPENSSL_PATH)/out_nw_$(LIBARCH_L)/ssl.$(LIBEXT)
|
LDLIBS += $(OPENSSL_PATH)/out_nw_$(LIBARCH_L)/ssl.$(LIBEXT)
|
||||||
LDLIBS += $(OPENSSL_PATH)/out_nw_$(LIBARCH_L)/crypto.$(LIBEXT)
|
LDLIBS += $(OPENSSL_PATH)/out_nw_$(LIBARCH_L)/crypto.$(LIBEXT)
|
||||||
IMPORTS += GetProcessSwitchCount RunningProcess
|
IMPORTS += GetProcessSwitchCount RunningProcess
|
||||||
ifdef WITH_SPNEGO
|
|
||||||
# INCLUDES += -I$(FBOPENSSL_PATH)/include
|
|
||||||
LDLIBS += $(FBOPENSSL_PATH)/nw/fbopenssl.$(LIBEXT)
|
|
||||||
endif
|
|
||||||
else
|
else
|
||||||
ifdef WITH_AXTLS
|
ifdef WITH_AXTLS
|
||||||
INCLUDES += -I$(AXTLS_PATH)/inc
|
INCLUDES += -I$(AXTLS_PATH)/inc
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -26,9 +26,9 @@ struct callback_data {
|
|||||||
FILE *output;
|
FILE *output;
|
||||||
};
|
};
|
||||||
|
|
||||||
static long file_is_comming(struct curl_fileinfo *finfo,
|
static long file_is_coming(struct curl_fileinfo *finfo,
|
||||||
struct callback_data *data,
|
struct callback_data *data,
|
||||||
int remains);
|
int remains);
|
||||||
|
|
||||||
static long file_is_downloaded(struct callback_data *data);
|
static long file_is_downloaded(struct callback_data *data);
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ int main(int argc, char **argv)
|
|||||||
curl_easy_setopt(handle, CURLOPT_WILDCARDMATCH, 1L);
|
curl_easy_setopt(handle, CURLOPT_WILDCARDMATCH, 1L);
|
||||||
|
|
||||||
/* callback is called before download of concrete file started */
|
/* callback is called before download of concrete file started */
|
||||||
curl_easy_setopt(handle, CURLOPT_CHUNK_BGN_FUNCTION, file_is_comming);
|
curl_easy_setopt(handle, CURLOPT_CHUNK_BGN_FUNCTION, file_is_coming);
|
||||||
|
|
||||||
/* callback is called after data from the file have been transferred */
|
/* callback is called after data from the file have been transferred */
|
||||||
curl_easy_setopt(handle, CURLOPT_CHUNK_END_FUNCTION, file_is_downloaded);
|
curl_easy_setopt(handle, CURLOPT_CHUNK_END_FUNCTION, file_is_downloaded);
|
||||||
@@ -89,9 +89,9 @@ int main(int argc, char **argv)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long file_is_comming(struct curl_fileinfo *finfo,
|
static long file_is_coming(struct curl_fileinfo *finfo,
|
||||||
struct callback_data *data,
|
struct callback_data *data,
|
||||||
int remains)
|
int remains)
|
||||||
{
|
{
|
||||||
printf("%3d %40s %10luB ", remains, finfo->filename,
|
printf("%3d %40s %10luB ", remains, finfo->filename,
|
||||||
(unsigned long)finfo->size);
|
(unsigned long)finfo->size);
|
||||||
|
@@ -225,10 +225,10 @@ content is for the specific named data. See also the certinfo.c example. NOTE:
|
|||||||
this option is only available in libcurl built with OpenSSL, NSS, GSKit or
|
this option is only available in libcurl built with OpenSSL, NSS, GSKit or
|
||||||
QsoSSL support. (Added in 7.19.1)
|
QsoSSL support. (Added in 7.19.1)
|
||||||
.IP CURLINFO_TLS_SESSION
|
.IP CURLINFO_TLS_SESSION
|
||||||
Pass a pointer to a 'struct curl_tlsinfo *'. The pointer will be initialized
|
Pass a pointer to a 'struct curl_tlssessioninfo *'. The pointer will be
|
||||||
to refer to a 'struct curl_tlsinfo *' that will contain an enum indicating the
|
initialized to refer to a 'struct curl_tlssessioninfo *' that will contain an
|
||||||
SSL library used for the handshake and the respective internal TLS session
|
enum indicating the SSL library used for the handshake and the respective
|
||||||
structure of this underlying SSL library.
|
internal TLS session structure of this underlying SSL library.
|
||||||
|
|
||||||
This may then be used to extract certificate information in a format
|
This may then be used to extract certificate information in a format
|
||||||
convenient for further processing, such as manual validation. NOTE: this
|
convenient for further processing, such as manual validation. NOTE: this
|
||||||
|
@@ -86,6 +86,10 @@ you must set its length with \fBCURLFORM_CONTENTSLENGTH\fP.
|
|||||||
.IP CURLFORM_CONTENTSLENGTH
|
.IP CURLFORM_CONTENTSLENGTH
|
||||||
followed by a long giving the length of the contents. Note that for
|
followed by a long giving the length of the contents. Note that for
|
||||||
\fICURLFORM_STREAM\fP contents, this option is mandatory.
|
\fICURLFORM_STREAM\fP contents, this option is mandatory.
|
||||||
|
|
||||||
|
If you pass a 0 (zero) for this option, libcurl will instead do a strlen() on
|
||||||
|
the contents to figure out the size. If you really want to send a zero byte
|
||||||
|
content then you must make sure strlen() on the data pointer returns zero.
|
||||||
.IP CURLFORM_FILECONTENT
|
.IP CURLFORM_FILECONTENT
|
||||||
followed by a filename, causes that file to be read and its contents used
|
followed by a filename, causes that file to be read and its contents used
|
||||||
as data in this part. This part does \fInot\fP automatically become a file
|
as data in this part. This part does \fInot\fP automatically become a file
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
.\" *
|
.\" *
|
||||||
.\" **************************************************************************
|
.\" **************************************************************************
|
||||||
.\"
|
.\"
|
||||||
.TH curl_version_info 3 "18 Feb 2014" "libcurl 7.33.0" "libcurl Manual"
|
.TH curl_version_info 3 "2 Aug 2014" "libcurl 7.38.0" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_version_info - returns run-time libcurl version info
|
curl_version_info - returns run-time libcurl version info
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -124,9 +124,14 @@ libcurl was built with support for IDNA, domain names with international
|
|||||||
letters. (Added in 7.12.0)
|
letters. (Added in 7.12.0)
|
||||||
.IP CURL_VERSION_SSPI
|
.IP CURL_VERSION_SSPI
|
||||||
libcurl was built with support for SSPI. This is only available on Windows and
|
libcurl was built with support for SSPI. This is only available on Windows and
|
||||||
makes libcurl use Windows-provided functions for NTLM authentication. It also
|
makes libcurl use Windows-provided functions for NTLM, SPNEGO and SASL DIGEST-MD5
|
||||||
allows libcurl to use the current user and the current user's password without
|
authentication. It also allows libcurl to use the current user credentials without
|
||||||
the app having to pass them on. (Added in 7.13.2)
|
the app having to pass them on. (Added in 7.13.2)
|
||||||
|
.IP CURL_VERSION_GSSAPI
|
||||||
|
libcurl was built with support for GSS-API. This makes libcurl use provided
|
||||||
|
functions for Kerberos and SPNEGO authentication. It also allows libcurl
|
||||||
|
to use the current user credentials without the app having to pass them on.
|
||||||
|
(Added in 7.38.0)
|
||||||
.IP CURL_VERSION_CONV
|
.IP CURL_VERSION_CONV
|
||||||
libcurl was built with support for character conversions, as provided by the
|
libcurl was built with support for character conversions, as provided by the
|
||||||
CURLOPT_CONV_* callbacks. (Added in 7.15.4)
|
CURLOPT_CONV_* callbacks. (Added in 7.15.4)
|
||||||
@@ -142,8 +147,7 @@ libcurl was built with support for HTTP2.
|
|||||||
\fIssl_version\fP is an ASCII string for the OpenSSL version used. If libcurl
|
\fIssl_version\fP is an ASCII string for the OpenSSL version used. If libcurl
|
||||||
has no SSL support, this is NULL.
|
has no SSL support, this is NULL.
|
||||||
|
|
||||||
\fIssl_version_num\fP is the numerical OpenSSL version value as defined by the
|
\fIssl_version_num\fP is always 0.
|
||||||
OpenSSL project. If libcurl has no SSL support, this is 0.
|
|
||||||
|
|
||||||
\fIlibz_version\fP is an ASCII string (there is no numerical version). If
|
\fIlibz_version\fP is an ASCII string (there is no numerical version). If
|
||||||
libcurl has no libz support, this is NULL.
|
libcurl has no libz support, this is NULL.
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
An overview of the six time values available from curl_easy_getinfo()
|
An overview of the six time values available from curl_easy_getinfo()
|
||||||
|
|
||||||
curk_easy_perform()
|
curl_easy_perform()
|
||||||
|
|
|
|
||||||
|--NT
|
|--NT
|
||||||
|--|--CT
|
|--|--CT
|
||||||
|
@@ -83,6 +83,9 @@ FTP servers return a 227-line as a response to a PASV command. If libcurl
|
|||||||
fails to parse that line, this return code is passed back.
|
fails to parse that line, this return code is passed back.
|
||||||
.IP "CURLE_FTP_CANT_GET_HOST (15)"
|
.IP "CURLE_FTP_CANT_GET_HOST (15)"
|
||||||
An internal failure to lookup the host used for the new connection.
|
An internal failure to lookup the host used for the new connection.
|
||||||
|
.IP "CURLE_HTTP2 (16)"
|
||||||
|
A problem was detected in the HTTP2 framing layer. This is somewhat generic
|
||||||
|
and can be one out of several problems, see the error buffer for details.
|
||||||
.IP "CURLE_FTP_COULDNT_SET_TYPE (17)"
|
.IP "CURLE_FTP_COULDNT_SET_TYPE (17)"
|
||||||
Received an error when trying to set the transfer mode to binary or ASCII.
|
Received an error when trying to set the transfer mode to binary or ASCII.
|
||||||
.IP "CURLE_PARTIAL_FILE (18)"
|
.IP "CURLE_PARTIAL_FILE (18)"
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
.\" *
|
.\" *
|
||||||
.\" **************************************************************************
|
.\" **************************************************************************
|
||||||
.\"
|
.\"
|
||||||
.TH libcurl-tutorial 3 "4 Mar 2009" "libcurl" "libcurl programming"
|
.TH libcurl-tutorial 3 "2 Aug 2014" "libcurl" "libcurl programming"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
libcurl-tutorial \- libcurl programming tutorial
|
libcurl-tutorial \- libcurl programming tutorial
|
||||||
.SH "Objective"
|
.SH "Objective"
|
||||||
@@ -442,7 +442,7 @@ authentication method is called 'Basic', which is sending the name and
|
|||||||
password in clear-text in the HTTP request, base64-encoded. This is insecure.
|
password in clear-text in the HTTP request, base64-encoded. This is insecure.
|
||||||
|
|
||||||
At the time of this writing, libcurl can be built to use: Basic, Digest, NTLM,
|
At the time of this writing, libcurl can be built to use: Basic, Digest, NTLM,
|
||||||
Negotiate, GSS-Negotiate and SPNEGO. You can tell libcurl which one to use
|
Negotiate (SPNEGO). You can tell libcurl which one to use
|
||||||
with \fICURLOPT_HTTPAUTH(3)\fP as in:
|
with \fICURLOPT_HTTPAUTH(3)\fP as in:
|
||||||
|
|
||||||
curl_easy_setopt(easyhandle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
|
curl_easy_setopt(easyhandle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
|
||||||
|
@@ -40,7 +40,7 @@ details.
|
|||||||
|
|
||||||
To transfer files, you create an "easy handle" using \fIcurl_easy_init(3)\fP
|
To transfer files, you create an "easy handle" using \fIcurl_easy_init(3)\fP
|
||||||
for a single individual transfer (in either direction). You then set your
|
for a single individual transfer (in either direction). You then set your
|
||||||
desired set of options in that handle with \fIcurk_easy_setopt(3)\fP. Options
|
desired set of options in that handle with \fIcurl_easy_setopt(3)\fP. Options
|
||||||
you set with \fIcurl_easy_setopt(3)\fP stick. They will be used on every
|
you set with \fIcurl_easy_setopt(3)\fP stick. They will be used on every
|
||||||
repeated use of this handle until you either change the option, or you reset
|
repeated use of this handle until you either change the option, or you reset
|
||||||
them all with \fIcurl_easy_reset(3)\fP.
|
them all with \fIcurl_easy_reset(3)\fP.
|
||||||
|
@@ -1,3 +1,24 @@
|
|||||||
|
#***************************************************************************
|
||||||
|
# _ _ ____ _
|
||||||
|
# Project ___| | | | _ \| |
|
||||||
|
# / __| | | | |_) | |
|
||||||
|
# | (__| |_| | _ <| |___
|
||||||
|
# \___|\___/|_| \_\_____|
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006, David Shaw <dshaw@jabberwocky.com>
|
||||||
|
#
|
||||||
|
# This software is licensed as described in the file COPYING, which
|
||||||
|
# you should have received as part of this distribution. The terms
|
||||||
|
# are also available at 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.
|
||||||
|
#
|
||||||
|
###########################################################################
|
||||||
# LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION],
|
# LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION],
|
||||||
# [ACTION-IF-YES], [ACTION-IF-NO])
|
# [ACTION-IF-YES], [ACTION-IF-NO])
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
|
@@ -52,4 +52,5 @@ If built TLS enabled
|
|||||||
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
|
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
|
||||||
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
|
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
|
.BR CURLOPT_CAPATH "(3), "
|
||||||
.BR CURLOPT_SSL_VERIFYPEER "(3), " CURLOPT_SSL_VERIFYHOST "(3), "
|
.BR CURLOPT_SSL_VERIFYPEER "(3), " CURLOPT_SSL_VERIFYHOST "(3), "
|
||||||
|
@@ -32,10 +32,10 @@ Pass a char * to a zero terminated string naming a directory holding multiple
|
|||||||
CA certificates to verify the peer with. If libcurl is built against OpenSSL,
|
CA certificates to verify the peer with. If libcurl is built against OpenSSL,
|
||||||
the certificate directory must be prepared using the openssl c_rehash utility.
|
the certificate directory must be prepared using the openssl c_rehash utility.
|
||||||
This makes sense only when used in combination with the
|
This makes sense only when used in combination with the
|
||||||
\fICURLOPT_SSL_VERIFYPEER(3)\fP option. If \fICURLOPT_SSL_VERIFYPEER(3)\fP is
|
\fICURLOPT_SSL_VERIFYPEER(3)\fP option.
|
||||||
zero, \fICURLOPT_CAPATH(3)\fP need not even indicate an accessible path. The
|
|
||||||
\fICURLOPT_CAPATH(3)\fP function apparently does not work in Windows due to
|
The \fICURLOPT_CAPATH(3)\fP function apparently does not work in Windows due
|
||||||
some limitation in openssl.
|
to some limitation in openssl.
|
||||||
.SH DEFAULT
|
.SH DEFAULT
|
||||||
NULL
|
NULL
|
||||||
.SH PROTOCOLS
|
.SH PROTOCOLS
|
||||||
@@ -50,4 +50,5 @@ compatibility.
|
|||||||
Returns CURLE_OK if TLS enabled, and CURLE_UNKNOWN_OPTION if not, or
|
Returns CURLE_OK if TLS enabled, and CURLE_UNKNOWN_OPTION if not, or
|
||||||
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
|
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
|
.BR CURLOPT_CAINFO "(3), "
|
||||||
.BR CURLOPT_STDERR "(3), " CURLOPT_DEBUGFUNCTION "(3), "
|
.BR CURLOPT_STDERR "(3), " CURLOPT_DEBUGFUNCTION "(3), "
|
||||||
|
@@ -40,7 +40,7 @@ This callback function gets called by libcurl before a part of the stream is
|
|||||||
going to be transferred (if the transfer supports chunks).
|
going to be transferred (if the transfer supports chunks).
|
||||||
|
|
||||||
The \fItransfer_info\fP pointer will point to a struct curl_fileinfo with
|
The \fItransfer_info\fP pointer will point to a struct curl_fileinfo with
|
||||||
details about the file that is about to get transfered.
|
details about the file that is about to get transferred.
|
||||||
|
|
||||||
This callback makes sense only when using the \fICURLOPT_WILDCARDMATCH(3)\fP
|
This callback makes sense only when using the \fICURLOPT_WILDCARDMATCH(3)\fP
|
||||||
option for now.
|
option for now.
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.TH CURLOPT_FTPSSLAUTH 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
|
.TH CURLOPT_FTPSSLAUTH 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
CURLOPT_FTPSSLAUTH \- set order to attemp TSL vs SSL when using FTP
|
CURLOPT_FTPSSLAUTH \- set order in which to attempt TLS vs SSL when using FTP
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
@@ -41,7 +41,7 @@ sent to a server and not to a proxy. Proxy headers must be set with
|
|||||||
\fICURLOPT_PROXYHEADER(3)\fP to get used. Note that if a non-CONNECT request
|
\fICURLOPT_PROXYHEADER(3)\fP to get used. Note that if a non-CONNECT request
|
||||||
is sent to a proxy, libcurl will send both server headers and proxy
|
is sent to a proxy, libcurl will send both server headers and proxy
|
||||||
headers. When doing CONNECT, libcurl will send \fICURLOPT_PROXYHEADER(3)\fP
|
headers. When doing CONNECT, libcurl will send \fICURLOPT_PROXYHEADER(3)\fP
|
||||||
headers only do the proxy and then \fICURLOPT_HTTPHEADER(3)\fP headers only to
|
headers only to the proxy and then \fICURLOPT_HTTPHEADER(3)\fP headers only to
|
||||||
the server.
|
the server.
|
||||||
.SH DEFAULT
|
.SH DEFAULT
|
||||||
CURLHEADER_UNIFIED
|
CURLHEADER_UNIFIED
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
.\" *
|
.\" *
|
||||||
.\" **************************************************************************
|
.\" **************************************************************************
|
||||||
.\"
|
.\"
|
||||||
.TH CURLOPT_HTTPAUTH 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
|
.TH CURLOPT_HTTPAUTH 3 "2 Aug 2014" "libcurl 7.38.0" "curl_easy_setopt options"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
CURLOPT_HTTPAUTH \- set HTTP server authentication methods to try
|
CURLOPT_HTTPAUTH \- set HTTP server authentication methods to try
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -56,14 +56,12 @@ defined in RFC2617 and is a more secure way to do authentication over public
|
|||||||
networks than the regular old-fashioned Basic method. The IE flavor is simply
|
networks than the regular old-fashioned Basic method. The IE flavor is simply
|
||||||
that libcurl will use a special "quirk" that IE is known to have used before
|
that libcurl will use a special "quirk" that IE is known to have used before
|
||||||
version 7 and that some servers require the client to use.
|
version 7 and that some servers require the client to use.
|
||||||
.IP CURLAUTH_GSSNEGOTIATE
|
.IP CURLAUTH_NEGOTIATE
|
||||||
HTTP GSS-Negotiate authentication. The GSS-Negotiate (also known as plain
|
HTTP Negotiate (SPNEGO) authentication. Negotiate authentication is defined
|
||||||
\&"Negotiate") method was designed by Microsoft and is used in their web
|
in RFC 4559 and is the most secure way to perform authentication over HTTP.
|
||||||
applications. It is primarily meant as a support for Kerberos5 authentication
|
|
||||||
but may also be used along with other authentication methods. For more
|
|
||||||
information see IETF draft draft-brezak-spnego-http-04.txt.
|
|
||||||
|
|
||||||
You need to build libcurl with a suitable GSS-API library for this to work.
|
You need to build libcurl with a suitable GSS-API library or SSPI on Windows
|
||||||
|
for this to work.
|
||||||
.IP CURLAUTH_NTLM
|
.IP CURLAUTH_NTLM
|
||||||
HTTP NTLM authentication. A proprietary protocol invented and used by
|
HTTP NTLM authentication. A proprietary protocol invented and used by
|
||||||
Microsoft. It uses a challenge-response and hash concept similar to Digest, to
|
Microsoft. It uses a challenge-response and hash concept similar to Digest, to
|
||||||
|
@@ -57,7 +57,7 @@ The callback MUST return \fICURLIOE_UNKNOWNCMD\fP if the input \fIcmd\fP is
|
|||||||
not \fICURLIOCMD_RESTARTREAD\fP.
|
not \fICURLIOCMD_RESTARTREAD\fP.
|
||||||
|
|
||||||
The \fIclientp\fP argument to the callback is set with the
|
The \fIclientp\fP argument to the callback is set with the
|
||||||
\fUICURLOPT_IOCTLDATA(3)\fP option.
|
\fICURLOPT_IOCTLDATA(3)\fP option.
|
||||||
|
|
||||||
This option is deprecated! Do not use it. Use \fICURLOPT_SEEKFUNCTION(3)\fP
|
This option is deprecated! Do not use it. Use \fICURLOPT_SEEKFUNCTION(3)\fP
|
||||||
instead to provide seeking! If \fICURLOPT_SEEKFUNCTION(3)\fP is set, this
|
instead to provide seeking! If \fICURLOPT_SEEKFUNCTION(3)\fP is set, this
|
||||||
|
@@ -22,15 +22,18 @@
|
|||||||
.\"
|
.\"
|
||||||
.TH CURLOPT_NOBODY 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
|
.TH CURLOPT_NOBODY 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
CURLOPT_NOBODY \- do the request without getting the body
|
CURLOPT_NOBODY \- do the download request without getting the body
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOBODY, long opt);
|
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOBODY, long opt);
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
A long parameter set to 1 tells libcurl to not include the body-part in the
|
A long parameter set to 1 tells libcurl to not include the body-part in the
|
||||||
output. For HTTP(S), this makes libcurl do a HEAD request. For most other
|
output when doing what would otherwise be a download. For HTTP(S), this makes
|
||||||
protocols ie means just not asking for transferring the body data.
|
libcurl do a HEAD request. For most other protocols it means just not asking
|
||||||
|
to transfer the body data.
|
||||||
|
|
||||||
|
Enabling this option means asking for a download but without a body.
|
||||||
.SH DEFAULT
|
.SH DEFAULT
|
||||||
0, the body is transferred
|
0, the body is transferred
|
||||||
.SH PROTOCOLS
|
.SH PROTOCOLS
|
||||||
|
@@ -32,7 +32,7 @@ A parameter set to 1 tells the library to use HTTP PUT to transfer data. The
|
|||||||
data should be set with \fICURLOPT_READDATA(3)\fP and
|
data should be set with \fICURLOPT_READDATA(3)\fP and
|
||||||
\fICURLOPT_INFILESIZE(3)\fP.
|
\fICURLOPT_INFILESIZE(3)\fP.
|
||||||
|
|
||||||
This option is \dBdeprecated\fP since version 7.12.1. Use
|
This option is \fBdeprecated\fP since version 7.12.1. Use
|
||||||
\fICURLOPT_UPLOAD(3)\fP!
|
\fICURLOPT_UPLOAD(3)\fP!
|
||||||
.SH DEFAULT
|
.SH DEFAULT
|
||||||
0, disabled
|
0, disabled
|
||||||
|
@@ -41,7 +41,7 @@ All
|
|||||||
.SH EXAMPLE
|
.SH EXAMPLE
|
||||||
TODO
|
TODO
|
||||||
.SH AVAILABILITY
|
.SH AVAILABILITY
|
||||||
Added in 7.19.4, before then it would follow all protcols.
|
Added in 7.19.4, before then it would follow all protocols.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
|
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.TH CURLOPT_SSH_KEYDATA 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
|
.TH CURLOPT_SSH_KEYDATA 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
CURLOPT_SSH_KEYDATA \- pointer to apss to the SSH key callback
|
CURLOPT_SSH_KEYDATA \- pointer to pass to the SSH key callback
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
@@ -51,6 +51,12 @@ typically also want to ensure that the server is the server you mean to be
|
|||||||
talking to. Use \fICURLOPT_SSL_VERIFYHOST(3)\fP for that. The check that the
|
talking to. Use \fICURLOPT_SSL_VERIFYHOST(3)\fP for that. The check that the
|
||||||
host name in the certificate is valid for the host name you're connecting to
|
host name in the certificate is valid for the host name you're connecting to
|
||||||
is done independently of the \fICURLOPT_SSL_VERIFYPEER(3)\fP option.
|
is done independently of the \fICURLOPT_SSL_VERIFYPEER(3)\fP option.
|
||||||
|
|
||||||
|
WARNING: disabling verification of the certificate allows bad guys to
|
||||||
|
man-in-the-middle the communication without you knowing it. Disabling
|
||||||
|
verification makes the communication insecure. Just having encryption on a
|
||||||
|
transfer is not enough as you cannot be sure that you are communicating with
|
||||||
|
the correct end-point.
|
||||||
.SH DEFAULT
|
.SH DEFAULT
|
||||||
By default, curl assumes a value of 1.
|
By default, curl assumes a value of 1.
|
||||||
.SH PROTOCOLS
|
.SH PROTOCOLS
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.TH CURLOPT_URL 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
|
.TH CURLOPT_URL 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
CURLOPT_URL \- provide the URL to use in the reqest
|
CURLOPT_URL \- provide the URL to use in the request
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
@@ -37,6 +37,22 @@ user name to use for the transfer.
|
|||||||
authentication. You should not use this option together with the (older)
|
authentication. You should not use this option together with the (older)
|
||||||
\fICURLOPT_USERPWD(3)\fP option.
|
\fICURLOPT_USERPWD(3)\fP option.
|
||||||
|
|
||||||
|
When using Kerberos V5 authentication with a Windows based server, you should
|
||||||
|
include the domain name in order for the server to successfully obtain a
|
||||||
|
Kerberos Ticket. If you don't then the initial part of the authentication
|
||||||
|
handshake may fail.
|
||||||
|
|
||||||
|
When using NTLM, the user name can be specified simply as the user name
|
||||||
|
without the domain name should the server be part of a single domain and
|
||||||
|
forest.
|
||||||
|
|
||||||
|
To include the domain name use either Down-Level Logon Name or UPN (User
|
||||||
|
Principal Name) formats. For example, EXAMPLE\\user and user@example.com
|
||||||
|
respectively.
|
||||||
|
|
||||||
|
Some HTTP servers (on Windows) support inclusion of the domain for Basic
|
||||||
|
authentication as well.
|
||||||
|
|
||||||
To specify the password and login options, along with the user name, use the
|
To specify the password and login options, along with the user name, use the
|
||||||
\fICURLOPT_PASSWORD(3)\fP and \fICURLOPT_LOGIN_OPTIONS(3)\fP options.
|
\fICURLOPT_PASSWORD(3)\fP and \fICURLOPT_LOGIN_OPTIONS(3)\fP options.
|
||||||
.SH DEFAULT
|
.SH DEFAULT
|
||||||
|
@@ -31,10 +31,21 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USERPWD, char *userpwd);
|
|||||||
Pass a char * as parameter, pointing to a zero terminated login details string
|
Pass a char * as parameter, pointing to a zero terminated login details string
|
||||||
for the connection. The format of which is: [user name]:[password].
|
for the connection. The format of which is: [user name]:[password].
|
||||||
|
|
||||||
When using NTLM, you can set the domain by prepending it to the user name and
|
When using Kerberos V5 authentication with a Windows based server, you should
|
||||||
separating the domain and name with a forward (/) or backward slash (\\). Like
|
specify the user name part with the domain name in order for the server to
|
||||||
this: "domain/user:password" or "domain\\user:password". Some HTTP servers (on
|
successfully obtain a Kerberos Ticket. If you don't then the initial part of
|
||||||
Windows) support this style even for Basic authentication.
|
the authentication handshake may fail.
|
||||||
|
|
||||||
|
When using NTLM, the user name can be specified simply as the user name
|
||||||
|
without the domain name should the server be part of a single domain and
|
||||||
|
forest.
|
||||||
|
|
||||||
|
To specify the domain name use either Down-Level Logon Name or UPN (User
|
||||||
|
Principal Name) formats. For example, EXAMPLE\\user and user@example.com
|
||||||
|
respectively.
|
||||||
|
|
||||||
|
Some HTTP servers (on Windows) support inclusion of the domain for Basic
|
||||||
|
authentication as well.
|
||||||
|
|
||||||
When using HTTP and \fICURLOPT_FOLLOWLOCATION(3)\fP, libcurl might perform
|
When using HTTP and \fICURLOPT_FOLLOWLOCATION(3)\fP, libcurl might perform
|
||||||
several requests to possibly different hosts. libcurl will only send this user
|
several requests to possibly different hosts. libcurl will only send this user
|
||||||
|
@@ -17,7 +17,8 @@ CURLAUTH_ANYSAFE 7.10.6
|
|||||||
CURLAUTH_BASIC 7.10.6
|
CURLAUTH_BASIC 7.10.6
|
||||||
CURLAUTH_DIGEST 7.10.6
|
CURLAUTH_DIGEST 7.10.6
|
||||||
CURLAUTH_DIGEST_IE 7.19.3
|
CURLAUTH_DIGEST_IE 7.19.3
|
||||||
CURLAUTH_GSSNEGOTIATE 7.10.6
|
CURLAUTH_GSSNEGOTIATE 7.10.6 7.38.0
|
||||||
|
CURLAUTH_NEGOTIATE 7.38.0
|
||||||
CURLAUTH_NONE 7.10.6
|
CURLAUTH_NONE 7.10.6
|
||||||
CURLAUTH_NTLM 7.10.6
|
CURLAUTH_NTLM 7.10.6
|
||||||
CURLAUTH_NTLM_WB 7.22.0
|
CURLAUTH_NTLM_WB 7.22.0
|
||||||
@@ -78,6 +79,7 @@ CURLE_HTTP_PORT_FAILED 7.3 7.12.0
|
|||||||
CURLE_HTTP_POST_ERROR 7.1
|
CURLE_HTTP_POST_ERROR 7.1
|
||||||
CURLE_HTTP_RANGE_ERROR 7.1 7.17.0
|
CURLE_HTTP_RANGE_ERROR 7.1 7.17.0
|
||||||
CURLE_HTTP_RETURNED_ERROR 7.10.3
|
CURLE_HTTP_RETURNED_ERROR 7.10.3
|
||||||
|
CURLE_HTTP2 7.38.0
|
||||||
CURLE_INTERFACE_FAILED 7.12.0
|
CURLE_INTERFACE_FAILED 7.12.0
|
||||||
CURLE_LDAP_CANNOT_BIND 7.1
|
CURLE_LDAP_CANNOT_BIND 7.1
|
||||||
CURLE_LDAP_INVALID_URL 7.10.8
|
CURLE_LDAP_INVALID_URL 7.10.8
|
||||||
@@ -602,6 +604,7 @@ CURLSSH_AUTH_KEYBOARD 7.16.1
|
|||||||
CURLSSH_AUTH_NONE 7.16.1
|
CURLSSH_AUTH_NONE 7.16.1
|
||||||
CURLSSH_AUTH_PASSWORD 7.16.1
|
CURLSSH_AUTH_PASSWORD 7.16.1
|
||||||
CURLSSH_AUTH_PUBLICKEY 7.16.1
|
CURLSSH_AUTH_PUBLICKEY 7.16.1
|
||||||
|
CURLSSLBACKEND_AXTLS 7.38.0
|
||||||
CURLSSLBACKEND_CYASSL 7.34.0
|
CURLSSLBACKEND_CYASSL 7.34.0
|
||||||
CURLSSLBACKEND_DARWINSSL 7.34.0
|
CURLSSLBACKEND_DARWINSSL 7.34.0
|
||||||
CURLSSLBACKEND_GNUTLS 7.34.0
|
CURLSSLBACKEND_GNUTLS 7.34.0
|
||||||
@@ -727,7 +730,8 @@ CURL_VERSION_ASYNCHDNS 7.10.7
|
|||||||
CURL_VERSION_CONV 7.15.4
|
CURL_VERSION_CONV 7.15.4
|
||||||
CURL_VERSION_CURLDEBUG 7.19.6
|
CURL_VERSION_CURLDEBUG 7.19.6
|
||||||
CURL_VERSION_DEBUG 7.10.6
|
CURL_VERSION_DEBUG 7.10.6
|
||||||
CURL_VERSION_GSSNEGOTIATE 7.10.6
|
CURL_VERSION_GSSAPI 7.38.0
|
||||||
|
CURL_VERSION_GSSNEGOTIATE 7.10.6 7.38.0
|
||||||
CURL_VERSION_HTTP2 7.33.0
|
CURL_VERSION_HTTP2 7.33.0
|
||||||
CURL_VERSION_IDN 7.12.0
|
CURL_VERSION_IDN 7.12.0
|
||||||
CURL_VERSION_IPV6 7.10
|
CURL_VERSION_IPV6 7.10
|
||||||
|
@@ -423,7 +423,9 @@ typedef enum {
|
|||||||
CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
|
CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
|
||||||
CURLE_FTP_WEIRD_227_FORMAT, /* 14 */
|
CURLE_FTP_WEIRD_227_FORMAT, /* 14 */
|
||||||
CURLE_FTP_CANT_GET_HOST, /* 15 */
|
CURLE_FTP_CANT_GET_HOST, /* 15 */
|
||||||
CURLE_OBSOLETE16, /* 16 - NOT USED */
|
CURLE_HTTP2, /* 16 - A problem in the http2 framing layer.
|
||||||
|
[was obsoleted in August 2007 for 7.17.0,
|
||||||
|
reused in July 2014 for 7.38.0] */
|
||||||
CURLE_FTP_COULDNT_SET_TYPE, /* 17 */
|
CURLE_FTP_COULDNT_SET_TYPE, /* 17 */
|
||||||
CURLE_PARTIAL_FILE, /* 18 */
|
CURLE_PARTIAL_FILE, /* 18 */
|
||||||
CURLE_FTP_COULDNT_RETR_FILE, /* 19 */
|
CURLE_FTP_COULDNT_RETR_FILE, /* 19 */
|
||||||
@@ -525,7 +527,10 @@ typedef enum {
|
|||||||
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
|
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
|
||||||
the obsolete stuff removed! */
|
the obsolete stuff removed! */
|
||||||
|
|
||||||
/* Previously obsoletes error codes re-used in 7.24.0 */
|
/* Previously obsolete error code re-used in 7.38.0 */
|
||||||
|
#define CURLE_OBSOLETE16 CURLE_HTTP2
|
||||||
|
|
||||||
|
/* Previously obsolete error codes re-used in 7.24.0 */
|
||||||
#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED
|
#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED
|
||||||
#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT
|
#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT
|
||||||
|
|
||||||
@@ -619,7 +624,8 @@ typedef enum {
|
|||||||
* CURLAUTH_NONE - No HTTP authentication
|
* CURLAUTH_NONE - No HTTP authentication
|
||||||
* CURLAUTH_BASIC - HTTP Basic authentication (default)
|
* CURLAUTH_BASIC - HTTP Basic authentication (default)
|
||||||
* CURLAUTH_DIGEST - HTTP Digest authentication
|
* CURLAUTH_DIGEST - HTTP Digest authentication
|
||||||
* CURLAUTH_GSSNEGOTIATE - HTTP GSS-Negotiate authentication
|
* CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication
|
||||||
|
* CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated)
|
||||||
* CURLAUTH_NTLM - HTTP NTLM authentication
|
* CURLAUTH_NTLM - HTTP NTLM authentication
|
||||||
* CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour
|
* CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour
|
||||||
* CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper
|
* CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper
|
||||||
@@ -632,7 +638,9 @@ typedef enum {
|
|||||||
#define CURLAUTH_NONE ((unsigned long)0)
|
#define CURLAUTH_NONE ((unsigned long)0)
|
||||||
#define CURLAUTH_BASIC (((unsigned long)1)<<0)
|
#define CURLAUTH_BASIC (((unsigned long)1)<<0)
|
||||||
#define CURLAUTH_DIGEST (((unsigned long)1)<<1)
|
#define CURLAUTH_DIGEST (((unsigned long)1)<<1)
|
||||||
#define CURLAUTH_GSSNEGOTIATE (((unsigned long)1)<<2)
|
#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2)
|
||||||
|
/* Deprecated since the advent of CURLAUTH_NEGOTIATE */
|
||||||
|
#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE
|
||||||
#define CURLAUTH_NTLM (((unsigned long)1)<<3)
|
#define CURLAUTH_NTLM (((unsigned long)1)<<3)
|
||||||
#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4)
|
#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4)
|
||||||
#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5)
|
#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5)
|
||||||
@@ -2025,7 +2033,8 @@ typedef enum {
|
|||||||
CURLSSLBACKEND_POLARSSL = 6,
|
CURLSSLBACKEND_POLARSSL = 6,
|
||||||
CURLSSLBACKEND_CYASSL = 7,
|
CURLSSLBACKEND_CYASSL = 7,
|
||||||
CURLSSLBACKEND_SCHANNEL = 8,
|
CURLSSLBACKEND_SCHANNEL = 8,
|
||||||
CURLSSLBACKEND_DARWINSSL = 9
|
CURLSSLBACKEND_DARWINSSL = 9,
|
||||||
|
CURLSSLBACKEND_AXTLS = 10
|
||||||
} curl_sslbackend;
|
} curl_sslbackend;
|
||||||
|
|
||||||
/* Information about the SSL library used and the respective internal SSL
|
/* Information about the SSL library used and the respective internal SSL
|
||||||
@@ -2231,10 +2240,11 @@ typedef struct {
|
|||||||
#define CURL_VERSION_SSL (1<<2) /* SSL options are present */
|
#define CURL_VERSION_SSL (1<<2) /* SSL options are present */
|
||||||
#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */
|
#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */
|
||||||
#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */
|
#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */
|
||||||
#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth support */
|
#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth support
|
||||||
|
(deprecated) */
|
||||||
#define CURL_VERSION_DEBUG (1<<6) /* built with debug capabilities */
|
#define CURL_VERSION_DEBUG (1<<6) /* built with debug capabilities */
|
||||||
#define CURL_VERSION_ASYNCHDNS (1<<7) /* asynchronous dns resolves */
|
#define CURL_VERSION_ASYNCHDNS (1<<7) /* asynchronous dns resolves */
|
||||||
#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth */
|
#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */
|
||||||
#define CURL_VERSION_LARGEFILE (1<<9) /* supports files bigger than 2GB */
|
#define CURL_VERSION_LARGEFILE (1<<9) /* supports files bigger than 2GB */
|
||||||
#define CURL_VERSION_IDN (1<<10) /* International Domain Names support */
|
#define CURL_VERSION_IDN (1<<10) /* International Domain Names support */
|
||||||
#define CURL_VERSION_SSPI (1<<11) /* SSPI is supported */
|
#define CURL_VERSION_SSPI (1<<11) /* SSPI is supported */
|
||||||
@@ -2243,6 +2253,7 @@ typedef struct {
|
|||||||
#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */
|
#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */
|
||||||
#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegating to winbind helper */
|
#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegating to winbind helper */
|
||||||
#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */
|
#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */
|
||||||
|
#define CURL_VERSION_GSSAPI (1<<17) /* GSS-API is supported */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NAME curl_version_info()
|
* NAME curl_version_info()
|
||||||
|
14
install-sh
14
install-sh
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# install - install a program, script, or datafile
|
# install - install a program, script, or datafile
|
||||||
|
|
||||||
scriptversion=2011-01-19.21; # UTC
|
scriptversion=2011-11-20.07; # UTC
|
||||||
|
|
||||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||||
@@ -35,7 +35,7 @@ scriptversion=2011-01-19.21; # UTC
|
|||||||
# FSF changes to this file are in the public domain.
|
# FSF changes to this file are in the public domain.
|
||||||
#
|
#
|
||||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||||
# `make' implicit rules from creating a file called install from it
|
# 'make' implicit rules from creating a file called install from it
|
||||||
# when there is no Makefile.
|
# when there is no Makefile.
|
||||||
#
|
#
|
||||||
# This script is compatible with the BSD install script, but was written
|
# This script is compatible with the BSD install script, but was written
|
||||||
@@ -156,7 +156,7 @@ while test $# -ne 0; do
|
|||||||
-s) stripcmd=$stripprog;;
|
-s) stripcmd=$stripprog;;
|
||||||
|
|
||||||
-t) dst_arg=$2
|
-t) dst_arg=$2
|
||||||
# Protect names problematic for `test' and other utilities.
|
# Protect names problematic for 'test' and other utilities.
|
||||||
case $dst_arg in
|
case $dst_arg in
|
||||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||||
esac
|
esac
|
||||||
@@ -190,7 +190,7 @@ if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
|||||||
fi
|
fi
|
||||||
shift # arg
|
shift # arg
|
||||||
dst_arg=$arg
|
dst_arg=$arg
|
||||||
# Protect names problematic for `test' and other utilities.
|
# Protect names problematic for 'test' and other utilities.
|
||||||
case $dst_arg in
|
case $dst_arg in
|
||||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||||
esac
|
esac
|
||||||
@@ -202,7 +202,7 @@ if test $# -eq 0; then
|
|||||||
echo "$0: no input file specified." >&2
|
echo "$0: no input file specified." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
# It's OK to call `install-sh -d' without argument.
|
# It's OK to call 'install-sh -d' without argument.
|
||||||
# This can happen when creating conditional directories.
|
# This can happen when creating conditional directories.
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
@@ -240,7 +240,7 @@ fi
|
|||||||
|
|
||||||
for src
|
for src
|
||||||
do
|
do
|
||||||
# Protect names problematic for `test' and other utilities.
|
# Protect names problematic for 'test' and other utilities.
|
||||||
case $src in
|
case $src in
|
||||||
-* | [=\(\)!]) src=./$src;;
|
-* | [=\(\)!]) src=./$src;;
|
||||||
esac
|
esac
|
||||||
@@ -354,7 +354,7 @@ do
|
|||||||
if test -z "$dir_arg" || {
|
if test -z "$dir_arg" || {
|
||||||
# Check for POSIX incompatibilities with -m.
|
# Check for POSIX incompatibilities with -m.
|
||||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||||
# other-writeable bit of parent directory when it shouldn't.
|
# other-writable bit of parent directory when it shouldn't.
|
||||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||||
case $ls_ld_tmpdir in
|
case $ls_ld_tmpdir in
|
||||||
|
@@ -60,7 +60,7 @@ SYS_INCL = -I"$(%watcom)/h/nt" -I"$(%watcom)/h"
|
|||||||
|
|
||||||
CFLAGS = -3r -mf -hc -zff -zgf -zq -zm -zc -s -fr=con -w2 -fpi -oilrtfm &
|
CFLAGS = -3r -mf -hc -zff -zgf -zq -zm -zc -s -fr=con -w2 -fpi -oilrtfm &
|
||||||
-wcd=201 -bt=nt -d+ -dWIN32 -dCURL_WANTS_CA_BUNDLE_ENV &
|
-wcd=201 -bt=nt -d+ -dWIN32 -dCURL_WANTS_CA_BUNDLE_ENV &
|
||||||
-dBUILDING_LIBCURL -dHAVE_SPNEGO=1 -I. -I"../include" $(SYS_INCL)
|
-dBUILDING_LIBCURL -I. -I"../include" $(SYS_INCL)
|
||||||
|
|
||||||
!ifdef %debug
|
!ifdef %debug
|
||||||
DEBUG = -dDEBUG=1 -dDEBUGBUILD
|
DEBUG = -dDEBUG=1 -dDEBUGBUILD
|
||||||
@@ -248,4 +248,4 @@ $(RESOURCE): libcurl.rc
|
|||||||
|
|
||||||
.c{$(OBJ_STAT)}.obj:
|
.c{$(OBJ_STAT)}.obj:
|
||||||
$(CC) $(CFLAGS) -DCURL_STATICLIB $[@ -fo=$^@
|
$(CC) $(CFLAGS) -DCURL_STATICLIB $[@ -fo=$^@
|
||||||
|
|
||||||
|
@@ -137,9 +137,6 @@ endif
|
|||||||
ifeq ($(findstring -sspi,$(CFG)),-sspi)
|
ifeq ($(findstring -sspi,$(CFG)),-sspi)
|
||||||
SSPI = 1
|
SSPI = 1
|
||||||
endif
|
endif
|
||||||
ifeq ($(findstring -spnego,$(CFG)),-spnego)
|
|
||||||
SPNEGO = 1
|
|
||||||
endif
|
|
||||||
ifeq ($(findstring -ldaps,$(CFG)),-ldaps)
|
ifeq ($(findstring -ldaps,$(CFG)),-ldaps)
|
||||||
LDAPS = 1
|
LDAPS = 1
|
||||||
endif
|
endif
|
||||||
|
@@ -217,9 +217,6 @@ endif
|
|||||||
ifeq ($(findstring -idn,$(CFG)),-idn)
|
ifeq ($(findstring -idn,$(CFG)),-idn)
|
||||||
WITH_IDN = 1
|
WITH_IDN = 1
|
||||||
endif
|
endif
|
||||||
ifeq ($(findstring -spnego,$(CFG)),-spnego)
|
|
||||||
WITH_SPNEGO = 1
|
|
||||||
endif
|
|
||||||
ifeq ($(findstring -ipv6,$(CFG)),-ipv6)
|
ifeq ($(findstring -ipv6,$(CFG)),-ipv6)
|
||||||
ENABLE_IPV6 = 1
|
ENABLE_IPV6 = 1
|
||||||
endif
|
endif
|
||||||
@@ -247,10 +244,6 @@ ifdef WITH_SSL
|
|||||||
LDLIBS += $(OPENSSL_PATH)/out_nw_$(LIBARCH_L)/crypto.$(LIBEXT)
|
LDLIBS += $(OPENSSL_PATH)/out_nw_$(LIBARCH_L)/crypto.$(LIBEXT)
|
||||||
IMPORTS += GetProcessSwitchCount RunningProcess
|
IMPORTS += GetProcessSwitchCount RunningProcess
|
||||||
INSTDEP += ca-bundle.crt
|
INSTDEP += ca-bundle.crt
|
||||||
ifdef WITH_SPNEGO
|
|
||||||
INCLUDES += -I$(FBOPENSSL_PATH)/include
|
|
||||||
LDLIBS += $(FBOPENSSL_PATH)/nw/fbopenssl.$(LIBEXT)
|
|
||||||
endif
|
|
||||||
else
|
else
|
||||||
ifdef WITH_AXTLS
|
ifdef WITH_AXTLS
|
||||||
INCLUDES += -I$(AXTLS_PATH)/inc
|
INCLUDES += -I$(AXTLS_PATH)/inc
|
||||||
|
@@ -235,7 +235,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
|
|||||||
milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
|
milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
|
||||||
if(milli == 0)
|
if(milli == 0)
|
||||||
milli += 10;
|
milli += 10;
|
||||||
Curl_expire(conn->data, milli);
|
Curl_expire_latest(conn->data, milli);
|
||||||
|
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
@@ -669,7 +669,7 @@ CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
|
|||||||
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
|
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
|
||||||
const char *local_ip6)
|
const char *local_ip6)
|
||||||
{
|
{
|
||||||
#if (ARES_VERSION >= 0x010704)
|
#if (ARES_VERSION >= 0x010704) && defined(ENABLE_IPV6)
|
||||||
unsigned char a6[INET6_ADDRSTRLEN];
|
unsigned char a6[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
if((!local_ip6) || (local_ip6[0] == 0)) {
|
if((!local_ip6) || (local_ip6[0] == 0)) {
|
||||||
|
@@ -166,6 +166,7 @@ struct thread_sync_data {
|
|||||||
#ifdef HAVE_GETADDRINFO
|
#ifdef HAVE_GETADDRINFO
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
#endif
|
#endif
|
||||||
|
struct thread_data *td; /* for thread-self cleanup */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct thread_data {
|
struct thread_data {
|
||||||
@@ -202,13 +203,16 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd)
|
|||||||
|
|
||||||
/* Initialize resolver thread synchronization data */
|
/* Initialize resolver thread synchronization data */
|
||||||
static
|
static
|
||||||
int init_thread_sync_data(struct thread_sync_data * tsd,
|
int init_thread_sync_data(struct thread_data * td,
|
||||||
const char * hostname,
|
const char * hostname,
|
||||||
int port,
|
int port,
|
||||||
const struct addrinfo *hints)
|
const struct addrinfo *hints)
|
||||||
{
|
{
|
||||||
|
struct thread_sync_data *tsd = &td->tsd;
|
||||||
|
|
||||||
memset(tsd, 0, sizeof(*tsd));
|
memset(tsd, 0, sizeof(*tsd));
|
||||||
|
|
||||||
|
tsd->td = td;
|
||||||
tsd->port = port;
|
tsd->port = port;
|
||||||
#ifdef HAVE_GETADDRINFO
|
#ifdef HAVE_GETADDRINFO
|
||||||
DEBUGASSERT(hints);
|
DEBUGASSERT(hints);
|
||||||
@@ -266,6 +270,7 @@ static int getaddrinfo_complete(struct connectdata *conn)
|
|||||||
static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
|
static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
|
||||||
{
|
{
|
||||||
struct thread_sync_data *tsd = (struct thread_sync_data*)arg;
|
struct thread_sync_data *tsd = (struct thread_sync_data*)arg;
|
||||||
|
struct thread_data *td = tsd->td;
|
||||||
char service[12];
|
char service[12];
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@@ -280,8 +285,16 @@ static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Curl_mutex_acquire(tsd->mtx);
|
Curl_mutex_acquire(tsd->mtx);
|
||||||
tsd->done = 1;
|
if(tsd->done) {
|
||||||
Curl_mutex_release(tsd->mtx);
|
/* too late, gotta clean up the mess */
|
||||||
|
Curl_mutex_release(tsd->mtx);
|
||||||
|
destroy_thread_sync_data(tsd);
|
||||||
|
free(td);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tsd->done = 1;
|
||||||
|
Curl_mutex_release(tsd->mtx);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -294,6 +307,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
|
|||||||
static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
|
static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
|
||||||
{
|
{
|
||||||
struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
|
struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
|
||||||
|
struct thread_data *td = tsd->td;
|
||||||
|
|
||||||
tsd->res = Curl_ipv4_resolve_r(tsd->hostname, tsd->port);
|
tsd->res = Curl_ipv4_resolve_r(tsd->hostname, tsd->port);
|
||||||
|
|
||||||
@@ -304,8 +318,16 @@ static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Curl_mutex_acquire(tsd->mtx);
|
Curl_mutex_acquire(tsd->mtx);
|
||||||
tsd->done = 1;
|
if(tsd->done) {
|
||||||
Curl_mutex_release(tsd->mtx);
|
/* too late, gotta clean up the mess */
|
||||||
|
Curl_mutex_release(tsd->mtx);
|
||||||
|
destroy_thread_sync_data(tsd);
|
||||||
|
free(td);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tsd->done = 1;
|
||||||
|
Curl_mutex_release(tsd->mtx);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -317,21 +339,37 @@ static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
|
|||||||
*/
|
*/
|
||||||
static void destroy_async_data (struct Curl_async *async)
|
static void destroy_async_data (struct Curl_async *async)
|
||||||
{
|
{
|
||||||
|
if(async->os_specific) {
|
||||||
|
struct thread_data *td = (struct thread_data*) async->os_specific;
|
||||||
|
int done;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if the thread is still blocking in the resolve syscall, detach it and
|
||||||
|
* let the thread do the cleanup...
|
||||||
|
*/
|
||||||
|
Curl_mutex_acquire(td->tsd.mtx);
|
||||||
|
done = td->tsd.done;
|
||||||
|
td->tsd.done = 1;
|
||||||
|
Curl_mutex_release(td->tsd.mtx);
|
||||||
|
|
||||||
|
if(!done) {
|
||||||
|
Curl_thread_destroy(td->thread_hnd);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(td->thread_hnd != curl_thread_t_null)
|
||||||
|
Curl_thread_join(&td->thread_hnd);
|
||||||
|
|
||||||
|
destroy_thread_sync_data(&td->tsd);
|
||||||
|
|
||||||
|
free(async->os_specific);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async->os_specific = NULL;
|
||||||
|
|
||||||
if(async->hostname)
|
if(async->hostname)
|
||||||
free(async->hostname);
|
free(async->hostname);
|
||||||
|
|
||||||
if(async->os_specific) {
|
|
||||||
struct thread_data *td = (struct thread_data*) async->os_specific;
|
|
||||||
|
|
||||||
if(td->thread_hnd != curl_thread_t_null)
|
|
||||||
Curl_thread_join(&td->thread_hnd);
|
|
||||||
|
|
||||||
destroy_thread_sync_data(&td->tsd);
|
|
||||||
|
|
||||||
free(async->os_specific);
|
|
||||||
}
|
|
||||||
async->hostname = NULL;
|
async->hostname = NULL;
|
||||||
async->os_specific = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -357,7 +395,7 @@ static bool init_resolve_thread (struct connectdata *conn,
|
|||||||
conn->async.dns = NULL;
|
conn->async.dns = NULL;
|
||||||
td->thread_hnd = curl_thread_t_null;
|
td->thread_hnd = curl_thread_t_null;
|
||||||
|
|
||||||
if(!init_thread_sync_data(&td->tsd, hostname, port, hints))
|
if(!init_thread_sync_data(td, hostname, port, hints))
|
||||||
goto err_exit;
|
goto err_exit;
|
||||||
|
|
||||||
Curl_safefree(conn->async.hostname);
|
Curl_safefree(conn->async.hostname);
|
||||||
@@ -503,7 +541,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
|
|||||||
td->poll_interval = 250;
|
td->poll_interval = 250;
|
||||||
|
|
||||||
td->interval_end = elapsed + td->poll_interval;
|
td->interval_end = elapsed + td->poll_interval;
|
||||||
Curl_expire(conn->data, td->poll_interval);
|
Curl_expire_latest(conn->data, td->poll_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
83
lib/base64.c
83
lib/base64.c
@@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -37,9 +37,14 @@
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
/* ---- Base64 Encoding/Decoding Table --- */
|
/* ---- Base64 Encoding/Decoding Table --- */
|
||||||
static const char table64[]=
|
static const char base64[]=
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
|
/* The Base 64 encoding with an URL and filename safe alphabet, RFC 4648
|
||||||
|
section 5 */
|
||||||
|
static const char base64url[]=
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||||
|
|
||||||
static size_t decodeQuantum(unsigned char *dest, const char *src)
|
static size_t decodeQuantum(unsigned char *dest, const char *src)
|
||||||
{
|
{
|
||||||
size_t padding = 0;
|
size_t padding = 0;
|
||||||
@@ -54,7 +59,7 @@ static size_t decodeQuantum(unsigned char *dest, const char *src)
|
|||||||
padding++;
|
padding++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p = table64;
|
p = base64;
|
||||||
|
|
||||||
while(*p && (*p != *s)) {
|
while(*p && (*p != *s)) {
|
||||||
v++;
|
v++;
|
||||||
@@ -167,26 +172,10 @@ CURLcode Curl_base64_decode(const char *src,
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static CURLcode base64_encode(const char *table64,
|
||||||
* Curl_base64_encode()
|
struct SessionHandle *data,
|
||||||
*
|
const char *inputbuff, size_t insize,
|
||||||
* Given a pointer to an input buffer and an input size, encode it and
|
char **outptr, size_t *outlen)
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
CURLcode Curl_base64_encode(struct SessionHandle *data,
|
|
||||||
const char *inputbuff, size_t insize,
|
|
||||||
char **outptr, size_t *outlen)
|
|
||||||
{
|
{
|
||||||
CURLcode error;
|
CURLcode error;
|
||||||
unsigned char ibuf[3];
|
unsigned char ibuf[3];
|
||||||
@@ -274,4 +263,52 @@ CURLcode Curl_base64_encode(struct SessionHandle *data,
|
|||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_base64_encode()
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
CURLcode Curl_base64_encode(struct SessionHandle *data,
|
||||||
|
const char *inputbuff, size_t insize,
|
||||||
|
char **outptr, size_t *outlen)
|
||||||
|
{
|
||||||
|
return base64_encode(base64, data, inputbuff, insize, outptr, outlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_base64url_encode()
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
CURLcode Curl_base64url_encode(struct SessionHandle *data,
|
||||||
|
const char *inputbuff, size_t insize,
|
||||||
|
char **outptr, size_t *outlen)
|
||||||
|
{
|
||||||
|
return base64_encode(base64url, data, inputbuff, insize, outptr, outlen);
|
||||||
|
}
|
||||||
/* ---- End of Base64 Encoding ---- */
|
/* ---- End of Base64 Encoding ---- */
|
||||||
|
@@ -69,7 +69,6 @@
|
|||||||
#define HAVE_SETMODE 1
|
#define HAVE_SETMODE 1
|
||||||
#define HAVE_SIGNAL 1
|
#define HAVE_SIGNAL 1
|
||||||
#define HAVE_SOCKET 1
|
#define HAVE_SOCKET 1
|
||||||
#define HAVE_SPNEGO 1
|
|
||||||
#define HAVE_STRDUP 1
|
#define HAVE_STRDUP 1
|
||||||
#define HAVE_STRICMP 1
|
#define HAVE_STRICMP 1
|
||||||
#define HAVE_STRTOLL 1
|
#define HAVE_STRTOLL 1
|
||||||
|
@@ -175,6 +175,15 @@
|
|||||||
/* Define if you have GSS API. */
|
/* Define if you have GSS API. */
|
||||||
#define HAVE_GSSAPI
|
#define HAVE_GSSAPI
|
||||||
|
|
||||||
|
/* Define if you have the GNU gssapi libraries */
|
||||||
|
#undef HAVE_GSSGNU
|
||||||
|
|
||||||
|
/* Define if you have the Heimdal gssapi libraries */
|
||||||
|
#define HAVE_GSSHEIMDAL
|
||||||
|
|
||||||
|
/* Define if you have the MIT gssapi libraries */
|
||||||
|
#undef HAVE_GSSMIT
|
||||||
|
|
||||||
/* Define if you have the `ucb' library (-lucb). */
|
/* Define if you have the `ucb' library (-lucb). */
|
||||||
#undef HAVE_LIBUCB
|
#undef HAVE_LIBUCB
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -260,7 +260,8 @@
|
|||||||
/* Define to 1 if you have the IoctlSocket camel case function. */
|
/* Define to 1 if you have the IoctlSocket camel case function. */
|
||||||
/* #undef HAVE_IOCTLSOCKET_CAMEL */
|
/* #undef HAVE_IOCTLSOCKET_CAMEL */
|
||||||
|
|
||||||
/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. */
|
/* Define to 1 if you have a working IoctlSocket camel case FIONBIO
|
||||||
|
function. */
|
||||||
/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
|
/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
|
||||||
|
|
||||||
/* Define to 1 if you have the <io.h> header file. */
|
/* Define to 1 if you have the <io.h> header file. */
|
||||||
@@ -480,9 +481,6 @@
|
|||||||
/* Define to 1 if you have the `socket' function. */
|
/* Define to 1 if you have the `socket' function. */
|
||||||
#define HAVE_SOCKET 1
|
#define HAVE_SOCKET 1
|
||||||
|
|
||||||
/* Define this if you have the SPNEGO library fbopenssl */
|
|
||||||
/* #undef HAVE_SPNEGO */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `SSL_get_shutdown' function. */
|
/* Define to 1 if you have the `SSL_get_shutdown' function. */
|
||||||
/*#define HAVE_SSL_GET_SHUTDOWN 1*/
|
/*#define HAVE_SSL_GET_SHUTDOWN 1*/
|
||||||
|
|
||||||
@@ -659,7 +657,8 @@
|
|||||||
/*#define PACKAGE "curl"*/
|
/*#define PACKAGE "curl"*/
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
/*#define PACKAGE_BUGREPORT "a suitable curl mailing list => http://curl.haxx.se/mail/"*/
|
/*#define PACKAGE_BUGREPORT \
|
||||||
|
"a suitable curl mailing list => http://curl.haxx.se/mail/"*/
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
/* Define to the full name of this package. */
|
||||||
/*#define PACKAGE_NAME "curl"*/
|
/*#define PACKAGE_NAME "curl"*/
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -246,7 +246,8 @@
|
|||||||
/* Define to 1 if you have the IoctlSocket camel case function. */
|
/* Define to 1 if you have the IoctlSocket camel case function. */
|
||||||
/* #undef HAVE_IOCTLSOCKET_CAMEL */
|
/* #undef HAVE_IOCTLSOCKET_CAMEL */
|
||||||
|
|
||||||
/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. */
|
/* Define to 1 if you have a working IoctlSocket camel case FIONBIO
|
||||||
|
function. */
|
||||||
/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
|
/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
|
||||||
|
|
||||||
/* Define to 1 if you have the <io.h> header file. */
|
/* Define to 1 if you have the <io.h> header file. */
|
||||||
@@ -436,9 +437,6 @@
|
|||||||
/* Define to 1 if you have the `socket' function. */
|
/* Define to 1 if you have the `socket' function. */
|
||||||
#define HAVE_SOCKET 1
|
#define HAVE_SOCKET 1
|
||||||
|
|
||||||
/* Define this if you have the SPNEGO library fbopenssl */
|
|
||||||
/* #undef HAVE_SPNEGO */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <ssl.h> header file. */
|
/* Define to 1 if you have the <ssl.h> header file. */
|
||||||
/* #undef HAVE_SSL_H */
|
/* #undef HAVE_SSL_H */
|
||||||
#define HAVE_SSL_H 1
|
#define HAVE_SSL_H 1
|
||||||
@@ -581,7 +579,8 @@
|
|||||||
#define PACKAGE "curl"
|
#define PACKAGE "curl"
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
#define PACKAGE_BUGREPORT "a suitable curl mailing list => http://curl.haxx.se/mail/"
|
#define PACKAGE_BUGREPORT \
|
||||||
|
"a suitable curl mailing list => http://curl.haxx.se/mail/"
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
/* Define to the full name of this package. */
|
||||||
#define PACKAGE_NAME "curl"
|
#define PACKAGE_NAME "curl"
|
||||||
|
@@ -547,9 +547,6 @@
|
|||||||
/* Define to 1 if you have the `socket' function. */
|
/* Define to 1 if you have the `socket' function. */
|
||||||
#define HAVE_SOCKET 1
|
#define HAVE_SOCKET 1
|
||||||
|
|
||||||
/* Define this if you have the SPNEGO library fbopenssl */
|
|
||||||
/* #undef HAVE_SPNEGO */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `SSL_get_shutdown' function. */
|
/* Define to 1 if you have the `SSL_get_shutdown' function. */
|
||||||
#define HAVE_SSL_GET_SHUTDOWN 1
|
#define HAVE_SSL_GET_SHUTDOWN 1
|
||||||
|
|
||||||
|
@@ -202,6 +202,7 @@ void Curl_conncache_foreach(struct conncache *connc,
|
|||||||
struct connectdata *conn;
|
struct connectdata *conn;
|
||||||
|
|
||||||
bundle = he->ptr;
|
bundle = he->ptr;
|
||||||
|
he = Curl_hash_next_element(&iter);
|
||||||
|
|
||||||
curr = bundle->conn_list->head;
|
curr = bundle->conn_list->head;
|
||||||
while(curr) {
|
while(curr) {
|
||||||
@@ -213,8 +214,6 @@ void Curl_conncache_foreach(struct conncache *connc,
|
|||||||
if(1 == func(conn, param))
|
if(1 == func(conn, param))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
he = Curl_hash_next_element(&iter);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012, 2013, Linus Nielsen Feltzing, <linus@haxx.se>
|
* Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se>
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -25,7 +25,8 @@
|
|||||||
struct conncache {
|
struct conncache {
|
||||||
struct curl_hash *hash;
|
struct curl_hash *hash;
|
||||||
size_t num_connections;
|
size_t num_connections;
|
||||||
size_t next_connection_id;
|
long next_connection_id;
|
||||||
|
struct timeval last_cleanup;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct conncache *Curl_conncache_init(int size);
|
struct conncache *Curl_conncache_init(int size);
|
||||||
|
@@ -94,7 +94,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error);
|
|||||||
#define KEEPALIVE_FACTOR(x)
|
#define KEEPALIVE_FACTOR(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_WINSOCK_H) && !defined(SIO_KEEPALIVE_VALS)
|
#if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
|
||||||
#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
|
#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
|
||||||
|
|
||||||
struct tcp_keepalive {
|
struct tcp_keepalive {
|
||||||
@@ -1054,7 +1054,7 @@ singleipconnect(struct connectdata *conn,
|
|||||||
|
|
||||||
conn->connecttime = Curl_tvnow();
|
conn->connecttime = Curl_tvnow();
|
||||||
if(conn->num_addr > 1)
|
if(conn->num_addr > 1)
|
||||||
Curl_expire(data, conn->timeoutms_per_addr);
|
Curl_expire_latest(data, conn->timeoutms_per_addr);
|
||||||
|
|
||||||
/* Connect TCP sockets, bind UDP */
|
/* Connect TCP sockets, bind UDP */
|
||||||
if(!isconnected && (conn->socktype == SOCK_STREAM)) {
|
if(!isconnected && (conn->socktype == SOCK_STREAM)) {
|
||||||
|
56
lib/cookie.c
56
lib/cookie.c
@@ -95,6 +95,7 @@ Example set of cookies:
|
|||||||
#include "strtoofft.h"
|
#include "strtoofft.h"
|
||||||
#include "rawstr.h"
|
#include "rawstr.h"
|
||||||
#include "curl_memrchr.h"
|
#include "curl_memrchr.h"
|
||||||
|
#include "inet_pton.h"
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
@@ -319,6 +320,28 @@ static void remove_expired(struct CookieInfo *cookies)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return true if the given string is an IP(v4|v6) address.
|
||||||
|
*/
|
||||||
|
static bool isip(const char *domain)
|
||||||
|
{
|
||||||
|
struct in_addr addr;
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
struct in6_addr addr6;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(Curl_inet_pton(AF_INET, domain, &addr)
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
|| Curl_inet_pton(AF_INET6, domain, &addr6)
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
/* domain name given as IP address */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
*
|
*
|
||||||
* Curl_cookie_add()
|
* Curl_cookie_add()
|
||||||
@@ -439,24 +462,33 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(Curl_raw_equal("domain", name)) {
|
else if(Curl_raw_equal("domain", name)) {
|
||||||
|
bool is_ip;
|
||||||
|
const char *dotp;
|
||||||
|
|
||||||
/* Now, we make sure that our host is within the given domain,
|
/* Now, we make sure that our host is within the given domain,
|
||||||
or the given domain is not valid and thus cannot be set. */
|
or the given domain is not valid and thus cannot be set. */
|
||||||
|
|
||||||
if('.' == whatptr[0])
|
if('.' == whatptr[0])
|
||||||
whatptr++; /* ignore preceding dot */
|
whatptr++; /* ignore preceding dot */
|
||||||
|
|
||||||
if(!domain || tailmatch(whatptr, domain)) {
|
is_ip = isip(domain ? domain : whatptr);
|
||||||
const char *tailptr=whatptr;
|
|
||||||
if(tailptr[0] == '.')
|
/* check for more dots */
|
||||||
tailptr++;
|
dotp = strchr(whatptr, '.');
|
||||||
strstore(&co->domain, tailptr); /* don't prefix w/dots
|
if(!dotp)
|
||||||
internally */
|
domain=":";
|
||||||
|
|
||||||
|
if(!domain
|
||||||
|
|| (is_ip && !strcmp(whatptr, domain))
|
||||||
|
|| (!is_ip && tailmatch(whatptr, domain))) {
|
||||||
|
strstore(&co->domain, whatptr);
|
||||||
if(!co->domain) {
|
if(!co->domain) {
|
||||||
badcookie = TRUE;
|
badcookie = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
co->tailmatch=TRUE; /* we always do that if the domain name was
|
if(!is_ip)
|
||||||
given */
|
co->tailmatch=TRUE; /* we always do that if the domain name was
|
||||||
|
given */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* we did not get a tailmatch and then the attempted set domain
|
/* we did not get a tailmatch and then the attempted set domain
|
||||||
@@ -968,6 +1000,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
|||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
struct Cookie *mainco=NULL;
|
struct Cookie *mainco=NULL;
|
||||||
size_t matches = 0;
|
size_t matches = 0;
|
||||||
|
bool is_ip;
|
||||||
|
|
||||||
if(!c || !c->cookies)
|
if(!c || !c->cookies)
|
||||||
return NULL; /* no cookie struct or no cookies in the struct */
|
return NULL; /* no cookie struct or no cookies in the struct */
|
||||||
@@ -975,6 +1008,9 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
|||||||
/* at first, remove expired cookies */
|
/* at first, remove expired cookies */
|
||||||
remove_expired(c);
|
remove_expired(c);
|
||||||
|
|
||||||
|
/* check if host is an IP(v4|v6) address */
|
||||||
|
is_ip = isip(host);
|
||||||
|
|
||||||
co = c->cookies;
|
co = c->cookies;
|
||||||
|
|
||||||
while(co) {
|
while(co) {
|
||||||
@@ -986,8 +1022,8 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
|||||||
|
|
||||||
/* now check if the domain is correct */
|
/* now check if the domain is correct */
|
||||||
if(!co->domain ||
|
if(!co->domain ||
|
||||||
(co->tailmatch && tailmatch(co->domain, host)) ||
|
(co->tailmatch && !is_ip && tailmatch(co->domain, host)) ||
|
||||||
(!co->tailmatch && Curl_raw_equal(host, co->domain)) ) {
|
((!co->tailmatch || is_ip) && Curl_raw_equal(host, co->domain)) ) {
|
||||||
/* the right part of the host matches the domain stuff in the
|
/* the right part of the host matches the domain stuff in the
|
||||||
cookie data */
|
cookie data */
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -25,6 +25,9 @@
|
|||||||
CURLcode Curl_base64_encode(struct SessionHandle *data,
|
CURLcode Curl_base64_encode(struct SessionHandle *data,
|
||||||
const char *inputbuff, size_t insize,
|
const char *inputbuff, size_t insize,
|
||||||
char **outptr, size_t *outlen);
|
char **outptr, size_t *outlen);
|
||||||
|
CURLcode Curl_base64url_encode(struct SessionHandle *data,
|
||||||
|
const char *inputbuff, size_t insize,
|
||||||
|
char **outptr, size_t *outlen);
|
||||||
|
|
||||||
CURLcode Curl_base64_decode(const char *src,
|
CURLcode Curl_base64_decode(const char *src,
|
||||||
unsigned char **outptr, size_t *outlen);
|
unsigned char **outptr, size_t *outlen);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 2011 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -27,15 +27,21 @@
|
|||||||
#include "curl_gssapi.h"
|
#include "curl_gssapi.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
|
|
||||||
|
static const char spnego_oid_bytes[] = "\x2b\x06\x01\x05\x05\x02";
|
||||||
|
gss_OID_desc Curl_spnego_mech_oid = { 6, &spnego_oid_bytes };
|
||||||
|
static const char krb5_oid_bytes[] = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02";
|
||||||
|
gss_OID_desc Curl_krb5_mech_oid = { 9, &krb5_oid_bytes };
|
||||||
|
|
||||||
OM_uint32 Curl_gss_init_sec_context(
|
OM_uint32 Curl_gss_init_sec_context(
|
||||||
struct SessionHandle *data,
|
struct SessionHandle *data,
|
||||||
OM_uint32 * minor_status,
|
OM_uint32 *minor_status,
|
||||||
gss_ctx_id_t * context,
|
gss_ctx_id_t *context,
|
||||||
gss_name_t target_name,
|
gss_name_t target_name,
|
||||||
|
gss_OID mech_type,
|
||||||
gss_channel_bindings_t input_chan_bindings,
|
gss_channel_bindings_t input_chan_bindings,
|
||||||
gss_buffer_t input_token,
|
gss_buffer_t input_token,
|
||||||
gss_buffer_t output_token,
|
gss_buffer_t output_token,
|
||||||
OM_uint32 * ret_flags)
|
OM_uint32 *ret_flags)
|
||||||
{
|
{
|
||||||
OM_uint32 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
|
OM_uint32 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
|
||||||
|
|
||||||
@@ -55,7 +61,7 @@ OM_uint32 Curl_gss_init_sec_context(
|
|||||||
GSS_C_NO_CREDENTIAL, /* cred_handle */
|
GSS_C_NO_CREDENTIAL, /* cred_handle */
|
||||||
context,
|
context,
|
||||||
target_name,
|
target_name,
|
||||||
GSS_C_NO_OID, /* mech_type */
|
mech_type,
|
||||||
req_flags,
|
req_flags,
|
||||||
0, /* time_req */
|
0, /* time_req */
|
||||||
input_chan_bindings,
|
input_chan_bindings,
|
||||||
|
@@ -39,18 +39,21 @@
|
|||||||
# include <gssapi.h>
|
# include <gssapi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern gss_OID_desc Curl_spnego_mech_oid;
|
||||||
|
extern gss_OID_desc Curl_krb5_mech_oid;
|
||||||
|
|
||||||
/* Common method for using gss api */
|
/* Common method for using GSS-API */
|
||||||
|
|
||||||
OM_uint32 Curl_gss_init_sec_context(
|
OM_uint32 Curl_gss_init_sec_context(
|
||||||
struct SessionHandle *data,
|
struct SessionHandle *data,
|
||||||
OM_uint32 * minor_status,
|
OM_uint32 *minor_status,
|
||||||
gss_ctx_id_t * context,
|
gss_ctx_id_t *context,
|
||||||
gss_name_t target_name,
|
gss_name_t target_name,
|
||||||
|
gss_OID mech_type,
|
||||||
gss_channel_bindings_t input_chan_bindings,
|
gss_channel_bindings_t input_chan_bindings,
|
||||||
gss_buffer_t input_token,
|
gss_buffer_t input_token,
|
||||||
gss_buffer_t output_token,
|
gss_buffer_t output_token,
|
||||||
OM_uint32 * ret_flags);
|
OM_uint32 *ret_flags);
|
||||||
|
|
||||||
#endif /* HAVE_GSSAPI */
|
#endif /* HAVE_GSSAPI */
|
||||||
|
|
||||||
|
@@ -353,6 +353,9 @@ void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm)
|
|||||||
ntlm->has_handles = 0;
|
ntlm->has_handles = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ntlm->max_token_length = 0;
|
||||||
|
Curl_safefree(ntlm->output_token);
|
||||||
|
|
||||||
Curl_sspi_free_identity(ntlm->p_identity);
|
Curl_sspi_free_identity(ntlm->p_identity);
|
||||||
ntlm->p_identity = NULL;
|
ntlm->p_identity = NULL;
|
||||||
}
|
}
|
||||||
@@ -409,11 +412,11 @@ CURLcode Curl_ntlm_create_type1_message(const char *userp,
|
|||||||
(*) -> Optional
|
(*) -> Optional
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsigned char ntlmbuf[NTLM_BUFSIZE];
|
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_SSPI
|
#ifdef USE_WINDOWS_SSPI
|
||||||
|
|
||||||
|
PSecPkgInfo SecurityPackage;
|
||||||
SecBuffer type_1_buf;
|
SecBuffer type_1_buf;
|
||||||
SecBufferDesc type_1_desc;
|
SecBufferDesc type_1_desc;
|
||||||
SECURITY_STATUS status;
|
SECURITY_STATUS status;
|
||||||
@@ -422,6 +425,22 @@ CURLcode Curl_ntlm_create_type1_message(const char *userp,
|
|||||||
|
|
||||||
Curl_ntlm_sspi_cleanup(ntlm);
|
Curl_ntlm_sspi_cleanup(ntlm);
|
||||||
|
|
||||||
|
/* Query the security package for NTLM */
|
||||||
|
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT("NTLM"),
|
||||||
|
&SecurityPackage);
|
||||||
|
if(status != SEC_E_OK)
|
||||||
|
return CURLE_NOT_BUILT_IN;
|
||||||
|
|
||||||
|
ntlm->max_token_length = SecurityPackage->cbMaxToken;
|
||||||
|
|
||||||
|
/* Release the package buffer as it is not required anymore */
|
||||||
|
s_pSecFn->FreeContextBuffer(SecurityPackage);
|
||||||
|
|
||||||
|
/* Allocate our output buffer */
|
||||||
|
ntlm->output_token = malloc(ntlm->max_token_length);
|
||||||
|
if(!ntlm->output_token)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
if(userp && *userp) {
|
if(userp && *userp) {
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
|
|
||||||
@@ -450,9 +469,9 @@ CURLcode Curl_ntlm_create_type1_message(const char *userp,
|
|||||||
type_1_desc.ulVersion = SECBUFFER_VERSION;
|
type_1_desc.ulVersion = SECBUFFER_VERSION;
|
||||||
type_1_desc.cBuffers = 1;
|
type_1_desc.cBuffers = 1;
|
||||||
type_1_desc.pBuffers = &type_1_buf;
|
type_1_desc.pBuffers = &type_1_buf;
|
||||||
type_1_buf.cbBuffer = NTLM_BUFSIZE;
|
|
||||||
type_1_buf.BufferType = SECBUFFER_TOKEN;
|
type_1_buf.BufferType = SECBUFFER_TOKEN;
|
||||||
type_1_buf.pvBuffer = ntlmbuf;
|
type_1_buf.pvBuffer = ntlm->output_token;
|
||||||
|
type_1_buf.cbBuffer = curlx_uztoul(ntlm->max_token_length);
|
||||||
|
|
||||||
/* Generate our type-1 message */
|
/* Generate our type-1 message */
|
||||||
status = s_pSecFn->InitializeSecurityContext(&ntlm->handle, NULL,
|
status = s_pSecFn->InitializeSecurityContext(&ntlm->handle, NULL,
|
||||||
@@ -478,6 +497,7 @@ CURLcode Curl_ntlm_create_type1_message(const char *userp,
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
unsigned char ntlmbuf[NTLM_BUFSIZE];
|
||||||
const char *host = ""; /* empty */
|
const char *host = ""; /* empty */
|
||||||
const char *domain = ""; /* empty */
|
const char *domain = ""; /* empty */
|
||||||
size_t hostlen = 0;
|
size_t hostlen = 0;
|
||||||
@@ -555,7 +575,12 @@ CURLcode Curl_ntlm_create_type1_message(const char *userp,
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* Return with binary blob encoded into base64 */
|
/* Return with binary blob encoded into base64 */
|
||||||
|
#ifdef USE_WINDOWS_SSPI
|
||||||
|
return Curl_base64_encode(NULL, (char *)ntlm->output_token, size,
|
||||||
|
outptr, outlen);
|
||||||
|
#else
|
||||||
return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
|
return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -602,10 +627,10 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
|
|||||||
(*) -> Optional
|
(*) -> Optional
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsigned char ntlmbuf[NTLM_BUFSIZE];
|
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_SSPI
|
#ifdef USE_WINDOWS_SSPI
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
SecBuffer type_2_buf;
|
SecBuffer type_2_buf;
|
||||||
SecBuffer type_3_buf;
|
SecBuffer type_3_buf;
|
||||||
SecBufferDesc type_2_desc;
|
SecBufferDesc type_2_desc;
|
||||||
@@ -631,8 +656,8 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
|
|||||||
type_3_desc.cBuffers = 1;
|
type_3_desc.cBuffers = 1;
|
||||||
type_3_desc.pBuffers = &type_3_buf;
|
type_3_desc.pBuffers = &type_3_buf;
|
||||||
type_3_buf.BufferType = SECBUFFER_TOKEN;
|
type_3_buf.BufferType = SECBUFFER_TOKEN;
|
||||||
type_3_buf.pvBuffer = ntlmbuf;
|
type_3_buf.pvBuffer = ntlm->output_token;
|
||||||
type_3_buf.cbBuffer = NTLM_BUFSIZE;
|
type_3_buf.cbBuffer = curlx_uztoul(ntlm->max_token_length);
|
||||||
|
|
||||||
/* Generate our type-3 message */
|
/* Generate our type-3 message */
|
||||||
status = s_pSecFn->InitializeSecurityContext(&ntlm->handle,
|
status = s_pSecFn->InitializeSecurityContext(&ntlm->handle,
|
||||||
@@ -651,9 +676,17 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
|
|||||||
|
|
||||||
size = type_3_buf.cbBuffer;
|
size = type_3_buf.cbBuffer;
|
||||||
|
|
||||||
|
/* Return with binary blob encoded into base64 */
|
||||||
|
result = Curl_base64_encode(NULL, (char *)ntlm->output_token, size,
|
||||||
|
outptr, outlen);
|
||||||
|
|
||||||
Curl_ntlm_sspi_cleanup(ntlm);
|
Curl_ntlm_sspi_cleanup(ntlm);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
unsigned char ntlmbuf[NTLM_BUFSIZE];
|
||||||
int lmrespoff;
|
int lmrespoff;
|
||||||
unsigned char lmresp[24]; /* fixed-size */
|
unsigned char lmresp[24]; /* fixed-size */
|
||||||
#if USE_NTRESPONSES
|
#if USE_NTRESPONSES
|
||||||
@@ -969,10 +1002,9 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
|
|||||||
if(res)
|
if(res)
|
||||||
return CURLE_CONV_FAILED;
|
return CURLE_CONV_FAILED;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Return with binary blob encoded into base64 */
|
/* Return with binary blob encoded into base64 */
|
||||||
return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
|
return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* USE_NTLM */
|
#endif /* USE_NTLM */
|
||||||
|
@@ -39,6 +39,9 @@
|
|||||||
#ifdef HAVE_SIGNAL_H
|
#ifdef HAVE_SIGNAL_H
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_PWD_H
|
||||||
|
#include <pwd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
@@ -117,6 +120,10 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
|
|||||||
char *slash, *domain = NULL;
|
char *slash, *domain = NULL;
|
||||||
const char *ntlm_auth = NULL;
|
const char *ntlm_auth = NULL;
|
||||||
char *ntlm_auth_alloc = NULL;
|
char *ntlm_auth_alloc = NULL;
|
||||||
|
#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
|
||||||
|
struct passwd pw, *pw_res;
|
||||||
|
char pwbuf[1024];
|
||||||
|
#endif
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
/* Return if communication with ntlm_auth already set up */
|
/* Return if communication with ntlm_auth already set up */
|
||||||
@@ -125,6 +132,30 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
|
||||||
username = userp;
|
username = userp;
|
||||||
|
/* The real ntlm_auth really doesn't like being invoked with an
|
||||||
|
empty username. It won't make inferences for itself, and expects
|
||||||
|
the client to do so (mostly because it's really designed for
|
||||||
|
servers like squid to use for auth, and client support is an
|
||||||
|
afterthought for it). So try hard to provide a suitable username
|
||||||
|
if we don't already have one. But if we can't, provide the
|
||||||
|
empty one anyway. Perhaps they have an implementation of the
|
||||||
|
ntlm_auth helper which *doesn't* need it so we might as well try */
|
||||||
|
if(!username || !username[0]) {
|
||||||
|
username = getenv("NTLMUSER");
|
||||||
|
if(!username || !username[0])
|
||||||
|
username = getenv("LOGNAME");
|
||||||
|
if(!username || !username[0])
|
||||||
|
username = getenv("USER");
|
||||||
|
#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
|
||||||
|
if((!username || !username[0]) &&
|
||||||
|
!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res) &&
|
||||||
|
pw_res) {
|
||||||
|
username = pw.pw_name;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if(!username || !username[0])
|
||||||
|
username = userp;
|
||||||
|
}
|
||||||
slash = strpbrk(username, "\\/");
|
slash = strpbrk(username, "\\/");
|
||||||
if(slash) {
|
if(slash) {
|
||||||
if((domain = strdup(username)) == NULL)
|
if((domain = strdup(username)) == NULL)
|
||||||
@@ -227,11 +258,11 @@ done:
|
|||||||
static CURLcode ntlm_wb_response(struct connectdata *conn,
|
static CURLcode ntlm_wb_response(struct connectdata *conn,
|
||||||
const char *input, curlntlm state)
|
const char *input, curlntlm state)
|
||||||
{
|
{
|
||||||
ssize_t size;
|
char *buf = malloc(NTLM_BUFSIZE);
|
||||||
char buf[NTLM_BUFSIZE];
|
size_t len_in = strlen(input), len_out = 0;
|
||||||
char *tmpbuf = buf;
|
|
||||||
size_t len_in = strlen(input);
|
if(!buf)
|
||||||
size_t len_out = sizeof(buf);
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
while(len_in > 0) {
|
while(len_in > 0) {
|
||||||
ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in);
|
ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in);
|
||||||
@@ -246,8 +277,11 @@ static CURLcode ntlm_wb_response(struct connectdata *conn,
|
|||||||
len_in -= written;
|
len_in -= written;
|
||||||
}
|
}
|
||||||
/* Read one line */
|
/* Read one line */
|
||||||
while(len_out > 0) {
|
while(1) {
|
||||||
size = sread(conn->ntlm_auth_hlpr_socket, tmpbuf, len_out);
|
ssize_t size;
|
||||||
|
char *newbuf;
|
||||||
|
|
||||||
|
size = sread(conn->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE);
|
||||||
if(size == -1) {
|
if(size == -1) {
|
||||||
if(errno == EINTR)
|
if(errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
@@ -255,22 +289,28 @@ static CURLcode ntlm_wb_response(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
else if(size == 0)
|
else if(size == 0)
|
||||||
goto done;
|
goto done;
|
||||||
else if(tmpbuf[size - 1] == '\n') {
|
|
||||||
tmpbuf[size - 1] = '\0';
|
len_out += size;
|
||||||
|
if(buf[len_out - 1] == '\n') {
|
||||||
|
buf[len_out - 1] = '\0';
|
||||||
goto wrfinish;
|
goto wrfinish;
|
||||||
}
|
}
|
||||||
tmpbuf += size;
|
newbuf = realloc(buf, len_out + NTLM_BUFSIZE);
|
||||||
len_out -= size;
|
if(!newbuf) {
|
||||||
|
free(buf);
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
buf = newbuf;
|
||||||
}
|
}
|
||||||
goto done;
|
goto done;
|
||||||
wrfinish:
|
wrfinish:
|
||||||
/* Samba/winbind installed but not configured */
|
/* Samba/winbind installed but not configured */
|
||||||
if(state == NTLMSTATE_TYPE1 &&
|
if(state == NTLMSTATE_TYPE1 &&
|
||||||
size == 3 &&
|
len_out == 3 &&
|
||||||
buf[0] == 'P' && buf[1] == 'W')
|
buf[0] == 'P' && buf[1] == 'W')
|
||||||
return CURLE_REMOTE_ACCESS_DENIED;
|
return CURLE_REMOTE_ACCESS_DENIED;
|
||||||
/* invalid response */
|
/* invalid response */
|
||||||
if(size < 4)
|
if(len_out < 4)
|
||||||
goto done;
|
goto done;
|
||||||
if(state == NTLMSTATE_TYPE1 &&
|
if(state == NTLMSTATE_TYPE1 &&
|
||||||
(buf[0]!='Y' || buf[1]!='R' || buf[2]!=' '))
|
(buf[0]!='Y' || buf[1]!='R' || buf[2]!=' '))
|
||||||
@@ -280,9 +320,11 @@ wrfinish:
|
|||||||
(buf[0]!='A' || buf[1]!='F' || buf[2]!=' '))
|
(buf[0]!='A' || buf[1]!='F' || buf[2]!=' '))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
conn->response_header = aprintf("NTLM %.*s", size - 4, buf + 3);
|
conn->response_header = aprintf("NTLM %.*s", len_out - 4, buf + 3);
|
||||||
|
free(buf);
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
done:
|
done:
|
||||||
|
free(buf);
|
||||||
return CURLE_REMOTE_ACCESS_DENIED;
|
return CURLE_REMOTE_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -53,6 +53,10 @@
|
|||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
#if defined(USE_WINDOWS_SSPI)
|
||||||
|
extern void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH) && !defined(USE_WINDOWS_SSPI)
|
#if !defined(CURL_DISABLE_CRYPTO_AUTH) && !defined(USE_WINDOWS_SSPI)
|
||||||
#define DIGEST_QOP_VALUE_AUTH (1 << 0)
|
#define DIGEST_QOP_VALUE_AUTH (1 << 0)
|
||||||
#define DIGEST_QOP_VALUE_AUTH_INT (1 << 1)
|
#define DIGEST_QOP_VALUE_AUTH_INT (1 << 1)
|
||||||
@@ -120,6 +124,26 @@ static CURLcode sasl_digest_get_qop_values(const char *options, int *value)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(USE_WINDOWS_SSPI)
|
||||||
|
/*
|
||||||
|
* Curl_sasl_build_spn()
|
||||||
|
*
|
||||||
|
* This is used to build a SPN string in the format service/host.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
*
|
||||||
|
* serivce [in] - The service type such as www, smtp, pop or imap.
|
||||||
|
* instance [in] - The instance name such as the host nme or realm.
|
||||||
|
*
|
||||||
|
* Returns a pointer to the newly allocated SPN.
|
||||||
|
*/
|
||||||
|
char *Curl_sasl_build_spn(const char *service, const char *host)
|
||||||
|
{
|
||||||
|
/* Generate and return our SPN */
|
||||||
|
return aprintf("%s/%s", service, host);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_sasl_create_plain_message()
|
* Curl_sasl_create_plain_message()
|
||||||
*
|
*
|
||||||
@@ -421,7 +445,7 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
|||||||
char nonceCount[] = "00000001";
|
char nonceCount[] = "00000001";
|
||||||
char method[] = "AUTHENTICATE";
|
char method[] = "AUTHENTICATE";
|
||||||
char qop[] = DIGEST_QOP_VALUE_STRING_AUTH;
|
char qop[] = DIGEST_QOP_VALUE_STRING_AUTH;
|
||||||
char uri[128];
|
char *spn = NULL;
|
||||||
|
|
||||||
/* Decode the challange message */
|
/* Decode the challange message */
|
||||||
result = sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce),
|
result = sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce),
|
||||||
@@ -486,19 +510,24 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
|||||||
for(i = 0; i < MD5_DIGEST_LEN; i++)
|
for(i = 0; i < MD5_DIGEST_LEN; i++)
|
||||||
snprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]);
|
snprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]);
|
||||||
|
|
||||||
/* Prepare the URL string */
|
/* Generate our SPN */
|
||||||
snprintf(uri, sizeof(uri), "%s/%s", service, realm);
|
spn = Curl_sasl_build_spn(service, realm);
|
||||||
|
if(!spn)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
/* Calculate H(A2) */
|
/* Calculate H(A2) */
|
||||||
ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
|
ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
|
||||||
if(!ctxt)
|
if(!ctxt) {
|
||||||
|
Curl_safefree(spn);
|
||||||
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
Curl_MD5_update(ctxt, (const unsigned char *) method,
|
Curl_MD5_update(ctxt, (const unsigned char *) method,
|
||||||
curlx_uztoui(strlen(method)));
|
curlx_uztoui(strlen(method)));
|
||||||
Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
|
Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
|
||||||
Curl_MD5_update(ctxt, (const unsigned char *) uri,
|
Curl_MD5_update(ctxt, (const unsigned char *) spn,
|
||||||
curlx_uztoui(strlen(uri)));
|
curlx_uztoui(strlen(spn)));
|
||||||
Curl_MD5_final(ctxt, digest);
|
Curl_MD5_final(ctxt, digest);
|
||||||
|
|
||||||
for(i = 0; i < MD5_DIGEST_LEN; i++)
|
for(i = 0; i < MD5_DIGEST_LEN; i++)
|
||||||
@@ -506,8 +535,11 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
|||||||
|
|
||||||
/* Now calculate the response hash */
|
/* Now calculate the response hash */
|
||||||
ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
|
ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
|
||||||
if(!ctxt)
|
if(!ctxt) {
|
||||||
|
Curl_safefree(spn);
|
||||||
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
Curl_MD5_update(ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN);
|
Curl_MD5_update(ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN);
|
||||||
Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
|
Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
|
||||||
@@ -536,17 +568,19 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
|||||||
"cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s,"
|
"cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s,"
|
||||||
"qop=%s",
|
"qop=%s",
|
||||||
userp, realm, nonce,
|
userp, realm, nonce,
|
||||||
cnonce, nonceCount, uri, resp_hash_hex, qop);
|
cnonce, nonceCount, spn, resp_hash_hex, qop);
|
||||||
|
Curl_safefree(spn);
|
||||||
if(!response)
|
if(!response)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
/* Base64 encode the response */
|
/* Base64 encode the response */
|
||||||
result = Curl_base64_encode(data, response, 0, outptr, outlen);
|
result = Curl_base64_encode(data, response, 0, outptr, outlen);
|
||||||
|
|
||||||
free(response);
|
Curl_safefree(response);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif /* USE_WINDOWS_SSPI */
|
#endif /* !USE_WINDOWS_SSPI */
|
||||||
|
|
||||||
#endif /* CURL_DISABLE_CRYPTO_AUTH */
|
#endif /* CURL_DISABLE_CRYPTO_AUTH */
|
||||||
|
|
||||||
@@ -688,12 +722,17 @@ CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data,
|
|||||||
*/
|
*/
|
||||||
void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
|
void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
|
||||||
{
|
{
|
||||||
|
#if defined(USE_WINDOWS_SSPI)
|
||||||
|
/* Cleanup the gssapi structure */
|
||||||
|
if(authused == SASL_MECH_GSSAPI) {
|
||||||
|
Curl_sasl_gssapi_cleanup(&conn->krb5);
|
||||||
|
}
|
||||||
#ifdef USE_NTLM
|
#ifdef USE_NTLM
|
||||||
/* Cleanup the ntlm structure */
|
/* Cleanup the ntlm structure */
|
||||||
if(authused == SASL_MECH_NTLM) {
|
else if(authused == SASL_MECH_NTLM) {
|
||||||
Curl_ntlm_sspi_cleanup(&conn->ntlm);
|
Curl_ntlm_sspi_cleanup(&conn->ntlm);
|
||||||
}
|
}
|
||||||
(void)conn;
|
#endif
|
||||||
#else
|
#else
|
||||||
/* Reserved for future use */
|
/* Reserved for future use */
|
||||||
(void)conn;
|
(void)conn;
|
||||||
|
@@ -28,6 +28,10 @@ struct SessionHandle;
|
|||||||
struct connectdata;
|
struct connectdata;
|
||||||
struct ntlmdata;
|
struct ntlmdata;
|
||||||
|
|
||||||
|
#if defined(USE_WINDOWS_SSPI)
|
||||||
|
struct kerberos5data;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Authentication mechanism values */
|
/* Authentication mechanism values */
|
||||||
#define SASL_AUTH_NONE 0
|
#define SASL_AUTH_NONE 0
|
||||||
#define SASL_AUTH_ANY ~0U
|
#define SASL_AUTH_ANY ~0U
|
||||||
@@ -57,6 +61,13 @@ struct ntlmdata;
|
|||||||
(wordlen == (sizeof(mech) - 1) / sizeof(char) && \
|
(wordlen == (sizeof(mech) - 1) / sizeof(char) && \
|
||||||
!memcmp(line, mech, wordlen))
|
!memcmp(line, mech, wordlen))
|
||||||
|
|
||||||
|
/* This is used to build a SPN string */
|
||||||
|
#if !defined(USE_WINDOWS_SSPI)
|
||||||
|
char *Curl_sasl_build_spn(const char *service, const char *instance);
|
||||||
|
#else
|
||||||
|
TCHAR *Curl_sasl_build_spn(const char *service, const char *instance);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This is used to generate a base64 encoded PLAIN authentication message */
|
/* This is used to generate a base64 encoded PLAIN authentication message */
|
||||||
CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
|
CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
|
||||||
const char *userp,
|
const char *userp,
|
||||||
@@ -112,6 +123,27 @@ CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
|
|||||||
|
|
||||||
#endif /* USE_NTLM */
|
#endif /* USE_NTLM */
|
||||||
|
|
||||||
|
#if defined(USE_WINDOWS_SSPI)
|
||||||
|
/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) user token
|
||||||
|
message */
|
||||||
|
CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
|
||||||
|
const char *userp,
|
||||||
|
const char *passwdp,
|
||||||
|
const char *service,
|
||||||
|
const bool mutual,
|
||||||
|
const char *chlg64,
|
||||||
|
struct kerberos5data *krb5,
|
||||||
|
char **outptr, size_t *outlen);
|
||||||
|
|
||||||
|
/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) security
|
||||||
|
token message */
|
||||||
|
CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||||
|
const char *input,
|
||||||
|
struct kerberos5data *krb5,
|
||||||
|
char **outptr,
|
||||||
|
size_t *outlen);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This is used to generate a base64 encoded XOAUTH2 authentication message
|
/* This is used to generate a base64 encoded XOAUTH2 authentication message
|
||||||
containing the user name and bearer token */
|
containing the user name and bearer token */
|
||||||
CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data,
|
CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data,
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
|
* Copyright (C) 2014, Steve Holme, <steve_holme@hotmail.com>.
|
||||||
* Copyright (C) 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
@@ -20,12 +21,13 @@
|
|||||||
*
|
*
|
||||||
* RFC2831 DIGEST-MD5 authentication
|
* RFC2831 DIGEST-MD5 authentication
|
||||||
* RFC4422 Simple Authentication and Security Layer (SASL)
|
* RFC4422 Simple Authentication and Security Layer (SASL)
|
||||||
|
* RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include "curl_setup.h"
|
#include "curl_setup.h"
|
||||||
|
|
||||||
#if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
#if defined(USE_WINDOWS_SSPI)
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
@@ -34,6 +36,7 @@
|
|||||||
#include "curl_base64.h"
|
#include "curl_base64.h"
|
||||||
#include "warnless.h"
|
#include "warnless.h"
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
|
#include "curl_multibyte.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
@@ -41,6 +44,55 @@
|
|||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_sasl_build_spn()
|
||||||
|
*
|
||||||
|
* This is used to build a SPN string in the format service/host.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
*
|
||||||
|
* serivce [in] - The service type such as www, smtp, pop or imap.
|
||||||
|
* instance [in] - The instance name such as the host nme or realm.
|
||||||
|
*
|
||||||
|
* Returns a pointer to the newly allocated SPN.
|
||||||
|
*/
|
||||||
|
TCHAR *Curl_sasl_build_spn(const char *service, const char *host)
|
||||||
|
{
|
||||||
|
char *utf8_spn = NULL;
|
||||||
|
TCHAR *tchar_spn = NULL;
|
||||||
|
|
||||||
|
/* Note: We could use DsMakeSPN() or DsClientMakeSpnForTargetServer() rather
|
||||||
|
than doing this ourselves but the first is only available in Windows XP
|
||||||
|
and Windows Server 2003 and the latter is only available in Windows 2000
|
||||||
|
but not Windows95/98/ME or Windows NT4.0 unless the Active Directory
|
||||||
|
Client Extensions are installed. As such it is far simpler for us to
|
||||||
|
formulate the SPN instead. */
|
||||||
|
|
||||||
|
/* Allocate our UTF8 based SPN */
|
||||||
|
utf8_spn = aprintf("%s/%s", service, host);
|
||||||
|
if(!utf8_spn) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate our TCHAR based SPN */
|
||||||
|
tchar_spn = Curl_convert_UTF8_to_tchar(utf8_spn);
|
||||||
|
if(!tchar_spn) {
|
||||||
|
Curl_safefree(utf8_spn);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the UTF8 variant when operating with Unicode */
|
||||||
|
if(utf8_spn != tchar_spn)
|
||||||
|
Curl_safefree(utf8_spn);
|
||||||
|
|
||||||
|
/* Return our newly allocated SPN */
|
||||||
|
return tchar_spn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||||
/*
|
/*
|
||||||
* Curl_sasl_create_digest_md5_message()
|
* Curl_sasl_create_digest_md5_message()
|
||||||
*
|
*
|
||||||
@@ -68,10 +120,11 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
|||||||
char **outptr, size_t *outlen)
|
char **outptr, size_t *outlen)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
char *spn = NULL;
|
TCHAR *spn = NULL;
|
||||||
size_t chlglen = 0;
|
size_t chlglen = 0;
|
||||||
|
size_t resp_max = 0;
|
||||||
unsigned char *chlg = NULL;
|
unsigned char *chlg = NULL;
|
||||||
unsigned char resp[1024];
|
unsigned char *resp = NULL;
|
||||||
CredHandle handle;
|
CredHandle handle;
|
||||||
CtxtHandle ctx;
|
CtxtHandle ctx;
|
||||||
PSecPkgInfo SecurityPackage;
|
PSecPkgInfo SecurityPackage;
|
||||||
@@ -107,18 +160,37 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
|||||||
&SecurityPackage);
|
&SecurityPackage);
|
||||||
if(status != SEC_E_OK) {
|
if(status != SEC_E_OK) {
|
||||||
Curl_safefree(chlg);
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
return CURLE_NOT_BUILT_IN;
|
return CURLE_NOT_BUILT_IN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate our SPN */
|
resp_max = SecurityPackage->cbMaxToken;
|
||||||
spn = aprintf("%s/%s", service, data->easy_conn->host.name);
|
|
||||||
if(!spn)
|
/* Release the package buffer as it is not required anymore */
|
||||||
|
s_pSecFn->FreeContextBuffer(SecurityPackage);
|
||||||
|
|
||||||
|
/* Allocate our response buffer */
|
||||||
|
resp = malloc(resp_max);
|
||||||
|
if(!resp) {
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate our SPN */
|
||||||
|
spn = Curl_sasl_build_spn(service, data->easy_conn->host.name);
|
||||||
|
if(!spn) {
|
||||||
|
Curl_safefree(resp);
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
/* Populate our identity structure */
|
/* Populate our identity structure */
|
||||||
result = Curl_create_sspi_identity(userp, passwdp, &identity);
|
result = Curl_create_sspi_identity(userp, passwdp, &identity);
|
||||||
if(result) {
|
if(result) {
|
||||||
Curl_safefree(spn);
|
Curl_safefree(spn);
|
||||||
|
Curl_safefree(resp);
|
||||||
Curl_safefree(chlg);
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -134,6 +206,7 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
|||||||
if(status != SEC_E_OK) {
|
if(status != SEC_E_OK) {
|
||||||
Curl_sspi_free_identity(&identity);
|
Curl_sspi_free_identity(&identity);
|
||||||
Curl_safefree(spn);
|
Curl_safefree(spn);
|
||||||
|
Curl_safefree(resp);
|
||||||
Curl_safefree(chlg);
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
@@ -153,17 +226,12 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
|||||||
resp_desc.pBuffers = &resp_buf;
|
resp_desc.pBuffers = &resp_buf;
|
||||||
resp_buf.BufferType = SECBUFFER_TOKEN;
|
resp_buf.BufferType = SECBUFFER_TOKEN;
|
||||||
resp_buf.pvBuffer = resp;
|
resp_buf.pvBuffer = resp;
|
||||||
resp_buf.cbBuffer = sizeof(resp);
|
resp_buf.cbBuffer = curlx_uztoul(resp_max);
|
||||||
|
|
||||||
/* Generate our challenge-response message */
|
/* Generate our challenge-response message */
|
||||||
status = s_pSecFn->InitializeSecurityContext(&handle,
|
status = s_pSecFn->InitializeSecurityContext(&handle, NULL, spn, 0, 0, 0,
|
||||||
NULL,
|
&chlg_desc, 0, &ctx,
|
||||||
(TCHAR *) spn,
|
&resp_desc, &attrs, &tsDummy);
|
||||||
0, 0, 0,
|
|
||||||
&chlg_desc,
|
|
||||||
0, &ctx,
|
|
||||||
&resp_desc,
|
|
||||||
&attrs, &tsDummy);
|
|
||||||
|
|
||||||
if(status == SEC_I_COMPLETE_AND_CONTINUE ||
|
if(status == SEC_I_COMPLETE_AND_CONTINUE ||
|
||||||
status == SEC_I_CONTINUE_NEEDED)
|
status == SEC_I_CONTINUE_NEEDED)
|
||||||
@@ -172,6 +240,7 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
|||||||
s_pSecFn->FreeCredentialsHandle(&handle);
|
s_pSecFn->FreeCredentialsHandle(&handle);
|
||||||
Curl_sspi_free_identity(&identity);
|
Curl_sspi_free_identity(&identity);
|
||||||
Curl_safefree(spn);
|
Curl_safefree(spn);
|
||||||
|
Curl_safefree(resp);
|
||||||
Curl_safefree(chlg);
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
return CURLE_RECV_ERROR;
|
return CURLE_RECV_ERROR;
|
||||||
@@ -191,10 +260,437 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
|||||||
/* Free the SPN */
|
/* Free the SPN */
|
||||||
Curl_safefree(spn);
|
Curl_safefree(spn);
|
||||||
|
|
||||||
|
/* Free the response buffer */
|
||||||
|
Curl_safefree(resp);
|
||||||
|
|
||||||
/* Free the decoeded challenge message */
|
/* Free the decoeded challenge message */
|
||||||
Curl_safefree(chlg);
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* USE_WINDOWS_SSPI && !CURL_DISABLE_CRYPTO_AUTH */
|
#endif /* !CURL_DISABLE_CRYPTO_AUTH */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_sasl_create_gssapi_user_message()
|
||||||
|
*
|
||||||
|
* This is used to generate an already encoded GSSAPI (Kerberos V5) user token
|
||||||
|
* message ready for sending to the recipient.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
*
|
||||||
|
* data [in] - The session handle.
|
||||||
|
* userp [in] - The user name.
|
||||||
|
* passdwp [in] - The user's password.
|
||||||
|
* service [in] - The service type such as www, smtp, pop or imap.
|
||||||
|
* mutual_auth [in] - Flag specifing whether or not mutual authentication
|
||||||
|
* is enabled.
|
||||||
|
* chlg64 [in] - Pointer to the optional base64 encoded challenge
|
||||||
|
* message.
|
||||||
|
* krb5 [in/out] - The gssapi data struct being used and modified.
|
||||||
|
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||||
|
* holding the result will be stored upon completion.
|
||||||
|
* outlen [out] - The length of the output message.
|
||||||
|
*
|
||||||
|
* Returns CURLE_OK on success.
|
||||||
|
*/
|
||||||
|
CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
|
||||||
|
const char *userp,
|
||||||
|
const char *passwdp,
|
||||||
|
const char *service,
|
||||||
|
const bool mutual_auth,
|
||||||
|
const char *chlg64,
|
||||||
|
struct kerberos5data *krb5,
|
||||||
|
char **outptr, size_t *outlen)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
size_t chlglen = 0;
|
||||||
|
unsigned char *chlg = NULL;
|
||||||
|
CtxtHandle context;
|
||||||
|
PSecPkgInfo SecurityPackage;
|
||||||
|
SecBuffer chlg_buf;
|
||||||
|
SecBuffer resp_buf;
|
||||||
|
SecBufferDesc chlg_desc;
|
||||||
|
SecBufferDesc resp_desc;
|
||||||
|
SECURITY_STATUS status;
|
||||||
|
unsigned long attrs;
|
||||||
|
TimeStamp tsDummy; /* For Windows 9x compatibility of SSPI calls */
|
||||||
|
|
||||||
|
if(!krb5->credentials) {
|
||||||
|
/* Query the security package for Kerberos */
|
||||||
|
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT("Kerberos"),
|
||||||
|
&SecurityPackage);
|
||||||
|
if(status != SEC_E_OK) {
|
||||||
|
return CURLE_NOT_BUILT_IN;
|
||||||
|
}
|
||||||
|
|
||||||
|
krb5->token_max = SecurityPackage->cbMaxToken;
|
||||||
|
|
||||||
|
/* Release the package buffer as it is not required anymore */
|
||||||
|
s_pSecFn->FreeContextBuffer(SecurityPackage);
|
||||||
|
|
||||||
|
/* Generate our SPN */
|
||||||
|
krb5->spn = Curl_sasl_build_spn(service, data->easy_conn->host.name);
|
||||||
|
if(!krb5->spn)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
if(userp && *userp) {
|
||||||
|
/* Populate our identity structure */
|
||||||
|
result = Curl_create_sspi_identity(userp, passwdp, &krb5->identity);
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* Allow proper cleanup of the identity structure */
|
||||||
|
krb5->p_identity = &krb5->identity;
|
||||||
|
|
||||||
|
/* Allocate our response buffer */
|
||||||
|
krb5->output_token = malloc(krb5->token_max);
|
||||||
|
if(!krb5->output_token)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* Use the current Windows user */
|
||||||
|
krb5->p_identity = NULL;
|
||||||
|
|
||||||
|
/* Allocate our credentials handle */
|
||||||
|
krb5->credentials = malloc(sizeof(CredHandle));
|
||||||
|
if(!krb5->credentials)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
memset(krb5->credentials, 0, sizeof(CredHandle));
|
||||||
|
|
||||||
|
/* Acquire our credientials handle */
|
||||||
|
status = s_pSecFn->AcquireCredentialsHandle(NULL,
|
||||||
|
(TCHAR *) TEXT("Kerberos"),
|
||||||
|
SECPKG_CRED_OUTBOUND, NULL,
|
||||||
|
krb5->p_identity, NULL, NULL,
|
||||||
|
krb5->credentials, &tsDummy);
|
||||||
|
if(status != SEC_E_OK)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
/* Allocate our new context handle */
|
||||||
|
krb5->context = malloc(sizeof(CtxtHandle));
|
||||||
|
if(!krb5->context)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
memset(krb5->context, 0, sizeof(CtxtHandle));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Decode the base-64 encoded challenge message */
|
||||||
|
if(strlen(chlg64) && *chlg64 != '=') {
|
||||||
|
result = Curl_base64_decode(chlg64, &chlg, &chlglen);
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure we have a valid challenge message */
|
||||||
|
if(!chlg)
|
||||||
|
return CURLE_BAD_CONTENT_ENCODING;
|
||||||
|
|
||||||
|
/* Setup the challenge "input" security buffer */
|
||||||
|
chlg_desc.ulVersion = SECBUFFER_VERSION;
|
||||||
|
chlg_desc.cBuffers = 1;
|
||||||
|
chlg_desc.pBuffers = &chlg_buf;
|
||||||
|
chlg_buf.BufferType = SECBUFFER_TOKEN;
|
||||||
|
chlg_buf.pvBuffer = chlg;
|
||||||
|
chlg_buf.cbBuffer = curlx_uztoul(chlglen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup the response "output" security buffer */
|
||||||
|
resp_desc.ulVersion = SECBUFFER_VERSION;
|
||||||
|
resp_desc.cBuffers = 1;
|
||||||
|
resp_desc.pBuffers = &resp_buf;
|
||||||
|
resp_buf.BufferType = SECBUFFER_TOKEN;
|
||||||
|
resp_buf.pvBuffer = krb5->output_token;
|
||||||
|
resp_buf.cbBuffer = curlx_uztoul(krb5->token_max);
|
||||||
|
|
||||||
|
/* Generate our challenge-response message */
|
||||||
|
status = s_pSecFn->InitializeSecurityContext(krb5->credentials,
|
||||||
|
chlg ? krb5->context : NULL,
|
||||||
|
krb5->spn,
|
||||||
|
(mutual_auth ?
|
||||||
|
ISC_REQ_MUTUAL_AUTH : 0),
|
||||||
|
0, SECURITY_NATIVE_DREP,
|
||||||
|
chlg ? &chlg_desc : NULL, 0,
|
||||||
|
&context,
|
||||||
|
&resp_desc, &attrs,
|
||||||
|
&tsDummy);
|
||||||
|
|
||||||
|
if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
|
return CURLE_RECV_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(memcmp(&context, krb5->context, sizeof(context))) {
|
||||||
|
s_pSecFn->DeleteSecurityContext(krb5->context);
|
||||||
|
|
||||||
|
memcpy(krb5->context, &context, sizeof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(resp_buf.cbBuffer) {
|
||||||
|
/* Base64 encode the response */
|
||||||
|
result = Curl_base64_encode(data, (char *)resp_buf.pvBuffer,
|
||||||
|
resp_buf.cbBuffer, outptr, outlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the decoded challenge */
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_sasl_create_gssapi_security_message()
|
||||||
|
*
|
||||||
|
* This is used to generate an already encoded GSSAPI (Kerberos V5) security
|
||||||
|
* token message ready for sending to the recipient.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
*
|
||||||
|
* data [in] - The session handle.
|
||||||
|
* chlg64 [in] - Pointer to the optional base64 encoded challenge message.
|
||||||
|
* krb5 [in/out] - The gssapi data struct being used and modified.
|
||||||
|
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||||
|
* holding the result will be stored upon completion.
|
||||||
|
* outlen [out] - The length of the output message.
|
||||||
|
*
|
||||||
|
* Returns CURLE_OK on success.
|
||||||
|
*/
|
||||||
|
CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
|
||||||
|
const char *chlg64,
|
||||||
|
struct kerberos5data *krb5,
|
||||||
|
char **outptr,
|
||||||
|
size_t *outlen)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
size_t offset = 0;
|
||||||
|
size_t chlglen = 0;
|
||||||
|
size_t messagelen = 0;
|
||||||
|
size_t appdatalen = 0;
|
||||||
|
unsigned char *chlg = NULL;
|
||||||
|
unsigned char *trailer = NULL;
|
||||||
|
unsigned char *message = NULL;
|
||||||
|
unsigned char *padding = NULL;
|
||||||
|
unsigned char *appdata = NULL;
|
||||||
|
SecBuffer input_buf[2];
|
||||||
|
SecBuffer wrap_buf[3];
|
||||||
|
SecBufferDesc input_desc;
|
||||||
|
SecBufferDesc wrap_desc;
|
||||||
|
unsigned long indata = 0;
|
||||||
|
unsigned long outdata = 0;
|
||||||
|
unsigned long qop = 0;
|
||||||
|
unsigned long sec_layer = 0;
|
||||||
|
unsigned long max_size = 0;
|
||||||
|
SecPkgContext_Sizes sizes;
|
||||||
|
SecPkgCredentials_Names names;
|
||||||
|
SECURITY_STATUS status;
|
||||||
|
|
||||||
|
/* TODO: Verify the unicodeness of this function */
|
||||||
|
|
||||||
|
/* Decode the base-64 encoded input message */
|
||||||
|
if(strlen(chlg64) && *chlg64 != '=') {
|
||||||
|
result = Curl_base64_decode(chlg64, &chlg, &chlglen);
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure we have a valid challenge message */
|
||||||
|
if(!chlg)
|
||||||
|
return CURLE_BAD_CONTENT_ENCODING;
|
||||||
|
|
||||||
|
/* Get our response size information */
|
||||||
|
status = s_pSecFn->QueryContextAttributes(krb5->context,
|
||||||
|
SECPKG_ATTR_SIZES,
|
||||||
|
&sizes);
|
||||||
|
if(status != SEC_E_OK) {
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the fully qualified username back from the context */
|
||||||
|
status = s_pSecFn->QueryCredentialsAttributes(krb5->credentials,
|
||||||
|
SECPKG_CRED_ATTR_NAMES,
|
||||||
|
&names);
|
||||||
|
if(status != SEC_E_OK) {
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
|
return CURLE_RECV_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup the "input" security buffer */
|
||||||
|
input_desc.ulVersion = SECBUFFER_VERSION;
|
||||||
|
input_desc.cBuffers = 2;
|
||||||
|
input_desc.pBuffers = input_buf;
|
||||||
|
input_buf[0].BufferType = SECBUFFER_STREAM;
|
||||||
|
input_buf[0].pvBuffer = chlg;
|
||||||
|
input_buf[0].cbBuffer = curlx_uztoul(chlglen);
|
||||||
|
input_buf[1].BufferType = SECBUFFER_DATA;
|
||||||
|
input_buf[1].pvBuffer = NULL;
|
||||||
|
input_buf[1].cbBuffer = 0;
|
||||||
|
|
||||||
|
/* Decrypt in the inbound challenge obtaining the qop */
|
||||||
|
status = s_pSecFn->DecryptMessage(krb5->context, &input_desc, 0, &qop);
|
||||||
|
if(status != SEC_E_OK) {
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
|
return CURLE_BAD_CONTENT_ENCODING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not 4 octets long to fail as per RFC4752 Section 3.1 */
|
||||||
|
if(input_buf[1].cbBuffer != 4) {
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
|
return CURLE_BAD_CONTENT_ENCODING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the data out into a coinput_bufnvenient variable and free the SSPI
|
||||||
|
allocated buffer as it is not required anymore */
|
||||||
|
memcpy(&indata, input_buf[1].pvBuffer, 4);
|
||||||
|
s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer);
|
||||||
|
|
||||||
|
/* Extract the security layer */
|
||||||
|
sec_layer = indata & 0x000000FF;
|
||||||
|
if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) {
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
|
return CURLE_BAD_CONTENT_ENCODING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extract the maximum message size the server can receive */
|
||||||
|
max_size = ntohl(indata & 0xFFFFFF00);
|
||||||
|
if(max_size > 0) {
|
||||||
|
/* The server has told us it supports a maximum receive buffer, however, as
|
||||||
|
we don't require one unless we are encrypting data we, tell the server
|
||||||
|
our receive buffer is zero. */
|
||||||
|
max_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
outdata = htonl(max_size) | sec_layer;
|
||||||
|
|
||||||
|
/* Allocate the trailer */
|
||||||
|
trailer = malloc(sizes.cbSecurityTrailer);
|
||||||
|
if(!trailer) {
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate our message */
|
||||||
|
messagelen = 4 + strlen(names.sUserName) + 1;
|
||||||
|
message = malloc(messagelen);
|
||||||
|
if(!message) {
|
||||||
|
Curl_safefree(trailer);
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Populate the message with the security layer, client supported receive
|
||||||
|
message size and authorization identity including the 0x00 based
|
||||||
|
terminator. Note: Dispite RFC4752 Section 3.1 stating "The authorization
|
||||||
|
identity is not terminated with the zero-valued (%x00) octet." it seems
|
||||||
|
necessary to include it. */
|
||||||
|
memcpy(message, &outdata, 4);
|
||||||
|
strcpy((char *)message + 4, names.sUserName);
|
||||||
|
|
||||||
|
/* Allocate the padding */
|
||||||
|
padding = malloc(sizes.cbBlockSize);
|
||||||
|
if(!padding) {
|
||||||
|
Curl_safefree(message);
|
||||||
|
Curl_safefree(trailer);
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup the "authentication data" security buffer */
|
||||||
|
wrap_desc.ulVersion = SECBUFFER_VERSION;
|
||||||
|
wrap_desc.cBuffers = 3;
|
||||||
|
wrap_desc.pBuffers = wrap_buf;
|
||||||
|
wrap_buf[0].BufferType = SECBUFFER_TOKEN;
|
||||||
|
wrap_buf[0].pvBuffer = trailer;
|
||||||
|
wrap_buf[0].cbBuffer = sizes.cbSecurityTrailer;
|
||||||
|
wrap_buf[1].BufferType = SECBUFFER_DATA;
|
||||||
|
wrap_buf[1].pvBuffer = message;
|
||||||
|
wrap_buf[1].cbBuffer = curlx_uztoul(messagelen);
|
||||||
|
wrap_buf[2].BufferType = SECBUFFER_PADDING;
|
||||||
|
wrap_buf[2].pvBuffer = padding;
|
||||||
|
wrap_buf[2].cbBuffer = sizes.cbBlockSize;
|
||||||
|
|
||||||
|
/* Encrypt the data */
|
||||||
|
status = s_pSecFn->EncryptMessage(krb5->context, KERB_WRAP_NO_ENCRYPT,
|
||||||
|
&wrap_desc, 0);
|
||||||
|
if(status != SEC_E_OK) {
|
||||||
|
Curl_safefree(padding);
|
||||||
|
Curl_safefree(message);
|
||||||
|
Curl_safefree(trailer);
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate the encryption (wrap) buffer */
|
||||||
|
appdatalen = wrap_buf[0].cbBuffer + wrap_buf[1].cbBuffer +
|
||||||
|
wrap_buf[2].cbBuffer;
|
||||||
|
appdata = malloc(appdatalen);
|
||||||
|
if(!appdata) {
|
||||||
|
Curl_safefree(padding);
|
||||||
|
Curl_safefree(message);
|
||||||
|
Curl_safefree(trailer);
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Populate the encryption buffer */
|
||||||
|
memcpy(appdata, wrap_buf[0].pvBuffer, wrap_buf[0].cbBuffer);
|
||||||
|
offset += wrap_buf[0].cbBuffer;
|
||||||
|
memcpy(appdata + offset, wrap_buf[1].pvBuffer, wrap_buf[1].cbBuffer);
|
||||||
|
offset += wrap_buf[1].cbBuffer;
|
||||||
|
memcpy(appdata + offset, wrap_buf[2].pvBuffer, wrap_buf[2].cbBuffer);
|
||||||
|
|
||||||
|
/* Base64 encode the response */
|
||||||
|
result = Curl_base64_encode(data, (char *)appdata, appdatalen, outptr,
|
||||||
|
outlen);
|
||||||
|
|
||||||
|
/* Free all of our local buffers */
|
||||||
|
Curl_safefree(appdata);
|
||||||
|
Curl_safefree(padding);
|
||||||
|
Curl_safefree(message);
|
||||||
|
Curl_safefree(trailer);
|
||||||
|
Curl_safefree(chlg);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5)
|
||||||
|
{
|
||||||
|
/* Free the context */
|
||||||
|
if(krb5->context) {
|
||||||
|
s_pSecFn->DeleteSecurityContext(krb5->context);
|
||||||
|
free(krb5->context);
|
||||||
|
krb5->context = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the credientials handle */
|
||||||
|
if(krb5->credentials) {
|
||||||
|
s_pSecFn->FreeCredentialsHandle(krb5->credentials);
|
||||||
|
free(krb5->credentials);
|
||||||
|
krb5->credentials = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free our identity */
|
||||||
|
Curl_sspi_free_identity(krb5->p_identity);
|
||||||
|
krb5->p_identity = NULL;
|
||||||
|
|
||||||
|
/* Free the SPN and output token */
|
||||||
|
Curl_safefree(krb5->spn);
|
||||||
|
Curl_safefree(krb5->output_token);
|
||||||
|
|
||||||
|
/* Reset any variables */
|
||||||
|
krb5->token_max = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_WINDOWS_SSPI */
|
||||||
|
@@ -610,7 +610,7 @@ int netware_init(void);
|
|||||||
|
|
||||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \
|
#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \
|
||||||
(defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
|
(defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
|
||||||
#define USE_HTTP_NEGOTIATE
|
#define USE_SPNEGO
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Single point where USE_NTLM definition might be done */
|
/* Single point where USE_NTLM definition might be done */
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -304,5 +304,12 @@ extern PSecurityFunctionTable s_pSecFn;
|
|||||||
(unsigned long)SEC_WINNT_AUTH_IDENTITY_ANSI
|
(unsigned long)SEC_WINNT_AUTH_IDENTITY_ANSI
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions required from ntsecapi.h are directly provided below this point
|
||||||
|
* to avoid including ntsecapi.h due to a conflict with OpenSSL's safestack.h
|
||||||
|
*/
|
||||||
|
#define KERB_WRAP_NO_ENCRYPT 0x80000001
|
||||||
|
|
||||||
#endif /* USE_WINDOWS_SSPI */
|
#endif /* USE_WINDOWS_SSPI */
|
||||||
|
|
||||||
#endif /* HEADER_CURL_SSPI_H */
|
#endif /* HEADER_CURL_SSPI_H */
|
||||||
|
@@ -4470,8 +4470,8 @@ CURLcode ftp_regular_transfer(struct connectdata *conn,
|
|||||||
|
|
||||||
Curl_pgrsSetUploadCounter(data, 0);
|
Curl_pgrsSetUploadCounter(data, 0);
|
||||||
Curl_pgrsSetDownloadCounter(data, 0);
|
Curl_pgrsSetDownloadCounter(data, 0);
|
||||||
Curl_pgrsSetUploadSize(data, 0);
|
Curl_pgrsSetUploadSize(data, -1);
|
||||||
Curl_pgrsSetDownloadSize(data, 0);
|
Curl_pgrsSetDownloadSize(data, -1);
|
||||||
|
|
||||||
ftpc->ctl_valid = TRUE; /* starts good */
|
ftpc->ctl_valid = TRUE; /* starts good */
|
||||||
|
|
||||||
|
@@ -285,6 +285,7 @@ static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info,
|
|||||||
struct curl_tlssessioninfo *tsi = &data->tsi;
|
struct curl_tlssessioninfo *tsi = &data->tsi;
|
||||||
struct connectdata *conn = data->easy_conn;
|
struct connectdata *conn = data->easy_conn;
|
||||||
unsigned int sockindex = 0;
|
unsigned int sockindex = 0;
|
||||||
|
void *internals = NULL;
|
||||||
|
|
||||||
*tsip = tsi;
|
*tsip = tsi;
|
||||||
tsi->backend = CURLSSLBACKEND_NONE;
|
tsi->backend = CURLSSLBACKEND_NONE;
|
||||||
@@ -303,25 +304,24 @@ static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info,
|
|||||||
|
|
||||||
/* Return the TLS session information from the relevant backend */
|
/* Return the TLS session information from the relevant backend */
|
||||||
#ifdef USE_SSLEAY
|
#ifdef USE_SSLEAY
|
||||||
tsi->backend = CURLSSLBACKEND_OPENSSL;
|
internals = conn->ssl[sockindex].ctx;
|
||||||
tsi->internals = conn->ssl[sockindex].ctx;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_GNUTLS
|
#ifdef USE_GNUTLS
|
||||||
tsi->backend = CURLSSLBACKEND_GNUTLS;
|
internals = conn->ssl[sockindex].session;
|
||||||
tsi->internals = conn->ssl[sockindex].session;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_NSS
|
#ifdef USE_NSS
|
||||||
tsi->backend = CURLSSLBACKEND_NSS;
|
internals = conn->ssl[sockindex].handle;
|
||||||
tsi->internals = conn->ssl[sockindex].handle;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_QSOSSL
|
#ifdef USE_QSOSSL
|
||||||
tsi->backend = CURLSSLBACKEND_QSOSSL;
|
internals = conn->ssl[sockindex].handle;
|
||||||
tsi->internals = conn->ssl[sockindex].handle;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_GSKIT
|
#ifdef USE_GSKIT
|
||||||
tsi->backend = CURLSSLBACKEND_GSKIT;
|
internals = conn->ssl[sockindex].handle;
|
||||||
tsi->internals = conn->ssl[sockindex].handle;
|
|
||||||
#endif
|
#endif
|
||||||
|
if(internals) {
|
||||||
|
tsi->backend = Curl_ssl_backend();
|
||||||
|
tsi->internals = internals;
|
||||||
|
}
|
||||||
/* NOTE: For other SSL backends, it is not immediately clear what data
|
/* NOTE: For other SSL backends, it is not immediately clear what data
|
||||||
to return from 'struct ssl_connect_data'; thus, for now we keep the
|
to return from 'struct ssl_connect_data'; thus, for now we keep the
|
||||||
backend as CURLSSLBACKEND_NONE in those cases, which should be
|
backend as CURLSSLBACKEND_NONE in those cases, which should be
|
||||||
|
71
lib/hostip.c
71
lib/hostip.c
@@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -318,6 +318,48 @@ remove_entry_if_stale(struct SessionHandle *data, struct Curl_dns_entry *dns)
|
|||||||
sigjmp_buf curl_jmpenv;
|
sigjmp_buf curl_jmpenv;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
|
||||||
|
*
|
||||||
|
* Curl_resolv() checks initially and multi_runsingle() checks each time
|
||||||
|
* it discovers the handle in the state WAITRESOLVE whether the hostname
|
||||||
|
* has already been resolved and the address has already been stored in
|
||||||
|
* the DNS cache. This short circuits waiting for a lot of pending
|
||||||
|
* lookups for the same hostname requested by different handles.
|
||||||
|
*
|
||||||
|
* Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
|
||||||
|
*/
|
||||||
|
struct Curl_dns_entry *
|
||||||
|
Curl_fetch_addr(struct connectdata *conn,
|
||||||
|
const char *hostname,
|
||||||
|
int port, int *stale)
|
||||||
|
{
|
||||||
|
char *entry_id = NULL;
|
||||||
|
struct Curl_dns_entry *dns = NULL;
|
||||||
|
size_t entry_len;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
|
/* Create an entry id, based upon the hostname and port */
|
||||||
|
entry_id = create_hostcache_id(hostname, port);
|
||||||
|
/* If we can't create the entry id, fail */
|
||||||
|
if(!entry_id)
|
||||||
|
return dns;
|
||||||
|
|
||||||
|
entry_len = strlen(entry_id);
|
||||||
|
|
||||||
|
/* See if its already in our dns cache */
|
||||||
|
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1);
|
||||||
|
|
||||||
|
/* free the allocated entry_id again */
|
||||||
|
free(entry_id);
|
||||||
|
|
||||||
|
/* See whether the returned entry is stale. Done before we release lock */
|
||||||
|
*stale = remove_entry_if_stale(data, dns);
|
||||||
|
if(*stale)
|
||||||
|
dns = NULL; /* the memory deallocation is being handled by the hash */
|
||||||
|
|
||||||
|
return dns;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
|
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
|
||||||
@@ -403,39 +445,22 @@ int Curl_resolv(struct connectdata *conn,
|
|||||||
int port,
|
int port,
|
||||||
struct Curl_dns_entry **entry)
|
struct Curl_dns_entry **entry)
|
||||||
{
|
{
|
||||||
char *entry_id = NULL;
|
|
||||||
struct Curl_dns_entry *dns = NULL;
|
struct Curl_dns_entry *dns = NULL;
|
||||||
size_t entry_len;
|
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
int rc = CURLRESOLV_ERROR; /* default to failure */
|
int stale, rc = CURLRESOLV_ERROR; /* default to failure */
|
||||||
|
|
||||||
*entry = NULL;
|
*entry = NULL;
|
||||||
|
|
||||||
/* Create an entry id, based upon the hostname and port */
|
|
||||||
entry_id = create_hostcache_id(hostname, port);
|
|
||||||
/* If we can't create the entry id, fail */
|
|
||||||
if(!entry_id)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
entry_len = strlen(entry_id);
|
|
||||||
|
|
||||||
if(data->share)
|
if(data->share)
|
||||||
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
|
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
|
||||||
|
|
||||||
/* See if its already in our dns cache */
|
dns = Curl_fetch_addr(conn, hostname, port, &stale);
|
||||||
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1);
|
|
||||||
|
|
||||||
/* free the allocated entry_id again */
|
infof(data, "Hostname was %sfound in DNS cache\n", dns||stale?"":"NOT ");
|
||||||
free(entry_id);
|
if(stale)
|
||||||
|
|
||||||
infof(data, "Hostname was %sfound in DNS cache\n", dns?"":"NOT ");
|
|
||||||
|
|
||||||
/* See whether the returned entry is stale. Done before we release lock */
|
|
||||||
if(remove_entry_if_stale(data, dns)) {
|
|
||||||
infof(data, "Hostname in DNS cache was stale, zapped\n");
|
infof(data, "Hostname in DNS cache was stale, zapped\n");
|
||||||
dns = NULL; /* the memory deallocation is being handled by the hash */
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dns) {
|
if(dns) {
|
||||||
dns->inuse++; /* we use it! */
|
dns->inuse++; /* we use it! */
|
||||||
|
11
lib/hostip.h
11
lib/hostip.h
@@ -171,6 +171,17 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
|
|||||||
const char *Curl_printable_address(const Curl_addrinfo *ip,
|
const char *Curl_printable_address(const Curl_addrinfo *ip,
|
||||||
char *buf, size_t bufsize);
|
char *buf, size_t bufsize);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
|
||||||
|
*
|
||||||
|
* Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
|
||||||
|
*/
|
||||||
|
struct Curl_dns_entry *
|
||||||
|
Curl_fetch_addr(struct connectdata *conn,
|
||||||
|
const char *hostname,
|
||||||
|
int port,
|
||||||
|
int *stale);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
|
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
|
||||||
*
|
*
|
||||||
|
92
lib/http.c
92
lib/http.c
@@ -328,8 +328,8 @@ static bool pickoneauth(struct auth *pick)
|
|||||||
|
|
||||||
/* The order of these checks is highly relevant, as this will be the order
|
/* The order of these checks is highly relevant, as this will be the order
|
||||||
of preference in case of the existence of multiple accepted types. */
|
of preference in case of the existence of multiple accepted types. */
|
||||||
if(avail & CURLAUTH_GSSNEGOTIATE)
|
if(avail & CURLAUTH_NEGOTIATE)
|
||||||
pick->picked = CURLAUTH_GSSNEGOTIATE;
|
pick->picked = CURLAUTH_NEGOTIATE;
|
||||||
else if(avail & CURLAUTH_DIGEST)
|
else if(avail & CURLAUTH_DIGEST)
|
||||||
pick->picked = CURLAUTH_DIGEST;
|
pick->picked = CURLAUTH_DIGEST;
|
||||||
else if(avail & CURLAUTH_NTLM)
|
else if(avail & CURLAUTH_NTLM)
|
||||||
@@ -557,7 +557,7 @@ output_auth_headers(struct connectdata *conn,
|
|||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
const char *auth=NULL;
|
const char *auth=NULL;
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
#ifdef USE_HTTP_NEGOTIATE
|
#ifdef USE_SPNEGO
|
||||||
struct negotiatedata *negdata = proxy?
|
struct negotiatedata *negdata = proxy?
|
||||||
&data->state.proxyneg:&data->state.negotiate;
|
&data->state.proxyneg:&data->state.negotiate;
|
||||||
#endif
|
#endif
|
||||||
@@ -567,11 +567,11 @@ output_auth_headers(struct connectdata *conn,
|
|||||||
(void)path;
|
(void)path;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_HTTP_NEGOTIATE
|
#ifdef USE_SPNEGO
|
||||||
negdata->state = GSS_AUTHNONE;
|
negdata->state = GSS_AUTHNONE;
|
||||||
if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) &&
|
if((authstatus->picked == CURLAUTH_NEGOTIATE) &&
|
||||||
negdata->context && !GSS_ERROR(negdata->status)) {
|
negdata->context && !GSS_ERROR(negdata->status)) {
|
||||||
auth="GSS-Negotiate";
|
auth="Negotiate";
|
||||||
result = Curl_output_negotiate(conn, proxy);
|
result = Curl_output_negotiate(conn, proxy);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
@@ -737,6 +737,10 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
|
|||||||
*/
|
*/
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
|
#ifdef USE_SPNEGO
|
||||||
|
struct negotiatedata *negdata = proxy?
|
||||||
|
&data->state.proxyneg:&data->state.negotiate;
|
||||||
|
#endif
|
||||||
unsigned long *availp;
|
unsigned long *availp;
|
||||||
struct auth *authp;
|
struct auth *authp;
|
||||||
|
|
||||||
@@ -767,21 +771,14 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
while(*auth) {
|
while(*auth) {
|
||||||
#ifdef USE_HTTP_NEGOTIATE
|
#ifdef USE_SPNEGO
|
||||||
if(checkprefix("GSS-Negotiate", auth) ||
|
if(checkprefix("Negotiate", auth)) {
|
||||||
checkprefix("Negotiate", auth)) {
|
|
||||||
int neg;
|
int neg;
|
||||||
*availp |= CURLAUTH_GSSNEGOTIATE;
|
*availp |= CURLAUTH_NEGOTIATE;
|
||||||
authp->avail |= CURLAUTH_GSSNEGOTIATE;
|
authp->avail |= CURLAUTH_NEGOTIATE;
|
||||||
|
|
||||||
if(authp->picked == CURLAUTH_GSSNEGOTIATE) {
|
if(authp->picked == CURLAUTH_NEGOTIATE) {
|
||||||
if(data->state.negotiate.state == GSS_AUTHSENT) {
|
if(negdata->state == GSS_AUTHSENT || negdata->state == GSS_AUTHNONE) {
|
||||||
/* 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 if(data->state.negotiate.state == GSS_AUTHNONE) {
|
|
||||||
neg = Curl_input_negotiate(conn, proxy, auth);
|
neg = Curl_input_negotiate(conn, proxy, auth);
|
||||||
if(neg == 0) {
|
if(neg == 0) {
|
||||||
DEBUGASSERT(!data->req.newurl);
|
DEBUGASSERT(!data->req.newurl);
|
||||||
@@ -789,8 +786,8 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
|
|||||||
if(!data->req.newurl)
|
if(!data->req.newurl)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
data->state.authproblem = FALSE;
|
data->state.authproblem = FALSE;
|
||||||
/* we received GSS auth info and we dealt with it fine */
|
/* we received a GSS auth token and we dealt with it fine */
|
||||||
data->state.negotiate.state = GSS_AUTHRECV;
|
negdata->state = GSS_AUTHRECV;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
data->state.authproblem = TRUE;
|
data->state.authproblem = TRUE;
|
||||||
@@ -923,14 +920,6 @@ static int http_should_fail(struct connectdata *conn)
|
|||||||
if(httpcode < 400)
|
if(httpcode < 400)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if(data->state.resume_from &&
|
|
||||||
(data->set.httpreq==HTTPREQ_GET) &&
|
|
||||||
(httpcode == 416)) {
|
|
||||||
/* "Requested Range Not Satisfiable", just proceed and
|
|
||||||
pretend this is no error */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Any code >= 400 that's not 401 or 407 is always
|
** Any code >= 400 that's not 401 or 407 is always
|
||||||
** a terminal error
|
** a terminal error
|
||||||
@@ -1443,6 +1432,12 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
|||||||
|
|
||||||
Curl_unencode_cleanup(conn);
|
Curl_unencode_cleanup(conn);
|
||||||
|
|
||||||
|
#ifdef USE_SPNEGO
|
||||||
|
if(data->state.proxyneg.state == GSS_AUTHSENT ||
|
||||||
|
data->state.negotiate.state == GSS_AUTHSENT)
|
||||||
|
Curl_cleanup_negotiate(data);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* set the proper values (possibly modified on POST) */
|
/* set the proper values (possibly modified on POST) */
|
||||||
conn->fread_func = data->set.fread_func; /* restore */
|
conn->fread_func = data->set.fread_func; /* restore */
|
||||||
conn->fread_in = data->set.in; /* restore */
|
conn->fread_in = data->set.in; /* restore */
|
||||||
@@ -1522,10 +1517,6 @@ static CURLcode expect100(struct SessionHandle *data,
|
|||||||
const char *ptr;
|
const char *ptr;
|
||||||
data->state.expect100header = FALSE; /* default to false unless it is set
|
data->state.expect100header = FALSE; /* default to false unless it is set
|
||||||
to TRUE below */
|
to TRUE below */
|
||||||
if(conn->httpversion == 20) {
|
|
||||||
/* We don't use Expect in HTTP2 */
|
|
||||||
return CURLE_OK;
|
|
||||||
}
|
|
||||||
if(use_http_1_1plus(data, conn)) {
|
if(use_http_1_1plus(data, conn)) {
|
||||||
/* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
|
/* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
|
||||||
100-continue to the headers which actually speeds up post operations
|
100-continue to the headers which actually speeds up post operations
|
||||||
@@ -1757,8 +1748,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
/* TODO: add error checking here */
|
result = Curl_http2_switched(conn);
|
||||||
Curl_http2_switched(conn);
|
if(result)
|
||||||
|
return result;
|
||||||
break;
|
break;
|
||||||
case NPN_HTTP1_1:
|
case NPN_HTTP1_1:
|
||||||
/* continue with HTTP/1.1 when explicitly requested */
|
/* continue with HTTP/1.1 when explicitly requested */
|
||||||
@@ -1770,7 +1762,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* prepare for a http2 request */
|
/* prepare for a http2 request */
|
||||||
Curl_http2_setup(conn);
|
result = Curl_http2_setup(conn);
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
http = data->req.protop;
|
http = data->req.protop;
|
||||||
@@ -2357,7 +2351,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
http->postdata = NULL; /* nothing to post at this point */
|
http->postdata = NULL; /* nothing to post at this point */
|
||||||
Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */
|
Curl_pgrsSetUploadSize(data, -1); /* upload size is unknown atm */
|
||||||
|
|
||||||
/* If 'authdone' is FALSE, we must not set the write socket index to the
|
/* If 'authdone' is FALSE, we must not set the write socket index to the
|
||||||
Curl_transfer() call below, as we're not ready to actually upload any
|
Curl_transfer() call below, as we're not ready to actually upload any
|
||||||
@@ -3004,8 +2998,9 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
|
|||||||
k->upgr101 = UPGR101_RECEIVED;
|
k->upgr101 = UPGR101_RECEIVED;
|
||||||
|
|
||||||
/* switch to http2 now */
|
/* switch to http2 now */
|
||||||
/* TODO: add error checking */
|
result = Curl_http2_switched(conn);
|
||||||
Curl_http2_switched(conn);
|
if(result)
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -3536,23 +3531,30 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
|
|||||||
/* Content-Range: bytes [num]-
|
/* Content-Range: bytes [num]-
|
||||||
Content-Range: bytes: [num]-
|
Content-Range: bytes: [num]-
|
||||||
Content-Range: [num]-
|
Content-Range: [num]-
|
||||||
|
Content-Range: [asterisk]/[total]
|
||||||
|
|
||||||
The second format was added since Sun's webserver
|
The second format was added since Sun's webserver
|
||||||
JavaWebServer/1.1.1 obviously sends the header this way!
|
JavaWebServer/1.1.1 obviously sends the header this way!
|
||||||
The third added since some servers use that!
|
The third added since some servers use that!
|
||||||
|
The forth means the requested range was unsatisfied.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *ptr = k->p + 14;
|
char *ptr = k->p + 14;
|
||||||
|
|
||||||
/* Move forward until first digit */
|
/* Move forward until first digit or asterisk */
|
||||||
while(*ptr && !ISDIGIT(*ptr))
|
while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
|
||||||
ptr++;
|
ptr++;
|
||||||
|
|
||||||
k->offset = curlx_strtoofft(ptr, NULL, 10);
|
/* if it truly stopped on a digit */
|
||||||
|
if(ISDIGIT(*ptr)) {
|
||||||
|
k->offset = curlx_strtoofft(ptr, NULL, 10);
|
||||||
|
|
||||||
if(data->state.resume_from == k->offset)
|
if(data->state.resume_from == k->offset)
|
||||||
/* we asked for a resume and we got it */
|
/* we asked for a resume and we got it */
|
||||||
k->content_range = TRUE;
|
k->content_range = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data->state.resume_from = 0; /* get everything */
|
||||||
}
|
}
|
||||||
#if !defined(CURL_DISABLE_COOKIES)
|
#if !defined(CURL_DISABLE_COOKIES)
|
||||||
else if(data->cookies &&
|
else if(data->cookies &&
|
||||||
|
@@ -169,7 +169,9 @@ struct http_conn {
|
|||||||
sending send_underlying; /* underlying send Curl_send callback */
|
sending send_underlying; /* underlying send Curl_send callback */
|
||||||
recving recv_underlying; /* underlying recv Curl_recv callback */
|
recving recv_underlying; /* underlying recv Curl_recv callback */
|
||||||
bool closed; /* TRUE on HTTP2 stream close */
|
bool closed; /* TRUE on HTTP2 stream close */
|
||||||
Curl_send_buffer *header_recvbuf; /* store response headers */
|
Curl_send_buffer *header_recvbuf; /* store response headers. We
|
||||||
|
store non-final and final
|
||||||
|
response headers into it. */
|
||||||
size_t nread_header_recvbuf; /* number of bytes in header_recvbuf
|
size_t nread_header_recvbuf; /* number of bytes in header_recvbuf
|
||||||
fed into upper layer */
|
fed into upper layer */
|
||||||
int32_t stream_id; /* stream we are interested in */
|
int32_t stream_id; /* stream we are interested in */
|
||||||
@@ -185,6 +187,7 @@ struct http_conn {
|
|||||||
const uint8_t *upload_mem; /* points to a buffer to read from */
|
const uint8_t *upload_mem; /* points to a buffer to read from */
|
||||||
size_t upload_len; /* size of the buffer 'upload_mem' points to */
|
size_t upload_len; /* size of the buffer 'upload_mem' points to */
|
||||||
size_t upload_left; /* number of bytes left to upload */
|
size_t upload_left; /* number of bytes left to upload */
|
||||||
|
int status_code; /* HTTP status code */
|
||||||
#else
|
#else
|
||||||
int unused; /* prevent a compiler warning */
|
int unused; /* prevent a compiler warning */
|
||||||
#endif
|
#endif
|
||||||
|
304
lib/http2.c
304
lib/http2.c
@@ -39,7 +39,7 @@
|
|||||||
/* include memdebug.h last */
|
/* include memdebug.h last */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
#if (NGHTTP2_VERSION_NUM < 0x000300)
|
#if (NGHTTP2_VERSION_NUM < 0x000600)
|
||||||
#error too old nghttp2 version, upgrade!
|
#error too old nghttp2 version, upgrade!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -191,27 +191,80 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
|||||||
struct connectdata *conn = (struct connectdata *)userp;
|
struct connectdata *conn = (struct connectdata *)userp;
|
||||||
struct http_conn *c = &conn->proto.httpc;
|
struct http_conn *c = &conn->proto.httpc;
|
||||||
int rv;
|
int rv;
|
||||||
|
size_t left, ncopy;
|
||||||
|
|
||||||
(void)session;
|
(void)session;
|
||||||
(void)frame;
|
(void)frame;
|
||||||
infof(conn->data, "on_frame_recv() was called with header %x\n",
|
infof(conn->data, "on_frame_recv() was called with header %x\n",
|
||||||
frame->hd.type);
|
frame->hd.type);
|
||||||
switch(frame->hd.type) {
|
switch(frame->hd.type) {
|
||||||
|
case NGHTTP2_DATA:
|
||||||
|
/* If body started, then receiving DATA is illegal. */
|
||||||
|
if(!c->bodystarted) {
|
||||||
|
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||||
|
frame->hd.stream_id,
|
||||||
|
NGHTTP2_PROTOCOL_ERROR);
|
||||||
|
|
||||||
|
if(nghttp2_is_fatal(rv)) {
|
||||||
|
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case NGHTTP2_HEADERS:
|
case NGHTTP2_HEADERS:
|
||||||
if(frame->headers.cat != NGHTTP2_HCAT_RESPONSE)
|
if(frame->headers.cat == NGHTTP2_HCAT_REQUEST)
|
||||||
break;
|
break;
|
||||||
c->bodystarted = TRUE;
|
|
||||||
|
if(c->bodystarted) {
|
||||||
|
/* Only valid HEADERS after body started is trailer header,
|
||||||
|
which is not fully supported in this code. If HEADERS is not
|
||||||
|
trailer, then it is a PROTOCOL_ERROR. */
|
||||||
|
if((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
|
||||||
|
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||||
|
frame->hd.stream_id,
|
||||||
|
NGHTTP2_PROTOCOL_ERROR);
|
||||||
|
|
||||||
|
if(nghttp2_is_fatal(rv)) {
|
||||||
|
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c->status_code == -1) {
|
||||||
|
/* No :status header field means PROTOCOL_ERROR. */
|
||||||
|
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||||
|
frame->hd.stream_id,
|
||||||
|
NGHTTP2_PROTOCOL_ERROR);
|
||||||
|
|
||||||
|
if(nghttp2_is_fatal(rv)) {
|
||||||
|
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only final status code signals the end of header */
|
||||||
|
if(c->status_code / 100 != 1) {
|
||||||
|
c->bodystarted = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->status_code = -1;
|
||||||
|
|
||||||
Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
|
Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
|
||||||
c->nread_header_recvbuf = c->len < c->header_recvbuf->size_used ?
|
|
||||||
c->len : c->header_recvbuf->size_used;
|
|
||||||
|
|
||||||
memcpy(c->mem, c->header_recvbuf->buffer, c->nread_header_recvbuf);
|
left = c->header_recvbuf->size_used - c->nread_header_recvbuf;
|
||||||
|
ncopy = c->len < left ? c->len : left;
|
||||||
|
|
||||||
c->mem += c->nread_header_recvbuf;
|
memcpy(c->mem, c->header_recvbuf->buffer + c->nread_header_recvbuf, ncopy);
|
||||||
c->len -= c->nread_header_recvbuf;
|
c->nread_header_recvbuf += ncopy;
|
||||||
|
|
||||||
|
c->mem += ncopy;
|
||||||
|
c->len -= ncopy;
|
||||||
break;
|
break;
|
||||||
case NGHTTP2_PUSH_PROMISE:
|
case NGHTTP2_PUSH_PROMISE:
|
||||||
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||||
frame->hd.stream_id, NGHTTP2_CANCEL);
|
frame->push_promise.promised_stream_id,
|
||||||
|
NGHTTP2_CANCEL);
|
||||||
if(nghttp2_is_fatal(rv)) {
|
if(nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@@ -222,7 +275,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
|||||||
|
|
||||||
static int on_invalid_frame_recv(nghttp2_session *session,
|
static int on_invalid_frame_recv(nghttp2_session *session,
|
||||||
const nghttp2_frame *frame,
|
const nghttp2_frame *frame,
|
||||||
nghttp2_error_code error_code, void *userp)
|
uint32_t error_code, void *userp)
|
||||||
{
|
{
|
||||||
struct connectdata *conn = (struct connectdata *)userp;
|
struct connectdata *conn = (struct connectdata *)userp;
|
||||||
(void)session;
|
(void)session;
|
||||||
@@ -297,7 +350,7 @@ static int on_frame_not_send(nghttp2_session *session,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int on_stream_close(nghttp2_session *session, int32_t stream_id,
|
static int on_stream_close(nghttp2_session *session, int32_t stream_id,
|
||||||
nghttp2_error_code error_code, void *userp)
|
uint32_t error_code, void *userp)
|
||||||
{
|
{
|
||||||
struct connectdata *conn = (struct connectdata *)userp;
|
struct connectdata *conn = (struct connectdata *)userp;
|
||||||
struct http_conn *c = &conn->proto.httpc;
|
struct http_conn *c = &conn->proto.httpc;
|
||||||
@@ -315,20 +368,6 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int on_unknown_frame_recv(nghttp2_session *session,
|
|
||||||
const uint8_t *head, size_t headlen,
|
|
||||||
const uint8_t *payload, size_t payloadlen,
|
|
||||||
void *userp)
|
|
||||||
{
|
|
||||||
struct connectdata *conn = (struct connectdata *)userp;
|
|
||||||
(void)session;
|
|
||||||
(void)head;
|
|
||||||
(void)headlen;
|
|
||||||
(void)payload;
|
|
||||||
(void)payloadlen;
|
|
||||||
infof(conn->data, "on_unknown_frame_recv() was called\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static int on_begin_headers(nghttp2_session *session,
|
static int on_begin_headers(nghttp2_session *session,
|
||||||
const nghttp2_frame *frame, void *userp)
|
const nghttp2_frame *frame, void *userp)
|
||||||
{
|
{
|
||||||
@@ -339,6 +378,33 @@ static int on_begin_headers(nghttp2_session *session,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Decode HTTP status code. Returns -1 if no valid status code was
|
||||||
|
decoded. */
|
||||||
|
static int decode_status_code(const uint8_t *value, size_t len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if(len != 3) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
|
||||||
|
for(i = 0; i < 3; ++i) {
|
||||||
|
char c = value[i];
|
||||||
|
|
||||||
|
if(c < '0' || c > '9') {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res *= 10;
|
||||||
|
res += c - '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static const char STATUS[] = ":status";
|
static const char STATUS[] = ":status";
|
||||||
|
|
||||||
/* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */
|
/* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */
|
||||||
@@ -350,6 +416,10 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
|||||||
{
|
{
|
||||||
struct connectdata *conn = (struct connectdata *)userp;
|
struct connectdata *conn = (struct connectdata *)userp;
|
||||||
struct http_conn *c = &conn->proto.httpc;
|
struct http_conn *c = &conn->proto.httpc;
|
||||||
|
int rv;
|
||||||
|
int goodname;
|
||||||
|
int goodheader;
|
||||||
|
|
||||||
(void)session;
|
(void)session;
|
||||||
(void)frame;
|
(void)frame;
|
||||||
(void)flags;
|
(void)flags;
|
||||||
@@ -358,45 +428,83 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(c->bodystarted) {
|
||||||
|
/* Ignore trailer or HEADERS not mapped to HTTP semantics. The
|
||||||
|
consequence is handled in on_frame_recv(). */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
goodname = nghttp2_check_header_name(name, namelen);
|
||||||
|
goodheader = nghttp2_check_header_value(value, valuelen);
|
||||||
|
|
||||||
|
if(!goodname || !goodheader) {
|
||||||
|
|
||||||
|
infof(conn->data, "Detected bad incoming header %s%s, reset stream!\n",
|
||||||
|
goodname?"":"name",
|
||||||
|
goodheader?"":"value");
|
||||||
|
|
||||||
|
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||||
|
frame->hd.stream_id,
|
||||||
|
NGHTTP2_PROTOCOL_ERROR);
|
||||||
|
|
||||||
|
if(nghttp2_is_fatal(rv)) {
|
||||||
|
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
if(namelen == sizeof(":status") - 1 &&
|
if(namelen == sizeof(":status") - 1 &&
|
||||||
memcmp(STATUS, name, namelen) == 0) {
|
memcmp(STATUS, name, namelen) == 0) {
|
||||||
snprintf(c->header_recvbuf->buffer, 13, "HTTP/2.0 %s", value);
|
|
||||||
c->header_recvbuf->buffer[12] = '\r';
|
/* :status must appear exactly once. */
|
||||||
|
if(c->status_code != -1 ||
|
||||||
|
(c->status_code = decode_status_code(value, valuelen)) == -1) {
|
||||||
|
|
||||||
|
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||||
|
frame->hd.stream_id,
|
||||||
|
NGHTTP2_PROTOCOL_ERROR);
|
||||||
|
if(nghttp2_is_fatal(rv)) {
|
||||||
|
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Curl_add_buffer(c->header_recvbuf, "HTTP/2.0 ", 9);
|
||||||
|
Curl_add_buffer(c->header_recvbuf, value, valuelen);
|
||||||
|
Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
/* Here we are sure that namelen > 0 because of
|
||||||
|
nghttp2_check_header_name(). Pseudo header other than :status
|
||||||
|
is illegal. */
|
||||||
|
if(c->status_code == -1 || name[0] == ':') {
|
||||||
|
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||||
|
frame->hd.stream_id,
|
||||||
|
NGHTTP2_PROTOCOL_ERROR);
|
||||||
|
if(nghttp2_is_fatal(rv)) {
|
||||||
|
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
/* convert to a HTTP1-style header */
|
/* convert to a HTTP1-style header */
|
||||||
infof(conn->data, "got header\n");
|
|
||||||
Curl_add_buffer(c->header_recvbuf, name, namelen);
|
Curl_add_buffer(c->header_recvbuf, name, namelen);
|
||||||
Curl_add_buffer(c->header_recvbuf, ":", 1);
|
Curl_add_buffer(c->header_recvbuf, ":", 1);
|
||||||
Curl_add_buffer(c->header_recvbuf, value, valuelen);
|
Curl_add_buffer(c->header_recvbuf, value, valuelen);
|
||||||
Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
|
Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
|
||||||
|
|
||||||
|
infof(conn->data, "got http2 header: %.*s: %.*s\n",
|
||||||
|
namelen, name, valuelen, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0; /* 0 is successful */
|
return 0; /* 0 is successful */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This is all callbacks nghttp2 calls
|
|
||||||
*/
|
|
||||||
static const nghttp2_session_callbacks callbacks = {
|
|
||||||
send_callback, /* nghttp2_send_callback */
|
|
||||||
NULL, /* nghttp2_recv_callback */
|
|
||||||
on_frame_recv, /* nghttp2_on_frame_recv_callback */
|
|
||||||
on_invalid_frame_recv, /* nghttp2_on_invalid_frame_recv_callback */
|
|
||||||
on_data_chunk_recv, /* nghttp2_on_data_chunk_recv_callback */
|
|
||||||
before_frame_send, /* nghttp2_before_frame_send_callback */
|
|
||||||
on_frame_send, /* nghttp2_on_frame_send_callback */
|
|
||||||
on_frame_not_send, /* nghttp2_on_frame_not_send_callback */
|
|
||||||
on_stream_close, /* nghttp2_on_stream_close_callback */
|
|
||||||
on_unknown_frame_recv, /* nghttp2_on_unknown_frame_recv_callback */
|
|
||||||
on_begin_headers, /* nghttp2_on_begin_headers_callback */
|
|
||||||
on_header /* nghttp2_on_header_callback */
|
|
||||||
#if NGHTTP2_VERSION_NUM >= 0x000400
|
|
||||||
, NULL /* nghttp2_select_padding_callback */
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t data_source_read_callback(nghttp2_session *session,
|
static ssize_t data_source_read_callback(nghttp2_session *session,
|
||||||
int32_t stream_id,
|
int32_t stream_id,
|
||||||
uint8_t *buf, size_t length,
|
uint8_t *buf, size_t length,
|
||||||
@@ -444,13 +552,54 @@ CURLcode Curl_http2_init(struct connectdata *conn)
|
|||||||
{
|
{
|
||||||
if(!conn->proto.httpc.h2) {
|
if(!conn->proto.httpc.h2) {
|
||||||
int rc;
|
int rc;
|
||||||
|
nghttp2_session_callbacks *callbacks;
|
||||||
|
|
||||||
conn->proto.httpc.inbuf = malloc(H2_BUFSIZE);
|
conn->proto.httpc.inbuf = malloc(H2_BUFSIZE);
|
||||||
if(conn->proto.httpc.inbuf == NULL)
|
if(conn->proto.httpc.inbuf == NULL)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
rc = nghttp2_session_callbacks_new(&callbacks);
|
||||||
|
|
||||||
|
if(rc) {
|
||||||
|
failf(conn->data, "Couldn't initialize nghttp2 callbacks!");
|
||||||
|
return CURLE_OUT_OF_MEMORY; /* most likely at least */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* nghttp2_send_callback */
|
||||||
|
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
||||||
|
/* nghttp2_on_frame_recv_callback */
|
||||||
|
nghttp2_session_callbacks_set_on_frame_recv_callback
|
||||||
|
(callbacks, on_frame_recv);
|
||||||
|
/* nghttp2_on_invalid_frame_recv_callback */
|
||||||
|
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback
|
||||||
|
(callbacks, on_invalid_frame_recv);
|
||||||
|
/* nghttp2_on_data_chunk_recv_callback */
|
||||||
|
nghttp2_session_callbacks_set_on_data_chunk_recv_callback
|
||||||
|
(callbacks, on_data_chunk_recv);
|
||||||
|
/* nghttp2_before_frame_send_callback */
|
||||||
|
nghttp2_session_callbacks_set_before_frame_send_callback
|
||||||
|
(callbacks, before_frame_send);
|
||||||
|
/* nghttp2_on_frame_send_callback */
|
||||||
|
nghttp2_session_callbacks_set_on_frame_send_callback
|
||||||
|
(callbacks, on_frame_send);
|
||||||
|
/* nghttp2_on_frame_not_send_callback */
|
||||||
|
nghttp2_session_callbacks_set_on_frame_not_send_callback
|
||||||
|
(callbacks, on_frame_not_send);
|
||||||
|
/* nghttp2_on_stream_close_callback */
|
||||||
|
nghttp2_session_callbacks_set_on_stream_close_callback
|
||||||
|
(callbacks, on_stream_close);
|
||||||
|
/* nghttp2_on_begin_headers_callback */
|
||||||
|
nghttp2_session_callbacks_set_on_begin_headers_callback
|
||||||
|
(callbacks, on_begin_headers);
|
||||||
|
/* nghttp2_on_header_callback */
|
||||||
|
nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header);
|
||||||
|
|
||||||
/* The nghttp2 session is not yet setup, do it */
|
/* The nghttp2 session is not yet setup, do it */
|
||||||
rc = nghttp2_session_client_new(&conn->proto.httpc.h2,
|
rc = nghttp2_session_client_new(&conn->proto.httpc.h2,
|
||||||
&callbacks, conn);
|
callbacks, conn);
|
||||||
|
|
||||||
|
nghttp2_session_callbacks_del(callbacks);
|
||||||
|
|
||||||
if(rc) {
|
if(rc) {
|
||||||
failf(conn->data, "Couldn't initialize nghttp2!");
|
failf(conn->data, "Couldn't initialize nghttp2!");
|
||||||
return CURLE_OUT_OF_MEMORY; /* most likely at least */
|
return CURLE_OUT_OF_MEMORY; /* most likely at least */
|
||||||
@@ -504,8 +653,8 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
|
|||||||
}
|
}
|
||||||
conn->proto.httpc.binlen = binlen;
|
conn->proto.httpc.binlen = binlen;
|
||||||
|
|
||||||
result = Curl_base64_encode(conn->data, (const char *)binsettings, binlen,
|
result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
|
||||||
&base64, &blen);
|
&base64, &blen);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -536,6 +685,9 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
|||||||
(void)sockindex; /* we always do HTTP2 on sockindex 0 */
|
(void)sockindex; /* we always do HTTP2 on sockindex 0 */
|
||||||
|
|
||||||
if(httpc->closed) {
|
if(httpc->closed) {
|
||||||
|
/* Reset to FALSE to prevent infinite loop in readwrite_data
|
||||||
|
function. */
|
||||||
|
httpc->closed = FALSE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,12 +767,19 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
|||||||
/* If stream is closed, return 0 to signal the http routine to close
|
/* If stream is closed, return 0 to signal the http routine to close
|
||||||
the connection */
|
the connection */
|
||||||
if(httpc->closed) {
|
if(httpc->closed) {
|
||||||
|
/* Reset to FALSE to prevent infinite loop in readwrite_data
|
||||||
|
function. */
|
||||||
|
httpc->closed = FALSE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*err = CURLE_AGAIN;
|
*err = CURLE_AGAIN;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Index where :authority header field will appear in request header
|
||||||
|
field list. */
|
||||||
|
#define AUTHORITY_DST_IDX 3
|
||||||
|
|
||||||
/* return number of received (decrypted) bytes */
|
/* return number of received (decrypted) bytes */
|
||||||
static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||||
const void *mem, size_t len, CURLcode *err)
|
const void *mem, size_t len, CURLcode *err)
|
||||||
@@ -635,6 +794,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
|||||||
nghttp2_nv *nva;
|
nghttp2_nv *nva;
|
||||||
size_t nheader;
|
size_t nheader;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
size_t authority_idx;
|
||||||
char *hdbuf = (char*)mem;
|
char *hdbuf = (char*)mem;
|
||||||
char *end;
|
char *end;
|
||||||
nghttp2_data_provider data_prd;
|
nghttp2_data_provider data_prd;
|
||||||
@@ -705,10 +865,13 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
|||||||
hdbuf = strchr(hdbuf, 0x0a);
|
hdbuf = strchr(hdbuf, 0x0a);
|
||||||
++hdbuf;
|
++hdbuf;
|
||||||
|
|
||||||
|
authority_idx = 0;
|
||||||
|
|
||||||
for(i = 3; i < nheader; ++i) {
|
for(i = 3; i < nheader; ++i) {
|
||||||
end = strchr(hdbuf, ':');
|
end = strchr(hdbuf, ':');
|
||||||
assert(end);
|
assert(end);
|
||||||
if(end - hdbuf == 4 && Curl_raw_nequal("host", hdbuf, 4)) {
|
if(end - hdbuf == 4 && Curl_raw_nequal("host", hdbuf, 4)) {
|
||||||
|
authority_idx = i;
|
||||||
nva[i].name = (unsigned char *)":authority";
|
nva[i].name = (unsigned char *)":authority";
|
||||||
nva[i].namelen = (uint16_t)strlen((char *)nva[i].name);
|
nva[i].namelen = (uint16_t)strlen((char *)nva[i].name);
|
||||||
}
|
}
|
||||||
@@ -739,6 +902,15 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* :authority must come before non-pseudo header fields */
|
||||||
|
if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) {
|
||||||
|
nghttp2_nv authority = nva[authority_idx];
|
||||||
|
for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) {
|
||||||
|
nva[i] = nva[i - 1];
|
||||||
|
}
|
||||||
|
nva[i] = authority;
|
||||||
|
}
|
||||||
|
|
||||||
switch(conn->data->set.httpreq) {
|
switch(conn->data->set.httpreq) {
|
||||||
case HTTPREQ_POST:
|
case HTTPREQ_POST:
|
||||||
case HTTPREQ_POST_FORM:
|
case HTTPREQ_POST_FORM:
|
||||||
@@ -803,19 +975,19 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
|
|||||||
httpc->upload_mem = NULL;
|
httpc->upload_mem = NULL;
|
||||||
httpc->upload_len = 0;
|
httpc->upload_len = 0;
|
||||||
httpc->stream_id = -1;
|
httpc->stream_id = -1;
|
||||||
|
httpc->status_code = -1;
|
||||||
|
|
||||||
conn->httpversion = 20;
|
conn->httpversion = 20;
|
||||||
|
|
||||||
/* Put place holder for status line */
|
return 0;
|
||||||
return Curl_add_buffer(httpc->header_recvbuf, "HTTP/2.0 200\r\n", 14);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Curl_http2_switched(struct connectdata *conn)
|
CURLcode Curl_http2_switched(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
/* TODO: May get CURLE_AGAIN */
|
|
||||||
CURLcode rc;
|
CURLcode rc;
|
||||||
struct http_conn *httpc = &conn->proto.httpc;
|
struct http_conn *httpc = &conn->proto.httpc;
|
||||||
int rv;
|
int rv;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
httpc->recv_underlying = (recving)conn->recv[FIRSTSOCKET];
|
httpc->recv_underlying = (recving)conn->recv[FIRSTSOCKET];
|
||||||
httpc->send_underlying = (sending)conn->send[FIRSTSOCKET];
|
httpc->send_underlying = (sending)conn->send[FIRSTSOCKET];
|
||||||
@@ -827,7 +999,15 @@ int Curl_http2_switched(struct connectdata *conn)
|
|||||||
NGHTTP2_CLIENT_CONNECTION_PREFACE,
|
NGHTTP2_CLIENT_CONNECTION_PREFACE,
|
||||||
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN,
|
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN,
|
||||||
&rc);
|
&rc);
|
||||||
assert(rv == 24);
|
if(rc)
|
||||||
|
/* TODO: This may get CURLE_AGAIN */
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if(rv != 24) {
|
||||||
|
failf(data, "Only sent partial HTTP2 packet");
|
||||||
|
return CURLE_SEND_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if(conn->data->req.upgr101 == UPGR101_RECEIVED) {
|
if(conn->data->req.upgr101 == UPGR101_RECEIVED) {
|
||||||
/* stream 1 is opened implicitly on upgrade */
|
/* stream 1 is opened implicitly on upgrade */
|
||||||
httpc->stream_id = 1;
|
httpc->stream_id = 1;
|
||||||
@@ -835,9 +1015,9 @@ int Curl_http2_switched(struct connectdata *conn)
|
|||||||
rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings,
|
rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings,
|
||||||
httpc->binlen, NULL);
|
httpc->binlen, NULL);
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
failf(conn->data, "nghttp2_session_upgrade() failed: %s(%d)",
|
failf(data, "nghttp2_session_upgrade() failed: %s(%d)",
|
||||||
nghttp2_strerror(rv), rv);
|
nghttp2_strerror(rv), rv);
|
||||||
return -1;
|
return CURLE_HTTP2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -845,12 +1025,12 @@ int Curl_http2_switched(struct connectdata *conn)
|
|||||||
httpc->stream_id = -1;
|
httpc->stream_id = -1;
|
||||||
rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0);
|
rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0);
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
failf(conn->data, "nghttp2_submit_settings() failed: %s(%d)",
|
failf(data, "nghttp2_submit_settings() failed: %s(%d)",
|
||||||
nghttp2_strerror(rv), rv);
|
nghttp2_strerror(rv), rv);
|
||||||
return -1;
|
return CURLE_HTTP2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -37,13 +37,13 @@ CURLcode Curl_http2_send_request(struct connectdata *conn);
|
|||||||
CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
|
CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
|
||||||
struct connectdata *conn);
|
struct connectdata *conn);
|
||||||
CURLcode Curl_http2_setup(struct connectdata *conn);
|
CURLcode Curl_http2_setup(struct connectdata *conn);
|
||||||
int Curl_http2_switched(struct connectdata *conn);
|
CURLcode Curl_http2_switched(struct connectdata *conn);
|
||||||
#else /* USE_NGHTTP2 */
|
#else /* USE_NGHTTP2 */
|
||||||
#define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL
|
#define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL
|
||||||
#define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
|
#define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
|
||||||
#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
|
#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
|
||||||
#define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL
|
#define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL
|
||||||
#define Curl_http2_switched(x) (-1)
|
#define Curl_http2_switched(x) CURLE_UNSUPPORTED_PROTOCOL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* HEADER_CURL_HTTP2_H */
|
#endif /* HEADER_CURL_HTTP2_H */
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -39,19 +39,6 @@
|
|||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
#include "url.h"
|
#include "url.h"
|
||||||
|
|
||||||
#ifdef HAVE_SPNEGO
|
|
||||||
# include <spnegohelp.h>
|
|
||||||
# ifdef USE_SSLEAY
|
|
||||||
# ifdef USE_OPENSSL
|
|
||||||
# include <openssl/objects.h>
|
|
||||||
# else
|
|
||||||
# include <objects.h>
|
|
||||||
# endif
|
|
||||||
# else
|
|
||||||
# error "Can't compile SPNEGO support without OpenSSL."
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
@@ -61,24 +48,10 @@
|
|||||||
static int
|
static int
|
||||||
get_gss_name(struct connectdata *conn, bool proxy, gss_name_t *server)
|
get_gss_name(struct connectdata *conn, bool proxy, gss_name_t *server)
|
||||||
{
|
{
|
||||||
struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
|
|
||||||
&conn->data->state.negotiate;
|
|
||||||
OM_uint32 major_status, minor_status;
|
OM_uint32 major_status, minor_status;
|
||||||
gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
|
gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
|
||||||
char name[2048];
|
char name[2048];
|
||||||
const char* service;
|
const char* service = "HTTP";
|
||||||
|
|
||||||
/* 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'.
|
|
||||||
Change following lines if you want to use GSI */
|
|
||||||
|
|
||||||
/* IIS uses the <service>@<fqdn> form but uses 'http' as the service name */
|
|
||||||
|
|
||||||
if(neg_ctx->gss)
|
|
||||||
service = "KHTTP";
|
|
||||||
else
|
|
||||||
service = "HTTP";
|
|
||||||
|
|
||||||
token.length = strlen(service) + 1 + strlen(proxy ? conn->proxy.name :
|
token.length = strlen(service) + 1 + strlen(proxy ? conn->proxy.name :
|
||||||
conn->host.name) + 1;
|
conn->host.name) + 1;
|
||||||
@@ -141,31 +114,8 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
|||||||
int ret;
|
int ret;
|
||||||
size_t len;
|
size_t len;
|
||||||
size_t rawlen = 0;
|
size_t rawlen = 0;
|
||||||
bool gss;
|
|
||||||
const char* protocol;
|
|
||||||
CURLcode error;
|
CURLcode error;
|
||||||
|
|
||||||
if(checkprefix("GSS-Negotiate", header)) {
|
|
||||||
protocol = "GSS-Negotiate";
|
|
||||||
gss = TRUE;
|
|
||||||
}
|
|
||||||
else if(checkprefix("Negotiate", header)) {
|
|
||||||
protocol = "Negotiate";
|
|
||||||
gss = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if(neg_ctx->context) {
|
|
||||||
if(neg_ctx->gss != gss) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
neg_ctx->protocol = protocol;
|
|
||||||
neg_ctx->gss = gss;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) {
|
if(neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) {
|
||||||
/* We finished successfully our part of authentication, but server
|
/* We finished successfully our part of authentication, but server
|
||||||
* rejected it (since we're again here). Exit with an error since we
|
* rejected it (since we're again here). Exit with an error since we
|
||||||
@@ -178,7 +128,7 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
|||||||
(ret = get_gss_name(conn, proxy, &neg_ctx->server_name)))
|
(ret = get_gss_name(conn, proxy, &neg_ctx->server_name)))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
header += strlen(neg_ctx->protocol);
|
header += strlen("Negotiate");
|
||||||
while(*header && ISSPACE(*header))
|
while(*header && ISSPACE(*header))
|
||||||
header++;
|
header++;
|
||||||
|
|
||||||
@@ -191,59 +141,13 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
|||||||
input_token.length = rawlen;
|
input_token.length = rawlen;
|
||||||
|
|
||||||
DEBUGASSERT(input_token.value != NULL);
|
DEBUGASSERT(input_token.value != NULL);
|
||||||
|
|
||||||
#ifdef HAVE_SPNEGO /* Handle SPNEGO */
|
|
||||||
if(checkprefix("Negotiate", header)) {
|
|
||||||
unsigned char *spnegoToken = NULL;
|
|
||||||
size_t spnegoTokenLength = 0;
|
|
||||||
gss_buffer_desc mechToken = GSS_C_EMPTY_BUFFER;
|
|
||||||
|
|
||||||
spnegoToken = malloc(input_token.length);
|
|
||||||
if(spnegoToken == NULL) {
|
|
||||||
Curl_safefree(input_token.value);
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
memcpy(spnegoToken, input_token.value, input_token.length);
|
|
||||||
spnegoTokenLength = input_token.length;
|
|
||||||
|
|
||||||
if(!parseSpnegoTargetToken(spnegoToken,
|
|
||||||
spnegoTokenLength,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
(unsigned char**)&mechToken.value,
|
|
||||||
&mechToken.length,
|
|
||||||
NULL,
|
|
||||||
NULL)) {
|
|
||||||
Curl_safefree(spnegoToken);
|
|
||||||
infof(data, "Parse SPNEGO Target Token failed\n");
|
|
||||||
}
|
|
||||||
else if(!mechToken.value || !mechToken.length) {
|
|
||||||
Curl_safefree(spnegoToken);
|
|
||||||
if(mechToken.value)
|
|
||||||
gss_release_buffer(&discard_st, &mechToken);
|
|
||||||
infof(data, "Parse SPNEGO Target Token succeeded (NULL token)\n");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Curl_safefree(spnegoToken);
|
|
||||||
Curl_safefree(input_token.value);
|
|
||||||
input_token.value = malloc(mechToken.length);
|
|
||||||
if(input_token.value == NULL) {
|
|
||||||
gss_release_buffer(&discard_st, &mechToken);
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
memcpy(input_token.value, mechToken.value, mechToken.length);
|
|
||||||
input_token.length = mechToken.length;
|
|
||||||
gss_release_buffer(&discard_st, &mechToken);
|
|
||||||
infof(data, "Parse SPNEGO Target Token succeeded\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
major_status = Curl_gss_init_sec_context(data,
|
major_status = Curl_gss_init_sec_context(data,
|
||||||
&minor_status,
|
&minor_status,
|
||||||
&neg_ctx->context,
|
&neg_ctx->context,
|
||||||
neg_ctx->server_name,
|
neg_ctx->server_name,
|
||||||
|
&Curl_spnego_mech_oid,
|
||||||
GSS_C_NO_CHANNEL_BINDINGS,
|
GSS_C_NO_CHANNEL_BINDINGS,
|
||||||
&input_token,
|
&input_token,
|
||||||
&output_token,
|
&output_token,
|
||||||
@@ -279,52 +183,6 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
|
|||||||
CURLcode error;
|
CURLcode error;
|
||||||
OM_uint32 discard_st;
|
OM_uint32 discard_st;
|
||||||
|
|
||||||
#ifdef HAVE_SPNEGO /* Handle SPNEGO */
|
|
||||||
if(checkprefix("Negotiate", neg_ctx->protocol)) {
|
|
||||||
ASN1_OBJECT *object = NULL;
|
|
||||||
unsigned char *responseToken = NULL;
|
|
||||||
size_t responseTokenLength = 0;
|
|
||||||
gss_buffer_desc spnegoToken = GSS_C_EMPTY_BUFFER;
|
|
||||||
|
|
||||||
responseToken = malloc(neg_ctx->output_token.length);
|
|
||||||
if(responseToken == NULL)
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
memcpy(responseToken, neg_ctx->output_token.value,
|
|
||||||
neg_ctx->output_token.length);
|
|
||||||
responseTokenLength = neg_ctx->output_token.length;
|
|
||||||
|
|
||||||
object = OBJ_txt2obj("1.2.840.113554.1.2.2", 1);
|
|
||||||
if(!object) {
|
|
||||||
Curl_safefree(responseToken);
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!makeSpnegoInitialToken(object,
|
|
||||||
responseToken,
|
|
||||||
responseTokenLength,
|
|
||||||
(unsigned char**)&spnegoToken.value,
|
|
||||||
&spnegoToken.length)) {
|
|
||||||
Curl_safefree(responseToken);
|
|
||||||
ASN1_OBJECT_free(object);
|
|
||||||
infof(conn->data, "Make SPNEGO Initial Token failed\n");
|
|
||||||
}
|
|
||||||
else if(!spnegoToken.value || !spnegoToken.length) {
|
|
||||||
Curl_safefree(responseToken);
|
|
||||||
ASN1_OBJECT_free(object);
|
|
||||||
if(spnegoToken.value)
|
|
||||||
gss_release_buffer(&discard_st, &spnegoToken);
|
|
||||||
infof(conn->data, "Make SPNEGO Initial Token succeeded (NULL token)\n");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Curl_safefree(responseToken);
|
|
||||||
ASN1_OBJECT_free(object);
|
|
||||||
gss_release_buffer(&discard_st, &neg_ctx->output_token);
|
|
||||||
neg_ctx->output_token.value = spnegoToken.value;
|
|
||||||
neg_ctx->output_token.length = spnegoToken.length;
|
|
||||||
infof(conn->data, "Make SPNEGO Initial Token succeeded\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
error = Curl_base64_encode(conn->data,
|
error = Curl_base64_encode(conn->data,
|
||||||
neg_ctx->output_token.value,
|
neg_ctx->output_token.value,
|
||||||
neg_ctx->output_token.length,
|
neg_ctx->output_token.length,
|
||||||
@@ -343,8 +201,8 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
|
|||||||
return CURLE_REMOTE_ACCESS_DENIED;
|
return CURLE_REMOTE_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
userp = aprintf("%sAuthorization: %s %s\r\n", proxy ? "Proxy-" : "",
|
userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
|
||||||
neg_ctx->protocol, encoded);
|
encoded);
|
||||||
if(proxy) {
|
if(proxy) {
|
||||||
Curl_safefree(conn->allocptr.proxyuserpwd);
|
Curl_safefree(conn->allocptr.proxyuserpwd);
|
||||||
conn->allocptr.proxyuserpwd = userp;
|
conn->allocptr.proxyuserpwd = userp;
|
||||||
@@ -355,7 +213,6 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Curl_safefree(encoded);
|
Curl_safefree(encoded);
|
||||||
Curl_cleanup_negotiate(conn->data);
|
|
||||||
|
|
||||||
return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
|
return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef USE_HTTP_NEGOTIATE
|
#ifdef USE_SPNEGO
|
||||||
|
|
||||||
/* this is for Negotiate header input */
|
/* this is for Negotiate header input */
|
||||||
int Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
int Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
||||||
@@ -37,6 +37,6 @@ void Curl_cleanup_negotiate(struct SessionHandle *data);
|
|||||||
#define GSS_ERROR(status) (status & 0x80000000)
|
#define GSS_ERROR(status) (status & 0x80000000)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* USE_HTTP_NEGOTIATE */
|
#endif /* USE_SPNEGO */
|
||||||
|
|
||||||
#endif /* HEADER_CURL_HTTP_NEGOTIATE_H */
|
#endif /* HEADER_CURL_HTTP_NEGOTIATE_H */
|
||||||
|
@@ -24,13 +24,14 @@
|
|||||||
|
|
||||||
#ifdef USE_WINDOWS_SSPI
|
#ifdef USE_WINDOWS_SSPI
|
||||||
|
|
||||||
#if !defined(CURL_DISABLE_HTTP) && defined(USE_HTTP_NEGOTIATE)
|
#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
|
||||||
|
|
||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
#include "rawstr.h"
|
#include "rawstr.h"
|
||||||
#include "warnless.h"
|
#include "warnless.h"
|
||||||
#include "curl_base64.h"
|
#include "curl_base64.h"
|
||||||
|
#include "curl_sasl.h"
|
||||||
#include "http_negotiate.h"
|
#include "http_negotiate.h"
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
#include "curl_multibyte.h"
|
#include "curl_multibyte.h"
|
||||||
@@ -41,84 +42,47 @@
|
|||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
static int
|
|
||||||
get_gss_name(struct connectdata *conn, bool proxy,
|
|
||||||
struct negotiatedata *neg_ctx)
|
|
||||||
{
|
|
||||||
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'.
|
|
||||||
Change following lines if you want to use GSI */
|
|
||||||
|
|
||||||
/* IIS uses the <service>@<fqdn> form but uses 'http' as the service name,
|
|
||||||
and SSPI then generates an NTLM token. When using <service>/<fqdn> a
|
|
||||||
Kerberos token is generated. */
|
|
||||||
|
|
||||||
if(neg_ctx->gss)
|
|
||||||
service = "KHTTP";
|
|
||||||
else
|
|
||||||
service = "HTTP";
|
|
||||||
|
|
||||||
length = strlen(service) + 1 + strlen(proxy ? conn->proxy.name :
|
|
||||||
conn->host.name) + 1;
|
|
||||||
if(length + 1 > sizeof(neg_ctx->server_name))
|
|
||||||
return EMSGSIZE;
|
|
||||||
|
|
||||||
snprintf(neg_ctx->server_name, sizeof(neg_ctx->server_name), "%s/%s",
|
|
||||||
service, proxy ? conn->proxy.name : conn->host.name);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* returning zero (0) means success, everything else is treated as "failure"
|
/* returning zero (0) means success, everything else is treated as "failure"
|
||||||
with no care exactly what the failure was */
|
with no care exactly what the failure was */
|
||||||
int Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
int Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
||||||
const char *header)
|
const char *header)
|
||||||
{
|
{
|
||||||
struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
|
BYTE *input_token = NULL;
|
||||||
&conn->data->state.negotiate;
|
|
||||||
BYTE *input_token = 0;
|
|
||||||
SecBufferDesc out_buff_desc;
|
SecBufferDesc out_buff_desc;
|
||||||
SecBuffer out_sec_buff;
|
SecBuffer out_sec_buff;
|
||||||
SecBufferDesc in_buff_desc;
|
SecBufferDesc in_buff_desc;
|
||||||
SecBuffer in_sec_buff;
|
SecBuffer in_sec_buff;
|
||||||
unsigned long context_attributes;
|
unsigned long context_attributes;
|
||||||
TimeStamp lifetime;
|
TimeStamp lifetime;
|
||||||
TCHAR *sname;
|
|
||||||
int ret;
|
int ret;
|
||||||
size_t len = 0, input_token_len = 0;
|
size_t len = 0, input_token_len = 0;
|
||||||
bool gss = FALSE;
|
|
||||||
const char* protocol;
|
|
||||||
CURLcode error;
|
CURLcode error;
|
||||||
|
|
||||||
if(checkprefix("GSS-Negotiate", header)) {
|
/* Point to the username and password */
|
||||||
protocol = "GSS-Negotiate";
|
const char *userp;
|
||||||
gss = TRUE;
|
const char *passwdp;
|
||||||
}
|
|
||||||
else if(checkprefix("Negotiate", header)) {
|
|
||||||
protocol = "Negotiate";
|
|
||||||
gss = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if(neg_ctx->context) {
|
/* Point to the correct struct with this */
|
||||||
if(neg_ctx->gss != gss) {
|
struct negotiatedata *neg_ctx;
|
||||||
return -1;
|
|
||||||
}
|
if(proxy) {
|
||||||
|
userp = conn->proxyuser;
|
||||||
|
passwdp = conn->proxypasswd;
|
||||||
|
neg_ctx = &conn->data->state.proxyneg;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
neg_ctx->protocol = protocol;
|
userp = conn->user;
|
||||||
neg_ctx->gss = gss;
|
passwdp = conn->passwd;
|
||||||
|
neg_ctx = &conn->data->state.negotiate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Not set means empty */
|
||||||
|
if(!userp)
|
||||||
|
userp = "";
|
||||||
|
|
||||||
|
if(!passwdp)
|
||||||
|
passwdp = "";
|
||||||
|
|
||||||
if(neg_ctx->context && neg_ctx->status == SEC_E_OK) {
|
if(neg_ctx->context && neg_ctx->status == SEC_E_OK) {
|
||||||
/* We finished successfully our part of authentication, but server
|
/* We finished successfully our part of authentication, but server
|
||||||
* rejected it (since we're again here). Exit with an error since we
|
* rejected it (since we're again here). Exit with an error since we
|
||||||
@@ -127,10 +91,17 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(0 == strlen(neg_ctx->server_name)) {
|
if(!neg_ctx->server_name) {
|
||||||
ret = get_gss_name(conn, proxy, neg_ctx);
|
/* Check proxy auth requested but no given proxy name */
|
||||||
if(ret)
|
if(proxy && !conn->proxy.name)
|
||||||
return ret;
|
return -1;
|
||||||
|
|
||||||
|
/* Generate our SPN */
|
||||||
|
neg_ctx->server_name = Curl_sasl_build_spn("HTTP",
|
||||||
|
proxy ? conn->proxy.name :
|
||||||
|
conn->host.name);
|
||||||
|
if(!neg_ctx->server_name)
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!neg_ctx->output_token) {
|
if(!neg_ctx->output_token) {
|
||||||
@@ -148,81 +119,91 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Obtain the input token, if any */
|
/* Obtain the input token, if any */
|
||||||
header += strlen(neg_ctx->protocol);
|
header += strlen("Negotiate");
|
||||||
while(*header && ISSPACE(*header))
|
while(*header && ISSPACE(*header))
|
||||||
header++;
|
header++;
|
||||||
|
|
||||||
len = strlen(header);
|
len = strlen(header);
|
||||||
if(!len) {
|
if(!len) {
|
||||||
/* first call in a new negotation, we have to acquire credentials,
|
/* Is this the first call in a new negotiation? */
|
||||||
and allocate memory for the context */
|
if(neg_ctx->context) {
|
||||||
|
/* The server rejected our authentication and hasn't suppled any more
|
||||||
|
negotiation mechanisms */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We have to acquire credentials and allocate memory for the context */
|
||||||
neg_ctx->credentials = malloc(sizeof(CredHandle));
|
neg_ctx->credentials = malloc(sizeof(CredHandle));
|
||||||
neg_ctx->context = malloc(sizeof(CtxtHandle));
|
neg_ctx->context = malloc(sizeof(CtxtHandle));
|
||||||
|
|
||||||
if(!neg_ctx->credentials || !neg_ctx->context)
|
if(!neg_ctx->credentials || !neg_ctx->context)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if(userp && *userp) {
|
||||||
|
/* Populate our identity structure */
|
||||||
|
error = Curl_create_sspi_identity(userp, passwdp, &neg_ctx->identity);
|
||||||
|
if(error)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Allow proper cleanup of the identity structure */
|
||||||
|
neg_ctx->p_identity = &neg_ctx->identity;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* Use the current Windows user */
|
||||||
|
neg_ctx->p_identity = NULL;
|
||||||
|
|
||||||
|
/* Acquire our credientials handle */
|
||||||
neg_ctx->status =
|
neg_ctx->status =
|
||||||
s_pSecFn->AcquireCredentialsHandle(NULL,
|
s_pSecFn->AcquireCredentialsHandle(NULL,
|
||||||
(TCHAR *) TEXT("Negotiate"),
|
(TCHAR *) TEXT("Negotiate"),
|
||||||
SECPKG_CRED_OUTBOUND, NULL, NULL,
|
SECPKG_CRED_OUTBOUND, NULL,
|
||||||
NULL, NULL, neg_ctx->credentials,
|
neg_ctx->p_identity, NULL, NULL,
|
||||||
&lifetime);
|
neg_ctx->credentials, &lifetime);
|
||||||
if(neg_ctx->status != SEC_E_OK)
|
if(neg_ctx->status != SEC_E_OK)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
input_token = malloc(neg_ctx->max_token_length);
|
|
||||||
if(!input_token)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
error = Curl_base64_decode(header,
|
error = Curl_base64_decode(header,
|
||||||
(unsigned char **)&input_token,
|
(unsigned char **)&input_token,
|
||||||
&input_token_len);
|
&input_token_len);
|
||||||
if(error || input_token_len == 0)
|
if(error || !input_token_len)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* prepare the output buffers, and input buffers if present */
|
/* Setup the "output" security buffer */
|
||||||
out_buff_desc.ulVersion = 0;
|
out_buff_desc.ulVersion = SECBUFFER_VERSION;
|
||||||
out_buff_desc.cBuffers = 1;
|
out_buff_desc.cBuffers = 1;
|
||||||
out_buff_desc.pBuffers = &out_sec_buff;
|
out_buff_desc.pBuffers = &out_sec_buff;
|
||||||
|
|
||||||
out_sec_buff.cbBuffer = curlx_uztoul(neg_ctx->max_token_length);
|
|
||||||
out_sec_buff.BufferType = SECBUFFER_TOKEN;
|
out_sec_buff.BufferType = SECBUFFER_TOKEN;
|
||||||
out_sec_buff.pvBuffer = neg_ctx->output_token;
|
out_sec_buff.pvBuffer = neg_ctx->output_token;
|
||||||
|
out_sec_buff.cbBuffer = curlx_uztoul(neg_ctx->max_token_length);
|
||||||
|
|
||||||
|
/* Setup the "input" security buffer if present */
|
||||||
if(input_token) {
|
if(input_token) {
|
||||||
in_buff_desc.ulVersion = 0;
|
in_buff_desc.ulVersion = SECBUFFER_VERSION;
|
||||||
in_buff_desc.cBuffers = 1;
|
in_buff_desc.cBuffers = 1;
|
||||||
in_buff_desc.pBuffers = &in_sec_buff;
|
in_buff_desc.pBuffers = &in_sec_buff;
|
||||||
|
|
||||||
in_sec_buff.cbBuffer = curlx_uztoul(input_token_len);
|
|
||||||
in_sec_buff.BufferType = SECBUFFER_TOKEN;
|
in_sec_buff.BufferType = SECBUFFER_TOKEN;
|
||||||
in_sec_buff.pvBuffer = input_token;
|
in_sec_buff.pvBuffer = input_token;
|
||||||
|
in_sec_buff.cbBuffer = curlx_uztoul(input_token_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
sname = Curl_convert_UTF8_to_tchar(neg_ctx->server_name);
|
/* Generate our message */
|
||||||
if(!sname)
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
neg_ctx->status = s_pSecFn->InitializeSecurityContext(
|
neg_ctx->status = s_pSecFn->InitializeSecurityContext(
|
||||||
neg_ctx->credentials,
|
neg_ctx->credentials,
|
||||||
input_token ? neg_ctx->context : 0,
|
input_token ? neg_ctx->context : NULL,
|
||||||
sname,
|
neg_ctx->server_name,
|
||||||
ISC_REQ_CONFIDENTIALITY,
|
ISC_REQ_CONFIDENTIALITY,
|
||||||
0,
|
0,
|
||||||
SECURITY_NATIVE_DREP,
|
SECURITY_NATIVE_DREP,
|
||||||
input_token ? &in_buff_desc : 0,
|
input_token ? &in_buff_desc : NULL,
|
||||||
0,
|
0,
|
||||||
neg_ctx->context,
|
neg_ctx->context,
|
||||||
&out_buff_desc,
|
&out_buff_desc,
|
||||||
&context_attributes,
|
&context_attributes,
|
||||||
&lifetime);
|
&lifetime);
|
||||||
|
|
||||||
Curl_unicodefree(sname);
|
Curl_safefree(input_token);
|
||||||
|
|
||||||
if(GSS_ERROR(neg_ctx->status))
|
if(GSS_ERROR(neg_ctx->status))
|
||||||
return -1;
|
return -1;
|
||||||
@@ -257,18 +238,21 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
|
|||||||
if(error)
|
if(error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if(len == 0)
|
if(!len)
|
||||||
return CURLE_REMOTE_ACCESS_DENIED;
|
return CURLE_REMOTE_ACCESS_DENIED;
|
||||||
|
|
||||||
userp = aprintf("%sAuthorization: %s %s\r\n", proxy ? "Proxy-" : "",
|
userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
|
||||||
neg_ctx->protocol, encoded);
|
encoded);
|
||||||
|
|
||||||
if(proxy)
|
if(proxy) {
|
||||||
|
Curl_safefree(conn->allocptr.proxyuserpwd);
|
||||||
conn->allocptr.proxyuserpwd = userp;
|
conn->allocptr.proxyuserpwd = userp;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
|
Curl_safefree(conn->allocptr.userpwd);
|
||||||
conn->allocptr.userpwd = userp;
|
conn->allocptr.userpwd = userp;
|
||||||
|
}
|
||||||
free(encoded);
|
free(encoded);
|
||||||
Curl_cleanup_negotiate (conn->data);
|
|
||||||
return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
|
return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,21 +261,22 @@ static void cleanup(struct negotiatedata *neg_ctx)
|
|||||||
if(neg_ctx->context) {
|
if(neg_ctx->context) {
|
||||||
s_pSecFn->DeleteSecurityContext(neg_ctx->context);
|
s_pSecFn->DeleteSecurityContext(neg_ctx->context);
|
||||||
free(neg_ctx->context);
|
free(neg_ctx->context);
|
||||||
neg_ctx->context = 0;
|
neg_ctx->context = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(neg_ctx->credentials) {
|
if(neg_ctx->credentials) {
|
||||||
s_pSecFn->FreeCredentialsHandle(neg_ctx->credentials);
|
s_pSecFn->FreeCredentialsHandle(neg_ctx->credentials);
|
||||||
free(neg_ctx->credentials);
|
free(neg_ctx->credentials);
|
||||||
neg_ctx->credentials = 0;
|
neg_ctx->credentials = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if(neg_ctx->output_token) {
|
|
||||||
free(neg_ctx->output_token);
|
|
||||||
neg_ctx->output_token = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
neg_ctx->max_token_length = 0;
|
neg_ctx->max_token_length = 0;
|
||||||
|
Curl_safefree(neg_ctx->output_token);
|
||||||
|
|
||||||
|
Curl_safefree(neg_ctx->server_name);
|
||||||
|
|
||||||
|
Curl_sspi_free_identity(neg_ctx->p_identity);
|
||||||
|
neg_ctx->p_identity = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curl_cleanup_negotiate(struct SessionHandle *data)
|
void Curl_cleanup_negotiate(struct SessionHandle *data)
|
||||||
@@ -300,6 +285,6 @@ void Curl_cleanup_negotiate(struct SessionHandle *data)
|
|||||||
cleanup(&data->state.proxyneg);
|
cleanup(&data->state.proxyneg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !CURL_DISABLE_HTTP && USE_HTTP_NEGOTIATE */
|
#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
|
||||||
|
|
||||||
#endif /* USE_WINDOWS_SSPI */
|
#endif /* USE_WINDOWS_SSPI */
|
||||||
|
@@ -98,8 +98,6 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
struct SessionHandle *data=conn->data;
|
struct SessionHandle *data=conn->data;
|
||||||
struct SingleRequest *k = &data->req;
|
struct SingleRequest *k = &data->req;
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
long timeout =
|
|
||||||
data->set.timeout?data->set.timeout:PROXY_TIMEOUT; /* in milliseconds */
|
|
||||||
curl_socket_t tunnelsocket = conn->sock[sockindex];
|
curl_socket_t tunnelsocket = conn->sock[sockindex];
|
||||||
curl_off_t cl=0;
|
curl_off_t cl=0;
|
||||||
bool closeConnection = FALSE;
|
bool closeConnection = FALSE;
|
||||||
@@ -223,14 +221,25 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
conn->tunnel_state[sockindex] = TUNNEL_CONNECT;
|
conn->tunnel_state[sockindex] = TUNNEL_CONNECT;
|
||||||
|
|
||||||
/* now we've issued the CONNECT and we're waiting to hear back, return
|
|
||||||
and get called again polling-style */
|
|
||||||
return CURLE_OK;
|
|
||||||
|
|
||||||
} /* END CONNECT PHASE */
|
} /* END CONNECT PHASE */
|
||||||
|
|
||||||
{ /* BEGIN NEGOTIATION PHASE */
|
check = Curl_timeleft(data, NULL, TRUE);
|
||||||
|
if(check <= 0) {
|
||||||
|
failf(data, "Proxy CONNECT aborted due to timeout");
|
||||||
|
return CURLE_RECV_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
|
||||||
|
/* return so we'll be called again polling-style */
|
||||||
|
return CURLE_OK;
|
||||||
|
else {
|
||||||
|
DEBUGF(infof(data,
|
||||||
|
"Read response immediately from proxy CONNECT\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* at this point, the tunnel_connecting phase is over. */
|
||||||
|
|
||||||
|
{ /* READING RESPONSE PHASE */
|
||||||
size_t nread; /* total size read */
|
size_t nread; /* total size read */
|
||||||
int perline; /* count bytes per line */
|
int perline; /* count bytes per line */
|
||||||
int keepon=TRUE;
|
int keepon=TRUE;
|
||||||
@@ -247,9 +256,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
|
|
||||||
while((nread<BUFSIZE) && (keepon && !error)) {
|
while((nread<BUFSIZE) && (keepon && !error)) {
|
||||||
|
|
||||||
/* if timeout is requested, find out how much remaining time we have */
|
check = Curl_timeleft(data, NULL, TRUE);
|
||||||
check = timeout - /* timeout time */
|
|
||||||
Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
|
|
||||||
if(check <= 0) {
|
if(check <= 0) {
|
||||||
failf(data, "Proxy CONNECT aborted due to timeout");
|
failf(data, "Proxy CONNECT aborted due to timeout");
|
||||||
error = SELECT_TIMEOUT; /* already too little time */
|
error = SELECT_TIMEOUT; /* already too little time */
|
||||||
@@ -279,6 +286,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
/* proxy auth was requested and there was proxy auth available,
|
/* proxy auth was requested and there was proxy auth available,
|
||||||
then deem this as "mere" proxy disconnect */
|
then deem this as "mere" proxy disconnect */
|
||||||
conn->bits.proxy_connect_closed = TRUE;
|
conn->bits.proxy_connect_closed = TRUE;
|
||||||
|
infof(data, "Proxy CONNECT connection closed");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
error = SELECT_ERROR;
|
error = SELECT_ERROR;
|
||||||
@@ -527,7 +535,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
conn->sock[sockindex] = CURL_SOCKET_BAD;
|
conn->sock[sockindex] = CURL_SOCKET_BAD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} /* END NEGOTIATION PHASE */
|
} /* END READING RESPONSE PHASE */
|
||||||
|
|
||||||
/* If we are supposed to continue and request a new URL, which basically
|
/* If we are supposed to continue and request a new URL, which basically
|
||||||
* means the HTTP authentication is still going on so if the tunnel
|
* means the HTTP authentication is still going on so if the tunnel
|
||||||
@@ -542,22 +550,33 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
} while(data->req.newurl);
|
} while(data->req.newurl);
|
||||||
|
|
||||||
if(200 != data->req.httpcode) {
|
if(200 != data->req.httpcode) {
|
||||||
failf(data, "Received HTTP code %d from proxy after CONNECT",
|
if(closeConnection && data->req.newurl) {
|
||||||
data->req.httpcode);
|
|
||||||
|
|
||||||
if(closeConnection && data->req.newurl)
|
|
||||||
conn->bits.proxy_connect_closed = TRUE;
|
conn->bits.proxy_connect_closed = TRUE;
|
||||||
|
infof(data, "Connect me again please\n");
|
||||||
if(data->req.newurl) {
|
}
|
||||||
/* this won't be used anymore for the CONNECT so free it now */
|
else {
|
||||||
free(data->req.newurl);
|
if(data->req.newurl) {
|
||||||
data->req.newurl = NULL;
|
/* this won't be used anymore for the CONNECT so free it now */
|
||||||
|
free(data->req.newurl);
|
||||||
|
data->req.newurl = NULL;
|
||||||
|
}
|
||||||
|
/* failure, close this connection to avoid re-use */
|
||||||
|
connclose(conn, "proxy CONNECT failure");
|
||||||
|
Curl_closesocket(conn, conn->sock[sockindex]);
|
||||||
|
conn->sock[sockindex] = CURL_SOCKET_BAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* to back to init state */
|
/* to back to init state */
|
||||||
conn->tunnel_state[sockindex] = TUNNEL_INIT;
|
conn->tunnel_state[sockindex] = TUNNEL_INIT;
|
||||||
|
|
||||||
return CURLE_RECV_ERROR;
|
if(conn->bits.proxy_connect_closed)
|
||||||
|
/* this is not an error, just part of the connection negotiation */
|
||||||
|
return CURLE_OK;
|
||||||
|
else {
|
||||||
|
failf(data, "Received HTTP code %d from proxy after CONNECT",
|
||||||
|
data->req.httpcode);
|
||||||
|
return CURLE_RECV_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
|
conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
|
||||||
|
196
lib/imap.c
196
lib/imap.c
@@ -24,6 +24,7 @@
|
|||||||
* RFC3501 IMAPv4 protocol
|
* RFC3501 IMAPv4 protocol
|
||||||
* RFC4422 Simple Authentication and Security Layer (SASL)
|
* RFC4422 Simple Authentication and Security Layer (SASL)
|
||||||
* RFC4616 PLAIN authentication
|
* RFC4616 PLAIN authentication
|
||||||
|
* RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
|
||||||
* RFC4959 IMAP Extension for SASL Initial Client Response
|
* RFC4959 IMAP Extension for SASL Initial Client Response
|
||||||
* RFC5092 IMAP URL Scheme
|
* RFC5092 IMAP URL Scheme
|
||||||
* RFC6749 OAuth 2.0 Authorization Framework
|
* RFC6749 OAuth 2.0 Authorization Framework
|
||||||
@@ -433,6 +434,9 @@ static void state(struct connectdata *conn, imapstate newstate)
|
|||||||
"AUTHENTICATE_DIGESTMD5_RESP",
|
"AUTHENTICATE_DIGESTMD5_RESP",
|
||||||
"AUTHENTICATE_NTLM",
|
"AUTHENTICATE_NTLM",
|
||||||
"AUTHENTICATE_NTLM_TYPE2MSG",
|
"AUTHENTICATE_NTLM_TYPE2MSG",
|
||||||
|
"AUTHENTICATE_GSSAPI",
|
||||||
|
"AUTHENTICATE_GSSAPI_TOKEN",
|
||||||
|
"AUTHENTICATE_GSSAPI_NO_DATA",
|
||||||
"AUTHENTICATE_XOAUTH2",
|
"AUTHENTICATE_XOAUTH2",
|
||||||
"AUTHENTICATE_CANCEL",
|
"AUTHENTICATE_CANCEL",
|
||||||
"AUTHENTICATE_FINAL",
|
"AUTHENTICATE_FINAL",
|
||||||
@@ -1296,6 +1300,158 @@ static CURLcode imap_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_WINDOWS_SSPI)
|
||||||
|
/* For AUTHENTICATE GSSAPI (without initial response) responses */
|
||||||
|
static CURLcode imap_state_auth_gssapi_resp(struct connectdata *conn,
|
||||||
|
int imapcode,
|
||||||
|
imapstate instate)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
struct imap_conn *imapc = &conn->proto.imapc;
|
||||||
|
size_t len = 0;
|
||||||
|
char *respmsg = NULL;
|
||||||
|
|
||||||
|
(void)instate; /* no use for this yet */
|
||||||
|
|
||||||
|
if(imapcode != '+') {
|
||||||
|
failf(data, "Access denied: %d", imapcode);
|
||||||
|
result = CURLE_LOGIN_DENIED;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Create the initial response message */
|
||||||
|
result = Curl_sasl_create_gssapi_user_message(data, conn->user,
|
||||||
|
conn->passwd, "imap",
|
||||||
|
imapc->mutual_auth,
|
||||||
|
NULL, &conn->krb5,
|
||||||
|
&respmsg, &len);
|
||||||
|
if(!result && respmsg) {
|
||||||
|
/* Send the message */
|
||||||
|
result = Curl_pp_sendf(&imapc->pp, "%s", respmsg);
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, IMAP_AUTHENTICATE_GSSAPI_TOKEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Curl_safefree(respmsg);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For AUTHENTICATE GSSAPI user token responses */
|
||||||
|
static CURLcode imap_state_auth_gssapi_token_resp(struct connectdata *conn,
|
||||||
|
int imapcode,
|
||||||
|
imapstate instate)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
struct imap_conn *imapc = &conn->proto.imapc;
|
||||||
|
char *chlgmsg = NULL;
|
||||||
|
char *respmsg = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
(void)instate; /* no use for this yet */
|
||||||
|
|
||||||
|
if(imapcode != '+') {
|
||||||
|
failf(data, "Access denied: %d", imapcode);
|
||||||
|
result = CURLE_LOGIN_DENIED;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Get the challenge message */
|
||||||
|
imap_get_message(data->state.buffer, &chlgmsg);
|
||||||
|
|
||||||
|
if(imapc->mutual_auth)
|
||||||
|
/* Decode the user token challenge and create the optional response
|
||||||
|
message */
|
||||||
|
result = Curl_sasl_create_gssapi_user_message(data, NULL, NULL, NULL,
|
||||||
|
imapc->mutual_auth,
|
||||||
|
chlgmsg, &conn->krb5,
|
||||||
|
&respmsg, &len);
|
||||||
|
else
|
||||||
|
/* Decode the security challenge and create the response message */
|
||||||
|
result = Curl_sasl_create_gssapi_security_message(data, chlgmsg,
|
||||||
|
&conn->krb5,
|
||||||
|
&respmsg, &len);
|
||||||
|
|
||||||
|
if(result) {
|
||||||
|
if(result == CURLE_BAD_CONTENT_ENCODING) {
|
||||||
|
/* Send the cancellation */
|
||||||
|
result = Curl_pp_sendf(&imapc->pp, "%s", "*");
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, IMAP_AUTHENTICATE_CANCEL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Send the response */
|
||||||
|
if(respmsg)
|
||||||
|
result = Curl_pp_sendf(&imapc->pp, "%s", respmsg);
|
||||||
|
else
|
||||||
|
result = Curl_pp_sendf(&imapc->pp, "%s", "");
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, (imapc->mutual_auth ? IMAP_AUTHENTICATE_GSSAPI_NO_DATA :
|
||||||
|
IMAP_AUTHENTICATE_FINAL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Curl_safefree(respmsg);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For AUTHENTICATE GSSAPI no data responses */
|
||||||
|
static CURLcode imap_state_auth_gssapi_no_data_resp(struct connectdata *conn,
|
||||||
|
int imapcode,
|
||||||
|
imapstate instate)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
char *chlgmsg = NULL;
|
||||||
|
char *respmsg = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
(void)instate; /* no use for this yet */
|
||||||
|
|
||||||
|
if(imapcode != '+') {
|
||||||
|
failf(data, "Access denied: %d", imapcode);
|
||||||
|
result = CURLE_LOGIN_DENIED;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Get the challenge message */
|
||||||
|
imap_get_message(data->state.buffer, &chlgmsg);
|
||||||
|
|
||||||
|
/* Decode the security challenge and create the response message */
|
||||||
|
result = Curl_sasl_create_gssapi_security_message(data, chlgmsg,
|
||||||
|
&conn->krb5,
|
||||||
|
&respmsg, &len);
|
||||||
|
if(result) {
|
||||||
|
if(result == CURLE_BAD_CONTENT_ENCODING) {
|
||||||
|
/* Send the cancellation */
|
||||||
|
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*");
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, IMAP_AUTHENTICATE_CANCEL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Send the response */
|
||||||
|
if(respmsg) {
|
||||||
|
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", respmsg);
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, IMAP_AUTHENTICATE_FINAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Curl_safefree(respmsg);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* For AUTHENTICATE XOAUTH2 (without initial response) responses */
|
/* For AUTHENTICATE XOAUTH2 (without initial response) responses */
|
||||||
static CURLcode imap_state_auth_xoauth2_resp(struct connectdata *conn,
|
static CURLcode imap_state_auth_xoauth2_resp(struct connectdata *conn,
|
||||||
int imapcode,
|
int imapcode,
|
||||||
@@ -1506,7 +1662,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
|
|||||||
(void)instate; /* no use for this yet */
|
(void)instate; /* no use for this yet */
|
||||||
|
|
||||||
if(imapcode != '*') {
|
if(imapcode != '*') {
|
||||||
Curl_pgrsSetDownloadSize(data, 0);
|
Curl_pgrsSetDownloadSize(data, -1);
|
||||||
state(conn, IMAP_STOP);
|
state(conn, IMAP_STOP);
|
||||||
return CURLE_REMOTE_FILE_NOT_FOUND; /* TODO: Fix error code */
|
return CURLE_REMOTE_FILE_NOT_FOUND; /* TODO: Fix error code */
|
||||||
}
|
}
|
||||||
@@ -1755,6 +1911,21 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_WINDOWS_SSPI)
|
||||||
|
case IMAP_AUTHENTICATE_GSSAPI:
|
||||||
|
result = imap_state_auth_gssapi_resp(conn, imapcode, imapc->state);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IMAP_AUTHENTICATE_GSSAPI_TOKEN:
|
||||||
|
result = imap_state_auth_gssapi_token_resp(conn, imapcode, imapc->state);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IMAP_AUTHENTICATE_GSSAPI_NO_DATA:
|
||||||
|
result = imap_state_auth_gssapi_no_data_resp(conn, imapcode,
|
||||||
|
imapc->state);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case IMAP_AUTHENTICATE_XOAUTH2:
|
case IMAP_AUTHENTICATE_XOAUTH2:
|
||||||
result = imap_state_auth_xoauth2_resp(conn, imapcode, imapc->state);
|
result = imap_state_auth_xoauth2_resp(conn, imapcode, imapc->state);
|
||||||
break;
|
break;
|
||||||
@@ -2165,8 +2336,8 @@ static CURLcode imap_regular_transfer(struct connectdata *conn,
|
|||||||
/* Set the progress data */
|
/* Set the progress data */
|
||||||
Curl_pgrsSetUploadCounter(data, 0);
|
Curl_pgrsSetUploadCounter(data, 0);
|
||||||
Curl_pgrsSetDownloadCounter(data, 0);
|
Curl_pgrsSetDownloadCounter(data, 0);
|
||||||
Curl_pgrsSetUploadSize(data, 0);
|
Curl_pgrsSetUploadSize(data, -1);
|
||||||
Curl_pgrsSetDownloadSize(data, 0);
|
Curl_pgrsSetDownloadSize(data, -1);
|
||||||
|
|
||||||
/* Carry out the perform */
|
/* Carry out the perform */
|
||||||
result = imap_perform(conn, &connected, dophase_done);
|
result = imap_perform(conn, &connected, dophase_done);
|
||||||
@@ -2632,6 +2803,25 @@ static CURLcode imap_calc_sasl_details(struct connectdata *conn,
|
|||||||
|
|
||||||
/* Calculate the supported authentication mechanism, by decreasing order of
|
/* Calculate the supported authentication mechanism, by decreasing order of
|
||||||
security, as well as the initial response where appropriate */
|
security, as well as the initial response where appropriate */
|
||||||
|
#if defined(USE_WINDOWS_SSPI)
|
||||||
|
if((imapc->authmechs & SASL_MECH_GSSAPI) &&
|
||||||
|
(imapc->prefmech & SASL_MECH_GSSAPI)) {
|
||||||
|
imapc->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */
|
||||||
|
|
||||||
|
*mech = SASL_MECH_STRING_GSSAPI;
|
||||||
|
*state1 = IMAP_AUTHENTICATE_GSSAPI;
|
||||||
|
*state2 = IMAP_AUTHENTICATE_GSSAPI_TOKEN;
|
||||||
|
imapc->authused = SASL_MECH_GSSAPI;
|
||||||
|
|
||||||
|
if(imapc->ir_supported || data->set.sasl_ir)
|
||||||
|
result = Curl_sasl_create_gssapi_user_message(data, conn->user,
|
||||||
|
conn->passwd, "imap",
|
||||||
|
imapc->mutual_auth,
|
||||||
|
NULL, &conn->krb5,
|
||||||
|
initresp, len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||||
if((imapc->authmechs & SASL_MECH_DIGEST_MD5) &&
|
if((imapc->authmechs & SASL_MECH_DIGEST_MD5) &&
|
||||||
(imapc->prefmech & SASL_MECH_DIGEST_MD5)) {
|
(imapc->prefmech & SASL_MECH_DIGEST_MD5)) {
|
||||||
|
@@ -43,6 +43,9 @@ typedef enum {
|
|||||||
IMAP_AUTHENTICATE_DIGESTMD5_RESP,
|
IMAP_AUTHENTICATE_DIGESTMD5_RESP,
|
||||||
IMAP_AUTHENTICATE_NTLM,
|
IMAP_AUTHENTICATE_NTLM,
|
||||||
IMAP_AUTHENTICATE_NTLM_TYPE2MSG,
|
IMAP_AUTHENTICATE_NTLM_TYPE2MSG,
|
||||||
|
IMAP_AUTHENTICATE_GSSAPI,
|
||||||
|
IMAP_AUTHENTICATE_GSSAPI_TOKEN,
|
||||||
|
IMAP_AUTHENTICATE_GSSAPI_NO_DATA,
|
||||||
IMAP_AUTHENTICATE_XOAUTH2,
|
IMAP_AUTHENTICATE_XOAUTH2,
|
||||||
IMAP_AUTHENTICATE_CANCEL,
|
IMAP_AUTHENTICATE_CANCEL,
|
||||||
IMAP_AUTHENTICATE_FINAL,
|
IMAP_AUTHENTICATE_FINAL,
|
||||||
@@ -89,6 +92,7 @@ struct imap_conn {
|
|||||||
bool tls_supported; /* StartTLS capability supported by server */
|
bool tls_supported; /* StartTLS capability supported by server */
|
||||||
bool login_disabled; /* LOGIN command disabled by server */
|
bool login_disabled; /* LOGIN command disabled by server */
|
||||||
bool ir_supported; /* Initial response supported by server */
|
bool ir_supported; /* Initial response supported by server */
|
||||||
|
bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */
|
||||||
char *mailbox; /* The last selected mailbox */
|
char *mailbox; /* The last selected mailbox */
|
||||||
char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */
|
char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */
|
||||||
};
|
};
|
||||||
|
@@ -236,6 +236,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
|
|||||||
&min,
|
&min,
|
||||||
context,
|
context,
|
||||||
gssname,
|
gssname,
|
||||||
|
&Curl_krb5_mech_oid,
|
||||||
&chan,
|
&chan,
|
||||||
gssresp,
|
gssresp,
|
||||||
&output_buffer,
|
&output_buffer,
|
||||||
|
@@ -40,17 +40,15 @@ use Text::Wrap;
|
|||||||
|
|
||||||
my %urls = (
|
my %urls = (
|
||||||
'nss' =>
|
'nss' =>
|
||||||
'http://mxr.mozilla.org/nss/source/lib/ckfw/builtins/certdata.txt?raw=1',
|
'http://hg.mozilla.org/projects/nss/raw-file/tip/lib/ckfw/builtins/certdata.txt',
|
||||||
'central' =>
|
'central' =>
|
||||||
'http://mxr.mozilla.org/mozilla-central/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1',
|
'http://hg.mozilla.org/mozilla-central/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
|
||||||
'aurora' =>
|
'aurora' =>
|
||||||
'http://mxr.mozilla.org/mozilla-aurora/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1',
|
'http://hg.mozilla.org/releases/mozilla-aurora/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
|
||||||
'beta' =>
|
'beta' =>
|
||||||
'http://mxr.mozilla.org/mozilla-beta/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1',
|
'http://hg.mozilla.org/releases/mozilla-beta/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
|
||||||
'release' =>
|
'release' =>
|
||||||
'http://mxr.mozilla.org/mozilla-release/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1',
|
'http://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
|
||||||
'mozilla' =>
|
|
||||||
'http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1'
|
|
||||||
);
|
);
|
||||||
|
|
||||||
$opt_d = 'release';
|
$opt_d = 'release';
|
||||||
@@ -58,7 +56,7 @@ $opt_d = 'release';
|
|||||||
# If the OpenSSL commandline is not in search path you can configure it here!
|
# If the OpenSSL commandline is not in search path you can configure it here!
|
||||||
my $openssl = 'openssl';
|
my $openssl = 'openssl';
|
||||||
|
|
||||||
my $version = '1.21';
|
my $version = '1.22';
|
||||||
|
|
||||||
$opt_w = 76; # default base64 encoded lines length
|
$opt_w = 76; # default base64 encoded lines length
|
||||||
|
|
||||||
@@ -209,6 +207,28 @@ sub PARSE_CSV_PARAM($$@) {
|
|||||||
return @values;
|
return @values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub sha1 {
|
||||||
|
my ($txt)=@_;
|
||||||
|
my $sha1 = `$openssl dgst -sha1 $txt | cut '-d ' -f2`;
|
||||||
|
chomp $sha1;
|
||||||
|
return $sha1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub oldsha1 {
|
||||||
|
my ($crt)=@_;
|
||||||
|
my $sha1="";
|
||||||
|
open(C, "<$crt");
|
||||||
|
while(<C>) {
|
||||||
|
chomp;
|
||||||
|
if($_ =~ /^\#\# SHA1: (.*)/) {
|
||||||
|
$sha1 = $1;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(C);
|
||||||
|
return $sha1;
|
||||||
|
}
|
||||||
|
|
||||||
if ( $opt_p !~ m/:/ ) {
|
if ( $opt_p !~ m/:/ ) {
|
||||||
print "Error: Mozilla trust identifier list must include both purposes and levels\n";
|
print "Error: Mozilla trust identifier list must include both purposes and levels\n";
|
||||||
HELP_MESSAGE();
|
HELP_MESSAGE();
|
||||||
@@ -238,6 +258,10 @@ my $stdout = $crt eq '-';
|
|||||||
my $resp;
|
my $resp;
|
||||||
my $fetched;
|
my $fetched;
|
||||||
|
|
||||||
|
my $oldsha1= oldsha1($crt);
|
||||||
|
|
||||||
|
print STDERR "SHA1 of old file: $oldsha1\n";
|
||||||
|
|
||||||
unless ($opt_n and -e $txt) {
|
unless ($opt_n and -e $txt) {
|
||||||
print STDERR "Downloading '$txt' ...\n" if (!$opt_q);
|
print STDERR "Downloading '$txt' ...\n" if (!$opt_q);
|
||||||
my $ua = new LWP::UserAgent(agent => "$0/$version");
|
my $ua = new LWP::UserAgent(agent => "$0/$version");
|
||||||
@@ -257,7 +281,25 @@ unless ($opt_n and -e $txt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
my $currentdate = scalar gmtime($fetched ? $resp->last_modified : (stat($txt))[9]);
|
my $filedate = $fetched ? $resp->last_modified : (stat($txt))[9];
|
||||||
|
my $datesrc = "as of";
|
||||||
|
if(!$filedate) {
|
||||||
|
# mxr.mozilla.org gave us a time, hg.mozilla.org does not!
|
||||||
|
$filedate = time();
|
||||||
|
$datesrc="downloaded on";
|
||||||
|
}
|
||||||
|
|
||||||
|
# get the hash from the download file
|
||||||
|
my $newsha1= sha1($txt);
|
||||||
|
|
||||||
|
if($oldsha1 eq $newsha1) {
|
||||||
|
print STDERR "Downloaded file identical to previous run\'s source file. Exiting\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
print STDERR "SHA1 of new file: $newsha1\n";
|
||||||
|
|
||||||
|
my $currentdate = scalar gmtime($filedate);
|
||||||
|
|
||||||
my $format = $opt_t ? "plain text and " : "";
|
my $format = $opt_t ? "plain text and " : "";
|
||||||
if( $stdout ) {
|
if( $stdout ) {
|
||||||
@@ -267,9 +309,9 @@ if( $stdout ) {
|
|||||||
}
|
}
|
||||||
print CRT <<EOT;
|
print CRT <<EOT;
|
||||||
##
|
##
|
||||||
## $crt -- Bundle of CA Root Certificates
|
## Bundle of CA Root Certificates
|
||||||
##
|
##
|
||||||
## Certificate data from Mozilla as of: ${currentdate}
|
## Certificate data from Mozilla ${datesrc}: ${currentdate}
|
||||||
##
|
##
|
||||||
## This is a bundle of X.509 certificates of public Certificate Authorities
|
## This is a bundle of X.509 certificates of public Certificate Authorities
|
||||||
## (CA). These were automatically extracted from Mozilla's root certificates
|
## (CA). These were automatically extracted from Mozilla's root certificates
|
||||||
@@ -281,6 +323,9 @@ print CRT <<EOT;
|
|||||||
## an Apache+mod_ssl webserver for SSL client authentication.
|
## an Apache+mod_ssl webserver for SSL client authentication.
|
||||||
## Just configure this file as the SSLCACertificateFile.
|
## Just configure this file as the SSLCACertificateFile.
|
||||||
##
|
##
|
||||||
|
## Conversion done with mk-ca-bundle.pl verison $version.
|
||||||
|
## SHA1: $newsha1
|
||||||
|
##
|
||||||
|
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
@@ -415,7 +460,3 @@ unless( $stdout ) {
|
|||||||
}
|
}
|
||||||
unlink $txt if ($opt_u);
|
unlink $txt if ($opt_u);
|
||||||
print STDERR "Done ($certnum CA certs processed, $skipnum skipped).\n" if (!$opt_q);
|
print STDERR "Done ($certnum CA certs processed, $skipnum skipped).\n" if (!$opt_q);
|
||||||
|
|
||||||
exit;
|
|
||||||
|
|
||||||
|
|
||||||
|
126
lib/multi.c
126
lib/multi.c
@@ -30,6 +30,7 @@
|
|||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include "easyif.h"
|
#include "easyif.h"
|
||||||
|
#include "share.h"
|
||||||
#include "multiif.h"
|
#include "multiif.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
#include "timeval.h"
|
#include "timeval.h"
|
||||||
@@ -308,6 +309,10 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
|
|||||||
if(!multi->msglist)
|
if(!multi->msglist)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
multi->pending = Curl_llist_alloc(multi_freeamsg);
|
||||||
|
if(!multi->pending)
|
||||||
|
goto error;
|
||||||
|
|
||||||
/* allocate a new easy handle to use when closing cached connections */
|
/* allocate a new easy handle to use when closing cached connections */
|
||||||
multi->closure_handle = curl_easy_init();
|
multi->closure_handle = curl_easy_init();
|
||||||
if(!multi->closure_handle)
|
if(!multi->closure_handle)
|
||||||
@@ -333,6 +338,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
|
|||||||
Curl_close(multi->closure_handle);
|
Curl_close(multi->closure_handle);
|
||||||
multi->closure_handle = NULL;
|
multi->closure_handle = NULL;
|
||||||
Curl_llist_destroy(multi->msglist, NULL);
|
Curl_llist_destroy(multi->msglist, NULL);
|
||||||
|
Curl_llist_destroy(multi->pending, NULL);
|
||||||
|
|
||||||
free(multi);
|
free(multi);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1045,7 +1051,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
/* There was no connection available. We will go to the pending
|
/* There was no connection available. We will go to the pending
|
||||||
state and wait for an available connection. */
|
state and wait for an available connection. */
|
||||||
multistate(data, CURLM_STATE_CONNECT_PEND);
|
multistate(data, CURLM_STATE_CONNECT_PEND);
|
||||||
data->result = CURLE_OK;
|
|
||||||
|
/* add this handle to the list of connect-pending handles */
|
||||||
|
if(!Curl_llist_insert_next(multi->pending, multi->pending->tail, data))
|
||||||
|
data->result = CURLE_OUT_OF_MEMORY;
|
||||||
|
else
|
||||||
|
data->result = CURLE_OK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1084,9 +1095,32 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
/* awaiting an asynch name resolve to complete */
|
/* awaiting an asynch name resolve to complete */
|
||||||
{
|
{
|
||||||
struct Curl_dns_entry *dns = NULL;
|
struct Curl_dns_entry *dns = NULL;
|
||||||
|
struct connectdata *conn = data->easy_conn;
|
||||||
|
int stale;
|
||||||
|
|
||||||
/* check if we have the name resolved by now */
|
/* check if we have the name resolved by now */
|
||||||
data->result = Curl_resolver_is_resolved(data->easy_conn, &dns);
|
if(data->share)
|
||||||
|
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
|
||||||
|
|
||||||
|
dns = Curl_fetch_addr(conn, conn->host.name, (int)conn->port, &stale);
|
||||||
|
|
||||||
|
if(dns) {
|
||||||
|
dns->inuse++; /* we use it! */
|
||||||
|
#ifdef CURLRES_ASYNCH
|
||||||
|
conn->async.dns = dns;
|
||||||
|
conn->async.done = TRUE;
|
||||||
|
#endif
|
||||||
|
data->result = CURLRESOLV_RESOLVED;
|
||||||
|
infof(data, "Hostname was found in DNS cache\n");
|
||||||
|
}
|
||||||
|
if(stale)
|
||||||
|
infof(data, "Hostname in DNS cache was stale, zapped\n");
|
||||||
|
|
||||||
|
if(data->share)
|
||||||
|
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
||||||
|
|
||||||
|
if(!dns)
|
||||||
|
data->result = Curl_resolver_is_resolved(data->easy_conn, &dns);
|
||||||
|
|
||||||
/* Update sockets here, because the socket(s) may have been
|
/* Update sockets here, because the socket(s) may have been
|
||||||
closed and the application thus needs to be told, even if it
|
closed and the application thus needs to be told, even if it
|
||||||
@@ -1137,11 +1171,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
data->result = Curl_http_connect(data->easy_conn, &protocol_connect);
|
data->result = Curl_http_connect(data->easy_conn, &protocol_connect);
|
||||||
|
|
||||||
if(data->easy_conn->bits.proxy_connect_closed) {
|
if(data->easy_conn->bits.proxy_connect_closed) {
|
||||||
/* reset the error buffer */
|
/* connect back to proxy again */
|
||||||
if(data->set.errorbuffer)
|
|
||||||
data->set.errorbuffer[0] = '\0';
|
|
||||||
data->state.errorbuf = FALSE;
|
|
||||||
|
|
||||||
data->result = CURLE_OK;
|
data->result = CURLE_OK;
|
||||||
result = CURLM_CALL_MULTI_PERFORM;
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
multistate(data, CURLM_STATE_CONNECT);
|
multistate(data, CURLM_STATE_CONNECT);
|
||||||
@@ -1167,7 +1197,15 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
&protocol_connect);
|
&protocol_connect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(CURLE_OK != data->result) {
|
if(data->easy_conn->bits.proxy_connect_closed) {
|
||||||
|
/* connect back to proxy again since it was closed in a proxy CONNECT
|
||||||
|
setup */
|
||||||
|
data->result = CURLE_OK;
|
||||||
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
|
multistate(data, CURLM_STATE_CONNECT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(CURLE_OK != data->result) {
|
||||||
/* failure detected */
|
/* failure detected */
|
||||||
/* Just break, the cleaning up is handled all in one place */
|
/* Just break, the cleaning up is handled all in one place */
|
||||||
disconnect_conn = TRUE;
|
disconnect_conn = TRUE;
|
||||||
@@ -1463,7 +1501,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
data->set.buffer_size : BUFSIZE);
|
data->set.buffer_size : BUFSIZE);
|
||||||
timeout_ms = Curl_sleep_time(data->set.max_send_speed,
|
timeout_ms = Curl_sleep_time(data->set.max_send_speed,
|
||||||
data->progress.ulspeed, buffersize);
|
data->progress.ulspeed, buffersize);
|
||||||
Curl_expire(data, timeout_ms);
|
Curl_expire_latest(data, timeout_ms);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1479,7 +1517,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
data->set.buffer_size : BUFSIZE);
|
data->set.buffer_size : BUFSIZE);
|
||||||
timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
|
timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
|
||||||
data->progress.dlspeed, buffersize);
|
data->progress.dlspeed, buffersize);
|
||||||
Curl_expire(data, timeout_ms);
|
Curl_expire_latest(data, timeout_ms);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1541,7 +1579,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
|
|
||||||
/* expire the new receiving pipeline head */
|
/* expire the new receiving pipeline head */
|
||||||
if(data->easy_conn->recv_pipe->head)
|
if(data->easy_conn->recv_pipe->head)
|
||||||
Curl_expire(data->easy_conn->recv_pipe->head->ptr, 1);
|
Curl_expire_latest(data->easy_conn->recv_pipe->head->ptr, 1);
|
||||||
|
|
||||||
/* Check if we can move pending requests to send pipe */
|
/* Check if we can move pending requests to send pipe */
|
||||||
Curl_multi_process_pending_handles(multi);
|
Curl_multi_process_pending_handles(multi);
|
||||||
@@ -1843,18 +1881,12 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
|||||||
multi->closure_handle->dns.hostcache);
|
multi->closure_handle->dns.hostcache);
|
||||||
|
|
||||||
Curl_close(multi->closure_handle);
|
Curl_close(multi->closure_handle);
|
||||||
multi->closure_handle = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Curl_hash_destroy(multi->sockhash);
|
Curl_hash_destroy(multi->sockhash);
|
||||||
multi->sockhash = NULL;
|
|
||||||
|
|
||||||
Curl_conncache_destroy(multi->conn_cache);
|
Curl_conncache_destroy(multi->conn_cache);
|
||||||
multi->conn_cache = NULL;
|
|
||||||
|
|
||||||
/* remove the pending list of messages */
|
|
||||||
Curl_llist_destroy(multi->msglist, NULL);
|
Curl_llist_destroy(multi->msglist, NULL);
|
||||||
multi->msglist = NULL;
|
Curl_llist_destroy(multi->pending, NULL);
|
||||||
|
|
||||||
/* remove all easy handles */
|
/* remove all easy handles */
|
||||||
data = multi->easyp;
|
data = multi->easyp;
|
||||||
@@ -1875,7 +1907,6 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Curl_hash_destroy(multi->hostcache);
|
Curl_hash_destroy(multi->hostcache);
|
||||||
multi->hostcache = NULL;
|
|
||||||
|
|
||||||
/* Free the blacklists by setting them to NULL */
|
/* Free the blacklists by setting them to NULL */
|
||||||
Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
|
Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
|
||||||
@@ -2654,6 +2685,46 @@ void Curl_expire(struct SessionHandle *data, long milli)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_expire_latest()
|
||||||
|
*
|
||||||
|
* This is like Curl_expire() but will only add a timeout node to the list of
|
||||||
|
* timers if there is no timeout that will expire before the given time.
|
||||||
|
*
|
||||||
|
* Use this function if the code logic risks calling this function many times
|
||||||
|
* or if there's no particular conditional wait in the code for this specific
|
||||||
|
* time-out period to expire.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void Curl_expire_latest(struct SessionHandle *data, long milli)
|
||||||
|
{
|
||||||
|
struct timeval *exp = &data->state.expiretime;
|
||||||
|
|
||||||
|
struct timeval set;
|
||||||
|
|
||||||
|
set = Curl_tvnow();
|
||||||
|
set.tv_sec += milli/1000;
|
||||||
|
set.tv_usec += (milli%1000)*1000;
|
||||||
|
|
||||||
|
if(set.tv_usec >= 1000000) {
|
||||||
|
set.tv_sec++;
|
||||||
|
set.tv_usec -= 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(exp->tv_sec || exp->tv_usec) {
|
||||||
|
/* This means that the struct is added as a node in the splay tree.
|
||||||
|
Compare if the new time is earlier, and only remove-old/add-new if it
|
||||||
|
is. */
|
||||||
|
long diff = curlx_tvdiff(set, *exp);
|
||||||
|
if(diff > 0)
|
||||||
|
/* the new expire time was later than the top time, so just skip this */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Just add the timeout like normal */
|
||||||
|
Curl_expire(data, milli);
|
||||||
|
}
|
||||||
|
|
||||||
CURLMcode curl_multi_assign(CURLM *multi_handle,
|
CURLMcode curl_multi_assign(CURLM *multi_handle,
|
||||||
curl_socket_t s, void *hashp)
|
curl_socket_t s, void *hashp)
|
||||||
{
|
{
|
||||||
@@ -2708,16 +2779,23 @@ struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
|
|||||||
|
|
||||||
void Curl_multi_process_pending_handles(struct Curl_multi *multi)
|
void Curl_multi_process_pending_handles(struct Curl_multi *multi)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data;
|
struct curl_llist_element *e = multi->pending->head;
|
||||||
|
|
||||||
|
while(e) {
|
||||||
|
struct SessionHandle *data = e->ptr;
|
||||||
|
struct curl_llist_element *next = e->next;
|
||||||
|
|
||||||
data=multi->easyp;
|
|
||||||
while(data) {
|
|
||||||
if(data->mstate == CURLM_STATE_CONNECT_PEND) {
|
if(data->mstate == CURLM_STATE_CONNECT_PEND) {
|
||||||
multistate(data, CURLM_STATE_CONNECT);
|
multistate(data, CURLM_STATE_CONNECT);
|
||||||
|
|
||||||
|
/* Remove this node from the list */
|
||||||
|
Curl_llist_remove(multi->pending, e, NULL);
|
||||||
|
|
||||||
/* Make sure that the handle will be processed soonish. */
|
/* Make sure that the handle will be processed soonish. */
|
||||||
Curl_expire(data, 1);
|
Curl_expire_latest(data, 1);
|
||||||
}
|
}
|
||||||
data = data->next; /* operate on next handle */
|
|
||||||
|
e = next; /* operate on next handle */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -75,6 +75,9 @@ struct Curl_multi {
|
|||||||
|
|
||||||
struct curl_llist *msglist; /* a list of messages from completed transfers */
|
struct curl_llist *msglist; /* a list of messages from completed transfers */
|
||||||
|
|
||||||
|
struct curl_llist *pending; /* SessionHandles that are in the
|
||||||
|
CURLM_STATE_CONNECT_PEND state */
|
||||||
|
|
||||||
/* callback function and user data pointer for the *socket() API */
|
/* callback function and user data pointer for the *socket() API */
|
||||||
curl_socket_callback socket_cb;
|
curl_socket_callback socket_cb;
|
||||||
void *socket_userp;
|
void *socket_userp;
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
* Prototypes for library-wide functions provided by multi.c
|
* Prototypes for library-wide functions provided by multi.c
|
||||||
*/
|
*/
|
||||||
void Curl_expire(struct SessionHandle *data, long milli);
|
void Curl_expire(struct SessionHandle *data, long milli);
|
||||||
|
void Curl_expire_latest(struct SessionHandle *data, long milli);
|
||||||
|
|
||||||
bool Curl_multi_pipeline_enabled(const struct Curl_multi* multi);
|
bool Curl_multi_pipeline_enabled(const struct Curl_multi* multi);
|
||||||
void Curl_multi_handlePipeBreak(struct SessionHandle *data);
|
void Curl_multi_handlePipeBreak(struct SessionHandle *data);
|
||||||
|
@@ -530,8 +530,10 @@ static int parsedate(const char *date, time_t *output)
|
|||||||
/* Add the time zone diff between local time zone and GMT. */
|
/* Add the time zone diff between local time zone and GMT. */
|
||||||
long delta = (long)(tzoff!=-1?tzoff:0);
|
long delta = (long)(tzoff!=-1?tzoff:0);
|
||||||
|
|
||||||
if((delta>0) && (t > LONG_MAX - delta))
|
if((delta>0) && (t > LONG_MAX - delta)) {
|
||||||
return -1; /* time_t overflow */
|
*output = 0x7fffffff;
|
||||||
|
return PARSEDATE_LATER; /* time_t overflow */
|
||||||
|
}
|
||||||
|
|
||||||
t += delta;
|
t += delta;
|
||||||
}
|
}
|
||||||
@@ -561,9 +563,6 @@ time_t curl_getdate(const char *p, const time_t *now)
|
|||||||
* Curl_gmtime() is a gmtime() replacement for portability. Do not use the
|
* Curl_gmtime() is a gmtime() replacement for portability. Do not use the
|
||||||
* gmtime_r() or gmtime() functions anywhere else but here.
|
* gmtime_r() or gmtime() functions anywhere else but here.
|
||||||
*
|
*
|
||||||
* To make sure no such function calls slip in, we define them to cause build
|
|
||||||
* errors, which is why we use the name within parentheses in this function.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CURLcode Curl_gmtime(time_t intime, struct tm *store)
|
CURLcode Curl_gmtime(time_t intime, struct tm *store)
|
||||||
|
194
lib/pop3.c
194
lib/pop3.c
@@ -27,6 +27,7 @@
|
|||||||
* RFC2831 DIGEST-MD5 authentication
|
* RFC2831 DIGEST-MD5 authentication
|
||||||
* RFC4422 Simple Authentication and Security Layer (SASL)
|
* RFC4422 Simple Authentication and Security Layer (SASL)
|
||||||
* RFC4616 PLAIN authentication
|
* RFC4616 PLAIN authentication
|
||||||
|
* RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
|
||||||
* RFC5034 POP3 SASL Authentication Mechanism
|
* RFC5034 POP3 SASL Authentication Mechanism
|
||||||
* RFC6749 OAuth 2.0 Authorization Framework
|
* RFC6749 OAuth 2.0 Authorization Framework
|
||||||
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
|
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
|
||||||
@@ -320,6 +321,9 @@ static void state(struct connectdata *conn, pop3state newstate)
|
|||||||
"AUTH_DIGESTMD5_RESP",
|
"AUTH_DIGESTMD5_RESP",
|
||||||
"AUTH_NTLM",
|
"AUTH_NTLM",
|
||||||
"AUTH_NTLM_TYPE2MSG",
|
"AUTH_NTLM_TYPE2MSG",
|
||||||
|
"AUTH_GSSAPI",
|
||||||
|
"AUTH_GSSAPI_TOKEN",
|
||||||
|
"AUTH_GSSAPI_NO_DATA",
|
||||||
"AUTH_XOAUTH2",
|
"AUTH_XOAUTH2",
|
||||||
"AUTH_CANCEL",
|
"AUTH_CANCEL",
|
||||||
"AUTH_FINAL",
|
"AUTH_FINAL",
|
||||||
@@ -1127,6 +1131,158 @@ static CURLcode pop3_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_WINDOWS_SSPI)
|
||||||
|
/* For AUTH GSSAPI (without initial response) responses */
|
||||||
|
static CURLcode pop3_state_auth_gssapi_resp(struct connectdata *conn,
|
||||||
|
int pop3code,
|
||||||
|
pop3state instate)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||||
|
size_t len = 0;
|
||||||
|
char *respmsg = NULL;
|
||||||
|
|
||||||
|
(void)instate; /* no use for this yet */
|
||||||
|
|
||||||
|
if(pop3code != '+') {
|
||||||
|
failf(data, "Access denied: %d", pop3code);
|
||||||
|
result = CURLE_LOGIN_DENIED;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Create the initial response message */
|
||||||
|
result = Curl_sasl_create_gssapi_user_message(data, conn->user,
|
||||||
|
conn->passwd, "pop",
|
||||||
|
pop3c->mutual_auth,
|
||||||
|
NULL, &conn->krb5,
|
||||||
|
&respmsg, &len);
|
||||||
|
if(!result && respmsg) {
|
||||||
|
/* Send the message */
|
||||||
|
result = Curl_pp_sendf(&pop3c->pp, "%s", respmsg);
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, POP3_AUTH_GSSAPI_TOKEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Curl_safefree(respmsg);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For AUTH GSSAPI user token responses */
|
||||||
|
static CURLcode pop3_state_auth_gssapi_token_resp(struct connectdata *conn,
|
||||||
|
int pop3code,
|
||||||
|
pop3state instate)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||||
|
char *chlgmsg = NULL;
|
||||||
|
char *respmsg = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
(void)instate; /* no use for this yet */
|
||||||
|
|
||||||
|
if(pop3code != '+') {
|
||||||
|
failf(data, "Access denied: %d", pop3code);
|
||||||
|
result = CURLE_LOGIN_DENIED;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Get the challenge message */
|
||||||
|
pop3_get_message(data->state.buffer, &chlgmsg);
|
||||||
|
|
||||||
|
if(pop3c->mutual_auth)
|
||||||
|
/* Decode the user token challenge and create the optional response
|
||||||
|
message */
|
||||||
|
result = Curl_sasl_create_gssapi_user_message(data, NULL, NULL, NULL,
|
||||||
|
pop3c->mutual_auth,
|
||||||
|
chlgmsg, &conn->krb5,
|
||||||
|
&respmsg, &len);
|
||||||
|
else
|
||||||
|
/* Decode the security challenge and create the response message */
|
||||||
|
result = Curl_sasl_create_gssapi_security_message(data, chlgmsg,
|
||||||
|
&conn->krb5,
|
||||||
|
&respmsg, &len);
|
||||||
|
|
||||||
|
if(result) {
|
||||||
|
if(result == CURLE_BAD_CONTENT_ENCODING) {
|
||||||
|
/* Send the cancellation */
|
||||||
|
result = Curl_pp_sendf(&pop3c->pp, "%s", "*");
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, POP3_AUTH_CANCEL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Send the response */
|
||||||
|
if(respmsg)
|
||||||
|
result = Curl_pp_sendf(&pop3c->pp, "%s", respmsg);
|
||||||
|
else
|
||||||
|
result = Curl_pp_sendf(&pop3c->pp, "%s", "");
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, (pop3c->mutual_auth ? POP3_AUTH_GSSAPI_NO_DATA :
|
||||||
|
POP3_AUTH_FINAL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Curl_safefree(respmsg);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For AUTH GSSAPI no data responses */
|
||||||
|
static CURLcode pop3_state_auth_gssapi_no_data_resp(struct connectdata *conn,
|
||||||
|
int pop3code,
|
||||||
|
pop3state instate)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
char *chlgmsg = NULL;
|
||||||
|
char *respmsg = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
(void)instate; /* no use for this yet */
|
||||||
|
|
||||||
|
if(pop3code != '+') {
|
||||||
|
failf(data, "Access denied: %d", pop3code);
|
||||||
|
result = CURLE_LOGIN_DENIED;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Get the challenge message */
|
||||||
|
pop3_get_message(data->state.buffer, &chlgmsg);
|
||||||
|
|
||||||
|
/* Decode the security challenge and create the security message */
|
||||||
|
result = Curl_sasl_create_gssapi_security_message(data, chlgmsg,
|
||||||
|
&conn->krb5,
|
||||||
|
&respmsg, &len);
|
||||||
|
if(result) {
|
||||||
|
if(result == CURLE_BAD_CONTENT_ENCODING) {
|
||||||
|
/* Send the cancellation */
|
||||||
|
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*");
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, POP3_AUTH_CANCEL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Send the response */
|
||||||
|
if(respmsg) {
|
||||||
|
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", respmsg);
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, POP3_AUTH_FINAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Curl_safefree(respmsg);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* For AUTH XOAUTH2 (without initial response) responses */
|
/* For AUTH XOAUTH2 (without initial response) responses */
|
||||||
static CURLcode pop3_state_auth_xoauth2_resp(struct connectdata *conn,
|
static CURLcode pop3_state_auth_xoauth2_resp(struct connectdata *conn,
|
||||||
int pop3code, pop3state instate)
|
int pop3code, pop3state instate)
|
||||||
@@ -1435,6 +1591,21 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_WINDOWS_SSPI)
|
||||||
|
case POP3_AUTH_GSSAPI:
|
||||||
|
result = pop3_state_auth_gssapi_resp(conn, pop3code, pop3c->state);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case POP3_AUTH_GSSAPI_TOKEN:
|
||||||
|
result = pop3_state_auth_gssapi_token_resp(conn, pop3code, pop3c->state);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case POP3_AUTH_GSSAPI_NO_DATA:
|
||||||
|
result = pop3_state_auth_gssapi_no_data_resp(conn, pop3code,
|
||||||
|
pop3c->state);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case POP3_AUTH_XOAUTH2:
|
case POP3_AUTH_XOAUTH2:
|
||||||
result = pop3_state_auth_xoauth2_resp(conn, pop3code, pop3c->state);
|
result = pop3_state_auth_xoauth2_resp(conn, pop3code, pop3c->state);
|
||||||
break;
|
break;
|
||||||
@@ -1764,8 +1935,8 @@ static CURLcode pop3_regular_transfer(struct connectdata *conn,
|
|||||||
/* Set the progress data */
|
/* Set the progress data */
|
||||||
Curl_pgrsSetUploadCounter(data, 0);
|
Curl_pgrsSetUploadCounter(data, 0);
|
||||||
Curl_pgrsSetDownloadCounter(data, 0);
|
Curl_pgrsSetDownloadCounter(data, 0);
|
||||||
Curl_pgrsSetUploadSize(data, 0);
|
Curl_pgrsSetUploadSize(data, -1);
|
||||||
Curl_pgrsSetDownloadSize(data, 0);
|
Curl_pgrsSetDownloadSize(data, -1);
|
||||||
|
|
||||||
/* Carry out the perform */
|
/* Carry out the perform */
|
||||||
result = pop3_perform(conn, &connected, dophase_done);
|
result = pop3_perform(conn, &connected, dophase_done);
|
||||||
@@ -1950,6 +2121,25 @@ static CURLcode pop3_calc_sasl_details(struct connectdata *conn,
|
|||||||
|
|
||||||
/* Calculate the supported authentication mechanism, by decreasing order of
|
/* Calculate the supported authentication mechanism, by decreasing order of
|
||||||
security, as well as the initial response where appropriate */
|
security, as well as the initial response where appropriate */
|
||||||
|
#if defined(USE_WINDOWS_SSPI)
|
||||||
|
if((pop3c->authmechs & SASL_MECH_GSSAPI) &&
|
||||||
|
(pop3c->prefmech & SASL_MECH_GSSAPI)) {
|
||||||
|
pop3c->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */
|
||||||
|
|
||||||
|
*mech = SASL_MECH_STRING_GSSAPI;
|
||||||
|
*state1 = POP3_AUTH_GSSAPI;
|
||||||
|
*state2 = POP3_AUTH_GSSAPI_TOKEN;
|
||||||
|
pop3c->authused = SASL_MECH_GSSAPI;
|
||||||
|
|
||||||
|
if(data->set.sasl_ir)
|
||||||
|
result = Curl_sasl_create_gssapi_user_message(data, conn->user,
|
||||||
|
conn->passwd, "pop",
|
||||||
|
pop3c->mutual_auth,
|
||||||
|
NULL, &conn->krb5,
|
||||||
|
initresp, len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||||
if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) &&
|
if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) &&
|
||||||
(pop3c->prefmech & SASL_MECH_DIGEST_MD5)) {
|
(pop3c->prefmech & SASL_MECH_DIGEST_MD5)) {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user